summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortschoening <tschoening@13f79535-47bb-0310-9956-ffa450edef68>2014-01-12 11:23:01 +0000
committertschoening <tschoening@13f79535-47bb-0310-9956-ffa450edef68>2014-01-12 11:23:01 +0000
commitd646e4c074ef37132797c22bd5fc13b63e446872 (patch)
tree0018b593ccbb74b255c3f756a60d270c818887f3
downloadlog4cxx-d646e4c074ef37132797c22bd5fc13b63e446872.tar.gz
The last officially published version has been 0.10.0 and should be the source for a latest_stable tag which gets the most current contents of the project site with the latest stable sources.
git-svn-id: http://svn.apache.org/repos/asf/incubator/log4cxx/branches/latest_stable@1557515 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--INSTALL157
-rw-r--r--KEYS52
-rw-r--r--LICENSE202
-rw-r--r--Makefile.am23
-rw-r--r--NOTICE5
-rwxr-xr-xautogen.sh29
-rw-r--r--build.xml1251
-rwxr-xr-xconfigure-aprutil.bat20
-rw-r--r--configure.bat19
-rw-r--r--configure.in489
-rw-r--r--doap_log4cxx.rdf44
-rw-r--r--find_apr.m4202
-rw-r--r--find_apu.m4211
-rw-r--r--liblog4cxx.pc.in25
-rw-r--r--pom.xml247
-rw-r--r--src/Makefile.am16
-rwxr-xr-xsrc/ant/apr-build.xml498
-rwxr-xr-xsrc/ant/apr-util-build.xml428
-rw-r--r--src/ant/common.xml184
-rwxr-xr-xsrc/ant/esmtp-build.xml146
-rw-r--r--src/ant/find-apr-util.xml313
-rw-r--r--src/ant/find-apr.xml313
-rw-r--r--src/ant/find-libesmtp.xml313
-rw-r--r--src/assembly/source.xml99
-rw-r--r--src/changes/Makefile.am15
-rw-r--r--src/changes/changes.xml394
-rw-r--r--src/changes/changes.xslt225
-rw-r--r--src/examples/Makefile.am16
-rw-r--r--src/examples/cpp/Makefile.am31
-rwxr-xr-xsrc/examples/cpp/console.cpp114
-rw-r--r--src/examples/cpp/delayedloop.cpp120
-rw-r--r--src/examples/cpp/stream.cpp57
-rw-r--r--src/examples/cpp/trivial.cpp53
-rw-r--r--src/main/Makefile.am16
-rw-r--r--src/main/cpp/Makefile.am173
-rw-r--r--src/main/cpp/action.cpp75
-rw-r--r--src/main/cpp/appenderattachableimpl.cpp160
-rw-r--r--src/main/cpp/appenderskeleton.cpp177
-rw-r--r--src/main/cpp/aprinitializer.cpp69
-rw-r--r--src/main/cpp/asyncappender.cpp364
-rw-r--r--src/main/cpp/basicconfigurator.cpp45
-rw-r--r--src/main/cpp/bufferedwriter.cpp60
-rwxr-xr-xsrc/main/cpp/bytearrayinputstream.cpp55
-rw-r--r--src/main/cpp/bytearrayoutputstream.cpp53
-rw-r--r--src/main/cpp/bytebuffer.cpp65
-rw-r--r--src/main/cpp/cacheddateformat.cpp309
-rw-r--r--src/main/cpp/charsetdecoder.cpp490
-rw-r--r--src/main/cpp/charsetencoder.cpp518
-rw-r--r--src/main/cpp/class.cpp192
-rw-r--r--src/main/cpp/classnamepatternconverter.cpp56
-rw-r--r--src/main/cpp/classregistration.cpp28
-rwxr-xr-xsrc/main/cpp/condition.cpp70
-rw-r--r--src/main/cpp/configurator.cpp32
-rw-r--r--src/main/cpp/consoleappender.cpp146
-rw-r--r--src/main/cpp/cyclicbuffer.cpp148
-rw-r--r--src/main/cpp/dailyrollingfileappender.cpp108
-rw-r--r--src/main/cpp/datagrampacket.cpp58
-rw-r--r--src/main/cpp/datagramsocket.cpp186
-rw-r--r--src/main/cpp/date.cpp53
-rw-r--r--src/main/cpp/dateformat.cpp37
-rw-r--r--src/main/cpp/datelayout.cpp121
-rw-r--r--src/main/cpp/datepatternconverter.cpp135
-rwxr-xr-xsrc/main/cpp/defaultconfigurator.cpp105
-rw-r--r--src/main/cpp/defaultloggerfactory.cpp30
-rw-r--r--src/main/cpp/defaultrepositoryselector.cpp40
-rw-r--r--src/main/cpp/domconfigurator.cpp969
-rw-r--r--src/main/cpp/exception.cpp427
-rw-r--r--src/main/cpp/fallbackerrorhandler.cpp106
-rw-r--r--src/main/cpp/file.cpp240
-rw-r--r--src/main/cpp/fileappender.cpp309
-rw-r--r--src/main/cpp/filedatepatternconverter.cpp39
-rw-r--r--src/main/cpp/fileinputstream.cpp94
-rw-r--r--src/main/cpp/filelocationpatternconverter.cpp50
-rw-r--r--src/main/cpp/fileoutputstream.cpp98
-rw-r--r--src/main/cpp/filerenameaction.cpp35
-rw-r--r--src/main/cpp/filewatchdog.cpp93
-rw-r--r--src/main/cpp/filter.cpp49
-rw-r--r--src/main/cpp/filterbasedtriggeringpolicy.cpp95
-rw-r--r--src/main/cpp/fixedwindowrollingpolicy.cpp295
-rw-r--r--src/main/cpp/formattinginfo.cpp68
-rw-r--r--src/main/cpp/fulllocationpatternconverter.cpp56
-rw-r--r--src/main/cpp/gzcompressaction.cpp95
-rw-r--r--src/main/cpp/hierarchy.cpp399
-rw-r--r--src/main/cpp/htmllayout.cpp220
-rw-r--r--src/main/cpp/inetaddress.cpp144
-rw-r--r--src/main/cpp/inputstream.cpp30
-rw-r--r--src/main/cpp/inputstreamreader.cpp74
-rw-r--r--src/main/cpp/integer.cpp34
-rw-r--r--src/main/cpp/integerpatternconverter.cpp52
-rw-r--r--src/main/cpp/layout.cpp40
-rw-r--r--src/main/cpp/level.cpp234
-rw-r--r--src/main/cpp/levelmatchfilter.cpp84
-rw-r--r--src/main/cpp/levelpatternconverter.cpp87
-rw-r--r--src/main/cpp/levelrangefilter.cpp89
-rw-r--r--src/main/cpp/linelocationpatternconverter.cpp52
-rw-r--r--src/main/cpp/lineseparatorpatternconverter.cpp57
-rw-r--r--src/main/cpp/literalpatternconverter.cpp62
-rw-r--r--src/main/cpp/loader.cpp71
-rw-r--r--src/main/cpp/locale.cpp55
-rw-r--r--src/main/cpp/locationinfo.cpp195
-rw-r--r--src/main/cpp/logger.cpp975
-rw-r--r--src/main/cpp/loggerpatternconverter.cpp55
-rw-r--r--src/main/cpp/loggingevent.cpp326
-rw-r--r--src/main/cpp/loggingeventpatternconverter.cpp49
-rw-r--r--src/main/cpp/loglog.cpp121
-rw-r--r--src/main/cpp/logmanager.cpp211
-rw-r--r--src/main/cpp/logstream.cpp504
-rw-r--r--src/main/cpp/manualtriggeringpolicy.cpp42
-rw-r--r--src/main/cpp/mdc.cpp236
-rw-r--r--src/main/cpp/messagebuffer.cpp430
-rw-r--r--src/main/cpp/messagepatternconverter.cpp52
-rw-r--r--src/main/cpp/methodlocationpatternconverter.cpp51
-rwxr-xr-xsrc/main/cpp/mutex.cpp61
-rw-r--r--src/main/cpp/nameabbreviator.cpp325
-rw-r--r--src/main/cpp/namepatternconverter.cpp56
-rw-r--r--src/main/cpp/ndc.cpp338
-rw-r--r--src/main/cpp/ndcpatternconverter.cpp54
-rw-r--r--src/main/cpp/nteventlogappender.cpp316
-rw-r--r--src/main/cpp/objectimpl.cpp48
-rw-r--r--src/main/cpp/objectoutputstream.cpp194
-rwxr-xr-xsrc/main/cpp/objectptr.cpp47
-rw-r--r--src/main/cpp/obsoleterollingfileappender.cpp155
-rw-r--r--src/main/cpp/odbcappender.cpp333
-rw-r--r--src/main/cpp/onlyonceerrorhandler.cpp89
-rw-r--r--src/main/cpp/optionconverter.cpp381
-rw-r--r--src/main/cpp/outputdebugstringappender.cpp47
-rw-r--r--src/main/cpp/outputstream.cpp30
-rw-r--r--src/main/cpp/outputstreamwriter.cpp78
-rw-r--r--src/main/cpp/patternconverter.cpp50
-rw-r--r--src/main/cpp/patternlayout.cpp187
-rw-r--r--src/main/cpp/patternparser.cpp341
-rwxr-xr-xsrc/main/cpp/pool.cpp86
-rw-r--r--src/main/cpp/properties.cpp370
-rw-r--r--src/main/cpp/propertiespatternconverter.cpp80
-rw-r--r--src/main/cpp/propertyconfigurator.cpp451
-rw-r--r--src/main/cpp/propertyresourcebundle.cpp57
-rw-r--r--src/main/cpp/propertysetter.cpp104
-rw-r--r--src/main/cpp/reader.cpp29
-rw-r--r--src/main/cpp/relativetimedateformat.cpp38
-rw-r--r--src/main/cpp/relativetimepatternconverter.cpp53
-rw-r--r--src/main/cpp/resourcebundle.cpp122
-rw-r--r--src/main/cpp/rollingfileappender.cpp384
-rw-r--r--src/main/cpp/rollingpolicy.cpp24
-rw-r--r--src/main/cpp/rollingpolicybase.cpp146
-rw-r--r--src/main/cpp/rolloverdescription.cpp62
-rw-r--r--src/main/cpp/rootlogger.cpp52
-rw-r--r--src/main/cpp/serversocket.cpp140
-rw-r--r--src/main/cpp/simpledateformat.cpp781
-rw-r--r--src/main/cpp/simplelayout.cpp37
-rw-r--r--src/main/cpp/sizebasedtriggeringpolicy.cpp56
-rw-r--r--src/main/cpp/smtpappender.cpp674
-rw-r--r--src/main/cpp/socket.cpp130
-rw-r--r--src/main/cpp/socketappender.cpp111
-rwxr-xr-xsrc/main/cpp/socketappenderskeleton.cpp176
-rw-r--r--src/main/cpp/sockethubappender.cpp238
-rw-r--r--src/main/cpp/socketoutputstream.cpp57
-rw-r--r--src/main/cpp/strftimedateformat.cpp55
-rw-r--r--src/main/cpp/stringhelper.cpp159
-rw-r--r--src/main/cpp/stringmatchfilter.cpp80
-rw-r--r--src/main/cpp/stringtokenizer.cpp60
-rwxr-xr-xsrc/main/cpp/synchronized.cpp49
-rw-r--r--src/main/cpp/syslogappender.cpp356
-rw-r--r--src/main/cpp/syslogwriter.cpp68
-rw-r--r--src/main/cpp/system.cpp96
-rw-r--r--src/main/cpp/systemerrwriter.cpp73
-rw-r--r--src/main/cpp/systemoutwriter.cpp74
-rw-r--r--src/main/cpp/telnetappender.cpp252
-rw-r--r--src/main/cpp/threadcxx.cpp175
-rw-r--r--src/main/cpp/threadlocal.cpp60
-rw-r--r--src/main/cpp/threadpatternconverter.cpp50
-rw-r--r--src/main/cpp/threadspecificdata.cpp131
-rw-r--r--src/main/cpp/throwableinformationpatternconverter.cpp64
-rw-r--r--src/main/cpp/timebasedrollingpolicy.cpp193
-rw-r--r--src/main/cpp/timezone.cpp250
-rw-r--r--src/main/cpp/transcoder.cpp538
-rw-r--r--src/main/cpp/transform.cpp117
-rw-r--r--src/main/cpp/triggeringpolicy.cpp35
-rw-r--r--src/main/cpp/ttcclayout.cpp77
-rw-r--r--src/main/cpp/writer.cpp29
-rw-r--r--src/main/cpp/writerappender.cpp264
-rw-r--r--src/main/cpp/xmllayout.cpp146
-rw-r--r--src/main/cpp/xmlsocketappender.cpp118
-rw-r--r--src/main/cpp/zipcompressaction.cpp86
-rw-r--r--src/main/include/Makefile.am16
-rw-r--r--src/main/include/log4cxx/Makefile.am24
-rw-r--r--src/main/include/log4cxx/appender.h148
-rw-r--r--src/main/include/log4cxx/appenderskeleton.h213
-rw-r--r--src/main/include/log4cxx/asyncappender.h292
-rw-r--r--src/main/include/log4cxx/basicconfigurator.h65
-rw-r--r--src/main/include/log4cxx/config/Makefile.am18
-rw-r--r--src/main/include/log4cxx/config/propertysetter.h108
-rw-r--r--src/main/include/log4cxx/config_msvc.h.in69
-rw-r--r--src/main/include/log4cxx/consoleappender.h79
-rw-r--r--src/main/include/log4cxx/dailyrollingfileappender.h203
-rwxr-xr-xsrc/main/include/log4cxx/db/Makefile.am18
-rw-r--r--src/main/include/log4cxx/db/odbcappender.h292
-rwxr-xr-xsrc/main/include/log4cxx/defaultconfigurator.h55
-rw-r--r--src/main/include/log4cxx/defaultloggerfactory.h45
-rw-r--r--src/main/include/log4cxx/file.h188
-rw-r--r--src/main/include/log4cxx/fileappender.h223
-rw-r--r--src/main/include/log4cxx/filter/Makefile.am18
-rw-r--r--src/main/include/log4cxx/filter/andfilter.h109
-rw-r--r--src/main/include/log4cxx/filter/denyallfilter.h73
-rw-r--r--src/main/include/log4cxx/filter/expressionfilter.h130
-rw-r--r--src/main/include/log4cxx/filter/levelmatchfilter.h102
-rw-r--r--src/main/include/log4cxx/filter/levelrangefilter.h137
-rw-r--r--src/main/include/log4cxx/filter/locationinfofilter.h87
-rw-r--r--src/main/include/log4cxx/filter/mapfilter.h44
-rw-r--r--src/main/include/log4cxx/filter/propertyfilter.h81
-rw-r--r--src/main/include/log4cxx/filter/stringmatchfilter.h92
-rw-r--r--src/main/include/log4cxx/helpers/Makefile.am18
-rw-r--r--src/main/include/log4cxx/helpers/absolutetimedateformat.h40
-rw-r--r--src/main/include/log4cxx/helpers/appenderattachableimpl.h128
-rw-r--r--src/main/include/log4cxx/helpers/aprinitializer.h57
-rw-r--r--src/main/include/log4cxx/helpers/bufferedoutputstream.h63
-rw-r--r--src/main/include/log4cxx/helpers/bufferedwriter.h63
-rwxr-xr-xsrc/main/include/log4cxx/helpers/bytearrayinputstream.h94
-rw-r--r--src/main/include/log4cxx/helpers/bytearrayoutputstream.h77
-rw-r--r--src/main/include/log4cxx/helpers/bytebuffer.h69
-rw-r--r--src/main/include/log4cxx/helpers/cacheddateformat.h220
-rw-r--r--src/main/include/log4cxx/helpers/charsetdecoder.h113
-rw-r--r--src/main/include/log4cxx/helpers/charsetencoder.h135
-rw-r--r--src/main/include/log4cxx/helpers/class.h67
-rw-r--r--src/main/include/log4cxx/helpers/classregistration.h41
-rwxr-xr-xsrc/main/include/log4cxx/helpers/condition.h73
-rw-r--r--src/main/include/log4cxx/helpers/cyclicbuffer.h92
-rw-r--r--src/main/include/log4cxx/helpers/datagrampacket.h135
-rw-r--r--src/main/include/log4cxx/helpers/datagramsocket.h128
-rw-r--r--src/main/include/log4cxx/helpers/date.h67
-rw-r--r--src/main/include/log4cxx/helpers/dateformat.h92
-rw-r--r--src/main/include/log4cxx/helpers/datelayout.h91
-rw-r--r--src/main/include/log4cxx/helpers/datetimedateformat.h42
-rw-r--r--src/main/include/log4cxx/helpers/exception.h287
-rw-r--r--src/main/include/log4cxx/helpers/fileinputstream.h96
-rw-r--r--src/main/include/log4cxx/helpers/fileoutputstream.h67
-rw-r--r--src/main/include/log4cxx/helpers/filewatchdog.h86
-rw-r--r--src/main/include/log4cxx/helpers/inetaddress.h106
-rw-r--r--src/main/include/log4cxx/helpers/inputstream.h72
-rw-r--r--src/main/include/log4cxx/helpers/inputstreamreader.h94
-rw-r--r--src/main/include/log4cxx/helpers/integer.h50
-rw-r--r--src/main/include/log4cxx/helpers/iso8601dateformat.h46
-rw-r--r--src/main/include/log4cxx/helpers/loader.h43
-rw-r--r--src/main/include/log4cxx/helpers/locale.h49
-rw-r--r--src/main/include/log4cxx/helpers/loglog.h113
-rw-r--r--src/main/include/log4cxx/helpers/messagebuffer.h828
-rwxr-xr-xsrc/main/include/log4cxx/helpers/mutex.h51
-rw-r--r--src/main/include/log4cxx/helpers/object.h138
-rw-r--r--src/main/include/log4cxx/helpers/objectimpl.h49
-rw-r--r--src/main/include/log4cxx/helpers/objectoutputstream.h95
-rw-r--r--src/main/include/log4cxx/helpers/objectptr.h183
-rw-r--r--src/main/include/log4cxx/helpers/onlyonceerrorhandler.h103
-rw-r--r--src/main/include/log4cxx/helpers/optionconverter.h164
-rw-r--r--src/main/include/log4cxx/helpers/outputstream.h59
-rw-r--r--src/main/include/log4cxx/helpers/outputstreamwriter.h65
-rwxr-xr-xsrc/main/include/log4cxx/helpers/pool.h59
-rw-r--r--src/main/include/log4cxx/helpers/properties.h186
-rw-r--r--src/main/include/log4cxx/helpers/propertyresourcebundle.h62
-rw-r--r--src/main/include/log4cxx/helpers/reader.h72
-rw-r--r--src/main/include/log4cxx/helpers/relativetimedateformat.h47
-rw-r--r--src/main/include/log4cxx/helpers/resourcebundle.h89
-rw-r--r--src/main/include/log4cxx/helpers/serversocket.h64
-rw-r--r--src/main/include/log4cxx/helpers/simpledateformat.h96
-rw-r--r--src/main/include/log4cxx/helpers/socket.h90
-rw-r--r--src/main/include/log4cxx/helpers/socketoutputstream.h74
-rw-r--r--src/main/include/log4cxx/helpers/strftimedateformat.h68
-rw-r--r--src/main/include/log4cxx/helpers/strictmath.h49
-rw-r--r--src/main/include/log4cxx/helpers/stringhelper.h61
-rw-r--r--src/main/include/log4cxx/helpers/stringtokenizer.h49
-rwxr-xr-xsrc/main/include/log4cxx/helpers/synchronized.h44
-rw-r--r--src/main/include/log4cxx/helpers/syslogwriter.h48
-rw-r--r--src/main/include/log4cxx/helpers/system.h53
-rw-r--r--src/main/include/log4cxx/helpers/systemerrwriter.h59
-rw-r--r--src/main/include/log4cxx/helpers/systemoutwriter.h58
-rw-r--r--src/main/include/log4cxx/helpers/tchar.h171
-rw-r--r--src/main/include/log4cxx/helpers/thread.h184
-rw-r--r--src/main/include/log4cxx/helpers/threadlocal.h85
-rw-r--r--src/main/include/log4cxx/helpers/threadspecificdata.h67
-rw-r--r--src/main/include/log4cxx/helpers/timezone.h70
-rw-r--r--src/main/include/log4cxx/helpers/transcoder.h256
-rw-r--r--src/main/include/log4cxx/helpers/transform.h62
-rw-r--r--src/main/include/log4cxx/helpers/writer.h58
-rw-r--r--src/main/include/log4cxx/helpers/xml.h131
-rw-r--r--src/main/include/log4cxx/hierarchy.h283
-rw-r--r--src/main/include/log4cxx/htmllayout.h133
-rw-r--r--src/main/include/log4cxx/layout.h97
-rw-r--r--src/main/include/log4cxx/level.h285
-rw-r--r--src/main/include/log4cxx/log4cxx.h.in51
-rw-r--r--src/main/include/log4cxx/log4cxx.hw99
-rw-r--r--src/main/include/log4cxx/logger.h1911
-rw-r--r--src/main/include/log4cxx/logmanager.h212
-rw-r--r--src/main/include/log4cxx/logstring.h90
-rw-r--r--src/main/include/log4cxx/mdc.h240
-rw-r--r--src/main/include/log4cxx/ndc.h353
-rw-r--r--src/main/include/log4cxx/net/Makefile.am18
-rw-r--r--src/main/include/log4cxx/net/smtpappender.h283
-rw-r--r--src/main/include/log4cxx/net/socketappender.h143
-rwxr-xr-xsrc/main/include/log4cxx/net/socketappenderskeleton.h179
-rw-r--r--src/main/include/log4cxx/net/sockethubappender.h197
-rw-r--r--src/main/include/log4cxx/net/syslogappender.h141
-rw-r--r--src/main/include/log4cxx/net/telnetappender.h158
-rw-r--r--src/main/include/log4cxx/net/xmlsocketappender.h150
-rw-r--r--src/main/include/log4cxx/nt/EventLogCategories.mc42
-rw-r--r--src/main/include/log4cxx/nt/Makefile.am18
-rw-r--r--src/main/include/log4cxx/nt/nteventlogappender.h111
-rw-r--r--src/main/include/log4cxx/nt/outputdebugstringappender.h48
-rw-r--r--src/main/include/log4cxx/pattern/Makefile.am18
-rw-r--r--src/main/include/log4cxx/pattern/classnamepatternconverter.h65
-rw-r--r--src/main/include/log4cxx/pattern/datepatternconverter.h82
-rw-r--r--src/main/include/log4cxx/pattern/filedatepatternconverter.h52
-rw-r--r--src/main/include/log4cxx/pattern/filelocationpatternconverter.h62
-rw-r--r--src/main/include/log4cxx/pattern/formattinginfo.h117
-rw-r--r--src/main/include/log4cxx/pattern/fulllocationpatternconverter.h63
-rw-r--r--src/main/include/log4cxx/pattern/integerpatternconverter.h64
-rw-r--r--src/main/include/log4cxx/pattern/levelpatternconverter.h62
-rw-r--r--src/main/include/log4cxx/pattern/linelocationpatternconverter.h62
-rw-r--r--src/main/include/log4cxx/pattern/lineseparatorpatternconverter.h69
-rw-r--r--src/main/include/log4cxx/pattern/literalpatternconverter.h67
-rw-r--r--src/main/include/log4cxx/pattern/loggerpatternconverter.h67
-rw-r--r--src/main/include/log4cxx/pattern/loggingeventpatternconverter.h84
-rw-r--r--src/main/include/log4cxx/pattern/messagepatternconverter.h60
-rw-r--r--src/main/include/log4cxx/pattern/methodlocationpatternconverter.h61
-rw-r--r--src/main/include/log4cxx/pattern/nameabbreviator.h81
-rw-r--r--src/main/include/log4cxx/pattern/namepatternconverter.h74
-rw-r--r--src/main/include/log4cxx/pattern/ndcpatternconverter.h60
-rw-r--r--src/main/include/log4cxx/pattern/patternconverter.h124
-rw-r--r--src/main/include/log4cxx/pattern/patternparser.h171
-rw-r--r--src/main/include/log4cxx/pattern/propertiespatternconverter.h71
-rw-r--r--src/main/include/log4cxx/pattern/relativetimepatternconverter.h59
-rw-r--r--src/main/include/log4cxx/pattern/threadpatternconverter.h60
-rw-r--r--src/main/include/log4cxx/pattern/throwableinformationpatternconverter.h74
-rw-r--r--src/main/include/log4cxx/patternlayout.h409
-rw-r--r--src/main/include/log4cxx/portability.h25
-rw-r--r--src/main/include/log4cxx/private/Makefile.am23
-rw-r--r--src/main/include/log4cxx/private/log4cxx_private.h.in56
-rw-r--r--src/main/include/log4cxx/private/log4cxx_private.hw84
-rw-r--r--src/main/include/log4cxx/propertyconfigurator.h395
-rw-r--r--src/main/include/log4cxx/provisionnode.h35
-rwxr-xr-xsrc/main/include/log4cxx/rolling/Makefile.am18
-rw-r--r--src/main/include/log4cxx/rolling/action.h87
-rw-r--r--src/main/include/log4cxx/rolling/filerenameaction.h59
-rw-r--r--src/main/include/log4cxx/rolling/filterbasedtriggeringpolicy.h118
-rwxr-xr-xsrc/main/include/log4cxx/rolling/fixedwindowrollingpolicy.h141
-rw-r--r--src/main/include/log4cxx/rolling/gzcompressaction.h73
-rw-r--r--src/main/include/log4cxx/rolling/manualtriggeringpolicy.h72
-rwxr-xr-xsrc/main/include/log4cxx/rolling/rollingfileappender.h105
-rw-r--r--src/main/include/log4cxx/rolling/rollingfileappenderskeleton.h152
-rwxr-xr-xsrc/main/include/log4cxx/rolling/rollingpolicy.h82
-rwxr-xr-xsrc/main/include/log4cxx/rolling/rollingpolicybase.h128
-rw-r--r--src/main/include/log4cxx/rolling/rolloverdescription.h101
-rwxr-xr-xsrc/main/include/log4cxx/rolling/sizebasedtriggeringpolicy.h82
-rwxr-xr-xsrc/main/include/log4cxx/rolling/timebasedrollingpolicy.h227
-rwxr-xr-xsrc/main/include/log4cxx/rolling/triggeringpolicy.h80
-rw-r--r--src/main/include/log4cxx/rolling/zipcompressaction.h74
-rw-r--r--src/main/include/log4cxx/rollingfileappender.h116
-rw-r--r--src/main/include/log4cxx/simplelayout.h83
-rw-r--r--src/main/include/log4cxx/spi/Makefile.am19
-rw-r--r--src/main/include/log4cxx/spi/appenderattachable.h98
-rw-r--r--src/main/include/log4cxx/spi/configurator.h61
-rw-r--r--src/main/include/log4cxx/spi/defaultrepositoryselector.h50
-rw-r--r--src/main/include/log4cxx/spi/errorhandler.h127
-rw-r--r--src/main/include/log4cxx/spi/filter.h133
-rw-r--r--src/main/include/log4cxx/spi/hierarchyeventlistener.h65
-rw-r--r--src/main/include/log4cxx/spi/location/Makefile.am18
-rw-r--r--src/main/include/log4cxx/spi/location/locationinfo.h136
-rw-r--r--src/main/include/log4cxx/spi/loggerfactory.h46
-rw-r--r--src/main/include/log4cxx/spi/loggerrepository.h116
-rw-r--r--src/main/include/log4cxx/spi/loggingevent.h263
-rw-r--r--src/main/include/log4cxx/spi/optionhandler.h72
-rw-r--r--src/main/include/log4cxx/spi/repositoryselector.h54
-rw-r--r--src/main/include/log4cxx/spi/rootlogger.h60
-rw-r--r--src/main/include/log4cxx/spi/triggeringeventevaluator.h50
-rw-r--r--src/main/include/log4cxx/stream.h566
-rw-r--r--src/main/include/log4cxx/ttcclayout.h187
-rw-r--r--src/main/include/log4cxx/varia/Makefile.am18
-rw-r--r--src/main/include/log4cxx/varia/fallbackerrorhandler.h116
-rw-r--r--src/main/include/log4cxx/writerappender.h217
-rw-r--r--src/main/include/log4cxx/xml/Makefile.am18
-rw-r--r--src/main/include/log4cxx/xml/domconfigurator.h316
-rw-r--r--src/main/include/log4cxx/xml/xmllayout.h138
-rw-r--r--src/main/resources/EventLogCategories.mc46
-rw-r--r--src/main/resources/MSG00001.binbin0 -> 164 bytes
-rwxr-xr-xsrc/main/resources/log4cxx.rc125
-rw-r--r--src/site/Makefile.am16
-rw-r--r--src/site/apt/Makefile.am15
-rw-r--r--src/site/apt/building/ant.apt235
-rw-r--r--src/site/apt/building/autotools.apt136
-rw-r--r--src/site/apt/building/maven.apt95
-rw-r--r--src/site/apt/building/vstudio.apt86
-rw-r--r--src/site/apt/building/xcode.apt65
-rw-r--r--src/site/apt/download.apt44
-rw-r--r--src/site/doxy/Doxyfile.in1306
-rw-r--r--src/site/doxy/Makefile.am86
-rw-r--r--src/site/doxy/license_notice_footer.txt1
-rwxr-xr-xsrc/site/doxy/mainpage.dox22
-rw-r--r--src/site/fml/Makefile.am15
-rw-r--r--src/site/fml/faq.fml70
-rw-r--r--src/site/resources/.htaccess33
-rw-r--r--src/site/resources/css/site.css17
-rwxr-xr-xsrc/site/resources/images/ls-logo.jpgbin0 -> 32725 bytes
-rw-r--r--src/site/resources/images/od.gifbin0 -> 5741 bytes
-rw-r--r--src/site/site.xml69
-rw-r--r--src/site/xdoc/Makefile.am15
-rw-r--r--src/site/xdoc/index.xml936
-rwxr-xr-xsrc/site/xdoc/stylesheets/project.xml43
-rw-r--r--src/site/xdoc/stylesheets/site.css156
-rwxr-xr-xsrc/site/xdoc/stylesheets/site.vsl357
-rw-r--r--src/test/Makefile.am16
-rw-r--r--src/test/cpp/Makefile.am160
-rw-r--r--src/test/cpp/abts.cpp451
-rw-r--r--src/test/cpp/abts.h107
-rw-r--r--src/test/cpp/abts_tests.h23
-rw-r--r--src/test/cpp/appenderskeletontestcase.cpp39
-rw-r--r--src/test/cpp/appenderskeletontestcase.h34
-rw-r--r--src/test/cpp/asyncappendertestcase.cpp288
-rw-r--r--src/test/cpp/consoleappendertestcase.cpp47
-rw-r--r--src/test/cpp/customlogger/xlogger.cpp103
-rw-r--r--src/test/cpp/customlogger/xlogger.h115
-rw-r--r--src/test/cpp/customlogger/xloggertestcase.cpp91
-rw-r--r--src/test/cpp/db/odbcappendertestcase.cpp54
-rw-r--r--src/test/cpp/defaultinit/testcase1.cpp52
-rw-r--r--src/test/cpp/defaultinit/testcase2.cpp61
-rw-r--r--src/test/cpp/defaultinit/testcase3.cpp55
-rw-r--r--src/test/cpp/defaultinit/testcase4.cpp61
-rw-r--r--src/test/cpp/encodingtest.cpp166
-rw-r--r--src/test/cpp/fileappendertest.cpp83
-rw-r--r--src/test/cpp/fileappendertestcase.cpp111
-rw-r--r--src/test/cpp/fileappendertestcase.h34
-rwxr-xr-xsrc/test/cpp/filetestcase.cpp185
-rw-r--r--src/test/cpp/helpers/absolutetimedateformattestcase.cpp179
-rw-r--r--src/test/cpp/helpers/cacheddateformattestcase.cpp613
-rw-r--r--src/test/cpp/helpers/charsetdecodertestcase.cpp110
-rw-r--r--src/test/cpp/helpers/charsetencodertestcase.cpp302
-rw-r--r--src/test/cpp/helpers/cyclicbuffertestcase.cpp169
-rw-r--r--src/test/cpp/helpers/datetimedateformattestcase.cpp241
-rw-r--r--src/test/cpp/helpers/inetaddresstestcase.cpp86
-rw-r--r--src/test/cpp/helpers/iso8601dateformattestcase.cpp161
-rw-r--r--src/test/cpp/helpers/localechanger.cpp50
-rw-r--r--src/test/cpp/helpers/localechanger.h59
-rw-r--r--src/test/cpp/helpers/messagebuffertest.cpp196
-rw-r--r--src/test/cpp/helpers/optionconvertertestcase.cpp219
-rw-r--r--src/test/cpp/helpers/propertiestestcase.cpp47
-rw-r--r--src/test/cpp/helpers/relativetimedateformattestcase.cpp94
-rw-r--r--src/test/cpp/helpers/stringhelpertestcase.cpp126
-rw-r--r--src/test/cpp/helpers/stringtokenizertestcase.cpp135
-rw-r--r--src/test/cpp/helpers/syslogwritertest.cpp44
-rw-r--r--src/test/cpp/helpers/timezonetestcase.cpp126
-rw-r--r--src/test/cpp/helpers/transcodertestcase.cpp309
-rwxr-xr-xsrc/test/cpp/hierarchytest.cpp57
-rw-r--r--src/test/cpp/hierarchythresholdtestcase.cpp131
-rw-r--r--src/test/cpp/insertwide.h34
-rw-r--r--src/test/cpp/l7dtestcase.cpp105
-rw-r--r--src/test/cpp/leveltestcase.cpp121
-rw-r--r--src/test/cpp/loggertestcase.cpp465
-rw-r--r--src/test/cpp/logunit.cpp242
-rw-r--r--src/test/cpp/logunit.h237
-rw-r--r--src/test/cpp/minimumtestcase.cpp248
-rwxr-xr-xsrc/test/cpp/ndctestcase.cpp110
-rw-r--r--src/test/cpp/net/smtpappendertestcase.cpp122
-rw-r--r--src/test/cpp/net/socketappendertestcase.cpp48
-rw-r--r--src/test/cpp/net/sockethubappendertestcase.cpp81
-rw-r--r--src/test/cpp/net/socketservertestcase.cpp481
-rw-r--r--src/test/cpp/net/socketservertestcase.h23
-rw-r--r--src/test/cpp/net/syslogappendertestcase.cpp47
-rw-r--r--src/test/cpp/net/telnetappendertestcase.cpp90
-rw-r--r--src/test/cpp/net/xmlsocketappendertestcase.cpp48
-rw-r--r--src/test/cpp/nt/nteventlogappendertestcase.cpp98
-rw-r--r--src/test/cpp/pattern/num343patternconverter.cpp48
-rw-r--r--src/test/cpp/pattern/num343patternconverter.h40
-rw-r--r--src/test/cpp/pattern/patternparsertestcase.cpp241
-rw-r--r--src/test/cpp/patternlayouttest.cpp547
-rw-r--r--src/test/cpp/propertyconfiguratortest.cpp88
-rw-r--r--src/test/cpp/rolling/filenamepatterntestcase.cpp189
-rw-r--r--src/test/cpp/rolling/filterbasedrollingtest.cpp144
-rw-r--r--src/test/cpp/rolling/manualrollingtest.cpp296
-rw-r--r--src/test/cpp/rolling/obsoletedailyrollingfileappendertest.cpp135
-rw-r--r--src/test/cpp/rolling/obsoleterollingfileappendertest.cpp144
-rw-r--r--src/test/cpp/rolling/sizebasedrollingtest.cpp351
-rwxr-xr-xsrc/test/cpp/rolling/timebasedrollingtest.cpp442
-rw-r--r--src/test/cpp/rollingfileappendertestcase.cpp46
-rw-r--r--src/test/cpp/spi/loggingeventtest.cpp121
-rw-r--r--src/test/cpp/streamtestcase.cpp619
-rw-r--r--src/test/cpp/testchar.h33
-rw-r--r--src/test/cpp/testutil.h28
-rw-r--r--src/test/cpp/util/absolutedateandtimefilter.cpp24
-rw-r--r--src/test/cpp/util/absolutedateandtimefilter.h33
-rw-r--r--src/test/cpp/util/absolutetimefilter.cpp24
-rw-r--r--src/test/cpp/util/absolutetimefilter.h33
-rw-r--r--src/test/cpp/util/binarycompare.cpp82
-rw-r--r--src/test/cpp/util/binarycompare.h36
-rw-r--r--src/test/cpp/util/compare.cpp170
-rw-r--r--src/test/cpp/util/compare.h43
-rw-r--r--src/test/cpp/util/controlfilter.cpp30
-rw-r--r--src/test/cpp/util/controlfilter.h36
-rw-r--r--src/test/cpp/util/filenamefilter.cpp38
-rw-r--r--src/test/cpp/util/filenamefilter.h34
-rw-r--r--src/test/cpp/util/filter.h68
-rw-r--r--src/test/cpp/util/iso8601filter.cpp23
-rw-r--r--src/test/cpp/util/iso8601filter.h33
-rw-r--r--src/test/cpp/util/linenumberfilter.cpp27
-rw-r--r--src/test/cpp/util/linenumberfilter.h33
-rw-r--r--src/test/cpp/util/relativetimefilter.cpp24
-rw-r--r--src/test/cpp/util/relativetimefilter.h33
-rw-r--r--src/test/cpp/util/serializationtesthelper.cpp81
-rw-r--r--src/test/cpp/util/serializationtesthelper.h42
-rw-r--r--src/test/cpp/util/threadfilter.cpp23
-rw-r--r--src/test/cpp/util/threadfilter.h33
-rw-r--r--src/test/cpp/util/transformer.cpp222
-rw-r--r--src/test/cpp/util/transformer.h56
-rw-r--r--src/test/cpp/util/utilfilter.cpp31
-rw-r--r--src/test/cpp/util/xmlfilenamefilter.cpp30
-rw-r--r--src/test/cpp/util/xmlfilenamefilter.h33
-rw-r--r--src/test/cpp/util/xmllineattributefilter.cpp25
-rw-r--r--src/test/cpp/util/xmllineattributefilter.h33
-rw-r--r--src/test/cpp/util/xmlthreadfilter.cpp25
-rw-r--r--src/test/cpp/util/xmlthreadfilter.h33
-rw-r--r--src/test/cpp/util/xmltimestampfilter.cpp26
-rw-r--r--src/test/cpp/util/xmltimestampfilter.h33
-rw-r--r--src/test/cpp/varia/errorhandlertestcase.cpp137
-rw-r--r--src/test/cpp/varia/levelmatchfiltertestcase.cpp168
-rw-r--r--src/test/cpp/varia/levelrangefiltertestcase.cpp257
-rw-r--r--src/test/cpp/vectorappender.cpp47
-rw-r--r--src/test/cpp/vectorappender.h59
-rw-r--r--src/test/cpp/writerappendertestcase.cpp28
-rw-r--r--src/test/cpp/writerappendertestcase.h34
-rw-r--r--src/test/cpp/xml/customleveltestcase.cpp126
-rw-r--r--src/test/cpp/xml/domtestcase.cpp236
-rw-r--r--src/test/cpp/xml/xlevel.cpp82
-rw-r--r--src/test/cpp/xml/xlevel.h66
-rw-r--r--src/test/cpp/xml/xmllayouttest.cpp417
-rw-r--r--src/test/cpp/xml/xmllayouttestcase.cpp357
-rw-r--r--src/test/java/org/apache/log4j/net/ShortSocketServer.java89
-rw-r--r--src/test/resources/L7D_en_US.properties18
-rw-r--r--src/test/resources/L7D_fr.properties18
-rw-r--r--src/test/resources/L7D_fr_CH.properties17
-rw-r--r--src/test/resources/Makefile.am68
-rw-r--r--src/test/resources/input/Makefile.am26
-rw-r--r--src/test/resources/input/defaultInit3.properties21
-rw-r--r--src/test/resources/input/hierarchyThreshold1.properties22
-rw-r--r--src/test/resources/input/hierarchyThreshold2.properties22
-rw-r--r--src/test/resources/input/hierarchyThreshold3.properties22
-rw-r--r--src/test/resources/input/hierarchyThreshold4.properties22
-rw-r--r--src/test/resources/input/hierarchyThreshold5.properties22
-rw-r--r--src/test/resources/input/hierarchyThreshold6.properties22
-rw-r--r--src/test/resources/input/hierarchyThreshold7.properties22
-rw-r--r--src/test/resources/input/hierarchyThreshold8.properties22
-rw-r--r--src/test/resources/input/l7d1.properties21
-rw-r--r--src/test/resources/input/ndc/Makefile.am25
-rwxr-xr-xsrc/test/resources/input/ndc/NDC1.properties26
-rw-r--r--src/test/resources/input/patternLayout.mdc.1.properties21
-rw-r--r--src/test/resources/input/patternLayout1.properties21
-rw-r--r--src/test/resources/input/patternLayout10.properties21
-rw-r--r--src/test/resources/input/patternLayout11.properties21
-rw-r--r--src/test/resources/input/patternLayout12.properties21
-rw-r--r--src/test/resources/input/patternLayout2.properties21
-rw-r--r--src/test/resources/input/patternLayout3.properties21
-rw-r--r--src/test/resources/input/patternLayout4.properties21
-rw-r--r--src/test/resources/input/patternLayout5.properties21
-rw-r--r--src/test/resources/input/patternLayout6.properties21
-rw-r--r--src/test/resources/input/patternLayout7.properties21
-rw-r--r--src/test/resources/input/patternLayout8.properties21
-rw-r--r--src/test/resources/input/patternLayout9.properties21
-rw-r--r--src/test/resources/input/rolling/Makefile.am25
-rw-r--r--src/test/resources/input/rolling/filter1.xml55
-rw-r--r--src/test/resources/input/rolling/obsoleteDRFA1.properties27
-rw-r--r--src/test/resources/input/rolling/obsoleteERFA1.properties28
-rw-r--r--src/test/resources/input/rolling/obsoleteRFA1.properties27
-rw-r--r--src/test/resources/input/rolling/time1.xml43
-rw-r--r--src/test/resources/input/socketServer1.properties23
-rw-r--r--src/test/resources/input/socketServer2.properties23
-rw-r--r--src/test/resources/input/socketServer3.properties22
-rw-r--r--src/test/resources/input/socketServer4.properties22
-rw-r--r--src/test/resources/input/socketServer5.properties22
-rw-r--r--src/test/resources/input/socketServer6.properties22
-rw-r--r--src/test/resources/input/socketServer7.properties22
-rw-r--r--src/test/resources/input/socketServer8.properties22
-rwxr-xr-xsrc/test/resources/input/xml/DOMTestCase1.xml51
-rwxr-xr-xsrc/test/resources/input/xml/DOMTestCase2.xml51
-rwxr-xr-xsrc/test/resources/input/xml/DOMTestCase3.xml37
-rwxr-xr-xsrc/test/resources/input/xml/DOMTestCase4.xml37
-rw-r--r--src/test/resources/input/xml/Makefile.am25
-rwxr-xr-xsrc/test/resources/input/xml/asyncAppender1.xml36
-rwxr-xr-xsrc/test/resources/input/xml/customLevel1.xml36
-rwxr-xr-xsrc/test/resources/input/xml/customLevel2.xml43
-rwxr-xr-xsrc/test/resources/input/xml/customLevel3.xml46
-rwxr-xr-xsrc/test/resources/input/xml/customLevel4.xml37
-rw-r--r--src/test/resources/input/xml/customLogger1.xml37
-rw-r--r--src/test/resources/input/xml/customLogger2.xml45
-rw-r--r--src/test/resources/input/xml/defaultInit.xml34
-rw-r--r--src/test/resources/input/xml/fallback1.xml52
-rw-r--r--src/test/resources/input/xml/filters.LevelMatchFilter.test4.0.xml40
-rw-r--r--src/test/resources/input/xml/filters.LevelMatchFilter.test4.1.xml40
-rw-r--r--src/test/resources/input/xml/filters.LevelMatchFilter.test4.2.xml40
-rw-r--r--src/test/resources/input/xml/filters.LevelMatchFilter.test4.3.xml40
-rw-r--r--src/test/resources/input/xml/filters.LevelMatchFilter.test4.4.xml40
-rwxr-xr-xsrc/test/resources/input/xml/log4j.dtd227
-rw-r--r--src/test/resources/input/xml/smtpAppender1.xml39
-rw-r--r--src/test/resources/witness/LevelMatchFilter_accept5
-rw-r--r--src/test/resources/witness/LevelMatchFilter_deny20
-rw-r--r--src/test/resources/witness/LevelRangeFilter_accept46
-rw-r--r--src/test/resources/witness/LevelRangeFilter_neutral46
-rw-r--r--src/test/resources/witness/Makefile.am38
-rw-r--r--src/test/resources/witness/NDCMatchFilter_accept11
-rw-r--r--src/test/resources/witness/NDCMatchFilter_deny21
-rwxr-xr-xsrc/test/resources/witness/customLevel.15
-rwxr-xr-xsrc/test/resources/witness/customLevel.25
-rwxr-xr-xsrc/test/resources/witness/customLevel.31
-rwxr-xr-xsrc/test/resources/witness/customLevel.45
-rw-r--r--src/test/resources/witness/customLogger.16
-rw-r--r--src/test/resources/witness/customLogger.21
-rwxr-xr-xsrc/test/resources/witness/dom.A1.115
-rwxr-xr-xsrc/test/resources/witness/dom.A1.215
-rwxr-xr-xsrc/test/resources/witness/dom.A2.110
-rwxr-xr-xsrc/test/resources/witness/dom.A2.210
-rw-r--r--src/test/resources/witness/encoding/Makefile.am27
-rw-r--r--src/test/resources/witness/encoding/UTF-16.logbin0 -> 88 bytes
-rw-r--r--src/test/resources/witness/encoding/UTF-16BE.logbin0 -> 86 bytes
-rw-r--r--src/test/resources/witness/encoding/UTF-16LE.logbin0 -> 86 bytes
-rw-r--r--src/test/resources/witness/encoding/UTF-8.log3
-rw-r--r--src/test/resources/witness/encoding/ascii.log3
-rw-r--r--src/test/resources/witness/encoding/latin1.log3
-rw-r--r--src/test/resources/witness/fallback10
-rw-r--r--src/test/resources/witness/hierarchyThreshold.10
-rw-r--r--src/test/resources/witness/hierarchyThreshold.21
-rw-r--r--src/test/resources/witness/hierarchyThreshold.32
-rw-r--r--src/test/resources/witness/hierarchyThreshold.43
-rw-r--r--src/test/resources/witness/hierarchyThreshold.54
-rw-r--r--src/test/resources/witness/hierarchyThreshold.65
-rw-r--r--src/test/resources/witness/hierarchyThreshold.76
-rw-r--r--src/test/resources/witness/hierarchyThreshold.86
-rw-r--r--src/test/resources/witness/l7d.121
-rw-r--r--src/test/resources/witness/ndc/Makefile.am25
-rwxr-xr-xsrc/test/resources/witness/ndc/NDC.125
-rw-r--r--src/test/resources/witness/patternLayout.110
-rw-r--r--src/test/resources/witness/patternLayout.1010
-rw-r--r--src/test/resources/witness/patternLayout.1110
-rw-r--r--src/test/resources/witness/patternLayout.1210
-rw-r--r--src/test/resources/witness/patternLayout.210
-rw-r--r--src/test/resources/witness/patternLayout.310
-rw-r--r--src/test/resources/witness/patternLayout.410
-rw-r--r--src/test/resources/witness/patternLayout.510
-rw-r--r--src/test/resources/witness/patternLayout.610
-rw-r--r--src/test/resources/witness/patternLayout.710
-rw-r--r--src/test/resources/witness/patternLayout.810
-rw-r--r--src/test/resources/witness/patternLayout.910
-rw-r--r--src/test/resources/witness/patternLayout.mdc.11
-rw-r--r--src/test/resources/witness/patternLayout.mdc.212
-rw-r--r--src/test/resources/witness/rolling/Makefile.am26
-rw-r--r--src/test/resources/witness/rolling/sbr-test2.010
-rw-r--r--src/test/resources/witness/rolling/sbr-test2.110
-rw-r--r--src/test/resources/witness/rolling/sbr-test2.log5
-rw-r--r--src/test/resources/witness/rolling/sbr-test3.0.gzbin0 -> 68 bytes
-rw-r--r--src/test/resources/witness/rolling/sbr-test3.1.gzbin0 -> 68 bytes
-rw-r--r--src/test/resources/witness/rolling/sbr-test3.log5
-rw-r--r--src/test/resources/witness/rolling/sbr-test4.log25
-rw-r--r--src/test/resources/witness/rolling/tbr-test1.00
-rw-r--r--src/test/resources/witness/rolling/tbr-test1.12
-rw-r--r--src/test/resources/witness/rolling/tbr-test1.22
-rw-r--r--src/test/resources/witness/rolling/tbr-test1.31
-rw-r--r--src/test/resources/witness/rolling/tbr-test2.00
-rw-r--r--src/test/resources/witness/rolling/tbr-test2.12
-rw-r--r--src/test/resources/witness/rolling/tbr-test2.22
-rw-r--r--src/test/resources/witness/rolling/tbr-test2.31
-rw-r--r--src/test/resources/witness/rolling/tbr-test3.31
-rw-r--r--src/test/resources/witness/rolling/tbr-test4.00
-rw-r--r--src/test/resources/witness/rolling/tbr-test4.12
-rw-r--r--src/test/resources/witness/rolling/tbr-test4.22
-rw-r--r--src/test/resources/witness/rolling/tbr-test4.31
-rw-r--r--src/test/resources/witness/rolling/tbr-test5.00
-rw-r--r--src/test/resources/witness/rolling/tbr-test5.12
-rw-r--r--src/test/resources/witness/rolling/tbr-test5.22
-rw-r--r--src/test/resources/witness/rolling/tbr-test5.31
-rw-r--r--src/test/resources/witness/rolling/tbr-test6.31
-rw-r--r--src/test/resources/witness/serialization/exception.binbin0 -> 1843 bytes
-rw-r--r--src/test/resources/witness/serialization/info.binbin0 -> 60 bytes
-rw-r--r--src/test/resources/witness/serialization/location.binbin0 -> 465 bytes
-rw-r--r--src/test/resources/witness/serialization/mdc.binbin0 -> 508 bytes
-rw-r--r--src/test/resources/witness/serialization/ndc.binbin0 -> 409 bytes
-rw-r--r--src/test/resources/witness/serialization/simple.binbin0 -> 399 bytes
-rw-r--r--src/test/resources/witness/simple25
-rw-r--r--src/test/resources/witness/socketServer.131
-rw-r--r--src/test/resources/witness/socketServer.231
-rw-r--r--src/test/resources/witness/socketServer.331
-rw-r--r--src/test/resources/witness/socketServer.431
-rw-r--r--src/test/resources/witness/socketServer.531
-rw-r--r--src/test/resources/witness/socketServer.631
-rw-r--r--src/test/resources/witness/socketServer.731
-rw-r--r--src/test/resources/witness/socketServer.831
-rw-r--r--src/test/resources/witness/ttcc25
-rw-r--r--src/test/resources/witness/xmlLayout.168
-rw-r--r--src/test/resources/witness/xmlLayout.285
-rw-r--r--src/test/resources/witness/xmlLayout.310
-rw-r--r--src/test/resources/witness/xmlLayout.mdc.18
-rw-r--r--src/test/resources/witness/xmlLayout.mdc.28
-rw-r--r--src/test/resources/witness/xmlLayout.null12
694 files changed, 75585 insertions, 0 deletions
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..6f568a8
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,157 @@
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Detailed build instructions are provided for in both HTML
+and APT format in releases. The APT sources are
+available in Subversion checkouts.
+
+autotools:
+site/building/autotools.html
+src/site/apt/building/autotools.apt
+
+Apache Ant:
+site/building/ant.html
+src/site/apt/building/ant.apt
+
+Apache Maven 2:
+site/building/maven.html
+src/site/apt/building/maven.apt
+
+Microsoft Visual Studio:
+site/building/vstudio.html
+src/site/apt/building/vstudio.apt
+
+Apple Xcode:
+site/building/xcode.html
+src/site/apt/building/xcode.apt
+
+
+
+
+Introduction
+============
+Apache log4cxx is a C++ transliteration of Apache log4j.
+
+
+
+Maven 2:
+==================
+
+Maven 2 used to prepare site documentation and will be used to package the release.
+TODO: add more documentation.
+
+
+Ant + cpptasks build:
+==================
+
+The Ant build script is the definitive build script for log4cxx and
+is able to build log4cxx with (at least) gcc, Microsoft Visual C++ 6, 7, 7.1
+and Borland C++ 5.5 and produce IDE project files for Microsoft Visual Studio
+6, Borland CBuilderX and Apple Xcode to assist in debugging.
+
+Prerequisites:
+
+Apache Ant 1.6.1 or later
+ http://ant.apache.org
+
+cpptasks.jar and ant-contrib.jar on CLASSPATH
+ (March 2005 or later releases or CVS HEAD)
+ http://ant-contrib.sourceforge.net
+
+JDK 1.4 or later. Earlier versions might work but
+have not been tested.
+
+GNU patch on command path.
+
+GNU sed, gzip and zip on command path (required for tests)
+
+Connection to internet
+
+ - or -
+
+The following files placed in the lib directory:
+ apr-1.2.2.tar.gz
+ apr-util-1.2.2.tar.gz
+
+ http://apr.apache.org
+
+
+
+Building:
+
+Unix gcc:
+
+$> export CLASSPATH=path_to_cpptasks/cpptasks.jar:path_to_antcontrib/ant-contrib.jar
+
+- or -
+
+$> setenv CLASSPATH path_to_cpptasks/cpptasks.jar:path_to_antcontrib/ant-contrib.jar
+
+
+$> ant
+
+
+Microsoft Visual C++:
+
+$> set CLASSPATH=path_to_cpptasks/cpptasks.jar;path_to_antcontrib/ant-contrib.jar
+$> path_to_vc\bin\vcvars32
+$> ant
+
+
+Borland C++:
+
+$> set CLASSPATH=path_to_cpptasks/cpptasks.jar;path_to_antcontrib/ant-contrib.jar
+$> ant -Dcompiler=bcc
+
+
+
+Build options:
+
+ -Dcompiler= see list from http://ant-contrib.sourceforge.net/cc.html
+ -Ddebug=[true | false]
+ -Dlib.type=[shared | static | dylib]
+ -Drtti=[false | true]
+ -Dapache.mirror=URL
+ -Dapr.lib.type=[static | shared]
+ -Daprutil.lib.type=[static | shared]
+ -Dapriconv.lib.type=[static | shared]
+ -Dhas.wchar_t=[1 | 0]
+ -Dlogchar=[wchar_t utf8]
+ -Dos.family=cygwin
+
+Build targets:
+
+ build Build log4cxx library
+ build-all Builds all artifacts
+ build-examples Builds example programs
+ build-projects-cbx Builds project files for Borland CBuilderX
+ build-projects-vc6 Builds project files for Microsoft Visual C++ 6
+ build-projects-xcode Builds project files for Apple Xcode
+ build-shortsocketserver builds a socket server used by unit tests
+ build-standalone-unittest Builds a unit tests + log4cxx executable
+ build-unittest Builds unit test app
+ check Runs all diagnostic tests
+ clean Removes built files
+ dist Builds a source distribution
+ fixcrlf repair end-of-line sequences
+ header-check Checks headers against Effective C++ guidelines
+ run-standalone-unittest Runs standalone unit test
+ run-unittest Runs unit test
+ usage Describes usage of the build script
+
+
+
+
+
diff --git a/KEYS b/KEYS
new file mode 100644
index 0000000..0f0c3c0
--- /dev/null
+++ b/KEYS
@@ -0,0 +1,52 @@
+This file contains the PGP&GPG keys of various Apache developers.
+Please don't use them for email unless you have to. Their main
+purpose is code signing.
+
+Apache users: pgp < KEYS
+Apache developers:
+ (pgpk -ll <your name> && pgpk -xa <your name>) >> this file.
+ or
+ (gpg --fingerprint --list-sigs <your name>
+ && gpg --armor --export <your name>) >> this file.
+
+Apache developers: please ensure that your key is also available via the
+PGP keyservers (such as pgpkeys.mit.edu).
+
+
+pub 1024D/2E114322 2005-06-11 [expires: 2010-06-10]
+ Key fingerprint = A1A2 B554 6D43 31B2 A41E 1C07 BE16 C95D 2E11 4322
+uid Curt Arnold <carnold@apache.org>
+sig 3 2E114322 2005-06-11 Curt Arnold <carnold@apache.org>
+sub 2048g/209ECE57 2005-06-11 [expires: 2010-06-10]
+sig 2E114322 2005-06-11 Curt Arnold <carnold@apache.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.3 (Darwin)
+
+mQGiBEKrSNQRBAC4J7udOBoC5+gVxBaPAbjXfnq12l5Pau1WD+UothePNGjI2hOp
++Rnzikk3ISgyrjiX3A8ScZYbu3iXvMpF4zknkGLdmerpf4Gz9xGeushwun+UFaFL
+MX5u7LWJo9wDKzbcJJit1j/qGEg/HRp5fnVYCh0/l4dLansL60NhxtYdxwCguu2e
+wZMZFroaiIXqnce7+cGDRq8D/2HgKGtEJHY3z8OtUqncWbW+RAQqdcT0Z+bMB8o6
+0UCHxUoJrFS1lA62qU3kcZ8ACPoh9xDW4X47EgNPELX81alymTI5FdqiDK7RIwzE
+JlOH/8JJgC6eSwiUXJ0cOJwpMonitcpMLouxuURuPSpfE5b1mQ1gFzN5MBL8xlZQ
+8IO6A/9qWwyWyQBoJud0RDIsVRosdoSBZtw9PHsURgsqfNsS2NXTWK4HjxExw1KO
+AXmRlALfrH8yAShy/AyiUrwlKHG2WPTe6Etygjlr4dIxqTiCOoi+qv+H8SXW4Qy3
+SnyozJ2RlKoYG0oDTbVMsPhOFdytHjConDLL9vS14j4kN9zWB7QgQ3VydCBBcm5v
+bGQgPGNhcm5vbGRAYXBhY2hlLm9yZz6IZAQTEQIAJAUCQqtI1AIbAwUJCWYBgAYL
+CQgHAwIDFQIDAxYCAQIeAQIXgAAKCRC+FsldLhFDIs5CAJ9roOB39ithHoCLaDJx
+l14efLwgNgCfcDBYutNX5W627kCeheDqhQbTqTi5Ag0EQqtJBRAIAN8maiGIO44S
+dc9Ep3CAm0aXDeR8IQ/F253WcMQtkFBjeHEDd6/+EFT52vswMI6ZJDVV/A7pe4VM
+XAdNutFmUG2gy9OJOu8gMuO3jTCLxUXyQYNF/RasOAQJgc7q1N5QgKtXVH2InQ21
+vHvlHM1fVe4rYDPr4JL2lZHe0P8kTzeQ7jI5pQnfYRJmS8I5AMQYFOiM48Pd7Sbs
+Wu/rym7ikcmKUe6ZE59hSioneVP31CDMNRxCAQJVS1mZxTozsAEoh+cvmRjOD1Es
+0iXvu6Sfe8+sLRL+7CNUZgixE1UFbdnNxuZGlG9qs0LGP7hDWijT1/Y4SHz4ovXx
+k0oocmFtiLcAAwcIAMbY7K99hLAFVaU2ukxCSp1TNPcD+IB3gtpRieKaZvBn/LGe
+CO+fNAogkw537lmpLk4nI+JiP/xWohyJ9lyEpW7yD4c9AHKNjqvEWD5Bhpnw4qKJ
+ohQSVQwEeJRsftY4D0jCP9xbgPiq5woBzHWNok3BVaHqLK0fd0/+KygnT+k6cR22
+Mus9RsEisXk9Oj5lvC0miDOWof4vk2Ll8/H3xt4CXAr13n5Yj2632HolOHrFUQXT
+gwc9v5CNIihOQMEiXFxHh743qbsUZktjxeYH7r8wSCV93/QQ4qELiWoUzndpkCRT
+lEKenucAv6f5qqZqG7pVW8S48T99HwzwqgFX5VOITwQYEQIADwUCQqtJBQIbDAUJ
+CWYBgAAKCRC+FsldLhFDIjnoAJ9ECOIrTH3adnVLOkHZnewyp2ssxwCgtLjlwZ7/
+4QtL3W5Id3nKxPFiI+c=
+=9ut1
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ 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 [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..ae48ca9
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+AUTOMAKE_OPTIONS = foreign
+
+SUBDIRS = src
+EXTRA_DIST = autogen.sh aclocal.m4 find_apr.m4 find_apu.m4 build.xml pom.xml NOTICE LICENSE INSTALL pom.xml KEYS
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = liblog4cxx.pc
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..34791e6
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,5 @@
+Apache log4cxx
+Copyright 2004-2007 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..1511583
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,29 @@
+#! /bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Regenerate the files autoconf / automake
+
+case `uname` in
+ (Darwin) LIBTOOLIZE=glibtoolize ;;
+ (*) LIBTOOLIZE=libtoolize ;;
+esac
+$LIBTOOLIZE --force --automake --copy
+
+rm -f config.cache
+rm -f config.log
+aclocal -I .
+autoconf
+automake -a --copy
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..2d318fa
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,1251 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<!DOCTYPE project [
+<!ENTITY libsets '
+ <libset libs="${apr-util.lib.prefix}${apr-util.lib.name}${apr-util.lib.suffix}" dir="${apr-util.lib.dir}" if="apr-util.lib.dir"/>
+ <libset libs="${apr-util.lib.prefix}${apr-util.lib.name}${apr-util.lib.suffix}" unless="apr-util.lib.dir"/>
+ <libset libs="${apr.lib.prefix}${apr.lib.name}${apr.lib.suffix}" dir="${apr.lib.dir}" if="apr.lib.dir"/>
+ <libset libs="${apr.lib.prefix}${apr.lib.name}${apr.lib.suffix}" unless="apr.lib.dir"/>
+ <libset libs="esmtp" dir="${esmtp.lib.dir}" if="esmtp.lib.dir"/>
+ <libset libs="esmtp" if="has-libesmtp" unless="esmtp.lib.dir"/>
+ <libset libs="${odbc.lib}" if="odbc.lib"/>
+ <libset libs="${apr-util.dependencies}" if="apr-util.dependencies" unless="apr-util-includes-dependencies"/>
+ <libset libs="pthread" if="is-unix"/>
+ <syslibset libs="advapi32 mswsock ws2_32 shell32" if="is-windows"/>
+ <syslibset libs="stdc++" if="is-gcc"/>
+ <syslibset libs="cw32mt" if="is-bcc"/>
+'>
+<!ENTITY license '
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+'>
+<!ENTITY common SYSTEM 'src/ant/common.xml'>
+<!ENTITY find-apr SYSTEM 'src/ant/find-apr.xml'>
+<!ENTITY find-apr-util SYSTEM 'src/ant/find-apr-util.xml'>
+<!ENTITY find-libesmtp SYSTEM 'src/ant/find-libesmtp.xml'>
+]>
+
+<!--
+This file builds log4cxx using Apache Ant (http://ant.apache.org)
+and the C++ compilation tasks from http://ant-contrib.sourceforge.net.
+
+
+-->
+<project name="log4cxx" default="check">
+
+&common;
+&find-apr;
+&find-apr-util;
+&find-libesmtp;
+
+<property name="base.dir" location="."/>
+<property name="src.dir" location="${base.dir}/src/main/cpp"/>
+<property name="resources.dir" location="${base.dir}/src/main/resources"/>
+<property name="include.dir" location="${base.dir}/src/main/include"/>
+<property name="target.dir" location="${base.dir}/target"/>
+<property name="lib.dir" location="${target.dir}/lib"/>
+<property name="examples.dir" location="${base.dir}/src/examples/cpp"/>
+<property name="tests.dir" location="${base.dir}/src/test"/>
+<property name="tests.cpp.dir" location="${tests.dir}/cpp"/>
+<property name="tests.resources.dir" location="${tests.dir}/resources"/>
+<property name="tests.output.dir" location="${tests.resources.dir}/output"/>
+<property name="m2_repo" location="${user.home}/.m2/repository"/>
+<property name="log4j.version" value="1.2.14"/>
+<available property="log4j.jar"
+ value="/usr/share/java/log4j-1.2.jar"
+ file="/usr/share/java/log4j-1.2.jar"/>
+<property name="log4j.jar"
+ location="${m2_repo}/log4j/log4j/${log4j.version}/log4j-${log4j.version}.jar"/>
+
+
+<property name="doxygen.exe" value="doxygen"/>
+
+<property name="lib.name" value="log4cxx"/>
+<property name="lib.prefix" value=""/>
+<property name="version" value="0.10.0"/>
+<property name="enable-char" value="1"/>
+<property name="enable-wchar_t" value="1"/>
+<property name="enable-unichar" value="0"/>
+<property name="enable-cfstring" value="0"/>
+<property name="with-charset" value="auto"/>
+<property name="with-SMTP" value="no"/>
+<property name="with-ODBC" value="no"/>
+
+
+<property name="svnsite.url" value="https://svn.apache.org/repos/asf/logging/site/trunk/docs/log4cxx"/>
+
+
+
+<target name="usage" description="Describes usage of the build script">
+ <echo>
+Ant build file for log4cxx
+
+Common invocations:
+
+> ant
+
+will attempt to locate APR and APR-util in /usr, /usr/local/apr and ..
+
+Builds and tests log4cxx.
+
+> ant -Dwith-apr=APRPATH -Dwith-apr-util=APUPATH
+
+Builds and tests log4cxx using APR and APR-Util at specified location
+
+> ant -p
+
+Displays available targets
+
+> ant build-projects-vc6
+
+Builds Microsoft Visual Studio 6 projects.
+-vc7, -vc8, -vc9 and -xcode for Visual Studio .NET, 2005, 2008 and Apple Xcode 2 and later.
+respectively.
+
+Command line options:
+
+-Ddebug=[true|false]
+-Doptimize=[speed|size|none]
+-Dversion=n.n.n
+-Denable-shared=[yes|no] (default yes)
+-Denable-static=[yes|no] (default yes)
+-Denable-char=[0, 1] (expose char* API, default 1)
+-Denable-wchar_t=[0, 1] (expose wchar_t* API, default 1)
+-Denable-unichar=[0, 1] (expose UniChar API, default 0)
+-Denable-cfstring[0, 1] (expose CFString API, default 0)
+-Dwith-charset=[auto|utf-8|iso-8859-1|usascii|ebcdic] (default auto)
+-Dwith-logchar=[utf-8|wchar_t|unichar] (default=utf-8 on Unix, wchar_t on Windows)
+-Dwith-apr=APRPATH
+-Dwith-apr-util=PATH
+-Dwith-SMTP=[libesmtp, no] (default no)
+-Dwith-ODBC=[unixODBC, iODBC, Microsoft, no] (default no)
+
+</echo>
+</target>
+
+
+<target name="init" depends="common-init">
+
+ <property name="log4cxx.lib.dir" value="${executable.dir}"/>
+ <mkdir dir="${log4cxx.lib.dir}"/>
+
+ <condition property="with-logchar" value="wchar_t">
+ <isset property="is-windows"/>
+ </condition>
+ <property name="with-logchar" value="utf-8"/>
+
+ <condition property="has-libesmtp" value="1">
+ <equals arg1="${with-SMTP}" arg2="libesmtp"/>
+ </condition>
+
+ <condition property="odbc.lib" value="iodbc">
+ <equals arg1="${with-ODBC}" arg2="iODBC"/>
+ </condition>
+
+ <condition property="odbc.lib" value="unixodbc">
+ <equals arg1="${with-ODBC}" arg2="unixODBC"/>
+ </condition>
+
+ <condition property="odbc.lib" value="odbc32">
+ <equals arg1="${with-ODBC}" arg2="Microsoft"/>
+ </condition>
+
+ <condition property="has-ODBC" value="1">
+ <isset property="odbc.lib"/>
+ </condition>
+ <property name="has-ODBC" value="0"/>
+
+ <condition property="force-ant" value="1">
+ <equals arg1="${find}" arg2="false"/>
+ </condition>
+ <echo>force-ant: ${force-ant}</echo>
+
+</target>
+
+<target name="clean" depends="init" description="Removes built files">
+ <delete dir="${target.dir}"/>
+ <delete>
+ <fileset dir="${include.dir}/log4cxx" includes="**/log4cxx.h"/>
+ </delete>
+
+</target>
+
+<target name="unix-configure" if="is-unix">
+ <copy tofile="${include.dir}/log4cxx/log4cxx.tmp"
+ file="${include.dir}/log4cxx/log4cxx.h.in" overwrite="true"/>
+ <copy tofile="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ file="${include.dir}/log4cxx/private/log4cxx_private.h.in" overwrite="true"/>
+</target>
+
+<target name="win-configure" if="is-windows">
+ <copy tofile="${include.dir}/log4cxx/log4cxx.tmp"
+ file="${include.dir}/log4cxx/log4cxx.hw" overwrite="true"/>
+ <copy tofile="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ file="${include.dir}/log4cxx/private/log4cxx_private.hw" overwrite="true"/>
+ <property name="odbc.lib" value="odbc32"/>
+</target>
+
+
+<target name="configure" depends="init,
+ unix-configure,
+ win-configure">
+ <echo message="Configuring with-logchar=${with-logchar}" />
+ <echo message="Configuring with-charset=${with-charset}" />
+ <echo message="Configuring with-SMTP=${with-SMTP}" />
+ <echo message="Configuring with-ODBC=${with-ODBC}" />
+ <echo message="Configuring enable-char=${enable-char}"/>
+ <echo message="Configuring enable-wchar_t=${enable-wchar_t}"/>
+ <echo message="Configuring enable-unichar=${enable-unichar}"/>
+ <echo message="Configuring enable-cfstring=${enable-cfstring}"/>
+
+ <condition property="logchar_is_utf8" value="1">
+ <equals arg1="${with-logchar}" arg2="utf-8"/>
+ </condition>
+ <property name="logchar_is_utf8" value="0"/>
+
+ <condition property="logchar_is_unichar" value="1">
+ <equals arg1="${with-logchar}" arg2="unichar"/>
+ </condition>
+ <property name="logchar_is_unichar" value="0"/>
+
+ <condition property="logchar_is_wchar" value="1">
+ <equals arg1="${with-logchar}" arg2="wchar_t"/>
+ </condition>
+ <property name="logchar_is_wchar" value="0"/>
+
+ <replaceregexp file="${include.dir}/log4cxx/log4cxx.tmp"
+ match="@LOGCHAR_IS_UNICHAR@"
+ replace="${logchar_is_unichar}"/>
+
+ <replaceregexp file="${include.dir}/log4cxx/log4cxx.tmp"
+ match="@LOGCHAR_IS_UTF8@"
+ replace="${logchar_is_utf8}"/>
+
+ <replaceregexp file="${include.dir}/log4cxx/log4cxx.tmp"
+ match="@LOGCHAR_IS_WCHAR@"
+ replace="${logchar_is_wchar}"/>
+
+ <condition property="charset_is_utf8" value="1">
+ <equals arg1="${with-charset}" arg2="utf-8"/>
+ </condition>
+ <property name="charset_is_utf8" value="0"/>
+
+ <condition property="charset_is_iso-8859-1" value="1">
+ <equals arg1="${with-charset}" arg2="iso-8859-1"/>
+ </condition>
+ <property name="charset_is_iso-8859-1" value="0"/>
+
+ <condition property="charset_is_usascii" value="1">
+ <equals arg1="${with-charset}" arg2="usascii"/>
+ </condition>
+ <property name="charset_is_usascii" value="0"/>
+
+ <condition property="charset_is_ebcdic" value="1">
+ <equals arg1="${with-charset}" arg2="ebcdic"/>
+ </condition>
+ <property name="charset_is_ebcdic" value="0"/>
+
+ <replaceregexp file="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ match="@CHARSET_UTF8@"
+ replace="${charset_is_utf8}"/>
+
+ <replaceregexp file="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ match="@CHARSET_ISO88591@"
+ replace="${charset_is_iso-8859-1}"/>
+ <replaceregexp file="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ match="@CHARSET_USASCII@"
+ replace="${charset_is_usascii}"/>
+ <replaceregexp file="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ match="@CHARSET_EBCDIC@"
+ replace="${charset_is_ebcdic}"/>
+
+ <replaceregexp file="${include.dir}/log4cxx/log4cxx.tmp"
+ match="@CHAR_API@"
+ replace="${enable-char}"/>
+
+ <replaceregexp file="${include.dir}/log4cxx/log4cxx.tmp"
+ match="@WCHAR_T_API@"
+ replace="${enable-wchar_t}"/>
+
+ <replaceregexp file="${include.dir}/log4cxx/log4cxx.tmp"
+ match="@UNICHAR_API@"
+ replace="${enable-unichar}"/>
+
+ <replaceregexp file="${include.dir}/log4cxx/log4cxx.tmp"
+ match="@CFSTRING_API@"
+ replace="${enable-cfstring}"/>
+
+
+ <replaceregexp file="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ match="@HAS_SYSLOG@"
+ replace="1"/>
+ <replaceregexp file="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ match="@HAS_STD_LOCALE@"
+ replace="1"/>
+ <replaceregexp file="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ match="@HAS_MBSRTOWCS@"
+ replace="1"/>
+ <replaceregexp file="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ match="@HAS_WCSTOMBS@"
+ replace="1"/>
+ <condition property="has-fwide" value="0">
+ <isset property="is-cygwin"/>
+ </condition>
+ <property name="has-fwide" value="1"/>
+ <replaceregexp file="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ match="@HAS_FWIDE@"
+ replace="${has-fwide}"/>
+
+ <condition property="has-libesmtp-value" value="1">
+ <isset property="has-libesmtp"/>
+ </condition>
+ <property name="has-libesmtp-value" value="0"/>
+ <replaceregexp file="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ match="LOG4CXX_HAVE_LIBESMTP 0"
+ replace="LOG4CXX_HAVE_LIBESMTP ${has-libesmtp-value}"/>
+ <replaceregexp file="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ match="@HAS_LIBESMTP@"
+ replace="${has-libesmtp-value}"/>
+
+ <replaceregexp file="${include.dir}/log4cxx/private/log4cxx_private.tmp"
+ match="@HAS_ODBC@"
+ replace="${has-ODBC}"/>
+
+ <antcall target="copy-if-changed">
+ <param name="tofile" value="${include.dir}/log4cxx/log4cxx.h"/>
+ <param name="file" value="${include.dir}/log4cxx/log4cxx.tmp"/>
+ </antcall>
+ <delete file="${include.dir}/log4cxx/log4cxx.tmp"/>
+ <antcall target="copy-if-changed">
+ <param name="tofile" value="${include.dir}/log4cxx/private/log4cxx_private.h"/>
+ <param name="file" value="${include.dir}/log4cxx/private/log4cxx_private.tmp"/>
+ </antcall>
+ <delete file="${include.dir}/log4cxx/private/log4cxx_private.tmp"/>
+
+</target>
+
+
+<target name="build-apr" depends="find-apr" unless="apr.lib.file">
+ <fail unless="apr.src.dir">Could not locate apr library or source.</fail>
+ <property name="apr.lib.type" value="static"/>
+ <property name="apr.lib.prefix" value=""/>
+ <property name="apr.lib.suffix" value=""/>
+ <property name="project.type" value="msvc6"/>
+ <ant antfile="src/ant/apr-build.xml" target="build" inheritAll="false">
+ <property name="basedir" value="${apr.src.dir}"/>
+ <property name="target.dir" value="${target.dir}"/>
+ <property name="debug" value="${debug}"/>
+ <property name="lib.prefix" value="${apr.lib.prefix}"/>
+ <property name="lib.suffix" value="${apr.lib.suffix}"/>
+ <property name="compiler" value="${compiler}"/>
+ <property name="runtime" value="${runtime}"/>
+ <property name="lib.type" value="${apr.lib.type}"/>
+ <property name="project.type" value="${project.type}"/>
+ <property name="projects.dir" value="${projects.dir}"/>
+ <property name="project.if.value" value="${project.if}"/>
+ <property name="use-pic" value="${use-pic}"/>
+ <property name="os.family" value="${os.family}"/>
+ </ant>
+ <condition property="apr.lib.dir" value="${target.dir}/${debug.release}/shared">
+ <equals arg1="${apr.lib.type}" arg2="shared"/>
+ </condition>
+ <property name="apr.lib.dir" location="${target.dir}/${debug.release}/static"/>
+ <property name="apr.project.file" location="${projects.dir}/apr"/>
+</target>
+
+
+<target name="build-apr-util" depends="build-apr, find-apr-util" unless="apr-util.lib.file">
+ <fail unless="apr-util.src.dir">Could not locate apr-util library or source.</fail>
+ <property name="apr-util.lib.type" value="${apr.lib.type}"/>
+ <property name="apr-util.lib.prefix" value=""/>
+ <property name="apr-util.lib.suffix" value=""/>
+ <property name="project.type" value="msvc6"/>
+ <!-- built this way, apr-util will include expat and doesn't need an external reference -->
+ <property name="apr-util-includes-dependencies" value="1"/>
+
+ <ant antfile="src/ant/apr-util-build.xml" target="build" inheritAll="false">
+ <property name="target.dir" value="${target.dir}"/>
+ <property name="basedir" value="${apr-util.src.dir}"/>
+ <property name="debug" value="${debug}"/>
+ <property name="lib.prefix" value="${apr-util.lib.prefix}"/>
+ <property name="lib.suffix" value="${apr-util.lib.suffix}"/>
+ <property name="compiler" value="${compiler}"/>
+ <property name="runtime" value="${runtime}"/>
+ <property name="apr.include.dir" value="${apr.include.dir}"/>
+ <property name="apr.lib.dir" value="${apr.lib.dir}"/>
+ <property name="apr.lib.type" value="${apr.lib.type}"/>
+ <property name="lib.type" value="${apr-util.lib.type}"/>
+ <property name="project.type" value="${project.type}"/>
+ <property name="projects.dir" value="${projects.dir}"/>
+ <property name="project.if.value" value="${project.if}"/>
+ <property name="use-pic" value="${use-pic}"/>
+ <property name="os.family" value="${os.family}"/>
+ </ant>
+
+ <condition property="apr-util.lib.dir" value="${target.dir}/${debug.release}/shared">
+ <equals arg1="${apr-util.lib.type}" arg2="shared"/>
+ </condition>
+ <property name="apr-util.lib.dir" location="${target.dir}/${debug.release}/static"/>
+ <property name="apr-util.project.file" location="${projects.dir}/apr-util"/>
+</target>
+
+<target name="build-libesmtp" depends="find-esmtp" if="has-libesmtp" unless="esmtp.lib.file">
+ <fail unless="esmtp.src.dir">Could not locate libesmtp library or source.</fail>
+ <property name="esmtp.lib.type" value="static"/>
+ <property name="esmtp.lib.prefix" value=""/>
+ <property name="esmtp.lib.suffix" value=""/>
+ <property name="project.type" value="msvc6"/>
+ <condition property="esmtp.compiler" value="gcc">
+ <equals arg1="${compiler}" arg2="g++"/>
+ </condition>
+ <property name="esmtp.compiler" value="${compiler}"/>
+
+ <ant antfile="src/ant/esmtp-build.xml" target="build" inheritAll="false">
+ <property name="target.dir" value="${target.dir}"/>
+ <property name="basedir" value="${esmtp.src.dir}"/>
+ <property name="debug" value="${debug}"/>
+ <property name="lib.prefix" value="${esmtp.lib.prefix}"/>
+ <property name="lib.suffix" value="${esmtp.lib.suffix}"/>
+ <property name="compiler" value="${esmtp.compiler}"/>
+ <property name="runtime" value="${runtime}"/>
+ <property name="lib.type" value="${esmtp.lib.type}"/>
+ <property name="project.type" value="${project.type}"/>
+ <property name="projects.dir" value="${projects.dir}"/>
+ <property name="project.if.value" value="${project.if}"/>
+ <property name="use-pic" value="${use-pic}"/>
+ <property name="os.family" value="${os.family}"/>
+ </ant>
+
+ <condition property="esmtp.lib.dir" value="${target.dir}/${debug.release}/shared">
+ <equals arg1="${esmtp.lib.type}" arg2="shared"/>
+ </condition>
+ <property name="esmtp.lib.dir" location="${target.dir}/${debug.release}/static"/>
+ <property name="esmtp.project.file" location="${projects.dir}/libesmtp"/>
+</target>
+
+
+<target name="make-header-check">
+ <echo file="${header}.cpp" append="false">
+#include "${header}"
+#include "${header}"
+</echo>
+</target>
+
+
+<target name="header-check" depends="build-apr-util, configure"
+ description="Checks headers against Effective C++ guidelines">
+ <fail unless="is-gcc">Requires GCC compiler</fail>
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
+ <delete dir="${target.dir}/header-check"/>
+ <mkdir dir="${target.dir}/header-check"/>
+ <copy todir="${target.dir}/header-check" overwrite="true">
+ <fileset dir="${include.dir}" includes="**/*.h">
+ <!-- obsolete header with #error directive to eliminate its use -->
+ <exclude name="**/tchar.h"/>
+ <!-- excluded due to conflict between log4cxx/rfa.h and log4cxx/rolling/rfa.h -->
+ <exclude name="log4cxx/rollingfileappender.h"/>
+ </fileset>
+ </copy>
+ <foreach target="make-header-check" param="header">
+ <path><fileset dir="${target.dir}/header-check" includes="**/*.h"/></path>
+ </foreach>
+ <property name="project.type" value="msvc6"/>
+ <cc objdir="${target.dir}/header-check"
+ name="gcc"
+ exceptions="true"
+ subsystem="gui"
+ optimize="none"
+ multithreaded="true"
+ relentless="true"
+ debug="${debug}"
+ projectsOnly="${projectsOnly}">
+ <compilerarg value="-Weffc++"/>
+ <compilerarg value="-Wall"/>
+ <compilerarg value="${pic-option}" if="pic-option"/>
+ <fileset dir="${target.dir}/header-check"
+ includes="**/*.cpp"
+ excludes="log4cxx/private/*.cpp **/aprinitializer.h.cpp"/>
+ <includepath path="${include.dir}"/>
+ <project outfile="${projects.dir}/header-check"
+ type="${project.type}" if="project.if"/>
+ </cc>
+</target>
+
+<target name="build-lib" depends="build-apr-util, build-libesmtp, configure" description="Build log4cxx library">
+ <mkdir dir="${log4cxx.lib.dir}/log4cxx_obj"/>
+
+ <condition property="apr-static" value="1">
+ <equals arg1="${apr.lib.type}" arg2="static"/>
+ </condition>
+
+ <condition property="apr-util-static" value="1">
+ <equals arg1="${apr-util.lib.type}" arg2="static"/>
+ </condition>
+
+ <condition property="apr-libs-match" value="1">
+ <equals arg1="${apr.lib.type}" arg2="${apr-util.lib.type}"/>
+ </condition>
+
+ <fail unless="apr-libs-match">apr is ${apr.lib.type} and apr-util is ${apr-util.lib.type}, must be same type.</fail>
+ <property name="lib.name" value="log4cxx"/>
+ <property name="lib.prefix" value=""/>
+ <property name="lib.suffix" value=""/>
+
+ <condition property="apr-util.dependencies" value="expat iconv">
+ <equals arg1="${apr-util.lib.type}" arg2="static"/>
+ </condition>
+
+
+ <property name="project.compiler" value="${compiler}"/>
+ <property name="project.type" value="msvc6"/>
+
+ <condition property="resource.compiler" value="windres">
+ <isset property="is-gcc"/>
+ </condition>
+ <condition property="resource.compiler" value="brc">
+ <isset property="is-bcc"/>
+ </condition>
+ <property name="resource.compiler" value="msrc"/>
+
+ <cc name="${project.compiler}"
+ exceptions="true"
+ outfile="${log4cxx.lib.dir}/${lib.prefix}${lib.name}${lib.suffix}"
+ outputfileproperty="log4cxx.lib.file"
+ subsystem="console"
+ multithreaded="true"
+ runtime="${runtime}"
+ outtype="${lib.type}"
+ objdir="${log4cxx.lib.dir}/log4cxx_obj"
+ debug="${debug}"
+ projectsOnly="${projectsOnly}">
+ <compiler name="${resource.compiler}" if="is-windows">
+ <includepath path="${resources.dir}"/>
+ <fileset dir="${resources.dir}" includes="*.rc"/>
+ </compiler>
+ <fileset dir="${src.dir}" includes="*.cpp"/>
+ <fileset dir="${include.dir}" includes="**/*.h"/>
+ <includepath path="${include.dir}"/>
+ <includepath path="${apr.include.dir}" if="apr.include.dir"/>
+ <includepath path="${apr-util.include.dir}" if="apr-util.include.dir"/>
+ <includepath path="${esmtp.include.dir}" if="esmtp.include.dir"/>
+ <defineset define="_USRDLL DLL_EXPORTS" if="is-windows"/>
+ <defineset define="LOG4CXX"/>
+ <defineset define="LOG4CXX_STATIC" if="is-static"/>
+ <defineset define="APR_DECLARE_STATIC" if="apr-static"/>
+ <defineset define="APU_DECLARE_STATIC" if="apr-util-static"/>
+ <defineset define="WIN32" if="is-windows"/>
+ <compilerarg value="${pic-option}" if="pic-option"/>
+ &libsets;
+ <project type="${project.type}" outfile="${projects.dir}/${lib.name}" if="project.if">
+ <comment>&license;</comment>
+ <dependency file="${projects.dir}/apr"/>
+ <dependency file="${projects.dir}/xml"/>
+ <dependency file="${projects.dir}/aprutil" depends="apr,xml"/>
+ <dependency name="${projects.dir}/libesmtp"/>
+ </project>
+ </cc>
+
+ <!-- copy liblog4cxx.so to log4cxx.dll for MinGW and Cygwin -->
+ <condition property="copy.log4cxx" value="${log4cxx.lib.dir}/${lib.prefix}${lib.name}${lib.suffix}.dll">
+ <and>
+ <os family="windows"/>
+ <isset property="is-gcc"/>
+ <equals arg1="${lib.type}" arg2="shared"/>
+ <isset property="log4cxx.lib.file"/>
+ </and>
+ </condition>
+</target>
+
+<target name="build" depends="build-lib" if="copy.log4cxx">
+ <copy file="${log4cxx.lib.file}" tofile="${copy.log4cxx}"
+ overwrite="true" preservelastmodified="true"/>
+</target>
+
+<target name="build-example">
+ <mkdir dir="${log4cxx.lib.dir}/${example.name}_obj"/>
+ <property name="project.compiler" value="${compiler}"/>
+ <property name="project.type" value="msvc6"/>
+ <property name="example.include.dir" value="${example.src.dir}"/>
+ <cc name="${project.compiler}"
+ exceptions="true"
+ outfile="${log4cxx.lib.dir}/${example.name}"
+ subsystem="console"
+ multithreaded="true"
+ runtime="${runtime}"
+ outtype="executable"
+ objdir="${log4cxx.lib.dir}/${example.name}_obj"
+ debug="${debug}"
+ projectsOnly="${projectsOnly}">
+ <fileset dir="${example.src.dir}" includes="${example.includes}"/>
+ <includepath path="${include.dir}"/>
+ <includepath path="${example.include.dir}"/>
+ <includepath path="${apr.include.dir}" if="apr.include.dir"/>
+
+ <defineset define="WIN32" if="is-windows"/>
+ <defineset define="LOG4CXX_STATIC" if="is-static"/>
+ <defineset define="APR_DECLARE_STATIC" if="apr-static"/>
+
+ <compilerarg value="${pic-option}" if="pic-option"/>
+
+ <libset libs="${lib.prefix}${lib.name}${lib.suffix}" dir="${log4cxx.lib.dir}"/>
+ &libsets;
+
+ <project outfile="${projects.dir}/${example.name}" type="${project.type}" if="project.if">
+ <comment>&license;</comment>
+ <dependency file="${projects.dir}/apr"/>
+ <dependency file="${projects.dir}/xml"/>
+ <dependency name="${projects.dir}/aprutil" depends="apr,xml"/>
+ <dependency name="${projects.dir}/libesmtp"/>
+ <dependency file="${projects.dir}/log4cxx" depends="apr,aprutil,xml"/>
+ </project>
+
+ </cc>
+</target>
+
+<target name="run-example">
+ <!-- remove any stray configuration files -->
+ <delete>
+ <fileset dir="${log4cxx.lib.dir}" includes="log4*.properties log4*.xml"/>
+ </delete>
+ <exec executable="${log4cxx.lib.dir}/${example.name}"
+ dir="${log4cxx.lib.dir}"
+ failonerror="true">
+ <env key="DYLD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.DYLD_LIBRARY_PATH}"/>
+ <env key="LD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.LD_LIBRARY_PATH}"/>
+ <env key="Path" value="${env.Path}"/>
+ </exec>
+</target>
+
+
+<target name="build-delayedloop" depends="build">
+ <antcall target="build-example">
+ <param name="example.src.dir" value="${examples.dir}"/>
+ <param name="example.name" value="delayedloop"/>
+ <param name="example.includes" value="delayedloop.cpp"/>
+ </antcall>
+</target>
+
+<target name="build-trivial" depends="build">
+ <antcall target="build-example">
+ <param name="example.src.dir" value="${examples.dir}"/>
+ <param name="example.name" value="trivial"/>
+ <param name="example.includes" value="trivial.cpp"/>
+ </antcall>
+</target>
+
+<target name="build-console" depends="build">
+ <antcall target="build-example">
+ <param name="example.src.dir" value="${examples.dir}"/>
+ <param name="example.name" value="console"/>
+ <param name="example.includes" value="console.cpp"/>
+ </antcall>
+</target>
+
+<target name="build-stream" depends="build">
+ <antcall target="build-example">
+ <param name="example.src.dir" value="${examples.dir}"/>
+ <param name="example.name" value="stream"/>
+ <param name="example.includes" value="stream.cpp"/>
+ </antcall>
+</target>
+
+<target name="build-examples"
+ depends="build-delayedloop, build-trivial, build-stream, build-console"
+ description="Builds example programs"/>
+
+
+
+<target name="build-unittest" depends="build"
+ description="Builds unit test app">
+ <mkdir dir="${log4cxx.lib.dir}/testsuite_obj"/>
+
+ <property name="project.compiler" value="${compiler}"/>
+ <property name="project.type" value="msvc6"/>
+ <cc name="${project.compiler}"
+ exceptions="true"
+ outfile="${log4cxx.lib.dir}/testsuite"
+ subsystem="console"
+ multithreaded="true"
+ runtime="${runtime}"
+ outputfileproperty="testsuite.exe"
+ outtype="executable"
+ objdir="${log4cxx.lib.dir}/testsuite_obj"
+ debug="${debug}"
+ projectsOnly="${projectsOnly}">
+ <fileset dir="${tests.cpp.dir}" includes="**/*.cpp **/*.c **/*.h"/>
+ <includepath path="${include.dir}"/>
+ <includepath path="${apr.include.dir}" if="apr.include.dir"/>
+ <includepath path="${apr-util.include.dir}" if="apr-util.include.dir"/>
+ <defineset define="LOG4CXX_STATIC" if="is-static"/>
+ <defineset define="APR_DECLARE_STATIC" if="apr-static"/>
+ <defineset define="APU_DECLARE_STATIC" if="apr-util-static"/>
+ <defineset define="WIN32" if="is-windows"/>
+ <compilerarg value="${pic-option}" if="pic-option"/>
+
+ <libset libs="${lib.prefix}${lib.name}${lib.suffix}" dir="${log4cxx.lib.dir}"/>
+ &libsets;
+
+ <project outfile="${projects.dir}/testsuite" type="${project.type}" if="project.if">
+ <comment>&license;</comment>
+ <dependency file="${projects.dir}/apr"/>
+ <dependency file="${projects.dir}/xml"/>
+ <dependency file="${projects.dir}/aprutil" depends="apr,xml"/>
+ <dependency name="${projects.dir}/libesmtp"/>
+ <dependency file="${projects.dir}/log4cxx" depends="apr,aprutil,libesmtp"/>
+ </project>
+ </cc>
+</target>
+
+
+
+
+<target name="build-standalone-unittest"
+ description="Builds a unit tests + log4cxx executable"
+ depends="build-apr-util, build-libesmtp, configure">
+ <mkdir dir="${executable.dir}/static/testsuite-standalone_obj"/>
+ <property name="project.compiler" value="${compiler}"/>
+ <property name="project.type" value="msvc6"/>
+ <condition property="resource.compiler" value="windres">
+ <isset property="is-gcc"/>
+ </condition>
+ <property name="resource.compiler" value="msrc"/>
+
+ <cc name="${project.compiler}"
+ exceptions="true"
+ outfile="${executable.dir}/static/testsuite-standalone"
+ subsystem="console"
+ multithreaded="true"
+ runtime="${runtime}"
+ outputfileproperty="testsuite-standalone.exe"
+ outtype="executable"
+ objdir="${executable.dir}/static/testsuite-standalone_obj"
+ debug="${debug}"
+ projectsOnly="${projectsOnly}">
+ <compiler name="${resource.compiler}" if="is-windows">
+ <includepath path="${resources.dir}"/>
+ <fileset dir="${resources.dir}" includes="*.rc"/>
+ </compiler>
+ <fileset dir="${src.dir}" includes="*.cpp" excludes="**/iconv_module.cpp"/>
+ <fileset dir="${include.dir}" includes="**/*.h"/>
+ <fileset dir="${tests.cpp.dir}" includes="**/*.cpp **/*.c **/*.h"/>
+ <includepath path="${include.dir}"/>
+ <includepath path="${apr.include.dir}" if="apr.include.dir"/>
+ <includepath path="${apr-util.include.dir}" if="apr-util.include.dir"/>
+ <includepath path="${esmtp.include.dir}" if="esmtp.include.dir"/>
+ <defineset define="LOG4CXX"/>
+ <defineset define="APR_DECLARE_STATIC" if="apr-static"/>
+ <defineset define="APU_DECLARE_STATIC" if="apr-util-static"/>
+ <defineset define="WIN32" if="is-windows"/>
+ <compilerarg value="${pic-option}" if="pic-option"/>
+
+ &libsets;
+
+ <includepath path="${include.dir}"/>
+ <includepath path="${apr.include.dir}"/>
+ <defineset define="LOG4CXX"/>
+ <libset libs="cw32mt" if="is-bcc"/>
+
+
+ <project outfile="${projects.dir}/testsuite-standalone"
+ type="${project.type}"
+ if="project.if">
+ <comment>&license;</comment>
+ <dependency file="${projects.dir}/apr"/>
+ <dependency file="${projects.dir}/xml"/>
+ <dependency file="${projects.dir}/aprutil" depends="apr,xml"/>
+ <dependency name="${projects.dir}/libesmtp"/>
+ </project>
+ </cc>
+</target>
+
+<target name="build-all" depends="build-examples, build-unittest"
+ description="Builds all artifacts"/>
+
+<target name="clean-output" depends="init">
+ <delete>
+ <fileset dir="${tests.dir}" includes="output/*"/>
+ </delete>
+</target>
+
+<target name="run-defaultinit-unittest" depends="build-unittest">
+ <antcall target="run-defaultinit-log4X">
+ <param name="config" value="log4j"/>
+ </antcall>
+ <antcall target="run-defaultinit-log4X">
+ <param name="config" value="log4cxx"/>
+ </antcall>
+</target>
+
+<target name="run-defaultinit-log4X">
+ <mkdir dir="${tests.output.dir}"/>
+
+
+ <!-- test of log4j.properties -->
+ <delete>
+ <fileset dir="${log4cxx.lib.dir}" includes="*.properties *.xml"/>
+ </delete>
+ <exec executable="${testsuite.exe}" dir="${log4cxx.lib.dir}"
+ failonerror="true">
+ <arg value="-v"/>
+ <arg value="testcase1"/>
+ <env key="DYLD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.DYLD_LIBRARY_PATH}"/>
+ <env key="LD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.LD_LIBRARY_PATH}"/>
+ </exec>
+
+ <copy tofile="${log4cxx.lib.dir}/${config}.xml"
+ file="${tests.resources.dir}/input/xml/defaultInit.xml" overwrite="true"/>
+ <exec executable="${testsuite.exe}" dir="${log4cxx.lib.dir}"
+ failonerror="true">
+ <arg value="-v"/>
+ <arg value="testcase2"/>
+ <env key="DYLD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.DYLD_LIBRARY_PATH}"/>
+ <env key="LD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.LD_LIBRARY_PATH}"/>
+ </exec>
+ <delete>
+ <fileset dir="${log4cxx.lib.dir}" includes="*.properties *.xml"/>
+ </delete>
+
+
+ <copy tofile="${log4cxx.lib.dir}/${config}.properties"
+ file="${tests.resources.dir}/input/defaultInit3.properties" overwrite="true"/>
+ <exec executable="${testsuite.exe}" dir="${log4cxx.lib.dir}"
+ failonerror="true">
+ <arg value="-v"/>
+ <arg value="testcase3"/>
+ <env key="DYLD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.DYLD_LIBRARY_PATH}"/>
+ <env key="LD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.LD_LIBRARY_PATH}"/>
+ </exec>
+ <delete>
+ <fileset dir="${log4cxx.lib.dir}" includes="*.properties *.xml"/>
+ </delete>
+
+
+ <copy file="${tests.resources.dir}/input/xml/defaultInit.xml" tofile="${log4cxx.lib.dir}/${config}.xml"/>
+ <copy file="${tests.resources.dir}/input/defaultInit3.properties" tofile="${log4cxx.lib.dir}/${config}.properties"/>
+ <exec executable="${testsuite.exe}" dir="${log4cxx.lib.dir}"
+ failonerror="true">
+ <arg value="-v"/>
+ <arg value="testcase4"/>
+ <env key="LD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.LD_LIBRARY_PATH}"/>
+ <env key="DYLD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.DYLD_LIBRARY_PATH}"/>
+ </exec>
+ <delete>
+ <fileset dir="${log4cxx.lib.dir}" includes="*.properties *.xml"/>
+ </delete>
+
+
+</target>
+
+<target name="run-unittest" depends="build-unittest, run-defaultinit-unittest, clean-output"
+ description="Runs unit test">
+ <property environment="env"/>
+ <mkdir dir="${tests.output.dir}"/>
+ <delete>
+ <fileset dir="${tests.output.dir}" includes="*"/>
+ </delete>
+ <exec executable="${testsuite.exe}" dir="${tests.resources.dir}"
+ failonerror="true">
+ <arg value="-v"/>
+ <env key="TOTO" value="wonderful"/>
+ <env key="key1" value="value1"/>
+ <env key="key2" value="value2"/>
+ <env key="LD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.LD_LIBRARY_PATH}"/>
+ <env key="DYLD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.DYLD_LIBRARY_PATH}"/>
+ <env key="Path"
+ value="${log4cxx.lib.dir};${env.Path}"/>
+ </exec>
+ <available property="dom3-status" value="" file="src/test/resources/output/dom&#xB3;"/>
+ <available property="dom4-status" value="" file="src/test/resources/output/dom&#x3195;"/>
+ <property name="dom3-status" value="NOT"/>
+ <property name="dom4-status" value="NOT"/>
+ <echo>output/dom&#xB3; was ${dom3-status} created in DOMTestCase::test3</echo>
+ <echo>output/dom&#x3195; was ${dom4-status} created in DOMTestCase::test4</echo>
+</target>
+
+<target name="run-standalone-unittest"
+ depends="build-standalone-unittest, clean-output"
+ description="Runs standalone unit test">
+ <property environment="env"/>
+ <mkdir dir="${tests.output.dir}"/>
+ <delete>
+ <fileset dir="${tests.output.dir}" includes="*"/>
+ </delete>
+ <exec executable="${log4cxx-standalone-test.exe}" dir="${tests.resources.dir}"
+ failonerror="true">
+ <arg value="-v"/>
+ <env key="TOTO" value="wonderful"/>
+ <env key="key1" value="value1"/>
+ <env key="key2" value="value2"/>
+ <env key="DYLD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.DYLD_LIBRARY_PATH}"/>
+ <env key="LD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.LD_LIBRARY_PATH}"/>
+ <env key="Path"
+ value="${log4cxx.lib.dir};${env.Path}"/>
+ </exec>
+ <available property="dom3-status" value="" file="src/test/resources/output/dom&#xB3;"/>
+ <available property="dom4-status" value="" file="src/test/resources/output/dom&#x3195;"/>
+ <property name="dom3-status" value="NOT"/>
+ <property name="dom4-status" value="NOT"/>
+ <echo>output/dom&#xB3; was ${dom3-status} created in DOMTestCase::test3</echo>
+ <echo>output/dom&#x3195; was ${dom4-status} created in DOMTestCase::test4</echo>
+</target>
+
+<target name="run-socketserver" depends="build-unittest, clean-output"
+ description="Runs SocketServer test">
+ <property environment="env"/>
+ <mkdir dir="${tests.output.dir}"/>
+ <delete>
+ <fileset dir="${tests.output.dir}" includes="*"/>
+ </delete>
+ <mkdir dir="target/test-classes"/>
+ <javac srcdir="src/test/java"
+ includes="org/apache/log4j/net/ShortSocketServer.java"
+ destdir="target/test-classes"
+ classpath="${log4j.jar}"/>
+ <parallel>
+ <java classname="org.apache.log4j.net.ShortSocketServer"
+ fork="yes" dir="src/test/resources" classpath="target/test-classes:${log4j.jar}">
+ <arg value="8"/>
+ <arg value="input/socketServer"/>
+ </java>
+ <sequential>
+ <sleep seconds="2"/>
+ <exec executable="${testsuite.exe}" dir="${tests.resources.dir}"
+ failonerror="true">
+ <arg value="-v"/>
+ <arg value="socketservertestcase"/>
+ <env key="LD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.LD_LIBRARY_PATH}"/>
+ <env key="DYLD_LIBRARY_PATH"
+ value="${log4cxx.lib.dir}:${apr.lib.dir}:${apr-util.lib.dir}:${env.DYLD_LIBRARY_PATH}"/>
+ <env key="Path"
+ value="${log4cxx.lib.dir};${env.Path}"/>
+ </exec>
+ </sequential>
+ </parallel>
+
+</target>
+
+<target name="build-projects">
+ <mkdir dir="${projects.dir}"/>
+ <property name="project.type" value="msvc6"/>
+ <antcall target="build-unittest">
+ <param name="project.if" value="true"/>
+ <param name="project.type" value="${project.type}"/>
+ <param name="project.compiler" value="${project.compiler}"/>
+ <param name="debug" value="${debug}"/>
+ <param name="projectsOnly" value="true"/>
+ <param name="os.family" value="${os.family}"/>
+ <param name="find" value="${find}"/>
+ </antcall>
+ <antcall target="build-standalone-unittest">
+ <param name="project.if" value="true"/>
+ <param name="project.type" value="${project.type}"/>
+ <param name="project.compiler" value="${project.compiler}"/>
+ <param name="debug" value="${debug}"/>
+ <param name="projectsOnly" value="true"/>
+ <param name="os.family" value="${os.family}"/>
+ <param name="find" value="${find}"/>
+ </antcall>
+ <antcall target="build-examples">
+ <param name="project.if" value="true"/>
+ <param name="project.type" value="${project.type}"/>
+ <param name="project.compiler" value="${project.compiler}"/>
+ <param name="debug" value="${debug}"/>
+ <param name="projectsOnly" value="true"/>
+ <param name="os.family" value="${os.family}"/>
+ <param name="find" value="${find}"/>
+ </antcall>
+</target>
+
+<target name="build-projects-vc6" depends="init"
+ description="Builds project files for Microsoft Visual C++ 6">
+ <antcall target="build-projects">
+ <param name="project.type" value="msvc6"/>
+ <param name="project.compiler" value="msvc"/>
+ <param name="os.family" value="windows"/>
+ <param name="debug" value="${debug}"/>
+ <param name="find" value="${find}"/>
+ </antcall>
+</target>
+
+<target name="build-projects-vc7" depends="init"
+ description="Builds project files for Microsoft Visual Studio .NET">
+ <antcall target="build-projects">
+ <param name="project.type" value="msvc7"/>
+ <param name="project.compiler" value="msvc"/>
+ <param name="os.family" value="windows"/>
+ <param name="debug" value="${debug}"/>
+ <param name="find" value="${find}"/>
+ </antcall>
+</target>
+
+<target name="build-projects-vc8" depends="init"
+ description="Builds project files for Microsoft Visual C++ 2005">
+ <antcall target="build-projects">
+ <param name="project.type" value="msvc8"/>
+ <param name="project.compiler" value="msvc"/>
+ <param name="os.family" value="windows"/>
+ <param name="debug" value="${debug}"/>
+ <param name="find" value="${find}"/>
+ </antcall>
+</target>
+
+
+<target name="build-projects-vc9" depends="init"
+ description="Builds project files for Microsoft Visual C++ 2008">
+ <antcall target="build-projects">
+ <param name="project.type" value="msvc9"/>
+ <param name="project.compiler" value="msvc"/>
+ <param name="os.family" value="windows"/>
+ <param name="debug" value="${debug}"/>
+ <param name="find" value="${find}"/>
+ </antcall>
+</target>
+
+ <target name="build-projects-xcode" depends="init"
+ description="Builds project files for Apple Xcode">
+ <antcall target="build-projects">
+ <param name="project.type" value="xcode"/>
+ <param name="project.compiler" value="gcc"/>
+ <param name="os.family" value="mac"/>
+ <param name="debug" value="${debug}"/>
+ <param name="find" value="${find}"/>
+ </antcall>
+</target>
+
+
+<target name="test-compile" depends="build-unittest, build-examples"/>
+
+
+<target name="check" depends="run-unittest, build-examples"
+ description="Runs all diagnostic tests">
+ <antcall target="run-example">
+ <param name="example.name" value="trivial"/>
+ </antcall>
+ <antcall target="run-example">
+ <param name="example.name" value="stream"/>
+ </antcall>
+</target>
+
+
+
+<target name="apidocs" depends="init" description="Build log4cxx manual">
+ <copy file="src/site/doxy/Doxyfile.in" tofile="${target.dir}/Doxyfile"
+ overwrite="true"/>
+ <replace file="${target.dir}/Doxyfile">
+ <replacefilter token="@VERSION@" value="${version}"/>
+ <replacefilter token="@base_dir@" value="${base.dir}"/>
+ <replacefilter token="@manual_dest@" value="${base.dir}/target/site/apidocs"/>
+ </replace>
+ <mkdir dir="target/site/apidocs"/>
+ <exec executable="${doxygen.exe}" dir="${target.dir}"/>
+
+ <!-- doxygen.css is GPL'd, looks better with it, but not intolerable without it -->
+ <echo file="${target.dir}/site/apidocs/doxygen.css">
+/*
+&license;
+*/
+/* Minimal replacement for GPL'd doxygen.css */
+</echo>
+ <echo file="${target.dir}/site/apidocs/tabs.css">
+/*
+&license;
+*/
+/* Minimal replacement for GPL'd tabs.css */
+DIV.tabs {
+ display : none ;
+}
+</echo>
+ <!-- fix for issue http://jira.codehaus.org/browse/MSKINS-2 -->
+ <replace file="${target.dir}/site/css/maven-theme.css"
+ token="font-size: normal;"
+ value="font-size: medium;"/>
+
+</target>
+
+
+<target name="site" depends="apidocs">
+ <!-- generate Visual Studio and XCode project files -->
+ <antcall target="build-projects-vc6">
+ <param name="find" value="false"/>
+ </antcall>
+ <antcall target="build-projects-xcode">
+ </antcall>
+
+ <replaceregexp flags="ig"
+ match="ADD LINK32 .*/NOLOGO"
+ replace="ADD LINK32 ADVAPI32.LIB WS2_32.LIB MSWSOCK.LIB SHELL32.LIB ODBC32.LIB /NOLOGO">
+ <fileset dir="${target.dir}" includes="**/*.dsp"/>
+ </replaceregexp>
+ <replaceregexp flags="g"
+ match=".\\apr.dsp"
+ replace="..\\\\..\\\\apr\\\\apr.dsp">
+ <fileset dir="${target.dir}" includes="**/*.dsw"/>
+ </replaceregexp>
+ <replaceregexp flags="g"
+ match=".\\aprutil.dsp"
+ replace="..\\\\..\\\\apr-util\\\\aprutil.dsp">
+ <fileset dir="${target.dir}" includes="**/*.dsw"/>
+ </replaceregexp>
+ <replaceregexp flags="g"
+ match=".\\xml.dsp"
+ replace="..\\\\..\\\\apr-util\\\\xml\\\\expat\\\\lib\\\\xml.dsp">
+ <fileset dir="${target.dir}" includes="**/*.dsw"/>
+ </replaceregexp>
+ <!-- drop library search path -->
+ <replaceregexp flags="g"
+ match="&lt;string&gt;[\./]*/usr/lib&lt;/string&gt;"
+ replace="">
+ <fileset dir="${target.dir}" includes="**/*.pbxproj"/>
+ </replaceregexp>
+ <replace dir="${target.dir}" includes="**/*.pbxproj"
+ token="/usr/include/apr-1.0"
+ value="/usr/include/apr-1"/>
+ <replace dir="${target.dir}" includes="**/*.pbxproj"
+ token="MacOSX10.4u.sdk"
+ value="MacOSX10.5.sdk"/>
+ <replace dir="${target.dir}/site" includes="**/*.html">
+ <replacetoken>&lt;html</replacetoken>
+ <replacevalue>&lt;!--
+&license;
+--&gt;&lt;html</replacevalue>
+ </replace>
+ <replace dir="${target.dir}/site/css" includes="maven*.css">
+ <replacetoken>body {</replacetoken>
+ <replacevalue>/*
+&license;
+*/
+body {</replacevalue>
+ </replace>
+ <replace dir="${target.dir}/site/css" includes="print.css">
+ <replacetoken>#banner</replacetoken>
+ <replacevalue>/*
+&license;
+*/
+#banner</replacevalue>
+ </replace>
+
+</target>
+
+<target name="gump" depends="check, header-check"/>
+
+<target name="fixcrlf" depends="init" description="repair end-of-line sequences">
+ <fixcrlf srcDir="${base.dir}" tab="remove" tablength="3"
+ eof="remove" fixlast="true" eol="unix" includes="*.xml **/*.cpp **/*.h" excludes="lib/**/*"/>
+</target>
+
+ <target name="prepare-changes" description="Prepares changes.xml from a JIRA issues list">
+ <xslt style="src/changes/changes.xslt"
+ in="issues.xml"
+ out="src/changes/changes.xml"/>
+ </target>
+
+ <target name="checkout-site" unless="svn-available">
+ <exec executable="svn">
+ <arg value="co"/>
+ <arg value="${svnsite.url}"/>
+ <arg value="target/site-deploy"/>
+ </exec>
+ </target>
+
+ <target name="update-site" if="svn-available">
+ <exec executable="svn" dir="target/site-deploy" failonerror="true">
+ <arg value="update"/>
+ </exec>
+ </target>
+
+ <target name="post-site" depends="checkout-site, update-site"/>
+
+
+ <target name="mime=html">
+ <exec executable="svn">
+ <arg value="propset"/>
+ <arg value="svn:mime-type"/>
+ <arg value="text/html"/>
+ <arg value="${src.html}"/>
+ </exec>
+ </target>
+
+ <target name="mime=css">
+ <exec executable="svn">
+ <arg value="propset"/>
+ <arg value="svn:mime-type"/>
+ <arg value="text/css"/>
+ <arg value="${src.css}"/>
+ </exec>
+ </target>
+
+
+ <target name="site-deploy">
+ <!-- Add any new files (and generate innocuous warnings for the existing content) -->
+ <delete file="target/site-deploy/svn-commit.tmp~"/>
+ <exec executable="bash" dir="target/site-deploy" failonerror="true">
+ <arg line='-c "svn add --force *"'/>
+ </exec>
+ <taskdef name="foreach" classname="net.sf.antcontrib.logic.ForEach" />
+ <foreach target="mime=html" param="src.html">
+ <path>
+ <fileset dir="target/site-deploy" includes="**/*.html"/>
+ </path>
+ </foreach>
+ <foreach target="mime=css" param="src.css">
+ <path>
+ <fileset dir="target/site-deploy" includes="**/*.css"/>
+ </path>
+ </foreach>
+ <!-- requires that SVN_EDITOR, VISUAL or EDITOR being set to edit commit description -->
+ <exec executable="svn" dir="target/site-deploy" failonerror="true">
+ <arg value="commit"/>
+ </exec>
+ </target>
+
+ <target name="autogen" depends="init" if="is-unix">
+ <exec executable="sh">
+ <arg value="autogen.sh"/>
+ </exec>
+ </target>
+
+
+</project>
diff --git a/configure-aprutil.bat b/configure-aprutil.bat
new file mode 100755
index 0000000..576c22e
--- /dev/null
+++ b/configure-aprutil.bat
@@ -0,0 +1,20 @@
+ECHO OFF
+REM Licensed to the Apache Software Foundation (ASF) under one or more
+REM contributor license agreements. See the NOTICE file distributed with
+REM this work for additional information regarding copyright ownership.
+REM The ASF licenses this file to You under the Apache License, Version 2.0
+REM (the "License"); you may not use this file except in compliance with
+REM the License. You may obtain a copy of the License at
+REM
+REM http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM Unless required by applicable law or agreed to in writing, software
+REM distributed under the License is distributed on an "AS IS" BASIS,
+REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+REM See the License for the specific language governing permissions and
+REM limitations under the License.
+REM
+REM
+sed -i -e "s/#define APU_HAVE_APR_ICONV\b.*/#define APU_HAVE_APR_ICONV 0/" ..\apr-util\include\apu.hw
+sed -i -e "s/#define APR_HAS_LDAP\b.*/#define APR_HAS_LDAP 0/" ..\apr-util\include\apr_ldap.hw
+
diff --git a/configure.bat b/configure.bat
new file mode 100644
index 0000000..1021514
--- /dev/null
+++ b/configure.bat
@@ -0,0 +1,19 @@
+ECHO OFF
+REM Licensed to the Apache Software Foundation (ASF) under one or more
+REM contributor license agreements. See the NOTICE file distributed with
+REM this work for additional information regarding copyright ownership.
+REM The ASF licenses this file to You under the Apache License, Version 2.0
+REM (the "License"); you may not use this file except in compliance with
+REM the License. You may obtain a copy of the License at
+REM
+REM http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM Unless required by applicable law or agreed to in writing, software
+REM distributed under the License is distributed on an "AS IS" BASIS,
+REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+REM See the License for the specific language governing permissions and
+REM limitations under the License.
+REM
+REM
+copy /Y src\main\include\log4cxx\log4cxx.hw src\main\include\log4cxx\log4cxx.h
+copy /Y src\main\include\log4cxx\private\log4cxx_private.hw src\main\include\log4cxx\private\log4cxx_private.h
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..5422e69
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,489 @@
+AC_INIT(src/main/cpp/logger.cpp)
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# autoconf 2.50 or higher to rebuild aclocal.m4, because the
+# AC_CREATE_PREFIX_CONFIG_H macro needs the AS_DIRNAME macro.
+AC_PREREQ(2.50)
+
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+
+#
+# +1 : ? : +1 == new interface that does not break old one
+# +1 : ? : 0 == new interface that breaks old one
+# ? : ? : 0 == no new interfaces, but breaks apps
+# ? :+1 : ? == just some internal changes, nothing breaks but might work
+# better
+# CURRENT : REVISION : AGE
+LT_VERSION=10:0:0
+
+AC_SUBST(LT_VERSION)
+
+AH_VERBATIM([HAVE_NO_EXPLICIT_EXPORTS],
+[/* no explicit exports */
+#define LOG4CXX_EXPORT])
+
+AM_INIT_AUTOMAKE(log4cxx, 0.10.0)
+
+# Checks for programs
+# ----------------------------------------------------------------------------
+
+AM_PROG_LIBTOOL
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+
+AC_PROG_CXX([g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC QCC])
+
+AC_PROG_CXXCPP
+AC_LANG(C++)
+
+# CXX fine tuning
+case "$host" in
+ *-dec-osf*)
+ CXXFLAGS="$CXXFLAGS -std strict_ansi_errors"
+ ;;
+ *)
+ ;;
+esac
+
+# Doxygen
+
+AC_ARG_ENABLE(doxygen,
+ AC_HELP_STRING(--enable-doxygen,
+ [enable documentation generation with doxygen (auto)]))
+
+AC_ARG_ENABLE(dot,
+ AC_HELP_STRING(--enable-dot,
+ [use 'dot' to generate graphs in doxygen (auto)]))
+
+AC_ARG_ENABLE(html-docs,
+ AC_HELP_STRING(--enable-html-docs,
+ [enable HTML generation with doxygen (yes)]),
+ [],
+ [enable_html_docs=yes])
+
+AC_ARG_ENABLE(latex-docs,
+ AC_HELP_STRING(--enable-latex-docs,
+ [enable LaTeX documentation generation with doxygen (no)]),
+ [],
+ [enable_latex_docs=no])
+
+if test "x$enable_doxygen" = xno; then
+ enable_doc=no
+else
+ AC_PATH_PROG(DOXYGEN, doxygen, , $PATH)
+ if test "x$DOXYGEN" = x; then
+ if test "x$enable_doxygen" = xyes; then
+ AC_MSG_ERROR([could not find doxygen])
+ fi
+ enable_doc=no
+ else
+ enable_doc=yes
+ AC_PATH_PROG(DOT, dot, , $PATH)
+ fi
+fi
+AM_CONDITIONAL(DOC, test x$enable_doc = xyes)
+AM_CONDITIONAL(LATEX_DOC, test x$enable_latex_docs = xyes)
+
+if test x$DOT = x; then
+ if test "x$enable_dot" = xyes; then
+ AC_MSG_ERROR([could not find dot])
+ fi
+ enable_dot=no
+else
+ enable_dot=yes
+fi
+
+manual_dest="manual"
+base_dir=`(cd $srcdir && pwd)`
+
+AC_SUBST(enable_dot)
+AC_SUBST(enable_html_docs)
+AC_SUBST(enable_latex_docs)
+AC_SUBST(manual_dest)
+AC_SUBST(base_dir)
+
+
+
+
+# Checks header files
+# ----------------------------------------------------------------------------
+APR_FIND_APR( , , 1, 1)
+if test "$apr_found" = "no"; then
+ AC_MSG_ERROR(APR could not be located. Please use the --with-apr option.)
+fi
+
+CPPFLAGS="$CPPFLAGS `$apr_config --cppflags` `$apr_config --includes`"
+APR_LIBS="`$apr_config --link-ld --libs`"
+AC_SUBST(APR_LIBS)
+LDFLAGS="$LDFLAGS $APR_LIBS"
+
+APR_FIND_APU( , , 1, 1)
+if test "$apu_found" = "no"; then
+ AC_MSG_ERROR(APR-util could not be located. Please use the --with-apr-util option.)
+fi
+
+CPPFLAGS="$CPPFLAGS `$apu_config --includes`"
+APU_LIBS="`$apu_config --link-ld --libs`"
+AC_SUBST(APU_LIBS)
+LDFLAGS="$LDFLAGS $APU_LIBS"
+
+# Checks local idioms
+# ----------------------------------------------------------------------------
+
+# for local syslog() function for SyslogAppender
+AC_CHECK_FUNCS(mbsrtowcs, [have_mbsrtowcs=yes], [have_mbsrtowcs=no])
+if test "$have_mbsrtowcs" = "yes"
+then
+ AC_SUBST(HAS_MBSRTOWCS, 1)
+else
+ AC_SUBST(HAS_MBSRTOWCS, 0)
+fi
+
+AC_CHECK_FUNCS(wcstombs, [have_wcstombs=yes], [have_wcstombs=no])
+if test "$have_wcstombs" = "yes"
+then
+ AC_SUBST(HAS_WCSTOMBS, 1)
+else
+ AC_SUBST(HAS_WCSTOMBS, 0)
+fi
+
+# for local syslog() function for SyslogAppender
+AC_CHECK_FUNCS(syslog, [have_syslog=yes], [have_syslog=no])
+if test "$have_syslog" = "yes"
+then
+ AC_SUBST(HAS_SYSLOG, 1)
+else
+ AC_SUBST(HAS_SYSLOG, 0)
+fi
+
+AC_CHECK_HEADER([locale],have_locale=yes,have_locale=no)
+if test "$have_locale" = "yes"
+then
+ AC_SUBST(HAS_STD_LOCALE, 1)
+else
+ AC_SUBST(HAS_STD_LOCALE, 0)
+fi
+
+AC_MSG_CHECKING([for wchar_t])
+AC_COMPILE_IFELSE(AC_LANG_SOURCE([[
+ #include <string>
+ std::wstring w;]]), [have_wchar_t=yes], [have_wchar_t=no])
+AC_MSG_RESULT($have_wchar_t)
+if test "$have_wchar_t" = "yes"
+then
+ AC_SUBST(HAS_WCHAR_T, 1)
+else
+ AC_SUBST(HAS_WCHAR_T, 0)
+fi
+
+AC_CHECK_FUNCS(fwide, [have_fwide=yes], [have_fwide=no])
+if test "$have_fwide" = "yes"
+then
+ AC_SUBST(HAS_FWIDE, 1)
+else
+ AC_SUBST(HAS_FWIDE, 0)
+fi
+
+
+# Checks for libraries
+# ----------------------------------------------------------------------------
+
+AC_PROG_RANLIB
+
+
+#for ODBCAppender
+AC_MSG_CHECKING(for ODBC support)
+AC_ARG_WITH(ODBC,
+ AC_HELP_STRING(--with-ODBC, [ODBC support. Accepted arguments :
+ unixODBC, iODBC, Microsoft, no (default=no)]),
+ [ac_with_odbc=$withval],
+ [ac_with_odbc=no])
+case "$ac_with_odbc" in
+ Microsoft)
+ AC_SUBST(HAS_ODBC, 1, ODBC support)
+ AC_MSG_RESULT(Microsoft)
+ LIBS_ODBC="-lodbc32"
+ ;;
+ unixODBC)
+ AC_MSG_RESULT(unixODBC)
+ AC_CHECK_HEADER(sqlext.h,, AC_MSG_ERROR(unixODBC not found !))
+ AC_SUBST(HAS_ODBC, 1, ODBC support)
+ LIBS_ODBC="-lodbc"
+ ;;
+ iODBC)
+ AC_MSG_RESULT(iODBC)
+ AC_CHECK_PROG(IODBC_CONFIG, iodbc-config, yes, no)
+ if test "x$IODBC_CONFIG" = "xyes"
+ then
+ AC_SUBST(HAS_ODBC, 1, ODBC support)
+ LIBS_ODBC="`iodbc-config --libs`"
+ CPPFLAGS_ODBC="`iodbc-config --cflags`"
+ else
+ AC_MSG_ERROR(iODBC not found !)
+ fi
+ ;;
+ no)
+ AC_SUBST(HAS_ODBC, 0, No ODBC support)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ AC_MSG_RESULT(???)
+ AC_MSG_ERROR(Unknown option : $ac_with_odbc)
+ ;;
+esac
+AC_SUBST(LIBS_ODBC)
+AC_SUBST(CPPFLAGS_ODBC)
+
+
+#for SMTPAppender
+AC_MSG_CHECKING(for SMTP support)
+AC_ARG_WITH(SMTP,
+ AC_HELP_STRING(--with-SMTP, [SMTP support. Accepted arguments :
+ libesmtp, no (default=no)]),
+ [ac_with_smtp=$withval],
+ [ac_with_smtp=no])
+case "$ac_with_smtp" in
+ libesmtp)
+ AC_MSG_RESULT(libesmtp)
+ AC_CHECK_LIB([esmtp], [smtp_create_session],,
+ AC_MSG_ERROR(libesmtp library not found !),
+ -lesmtp)
+ AC_SUBST(HAS_LIBESMTP, 1, SMTP support through libesmtp library.)
+ LIBS="-lesmtp $LIBS"
+ ;;
+ no)
+ AC_MSG_RESULT(no)
+ AC_SUBST(HAS_LIBESMTP, 0, SMTP support through libesmtp library.)
+ ;;
+ *)
+ AC_MSG_RESULT(???)
+ AC_MSG_ERROR(Unknown option : $ac_with_smtp)
+ ;;
+esac
+
+#for char api
+AC_ARG_ENABLE(char,
+ AC_HELP_STRING(--enable-char,
+ [enable char API (yes)]))
+if test "x$enable_char" = xno; then
+ have_char_api=no
+else
+ have_char_api=yes
+fi
+
+if test "$have_char_api" = "yes"
+then
+ AC_SUBST(CHAR_API, 1)
+else
+ AC_SUBST(CHAR_API, 0)
+fi
+
+#for wchar_t api
+AC_ARG_ENABLE(wchar_t,
+ AC_HELP_STRING(--enable-wchar_t,
+ [enable wchar_t API (yes if wchar_t available)]))
+if test "x$enable_wchar_t" = xno; then
+ have_wchar_t_api=no
+else
+ if test "$have_wchar_t" = "yes"
+ then
+ have_wchar_t_api=yes
+ else
+ have_wchar_t_api=no
+ fi
+fi
+
+if test "$have_wchar_t_api" = "yes"
+then
+ AC_SUBST(WCHAR_T_API, 1)
+else
+ AC_SUBST(WCHAR_T_API, 0)
+fi
+
+#for unichar api
+AC_ARG_ENABLE(unichar,
+ AC_HELP_STRING(--enable-unichar,
+ [enable unichar API (no)]))
+if test "x$enable_unichar" = "yes"
+then
+ AC_SUBST(UNICHAR_API, 1)
+else
+ AC_SUBST(UNICHAR_API, 0)
+fi
+
+#for cfstring api
+AC_ARG_ENABLE(cfstring,
+ AC_HELP_STRING(--enable-cfstring,
+ [enable cfstring API (no)]))
+if test "x$enable_cfstring" = xyes; then
+ AC_MSG_CHECKING([for cfstring])
+ CPPFLAGS="$CPPFLAGS -framework CoreFoundation"
+ AC_COMPILE_IFELSE(AC_LANG_SOURCE([[
+ #include <CoreFoundation/CFString.h>
+ CFStringRef x = CFSTR("Hello");]]), [have_cfstring_api=yes], [have_cfstring_api=no])
+ AC_MSG_RESULT($have_cfstring_api)
+else
+ have_cfstring_api=no
+fi
+
+if test "$have_cfstring_api" = "yes"
+then
+ AC_SUBST(CFSTRING_API, 1)
+else
+ AC_SUBST(CFSTRING_API, 0)
+fi
+
+#determine charset type
+AC_MSG_CHECKING([charset type])
+AC_ARG_WITH(charset,
+ AC_HELP_STRING(--with-charset=TYPE, [locale charset.
+ Accepted TYPE variants: auto, utf-8, iso-8859-1, usascii, ebcdic (default=auto)]),
+ [ac_with_charset=$withval],
+ [ac_with_charset=auto])
+
+case "$ac_with_charset" in
+ utf-8)
+ AC_MSG_RESULT(utf-8)
+ AC_SUBST(CHARSET_UTF8, 1)
+ AC_SUBST(CHARSET_ISO88591, 0)
+ AC_SUBST(CHARSET_USASCII, 0)
+ AC_SUBST(CHARSET_EBCDIC, 0)
+ ;;
+
+ iso-8859-1)
+ AC_MSG_RESULT(iso-8859-1)
+ AC_SUBST(CHARSET_UTF8, 0)
+ AC_SUBST(CHARSET_ISO88591, 1)
+ AC_SUBST(CHARSET_USASCII, 0)
+ AC_SUBST(CHARSET_EBCDIC, 0)
+ ;;
+
+ usascii)
+ AC_MSG_RESULT(usascii)
+ AC_SUBST(CHARSET_UTF8, 0)
+ AC_SUBST(CHARSET_ISO88591, 0)
+ AC_SUBST(CHARSET_USASCII, 1)
+ AC_SUBST(CHARSET_EBCDIC, 0)
+ ;;
+
+ ebcdic)
+ AC_MSG_RESULT(usascii)
+ AC_SUBST(CHARSET_UTF8, 0)
+ AC_SUBST(CHARSET_ISO88591, 0)
+ AC_SUBST(CHARSET_USASCII, 0)
+ AC_SUBST(CHARSET_EBCDIC, 1)
+ ;;
+
+ auto)
+ AC_MSG_RESULT(auto)
+ AC_SUBST(CHARSET_UTF8, 0)
+ AC_SUBST(CHARSET_ISO88591, 0)
+ AC_SUBST(CHARSET_USASCII, 0)
+ AC_SUBST(CHARSET_EBCDIC, 0)
+ ;;
+
+ *)
+ AC_MSG_RESULT(???)
+ AC_MSG_ERROR(Invalid charset type: $ac_with_charset)
+ ;;
+esac
+
+
+
+#determine logchar type
+AC_MSG_CHECKING([logchar type])
+AC_ARG_WITH(logchar,
+ AC_HELP_STRING(--with-logchar=TYPE, [type for logchar.
+ Accepted TYPE variants: utf-8, wchar_t, unichar (default=utf-8)]),
+ [ac_with_logchar=$withval],
+ [ac_with_logchar=utf-8])
+
+case "$ac_with_logchar" in
+ utf-8)
+ AC_MSG_RESULT(utf-8)
+ AC_SUBST(LOGCHAR_IS_UTF8, 1)
+ AC_SUBST(LOGCHAR_IS_WCHAR, 0)
+ AC_SUBST(LOGCHAR_IS_UNICHAR, 0)
+ ;;
+
+ wchar_t)
+ AC_MSG_RESULT(wchar_t)
+ AC_SUBST(LOGCHAR_IS_UTF8, 0)
+ AC_SUBST(LOGCHAR_IS_WCHAR, 1)
+ AC_SUBST(LOGCHAR_IS_UNICHAR, 0)
+ ;;
+
+ unichar)
+ AC_MSG_RESULT(unichar)
+ AC_SUBST(LOGCHAR_IS_UTF8, 0)
+ AC_SUBST(LOGCHAR_IS_WCHAR, 0)
+ AC_SUBST(LOGCHAR_IS_UNICHAR, 1)
+ ;;
+
+ *)
+ AC_MSG_RESULT(???)
+ AC_MSG_ERROR(Invalid logchar type: $ac_with_logchar)
+ ;;
+esac
+
+
+
+# Create files
+# ----------------------------------------------------------------------------
+
+AC_CONFIG_FILES([
+Makefile
+liblog4cxx.pc
+src/Makefile
+src/main/Makefile
+src/main/cpp/Makefile
+src/main/include/Makefile
+src/main/include/log4cxx/log4cxx.h
+src/main/include/log4cxx/private/log4cxx_private.h
+src/main/include/log4cxx/private/Makefile
+src/main/include/log4cxx/Makefile
+src/main/include/log4cxx/helpers/Makefile
+src/main/include/log4cxx/net/Makefile
+src/main/include/log4cxx/nt/Makefile
+src/main/include/log4cxx/spi/Makefile
+src/main/include/log4cxx/spi/location/Makefile
+src/main/include/log4cxx/varia/Makefile
+src/main/include/log4cxx/xml/Makefile
+src/main/include/log4cxx/config/Makefile
+src/main/include/log4cxx/db/Makefile
+src/main/include/log4cxx/rolling/Makefile
+src/main/include/log4cxx/pattern/Makefile
+src/main/include/log4cxx/filter/Makefile
+src/site/Makefile
+src/site/doxy/Makefile
+src/site/doxy/Doxyfile
+src/test/Makefile
+src/test/resources/Makefile
+src/test/resources/input/Makefile
+src/test/resources/input/ndc/Makefile
+src/test/resources/input/rolling/Makefile
+src/test/resources/input/xml/Makefile
+src/test/cpp/Makefile
+src/test/resources/witness/Makefile
+src/test/resources/witness/encoding/Makefile
+src/test/resources/witness/ndc/Makefile
+src/test/resources/witness/rolling/Makefile
+src/examples/Makefile
+src/examples/cpp/Makefile
+])
+AC_OUTPUT
diff --git a/doap_log4cxx.rdf b/doap_log4cxx.rdf
new file mode 100644
index 0000000..7dc9a3b
--- /dev/null
+++ b/doap_log4cxx.rdf
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl"?>
+<rdf:RDF xml:lang="en"
+ xmlns="http://usefulinc.com/ns/doap#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:asfext="http://projects.apache.org/ns/asfext#"
+ xmlns:foaf="http://xmlns.com/foaf/0.1/">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+ <Project rdf:about="http://logging.apache.org/log4cxx">
+ <created>2007-02-09</created>
+ <license rdf:resource="http://usefulinc.com/doap/licenses/asl20" />
+ <name>Apache log4cxx</name>
+ <homepage rdf:resource="http://logging.apache.org/log4cxx" />
+ <asfext:pmc rdf:resource="http://logging.apache.org" />
+ <shortdesc>Apache log4cxx provides logging services for C++.</shortdesc>
+ <bug-database rdf:resource="http://issues.apache.org/jira/browse/LOGCXX" />
+ <mailing-list rdf:resource="http://logging.apache.org/log4cxx/mail-lists.html" />
+ <download-page rdf:resource="http://logging.apache.org/log4cxx/download.html" />
+ <programming-language>C</programming-language>
+ <category rdf:resource="http://projects.apache.org/category/library" />
+ <repository>
+ <SVNRepository>
+ <location rdf:resource="http://svn.apache.org/repos/asf/logging/log4cxx/trunk/"/>
+ <browse rdf:resource="http://svn.apache.org/viewvc/logging/log4cxx/trunk/"/>
+ </SVNRepository>
+ </repository>
+ </Project>
+</rdf:RDF>
diff --git a/find_apr.m4 b/find_apr.m4
new file mode 100644
index 0000000..88f64a7
--- /dev/null
+++ b/find_apr.m4
@@ -0,0 +1,202 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements. See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License. You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl
+dnl find_apr.m4 : locate the APR include files and libraries
+dnl
+dnl This macro file can be used by applications to find and use the APR
+dnl library. It provides a standardized mechanism for using APR. It supports
+dnl embedding APR into the application source, or locating an installed
+dnl copy of APR.
+dnl
+dnl APR_FIND_APR(srcdir, builddir, implicit-install-check, acceptable-majors,
+dnl detailed-check)
+dnl
+dnl where srcdir is the location of the bundled APR source directory, or
+dnl empty if source is not bundled.
+dnl
+dnl where builddir is the location where the bundled APR will will be built,
+dnl or empty if the build will occur in the srcdir.
+dnl
+dnl where implicit-install-check set to 1 indicates if there is no
+dnl --with-apr option specified, we will look for installed copies.
+dnl
+dnl where acceptable-majors is a space separated list of acceptable major
+dnl version numbers. Often only a single major version will be acceptable.
+dnl If multiple versions are specified, and --with-apr=PREFIX or the
+dnl implicit installed search are used, then the first (leftmost) version
+dnl in the list that is found will be used. Currently defaults to [0 1].
+dnl
+dnl where detailed-check is an M4 macro which sets the apr_acceptable to
+dnl either "yes" or "no". The macro will be invoked for each installed
+dnl copy of APR found, with the apr_config variable set appropriately.
+dnl Only installed copies of APR which are considered acceptable by
+dnl this macro will be considered found. If no installed copies are
+dnl considered acceptable by this macro, apr_found will be set to either
+dnl either "no" or "reconfig".
+dnl
+dnl Sets the following variables on exit:
+dnl
+dnl apr_found : "yes", "no", "reconfig"
+dnl
+dnl apr_config : If the apr-config tool exists, this refers to it. If
+dnl apr_found is "reconfig", then the bundled directory
+dnl should be reconfigured *before* using apr_config.
+dnl
+dnl Note: this macro file assumes that apr-config has been installed; it
+dnl is normally considered a required part of an APR installation.
+dnl
+dnl If a bundled source directory is available and needs to be (re)configured,
+dnl then apr_found is set to "reconfig". The caller should reconfigure the
+dnl (passed-in) source directory, placing the result in the build directory,
+dnl as appropriate.
+dnl
+dnl If apr_found is "yes" or "reconfig", then the caller should use the
+dnl value of apr_config to fetch any necessary build/link information.
+dnl
+
+AC_DEFUN([APR_FIND_APR], [
+ apr_found="no"
+
+ if test "$target_os" = "os2-emx"; then
+ # Scripts don't pass test -x on OS/2
+ TEST_X="test -f"
+ else
+ TEST_X="test -x"
+ fi
+
+ ifelse([$4], [], [
+ ifdef(AC_WARNING,AC_WARNING([$0: missing argument 4 (acceptable-majors): Defaulting to APR 0.x then APR 1.x]))
+ acceptable_majors="0 1"],
+ [acceptable_majors="$4"])
+
+ apr_temp_acceptable_apr_config=""
+ for apr_temp_major in $acceptable_majors
+ do
+ case $apr_temp_major in
+ 0)
+ apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-config"
+ ;;
+ *)
+ apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-$apr_temp_major-config"
+ ;;
+ esac
+ done
+
+ AC_MSG_CHECKING(for APR)
+ AC_ARG_WITH(apr,
+ [ --with-apr=PATH prefix for installed APR or the full path to
+ apr-config],
+ [
+ if test "$withval" = "no" || test "$withval" = "yes"; then
+ AC_MSG_ERROR([--with-apr requires a directory or file to be provided])
+ fi
+
+ for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config
+ do
+ for lookdir in "$withval/bin" "$withval"
+ do
+ if $TEST_X "$lookdir/$apr_temp_apr_config_file"; then
+ apr_config="$lookdir/$apr_temp_apr_config_file"
+ ifelse([$5], [], [], [
+ apr_acceptable="yes"
+ $5
+ if test "$apr_acceptable" != "yes"; then
+ AC_MSG_WARN([Found APR in $apr_config, but we think it is considered unacceptable])
+ continue
+ fi])
+ apr_found="yes"
+ break 2
+ fi
+ done
+ done
+
+ if test "$apr_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then
+ apr_config="$withval"
+ ifelse([$5], [], [apr_found="yes"], [
+ apr_acceptable="yes"
+ $5
+ if test "$apr_acceptable" = "yes"; then
+ apr_found="yes"
+ fi])
+ fi
+
+ dnl if --with-apr is used, it is a fatal error for its argument
+ dnl to be invalid
+ if test "$apr_found" != "yes"; then
+ AC_MSG_ERROR([the --with-apr parameter is incorrect. It must specify an install prefix, a build directory, or an apr-config file.])
+ fi
+ ],[
+ dnl If we allow installed copies, check those before using bundled copy.
+ if test -n "$3" && test "$3" = "1"; then
+ for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config
+ do
+ if $apr_temp_apr_config_file --help > /dev/null 2>&1 ; then
+ apr_config="$apr_temp_apr_config_file"
+ ifelse([$5], [], [], [
+ apr_acceptable="yes"
+ $5
+ if test "$apr_acceptable" != "yes"; then
+ AC_MSG_WARN([skipped APR at $apr_config, version not acceptable])
+ continue
+ fi])
+ apr_found="yes"
+ break
+ else
+ dnl look in some standard places
+ for lookdir in /usr /usr/local /usr/local/apr /opt/apr; do
+ if $TEST_X "$lookdir/bin/$apr_temp_apr_config_file"; then
+ apr_config="$lookdir/bin/$apr_temp_apr_config_file"
+ ifelse([$5], [], [], [
+ apr_acceptable="yes"
+ $5
+ if test "$apr_acceptable" != "yes"; then
+ AC_MSG_WARN([skipped APR at $apr_config, version not acceptable])
+ continue
+ fi])
+ apr_found="yes"
+ break 2
+ fi
+ done
+ fi
+ done
+ fi
+ dnl if we have not found anything yet and have bundled source, use that
+ if test "$apr_found" = "no" && test -d "$1"; then
+ apr_temp_abs_srcdir="`cd $1 && pwd`"
+ apr_found="reconfig"
+ apr_bundled_major="`sed -n '/#define.*APR_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \"$1/include/apr_version.h\"`"
+ case $apr_bundled_major in
+ "")
+ AC_MSG_ERROR([failed to find major version of bundled APR])
+ ;;
+ 0)
+ apr_temp_apr_config_file="apr-config"
+ ;;
+ *)
+ apr_temp_apr_config_file="apr-$apr_bundled_major-config"
+ ;;
+ esac
+ if test -n "$2"; then
+ apr_config="$2/$apr_temp_apr_config_file"
+ else
+ apr_config="$1/$apr_temp_apr_config_file"
+ fi
+ fi
+ ])
+
+ AC_MSG_RESULT($apr_found)
+])
diff --git a/find_apu.m4 b/find_apu.m4
new file mode 100644
index 0000000..6654162
--- /dev/null
+++ b/find_apu.m4
@@ -0,0 +1,211 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Copyright 2002-2005 The Apache Software Foundation or its licensors, as
+dnl applicable.
+dnl
+dnl Licensed under the Apache License, Version 2.0 (the "License");
+dnl you may not use this file except in compliance with the License.
+dnl You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl
+dnl find_apu.m4 : locate the APR-util (APU) include files and libraries
+dnl
+dnl This macro file can be used by applications to find and use the APU
+dnl library. It provides a standardized mechanism for using APU. It supports
+dnl embedding APU into the application source, or locating an installed
+dnl copy of APU.
+dnl
+dnl APR_FIND_APU(srcdir, builddir, implicit-install-check, acceptable-majors,
+dnl detailed-check)
+dnl
+dnl where srcdir is the location of the bundled APU source directory, or
+dnl empty if source is not bundled.
+dnl
+dnl where builddir is the location where the bundled APU will be built,
+dnl or empty if the build will occur in the srcdir.
+dnl
+dnl where implicit-install-check set to 1 indicates if there is no
+dnl --with-apr-util option specified, we will look for installed copies.
+dnl
+dnl where acceptable-majors is a space separated list of acceptable major
+dnl version numbers. Often only a single major version will be acceptable.
+dnl If multiple versions are specified, and --with-apr-util=PREFIX or the
+dnl implicit installed search are used, then the first (leftmost) version
+dnl in the list that is found will be used. Currently defaults to [0 1].
+dnl
+dnl where detailed-check is an M4 macro which sets the apu_acceptable to
+dnl either "yes" or "no". The macro will be invoked for each installed
+dnl copy of APU found, with the apu_config variable set appropriately.
+dnl Only installed copies of APU which are considered acceptable by
+dnl this macro will be considered found. If no installed copies are
+dnl considered acceptable by this macro, apu_found will be set to either
+dnl either "no" or "reconfig".
+dnl
+dnl Sets the following variables on exit:
+dnl
+dnl apu_found : "yes", "no", "reconfig"
+dnl
+dnl apu_config : If the apu-config tool exists, this refers to it. If
+dnl apu_found is "reconfig", then the bundled directory
+dnl should be reconfigured *before* using apu_config.
+dnl
+dnl Note: this macro file assumes that apr-config has been installed; it
+dnl is normally considered a required part of an APR installation.
+dnl
+dnl Note: At this time, we cannot find *both* a source dir and a build dir.
+dnl If both are available, the build directory should be passed to
+dnl the --with-apr-util switch.
+dnl
+dnl Note: the installation layout is presumed to follow the standard
+dnl PREFIX/lib and PREFIX/include pattern. If the APU config file
+dnl is available (and can be found), then non-standard layouts are
+dnl possible, since it will be described in the config file.
+dnl
+dnl If a bundled source directory is available and needs to be (re)configured,
+dnl then apu_found is set to "reconfig". The caller should reconfigure the
+dnl (passed-in) source directory, placing the result in the build directory,
+dnl as appropriate.
+dnl
+dnl If apu_found is "yes" or "reconfig", then the caller should use the
+dnl value of apu_config to fetch any necessary build/link information.
+dnl
+
+AC_DEFUN([APR_FIND_APU], [
+ apu_found="no"
+
+ if test "$target_os" = "os2-emx"; then
+ # Scripts don't pass test -x on OS/2
+ TEST_X="test -f"
+ else
+ TEST_X="test -x"
+ fi
+
+ ifelse([$4], [],
+ [
+ ifdef(AC_WARNING,([$0: missing argument 4 (acceptable-majors): Defaulting to APU 0.x then APU 1.x]))
+ acceptable_majors="0 1"
+ ], [acceptable_majors="$4"])
+
+ apu_temp_acceptable_apu_config=""
+ for apu_temp_major in $acceptable_majors
+ do
+ case $apu_temp_major in
+ 0)
+ apu_temp_acceptable_apu_config="$apu_temp_acceptable_apu_config apu-config"
+ ;;
+ *)
+ apu_temp_acceptable_apu_config="$apu_temp_acceptable_apu_config apu-$apu_temp_major-config"
+ ;;
+ esac
+ done
+
+ AC_MSG_CHECKING(for APR-util)
+ AC_ARG_WITH(apr-util,
+ [ --with-apr-util=PATH prefix for installed APU or the full path to
+ apu-config],
+ [
+ if test "$withval" = "no" || test "$withval" = "yes"; then
+ AC_MSG_ERROR([--with-apr-util requires a directory or file to be provided])
+ fi
+
+ for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config
+ do
+ for lookdir in "$withval/bin" "$withval"
+ do
+ if $TEST_X "$lookdir/$apu_temp_apu_config_file"; then
+ apu_config="$lookdir/$apu_temp_apu_config_file"
+ ifelse([$5], [], [], [
+ apu_acceptable="yes"
+ $5
+ if test "$apu_acceptable" != "yes"; then
+ AC_MSG_WARN([Found APU in $apu_config, but it is considered unacceptable])
+ continue
+ fi])
+ apu_found="yes"
+ break 2
+ fi
+ done
+ done
+
+ if test "$apu_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then
+ apu_config="$withval"
+ ifelse([$5], [], [apu_found="yes"], [
+ apu_acceptable="yes"
+ $5
+ if test "$apu_acceptable" = "yes"; then
+ apu_found="yes"
+ fi])
+ fi
+
+ dnl if --with-apr-util is used, it is a fatal error for its argument
+ dnl to be invalid
+ if test "$apu_found" != "yes"; then
+ AC_MSG_ERROR([the --with-apr-util parameter is incorrect. It must specify an install prefix, a build directory, or an apu-config file.])
+ fi
+ ],[
+ if test -n "$3" && test "$3" = "1"; then
+ for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config
+ do
+ if $apu_temp_apu_config_file --help > /dev/null 2>&1 ; then
+ apu_config="$apu_temp_apu_config_file"
+ ifelse([$5], [], [], [
+ apu_acceptable="yes"
+ $5
+ if test "$apu_acceptable" != "yes"; then
+ AC_MSG_WARN([skipped APR-util at $apu_config, version not acceptable])
+ continue
+ fi])
+ apu_found="yes"
+ break
+ else
+ dnl look in some standard places (apparently not in builtin/default)
+ for lookdir in /usr /usr/local /usr/local/apr /opt/apr; do
+ if $TEST_X "$lookdir/bin/$apu_temp_apu_config_file"; then
+ apu_config="$lookdir/bin/$apu_temp_apu_config_file"
+ ifelse([$5], [], [], [
+ apu_acceptable="yes"
+ $5
+ if test "$apu_acceptable" != "yes"; then
+ AC_MSG_WARN([skipped APR-util at $apu_config, version not acceptable])
+ continue
+ fi])
+ apu_found="yes"
+ break 2
+ fi
+ done
+ fi
+ done
+ fi
+ dnl if we have not found anything yet and have bundled source, use that
+ if test "$apu_found" = "no" && test -d "$1"; then
+ apu_temp_abs_srcdir="`cd $1 && pwd`"
+ apu_found="reconfig"
+ apu_bundled_major="`sed -n '/#define.*APU_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \"$1/include/apu_version.h\"`"
+ case $apu_bundled_major in
+ "")
+ AC_MSG_ERROR([failed to find major version of bundled APU])
+ ;;
+ 0)
+ apu_temp_apu_config_file="apu-config"
+ ;;
+ *)
+ apu_temp_apu_config_file="apu-$apu_bundled_major-config"
+ ;;
+ esac
+ if test -n "$2"; then
+ apu_config="$2/$apu_temp_apu_config_file"
+ else
+ apu_config="$1/$apu_temp_apu_config_file"
+ fi
+ fi
+ ])
+
+ AC_MSG_RESULT($apu_found)
+])
diff --git a/liblog4cxx.pc.in b/liblog4cxx.pc.in
new file mode 100644
index 0000000..3800462
--- /dev/null
+++ b/liblog4cxx.pc.in
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: log4cxx
+Description: log4cxx C++ logging framework
+Version: @VERSION@
+Libs: -L${libdir} -llog4cxx
+Cflags: -I${includedir}
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..a80875f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,247 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>log4cxx</groupId>
+ <artifactId>apache-log4cxx</artifactId>
+ <packaging>pom</packaging>
+ <version>0.10.0</version>
+ <name>Apache log4cxx</name>
+ <description>Logging framework for C++.</description>
+ <url>http://logging.apache.org:80/log4cxx</url>
+ <issueManagement>
+ <system>JIRA</system>
+ <url>http://issues.apache.org/jira/</url>
+ </issueManagement>
+<mailingLists>
+ <mailingList>
+ <name>log4cxx-user : log4cxx usage</name>
+ <subscribe>log4cxx-user-subscribe@logging.apache.org</subscribe>
+ <unsubscribe>log4cxx-user-unsubscribe@logging.apache.org</unsubscribe>
+ <post>log4cxx-user@logging.apache.org</post>
+ <archive>http://mail-archives.apache.org/mod_mbox/logging-log4cxx-user/</archive>
+ <otherArchives>
+ <otherArchive>http://markmail.org/search/list:org.apache.logging.log4cxx-user</otherArchive>
+ <otherArchive>http://marc.info/?l=log4cxx-user</otherArchive>
+ <otherArchive>http://dir.gmane.org/gmane.comp.apache.logging.log4cxx.user</otherArchive>
+ </otherArchives>
+ </mailingList>
+ <mailingList>
+ <name>log4cxx-dev : log4cxx development</name>
+ <subscribe>log4cxx-dev-subscribe@logging.apache.org</subscribe>
+ <unsubscribe>log4cxx-dev-unsubscribe@logging.apache.org</unsubscribe>
+ <post>log4cxx-dev@logging.apache.org</post>
+ <archive>http://mail-archives.apache.org/mod_mbox/logging-log4cxx-dev/</archive>
+ <otherArchives>
+ <otherArchive>http://markmail.org/search/list:org.apache.logging.log4cxx-dev</otherArchive>
+ <otherArchive>http://marc.info/?l=log4cxx-dev</otherArchive>
+ <otherArchive>http://dir.gmane.org/gmane.comp.jakarta.log4j.devel</otherArchive>
+ </otherArchives>
+ </mailingList>
+</mailingLists>
+<licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ <distribution>repo</distribution>
+ </license>
+</licenses>
+<scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/logging/log4cxx/tags/v0_10_0-rc8</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/logging/log4cxx/tags/v0_10_0-rc8</developerConnection>
+ <url>http://svn.apache.org/viewcvs.cgi/logging/log4cxx/tags/v0_10_0-rc8</url>
+</scm>
+<organization>
+ <name>Apache Software Foundation</name>
+ <url>http://www.apache.org</url>
+</organization>
+<build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <id>compile</id>
+ <configuration>
+ <tasks>
+ <ant target="build" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <phase>test-compile</phase>
+ <id>test-compile</id>
+ <configuration>
+ <tasks>
+ <ant target="test-compile" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <phase>test</phase>
+ <id>test</id>
+ <configuration>
+ <tasks>
+ <ant target="check" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <phase>package</phase>
+ <id>autogen</id>
+ <configuration>
+ <tasks>
+ <ant target="autogen" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <phase>site</phase>
+ <id>site</id>
+ <configuration>
+ <tasks>
+ <ant target="site" />
+ <taskdef name="replaceregexp" classname="org.apache.tools.ant.taskdefs.optional.ReplaceRegExp" />
+ <replaceregexp file="target/site/source-repository.html" match="/tags/[^ &quot;'&lt;]*" replace="/trunk" flags="g" />
+ <replaceregexp match="Generated on .* for " replace="Generated for " flags="g">
+ <fileset dir="target/site/apidocs" includes="**/*.html" />
+ </replaceregexp>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <phase>post-site</phase>
+ <id>post-site</id>
+ <configuration>
+ <tasks>
+ <ant target="post-site" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <phase>site-deploy</phase>
+ <id>site-deploy</id>
+ <configuration>
+ <tasks>
+ <ant target="site-deploy" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>ant</groupId>
+ <artifactId>ant-nodeps</artifactId>
+ <version>1.6.5</version>
+ </dependency>
+ <dependency>
+ <groupId>ant-contrib</groupId>
+ <artifactId>ant-contrib</artifactId>
+ <version>1.0b2</version>
+ </dependency>
+ <dependency>
+ <groupId>ant-contrib</groupId>
+ <artifactId>cpptasks</artifactId>
+ <version>1.0b5</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptors>
+ <descriptor>src/assembly/source.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>assembly</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>rat-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+</build>
+ <dependencies>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.14</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <reporting>
+ <excludeDefaults>true</excludeDefaults>
+ <plugins>
+ <plugin>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>scm</report>
+ <report>dependencies</report>
+ <report>issue-tracking</report>
+ <report>mailing-list</report>
+ <report>license</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <artifactId>maven-release-plugin</artifactId>
+ <configuration>
+ <goals>site-deploy assembly:assembly</goals>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-changes-plugin</artifactId>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>changes-report</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ <configuration>
+ <issueLinkTemplate>%URL%/browse/%ISSUE%</issueLinkTemplate>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+ <distributionManagement>
+ <repository>
+ <id>tmp.repo</id>
+ <url>file:///tmp</url>
+ </repository>
+ <site>
+ <id>logging.site</id>
+ <url>file:///${user.dir}/target/site-deploy</url>
+ </site>
+ </distributionManagement>
+</project>
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..4a68a45
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+SUBDIRS = main examples site test
diff --git a/src/ant/apr-build.xml b/src/ant/apr-build.xml
new file mode 100755
index 0000000..6614a0e
--- /dev/null
+++ b/src/ant/apr-build.xml
@@ -0,0 +1,498 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<!DOCTYPE project [
+<!ENTITY common SYSTEM 'common.xml'>
+<!ENTITY license '
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+'>
+]>
+<!--
+
+This file builds APR using Apache Ant (http://ant.apache.org)
+and the C++ compilation tasks from http://ant-contrib.sourceforge.net.
+
+
+-->
+<project name="apr" default="check">
+
+&common;
+
+<property name="src.dir" location="${basedir}"/>
+<property name="include.dir" location="${src.dir}/include"/>
+<property name="test.dir" location="${src.dir}/test"/>
+<property name="target.dir" location="${basedir}/target"/>
+<property name="lib.name" value="apr-1"/>
+<property name="lib.prefix" value=""/>
+
+<target name="usage" description="Displays usage notes on build">
+ <echo>
+ </echo>
+</target>
+
+<target name="clean" description="Removes build product files">
+ <delete dir="${target.dir}"/>
+</target>
+
+<target name="win-configure" if="is-windows">
+ <copy file="${include.dir}/apr.hw" tofile="${include.dir}/apr.tmp" overwrite="true"/>
+ <replaceregexp file="${include.dir}/apr.tmp"
+ match="typedef *int *uid_t;" replace="/* typedef int uid_t */"/>
+ <replaceregexp file="${include.dir}/apr.tmp"
+ match="typedef *int *gid_t;" replace="/* typedef int gid_t */"/>
+ <antcall target="copy-if-changed">
+ <param name="file" value="${include.dir}/apr.tmp"/>
+ <param name="tofile" value="${include.dir}/apr.h"/>
+ </antcall>
+</target>
+
+
+<target name="check-configure" if="is-unix">
+ <condition property="force-configure" value="1">
+ <not><available file="${include.dir}/apr.h"/></not>
+ </condition>
+</target>
+
+<target name="unix-configure" depends="check-configure" if="force-configure">
+ <!-- shelling to configure allows cygwin to work -->
+ <exec executable="sh" dir="${src.dir}">
+ <arg value="./configure"/>
+ </exec>
+</target>
+
+
+<target name="init" depends="common-init">
+ <condition property="arch" value="win32">
+ <isset property="is-windows"/>
+ </condition>
+ <property name="arch" value="unix"/>
+</target>
+
+<target name="configure" depends="init, unix-configure, win-configure"/>
+
+
+
+<target name="build" depends="configure" description="Build library">
+ <mkdir dir="${executable.dir}/apr-ofiles"/>
+ <property name="project.compiler" value="${compiler}"/>
+ <property name="project.type" value="msvc6"/>
+
+ <cc name="${project.compiler}"
+ outfile="${executable.dir}/${lib.prefix}${lib.name}${lib.suffix}"
+ subsystem="console"
+ multithreaded="true"
+ runtime="${runtime}"
+ outtype="${lib.type}"
+ objdir="${executable.dir}/apr-ofiles"
+ outputfileproperty="apr-1.dll"
+ debug="${debug}"
+ projectsOnly="${projectsOnly}">
+ <!-- suppressing misc/win32/rand.c since it needs to include rpc.h -->
+ <fileset dir="${src.dir}" includes="**/${arch}/*.c" excludes="**/apr_app.c misc/win32/rand.c"/>
+ <fileset dir="${src.dir}" includes="**/${arch}/apr_app.c" if="is-static"/>
+ <fileset dir="${src.dir}/file_io/unix"
+ includes="copy.c fileacc.c filepath_util.c fullrw.c mktemp.c tempdir.c"/>
+ <fileset dir="${src.dir}/memory/unix" includes="*.c"/>
+ <fileset dir="${src.dir}/misc/unix"
+ includes="errorcodes.c getopt.c otherchild.c version.c"/>
+ <fileset dir="${src.dir}/mmap/unix" includes="common.c"/>
+ <fileset dir="${src.dir}/network_io/unix"
+ includes="inet_ntop.c inet_pton.c sockaddr.c"/>
+ <fileset dir="${src.dir}/poll/unix" includes="select.c"/>
+ <fileset dir="${src.dir}/random/unix" includes="*.c"/>
+ <fileset dir="${src.dir}/strings" includes="*.c"/>
+ <fileset dir="${src.dir}/tables" includes="*.c"/>
+ <fileset dir="${include.dir}" includes="*.h"/>
+ <fileset dir="${include.dir}/arch" includes="*.h"/>
+ <fileset dir="${include.dir}/arch/${arch}" includes="*.h"/>
+ <fileset dir="${include.dir}/arch/unix" includes="*.h"/>
+ <fileset dir="${src.dir}/support/unix" includes="waitio.c"/>
+ <includepath path="${include.dir}"/>
+ <includepath path="${include.dir}/arch"/>
+ <includepath path="${include.dir}/arch/${arch}"/>
+ <includepath path="${include.dir}/arch/unix"/>
+ <defineset define="APR_DECLARE_EXPORT" if="is-shared"/>
+ <defineset define="APR_DECLARE_STATIC" unless="is-shared"/>
+ <defineset if="is-windows">
+ <define name="WIN32" value="1"/>
+ </defineset>
+ <defineset define="_HAVE_CONFIG_H _REENTRANT _GNU_SOURCE" if="is-gcc"/>
+ <defineset define="HAVE_CONFIG_H DARWIN SIGPROCMASK_SETS_THREAD_MASK" if="is-mac"/>
+ <compilerarg value="${pic-option}" if="pic-option"/>
+ <libset libs="advapi32 ws2_32 mswsock rpcrt4" if="is-windows"/>
+ <libset libs="pthread dl" if="is-unix"/>
+ <libset libs="cw32mt" if="is-bcc"/>
+ <project type="${project.type}" outfile="${projects.dir}/apr" if="project.if">
+ <comment>&license;</comment>
+ </project>
+
+ </cc>
+ <property name="apr.lib.dir" location="${executable.dir}"/>
+</target>
+
+<target name="build-test">
+ <mkdir dir="${executable.dir}/apr-test-ofiles"/>
+ <property name="project.compiler" value="${compiler}"/>
+ <property name="project.type" value="msvc6"/>
+ <cc name="${project.compiler}"
+ outfile="${executable.dir}/${test}"
+ subsystem="console"
+ multithreaded="true"
+ runtime="${runtime}"
+ outtype="executable"
+ objdir="${executable.dir}/apr-test-ofiles"
+ debug="${debug}"
+ projectsOnly="${projectsOnly}">
+ <fileset dir="${test.dir}" includes="${testfiles}"/>
+ <includepath path="${include.dir}"/>
+ <defineset if="is-windows">
+ <define name="WIN32" value="1"/>
+ </defineset>
+ <defineset define="_HAVE_CONFIG_H _REENTRANT _GNU_SOURCE" if="is-gcc"/>
+ <defineset define="APR_DECLARE_STATIC" unless="is-shared"/>
+ <defineset define="HAVE_CONFIG_H DARWIN SIGPROCMASK_SETS_THREAD_MASK" if="is-mac"/>
+ <compilerarg value="${pic-option}" if="pic-option"/>
+ <libset dir="${apr.lib.dir}" libs="${lib.prefix}${lib.name}${lib.suffix}"/>
+ <libset libs="cw32mt" if="is-bcc"/>
+ <libset libs="pthread dl" if="is-unix"/>
+ <libset libs="advapi32 ws2_32 mswsock rpcrt4" if="is-windows"/>
+ <project type="${project.type}" outfile="${projects.dir}/${test}" if="project.if">
+ <comment>&license;</comment>
+ <dependency file="${projects.dir}/apr"/>
+ </project>
+ </cc>
+</target>
+
+<target name="run-test">
+ <exec executable="${apr.lib.dir}/${test}"
+ dir="${apr.lib.dir}"
+ failonerror="true">
+ <env key="DYLD_LIBRARY_PATH"
+ value="${apr.lib.dir}:${env.DYLD_LIBRARY_PATH}"/>
+ <env key="LD_LIBRARY_PATH"
+ value="${apr.lib.dir}:${env.LD_LIBRARY_PATH}"/>
+ </exec>
+</target>
+
+
+<target name="build-testlockperf" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="testlockperf"/>
+ <param name="testfiles" value="testlockperf.c"/>
+ </antcall>
+</target>
+
+<target name="run-testlockperf" depends="build-testlockperf">
+ <antcall target="run-test">
+ <param name="test" value="testlockperf"/>
+ </antcall>
+</target>
+
+<target name="build-testshmproducer" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="testshmproducer"/>
+ <param name="testfiles" value="testshmproducer.c"/>
+ </antcall>
+</target>
+
+<target name="build-testshmconsumer" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="testshmconsumer"/>
+ <param name="testfiles" value="testshmconsumer.c"/>
+ </antcall>
+</target>
+
+
+<target name="build-testmutexscope" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="testmutexscope"/>
+ <param name="testfiles" value="testmutexscope.c"/>
+ </antcall>
+</target>
+
+<target name="run-testmutexscope" depends="build-testmutexscope">
+ <antcall target="run-test">
+ <param name="test" value="testmutexscope"/>
+ </antcall>
+</target>
+
+<target name="build-occhild" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="occhild"/>
+ <param name="testfiles" value="occhild.c"/>
+ </antcall>
+</target>
+
+<target name="build-sockchild" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="sockchild"/>
+ <param name="testfiles" value="sockchild.c"/>
+ </antcall>
+</target>
+
+
+<target name="build-readchild" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="readchild"/>
+ <param name="testfiles" value="readchild.c"/>
+ </antcall>
+</target>
+
+
+<target name="build-globalmutexchild" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="globalmutexchild"/>
+ <param name="testfiles" value="globalmutexchild.c"/>
+ </antcall>
+</target>
+
+<target name="build-tryread" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="tryread"/>
+ <param name="testfiles" value="tryread.c"/>
+ </antcall>
+</target>
+
+<target name="build-proc_child" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="proc_child"/>
+ <param name="testfiles" value="proc_child.c"/>
+ </antcall>
+</target>
+
+
+<target name="build-sendfile" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="sendfile"/>
+ <param name="testfiles" value="sendfile.c"/>
+ </antcall>
+</target>
+
+
+<target name="build-mod_test" depends="build">
+ <mkdir dir="${executable.dir}/test-ofiles"/>
+ <mkdir dir="${executable.dir}/.libs"/>
+ <property name="project.compiler" value="${compiler}"/>
+ <property name="project.type" value="msvc6"/>
+ <cc name="${project.compiler}"
+ outfile="${executable.dir}/.libs/mod_test"
+ subsystem="console"
+ multithreaded="true"
+ runtime="${runtime}"
+ outtype="shared"
+ objdir="${executable.dir}/test-ofiles"
+ outputfileproperty="libmod_test.so"
+ debug="${debug}"
+ projectsOnly="${projectsOnly}">
+ <fileset dir="${test.dir}" includes="mod_test.c"/>
+ <includepath path="${include.dir}"/>
+ <defineset if="is-windows">
+ <define name="WIN32" value="1"/>
+ </defineset>
+ <defineset define="_HAVE_CONFIG_H _REENTRANT _GNU_SOURCE" if="is-gcc"/>
+ <defineset define="APR_DECLARE_STATIC" unless="is-shared"/>
+ <defineset define="HAVE_CONFIG_H DARWIN SIGPROCMASK_SETS_THREAD_MASK" if="is-mac"/>
+ <compilerarg value="${pic-option}" if="pic-option"/>
+ <libset dir="${apr.lib.dir}" libs="${lib.prefix}${lib.name}${lib.suffix}"/>
+ <libset libs="cw32mt" if="is-bcc"/>
+ <libset libs="advapi32 ws2_32 mswsock rpcrt4" if="is-windows"/>
+ <project type="${project.type}" outfile="${projects.dir}/mod_test" if="project.if">
+ <comment>&license;</comment>
+ <dependency file="${projects.dir}/apr-1"/>
+ </project>
+
+ </cc>
+ <copy file="${libmod_test.so}" tofile="${executable.dir}/.libs/mod_test.so"/>
+</target>
+
+
+<target name="build-testall" depends="build">
+ <mkdir dir="${executable.dir}/test-ofiles"/>
+ <property name="project.compiler" value="${compiler}"/>
+ <property name="project.type" value="msvc6"/>
+ <cc name="${project.compiler}"
+ outfile="${executable.dir}/testall"
+ subsystem="console"
+ multithreaded="true"
+ runtime="${runtime}"
+ outtype="executable"
+ objdir="${executable.dir}/test-ofiles"
+ debug="${debug}"
+ projectsOnly="${projectsOnly}">
+ <fileset dir="${test.dir}" includes="*.c">
+ <exclude name="nw_misc.c"/>
+ <exclude name="testlockperf.c"/>
+ <exclude name="occhild.c"/>
+ <exclude name="sockchild.c"/>
+ <exclude name="sockperf.c"/>
+ <exclude name="echod.c"/>
+ <exclude name="mockchild.c"/>
+ <exclude name="readchild.c"/>
+ <exclude name="globalmutexchild.c"/>
+ <exclude name="tryread.c"/>
+ <exclude name="proc_child.c"/>
+ <exclude name="sendfile.c"/>
+ <exclude name="testshmproducer.c"/>
+ <exclude name="testshmconsumer.c"/>
+ <exclude name="testmutexscope.c"/>
+ <exclude name="testapp.c"/>
+ </fileset>
+ <includepath path="${include.dir}"/>
+ <defineset if="is-windows">
+ <define name="WIN32" value="1"/>
+ </defineset>
+ <defineset define="_HAVE_CONFIG_H _REENTRANT _GNU_SOURCE" if="is-gcc"/>
+ <defineset define="APR_DECLARE_STATIC" unless="is-shared"/>
+ <defineset define="HAVE_CONFIG_H DARWIN SIGPROCMASK_SETS_THREAD_MASK" if="is-mac"/>
+ <compilerarg value="${pic-option}" if="pic-option"/>
+ <libset dir="${apr.lib.dir}" libs="${lib.prefix}${lib.name}${lib.suffix}"/>
+ <libset libs="cw32mt" if="is-bcc"/>
+ <libset libs="pthread dl" if="is-unix"/>
+ <libset libs="advapi32 ws2_32 mswsock rpcrt4" if="is-windows"/>
+ <project type="${project.type}" outfile="${projects.dir}/testall" if="project.if">
+ <comment>&license;</comment>
+ <dependency file="${projects.dir}/apr-1"/>
+ </project>
+ </cc>
+</target>
+
+<target name="run-testall" depends="build-testall, build-mod_test, build-tryread, build-readchild, build-globalmutexchild, build-occhild, build-proc_child, build-testshmconsumer, build-testshmproducer, build-sockchild">
+ <mkdir dir="${executable.dir}/data"/>
+ <copy todir="${executable.dir}/data">
+ <fileset dir="${test.dir}/data" includes="*"/>
+ </copy>
+ <exec executable="${executable.dir}/testall"
+ dir="${executable.dir}"
+ failonerror="true">
+ <env key="DYLD_LIBRARY_PATH"
+ value="${apr.lib.dir}:${executable.dir}/.libs:${env.DYLD_LIBRARY_PATH}"/>
+ <env key="LD_LIBRARY_PATH"
+ value="${apr.lib.dir}:${executable.dir}/.libs:${env.LD_LIBRARY_PATH}"/>
+ </exec>
+</target>
+
+
+
+<target name="build-check"
+ depends="build-testlockperf,
+ build-testshmproducer,
+ build-testshmconsumer,
+ build-testmutexscope,
+ build-testall"
+ description="Builds all test applications"/>
+
+<target name="check"
+ depends="run-testlockperf,
+ run-testall"
+ description="Runs all test applications">
+</target>
+
+<target name="build-projects">
+ <mkdir dir="${projects.dir}"/>
+ <antcall target="build">
+ <param name="project.if" value="true"/>
+ <param name="project.type" value="${project.type}"/>
+ <param name="project.compiler" value="${project.compiler}"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="debug" value="${debug}"/>
+ <param name="projectsOnly" value="true"/>
+ <param name="arch" value="${arch}"/>
+ </antcall>
+ <antcall target="build-check">
+ <param name="project.if" value="true"/>
+ <param name="project.type" value="${project.type}"/>
+ <param name="project.compiler" value="${project.compiler}"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="debug" value="${debug}"/>
+ <param name="projectsOnly" value="true"/>
+ <param name="arch" value="${arch}"/>
+ </antcall>
+</target>
+
+<target name="build-projects-vc6" depends="init"
+ description="Builds project files for Microsoft Visual C++ 6">
+ <antcall target="build-projects">
+ <param name="project.type" value="msvc6"/>
+ <param name="project.compiler" value="msvc"/>
+ <param name="os.family" value="windows"/>
+ <param name="debug" value="${debug}"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ </antcall>
+</target>
+
+
+<target name="build-projects-vc7" depends="init"
+ description="Builds project files for Microsoft Visual Studio .NET">
+ <antcall target="build-projects">
+ <param name="project.type" value="msvc7"/>
+ <param name="project.compiler" value="msvc"/>
+ <param name="os.family" value="windows"/>
+ <param name="debug" value="${debug}"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ </antcall>
+</target>
+
+<target name="build-projects-vc8" depends="init"
+ description="Builds project files for Microsoft Visual C++ 2005">
+ <antcall target="build-projects">
+ <param name="project.type" value="msvc8"/>
+ <param name="project.compiler" value="msvc"/>
+ <param name="os.family" value="windows"/>
+ <param name="debug" value="${debug}"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ </antcall>
+</target>
+
+ <target name="build-projects-vc9" depends="init"
+ description="Builds project files for Microsoft Visual C++ 2008">
+ <antcall target="build-projects">
+ <param name="project.type" value="msvc9"/>
+ <param name="project.compiler" value="msvc"/>
+ <param name="os.family" value="windows"/>
+ <param name="debug" value="${debug}"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ </antcall>
+ </target>
+
+ <target name="build-projects-xcode" depends="init"
+ description="Builds project files for Apple Xcode">
+ <antcall target="build-projects">
+ <param name="project.type" value="xcode"/>
+ <param name="project.compiler" value="${compiler}"/>
+ <param name="os.family" value="mac"/>
+ <param name="debug" value="${debug}"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ </antcall>
+</target>
+
+
+
+</project>
diff --git a/src/ant/apr-util-build.xml b/src/ant/apr-util-build.xml
new file mode 100755
index 0000000..1a27fa1
--- /dev/null
+++ b/src/ant/apr-util-build.xml
@@ -0,0 +1,428 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<!DOCTYPE project [
+<!ENTITY common SYSTEM 'common.xml'>
+<!ENTITY find-apr SYSTEM 'find-apr.xml'>
+<!ENTITY license '
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+'>
+]>
+
+<!--
+
+This file builds APR using Apache Ant (http://ant.apache.org)
+and the C++ compilation tasks from http://ant-contrib.sourceforge.net.
+
+
+-->
+<project name="aprutil" default="check" basedir=".">
+
+&common;
+&find-apr;
+
+<property name="src.dir" location="${basedir}"/>
+<property name="include.dir" location="${src.dir}/include"/>
+<property name="target.dir" location="${basedir}/target"/>
+
+
+<target name="usage" description="Displays usage notes">
+ <echo>
+ </echo>
+</target>
+
+<target name="init" depends="common-init">
+ <condition property="arch" value="win32">
+ <isset property="is-windows"/>
+ </condition>
+ <property name="arch" value="unix"/>
+</target>
+
+<target name="clean" description="Deletes build products">
+ <delete dir="${target.dir}"/>
+</target>
+
+
+<target name="configure-check" depends="init">
+ <condition property="aprutil-config-available" value="true">
+ <and>
+ <available file="${include.dir}/apu.h"/>
+ <available file="${include.dir}/apu_want.h"/>
+ <available file="${include.dir}/private/apu_config.h"/>
+ <available file="${include.dir}/private/apu_select_dbm.h"/>
+ <available file="${src.dir}/xml/expat/lib/expat.h"/>
+ <available file="${src.dir}/xml/expat/config.h"/>
+ </and>
+ </condition>
+</target>
+
+
+<target name="win-configure" depends="configure-check" if="is-windows" unless="aprutil-config-available">
+ <copy tofile="${include.dir}/apu.h" file="${include.dir}/apu.hw"/>
+ <replaceregexp file="${include.dir}/apu.h" match="#define *APU_HAVE_APR_ICONV.*" replace="#define APU_HAVE_APR_ICONV 0"/>
+ <copy tofile="${include.dir}/apu_want.h" file="${include.dir}/apu_want.hw"/>
+ <copy tofile="${include.dir}/apr_ldap.h" file="${include.dir}/apr_ldap.hw"/>
+ <replaceregexp file="${include.dir}/apr_ldap.h" match="#define APR_HAS_LDAP.*" replace="#define APR_HAS_LDAP 0"/>
+ <copy tofile="${include.dir}/private/apu_config.h" file="${include.dir}/private/apu_config.hw"/>
+ <copy tofile="${include.dir}/private/apu_select_dbm.h" file="${include.dir}/private/apu_select_dbm.hw"/>
+ <copy tofile="${src.dir}/xml/expat/lib/expat.h" file="${src.dir}/xml/expat/lib/expat.h.in"/>
+ <copy tofile="${src.dir}/xml/expat/lib/config.h" file="${src.dir}/xml/expat/lib/winconfig.h"/>
+</target>
+
+<target name="unix-configure" depends="configure-check, find-apr" if="is-unix" unless="aprutil-config-available">
+ <exec executable="sh" dir="${src.dir}">
+ <arg value="./configure"/>
+ <arg value="--with-apr=${apr.dir}"/>
+ </exec>
+ <exec executable="sh" dir="${src.dir}/xml/expat">
+ <arg value="./configure"/>
+ </exec>
+</target>
+
+
+<target name="configure" depends="unix-configure, win-configure">
+ <condition property="has-iconv" value="1">
+ <isfileselected file="${include.dir}/apu.h">
+ <contains text="#define APR_HAVE_ICONV 1" ignorewhitespace="true"/>
+ </isfileselected>
+ </condition>
+ <condition property="has-iconv" value="1">
+ <isfileselected file="${include.dir}/apu.h">
+ <contains text="#define APU_HAVE_ICONV 1" ignorewhitespace="true"/>
+ </isfileselected>
+ </condition>
+ <condition property="has-sqlite3" value="1">
+ <isfileselected file="${include.dir}/apu.h">
+ <contains text="#define APU_HAVE_SQLITE3 1" ignorewhitespace="true"/>
+ </isfileselected>
+ </condition>
+</target>
+
+
+<target name="build-xml" depends="configure" description="Builds Expat">
+ <!-- uses replace instead of preprocessor since
+ the quotes on VERSION cause problems with cpptasks -->
+ <replace file="${src.dir}/xml/expat/lib/xmlparse.c">
+ <replacefilter token="XML_MAJOR_VERSION" value="1"/>
+ <replacefilter token="XML_MINOR_VERSION" value="95"/>
+ <replacefilter token="XML_MICRO_VERSION" value="1"/>
+ <replacefilter token="VERSION" value='"expat_1.95.1"'/>
+ </replace>
+
+ <mkdir dir="${executable.dir}/apr-util-ofiles"/>
+ <property name="project.compiler" value="${compiler}"/>
+ <property name="project.type" value="msvc6"/>
+
+ <!-- this only generate a project file necessary to mimic
+ this visual studio project provided with APR -->
+ <cc name="${project.compiler}"
+ outfile="${executable.dir}/expat"
+ subsystem="console"
+ multithreaded="true"
+ runtime="${runtime}"
+ outtype="static"
+ objdir="${executable.dir}/apr-util-ofiles"
+ warnings="none"
+ debug="${debug}"
+ projectsOnly="true">
+ <fileset dir="${src.dir}/xml/expat/lib"
+ includes="xmlparse.c xmlrole.c xmltok.c"/>
+ <fileset dir="${src.dir}/xml/expat/lib" includes="*.h"/>
+ <fileset dir="${src.dir}/xml/expat" includes="*.h"/>
+ <includepath path="${src.dir}/xml/expat/lib"/>
+ <includepath path="${src.dir}/xml/expat"/>
+ <defineset>
+ <define name="XMLPARSEAPI" value=" "/>
+ </defineset>
+ <defineset define="WIN32" if="is-windows"/>
+ <defineset define="_HAVE_CONFIG_H _REENTRANT _GNU_SOURCE" if="is-gcc"/>
+ <compilerarg value="${pic-option}" if="pic-option"/>
+
+ <libset libs="cw32mt" if="is-bcc"/>
+ <project type="${project.type}" outfile="${projects.dir}/xml" if="project.if">
+ <comment>&license;</comment>
+ </project>
+ </cc>
+
+</target>
+
+<target name="build" depends="build-xml, find-apr" description="Build library">
+ <property name="apr.lib.prefix" value=""/>
+ <property name="apr.lib.name" value="apr-1"/>
+ <property name="apr.lib.suffix" value=""/>
+ <cc name="${project.compiler}"
+ outfile="${executable.dir}/aprutil-1${lib-suffix}"
+ subsystem="console"
+ multithreaded="true"
+ runtime="${runtime}"
+ outtype="${lib.type}"
+ objdir="${executable.dir}/apr-util-ofiles"
+ warnings="none"
+ debug="${debug}"
+ projectsOnly="${projectsOnly}">
+ <fileset dir="${src.dir}" includes="**/*.c"
+ excludes="test/*.c *.c ldap/*.c xml/expat/lib/*"/>
+ <fileset dir="${src.dir}/xml/expat/lib"
+ includes="xmlparse.c xmlrole.c xmltok.c"/>
+ <fileset dir="${src.dir}/xml/expat/lib" includes="*.h"/>
+ <fileset dir="${src.dir}/xml/expat" includes="*.h"/>
+ <fileset dir="${include.dir}" includes="*.h"/>
+ <fileset dir="${include.dir}/private" includes="*.h"/>
+ <includepath path="${apr.include.dir}"/>
+ <includepath path="${include.dir}"/>
+ <includepath path="${include.dir}/private"/>
+ <includepath path="${src.dir}/xml/expat/lib"/>
+ <includepath path="${src.dir}/xml/expat"/>
+ <defineset define="APU_DECLARE_EXPORT" if="is-shared"/>
+ <defineset define="APU_DECLARE_STATIC" unless="is-shared"/>
+ <defineset define="APR_DECLARE_STATIC" unless="is-apr-shared"/>
+ <defineset>
+ <define name="XMLPARSEAPI" value=" "/>
+ </defineset>
+ <defineset define="WIN32" if="is-windows"/>
+ <defineset define="_HAVE_CONFIG_H _REENTRANT _GNU_SOURCE" if="is-gcc"/>
+ <compilerarg value="${pic-option}" if="pic-option"/>
+
+ <libset dir="${executable.dir}" libs="xml ${apr.lib.prefix}${apr.lib.name}${apr.lib.suffix}"/>
+ <libset libs="cw32mt" if="is-bcc"/>
+ <libset libs="pthread dl" if="is-unix"/>
+ <libset libs="iconv" if="has-iconv"/>
+ <libset libs="sqlite3" if="has-sqlite3"/>
+ <defineset if="is-bcc">
+ <define name="EILSEQ" value="50"/>
+ </defineset>
+ <project type="${project.type}" outfile="${projects.dir}/aprutil" if="project.if">
+ <comment>&license;</comment>
+ <dependency file="${projects.dir}/apr"/>
+ </project>
+ </cc>
+ <property name="apr.lib.dir" location="${executable.dir}"/>
+</target>
+
+<target name="build-test">
+ <mkdir dir="${executable.dir}/apr-util-test-ofiles"/>
+ <property name="project.compiler" value="${compiler}"/>
+ <property name="project.type" value="msvc6"/>
+ <cc name="${project.compiler}"
+ outfile="${executable.dir}/${test}"
+ subsystem="console"
+ multithreaded="true"
+ runtime="${runtime}"
+ outtype="executable"
+ objdir="${executable.dir}/apr-util-test-ofiles"
+ debug="${debug}"
+ projectsOnly="${projectsOnly}">
+ <fileset dir="${src.dir}/test" includes="${include.files}" excludes="${exclude.files}"/>
+ <includepath path="${include.dir}"/>
+ <includepath path="${apr.include.dir}"/>
+ <defineset define="APU_DECLARE_STATIC" unless="is-shared"/>
+ <defineset define="APR_DECLARE_STATIC" unless="is-apr-shared"/>
+ <defineset if="is-windows">
+ <define name="WIN32" value="1"/>
+ </defineset>
+ <defineset define="_HAVE_CONFIG_H _REENTRANT _GNU_SOURCE" if="is-gcc"/>
+ <compilerarg value="${pic-option}" if="pic-option"/>
+ <libset dir="${apr.lib.dir}" libs="apr-1${lib-suffix}" if="apr.lib.dir"/>
+ <libset libs="apr-1${lib-suffix}" unless="apr.lib.dir"/>
+ <libset dir="${executable.dir}" libs="aprutil-1${lib-suffix}"/>
+ <libset libs="cw32mt" if="is-bcc"/>
+ <libset libs="pthread dl" if="is-unix"/>
+ <libset libs="iconv" if="has-iconv"/>
+ <libset libs="sqlite3" if="has-sqlite3"/>
+ <project type="${project.type}" outfile="${projects.dir}/${test}" if="project.if">
+ <comment>&license;</comment>
+ <dependency file="${projects.dir}/apr"/>
+ <dependency file="${projects.dir}/aprutil" depends="apr"/>
+ </project>
+ </cc>
+</target>
+
+<target name="copy-apr" if="is-windows">
+ <copy todir="${executable.dir}" overwrite="true">
+ <fileset dir="${apr.lib.dir}" includes="apr-1${lib-suffix}.dll"/>
+ </copy>
+</target>
+
+<target name="run-test" depends="copy-apr">
+ <exec executable="${executable.dir}/${test}"
+ dir="${executable.dir}"
+ failonerror="true">
+ <env key="DYLD_LIBRARY_PATH"
+ value="${apr.lib.dir}:${aprutil.lib.dir}:${env.DYLD_LIBRARY_PATH}"/>
+ <env key="LD_LIBRARY_PATH"
+ value="${apr.lib.dir}:${aprutil.lib.dir}:${env.LD_LIBRARY_PATH}"/>
+ <env key="Path"
+ value="${apr.lib.dir}:${aprutil.lib.dir}:${env.Path}"/>
+ </exec>
+</target>
+
+
+<target name="build-testall" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="testall"/>
+ <param name="include.files" value="**/*.c"/>
+ <param name="exclude.files" value="dbd.c testssl.c echod.c sockperf.c nw*.c"/>
+ </antcall>
+</target>
+
+<target name="run-testall" depends="build-testall">
+ <antcall target="run-test">
+ <param name="test" value="testall"/>
+ </antcall>
+</target>
+
+<target name="build-dbd" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="dbd"/>
+ <param name="include.files" value="dbd.c"/>
+ <param name="exclude.files" value="*.y"/>
+ </antcall>
+</target>
+
+<target name="run-dbd" depends="build-dbd">
+ <antcall target="run-test">
+ <param name="test" value="dbd"/>
+ </antcall>
+</target>
+
+<target name="build-testssl" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="testssl"/>
+ <param name="include.files" value="testssl.c"/>
+ </antcall>
+</target>
+
+<target name="run-testssl" depends="build-testssl">
+ <antcall target="run-test">
+ <param name="test" value="testssl"/>
+ </antcall>
+</target>
+
+<target name="build-echod" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="echod"/>
+ <param name="include.files" value="echod.c"/>
+ </antcall>
+</target>
+
+<target name="build-sockperf" depends="build">
+ <antcall target="build-test">
+ <param name="test" value="sockperf"/>
+ <param name="include.files" value="sockperf.c"/>
+ </antcall>
+</target>
+
+
+
+<target name="build-check"
+ depends="build-testall, build-dbd, build-testssl, build-echod"
+ description="Builds all tests"/>
+
+<target name="check"
+ depends="build-check"
+ description="Runs all tests"/>
+
+
+ <target name="build-projects">
+ <mkdir dir="${projects.dir}"/>
+ <antcall target="build">
+ <param name="project.if" value="true"/>
+ <param name="project.type" value="${project.type}"/>
+ <param name="project.compiler" value="${project.compiler}"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="debug" value="${debug}"/>
+ <param name="projectsOnly" value="true"/>
+ </antcall>
+ </target>
+
+ <target name="build-projects-vc6" depends="init"
+ description="Builds project files for Microsoft Visual C++ 6">
+ <antcall target="build-projects">
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="project.type" value="msvc6"/>
+ <param name="project.compiler" value="msvc"/>
+ <param name="os.family" value="windows"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="debug" value="${debug}"/>
+ </antcall>
+ </target>
+
+ <target name="build-projects-vc7" depends="init"
+ description="Builds project files for Microsoft Visual Studio .NET">
+ <antcall target="build-projects">
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="project.type" value="msvc7"/>
+ <param name="project.compiler" value="msvc"/>
+ <param name="os.family" value="windows"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="debug" value="${debug}"/>
+ </antcall>
+ </target>
+
+ <target name="build-projects-vc8" depends="init"
+ description="Builds project files for Microsoft Visual C++ 2005">
+ <antcall target="build-projects">
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="project.type" value="msvc8"/>
+ <param name="project.compiler" value="msvc"/>
+ <param name="os.family" value="windows"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="debug" value="${debug}"/>
+ </antcall>
+ </target>
+
+ <target name="build-projects-vc9" depends="init"
+ description="Builds project files for Microsoft Visual C++ 2008">
+ <antcall target="build-projects">
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="project.type" value="msvc9"/>
+ <param name="project.compiler" value="msvc"/>
+ <param name="os.family" value="windows"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="debug" value="${debug}"/>
+ </antcall>
+ </target>
+
+ <target name="build-projects-xcode" depends="init"
+ description="Builds project files for Apple Xcode">
+ <antcall target="build-projects">
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="project.type" value="xcode"/>
+ <param name="project.compiler" value="${compiler}"/>
+ <param name="os.family" value="mac"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="debug" value="${debug}"/>
+ </antcall>
+ </target>
+
+
+
+</project>
diff --git a/src/ant/common.xml b/src/ant/common.xml
new file mode 100644
index 0000000..7d9ae8e
--- /dev/null
+++ b/src/ant/common.xml
@@ -0,0 +1,184 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<property file="build.properties"/>
+<property name="debug" value="true"/>
+<property name="rtti" value="false"/>
+<property name="optimize" value="none"/>
+<property name="lib.type" value="shared"/>
+<property name="runtime" value="dynamic"/>
+
+<taskdef resource="cpptasks.tasks"/>
+<typedef resource="cpptasks.types"/>
+
+<target name="os-detect">
+ <condition property="os.family" value="mac">
+ <os family="mac"/>
+ </condition>
+ <condition property="os.family" value="windows">
+ <os family="windows"/>
+ </condition>
+ <property name="os.family" value="unix"/>
+ <condition property="is-mac" value="1">
+ <equals arg1="${os.family}" arg2="mac"/>
+ </condition>
+ <condition property="is-windows" value="1">
+ <equals arg1="${os.family}" arg2="windows"/>
+ </condition>
+ <condition property="is-unix" value="1">
+ <or>
+ <equals arg1="${os.family}" arg2="unix"/>
+ <equals arg1="${os.family}" arg2="mac"/>
+ <equals arg1="${os.family}" arg2="cygwin"/>
+ </or>
+ </condition>
+</target>
+
+
+<target name="win-init" depends="os-detect" if="is-windows">
+ <property name="compiler" value="msvc"/>
+
+ <condition property="is-bcc" value="true">
+ <or>
+ <equals arg1="${compiler}" arg2="bcc"/>
+ </or>
+ </condition>
+
+ <condition property="is-msvc" value="true">
+ <or>
+ <equals arg1="${compiler}" arg2="msvc"/>
+ </or>
+ </condition>
+
+ <condition property="is-mingw" value="true">
+ <or>
+ <equals arg1="${compiler}" arg2="gcc"/>
+ <equals arg1="${compiler}" arg2="g++"/>
+ </or>
+ </condition>
+</target>
+
+<target name="mac-init" depends="os-detect" if="is-mac">
+ <property name="project.type" value="xcode"/>
+</target>
+
+
+<target name="unix-init" depends="mac-init" if="is-unix">
+
+ <property name="compiler" value="gcc"/>
+
+ <condition property="has-expat" value="true">
+ <not><isset property="is-mac"/></not>
+ </condition>
+ <condition property="is-cygwin" value="true">
+ <os family="windows"/>
+ </condition>
+</target>
+
+
+<target name="common-init" depends="win-init, unix-init">
+ <available classname="net.sf.antcontrib.cpptasks.CCTask" property="cctask-available"/>
+ <fail unless="cctask-available">cpptasks required
+
+Use cpptasks 1.0b5 or later from
+http://ant-contrib.sourceforge.net.
+</fail>
+
+ <available classname="net.sf.antcontrib.cpptasks.ide.ProjectDef"
+ property="cctask-project-available"/>
+ <!-- fail unless="cctask-project-available">later version of cpptasks required
+
+Required features not present in cpptasks releases prior to Feb 2005</fail -->
+
+ <mkdir dir="${target.dir}"/>
+ <property name="projects.dir" value="${target.dir}"/>
+ <mkdir dir="${projects.dir}"/>
+
+ <condition property="is-gcc" value="true">
+ <or>
+ <equals arg1="${compiler}" arg2="gcc"/>
+ <equals arg1="${compiler}" arg2="g++"/>
+ </or>
+ </condition>
+
+ <condition property="pic-option" value="-fPIC">
+ <and>
+ <isset property="is-gcc"/>
+ <istrue value="${use-pic}"/>
+ </and>
+ </condition>
+
+
+ <condition property="is-debug" value="true">
+ <istrue value="${debug}"/>
+ </condition>
+
+ <condition property="debug.release" value="debug">
+ <isset property="is-debug"/>
+ </condition>
+ <property name="debug.release" value="release"/>
+
+
+ <condition property="D.debug" value="d">
+ <isset property="is-debug"/>
+ </condition>
+ <property name="D.debug" value=""/>
+
+ <condition property="D.R" value="d">
+ <isset property="is-debug"/>
+ </condition>
+ <property name="D.R" value="r"/>
+
+
+ <property name="lib-suffix" value=""/>
+
+ <condition property="is-static" value="1">
+ <equals arg1="${lib.type}" arg2="static"/>
+ </condition>
+ <condition property="is-shared" value="1">
+ <equals arg1="${lib.type}" arg2="shared"/>
+ </condition>
+
+ <property name="executable.dir" value="${target.dir}/${debug.release}/${lib.type}"/>
+
+ <property name="projectsOnly" value="false"/>
+
+ <property name="apr.lib.name" value="apr-1"/>
+ <property name="apr.sample.h" value="apr_pools.h"/>
+ <property name="apr.sample.c" value="file_io/unix/dir.c"/>
+ <property name="apr-util.lib.name" value="aprutil-1"/>
+ <property name="apr-util.sample.h" value="apr_xml.h"/>
+ <property name="apr-util.sample.c" value="xml/apr_xml.c"/>
+ <property name="esmtp.lib.name" value="esmtp"/>
+ <property name="esmtp.sample.h" value="libesmtp.h"/>
+ <property name="esmtp.sample.c" value="smtp-api.c"/>
+</target>
+
+
+<target name="copy-if-changed-compare" unless="force-copy">
+ <condition property="force-copy" value="2">
+ <not><filesmatch file1="${tofile}" file2="${file}"/></not>
+ </condition>
+</target>
+
+<target name="copy-if-changed" depends="copy-if-changed-compare" if="force-copy">
+ <copy tofile="${tofile}" file="${file}" overwrite="true"/>
+</target>
+
+
+
diff --git a/src/ant/esmtp-build.xml b/src/ant/esmtp-build.xml
new file mode 100755
index 0000000..2a93d72
--- /dev/null
+++ b/src/ant/esmtp-build.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0"?>
+<!DOCTYPE project [
+<!ENTITY common SYSTEM 'common.xml'>
+]>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+
+<!--
+
+This file builds libesmtp using Apache Ant (http://ant.apache.org)
+and the C++ compilation tasks from http://ant-contrib.sourceforge.net.
+
+
+-->
+<project name="esmtp" default="build">
+
+&common;
+
+<property name="src.dir" location="${basedir}"/>
+<property name="include.dir" location="${src.dir}"/>
+<property name="test.dir" location="${src.dir}/test"/>
+<property name="target.dir" location="${basedir}/target"/>
+<property name="lib.type" value="shared"/>
+<property name="projects.dir" location="${target.dir}"/>
+
+<target name="usage" description="Displays usage notes on build">
+ <echo>
+ </echo>
+</target>
+
+
+<target name="init" depends="common-init">
+</target>
+
+<target name="clean" description="Removes build product files">
+ <delete dir="${target.dir}"/>
+</target>
+
+
+<target name="configure-check" depends="init">
+ <condition property="esmtp-configure-available" value="true">
+ <available file="${include.dir}/config.h"/>
+ </condition>
+</target>
+
+
+<target name="win-configure" depends="configure-check" if="is-windows">
+ <antcall target="copy-if-changed">
+ <param name="file" value="${include.dir}/config.h.in"/>
+ <param name="tofile" value="${include.dir}/config.h"/>
+ </antcall>
+</target>
+
+<target name="unix-configure" depends="configure-check" if="is-unix" unless="esmtp-configure-available">
+ <!-- shelling to configure allows cygwin to work -->
+ <exec executable="sh" dir="${src.dir}">
+ <arg value="./configure"/>
+ </exec>
+</target>
+
+
+<target name="configure" depends="unix-configure, win-configure"/>
+
+
+<target name="build" depends="configure" description="Build library">
+ <mkdir dir="${executable.dir}/libesmtp-ofiles"/>
+ <property name="project.compiler" value="${compiler}"/>
+ <cc name="${project.compiler}"
+ outfile="${executable.dir}/esmtp${lib-suffix}"
+ subsystem="console"
+ multithreaded="true"
+ outtype="${lib.type}"
+ objdir="${executable.dir}/libesmtp-ofiles"
+ outputfileproperty="esmtp.dll"
+ debug="${debug}"
+ projectsOnly="${projectsOnly}">
+ <fileset dir="${src.dir}">
+ <include name="*.c"/>
+ <exclude name="getaddrinfo.c"/>
+ <exclude name="gethostbyname.c" if="is-windows"/>
+ <exclude name="strdup.c" if="is-windows"/>
+ <exclude name="snprintf.c" if="is-windows"/>
+ <exclude name="auth-client.c" if="is-windows"/>
+ <!-- exclude name="siobuf.c" if="is-windows"/ -->
+ </fileset>
+ <includepath path="${include.dir}"/>
+ <defineset define="HAVE_CONFIG_H"/>
+ <compilerarg value="${pic-option}" if="pic-option"/>
+ <libset libs="advapi32 ws2_32 mswsock rpcrt4" if="is-windows"/>
+ <libset libs="ssl crypto" if="is-unix"/>
+ <libset libs="cw32mt" if="is-bcc"/>
+ <project type="${project.type}" outfile="${projects.dir}/libesmtp" if="project.if"/>
+ </cc>
+</target>
+
+
+<target name="build-projects">
+ <mkdir dir="${projects.dir}"/>
+ <antcall target="build">
+ <param name="project.if" value="true"/>
+ <param name="project.type" value="${project.type}"/>
+ <param name="project.compiler" value="${project.compiler}"/>
+ <param name="projects.dir" value="${projects.dir}"/>
+ <param name="projectsOnly" value="true"/>
+ </antcall>
+</target>
+
+<target name="build-projects-vc6" description="Builds project files for Microsoft Visual C++ 6">
+ <antcall target="build-projects">
+ <param name="project.type" value="msvc6"/>
+ <param name="project.compiler" value="msvc"/>
+ </antcall>
+</target>
+
+<target name="build-projects-vc8" description="Builds project files for Microsoft Visual C++ 2005">
+ <antcall target="build-projects">
+ <param name="project.type" value="msvc8"/>
+ <param name="project.compiler" value="msvc"/>
+ </antcall>
+</target>
+
+<target name="build-projects-xcode" description="Builds project files for Apple Xcode">
+ <antcall target="build-projects">
+ <param name="project.type" value="xcode"/>
+ <param name="project.compiler" value="g++"/>
+ </antcall>
+</target>
+
+
+</project>
diff --git a/src/ant/find-apr-util.xml b/src/ant/find-apr-util.xml
new file mode 100644
index 0000000..646a8a4
--- /dev/null
+++ b/src/ant/find-apr-util.xml
@@ -0,0 +1,313 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<target name="find-apr-util-src" depends="init">
+ <condition property="apr-util.dir" value="${with-apr-util}">
+ <available file="${with-apr-util}"/>
+ </condition>
+ <condition property="apr-util.src.dir" value="${apr-util.dir}">
+ <available file="${apr-util.dir}/${apr-util.sample.c}"/>
+ </condition>
+ <condition property="apr-util.src.dir" value="../apr-util">
+ <available file="../apr-util/${apr-util.sample.c}"/>
+ </condition>
+</target>
+
+
+<target name="find-apr-util-lib" depends="find-apr-util-src" unless="force-ant">
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/lib${apr-util.lib.name}.la">
+ <available file="${apr-util.dir}/lib${apr-util.lib.name}.la"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/lib${apr-util.lib.name}.dylib">
+ <available file="${apr-util.dir}/lib${apr-util.lib.name}.dylib"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/lib${apr-util.lib.name}.so">
+ <available file="${apr-util.dir}/lib${apr-util.lib.name}.so"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/lib${apr-util.lib.name}.a">
+ <available file="${apr-util.dir}/lib${apr-util.lib.name}.a"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/${apr-util.lib.name}.lib">
+ <available file="${apr-util.dir}/${apr-util.lib.name}.lib"/></condition>
+ <condition property="apr-util.lib.file.dir" value="${apr-util.dir}">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/.libs/lib${apr-util.lib.name}.la">
+ <available file="${apr-util.dir}/.libs/lib${apr-util.lib.name}.la"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/.libs/lib${apr-util.lib.name}.dylib">
+ <available file="${apr-util.dir}/.libs/lib${apr-util.lib.name}.dylib"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/.libs/lib${apr-util.lib.name}.so">
+ <available file="${apr-util.dir}/.libs/lib${apr-util.lib.name}.so"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/.libs/lib${apr-util.lib.name}.a">
+ <available file="${apr-util.dir}/.libs/lib${apr-util.lib.name}.a"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/.libs/${apr-util.lib.name}.lib">
+ <available file="${apr-util.dir}/.libs/${apr-util.lib.name}.lib"/></condition>
+ <condition property="apr-util.lib.file.dir" value="${apr-util.dir}/.libs">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+
+ <!-- start looking at candidates in /usr -->
+ <condition property="apr-util.lib.file"
+ value="/usr/lib/lib${apr-util.lib.name}.la">
+ <available file="/usr/lib/lib${apr-util.lib.name}.la"/></condition>
+ <condition property="apr-util.lib.file"
+ value="/usr/lib/lib${apr-util.lib.name}.dylib">
+ <available file="/usr/lib/lib${apr-util.lib.name}.dylib"/></condition>
+ <condition property="apr-util.lib.file"
+ value="/usr/lib/lib${apr-util.lib.name}.so">
+ <available file="/usr/lib/lib${apr-util.lib.name}.so"/></condition>
+ <condition property="apr-util.lib.file"
+ value="/usr/lib/lib${apr-util.lib.name}.a">
+ <available file="/usr/lib/lib${apr-util.lib.name}.a"/></condition>
+ <condition property="apr-util.dir" value="/usr">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+ <condition property="apr-util.lib.file.dir" value="/usr/lib">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+
+ <!-- start looking at candidates in /usr/local -->
+ <condition property="apr-util.lib.file"
+ value="/usr/local/lib/lib${apr-util.lib.name}.la">
+ <available file="/usr/local/lib/lib${apr-util.lib.name}.la"/></condition>
+ <condition property="apr-util.lib.file"
+ value="/usr/local/lib/lib${apr-util.lib.name}.dylib">
+ <available file="/usr/local/lib/lib${apr-util.lib.name}.dylib"/></condition>
+ <condition property="apr-util.lib.file"
+ value="/usr/local/lib/lib${apr-util.lib.name}.so">
+ <available file="/usr/local/lib/lib${apr-util.lib.name}.so"/></condition>
+ <condition property="apr-util.lib.file"
+ value="/usr/local/lib/lib${apr-util.lib.name}.a">
+ <available file="/usr/local/lib/lib${apr-util.lib.name}.a"/></condition>
+ <condition property="apr-util.dir" value="/usr/local">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+ <condition property="apr-util.lib.file.dir" value="/usr/local/lib">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+
+
+ <property name="relative-apr-util" location="../apr-util"/>
+ <condition property="apr-util.dir" value="${relative-apr-util}">
+ <available file="${relative-apr-util}"/>
+ </condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/lib${apr-util.lib.name}.la">
+ <available file="${apr-util.dir}/lib${apr-util.lib.name}.la"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/lib${apr-util.lib.name}.dylib">
+ <available file="${apr-util.dir}/lib${apr-util.lib.name}.dylib"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/lib${apr-util.lib.name}.so">
+ <available file="${apr-util.dir}/lib${apr-util.lib.name}.so"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/lib${apr-util.lib.name}.a">
+ <available file="${apr-util.dir}/lib${apr-util.lib.name}.a"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/${apr-util.lib.name}.lib">
+ <available file="${apr-util.dir}/${apr-util.lib.name}.lib"/></condition>
+ <condition property="apr-util.lib.file.dir" value="${apr-util.dir}">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/.libs/lib${apr-util.lib.name}.la">
+ <available file="${apr-util.dir}/.libs/lib${apr-util.lib.name}.la"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/.libs/lib${apr-util.lib.name}.dylib">
+ <available file="${apr-util.dir}/.libs/lib${apr-util.lib.name}.dylib"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/.libs/lib${apr-util.lib.name}.so">
+ <available file="${apr-util.dir}/.libs/lib${apr-util.lib.name}.so"/></condition>
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/.libs/lib${apr-util.lib.name}.a">
+ <available file="${apr-util.dir}/.libs/lib${apr-util.lib.name}.a"/></condition>
+ <condition property="apr-util.lib.file.dir" value="${apr-util.dir}/.libs">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+ <fail unless="apr-util.dir">Unable to locate apr-util base directory.</fail>
+
+
+
+
+ <!-- Static debug libraries in APR's VC6 projects typical location (ignored unless debug build) -->
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/LibD/${apr-util.lib.name}.lib">
+ <and>
+ <isset property="is-debug"/>
+ <available file="${apr-util.dir}/LibD/${apr-util.lib.name}.lib"/>
+ </and>
+ </condition>
+ <condition property="apr-util.lib.file.dir"
+ value="${apr-util.dir}/LibD">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+
+
+
+
+ <!-- Shared debug libraries in APR's VC6 projects typical location (ignored unless debug build) -->
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/Debug/lib${apr-util.lib.name}.lib">
+ <and>
+ <isset property="is-debug"/>
+ <available file="${apr-util.dir}/Debug/lib${apr-util.lib.name}.lib"/>
+ </and>
+ </condition>
+ <condition property="apr-util.lib.file.dir"
+ value="${apr-util.dir}/Debug">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+
+
+
+ <!-- Static release libraries in APR's VC6 projects typical location (ignored unless debug build) -->
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/LibR/${apr-util.lib.name}.lib">
+ <available file="${apr-util.dir}/LibR/${apr-util.lib.name}.lib"/>
+ </condition>
+ <condition property="apr-util.lib.file.dir"
+ value="${apr-util.dir}/LibR">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+
+
+
+
+ <!-- Shared release libraries in APR's VC6 projects typical location -->
+ <condition property="apr-util.lib.file"
+ value="${apr-util.dir}/Release/lib${apr-util.lib.name}.lib">
+ <available file="${apr-util.dir}/Release/lib${apr-util.lib.name}.lib"/>
+ </condition>
+ <condition property="apr-util.lib.file.dir"
+ value="${apr-util.dir}/Release">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+
+
+
+ <condition property="apr-util.lib.dir" value="${apr-util.lib.file.dir}">
+ <and>
+ <isset property="apr-util.lib.file.dir"/>
+ <not>
+ <or>
+ <!-- default search path -->
+ <equals arg1="${apr-util.lib.file.dir}" arg2="/usr"/>
+ </or>
+ </not>
+ </and>
+ </condition>
+
+ <condition property="apr-util.lib.suffix" value="d">
+ <or>
+ <contains string="${apr-util.lib.file}" substring="/lib${apr-util.lib.name}d."/>
+ <contains string="${apr-util.lib.file}" substring="/${apr-util.lib.name}d."/>
+ </or>
+ </condition>
+ <condition property="apr-util.lib.suffix" value="D">
+ <or>
+ <contains string="${apr-util.lib.file}" substring="/lib${apr-util.lib.name}D."/>
+ <contains string="${apr-util.lib.file}" substring="/${apr-util.lib.name}D."/>
+ </or>
+ </condition>
+ <condition property="apr-util.lib.suffix" value="">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+
+ <condition property="apr-util.lib.prefix" value="lib">
+ <or>
+ <contains string="[${apr-util.lib.file}]" substring="/lib${apr-util.lib.name}.lib]"/>
+ </or>
+ </condition>
+ <condition property="apr-util.lib.prefix" value="">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+
+ <condition property="apr-util.lib.type" value="shared">
+ <or>
+ <contains string="${apr-util.lib.file}]"
+ substring=".dylib]"
+ casesensitive="no"/>
+ <contains string="${apr-util.lib.file}]"
+ substring=".so]"
+ casesensitive="no"/>
+ <contains string="${apr-util.lib.file}]"
+ substring=".la]"
+ casesensitive="no"/>
+ <and>
+ <!-- if we have just a .lib, guess based on file size.
+ Import libs should be much smaller. -->
+ <contains string="${apr-util.lib.file}]"
+ substring=".lib]"
+ casesensitive="no"/>
+ <isfileselected file="${apr-util.lib.file}">
+ <size value="250000" when="less"/>
+ </isfileselected>
+ </and>
+ </or>
+ </condition>
+
+
+ <condition property="apr-util.lib.type" value="static">
+ <isset property="apr-util.lib.file"/>
+ </condition>
+</target>
+
+<target name="find-apr-util" depends="find-apr-util-lib">
+ <!-- use character ref to prevent directory name from
+ being changed on global search and replacements -->
+ <condition property="apr-util.include.dir" value="${apr-util.dir}/include/ap&#x72;-1.0">
+ <available file="${apr-util.dir}/include/ap&#x72;-1.0/${apr-util.sample.h}"/>
+ </condition>
+ <condition property="apr-util.include.dir" value="${apr-util.dir}/include/ap&#x72;-1">
+ <available file="${apr-util.dir}/include/ap&#x72;-1/${apr-util.sample.h}"/>
+ </condition>
+ <condition property="apr-util.include.dir" value="${apr-util.dir}/include">
+ <available file="${apr-util.dir}/include/${apr-util.sample.h}"/>
+ </condition>
+ <condition property="apr-util.include.dir" value="${apr-util.dir}/../usr/include/ap&#x72;-1">
+ <available file="${apr-util.dir}/../usr/include/ap&#x72;-1/${apr-util.sample.h}"/>
+ </condition>
+ <condition property="apr-util.include.dir" value="${apr-util.src.dir}/include">
+ <available file="${apr-util.src.dir}/include/${apr-util.sample.h}"/>
+ </condition>
+
+ <condition property="apr-util.dir" value="${apr-util.src.dir}">
+ <isset property="apr-util.src.dir"/>
+ </condition>
+
+
+ <echo>apr-util-find:
+apr-util.dir=${apr-util.dir}
+apr-util.include.dir=${apr-util.include.dir}
+apr-util.src.dir=${apr-util.src.dir}
+apr-util.lib.file=${apr-util.lib.file}
+apr-util.lib.file.dir=${apr-util.lib.file.dir}
+apr-util.lib.dir=${apr-util.lib.dir}
+apr-util.lib.prefix=${apr-util.lib.prefix}
+apr-util.lib.suffix=${apr-util.lib.suffix}
+apr-util.lib.type=${apr-util.lib.type}
+</echo>
+</target>
diff --git a/src/ant/find-apr.xml b/src/ant/find-apr.xml
new file mode 100644
index 0000000..4561c69
--- /dev/null
+++ b/src/ant/find-apr.xml
@@ -0,0 +1,313 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<target name="find-apr-src" depends="init">
+ <condition property="apr.dir" value="${with-apr}">
+ <available file="${with-apr}"/>
+ </condition>
+ <condition property="apr.src.dir" value="${apr.dir}">
+ <available file="${apr.dir}/${apr.sample.c}"/>
+ </condition>
+ <condition property="apr.src.dir" value="../apr">
+ <available file="../apr/${apr.sample.c}"/>
+ </condition>
+</target>
+
+
+<target name="find-apr-lib" depends="find-apr-src" unless="force-ant">
+ <condition property="apr.lib.file"
+ value="${apr.dir}/lib${apr.lib.name}.la">
+ <available file="${apr.dir}/lib${apr.lib.name}.la"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/lib${apr.lib.name}.dylib">
+ <available file="${apr.dir}/lib${apr.lib.name}.dylib"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/lib${apr.lib.name}.so">
+ <available file="${apr.dir}/lib${apr.lib.name}.so"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/lib${apr.lib.name}.a">
+ <available file="${apr.dir}/lib${apr.lib.name}.a"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/${apr.lib.name}.lib">
+ <available file="${apr.dir}/${apr.lib.name}.lib"/></condition>
+ <condition property="apr.lib.file.dir" value="${apr.dir}">
+ <isset property="apr.lib.file"/>
+ </condition>
+
+ <condition property="apr.lib.file"
+ value="${apr.dir}/.libs/lib${apr.lib.name}.la">
+ <available file="${apr.dir}/.libs/lib${apr.lib.name}.la"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/.libs/lib${apr.lib.name}.dylib">
+ <available file="${apr.dir}/.libs/lib${apr.lib.name}.dylib"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/.libs/lib${apr.lib.name}.so">
+ <available file="${apr.dir}/.libs/lib${apr.lib.name}.so"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/.libs/lib${apr.lib.name}.a">
+ <available file="${apr.dir}/.libs/lib${apr.lib.name}.a"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/.libs/${apr.lib.name}.lib">
+ <available file="${apr.dir}/.libs/${apr.lib.name}.lib"/></condition>
+ <condition property="apr.lib.file.dir" value="${apr.dir}/.libs">
+ <isset property="apr.lib.file"/>
+ </condition>
+
+ <!-- start looking at candidates in /usr -->
+ <condition property="apr.lib.file"
+ value="/usr/lib/lib${apr.lib.name}.la">
+ <available file="/usr/lib/lib${apr.lib.name}.la"/></condition>
+ <condition property="apr.lib.file"
+ value="/usr/lib/lib${apr.lib.name}.dylib">
+ <available file="/usr/lib/lib${apr.lib.name}.dylib"/></condition>
+ <condition property="apr.lib.file"
+ value="/usr/lib/lib${apr.lib.name}.so">
+ <available file="/usr/lib/lib${apr.lib.name}.so"/></condition>
+ <condition property="apr.lib.file"
+ value="/usr/lib/lib${apr.lib.name}.a">
+ <available file="/usr/lib/lib${apr.lib.name}.a"/></condition>
+ <condition property="apr.dir" value="/usr">
+ <isset property="apr.lib.file"/>
+ </condition>
+ <condition property="apr.lib.file.dir" value="/usr/lib">
+ <isset property="apr.lib.file"/>
+ </condition>
+
+ <!-- start looking at candidates in /usr/local -->
+ <condition property="apr.lib.file"
+ value="/usr/local/lib/lib${apr.lib.name}.la">
+ <available file="/usr/local/lib/lib${apr.lib.name}.la"/></condition>
+ <condition property="apr.lib.file"
+ value="/usr/local/lib/lib${apr.lib.name}.dylib">
+ <available file="/usr/local/lib/lib${apr.lib.name}.dylib"/></condition>
+ <condition property="apr.lib.file"
+ value="/usr/local/lib/lib${apr.lib.name}.so">
+ <available file="/usr/local/lib/lib${apr.lib.name}.so"/></condition>
+ <condition property="apr.lib.file"
+ value="/usr/local/lib/lib${apr.lib.name}.a">
+ <available file="/usr/local/lib/lib${apr.lib.name}.a"/></condition>
+ <condition property="apr.dir" value="/usr/local">
+ <isset property="apr.lib.file"/>
+ </condition>
+ <condition property="apr.lib.file.dir" value="/usr/local/lib">
+ <isset property="apr.lib.file"/>
+ </condition>
+
+
+ <property name="relative-apr" location="../apr"/>
+ <condition property="apr.dir" value="${relative-apr}">
+ <available file="${relative-apr}"/>
+ </condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/lib${apr.lib.name}.la">
+ <available file="${apr.dir}/lib${apr.lib.name}.la"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/lib${apr.lib.name}.dylib">
+ <available file="${apr.dir}/lib${apr.lib.name}.dylib"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/lib${apr.lib.name}.so">
+ <available file="${apr.dir}/lib${apr.lib.name}.so"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/lib${apr.lib.name}.a">
+ <available file="${apr.dir}/lib${apr.lib.name}.a"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/${apr.lib.name}.lib">
+ <available file="${apr.dir}/${apr.lib.name}.lib"/></condition>
+ <condition property="apr.lib.file.dir" value="${apr.dir}">
+ <isset property="apr.lib.file"/>
+ </condition>
+
+ <condition property="apr.lib.file"
+ value="${apr.dir}/.libs/lib${apr.lib.name}.la">
+ <available file="${apr.dir}/.libs/lib${apr.lib.name}.la"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/.libs/lib${apr.lib.name}.dylib">
+ <available file="${apr.dir}/.libs/lib${apr.lib.name}.dylib"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/.libs/lib${apr.lib.name}.so">
+ <available file="${apr.dir}/.libs/lib${apr.lib.name}.so"/></condition>
+ <condition property="apr.lib.file"
+ value="${apr.dir}/.libs/lib${apr.lib.name}.a">
+ <available file="${apr.dir}/.libs/lib${apr.lib.name}.a"/></condition>
+ <condition property="apr.lib.file.dir" value="${apr.dir}/.libs">
+ <isset property="apr.lib.file"/>
+ </condition>
+ <fail unless="apr.dir">Unable to locate apr base directory.</fail>
+
+
+
+
+ <!-- Static debug libraries in APR's VC6 projects typical location (ignored unless debug build) -->
+ <condition property="apr.lib.file"
+ value="${apr.dir}/LibD/${apr.lib.name}.lib">
+ <and>
+ <isset property="is-debug"/>
+ <available file="${apr.dir}/LibD/${apr.lib.name}.lib"/>
+ </and>
+ </condition>
+ <condition property="apr.lib.file.dir"
+ value="${apr.dir}/LibD">
+ <isset property="apr.lib.file"/>
+ </condition>
+
+
+
+
+ <!-- Shared debug libraries in APR's VC6 projects typical location (ignored unless debug build) -->
+ <condition property="apr.lib.file"
+ value="${apr.dir}/Debug/lib${apr.lib.name}.lib">
+ <and>
+ <isset property="is-debug"/>
+ <available file="${apr.dir}/Debug/lib${apr.lib.name}.lib"/>
+ </and>
+ </condition>
+ <condition property="apr.lib.file.dir"
+ value="${apr.dir}/Debug">
+ <isset property="apr.lib.file"/>
+ </condition>
+
+
+
+ <!-- Static release libraries in APR's VC6 projects typical location (ignored unless debug build) -->
+ <condition property="apr.lib.file"
+ value="${apr.dir}/LibR/${apr.lib.name}.lib">
+ <available file="${apr.dir}/LibR/${apr.lib.name}.lib"/>
+ </condition>
+ <condition property="apr.lib.file.dir"
+ value="${apr.dir}/LibR">
+ <isset property="apr.lib.file"/>
+ </condition>
+
+
+
+
+ <!-- Shared release libraries in APR's VC6 projects typical location -->
+ <condition property="apr.lib.file"
+ value="${apr.dir}/Release/lib${apr.lib.name}.lib">
+ <available file="${apr.dir}/Release/lib${apr.lib.name}.lib"/>
+ </condition>
+ <condition property="apr.lib.file.dir"
+ value="${apr.dir}/Release">
+ <isset property="apr.lib.file"/>
+ </condition>
+
+
+
+ <condition property="apr.lib.dir" value="${apr.lib.file.dir}">
+ <and>
+ <isset property="apr.lib.file.dir"/>
+ <not>
+ <or>
+ <!-- default search path -->
+ <equals arg1="${apr.lib.file.dir}" arg2="/usr"/>
+ </or>
+ </not>
+ </and>
+ </condition>
+
+ <condition property="apr.lib.suffix" value="d">
+ <or>
+ <contains string="${apr.lib.file}" substring="/lib${apr.lib.name}d."/>
+ <contains string="${apr.lib.file}" substring="/${apr.lib.name}d."/>
+ </or>
+ </condition>
+ <condition property="apr.lib.suffix" value="D">
+ <or>
+ <contains string="${apr.lib.file}" substring="/lib${apr.lib.name}D."/>
+ <contains string="${apr.lib.file}" substring="/${apr.lib.name}D."/>
+ </or>
+ </condition>
+ <condition property="apr.lib.suffix" value="">
+ <isset property="apr.lib.file"/>
+ </condition>
+
+ <condition property="apr.lib.prefix" value="lib">
+ <or>
+ <contains string="[${apr.lib.file}]" substring="/lib${apr.lib.name}.lib]"/>
+ </or>
+ </condition>
+ <condition property="apr.lib.prefix" value="">
+ <isset property="apr.lib.file"/>
+ </condition>
+
+ <condition property="apr.lib.type" value="shared">
+ <or>
+ <contains string="${apr.lib.file}]"
+ substring=".dylib]"
+ casesensitive="no"/>
+ <contains string="${apr.lib.file}]"
+ substring=".so]"
+ casesensitive="no"/>
+ <contains string="${apr.lib.file}]"
+ substring=".la]"
+ casesensitive="no"/>
+ <and>
+ <!-- if we have just a .lib, guess based on file size.
+ Import libs should be much smaller. -->
+ <contains string="${apr.lib.file}]"
+ substring=".lib]"
+ casesensitive="no"/>
+ <isfileselected file="${apr.lib.file}">
+ <size value="250000" when="less"/>
+ </isfileselected>
+ </and>
+ </or>
+ </condition>
+
+
+ <condition property="apr.lib.type" value="static">
+ <isset property="apr.lib.file"/>
+ </condition>
+</target>
+
+<target name="find-apr" depends="find-apr-lib">
+ <!-- use character ref to prevent directory name from
+ being changed on global search and replacements -->
+ <condition property="apr.include.dir" value="${apr.dir}/include/ap&#x72;-1.0">
+ <available file="${apr.dir}/include/ap&#x72;-1.0/${apr.sample.h}"/>
+ </condition>
+ <condition property="apr.include.dir" value="${apr.dir}/include/ap&#x72;-1">
+ <available file="${apr.dir}/include/ap&#x72;-1/${apr.sample.h}"/>
+ </condition>
+ <condition property="apr.include.dir" value="${apr.dir}/include">
+ <available file="${apr.dir}/include/${apr.sample.h}"/>
+ </condition>
+ <condition property="apr.include.dir" value="${apr.dir}/../usr/include/ap&#x72;-1">
+ <available file="${apr.dir}/../usr/include/ap&#x72;-1/${apr.sample.h}"/>
+ </condition>
+ <condition property="apr.include.dir" value="${apr.src.dir}/include">
+ <available file="${apr.src.dir}/include/${apr.sample.h}"/>
+ </condition>
+
+ <condition property="apr.dir" value="${apr.src.dir}">
+ <isset property="apr.src.dir"/>
+ </condition>
+
+
+ <echo>apr-find:
+apr.dir=${apr.dir}
+apr.include.dir=${apr.include.dir}
+apr.src.dir=${apr.src.dir}
+apr.lib.file=${apr.lib.file}
+apr.lib.file.dir=${apr.lib.file.dir}
+apr.lib.dir=${apr.lib.dir}
+apr.lib.prefix=${apr.lib.prefix}
+apr.lib.suffix=${apr.lib.suffix}
+apr.lib.type=${apr.lib.type}
+</echo>
+</target>
diff --git a/src/ant/find-libesmtp.xml b/src/ant/find-libesmtp.xml
new file mode 100644
index 0000000..2c516e2
--- /dev/null
+++ b/src/ant/find-libesmtp.xml
@@ -0,0 +1,313 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<target name="find-esmtp-src" depends="init">
+ <condition property="esmtp.dir" value="${with-libesmtp}">
+ <available file="${with-libesmtp}"/>
+ </condition>
+ <condition property="esmtp.src.dir" value="${esmtp.dir}">
+ <available file="${esmtp.dir}/${esmtp.sample.c}"/>
+ </condition>
+ <condition property="esmtp.src.dir" value="../libesmtp">
+ <available file="../libesmtp/${esmtp.sample.c}"/>
+ </condition>
+</target>
+
+
+<target name="find-esmtp-lib" depends="find-esmtp-src" if="has-libesmtp" unless="force-ant">
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/lib${esmtp.lib.name}.la">
+ <available file="${esmtp.dir}/lib${esmtp.lib.name}.la"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/lib${esmtp.lib.name}.dylib">
+ <available file="${esmtp.dir}/lib${esmtp.lib.name}.dylib"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/lib${esmtp.lib.name}.so">
+ <available file="${esmtp.dir}/lib${esmtp.lib.name}.so"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/lib${esmtp.lib.name}.a">
+ <available file="${esmtp.dir}/lib${esmtp.lib.name}.a"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/${esmtp.lib.name}.lib">
+ <available file="${esmtp.dir}/${esmtp.lib.name}.lib"/></condition>
+ <condition property="esmtp.lib.file.dir" value="${esmtp.dir}">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/.libs/lib${esmtp.lib.name}.la">
+ <available file="${esmtp.dir}/.libs/lib${esmtp.lib.name}.la"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/.libs/lib${esmtp.lib.name}.dylib">
+ <available file="${esmtp.dir}/.libs/lib${esmtp.lib.name}.dylib"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/.libs/lib${esmtp.lib.name}.so">
+ <available file="${esmtp.dir}/.libs/lib${esmtp.lib.name}.so"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/.libs/lib${esmtp.lib.name}.a">
+ <available file="${esmtp.dir}/.libs/lib${esmtp.lib.name}.a"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/.libs/${esmtp.lib.name}.lib">
+ <available file="${esmtp.dir}/.libs/${esmtp.lib.name}.lib"/></condition>
+ <condition property="esmtp.lib.file.dir" value="${esmtp.dir}/.libs">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+
+ <!-- start looking at candidates in /usr -->
+ <condition property="esmtp.lib.file"
+ value="/usr/lib/lib${esmtp.lib.name}.la">
+ <available file="/usr/lib/lib${esmtp.lib.name}.la"/></condition>
+ <condition property="esmtp.lib.file"
+ value="/usr/lib/lib${esmtp.lib.name}.dylib">
+ <available file="/usr/lib/lib${esmtp.lib.name}.dylib"/></condition>
+ <condition property="esmtp.lib.file"
+ value="/usr/lib/lib${esmtp.lib.name}.so">
+ <available file="/usr/lib/lib${esmtp.lib.name}.so"/></condition>
+ <condition property="esmtp.lib.file"
+ value="/usr/lib/lib${esmtp.lib.name}.a">
+ <available file="/usr/lib/lib${esmtp.lib.name}.a"/></condition>
+ <condition property="esmtp.dir" value="/usr">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+ <condition property="esmtp.lib.file.dir" value="/usr/lib">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+
+ <!-- start looking at candidates in /usr/local -->
+ <condition property="esmtp.lib.file"
+ value="/usr/local/lib/lib${esmtp.lib.name}.la">
+ <available file="/usr/local/lib/lib${esmtp.lib.name}.la"/></condition>
+ <condition property="esmtp.lib.file"
+ value="/usr/local/lib/lib${esmtp.lib.name}.dylib">
+ <available file="/usr/local/lib/lib${esmtp.lib.name}.dylib"/></condition>
+ <condition property="esmtp.lib.file"
+ value="/usr/local/lib/lib${esmtp.lib.name}.so">
+ <available file="/usr/local/lib/lib${esmtp.lib.name}.so"/></condition>
+ <condition property="esmtp.lib.file"
+ value="/usr/local/lib/lib${esmtp.lib.name}.a">
+ <available file="/usr/local/lib/lib${esmtp.lib.name}.a"/></condition>
+ <condition property="esmtp.dir" value="/usr/local">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+ <condition property="esmtp.lib.file.dir" value="/usr/local/lib">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+
+
+ <property name="relative-esmtp" location="../libesmtp"/>
+ <condition property="esmtp.dir" value="${relative-esmtp}">
+ <available file="${relative-esmtp}"/>
+ </condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/lib${esmtp.lib.name}.la">
+ <available file="${esmtp.dir}/lib${esmtp.lib.name}.la"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/lib${esmtp.lib.name}.dylib">
+ <available file="${esmtp.dir}/lib${esmtp.lib.name}.dylib"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/lib${esmtp.lib.name}.so">
+ <available file="${esmtp.dir}/lib${esmtp.lib.name}.so"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/lib${esmtp.lib.name}.a">
+ <available file="${esmtp.dir}/lib${esmtp.lib.name}.a"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/${esmtp.lib.name}.lib">
+ <available file="${esmtp.dir}/${esmtp.lib.name}.lib"/></condition>
+ <condition property="esmtp.lib.file.dir" value="${esmtp.dir}">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/.libs/lib${esmtp.lib.name}.la">
+ <available file="${esmtp.dir}/.libs/lib${esmtp.lib.name}.la"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/.libs/lib${esmtp.lib.name}.dylib">
+ <available file="${esmtp.dir}/.libs/lib${esmtp.lib.name}.dylib"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/.libs/lib${esmtp.lib.name}.so">
+ <available file="${esmtp.dir}/.libs/lib${esmtp.lib.name}.so"/></condition>
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/.libs/lib${esmtp.lib.name}.a">
+ <available file="${esmtp.dir}/.libs/lib${esmtp.lib.name}.a"/></condition>
+ <condition property="esmtp.lib.file.dir" value="${esmtp.dir}/.libs">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+ <fail unless="esmtp.dir">Unable to locate esmtp base directory.</fail>
+
+
+
+
+ <!-- Static debug libraries in APR's VC6 projects typical location (ignored unless debug build) -->
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/LibD/${esmtp.lib.name}.lib">
+ <and>
+ <isset property="is-debug"/>
+ <available file="${esmtp.dir}/LibD/${esmtp.lib.name}.lib"/>
+ </and>
+ </condition>
+ <condition property="esmtp.lib.file.dir"
+ value="${esmtp.dir}/LibD">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+
+
+
+
+ <!-- Shared debug libraries in APR's VC6 projects typical location (ignored unless debug build) -->
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/Debug/lib${esmtp.lib.name}.lib">
+ <and>
+ <isset property="is-debug"/>
+ <available file="${esmtp.dir}/Debug/lib${esmtp.lib.name}.lib"/>
+ </and>
+ </condition>
+ <condition property="esmtp.lib.file.dir"
+ value="${esmtp.dir}/Debug">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+
+
+
+ <!-- Static release libraries in APR's VC6 projects typical location (ignored unless debug build) -->
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/LibR/${esmtp.lib.name}.lib">
+ <available file="${esmtp.dir}/LibR/${esmtp.lib.name}.lib"/>
+ </condition>
+ <condition property="esmtp.lib.file.dir"
+ value="${esmtp.dir}/LibR">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+
+
+
+
+ <!-- Shared release libraries in APR's VC6 projects typical location -->
+ <condition property="esmtp.lib.file"
+ value="${esmtp.dir}/Release/lib${esmtp.lib.name}.lib">
+ <available file="${esmtp.dir}/Release/lib${esmtp.lib.name}.lib"/>
+ </condition>
+ <condition property="esmtp.lib.file.dir"
+ value="${esmtp.dir}/Release">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+
+
+
+ <condition property="esmtp.lib.dir" value="${esmtp.lib.file.dir}">
+ <and>
+ <isset property="esmtp.lib.file.dir"/>
+ <not>
+ <or>
+ <!-- default search path -->
+ <equals arg1="${esmtp.lib.file.dir}" arg2="/usr"/>
+ </or>
+ </not>
+ </and>
+ </condition>
+
+ <condition property="esmtp.lib.suffix" value="d">
+ <or>
+ <contains string="${esmtp.lib.file}" substring="/lib${esmtp.lib.name}d."/>
+ <contains string="${esmtp.lib.file}" substring="/${esmtp.lib.name}d."/>
+ </or>
+ </condition>
+ <condition property="esmtp.lib.suffix" value="D">
+ <or>
+ <contains string="${esmtp.lib.file}" substring="/lib${esmtp.lib.name}D."/>
+ <contains string="${esmtp.lib.file}" substring="/${esmtp.lib.name}D."/>
+ </or>
+ </condition>
+ <condition property="esmtp.lib.suffix" value="">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+
+ <condition property="esmtp.lib.prefix" value="lib">
+ <or>
+ <contains string="[${esmtp.lib.file}]" substring="/lib${esmtp.lib.name}.lib]"/>
+ </or>
+ </condition>
+ <condition property="esmtp.lib.prefix" value="">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+
+ <condition property="esmtp.lib.type" value="shared">
+ <or>
+ <contains string="${esmtp.lib.file}]"
+ substring=".dylib]"
+ casesensitive="no"/>
+ <contains string="${esmtp.lib.file}]"
+ substring=".so]"
+ casesensitive="no"/>
+ <contains string="${esmtp.lib.file}]"
+ substring=".la]"
+ casesensitive="no"/>
+ <and>
+ <!-- if we have just a .lib, guess based on file size.
+ Import libs should be much smaller. -->
+ <contains string="${esmtp.lib.file}]"
+ substring=".lib]"
+ casesensitive="no"/>
+ <isfileselected file="${esmtp.lib.file}">
+ <size value="250000" when="less"/>
+ </isfileselected>
+ </and>
+ </or>
+ </condition>
+
+
+ <condition property="esmtp.lib.type" value="static">
+ <isset property="esmtp.lib.file"/>
+ </condition>
+</target>
+
+<target name="find-esmtp" depends="find-esmtp-lib">
+ <!-- use character ref to prevent directory name from
+ being changed on global search and replacements -->
+ <condition property="esmtp.include.dir" value="${esmtp.dir}/include">
+ <available file="${esmtp.dir}/include/${esmtp.sample.h}"/>
+ </condition>
+ <condition property="esmtp.include.dir" value="${esmtp.dir}">
+ <available file="${esmtp.dir}/${esmtp.sample.h}"/>
+ </condition>
+ <condition property="esmtp.include.dir" value="${esmtp.dir}/../usr/include">
+ <available file="${esmtp.dir}/../usr/include/${esmtp.sample.h}"/>
+ </condition>
+ <condition property="esmtp.include.dir" value="${esmtp.src.dir}/include">
+ <available file="${esmtp.src.dir}/include/${esmtp.sample.h}"/>
+ </condition>
+ <condition property="esmtp.include.dir" value="${esmtp.src.dir}">
+ <available file="${esmtp.src.dir}/include/${esmtp.sample.h}"/>
+ </condition>
+
+ <condition property="esmtp.dir" value="${esmtp.src.dir}">
+ <isset property="esmtp.src.dir"/>
+ </condition>
+
+
+ <echo>esmtp-find:
+esmtp.dir=${esmtp.dir}
+esmtp.include.dir=${esmtp.include.dir}
+esmtp.src.dir=${esmtp.src.dir}
+esmtp.lib.file=${esmtp.lib.file}
+esmtp.lib.file.dir=${esmtp.lib.file.dir}
+esmtp.lib.dir=${esmtp.lib.dir}
+esmtp.lib.prefix=${esmtp.lib.prefix}
+esmtp.lib.suffix=${esmtp.lib.suffix}
+esmtp.lib.type=${esmtp.lib.type}
+</echo>
+</target> \ No newline at end of file
diff --git a/src/assembly/source.xml b/src/assembly/source.xml
new file mode 100644
index 0000000..8c551ad
--- /dev/null
+++ b/src/assembly/source.xml
@@ -0,0 +1,99 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<assembly>
+ <id>source</id>
+ <formats>
+ <format>zip</format>
+ <format>tar.gz</format>
+ </formats>
+ <baseDirectory>apache-log4cxx-${project.version}</baseDirectory>
+ <includeSiteDirectory>true</includeSiteDirectory>
+ <fileSets>
+ <!-- autogen.sh is executable -->
+ <fileSet>
+ <includes>
+ <include>autogen.sh</include>
+ <include>configure.bat</include>
+ <include>configure-aprutil.bat</include>
+ <include>configure</include>
+ <include>install-sh</include>
+ <include>missing</include>
+ <include>ltmain.sh</include>
+ <include>depcomp</include>
+ </includes>
+ <fileMode>0755</fileMode>
+ </fileSet>
+ <fileSet>
+ <includes>
+ <include>INSTALL</include>
+ <include>KEYS</include>
+ <include>LICENSE</include>
+ <include>Makefile.am</include>
+ <include>NOTICE</include>
+ <include>build.xml</include>
+ <include>configure.in</include>
+ <include>find_apr.m4</include>
+ <include>find_apu.m4</include>
+ <include>liblog4cxx.pc.in</include>
+ <include>pom.xml</include>
+ <include>Makefile.in</include>
+ <include>config.sub</include>
+ <include>config.guess</include>
+ <include>aclocal.m4</include>
+ <include>src/**</include>
+ </includes>
+ <excludes>
+ <exclude>src/main/include/log4cxx/log4cxx.h</exclude>
+ <exclude>src/main/include/log4cxx/private/log4cxx_private.h</exclude>
+ <exclude>src/test/cpp/testsuite</exclude>
+ <exclude>src/examples/cpp/console</exclude>
+ <exclude>src/examples/cpp/delayedloop</exclude>
+ <exclude>src/examples/cpp/stream</exclude>
+ <exclude>src/examples/cpp/trivial</exclude>
+ <exclude>**/Makefile</exclude>
+ <exclude>**/*.o</exclude>
+ <exclude>**/*.Po</exclude>
+ <exclude>**/*.lo</exclude>
+ <exclude>**/*.a</exclude>
+ <exclude>**/*.la</exclude>
+ <exclude>**/*.so</exclude>
+ <exclude>**/*.dylib</exclude>
+ <exclude>**/*.dll</exclude>
+ <exclude>**/Doxyfile</exclude>
+ <exclude>src/test/resources/output/**</exclude>
+ <exclude>**/.libs/**</exclude>
+ <exclude>**/.deps/**</exclude>
+ <exclude>**/.svn</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>target</directory>
+ <lineEnding>keep</lineEnding>
+ <outputDirectory>projects</outputDirectory>
+ <includes>
+ <include>*.dsw</include>
+ <include>*.dsp</include>
+ <include>*.xcodeproj/project.pbxproj</include>
+ </includes>
+ <excludes>
+ <exclude>apr*.ds*</exclude>
+ <exclude>xml.ds*</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/src/changes/Makefile.am b/src/changes/Makefile.am
new file mode 100644
index 0000000..8e6be87
--- /dev/null
+++ b/src/changes/Makefile.am
@@ -0,0 +1,15 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
new file mode 100644
index 0000000..7faa62b
--- /dev/null
+++ b/src/changes/changes.xml
@@ -0,0 +1,394 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ -->
+<document>
+<properties>
+<title>Apache log4cxx</title>
+</properties>
+<body>
+<release version="0.10.0" date="2008-04-03" description="First Apache release">
+<action issue="LOGCXX-2">logger.h includes config.h</action>
+<action issue="LOGCXX-3">Missing #else</action>
+<action issue="LOGCXX-4">initialization not working on many OS's</action>
+<action issue="LOGCXX-5">Preprocessor macro WIN32 used instead of _WIN32</action>
+<action issue="LOGCXX-6">Win32 OutputDebugString</action>
+<action issue="LOGCXX-7">SocketAppender binary format not compatible with Chainsaw</action>
+<action issue="LOGCXX-8">Compilation problems using VC5 or VC6 with later Platform SDKs</action>
+<action issue="LOGCXX-10">Conflicting definitions of tchar.h/simulatenous Unicode+MBCS</action>
+<action issue="LOGCXX-11">Timezone may have side-effects</action>
+<action issue="LOGCXX-12">the threshold of ApenderSkeleton can not be set by calling setOption.</action>
+<action issue="LOGCXX-13">Add branch optimization hint to LOG4CXX_DEBUG macro</action>
+<action issue="LOGCXX-14">add -Wall to compile log4cxx will get many warning</action>
+<action issue="LOGCXX-15">PatternLayout don't use locale time zone,it's use GMT tome zone</action>
+<action issue="LOGCXX-16">Misleading statements in Introduction to log4cxx</action>
+<action issue="LOGCXX-17">Use of non reentrant time functions</action>
+<action issue="LOGCXX-18">LoggerStream Feature</action>
+<action issue="LOGCXX-19">Add .cvsignore's to ignore generated files</action>
+<action issue="LOGCXX-21">Add check that libxml2 not libxml has been included</action>
+<action issue="LOGCXX-22">Backslashes in filenames in XML config of FileAppender broken</action>
+<action issue="LOGCXX-23">Unit tests have become stale</action>
+<action issue="LOGCXX-24">Class and module name not available in LogEvent</action>
+<action issue="LOGCXX-25">Add Ant+cpptasks build file</action>
+<action issue="LOGCXX-26">Default initialization is broken</action>
+<action issue="LOGCXX-27">Appender threshold cannot be set in configuration files</action>
+<action issue="LOGCXX-28">Appender threshold cannot be set in configuration files</action>
+<action issue="LOGCXX-29">Appender attributes are not passed passed to setOption correctly.</action>
+<action issue="LOGCXX-30">StringTokenizer uses evil strtok and wcstok functions</action>
+<action issue="LOGCXX-31">Missing const qualifiers, Exception::getMessage() in particular.</action>
+<action issue="LOGCXX-32">Missing copy constructors and assignment operators</action>
+<action issue="LOGCXX-33">log4cxx::Exception is not derived from std::exception</action>
+<action issue="LOGCXX-34">Visual Studio 6 CVS build broken</action>
+<action issue="LOGCXX-35">Avoid use of MSXML</action>
+<action issue="LOGCXX-36">Migrate to Apache Portable Runtime threads</action>
+<action issue="LOGCXX-37">Unable to build log4cxx under Borland C++</action>
+<action issue="LOGCXX-39">Remove DailyRollingFileAppender</action>
+<action issue="LOGCXX-40">PatternLayout does not support Java date format specifiers</action>
+<action issue="LOGCXX-41">Layout timestamp doesn't seem to adjust for daylight saving</action>
+<action issue="LOGCXX-43">configure/make help needed</action>
+<action issue="LOGCXX-44">GUMP integation</action>
+<action issue="LOGCXX-45">_T causes error : 1048576 cannot be used as a function</action>
+<action issue="LOGCXX-46">Extra semicolon after namespace closing paren</action>
+<action issue="LOGCXX-47">Check headers for missing declarations and Effective C++ violations</action>
+<action issue="LOGCXX-48">Use hex representation for thread identifier</action>
+<action issue="LOGCXX-49">Move timezone specification into pattern, remove locale specification</action>
+<action issue="LOGCXX-50">variable name clash in macro</action>
+<action issue="LOGCXX-52">Migrate log4j 1.3 RollingFileAppender</action>
+<action issue="LOGCXX-53">Problems compiling with MsDev 6.0 (space in paths)</action>
+<action issue="LOGCXX-54">Eliminate use of boost-regex in unit tests</action>
+<action issue="LOGCXX-55">DailyRolling File Appender</action>
+<action issue="LOGCXX-56">BasicConfiguration is unreliable</action>
+<action issue="LOGCXX-57">Port log4j performance test</action>
+<action issue="LOGCXX-58">ImmediateFlush'd FileAppenders extremely slow on Windows</action>
+<action issue="LOGCXX-59">Implement encoding support for Writer appender</action>
+<action issue="LOGCXX-60">XML layout can be mismatched with document encoding</action>
+<action issue="LOGCXX-62">log4cxx 0.10.0 release</action>
+<action issue="LOGCXX-63">Platform appropriate line-feed convention</action>
+<action issue="LOGCXX-64">Migrate to APR network IO</action>
+<action issue="LOGCXX-66">SyslogAppender append method currently stubbed out</action>
+<action issue="LOGCXX-67">NTEventLogAppender always uses RPC method for logging and has inadequate error handling.</action>
+<action issue="LOGCXX-70">Logic flaws in StringHelper::startsWith and StringHelper::endsWith</action>
+<action issue="LOGCXX-71">Update performance page on web site</action>
+<action issue="LOGCXX-72">INSTALL out of date</action>
+<action issue="LOGCXX-73">Not loading configuration from log4cxx.properties or log4cxx.xml</action>
+<action issue="LOGCXX-74">MinGW build</action>
+<action issue="LOGCXX-75">Cygwin build</action>
+<action issue="LOGCXX-76">user.home, user.dir, java.io.tmpdir available within configuration files</action>
+<action issue="LOGCXX-77">Static builds broken</action>
+<action issue="LOGCXX-79">configure check for apr-util</action>
+<action issue="LOGCXX-80">Migrated network appenders to APR network IO</action>
+<action issue="LOGCXX-81">SimpleDateFormat does not compile on Solaris 2.95.2 gcc</action>
+<action issue="LOGCXX-82">Compiling with stream.h in multiple object files errors</action>
+<action issue="LOGCXX-83">log4cxx::Level::ERROR fails to compile when GDI enabled</action>
+<action issue="LOGCXX-84">Problems with stream logging in UTF8, no WCHAR_T build</action>
+<action issue="LOGCXX-85">Mac OS/X fixes and enhancements</action>
+<action issue="LOGCXX-86">Add TRACE level</action>
+<action issue="LOGCXX-87">Remove remaining uses of Category and Priority</action>
+<action issue="LOGCXX-88">Explore use of security-enhanced CRT methods</action>
+<action issue="LOGCXX-94">simplesocketserver.cpp should use LOG4CXX_STR("...") not L"..."</action>
+<action issue="LOGCXX-98">Gump build fails for log4cxx-ant-no-wchar-t target</action>
+<action issue="LOGCXX-100">Fixes for ODBCAppender</action>
+<action issue="LOGCXX-103">Much of CVS HEAD seems #if 0 out, especially ResourceBundle stuff</action>
+<action issue="LOGCXX-104">ODBCAppender::close does not check if appender is already closed</action>
+<action issue="LOGCXX-105">Infinite loop in string replacing</action>
+<action issue="LOGCXX-106">maxFileSize has bad type in SizeBasedTriggeringPolicy file</action>
+<action issue="LOGCXX-107">Can't compile log4cxx in ascii on Windows</action>
+<action issue="LOGCXX-110">try fix 64bit log4cxx_intptr_t</action>
+<action issue="LOGCXX-111">make Logger cache a LoggerRepositoryPtr instead of a "blind" pointer</action>
+<action issue="LOGCXX-112">change "static" to "auto" for Transcoder::decode() decoder and CharsetDecoder::getDefaultDecoder() decoder</action>
+<action issue="LOGCXX-113">separate apr detection m4 codes from aclocal.m4</action>
+<action issue="LOGCXX-114">Upgrade APR to 1.2.2 from 1.1.0</action>
+<action issue="LOGCXX-115">SVN head does not compile with Borland C++ compiler</action>
+<action issue="LOGCXX-116">SVN head does not compiler with MinGW compiler</action>
+<action issue="LOGCXX-117">Memory leak with ThreadSpecificData on Win32</action>
+<action issue="LOGCXX-118">Hierarchy corrupts with PropertyConfigurator</action>
+<action issue="LOGCXX-119">ndctestcase not working</action>
+<action issue="LOGCXX-120">Wrong parameter description in Patternlayout</action>
+<action issue="LOGCXX-123">UTF-8 build fails on Linux</action>
+<action issue="LOGCXX-124">wchar_t constructor missing in class NDC</action>
+<action issue="LOGCXX-125">L7dTestCase is stubbed out</action>
+<action issue="LOGCXX-126">std::cout stops working if log4cxx is first to output</action>
+<action issue="LOGCXX-127">Main build.xml not referencing "env" properly.</action>
+<action issue="LOGCXX-129">Asyncappender is full of race conditions (improper use of condition variables)</action>
+<action issue="LOGCXX-130">Compile fails on gcc4.1</action>
+<action issue="LOGCXX-131">TimeBasedRollingPolicy is declared "abstract"</action>
+<action issue="LOGCXX-132">various segmentation faults in multithreaded application</action>
+<action issue="LOGCXX-133">Missing parenthesis in LOG4CXX_ASSERT</action>
+<action issue="LOGCXX-134">FileAppender could create missing directories</action>
+<action issue="LOGCXX-135">Use std::string with logstream</action>
+<action issue="LOGCXX-136">DailyRollingFileAppender not using Property options</action>
+<action issue="LOGCXX-138">XMLLayoutTestCase output and filtered output gets overwritten</action>
+<action issue="LOGCXX-139">XMLLayoutTestCase uses inadequate filters for 64 bit platforms</action>
+<action issue="LOGCXX-140">Handle leak with LoggingEvent::getCurrentThreadName</action>
+<action issue="LOGCXX-141">Upgrade to APR 1.2.7 or later</action>
+<action issue="LOGCXX-142">socketservertestcase.cpp does not compile with Sun Studio 11 on Solaris</action>
+<action issue="LOGCXX-143">-xarch=v8plus should be removed from Makefile.in</action>
+<action issue="LOGCXX-146">DailyRollingFileAppender::~DailyRollingFileAppender must call finalize</action>
+<action issue="LOGCXX-149">make dist does not work</action>
+<action issue="LOGCXX-150">logstream's operator&lt;&lt; declared in the wrong namespace</action>
+<action issue="LOGCXX-151">Umlauts as literal in patternlayout won't be logged correct</action>
+<action issue="LOGCXX-152">gcc warning about cast from `const void*' to `log4cxx::helpers::Object*' discards qualifiers from pointer target typ</action>
+<action issue="LOGCXX-153">Automate log4cxx site and doxygen generation and deployment</action>
+<action issue="LOGCXX-155">Update source headers per new ASF header policy</action>
+<action issue="LOGCXX-156">immediate flush in console appender</action>
+<action issue="LOGCXX-157">make install fails since @manual_dest@ replacement is missing in Makefiles</action>
+<action issue="LOGCXX-158">tolower not defined in stringhelper.cpp</action>
+<action issue="LOGCXX-159">Initialization of local static objects out of order on Linux</action>
+<action issue="LOGCXX-160">helpers/object.h: DECLARE_LOG4CXX_OBJECT macro definition is missing virtual destructor declaration</action>
+<action issue="LOGCXX-161">Using RollingFileAppender increases the working set with each rollover</action>
+<action issue="LOGCXX-162">Problem printing string with embedded NULL character</action>
+<action issue="LOGCXX-163">liblog4cxx (svn 480882) does not link on Mac OS X 10.4</action>
+<action issue="LOGCXX-164">XMLSocketAppender is disabled</action>
+<action issue="LOGCXX-165">XMLSocketAppender may generate erroneous output due to mismatched encoding</action>
+<action issue="LOGCXX-167">system locale charmap is not determined properly on Fedora Core 6</action>
+<action issue="LOGCXX-168">log4j.dtd does not contain rollingPolicy and other o.a.l.r.RFA elements</action>
+<action issue="LOGCXX-169">XMLLayoutTestCase fails on compilers that do not provide location info</action>
+<action issue="LOGCXX-171">Add project description file for projects.apache.org</action>
+<action issue="LOGCXX-172">configure fail with ".infig.status: error: cannot find input file:"</action>
+<action issue="LOGCXX-175">APRCharsetEncoder is not thread safe</action>
+<action issue="LOGCXX-177">SocketImpl::accept uses private APR function: apr_wait_for_io_or_timeout</action>
+<action issue="LOGCXX-178">Link failure if wchar_t cannot be determined as UTF-16 or UTF-32</action>
+<action issue="LOGCXX-179">example applications do SIGABRT on aix 5.2</action>
+<action issue="LOGCXX-180">Build fails at domconfigurator.h</action>
+<action issue="LOGCXX-181">Level::DEBUG and other non-local statics cause crash on app shutdown on AIX</action>
+<action issue="LOGCXX-182">missing man page for simplesocketserver</action>
+<action issue="LOGCXX-183">Compiler warning: dereferencing type-punned pointer will break strict-aliasing rules</action>
+<action issue="LOGCXX-184">Crash when log level set to 'inherited'</action>
+<action issue="LOGCXX-186">Garbage characters in log files when log requests from multiple threads with hyperthreading enabled</action>
+<action issue="LOGCXX-187">LogLog::emit() could potentially interleave messages</action>
+<action issue="LOGCXX-188">Upgrade to apr 1.2.9 and apr-util 1.2.8</action>
+<action issue="LOGCXX-189">Migrate to Maven 2.0 for documentation and packaging</action>
+<action issue="LOGCXX-190">The 'logger.h' header includes itself.</action>
+<action issue="LOGCXX-191">Application cores when syslog appender is given an unreachable host/ip.</action>
+<action issue="LOGCXX-192">Suggested improvements to log4cxx webpages</action>
+<action issue="LOGCXX-193">Please rename or remove new local variable "buf" in Logger.h macros</action>
+<action issue="LOGCXX-194">Garbage in log files when appenders are defined in multiple levels of the logger hierarchy</action>
+<action issue="LOGCXX-195">Syslog appender adds characters to output.</action>
+<action issue="LOGCXX-196">Syslog appender destructor can cause core</action>
+<action issue="LOGCXX-197">ant can't generate vc6 project</action>
+<action issue="LOGCXX-200">Implement compression for RollingFileAppender</action>
+<action issue="LOGCXX-201">Visual Studio 6 build</action>
+<action issue="LOGCXX-202">ObjectPtrT has inconsistent const-ness on accessors</action>
+<action issue="LOGCXX-204">PatternParserTestCase and FileNamePatternTestCase fail only with VC6</action>
+<action issue="LOGCXX-208">isTraceEnabled implemenation missing in logger.cpp (Revision: 592627)</action>
+<action issue="LOGCXX-209">A message of type wchar_t* is not beeing written correctly to the internal message buffer (Revision: 592627)</action>
+<action issue="LOGCXX-210">HTMLLayout NDC null check</action>
+<action issue="LOGCXX-211">Crash(Segmentation Fault) in DailyRollingFileAppender when file change</action>
+<action issue="LOGCXX-212">unittest failed</action>
+<action issue="LOGCXX-213">trace method implementation is missing</action>
+<action issue="LOGCXX-214">Possible memory leak due to fault in build process (via make)</action>
+<action issue="LOGCXX-215">Eliminate sqlext.h from odbcappender.h</action>
+<action issue="LOGCXX-216">crash on program exit</action>
+<action issue="LOGCXX-217">Not initialized LoggerPtr segfault program.</action>
+<action issue="LOGCXX-218">Visual Studio 8 build</action>
+<action issue="LOGCXX-219">suspicious warnings</action>
+<action issue="LOGCXX-220">Memory leaks when using MFC</action>
+<action issue="LOGCXX-221">ThreadID layout does not match debugger</action>
+<action issue="LOGCXX-222">trunk compile error.</action>
+<action issue="LOGCXX-225">Migrate unit tests from LGPL'd CPPUNIT to an ASL'd testing framework</action>
+<action issue="LOGCXX-226">Default configurator uses *.properties in preference to *.xml</action>
+<action issue="LOGCXX-227">Remove @since tags</action>
+<action issue="LOGCXX-228">Remove @author tags</action>
+<action issue="LOGCXX-230">Align ant build options with automake</action>
+<action issue="LOGCXX-231">Deadlock in AsyncAppender</action>
+<action issue="LOGCXX-232">Drop src/performance</action>
+<action issue="LOGCXX-233">Unnecessary casts in ObjectPtrT</action>
+<action issue="LOGCXX-234">Assignment operator removes const qualifier</action>
+<action issue="LOGCXX-235">Add ObjectPtrT::exchange</action>
+<action issue="LOGCXX-236">Re-order constructor initialiser lists to match declaration order</action>
+<action issue="LOGCXX-237">Include missing headers</action>
+<action issue="LOGCXX-239">Inconsistent const qualification on logging methods.</action>
+<action issue="LOGCXX-241">Non-ascii named files have names mangled</action>
+<action issue="LOGCXX-242">Eliminate log4cxx proxies for APR types</action>
+<action issue="LOGCXX-243">Problem Compile in Doxy</action>
+<action issue="LOGCXX-246">Config refresh hangs a client application that uses TelnetAppender</action>
+<action issue="LOGCXX-247">MSVC project has wrong additional include directories</action>
+<action issue="LOGCXX-248">ODBCAppender has unicode issues</action>
+<action issue="LOGCXX-251">NDC::cloneStack and NDC::inherit missing in 0.10.0 RC2</action>
+<action issue="LOGCXX-252">Add documentation for use of operator&lt;&lt; in logging requests</action>
+<action issue="LOGCXX-253">Transcoder compilation error with utf-8 charset</action>
+<action issue="LOGCXX-254">Add build option for static C RTL</action>
+<action issue="LOGCXX-256">SocketHubAppender fails after accepting connection</action>
+<action issue="LOGCXX-257">ServerSocket::accept hangs on Unix</action>
+<action issue="LOGCXX-258">unable to build from make dist package due to missing doxygen file</action>
+<action issue="LOGCXX-259">Several appenders fail to compile in Visual Studio 2008</action>
+</release>
+<release version="0.9.7" date="2004-05-10">
+<action type="fix">Fixed examples source code in the "Short introduction to log4cxx".</action>
+<action type="fix">Fixed, in the renaming algorithm of RollingFileAppender and
+ DailyRollingFileAppender, a problem specific to Unicode.</action>
+<action type="fix">Fixed conflict with Windows macros "min" and "max", by renaming
+ StrictMath::min and StrictMath::max to StrictMath::minimum and
+ StrictMath::maximum.</action>
+<action type="add">Port to HPUX 11.0.</action>
+<action type="fix">Fixed segmentation fault in PropertyConfigurator.</action>
+<action type="add">Port to Solaris.</action>
+<action type="fix">Fixed MutexException thrown while destroying RollingFileAppender.</action>
+<action type="fix">Logging macros can be used without explicity declaring the use of log4cxx namespace.</action>
+<action type="fix">Fixed static library unresolved externals for msvc 6 and 7.1</action>
+</release>
+<release version="0.9.6" date="2004-04-11">
+<action>Timezone management has been optimized through the class TimeZone</action>
+<action>Inter-thread synchronization and reference counting has been optimized</action>
+<action>Reference counting now uses gcc atomic functions (bug 929078)</action>
+<action>Use of StringBuffer has been optimized.</action>
+<action>Support of localisation throug resourceBundles</action>
+<action>SyslogAppender now uses the system function 'syslog' to log on the local host.
+ (only for POSIX systems)</action>
+<action>Added TimeZone configuration to PatternLayout (bug 912563)</action>
+<action>Support of the DailyRollingFileAppender (feature request 842765)</action>
+</release>
+<release version="0.9.5" date="2004-02-04">
+<action>Port of log4j Jnuit tests with Cppunit and Boost Regex.</action>
+<action>Added explicit exports for MSDEV 6 and MSDEV 7 (no further need of .def files)</action>
+<action>Custom levels can be configured through the DOMConfigurator and
+ PropertyConfigurator classes (Level inherites from Object)</action>
+<action>Added a reference counter to LoggingEvent to avoid useless copies
+ (LoggingEvent inherites from Object)</action>
+<action>The file log4j.xml as well as the file log4j.properties are now search
+ for, in log4cxx initialization.</action>
+<action>The root logger can be assigned the "OFF" level.</action>
+<action>Added MSVC6 project missing files mutext.cpp and condition.cpp (bug 847397)</action>
+<action>condition.cpp now compiles with MSVC6 (bug 847417)</action>
+<action>fixed pure virtual function call in PropertyConfigurator::configureAndWatch
+ (bug 848521)</action>
+<action>XMLAppender now displays correct timestamp with MSVC 6 (bug 852836)</action>
+<action>SRLPORT 4.6 support.</action>
+<action>Fixed an infinite loop in class Properties.</action>
+<action>Fixed compilations problems with unicode.</action>
+<action>Fixed SocketAppender bug concerning MDC and NDC.</action>
+</release>
+<release version="0.9.4" date="2003-10-25">
+<action>StringBuffer has been optimized.</action>
+<action>Fixed miscellaneous threading problems.</action>
+<action>Added TimeZone support in PatternLayout (bug 796894)</action>
+<action>Fixed threading configuration problems (bug 809125)</action>
+<action>Fixed miscellaneous MSVC and cygwin compilation problems.</action>
+</release>
+<release version="0.9.3" date="2003-09-19">
+<action>Changed tstring to log4cxx::String and tostringstream to
+ log4cxx::StringBuffer.
+</action>
+<action>Fixed MSVC 2003 compilation erros and warnings.
+</action>
+<action>Added helpers for NDC and MDC.
+</action>
+<action>Added TimeZone support in TTCCLayout.
+</action>
+<action>Fixed compilation problems with logger macros (LOG4CXX_...)
+</action>
+<action>Fixed milliseconds formatting problem with MSVC 6.0 and 2003
+</action>
+<action>Fixed AsyncAppender crash
+</action>
+<action>Added new tests
+</action>
+<action>Added benchmarks
+</action>
+</release>
+<release version="0.9.2" date="2003-08-10">
+<action>Fixed FreeBSD compilation problem with pthread mutex (class CriticalSection).
+</action>
+<action>Fixed milliseconds formatting problem (class DateFormat).
+</action>
+<action>Long events (&gt; 1024 chars) are now supported in the class XMLSocketAppender.
+</action>
+<action>Carriage returns have been normalized in the class XMLLayout.
+</action>
+</release>
+<release version="0.9.1" date="2003-08-06">
+<action>Fixed deadlock problems in classes Logger and AsyncAppender.
+</action>
+<action>Fixed MSVC 6.0 compilation problems.
+</action>
+<action>Added MSVC 6.0 static libraty project.
+</action>
+<action>Default configuration for the SMTP options is "no".
+</action>
+</release>
+<release version="0.9.0" date="2003-08-06">
+<action>Added ODBCAppender (matching log4j JDBCAppender)
+</action>
+<action>Added SyslogAppender
+</action>
+<action>Added SMTPAppender (only for Linux/FreeBSD)
+</action>
+<action>Added BasicConfigurator
+</action>
+<action>Added a FileWatchDog in PropertyConfigurator and DOMConfigurator
+</action>
+<action>Possibility to load a custom LoggerFactory through the DOMConfigurator
+</action>
+<action>Changed time precision from seconds to milliseconds
+</action>
+<action>Added MSVC 6.0 'Unicode Debug' and 'Unicode Release' targets
+</action>
+<action>Added Java like System class.
+</action>
+</release>
+<release version="0.1.1" date="2003-07-09">
+<action>Fixed MSVC 6.0 compilation problems concerning the 'Release' target
+</action>
+<action>Added MSVC 6.0 tests projects
+</action>
+</release>
+<release version="0.1.0" date="2003-07-08">
+<action>FreeBSD Autotools/Compilation support
+</action>
+<action>Fixed TelnetAppender crash when a socket bind exception occured.
+</action>
+<action>Added log4j DTD support to XMLLayout and DOMConfigurator
+</action>
+<action>Can now send events in XML format over TCP (class XMLSocketAppender) for the
+ log4j Chainsaw UI
+</action>
+<action>Now compiles with 'configure --enable-unicode' (UTF16 Unicode support)
+</action>
+<action>Added Java like Properties class. It's a helper for the PropertyConfigurator
+</action>
+<action>Added Java like objects with dynamic cast and instanciation. Custom objects
+ can be configured through the DOMConfigurator and PropertyConfigurator classes
+</action>
+<action>Port of the PropertyConfigurator class
+</action>
+<action>Port of the "Map Diagnostic Context" (MDC) class
+</action>
+<action>Added 13 tests (try make check)
+</action>
+</release>
+<release version="0.0.1" date="2003-05-31">
+<action type="add">Loggers, Hierarchy, Filters, Appenders, Layouts, NDC
+</action>
+<action type="add">Appenders:
+ AsyncAppender, ConsoleAppender, FileAppender, NTEventLogAppender,
+ RollingFileAppender, SocketAppender, SocketHubAappender,
+ TelnetAppender
+</action>
+<action type="add">Layouts:
+ HTMLLayout, PatternLayout, SimpleLayout, TTCCLayout, XMLLayout
+</action>
+<action type="add">Filters:
+ DenyAllFilter, LevelMatchFilter, LevelRangeFilter, StringMatchFilter
+
+</action>
+<action type="add">Configurators:
+ DOMConfigurator
+</action>
+</release>
+</body>
+</document>
diff --git a/src/changes/changes.xslt b/src/changes/changes.xslt
new file mode 100644
index 0000000..1108ea7
--- /dev/null
+++ b/src/changes/changes.xslt
@@ -0,0 +1,225 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xsl:version="1.0">
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:apply-templates select="/"/>
+
+ <xsl:template match="/">
+ <xsl:comment>
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </xsl:comment>
+ <document>
+ <properties>
+ <title>Apache log4cxx</title>
+ </properties>
+ <body>
+
+ <release version="0.10.0" date="2008-02-29" description="First Apache release">
+ <xsl:apply-templates select='/rss/channel/item'>
+ <xsl:sort select="substring-after(key, '-')" data-type="number"/>
+ </xsl:apply-templates>
+ </release>
+
+<release version="0.9.7" date="2004-05-10">
+<action type="fix">Fixed examples source code in the "Short introduction to log4cxx".</action>
+<action type="fix">Fixed, in the renaming algorithm of RollingFileAppender and
+ DailyRollingFileAppender, a problem specific to Unicode.</action>
+<action type="fix">Fixed conflict with Windows macros "min" and "max", by renaming
+ StrictMath::min and StrictMath::max to StrictMath::minimum and
+ StrictMath::maximum.</action>
+<action type="add">Port to HPUX 11.0.</action>
+<action type="fix">Fixed segmentation fault in PropertyConfigurator.</action>
+<action type="add">Port to Solaris.</action>
+<action type="fix">Fixed MutexException thrown while destroying RollingFileAppender.</action>
+<action type="fix">Logging macros can be used without explicity declaring the use of log4cxx namespace.</action>
+<action type="fix">Fixed static library unresolved externals for msvc 6 and 7.1</action>
+</release>
+<release version="0.9.6" date="2004-04-11">
+<action>Timezone management has been optimized through the class TimeZone</action>
+<action>Inter-thread synchronization and reference counting has been optimized</action>
+<action>Reference counting now uses gcc atomic functions (bug 929078)</action>
+<action>Use of StringBuffer has been optimized.</action>
+<action>Support of localisation throug resourceBundles</action>
+<action>SyslogAppender now uses the system function 'syslog' to log on the local host.
+ (only for POSIX systems)</action>
+<action>Added TimeZone configuration to PatternLayout (bug 912563)</action>
+<action>Support of the DailyRollingFileAppender (feature request 842765)</action>
+</release>
+<release version="0.9.5" date="2004-02-04">
+<action>Port of log4j Jnuit tests with Cppunit and Boost Regex.</action>
+<action>Added explicit exports for MSDEV 6 and MSDEV 7 (no further need of .def files)</action>
+<action>Custom levels can be configured through the DOMConfigurator and
+ PropertyConfigurator classes (Level inherites from Object)</action>
+<action>Added a reference counter to LoggingEvent to avoid useless copies
+ (LoggingEvent inherites from Object)</action>
+<action>The file log4j.xml as well as the file log4j.properties are now search
+ for, in log4cxx initialization.</action>
+<action>The root logger can be assigned the "OFF" level.</action>
+<action>Added MSVC6 project missing files mutext.cpp and condition.cpp (bug 847397)</action>
+<action>condition.cpp now compiles with MSVC6 (bug 847417)</action>
+<action>fixed pure virtual function call in PropertyConfigurator::configureAndWatch
+ (bug 848521)</action>
+<action>XMLAppender now displays correct timestamp with MSVC 6 (bug 852836)</action>
+<action>SRLPORT 4.6 support.</action>
+<action>Fixed an infinite loop in class Properties.</action>
+<action>Fixed compilations problems with unicode.</action>
+<action>Fixed SocketAppender bug concerning MDC and NDC.</action>
+</release>
+<release version="0.9.4" date="2003-10-25">
+<action>StringBuffer has been optimized.</action>
+<action>Fixed miscellaneous threading problems.</action>
+<action>Added TimeZone support in PatternLayout (bug 796894)</action>
+<action>Fixed threading configuration problems (bug 809125)</action>
+<action>Fixed miscellaneous MSVC and cygwin compilation problems.</action>
+</release>
+<release version="0.9.3" date="2003-09-19">
+<action>Changed tstring to log4cxx::String and tostringstream to
+ log4cxx::StringBuffer.
+</action>
+<action>Fixed MSVC 2003 compilation erros and warnings.
+</action>
+<action>Added helpers for NDC and MDC.
+</action>
+<action>Added TimeZone support in TTCCLayout.
+</action>
+<action>Fixed compilation problems with logger macros (LOG4CXX_...)
+</action>
+<action>Fixed milliseconds formatting problem with MSVC 6.0 and 2003
+</action>
+<action>Fixed AsyncAppender crash
+</action>
+<action>Added new tests
+</action>
+<action>Added benchmarks
+</action>
+</release>
+<release version="0.9.2" date="2003-08-10">
+<action>Fixed FreeBSD compilation problem with pthread mutex (class CriticalSection).
+</action>
+<action>Fixed milliseconds formatting problem (class DateFormat).
+</action>
+<action>Long events (&gt; 1024 chars) are now supported in the class XMLSocketAppender.
+</action>
+<action>Carriage returns have been normalized in the class XMLLayout.
+</action>
+</release>
+<release version="0.9.1" date="2003-08-06">
+<action>Fixed deadlock problems in classes Logger and AsyncAppender.
+</action>
+<action>Fixed MSVC 6.0 compilation problems.
+</action>
+<action>Added MSVC 6.0 static libraty project.
+</action>
+<action>Default configuration for the SMTP options is "no".
+</action>
+</release>
+<release version="0.9.0" date="2003-08-06">
+<action>Added ODBCAppender (matching log4j JDBCAppender)
+</action>
+<action>Added SyslogAppender
+</action>
+<action>Added SMTPAppender (only for Linux/FreeBSD)
+</action>
+<action>Added BasicConfigurator
+</action>
+<action>Added a FileWatchDog in PropertyConfigurator and DOMConfigurator
+</action>
+<action>Possibility to load a custom LoggerFactory through the DOMConfigurator
+</action>
+<action>Changed time precision from seconds to milliseconds
+</action>
+<action>Added MSVC 6.0 'Unicode Debug' and 'Unicode Release' targets
+</action>
+<action>Added Java like System class.
+</action>
+</release>
+<release version="0.1.1" date="2003-07-09">
+<action>Fixed MSVC 6.0 compilation problems concerning the 'Release' target
+</action>
+<action>Added MSVC 6.0 tests projects
+</action>
+</release>
+<release version="0.1.0" date="2003-07-08">
+<action>FreeBSD Autotools/Compilation support
+</action>
+<action>Fixed TelnetAppender crash when a socket bind exception occured.
+</action>
+<action>Added log4j DTD support to XMLLayout and DOMConfigurator
+</action>
+<action>Can now send events in XML format over TCP (class XMLSocketAppender) for the
+ log4j Chainsaw UI
+</action>
+<action>Now compiles with 'configure --enable-unicode' (UTF16 Unicode support)
+</action>
+<action>Added Java like Properties class. It's a helper for the PropertyConfigurator
+</action>
+<action>Added Java like objects with dynamic cast and instanciation. Custom objects
+ can be configured through the DOMConfigurator and PropertyConfigurator classes
+</action>
+<action>Port of the PropertyConfigurator class
+</action>
+<action>Port of the "Map Diagnostic Context" (MDC) class
+</action>
+<action>Added 13 tests (try make check)
+</action>
+</release>
+<release version="0.0.1" date="2003-05-31">
+<action type="add">Loggers, Hierarchy, Filters, Appenders, Layouts, NDC
+</action>
+<action type="add">Appenders:
+ AsyncAppender, ConsoleAppender, FileAppender, NTEventLogAppender,
+ RollingFileAppender, SocketAppender, SocketHubAappender,
+ TelnetAppender
+</action>
+<action type="add">Layouts:
+ HTMLLayout, PatternLayout, SimpleLayout, TTCCLayout, XMLLayout
+</action>
+<action type="add">Filters:
+ DenyAllFilter, LevelMatchFilter, LevelRangeFilter, StringMatchFilter
+
+</action>
+<action type="add">Configurators:
+ DOMConfigurator
+</action>
+</release>
+ </body>
+</document>
+</xsl:template>
+
+<xsl:template match="item">
+ <action issue="{key}"><xsl:value-of select="summary"/></action>
+</xsl:template>
+
+</xsl:transform>
diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am
new file mode 100644
index 0000000..83b32d8
--- /dev/null
+++ b/src/examples/Makefile.am
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+SUBDIRS = cpp
diff --git a/src/examples/cpp/Makefile.am b/src/examples/cpp/Makefile.am
new file mode 100644
index 0000000..ff5d7d9
--- /dev/null
+++ b/src/examples/cpp/Makefile.am
@@ -0,0 +1,31 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+noinst_PROGRAMS = trivial delayedloop stream console
+
+INCLUDES = -I$(top_srcdir)/src/main/include -I$(top_builddir)/src/main/include
+
+trivial_SOURCES = trivial.cpp
+trivial_LDADD = $(top_builddir)/src/main/cpp/liblog4cxx.la
+
+delayedloop_SOURCES = delayedloop.cpp
+delayedloop_LDADD = $(top_builddir)/src/main/cpp/liblog4cxx.la
+
+stream_SOURCES = stream.cpp
+stream_LDADD = $(top_builddir)/src/main/cpp/liblog4cxx.la
+
+console_SOURCES = console.cpp
+console_LDADD = $(top_builddir)/src/main/cpp/liblog4cxx.la
+
diff --git a/src/examples/cpp/console.cpp b/src/examples/cpp/console.cpp
new file mode 100755
index 0000000..6a01d8a
--- /dev/null
+++ b/src/examples/cpp/console.cpp
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <stdlib.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/consoleappender.h>
+#include <log4cxx/simplelayout.h>
+#include <log4cxx/logmanager.h>
+#include <iostream>
+#include <locale.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+/**
+ * Configures console appender.
+ * @param err if true, use stderr, otherwise stdout.
+ */
+static void configure(bool err) {
+ log4cxx::ConsoleAppenderPtr appender(new log4cxx::ConsoleAppender());
+ if (err) {
+ appender->setTarget(LOG4CXX_STR("System.err"));
+ }
+ log4cxx::LayoutPtr layout(new log4cxx::SimpleLayout());
+ appender->setLayout(layout);
+ log4cxx::helpers::Pool pool;
+ appender->activateOptions(pool);
+ log4cxx::Logger::getRootLogger()->addAppender(appender);
+ LogManager::getLoggerRepository()->setConfigured(true);
+}
+
+/**
+ * Program to test compatibility of C RTL, C++ STL and log4cxx output to standard
+ * output and error streams.
+ *
+ * See bug LOGCXX_126.
+ *
+ *
+ */
+int main(int argc, char** argv)
+{
+ setlocale(LC_ALL, "");
+ if (argc <= 1) {
+ puts("Console test program\nUsage: console [-err] [ puts | putws | cout | wcout | configure | log | wide | byte ]*\n");
+ }
+ bool configured = false;
+ bool err = false;
+ for (int i = 1; i < argc; i++) {
+ if (strcmp("-err", argv[i]) == 0) {
+ err = true;
+ } else if (strcmp("puts", argv[i]) == 0) {
+ fputs("Hello, fputs\n", err ? stderr : stdout);
+#if LOG4CXX_WCHAR_T_API
+ } else if (strcmp("putws", argv[i]) == 0) {
+ fputws(L"Hello, fputws\n", err ? stderr : stdout);
+#endif
+ } else if (strcmp("cout", argv[i]) == 0) {
+ if (err) {
+ std::cerr << "Hello, cout" << std::endl;
+ } else {
+ std::cout << "Hello, cout" << std::endl;
+ }
+ } else if (strcmp("wcout", argv[i]) == 0) {
+ if (err) {
+ #if LOG4CXX_HAS_STD_WCOUT
+ std::wcerr << L"Hello, wcout" << std::endl;
+ #else
+ std::cerr << "Log4cxx has not wcout" << std::endl;
+ #endif
+ } else {
+ #if LOG4CXX_HAS_STD_WCOUT
+ std::wcout << L"Hello, wcout" << std::endl;
+ #else
+ std::cout << "Log4cxx has not wcout" << std::endl;
+ #endif
+ }
+ } else if (strcmp("configure", argv[i]) == 0) {
+ configure(err);
+ configured = true;
+ } else if (strcmp("log", argv[i]) == 0) {
+ if (!configured) {
+ configure(err);
+ configured = true;
+ }
+ log4cxx::Logger::getRootLogger()->info("Hello, log4cxx");
+#if LOG4CXX_WCHAR_T_API
+ } else if (strcmp("wide", argv[i]) == 0) {
+ fwide(err ? stderr : stdout, 1);
+ } else if (strcmp("byte", argv[i]) == 0) {
+ fwide(err ? stderr : stdout, -1);
+#endif
+ } else {
+ fputs("Unrecognized option: ", stderr);
+ fputs(argv[i], stderr);
+ fputs("\n", stderr);
+ fflush(stderr);
+ }
+ }
+ return 0;
+}
diff --git a/src/examples/cpp/delayedloop.cpp b/src/examples/cpp/delayedloop.cpp
new file mode 100644
index 0000000..ff785d5
--- /dev/null
+++ b/src/examples/cpp/delayedloop.cpp
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logger.h>
+#include <log4cxx/xml/domconfigurator.h>
+#include <log4cxx/propertyconfigurator.h>
+#include <apr_general.h>
+#include <apr_time.h>
+#include <iostream>
+#include <log4cxx/stream.h>
+#include <exception>
+#include <stdlib.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+/**
+This test program sits in a loop and logs things. Its logging is
+configured by a configuration file. Changes to this configuration
+file are monitored and when a change occurs, the config file is re-read.
+*/
+class DelayedLoop
+{
+ static LoggerPtr logger;
+
+public:
+ static void main(int argc, const char * const argv[])
+ {
+ if(argc == 2)
+ {
+ init(argv[1]);
+ }
+ else
+ {
+ usage(argv[0], "Wrong number of arguments.");
+ }
+
+ test();
+ }
+
+ static void usage(const char * programName, const char * msg)
+ {
+ std::cout << msg << std::endl;
+ std::cout << "Usage: " << programName <<
+ " configFile" << std::endl;
+ exit(1);
+ }
+
+
+ static void init(const std::string& configFile)
+ {
+ if(configFile.length() > 4 &&
+ configFile.substr(configFile.length() - 4) == ".xml")
+ {
+#if APR_HAS_THREADS
+ xml::DOMConfigurator::configureAndWatch(configFile, 3000);
+#else
+ xml::DOMConfigurator::configure(configFile);
+#endif
+ }
+ else
+ {
+#if APR_HAS_THREADS
+ PropertyConfigurator::configureAndWatch(configFile, 3000);
+#else
+ PropertyConfigurator::configure(configFile);
+#endif
+ }
+ }
+
+ static void test()
+ {
+ int i = 0;
+ while(true)
+ {
+ LOG4CXX_DEBUG(logger, "MSG " << i++);
+ try
+ {
+ apr_sleep(1000000);
+ }
+ catch(std::exception& e)
+ {
+ }
+ }
+ }
+};
+
+LoggerPtr DelayedLoop::logger = Logger::getLogger("DelayedLoop");
+
+int main(int argc, const char * const argv[])
+{
+ apr_app_initialize(&argc, &argv, NULL);
+ int result = EXIT_SUCCESS;
+ try
+ {
+ DelayedLoop::main(argc, argv);
+ }
+ catch(std::exception&)
+ {
+ result = EXIT_FAILURE;
+ }
+
+ apr_terminate();
+ return result;
+}
diff --git a/src/examples/cpp/stream.cpp b/src/examples/cpp/stream.cpp
new file mode 100644
index 0000000..0194c23
--- /dev/null
+++ b/src/examples/cpp/stream.cpp
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <stdlib.h>
+#include <log4cxx/stream.h>
+#include <log4cxx/basicconfigurator.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/ndc.h>
+#include <locale.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+int main()
+{
+ setlocale(LC_ALL, "");
+ int result = EXIT_SUCCESS;
+ try
+ {
+ BasicConfigurator::configure();
+ LoggerPtr rootLogger = Logger::getRootLogger();
+
+ NDC::push("trivial context");
+
+ log4cxx::logstream logstream(rootLogger, Level::getDebug());
+ logstream << "debug message " << 1 << LOG4CXX_ENDMSG;
+ logstream.setLevel(Level::getInfo());
+ logstream << "info message" << LOG4CXX_ENDMSG;
+ logstream << Level::getWarn() << "warn message" << LOG4CXX_ENDMSG;
+ logstream << Level::getError() << "error message" << LOG4CXX_ENDMSG;
+ logstream << Level::getFatal() << "fatal message" << LOG4CXX_ENDMSG;
+
+
+ NDC::pop();
+ }
+ catch(std::exception&)
+ {
+ result = EXIT_FAILURE;
+ }
+
+ return result;
+}
+
diff --git a/src/examples/cpp/trivial.cpp b/src/examples/cpp/trivial.cpp
new file mode 100644
index 0000000..6e8726e
--- /dev/null
+++ b/src/examples/cpp/trivial.cpp
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <stdlib.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/basicconfigurator.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/ndc.h>
+#include <locale.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+int main()
+{
+ setlocale(LC_ALL, "");
+ int result = EXIT_SUCCESS;
+ try
+ {
+ BasicConfigurator::configure();
+ LoggerPtr rootLogger = Logger::getRootLogger();
+
+ NDC::push("trivial context");
+
+ LOG4CXX_DEBUG(rootLogger, "debug message");
+ LOG4CXX_INFO(rootLogger, "info message");
+ LOG4CXX_WARN(rootLogger, "warn message");
+ LOG4CXX_ERROR(rootLogger, "error message");
+ LOG4CXX_FATAL(rootLogger, "fatal message");
+
+ NDC::pop();
+ }
+ catch(std::exception&)
+ {
+ result = EXIT_FAILURE;
+ }
+
+ return result;
+}
diff --git a/src/main/Makefile.am b/src/main/Makefile.am
new file mode 100644
index 0000000..67714c0
--- /dev/null
+++ b/src/main/Makefile.am
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+SUBDIRS = cpp include
diff --git a/src/main/cpp/Makefile.am b/src/main/cpp/Makefile.am
new file mode 100644
index 0000000..e809c95
--- /dev/null
+++ b/src/main/cpp/Makefile.am
@@ -0,0 +1,173 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+lib_LTLIBRARIES = liblog4cxx.la
+
+INCLUDES = -I$(top_srcdir)/src/main/include -I$(top_builddir)/src/main/include
+
+
+liblog4cxx_la_SOURCES = \
+ action.cpp \
+ appenderattachableimpl.cpp \
+ appenderskeleton.cpp \
+ aprinitializer.cpp \
+ asyncappender.cpp \
+ basicconfigurator.cpp \
+ bufferedwriter.cpp \
+ bytearrayinputstream.cpp \
+ bytearrayoutputstream.cpp \
+ bytebuffer.cpp \
+ cacheddateformat.cpp \
+ charsetdecoder.cpp \
+ charsetencoder.cpp \
+ class.cpp \
+ classnamepatternconverter.cpp \
+ classregistration.cpp \
+ condition.cpp \
+ configurator.cpp \
+ consoleappender.cpp \
+ cyclicbuffer.cpp \
+ dailyrollingfileappender.cpp \
+ datagrampacket.cpp \
+ datagramsocket.cpp \
+ date.cpp \
+ dateformat.cpp \
+ datelayout.cpp \
+ datepatternconverter.cpp \
+ defaultloggerfactory.cpp \
+ defaultconfigurator.cpp \
+ defaultrepositoryselector.cpp \
+ domconfigurator.cpp \
+ exception.cpp \
+ fallbackerrorhandler.cpp \
+ file.cpp \
+ fileappender.cpp \
+ filedatepatternconverter.cpp \
+ fileinputstream.cpp \
+ filelocationpatternconverter.cpp \
+ fileoutputstream.cpp \
+ filerenameaction.cpp \
+ filewatchdog.cpp \
+ filter.cpp \
+ filterbasedtriggeringpolicy.cpp \
+ fixedwindowrollingpolicy.cpp \
+ formattinginfo.cpp \
+ fulllocationpatternconverter.cpp \
+ gzcompressaction.cpp \
+ hierarchy.cpp \
+ htmllayout.cpp \
+ inetaddress.cpp \
+ inputstream.cpp \
+ inputstreamreader.cpp \
+ integer.cpp \
+ integerpatternconverter.cpp \
+ layout.cpp\
+ level.cpp \
+ levelmatchfilter.cpp \
+ levelrangefilter.cpp \
+ levelpatternconverter.cpp \
+ linelocationpatternconverter.cpp \
+ lineseparatorpatternconverter.cpp \
+ literalpatternconverter.cpp \
+ loggerpatternconverter.cpp \
+ loggingeventpatternconverter.cpp \
+ loader.cpp\
+ locale.cpp\
+ locationinfo.cpp\
+ logger.cpp \
+ loggingevent.cpp \
+ loglog.cpp \
+ logmanager.cpp \
+ logstream.cpp \
+ manualtriggeringpolicy.cpp \
+ messagebuffer.cpp \
+ messagepatternconverter.cpp \
+ methodlocationpatternconverter.cpp \
+ mdc.cpp \
+ mutex.cpp \
+ nameabbreviator.cpp \
+ namepatternconverter.cpp \
+ ndcpatternconverter.cpp \
+ ndc.cpp \
+ nteventlogappender.cpp \
+ objectimpl.cpp \
+ objectptr.cpp \
+ objectoutputstream.cpp \
+ obsoleterollingfileappender.cpp \
+ odbcappender.cpp \
+ onlyonceerrorhandler.cpp \
+ optionconverter.cpp \
+ outputdebugstringappender.cpp \
+ outputstream.cpp \
+ outputstreamwriter.cpp \
+ patternconverter.cpp \
+ patternlayout.cpp \
+ patternparser.cpp \
+ pool.cpp \
+ properties.cpp \
+ propertiespatternconverter.cpp \
+ propertyconfigurator.cpp \
+ propertyresourcebundle.cpp \
+ propertysetter.cpp \
+ reader.cpp \
+ relativetimedateformat.cpp \
+ relativetimepatternconverter.cpp \
+ resourcebundle.cpp \
+ rollingfileappender.cpp \
+ rollingpolicy.cpp \
+ rollingpolicybase.cpp \
+ rolloverdescription.cpp \
+ rootlogger.cpp \
+ serversocket.cpp \
+ simpledateformat.cpp \
+ simplelayout.cpp \
+ sizebasedtriggeringpolicy.cpp \
+ smtpappender.cpp \
+ socket.cpp \
+ socketappender.cpp \
+ socketappenderskeleton.cpp \
+ sockethubappender.cpp \
+ socketoutputstream.cpp \
+ strftimedateformat.cpp \
+ stringhelper.cpp \
+ stringmatchfilter.cpp \
+ stringtokenizer.cpp \
+ synchronized.cpp \
+ syslogappender.cpp \
+ syslogwriter.cpp \
+ system.cpp \
+ systemerrwriter.cpp \
+ systemoutwriter.cpp \
+ telnetappender.cpp \
+ threadcxx.cpp \
+ threadlocal.cpp \
+ threadspecificdata.cpp \
+ threadpatternconverter.cpp \
+ throwableinformationpatternconverter.cpp \
+ timezone.cpp \
+ timebasedrollingpolicy.cpp \
+ transform.cpp \
+ triggeringpolicy.cpp \
+ transcoder.cpp \
+ ttcclayout.cpp \
+ writer.cpp \
+ writerappender.cpp \
+ xmllayout.cpp\
+ xmlsocketappender.cpp \
+ zipcompressaction.cpp
+
+AM_CPPFLAGS = @CPPFLAGS_ODBC@
+liblog4cxx_la_LDFLAGS = -version-info @LT_VERSION@ @LIBS_ODBC@ -@APR_LIBS@
+
diff --git a/src/main/cpp/action.cpp b/src/main/cpp/action.cpp
new file mode 100644
index 0000000..9e440b5
--- /dev/null
+++ b/src/main/cpp/action.cpp
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/rolling/action.h>
+#include <log4cxx/helpers/synchronized.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(Action)
+
+Action::Action() :
+ complete(false),
+ interrupted(false),
+ pool(),
+ mutex(pool) {
+}
+
+Action::~Action() {
+}
+
+/**
+ * {@inheritDoc}
+ */
+void Action::run(log4cxx::helpers::Pool& pool1) {
+ synchronized sync(mutex);
+ if (!interrupted) {
+ try {
+ execute(pool1);
+ } catch(std::exception& ex) {
+ reportException(ex);
+ }
+ complete = true;
+ interrupted = true;
+ }
+}
+
+ /**
+ * {@inheritDoc}
+ */
+void Action::close() {
+ synchronized sync(mutex);
+ interrupted = true;
+}
+
+ /**
+ * Tests if the action is complete.
+ * @return true if action is complete.
+ */
+bool Action::isComplete() const {
+ return complete;
+}
+
+/**
+ * Capture exception.
+ *
+ * @param ex exception.
+ */
+void Action::reportException(const std::exception& /* ex */) {
+}
diff --git a/src/main/cpp/appenderattachableimpl.cpp b/src/main/cpp/appenderattachableimpl.cpp
new file mode 100644
index 0000000..5bd5a41
--- /dev/null
+++ b/src/main/cpp/appenderattachableimpl.cpp
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/appenderattachableimpl.h>
+#include <log4cxx/appender.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <algorithm>
+#include <log4cxx/helpers/pool.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+IMPLEMENT_LOG4CXX_OBJECT(AppenderAttachableImpl)
+
+
+AppenderAttachableImpl::AppenderAttachableImpl(Pool& pool)
+ : appenderList(),
+ mutex(pool) {
+}
+
+void AppenderAttachableImpl::addRef() const {
+ ObjectImpl::addRef();
+}
+
+void AppenderAttachableImpl::releaseRef() const {
+ ObjectImpl::releaseRef();
+}
+
+
+void AppenderAttachableImpl::addAppender(const AppenderPtr& newAppender)
+{
+ // Null values for newAppender parameter are strictly forbidden.
+ if(newAppender == 0)
+ {
+ return;
+ }
+
+ AppenderList::iterator it = std::find(
+ appenderList.begin(), appenderList.end(), newAppender);
+
+ if (it == appenderList.end())
+ {
+ appenderList.push_back(newAppender);
+ }
+}
+
+int AppenderAttachableImpl::appendLoopOnAppenders(
+ const spi::LoggingEventPtr& event,
+ Pool& p)
+{
+ for (AppenderList::iterator it = appenderList.begin();
+ it != appenderList.end();
+ it++) {
+ (*it)->doAppend(event, p);
+ }
+ return appenderList.size();
+}
+
+AppenderList AppenderAttachableImpl::getAllAppenders() const
+{
+ return appenderList;
+}
+
+AppenderPtr AppenderAttachableImpl::getAppender(const LogString& name) const
+{
+ if (name.empty())
+ {
+ return 0;
+ }
+
+ AppenderList::const_iterator it, itEnd = appenderList.end();
+ AppenderPtr appender;
+ for(it = appenderList.begin(); it != itEnd; it++)
+ {
+ appender = *it;
+ if(name == appender->getName())
+ {
+ return appender;
+ }
+ }
+
+ return 0;
+}
+
+bool AppenderAttachableImpl::isAttached(const AppenderPtr& appender) const
+{
+ if (appender == 0)
+ {
+ return false;
+ }
+
+ AppenderList::const_iterator it = std::find(
+ appenderList.begin(), appenderList.end(), appender);
+
+ return it != appenderList.end();
+}
+
+void AppenderAttachableImpl::removeAllAppenders()
+{
+ AppenderList::iterator it, itEnd = appenderList.end();
+ AppenderPtr a;
+ for(it = appenderList.begin(); it != itEnd; it++)
+ {
+ a = *it;
+ a->close();
+ }
+
+ appenderList.clear();
+}
+
+void AppenderAttachableImpl::removeAppender(const AppenderPtr& appender)
+{
+ if (appender == 0)
+ return;
+
+ AppenderList::iterator it = std::find(
+ appenderList.begin(), appenderList.end(), appender);
+
+ if (it != appenderList.end())
+ {
+ appenderList.erase(it);
+ }
+}
+
+void AppenderAttachableImpl::removeAppender(const LogString& name)
+{
+ if (name.empty())
+ {
+ return;
+ }
+
+ AppenderList::iterator it, itEnd = appenderList.end();
+ AppenderPtr appender;
+ for(it = appenderList.begin(); it != itEnd; it++)
+ {
+ appender = *it;
+ if(name == appender->getName())
+ {
+ appenderList.erase(it);
+ return;
+ }
+ }
+}
+
+
diff --git a/src/main/cpp/appenderskeleton.cpp b/src/main/cpp/appenderskeleton.cpp
new file mode 100644
index 0000000..43ab5a1
--- /dev/null
+++ b/src/main/cpp/appenderskeleton.cpp
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/spi/loggingevent.h>
+#include <log4cxx/appenderskeleton.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/onlyonceerrorhandler.h>
+#include <log4cxx/level.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <apr_atomic.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(AppenderSkeleton)
+
+
+AppenderSkeleton::AppenderSkeleton()
+: layout(),
+ name(),
+ threshold(Level::getAll()),
+ errorHandler(new OnlyOnceErrorHandler()),
+ headFilter(),
+ tailFilter(),
+ pool(),
+ mutex(pool)
+{
+ synchronized sync(mutex);
+ closed = false;
+}
+
+AppenderSkeleton::AppenderSkeleton(const LayoutPtr& layout1)
+: layout(layout1),
+ name(),
+ threshold(Level::getAll()),
+ errorHandler(new OnlyOnceErrorHandler()),
+ headFilter(),
+ tailFilter(),
+ pool(),
+ mutex(pool)
+{
+ synchronized sync(mutex);
+ closed = false;
+}
+
+void AppenderSkeleton::addRef() const {
+ ObjectImpl::addRef();
+}
+
+void AppenderSkeleton::releaseRef() const {
+ ObjectImpl::releaseRef();
+}
+
+void AppenderSkeleton::finalize()
+{
+// An appender might be closed then garbage collected. There is no
+// point in closing twice.
+ if(closed)
+ {
+ return;
+ }
+
+ close();
+}
+
+void AppenderSkeleton::addFilter(const spi::FilterPtr& newFilter)
+{
+ synchronized sync(mutex);
+ if(headFilter == 0)
+ {
+ headFilter = tailFilter = newFilter;
+ }
+ else
+ {
+ tailFilter->setNext(newFilter);
+ tailFilter = newFilter;
+ }
+}
+
+void AppenderSkeleton::clearFilters()
+{
+ synchronized sync(mutex);
+ headFilter = tailFilter = 0;
+}
+
+bool AppenderSkeleton::isAsSevereAsThreshold(const LevelPtr& level) const
+{
+ return ((level == 0) || level->isGreaterOrEqual(threshold));
+}
+
+void AppenderSkeleton::doAppend(const spi::LoggingEventPtr& event, Pool& pool1)
+{
+ synchronized sync(mutex);
+
+
+ if(closed)
+ {
+ LogLog::error(((LogString) LOG4CXX_STR("Attempted to append to closed appender named ["))
+ + name + LOG4CXX_STR("]."));
+ return;
+ }
+
+ if(!isAsSevereAsThreshold(event->getLevel()))
+ {
+ return;
+ }
+
+ FilterPtr f = headFilter;
+
+
+ while(f != 0)
+ {
+ switch(f->decide(event))
+ {
+ case Filter::DENY:
+ return;
+ case Filter::ACCEPT:
+ f = 0;
+ break;
+ case Filter::NEUTRAL:
+ f = f->getNext();
+ }
+ }
+
+ append(event, pool1);
+}
+
+void AppenderSkeleton::setErrorHandler(const spi::ErrorHandlerPtr& errorHandler1)
+{
+ synchronized sync(mutex);
+
+ if(errorHandler1 == 0)
+ {
+ // We do not throw exception here since the cause is probably a
+ // bad config file.
+ LogLog::warn(LOG4CXX_STR("You have tried to set a null error-handler."));
+ }
+ else
+ {
+ this->errorHandler = errorHandler1;
+ }
+}
+
+void AppenderSkeleton::setThreshold(const LevelPtr& threshold1)
+{
+ synchronized sync(mutex);
+ this->threshold = threshold1;
+}
+
+void AppenderSkeleton::setOption(const LogString& option,
+ const LogString& value)
+{
+ if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("THRESHOLD"), LOG4CXX_STR("threshold")))
+ {
+ setThreshold(Level::toLevelLS(value));
+ }
+}
+
+
diff --git a/src/main/cpp/aprinitializer.cpp b/src/main/cpp/aprinitializer.cpp
new file mode 100644
index 0000000..67c9b2f
--- /dev/null
+++ b/src/main/cpp/aprinitializer.cpp
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/helpers/aprinitializer.h>
+#include <apr_pools.h>
+#include <apr_atomic.h>
+#include <apr_time.h>
+#include <assert.h>
+#include <log4cxx/helpers/threadspecificdata.h>
+
+using namespace log4cxx::helpers;
+using namespace log4cxx;
+
+bool APRInitializer::isDestructed = false;
+
+APRInitializer::APRInitializer() {
+ apr_initialize();
+ apr_pool_create(&p, NULL);
+ apr_atomic_init(p);
+ startTime = apr_time_now();
+#if APR_HAS_THREADS
+ apr_status_t stat = apr_threadkey_private_create(&tlsKey, tlsDestruct, p);
+ assert(stat == APR_SUCCESS);
+#endif
+}
+
+APRInitializer::~APRInitializer() {
+ apr_terminate();
+ isDestructed = true;
+}
+
+APRInitializer& APRInitializer::getInstance() {
+ static APRInitializer init;
+ return init;
+}
+
+
+log4cxx_time_t APRInitializer::initialize() {
+ return getInstance().startTime;
+}
+
+apr_pool_t* APRInitializer::getRootPool() {
+ return getInstance().p;
+}
+
+apr_threadkey_t* APRInitializer::getTlsKey() {
+ return getInstance().tlsKey;
+}
+
+void APRInitializer::tlsDestruct(void* ptr) {
+ delete ((ThreadSpecificData*) ptr);
+}
diff --git a/src/main/cpp/asyncappender.cpp b/src/main/cpp/asyncappender.cpp
new file mode 100644
index 0000000..44732c2
--- /dev/null
+++ b/src/main/cpp/asyncappender.cpp
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/asyncappender.h>
+
+
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <apr_thread_proc.h>
+#include <apr_thread_mutex.h>
+#include <apr_thread_cond.h>
+#include <log4cxx/helpers/condition.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <apr_atomic.h>
+#include <log4cxx/helpers/optionconverter.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+
+IMPLEMENT_LOG4CXX_OBJECT(AsyncAppender)
+
+
+AsyncAppender::AsyncAppender()
+: AppenderSkeleton(),
+ buffer(),
+ bufferMutex(pool),
+ bufferNotFull(pool),
+ bufferNotEmpty(pool),
+ discardMap(new DiscardMap()),
+ bufferSize(DEFAULT_BUFFER_SIZE),
+ appenders(new AppenderAttachableImpl(pool)),
+ dispatcher(),
+ locationInfo(false),
+ blocking(true) {
+#if APR_HAS_THREADS
+ dispatcher.run(dispatch, this);
+#endif
+}
+
+AsyncAppender::~AsyncAppender()
+{
+ finalize();
+ delete discardMap;
+}
+
+void AsyncAppender::addRef() const {
+ ObjectImpl::addRef();
+}
+
+void AsyncAppender::releaseRef() const {
+ ObjectImpl::releaseRef();
+}
+
+void AsyncAppender::addAppender(const AppenderPtr& newAppender)
+{
+ synchronized sync(appenders->getMutex());
+ appenders->addAppender(newAppender);
+}
+
+
+void AsyncAppender::setOption(const LogString& option,
+ const LogString& value) {
+ if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("LOCATIONINFO"), LOG4CXX_STR("locationinfo"))) {
+ setLocationInfo(OptionConverter::toBoolean(value, false));
+ }
+ if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BUFFERSIZE"), LOG4CXX_STR("buffersize"))) {
+ setBufferSize(OptionConverter::toInt(value, DEFAULT_BUFFER_SIZE));
+ }
+ if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BLOCKING"), LOG4CXX_STR("blocking"))) {
+ setBlocking(OptionConverter::toBoolean(value, true));
+ } else {
+ AppenderSkeleton::setOption(option, value);
+ }
+}
+
+
+void AsyncAppender::append(const spi::LoggingEventPtr& event, Pool& p) {
+#if APR_HAS_THREADS
+ //
+ // if dispatcher has died then
+ // append subsequent events synchronously
+ //
+ if (!dispatcher.isAlive() || bufferSize <= 0) {
+ synchronized sync(appenders->getMutex());
+ appenders->appendLoopOnAppenders(event, p);
+ return;
+ }
+
+ // Set the NDC and thread name for the calling thread as these
+ // LoggingEvent fields were not set at event creation time.
+ LogString ndcVal;
+ event->getNDC(ndcVal);
+ event->getThreadName();
+ // Get a copy of this thread's MDC.
+ event->getMDCCopy();
+
+
+ {
+ synchronized sync(bufferMutex);
+ while(true) {
+ int previousSize = buffer.size();
+ if (previousSize < bufferSize) {
+ buffer.push_back(event);
+ if (previousSize == 0) {
+ bufferNotEmpty.signalAll();
+ }
+ break;
+ }
+
+ //
+ // Following code is only reachable if buffer is full
+ //
+ //
+ // if blocking and thread is not already interrupted
+ // and not the dispatcher then
+ // wait for a buffer notification
+ bool discard = true;
+ if (blocking
+ && !Thread::interrupted()
+ && !dispatcher.isCurrentThread()) {
+ try {
+ bufferNotFull.await(bufferMutex);
+ discard = false;
+ } catch (InterruptedException& e) {
+ //
+ // reset interrupt status so
+ // calling code can see interrupt on
+ // their next wait or sleep.
+ Thread::currentThreadInterrupt();
+ }
+ }
+
+ //
+ // if blocking is false or thread has been interrupted
+ // add event to discard map.
+ //
+ if (discard) {
+ LogString loggerName = event->getLoggerName();
+ DiscardMap::iterator iter = discardMap->find(loggerName);
+ if (iter == discardMap->end()) {
+ DiscardSummary summary(event);
+ discardMap->insert(DiscardMap::value_type(loggerName, summary));
+ } else {
+ (*iter).second.add(event);
+ }
+ break;
+ }
+ }
+ }
+#else
+ synchronized sync(appenders->getMutex());
+ appenders->appendLoopOnAppenders(event, p);
+#endif
+ }
+
+
+void AsyncAppender::close() {
+ {
+ synchronized sync(bufferMutex);
+ closed = true;
+ bufferNotEmpty.signalAll();
+ bufferNotFull.signalAll();
+ }
+
+#if APR_HAS_THREADS
+ try {
+ dispatcher.join();
+ } catch(InterruptedException& e) {
+ Thread::currentThreadInterrupt();
+ LogLog::error(LOG4CXX_STR("Got an InterruptedException while waiting for the dispatcher to finish,"), e);
+ }
+#endif
+
+ {
+ synchronized sync(appenders->getMutex());
+ AppenderList appenderList = appenders->getAllAppenders();
+ for (AppenderList::iterator iter = appenderList.begin();
+ iter != appenderList.end();
+ iter++) {
+ (*iter)->close();
+ }
+ }
+}
+
+AppenderList AsyncAppender::getAllAppenders() const
+{
+ synchronized sync(appenders->getMutex());
+ return appenders->getAllAppenders();
+}
+
+AppenderPtr AsyncAppender::getAppender(const LogString& name) const
+{
+ synchronized sync(appenders->getMutex());
+ return appenders->getAppender(name);
+}
+
+bool AsyncAppender::isAttached(const AppenderPtr& appender) const
+{
+ synchronized sync(appenders->getMutex());
+ return appenders->isAttached(appender);
+}
+
+bool AsyncAppender::requiresLayout() const {
+ return false;
+}
+
+void AsyncAppender::removeAllAppenders()
+{
+ synchronized sync(appenders->getMutex());
+ appenders->removeAllAppenders();
+}
+
+void AsyncAppender::removeAppender(const AppenderPtr& appender)
+{
+ synchronized sync(appenders->getMutex());
+ appenders->removeAppender(appender);
+}
+
+void AsyncAppender::removeAppender(const LogString& name)
+{
+ synchronized sync(appenders->getMutex());
+ appenders->removeAppender(name);
+}
+
+bool AsyncAppender::getLocationInfo() const {
+ return locationInfo;
+}
+
+void AsyncAppender::setLocationInfo(bool flag) {
+ locationInfo = flag;
+}
+
+
+void AsyncAppender::setBufferSize(int size)
+{
+ if (size < 0) {
+ throw IllegalArgumentException(LOG4CXX_STR("size argument must be non-negative"));
+ }
+ synchronized sync(bufferMutex);
+ bufferSize = (size < 1) ? 1 : size;
+ bufferNotFull.signalAll();
+}
+
+int AsyncAppender::getBufferSize() const
+{
+ return bufferSize;
+}
+
+void AsyncAppender::setBlocking(bool value) {
+ synchronized sync(bufferMutex);
+ blocking = value;
+ bufferNotFull.signalAll();
+}
+
+bool AsyncAppender::getBlocking() const {
+ return blocking;
+}
+
+AsyncAppender::DiscardSummary::DiscardSummary(const LoggingEventPtr& event) :
+ maxEvent(event), count(1) {
+}
+
+AsyncAppender::DiscardSummary::DiscardSummary(const DiscardSummary& src) :
+ maxEvent(src.maxEvent), count(src.count) {
+}
+
+AsyncAppender::DiscardSummary& AsyncAppender::DiscardSummary::operator=(const DiscardSummary& src) {
+ maxEvent = src.maxEvent;
+ count = src.count;
+ return *this;
+}
+
+void AsyncAppender::DiscardSummary::add(const LoggingEventPtr& event) {
+ if (event->getLevel()->toInt() > maxEvent->getLevel()->toInt()) {
+ maxEvent = event;
+ }
+ count++;
+}
+
+LoggingEventPtr AsyncAppender::DiscardSummary::createEvent(Pool& p) {
+ LogString msg(LOG4CXX_STR("Discarded "));
+ StringHelper::toString(count, p, msg);
+ msg.append(LOG4CXX_STR(" messages due to a full event buffer including: "));
+ msg.append(maxEvent->getMessage());
+ return new LoggingEvent(
+ maxEvent->getLoggerName(),
+ maxEvent->getLevel(),
+ msg,
+ LocationInfo::getLocationUnavailable());
+}
+
+
+#if APR_HAS_THREADS
+void* LOG4CXX_THREAD_FUNC AsyncAppender::dispatch(apr_thread_t* thread, void* data) {
+ AsyncAppender* pThis = (AsyncAppender*) data;
+ bool isActive = true;
+ try {
+ while (isActive) {
+ //
+ // process events after lock on buffer is released.
+ //
+ Pool p;
+ LoggingEventList events;
+ {
+ synchronized sync(pThis->bufferMutex);
+ size_t bufferSize = pThis->buffer.size();
+ isActive = !pThis->closed;
+
+ while((bufferSize == 0) && isActive) {
+ pThis->bufferNotEmpty.await(pThis->bufferMutex);
+ bufferSize = pThis->buffer.size();
+ isActive = !pThis->closed;
+ }
+ for(LoggingEventList::iterator eventIter = pThis->buffer.begin();
+ eventIter != pThis->buffer.end();
+ eventIter++) {
+ events.push_back(*eventIter);
+ }
+ for(DiscardMap::iterator discardIter = pThis->discardMap->begin();
+ discardIter != pThis->discardMap->end();
+ discardIter++) {
+ events.push_back(discardIter->second.createEvent(p));
+ }
+ pThis->buffer.clear();
+ pThis->discardMap->clear();
+ pThis->bufferNotFull.signalAll();
+ }
+
+ for (LoggingEventList::iterator iter = events.begin();
+ iter != events.end();
+ iter++) {
+ synchronized sync(pThis->appenders->getMutex());
+ pThis->appenders->appendLoopOnAppenders(*iter, p);
+ }
+ }
+ } catch(InterruptedException& ex) {
+ Thread::currentThreadInterrupt();
+ } catch(...) {
+ }
+ return 0;
+}
+#endif
diff --git a/src/main/cpp/basicconfigurator.cpp b/src/main/cpp/basicconfigurator.cpp
new file mode 100644
index 0000000..d3d84f0
--- /dev/null
+++ b/src/main/cpp/basicconfigurator.cpp
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/basicconfigurator.h>
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/consoleappender.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/logger.h>
+
+using namespace log4cxx;
+
+void BasicConfigurator::configure()
+{
+ LogManager::getLoggerRepository()->setConfigured(true);
+ LoggerPtr root = Logger::getRootLogger();
+ static const LogString TTCC_CONVERSION_PATTERN(LOG4CXX_STR("%r [%t] %p %c %x - %m%n"));
+ LayoutPtr layout(new PatternLayout(TTCC_CONVERSION_PATTERN));
+ AppenderPtr appender(new ConsoleAppender(layout));
+ root->addAppender(appender);
+}
+
+void BasicConfigurator::configure(const AppenderPtr& appender)
+{
+ LoggerPtr root = Logger::getRootLogger();
+ root->addAppender(appender);
+}
+
+void BasicConfigurator::resetConfiguration()
+{
+ LogManager::resetConfiguration();
+}
diff --git a/src/main/cpp/bufferedwriter.cpp b/src/main/cpp/bufferedwriter.cpp
new file mode 100644
index 0000000..ebb2328
--- /dev/null
+++ b/src/main/cpp/bufferedwriter.cpp
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/bufferedwriter.h>
+#include <log4cxx/helpers/pool.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(BufferedWriter)
+
+BufferedWriter::BufferedWriter(WriterPtr& out1)
+ : out(out1), sz(1024) {
+}
+
+BufferedWriter::BufferedWriter(WriterPtr& out1, size_t sz1)
+ : out(out1), sz(sz1) {
+}
+
+BufferedWriter::~BufferedWriter() {
+}
+
+void BufferedWriter::close(Pool& p) {
+ flush(p);
+ out->close(p);
+}
+
+void BufferedWriter::flush(Pool& p) {
+ if (buf.length() > 0) {
+ out->write(buf, p);
+ buf.erase(buf.begin(), buf.end());
+ }
+}
+
+void BufferedWriter::write(const LogString& str, Pool& p) {
+ if (buf.length() + str.length() > sz) {
+ out->write(buf, p);
+ buf.erase(buf.begin(), buf.end());
+ }
+ if (str.length() > sz) {
+ out->write(str, p);
+ } else {
+ buf.append(str);
+ }
+}
+
diff --git a/src/main/cpp/bytearrayinputstream.cpp b/src/main/cpp/bytearrayinputstream.cpp
new file mode 100755
index 0000000..b1aaaef
--- /dev/null
+++ b/src/main/cpp/bytearrayinputstream.cpp
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/bytearrayinputstream.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <apr_file_io.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <algorithm>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace std;
+
+IMPLEMENT_LOG4CXX_OBJECT(ByteArrayInputStream)
+
+ByteArrayInputStream::ByteArrayInputStream(const std::vector<unsigned char>& bytes) :
+ buf(bytes), pos(0) {
+}
+
+
+
+ByteArrayInputStream::~ByteArrayInputStream() {
+}
+
+
+void ByteArrayInputStream::close() {
+}
+
+
+int ByteArrayInputStream::read(ByteBuffer& dst) {
+ if (pos >= buf.size()) {
+ return -1;
+ } else {
+ size_t bytesCopied = min(dst.remaining(), buf.size() - pos);
+ memcpy(dst.current(), &buf[pos], bytesCopied);
+ pos += bytesCopied;
+ dst.position(dst.position() + bytesCopied);
+ return bytesCopied;
+ }
+}
diff --git a/src/main/cpp/bytearrayoutputstream.cpp b/src/main/cpp/bytearrayoutputstream.cpp
new file mode 100644
index 0000000..0a3d4c8
--- /dev/null
+++ b/src/main/cpp/bytearrayoutputstream.cpp
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/bytearrayoutputstream.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <string.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(ByteArrayOutputStream)
+
+ByteArrayOutputStream::ByteArrayOutputStream() {
+}
+
+ByteArrayOutputStream::~ByteArrayOutputStream() {
+}
+
+void ByteArrayOutputStream::close(Pool& /* p */) {
+}
+
+void ByteArrayOutputStream::flush(Pool& /* p */) {
+}
+
+void ByteArrayOutputStream::write(ByteBuffer& buf, Pool& /* p */ ) {
+ size_t sz = array.size();
+ array.resize(sz + buf.remaining());
+ memcpy(&array[sz], buf.current(), buf.remaining());
+ buf.position(buf.limit());
+}
+
+std::vector<unsigned char> ByteArrayOutputStream::toByteArray() const {
+ return array;
+}
+
+
+
diff --git a/src/main/cpp/bytebuffer.cpp b/src/main/cpp/bytebuffer.cpp
new file mode 100644
index 0000000..d8157cf
--- /dev/null
+++ b/src/main/cpp/bytebuffer.cpp
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/exception.h>
+#include <apr_pools.h>
+#include <log4cxx/helpers/pool.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+ByteBuffer::ByteBuffer(char* data1, size_t capacity)
+ : base(data1), pos(0), lim(capacity), cap(capacity) {
+}
+
+ByteBuffer::~ByteBuffer() {
+}
+
+void ByteBuffer::clear() {
+ lim = cap;
+ pos = 0;
+}
+
+void ByteBuffer::flip() {
+ lim = pos;
+ pos = 0;
+}
+
+void ByteBuffer::position(size_t newPosition) {
+ if (newPosition < lim) {
+ pos = newPosition;
+ } else {
+ pos = lim;
+ }
+}
+
+void ByteBuffer::limit(size_t newLimit) {
+ if (newLimit > cap) {
+ throw IllegalArgumentException(LOG4CXX_STR("newLimit"));
+ }
+ lim = newLimit;
+}
+
+
+bool ByteBuffer::put(char byte) {
+ if (pos < lim) {
+ base[pos++] = byte;
+ return true;
+ }
+ return false;
+}
diff --git a/src/main/cpp/cacheddateformat.cpp b/src/main/cpp/cacheddateformat.cpp
new file mode 100644
index 0000000..e7ede1e
--- /dev/null
+++ b/src/main/cpp/cacheddateformat.cpp
@@ -0,0 +1,309 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define __STDC_CONSTANT_MACROS
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/cacheddateformat.h>
+
+
+#include <apr_time.h>
+#include <log4cxx/helpers/pool.h>
+#include <limits>
+#include <log4cxx/helpers/exception.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::pattern;
+
+
+
+
+/**
+* Supported digit set. If the wrapped DateFormat uses
+* a different unit set, the millisecond pattern
+* will not be recognized and duplicate requests
+* will use the cache.
+*/
+const logchar CachedDateFormat::digits[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0 };
+
+/**
+ * Expected representation of first magic number.
+ */
+const logchar CachedDateFormat::magicString1[] = { 0x36, 0x35, 0x34, 0 };
+
+
+/**
+ * Expected representation of second magic number.
+ */
+const logchar CachedDateFormat::magicString2[] = { 0x39, 0x38, 0x37, 0};
+
+
+/**
+ * Expected representation of 0 milliseconds.
+ */
+const logchar CachedDateFormat::zeroString[] = { 0x30, 0x30, 0x30, 0 };
+
+#undef min
+
+/**
+ * Creates a new CachedDateFormat object.
+ * @param dateFormat Date format, may not be null.
+ * @param expiration maximum cached range in milliseconds.
+ * If the dateFormat is known to be incompatible with the
+ * caching algorithm, use a value of 0 to totally disable
+ * caching or 1 to only use cache for duplicate requests.
+ */
+CachedDateFormat::CachedDateFormat(const DateFormatPtr& dateFormat,
+ int expiration1) :
+ formatter(dateFormat),
+ millisecondStart(0),
+ slotBegin(std::numeric_limits<log4cxx_time_t>::min()),
+ cache(50, 0x20),
+ expiration(expiration1),
+ previousTime(std::numeric_limits<log4cxx_time_t>::min()) {
+ if (dateFormat == NULL) {
+ throw IllegalArgumentException(LOG4CXX_STR("dateFormat cannot be null"));
+ }
+ if (expiration1 < 0) {
+ throw IllegalArgumentException(LOG4CXX_STR("expiration must be non-negative"));
+ }
+}
+
+
+/**
+ * Finds start of millisecond field in formatted time.
+ * @param time long time, must be integral number of seconds
+ * @param formatted String corresponding formatted string
+ * @param formatter DateFormat date format
+ * @return int position in string of first digit of milliseconds,
+ * -1 indicates no millisecond field, -2 indicates unrecognized
+ * field (likely RelativeTimeDateFormat)
+ */
+int CachedDateFormat::findMillisecondStart(
+ log4cxx_time_t time, const LogString& formatted,
+ const DateFormatPtr& formatter,
+ Pool& pool) {
+
+ apr_time_t slotBegin = (time / 1000000) * 1000000;
+ if (slotBegin > time) {
+ slotBegin -= 1000000;
+ }
+ int millis = (int) (time - slotBegin)/1000;
+
+ int magic = magic1;
+ LogString magicString(magicString1);
+ if (millis == magic1) {
+ magic = magic2;
+ magicString = magicString2;
+ }
+
+ LogString plusMagic;
+ formatter->format(plusMagic, slotBegin + magic, pool);
+
+ /**
+ * If the string lengths differ then
+ * we can't use the cache except for duplicate requests.
+ */
+ if (plusMagic.length() != formatted.length()) {
+ return UNRECOGNIZED_MILLISECONDS;
+ } else {
+ // find first difference between values
+ for (LogString::size_type i = 0; i < formatted.length(); i++) {
+ if (formatted[i] != plusMagic[i]) {
+ //
+ // determine the expected digits for the base time
+ const logchar abc[] = { 0x41, 0x42, 0x43, 0 };
+ LogString formattedMillis(abc);
+ millisecondFormat(millis, formattedMillis, 0);
+
+ LogString plusZero;
+ formatter->format(plusZero, slotBegin, pool);
+
+ // If the next 3 characters match the magic
+ // strings and the remaining fragments are identical
+ //
+ //
+ if (plusZero.length() == formatted.length()
+ && regionMatches(magicString, 0, plusMagic, i, magicString.length())
+ && regionMatches(formattedMillis, 0, formatted, i, magicString.length())
+ && regionMatches(zeroString, 0, plusZero, i, 3)
+ && (formatted.length() == i + 3
+ || plusZero.compare(i + 3,
+ LogString::npos, plusMagic, i+3, LogString::npos) == 0)) {
+ return i;
+ } else {
+ return UNRECOGNIZED_MILLISECONDS;
+ }
+ }
+ }
+ }
+ return NO_MILLISECONDS;
+}
+
+
+/**
+ * Formats a millisecond count into a date/time string.
+ *
+ * @param now Number of milliseconds after midnight 1 Jan 1970 GMT.
+ * @param sbuf the string buffer to write to
+ */
+ void CachedDateFormat::format(LogString& buf, log4cxx_time_t now, Pool& p) const {
+
+ //
+ // If the current requested time is identical to the previously
+ // requested time, then append the cache contents.
+ //
+ if (now == previousTime) {
+ buf.append(cache);
+ return;
+ }
+
+ //
+ // If millisecond pattern was not unrecognized
+ // (that is if it was found or milliseconds did not appear)
+ //
+ if (millisecondStart != UNRECOGNIZED_MILLISECONDS) {
+
+ // Check if the cache is still valid.
+ // If the requested time is within the same integral second
+ // as the last request and a shorter expiration was not requested.
+ if (now < slotBegin + expiration
+ && now >= slotBegin
+ && now < slotBegin + 1000000L) {
+
+ //
+ // if there was a millisecond field then update it
+ //
+ if (millisecondStart >= 0 ) {
+ millisecondFormat((int) ((now - slotBegin)/1000), cache, millisecondStart);
+ }
+ //
+ // update the previously requested time
+ // (the slot begin should be unchanged)
+ previousTime = now;
+ buf.append(cache);
+ return;
+ }
+ }
+
+
+ //
+ // could not use previous value.
+ // Call underlying formatter to format date.
+ cache.erase(cache.begin(), cache.end());
+ formatter->format(cache, now, p);
+ buf.append(cache);
+ previousTime = now;
+ slotBegin = (previousTime / 1000000) * 1000000;
+ if (slotBegin > previousTime) {
+ slotBegin -= 1000000;
+ }
+
+
+ //
+ // if the milliseconds field was previous found
+ // then reevaluate in case it moved.
+ //
+ if (millisecondStart >= 0) {
+ millisecondStart = findMillisecondStart(now, cache, formatter, p);
+ }
+}
+
+
+/**
+ * Formats a count of milliseconds (0-999) into a numeric representation.
+ * @param millis Millisecond coun between 0 and 999.
+ * @buf String buffer, may not be null.
+ * @offset Starting position in buffer, the length of the
+ * buffer must be at least offset + 3.
+ */
+void CachedDateFormat::millisecondFormat(int millis,
+ LogString& buf,
+ int offset) {
+ buf[offset] = digits[ millis / 100];
+ buf[offset + 1] = digits[(millis / 10) % 10];
+ buf[offset + 2] = digits[millis % 10];
+ }
+
+/**
+ * Set timezone.
+ *
+ * @remarks Setting the timezone using getCalendar().setTimeZone()
+ * will likely cause caching to misbehave.
+ * @param timeZone TimeZone new timezone
+ */
+void CachedDateFormat::setTimeZone(const TimeZonePtr& timeZone) {
+ formatter->setTimeZone(timeZone);
+ previousTime = std::numeric_limits<log4cxx_time_t>::min();
+ slotBegin = std::numeric_limits<log4cxx_time_t>::min();
+}
+
+
+
+void CachedDateFormat::numberFormat(LogString& s, int n, Pool& p) const {
+ formatter->numberFormat(s, n, p);
+}
+
+
+/**
+ * Gets maximum cache validity for the specified SimpleDateTime
+ * conversion pattern.
+ * @param pattern conversion pattern, may not be null.
+ * @returns Duration in microseconds from an integral second
+ * that the cache will return consistent results.
+ */
+int CachedDateFormat::getMaximumCacheValidity(const LogString& pattern) {
+ //
+ // If there are more "S" in the pattern than just one "SSS" then
+ // (for example, "HH:mm:ss,SSS SSS"), then set the expiration to
+ // one millisecond which should only perform duplicate request caching.
+ //
+ const logchar S = 0x53;
+ const logchar SSS[] = { 0x53, 0x53, 0x53, 0 };
+ size_t firstS = pattern.find(S);
+ size_t len = pattern.length();
+ //
+ // if there are no S's or
+ // three that start with the first S and no fourth S in the string
+ //
+ if (firstS == LogString::npos ||
+ (len >= firstS + 3 && pattern.compare(firstS, 3, SSS) == 0
+ && (len == firstS + 3 ||
+ pattern.find(S, firstS + 3) == LogString::npos))) {
+ return 1000000;
+ }
+ return 1000;
+}
+
+
+/**
+* Tests if two string regions are equal.
+* @param target target string.
+* @param toffset character position in target to start comparison.
+* @param other other string.
+* @param ooffset character position in other to start comparison.
+* @param len length of region.
+* @return true if regions are equal.
+*/
+bool CachedDateFormat::regionMatches(
+ const LogString& target,
+ size_t toffset,
+ const LogString& other,
+ size_t ooffset,
+ size_t len) {
+ return target.compare(toffset, len, other, ooffset, len) == 0;
+}
+
diff --git a/src/main/cpp/charsetdecoder.cpp b/src/main/cpp/charsetdecoder.cpp
new file mode 100644
index 0000000..19534c0
--- /dev/null
+++ b/src/main/cpp/charsetdecoder.cpp
@@ -0,0 +1,490 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/charsetdecoder.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/mutex.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/helpers/pool.h>
+#include <apr_xlate.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+#include <locale.h>
+#include <apr_portable.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/transcoder.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(CharsetDecoder)
+
+
+namespace log4cxx
+{
+ namespace helpers {
+
+#if APR_HAS_XLATE
+ /**
+ * Converts from an arbitrary encoding to LogString
+ * using apr_xlate. Requires real iconv implementation,
+ * apr-iconv will crash in use.
+ */
+ class APRCharsetDecoder : public CharsetDecoder
+ {
+ public:
+ /**
+ * Creates a new instance.
+ * @param frompage name of source encoding.
+ */
+ APRCharsetDecoder(const LogString& frompage) : pool(), mutex(pool) {
+#if LOG4CXX_LOGCHAR_IS_WCHAR
+ const char* topage = "WCHAR_T";
+#endif
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ const char* topage = "UTF-8";
+#endif
+#if LOG4CXX_LOGCHAR_IS_UNICHAR
+ const char* topage = "UTF-16";
+#endif
+ std::string fpage(Transcoder::encodeCharsetName(frompage));
+ apr_status_t stat = apr_xlate_open(&convset,
+ topage,
+ fpage.c_str(),
+ pool.getAPRPool());
+ if (stat != APR_SUCCESS) {
+ throw IllegalArgumentException(frompage);
+ }
+ }
+
+ /**
+ * Destructor.
+ */
+ virtual ~APRCharsetDecoder() {
+ }
+
+ virtual log4cxx_status_t decode(ByteBuffer& in,
+ LogString& out) {
+ enum { BUFSIZE = 256 };
+ logchar buf[BUFSIZE];
+ const apr_size_t initial_outbytes_left = BUFSIZE * sizeof(logchar);
+ apr_status_t stat = APR_SUCCESS;
+ if (in.remaining() == 0) {
+ size_t outbytes_left = initial_outbytes_left;
+ {
+ synchronized sync(mutex);
+ stat = apr_xlate_conv_buffer((apr_xlate_t*) convset,
+ NULL, NULL, (char*) buf, &outbytes_left);
+ }
+ out.append(buf, (initial_outbytes_left - outbytes_left)/sizeof(logchar));
+ } else {
+ while(in.remaining() > 0 && stat == APR_SUCCESS) {
+ size_t inbytes_left = in.remaining();
+ size_t initial_inbytes_left = inbytes_left;
+ size_t pos = in.position();
+ apr_size_t outbytes_left = initial_outbytes_left;
+ {
+ synchronized sync(mutex);
+ stat = apr_xlate_conv_buffer((apr_xlate_t*) convset,
+ in.data() + pos,
+ &inbytes_left,
+ (char*) buf,
+ &outbytes_left);
+ }
+ out.append(buf, (initial_outbytes_left - outbytes_left)/sizeof(logchar));
+ in.position(pos + (initial_inbytes_left - inbytes_left));
+ }
+ }
+ return stat;
+ }
+
+ private:
+ APRCharsetDecoder(const APRCharsetDecoder&);
+ APRCharsetDecoder& operator=(const APRCharsetDecoder&);
+ log4cxx::helpers::Pool pool;
+ Mutex mutex;
+ apr_xlate_t *convset;
+ };
+
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_MBSRTOWCS
+ /**
+ * Converts from the default multi-byte string to
+ * LogString using mbstowcs.
+ *
+ */
+ class MbstowcsCharsetDecoder : public CharsetDecoder
+ {
+ public:
+ MbstowcsCharsetDecoder() {
+ }
+
+ virtual ~MbstowcsCharsetDecoder() {
+ }
+
+ private:
+ inline log4cxx_status_t append(LogString& out, const wchar_t* buf) {
+ out.append(buf);
+ return APR_SUCCESS;
+ }
+
+ virtual log4cxx_status_t decode(ByteBuffer& in,
+ LogString& out) {
+ log4cxx_status_t stat = APR_SUCCESS;
+ enum { BUFSIZE = 256 };
+ wchar_t buf[BUFSIZE];
+
+ mbstate_t mbstate;
+ memset(&mbstate, 0, sizeof(mbstate));
+
+ while(in.remaining() > 0) {
+ size_t requested = in.remaining();
+ if (requested > BUFSIZE - 1) {
+ requested = BUFSIZE - 1;
+ }
+
+ memset(buf, 0, BUFSIZE*sizeof(wchar_t));
+ const char* src = in.current();
+ if(*src == 0) {
+ out.append(1, (logchar) 0);
+ in.position(in.position() + 1);
+ } else {
+ size_t converted = mbsrtowcs(buf,
+ &src,
+ requested,
+ &mbstate);
+ if (converted == (size_t) -1) {
+ stat = APR_BADARG;
+ in.position(src - in.data());
+ break;
+ } else {
+ stat = append(out, buf);
+ in.position(in.position() + converted);
+ }
+ }
+ }
+ return stat;
+ }
+
+
+
+ private:
+ MbstowcsCharsetDecoder(const MbstowcsCharsetDecoder&);
+ MbstowcsCharsetDecoder& operator=(const MbstowcsCharsetDecoder&);
+ };
+#endif
+
+
+ /**
+ * Decoder used when the external and internal charsets
+ * are the same.
+ *
+ */
+ class TrivialCharsetDecoder : public CharsetDecoder
+ {
+ public:
+ TrivialCharsetDecoder() {
+ }
+
+ virtual ~TrivialCharsetDecoder() {
+ }
+
+ virtual log4cxx_status_t decode(ByteBuffer& in,
+ LogString& out) {
+ size_t remaining = in.remaining();
+ if( remaining > 0) {
+ const logchar* src = (const logchar*) (in.data() + in.position());
+ size_t count = remaining / sizeof(logchar);
+ out.append(src, count);
+ in.position(in.position() + remaining);
+ }
+ return APR_SUCCESS;
+ }
+
+
+
+ private:
+ TrivialCharsetDecoder(const TrivialCharsetDecoder&);
+ TrivialCharsetDecoder& operator=(const TrivialCharsetDecoder&);
+ };
+
+
+#if LOG4CXX_LOGCHAR_IS_UTF8
+typedef TrivialCharsetDecoder UTF8CharsetDecoder;
+#else
+/**
+* Converts from UTF-8 to std::wstring
+*
+*/
+class UTF8CharsetDecoder : public CharsetDecoder
+{
+public:
+ UTF8CharsetDecoder() {
+ }
+
+ virtual ~UTF8CharsetDecoder() {
+ }
+
+private:
+ virtual log4cxx_status_t decode(ByteBuffer& in,
+ LogString& out) {
+ if (in.remaining() > 0) {
+ std::string tmp(in.current(), in.remaining());
+ std::string::const_iterator iter = tmp.begin();
+ while(iter != tmp.end()) {
+ unsigned int sv = Transcoder::decode(tmp, iter);
+ if (sv == 0xFFFF) {
+ size_t offset = iter - tmp.begin();
+ in.position(in.position() + offset);
+ return APR_BADARG;
+ } else {
+ Transcoder::encode(sv, out);
+ }
+ }
+ in.position(in.limit());
+ }
+ return APR_SUCCESS;
+ }
+
+private:
+ UTF8CharsetDecoder(const UTF8CharsetDecoder&);
+ UTF8CharsetDecoder& operator=(const UTF8CharsetDecoder&);
+};
+#endif
+
+/**
+* Converts from ISO-8859-1 to LogString.
+*
+*/
+class ISOLatinCharsetDecoder : public CharsetDecoder
+{
+public:
+ ISOLatinCharsetDecoder() {
+ }
+
+ virtual ~ISOLatinCharsetDecoder() {
+ }
+
+private:
+ virtual log4cxx_status_t decode(ByteBuffer& in,
+ LogString& out) {
+ if (in.remaining() > 0) {
+
+ const unsigned char* src = (unsigned char*) in.current();
+ const unsigned char* srcEnd = src + in.remaining();
+ while(src < srcEnd) {
+ unsigned int sv = *(src++);
+ Transcoder::encode(sv, out);
+ }
+ in.position(in.limit());
+ }
+ return APR_SUCCESS;
+ }
+
+
+
+private:
+ ISOLatinCharsetDecoder(const ISOLatinCharsetDecoder&);
+ ISOLatinCharsetDecoder& operator=(const ISOLatinCharsetDecoder&);
+};
+
+
+/**
+* Converts from US-ASCII to LogString.
+*
+*/
+class USASCIICharsetDecoder : public CharsetDecoder
+{
+public:
+ USASCIICharsetDecoder() {
+ }
+
+ virtual ~USASCIICharsetDecoder() {
+ }
+
+private:
+
+ virtual log4cxx_status_t decode(ByteBuffer& in,
+ LogString& out) {
+ log4cxx_status_t stat = APR_SUCCESS;
+ if (in.remaining() > 0) {
+
+ const unsigned char* src = (unsigned char*) in.current();
+ const unsigned char* srcEnd = src + in.remaining();
+ while(src < srcEnd) {
+ unsigned char sv = *src;
+ if (sv < 0x80) {
+ src++;
+ Transcoder::encode(sv, out);
+ } else {
+ stat = APR_BADARG;
+ break;
+ }
+ }
+ in.position(src - (const unsigned char*) in.data());
+ }
+ return stat;
+ }
+
+
+
+private:
+ USASCIICharsetDecoder(const USASCIICharsetDecoder&);
+ USASCIICharsetDecoder& operator=(const USASCIICharsetDecoder&);
+};
+
+ /**
+ * Charset decoder that uses an embedded CharsetDecoder consistent
+ * with current locale settings.
+ */
+ class LocaleCharsetDecoder : public CharsetDecoder {
+ public:
+ LocaleCharsetDecoder() : pool(), mutex(pool), decoder(), encoding() {
+ }
+ virtual ~LocaleCharsetDecoder() {
+ }
+ virtual log4cxx_status_t decode(ByteBuffer& in,
+ LogString& out) {
+ const char* p = in.current();
+ size_t i = in.position();
+#if !LOG4CXX_CHARSET_EBCDIC
+ for (; i < in.limit() && ((unsigned int) *p) < 0x80; i++, p++) {
+ out.append(1, *p);
+ }
+ in.position(i);
+#endif
+ if (i < in.limit()) {
+ Pool subpool;
+ const char* enc = apr_os_locale_encoding(subpool.getAPRPool());
+ {
+ synchronized sync(mutex);
+ if (enc == 0) {
+ if (decoder == 0) {
+ encoding = "C";
+ decoder = new USASCIICharsetDecoder();
+ }
+ } else if (encoding != enc) {
+ encoding = enc;
+ try {
+ LogString e;
+ Transcoder::decode(encoding, e);
+ decoder = getDecoder(e);
+ } catch (IllegalArgumentException& ex) {
+ decoder = new USASCIICharsetDecoder();
+ }
+ }
+ }
+ return decoder->decode(in, out);
+ }
+ return APR_SUCCESS;
+ }
+ private:
+ Pool pool;
+ Mutex mutex;
+ CharsetDecoderPtr decoder;
+ std::string encoding;
+ };
+
+
+
+ } // namespace helpers
+
+} //namespace log4cxx
+
+
+CharsetDecoder::CharsetDecoder() {
+}
+
+
+CharsetDecoder::~CharsetDecoder() {
+}
+
+CharsetDecoder* CharsetDecoder::createDefaultDecoder() {
+#if LOG4CXX_CHARSET_UTF8
+ return new UTF8CharsetDecoder();
+#elif LOG4CXX_CHARSET_ISO88591 || defined(_WIN32_WCE)
+ return new ISOLatinCharsetDecoder();
+#elif LOG4CXX_CHARSET_USASCII
+ return new USASCIICharsetDecoder();
+#elif LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_MBSRTOWCS
+ return new MbstowcsCharsetDecoder();
+#else
+ return new LocaleCharsetDecoder();
+#endif
+}
+
+CharsetDecoderPtr CharsetDecoder::getDefaultDecoder() {
+ static CharsetDecoderPtr decoder(createDefaultDecoder());
+ //
+ // if invoked after static variable destruction
+ // (if logging is called in the destructor of a static object)
+ // then create a new decoder.
+ //
+ if (decoder == 0) {
+ return createDefaultDecoder();
+ }
+ return decoder;
+}
+
+CharsetDecoderPtr CharsetDecoder::getUTF8Decoder() {
+ static CharsetDecoderPtr decoder(new UTF8CharsetDecoder());
+ //
+ // if invoked after static variable destruction
+ // (if logging is called in the destructor of a static object)
+ // then create a new decoder.
+ //
+ if (decoder == 0) {
+ return new UTF8CharsetDecoder();
+ }
+ return decoder;
+}
+
+CharsetDecoderPtr CharsetDecoder::getISOLatinDecoder() {
+ return new ISOLatinCharsetDecoder();
+}
+
+
+CharsetDecoderPtr CharsetDecoder::getDecoder(const LogString& charset) {
+ if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF-8"), LOG4CXX_STR("utf-8")) ||
+ StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF8"), LOG4CXX_STR("utf8"))) {
+ return new UTF8CharsetDecoder();
+ } else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("C"), LOG4CXX_STR("c")) ||
+ charset == LOG4CXX_STR("646") ||
+ StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("US-ASCII"), LOG4CXX_STR("us-ascii")) ||
+ StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO646-US"), LOG4CXX_STR("iso646-US")) ||
+ StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ANSI_X3.4-1968"), LOG4CXX_STR("ansi_x3.4-1968"))) {
+ return new USASCIICharsetDecoder();
+ } else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-8859-1"), LOG4CXX_STR("iso-8859-1")) ||
+ StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-LATIN-1"), LOG4CXX_STR("iso-latin-1"))) {
+ return new ISOLatinCharsetDecoder();
+ }
+#if APR_HAS_XLATE || !defined(_WIN32)
+ return new APRCharsetDecoder(charset);
+#else
+ throw IllegalArgumentException(charset);
+#endif
+}
+
+
+
+
+
+
diff --git a/src/main/cpp/charsetencoder.cpp b/src/main/cpp/charsetencoder.cpp
new file mode 100644
index 0000000..a5a09c4
--- /dev/null
+++ b/src/main/cpp/charsetencoder.cpp
@@ -0,0 +1,518 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/charsetencoder.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/exception.h>
+#include <apr_xlate.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/transcoder.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+#include <apr_portable.h>
+#include <log4cxx/helpers/mutex.h>
+#include <log4cxx/helpers/synchronized.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(CharsetEncoder)
+
+namespace log4cxx
+{
+
+ namespace helpers {
+
+#if APR_HAS_XLATE
+ /**
+ * A character encoder implemented using apr_xlate.
+ */
+ class APRCharsetEncoder : public CharsetEncoder
+ {
+ public:
+ APRCharsetEncoder(const LogString& topage) : pool(), mutex(pool) {
+#if LOG4CXX_LOGCHAR_IS_WCHAR
+ const char* frompage = "WCHAR_T";
+#endif
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ const char* frompage = "UTF-8";
+#endif
+#if LOG4CXX_LOGCHAR_IS_UNICHAR
+ const char* frompage = "UTF-16";
+#endif
+ std::string tpage(Transcoder::encodeCharsetName(topage));
+ apr_status_t stat = apr_xlate_open(&convset,
+ tpage.c_str(),
+ frompage,
+ pool.getAPRPool());
+ if (stat != APR_SUCCESS) {
+ throw IllegalArgumentException(topage);
+ }
+ }
+
+ virtual ~APRCharsetEncoder() {
+ }
+
+ virtual log4cxx_status_t encode(const LogString& in,
+ LogString::const_iterator& iter,
+ ByteBuffer& out) {
+ apr_status_t stat;
+ size_t outbytes_left = out.remaining();
+ size_t initial_outbytes_left = outbytes_left;
+ size_t position = out.position();
+ if (iter == in.end()) {
+ synchronized sync(mutex);
+ stat = apr_xlate_conv_buffer(convset, NULL, NULL,
+ out.data() + position, &outbytes_left);
+ } else {
+ LogString::size_type inOffset = (iter - in.begin());
+ apr_size_t inbytes_left =
+ (in.size() - inOffset) * sizeof(LogString::value_type);
+ apr_size_t initial_inbytes_left = inbytes_left;
+ {
+ synchronized sync(mutex);
+ stat = apr_xlate_conv_buffer(convset,
+ (const char*) (in.data() + inOffset),
+ &inbytes_left,
+ out.data() + position,
+ &outbytes_left);
+ }
+ iter += ((initial_inbytes_left - inbytes_left) / sizeof(LogString::value_type));
+ }
+ out.position(out.position() + (initial_outbytes_left - outbytes_left));
+ return stat;
+ }
+
+ private:
+ APRCharsetEncoder(const APRCharsetEncoder&);
+ APRCharsetEncoder& operator=(const APRCharsetEncoder&);
+ Pool pool;
+ Mutex mutex;
+ apr_xlate_t *convset;
+ };
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_WCSTOMBS
+ /**
+ * A character encoder implemented using wcstombs.
+ */
+ class WcstombsCharsetEncoder : public CharsetEncoder
+ {
+ public:
+ WcstombsCharsetEncoder() {
+ }
+
+ /**
+ * Converts a wchar_t to the default external multibyte encoding.
+ */
+ log4cxx_status_t encode(const LogString& in,
+ LogString::const_iterator& iter,
+ ByteBuffer& out) {
+ log4cxx_status_t stat = APR_SUCCESS;
+
+ if (iter != in.end()) {
+ size_t outbytes_left = out.remaining();
+ size_t position = out.position();
+ std::wstring::size_type inOffset = (iter - in.begin());
+ enum { BUFSIZE = 256 };
+ wchar_t buf[BUFSIZE];
+ size_t chunkSize = BUFSIZE - 1;
+ if (chunkSize * MB_LEN_MAX > outbytes_left) {
+ chunkSize = outbytes_left / MB_LEN_MAX;
+ }
+ if (chunkSize > in.length() - inOffset) {
+ chunkSize = in.length() - inOffset;
+ }
+ memset(buf, 0, BUFSIZE * sizeof(wchar_t));
+ memcpy(buf,
+ in.data() + inOffset,
+ chunkSize * sizeof(wchar_t));
+ size_t converted = wcstombs(out.data() + position, buf, outbytes_left);
+
+ if (converted == (size_t) -1) {
+ stat = APR_BADARG;
+ //
+ // if unconvertable character was encountered
+ // repeatedly halve source to get fragment that
+ // can be converted
+ for(chunkSize /= 2;
+ chunkSize > 0;
+ chunkSize /= 2) {
+ buf[chunkSize] = 0;
+ converted = wcstombs(out.data() + position, buf, outbytes_left);
+ if (converted != (size_t) -1) {
+ iter += chunkSize;
+ out.position(out.position() + converted);
+ break;
+ }
+ }
+ } else {
+ iter += chunkSize;
+ out.position(out.position() + converted);
+ }
+ }
+ return stat;
+ }
+
+
+
+ private:
+ WcstombsCharsetEncoder(const WcstombsCharsetEncoder&);
+ WcstombsCharsetEncoder& operator=(const WcstombsCharsetEncoder&);
+ };
+#endif
+
+
+ /**
+ * Encodes a LogString to US-ASCII.
+ */
+ class USASCIICharsetEncoder : public CharsetEncoder
+ {
+ public:
+ USASCIICharsetEncoder() {
+ }
+
+ virtual log4cxx_status_t encode(const LogString& in,
+ LogString::const_iterator& iter,
+ ByteBuffer& out) {
+ log4cxx_status_t stat = APR_SUCCESS;
+ if (iter != in.end()) {
+ while(out.remaining() > 0 && iter != in.end()) {
+ LogString::const_iterator prev(iter);
+ unsigned int sv = Transcoder::decode(in, iter);
+ if (sv <= 0x7F) {
+ out.put((char) sv);
+ } else {
+ iter = prev;
+ stat = APR_BADARG;
+ break;
+ }
+ }
+ }
+ return stat;
+ }
+
+ private:
+ USASCIICharsetEncoder(const USASCIICharsetEncoder&);
+ USASCIICharsetEncoder& operator=(const USASCIICharsetEncoder&);
+ };
+
+ /**
+ * Converts a LogString to ISO-8859-1.
+ */
+ class ISOLatinCharsetEncoder : public CharsetEncoder
+ {
+ public:
+ ISOLatinCharsetEncoder() {
+ }
+
+ virtual log4cxx_status_t encode(const LogString& in,
+ LogString::const_iterator& iter,
+ ByteBuffer& out) {
+ log4cxx_status_t stat = APR_SUCCESS;
+ if (iter != in.end()) {
+ while(out.remaining() > 0 && iter != in.end()) {
+ LogString::const_iterator prev(iter);
+ unsigned int sv = Transcoder::decode(in, iter);
+ if (sv <= 0xFF) {
+ out.put((char) sv);
+ } else {
+ iter = prev;
+ stat = APR_BADARG;
+ break;
+ }
+ }
+ }
+ return stat;
+ }
+
+ private:
+ ISOLatinCharsetEncoder(const ISOLatinCharsetEncoder&);
+ ISOLatinCharsetEncoder& operator=(const ISOLatinCharsetEncoder&);
+ };
+
+ /**
+ * Encodes a LogString to a byte array when the encodings are identical.
+ */
+ class TrivialCharsetEncoder : public CharsetEncoder
+ {
+ public:
+ TrivialCharsetEncoder() {
+ }
+
+
+ virtual log4cxx_status_t encode(const LogString& in,
+ LogString::const_iterator& iter,
+ ByteBuffer& out) {
+ if(iter != in.end()) {
+ size_t requested = in.length() - (iter - in.begin());
+ if (requested > out.remaining()/sizeof(logchar)) {
+ requested = out.remaining()/sizeof(logchar);
+ }
+ memcpy(out.current(),
+ (const char*) in.data() + (iter - in.begin()),
+ requested * sizeof(logchar));
+ iter += requested;
+ out.position(out.position() + requested * sizeof(logchar));
+ }
+ return APR_SUCCESS;
+ }
+
+ private:
+ TrivialCharsetEncoder(const TrivialCharsetEncoder&);
+ TrivialCharsetEncoder& operator=(const TrivialCharsetEncoder&);
+ };
+
+#if LOG4CXX_LOGCHAR_IS_UTF8
+typedef TrivialCharsetEncoder UTF8CharsetEncoder;
+#else
+/**
+ * Converts a LogString to UTF-8.
+ */
+class UTF8CharsetEncoder : public CharsetEncoder {
+public:
+ UTF8CharsetEncoder() {
+ }
+
+ virtual log4cxx_status_t encode(const LogString& in,
+ LogString::const_iterator& iter,
+ ByteBuffer& out) {
+ while(iter != in.end() && out.remaining() >= 8) {
+ unsigned int sv = Transcoder::decode(in, iter);
+ if (sv == 0xFFFF) {
+ return APR_BADARG;
+ }
+ Transcoder::encodeUTF8(sv, out);
+ }
+ return APR_SUCCESS;
+ }
+
+private:
+ UTF8CharsetEncoder(const UTF8CharsetEncoder&);
+ UTF8CharsetEncoder& operator=(const UTF8CharsetEncoder&);
+};
+#endif
+
+/**
+ * Encodes a LogString to UTF16-BE.
+ */
+class UTF16BECharsetEncoder : public CharsetEncoder {
+public:
+ UTF16BECharsetEncoder() {
+ }
+
+ virtual log4cxx_status_t encode(const LogString& in,
+ LogString::const_iterator& iter,
+ ByteBuffer& out) {
+ while(iter != in.end() && out.remaining() >= 4) {
+ unsigned int sv = Transcoder::decode(in, iter);
+ if (sv == 0xFFFF) {
+ return APR_BADARG;
+ }
+ Transcoder::encodeUTF16BE(sv, out);
+ }
+ return APR_SUCCESS;
+ }
+
+private:
+ UTF16BECharsetEncoder(const UTF16BECharsetEncoder&);
+ UTF16BECharsetEncoder& operator=(const UTF16BECharsetEncoder&);
+};
+
+/**
+ * Encodes a LogString to UTF16-LE.
+ */
+class UTF16LECharsetEncoder : public CharsetEncoder {
+public:
+ UTF16LECharsetEncoder() {
+ }
+
+
+ virtual log4cxx_status_t encode(const LogString& in,
+ LogString::const_iterator& iter,
+ ByteBuffer& out) {
+ while(iter != in.end() && out.remaining() >= 4) {
+ unsigned int sv = Transcoder::decode(in, iter);
+ if (sv == 0xFFFF) {
+ return APR_BADARG;
+ }
+ Transcoder::encodeUTF16LE(sv, out);
+ }
+ return APR_SUCCESS;
+ }
+private:
+ UTF16LECharsetEncoder(const UTF16LECharsetEncoder&);
+ UTF16LECharsetEncoder& operator=(const UTF16LECharsetEncoder&);
+};
+
+/**
+ * Charset encoder that uses an embedded CharsetEncoder consistent
+ * with current locale settings.
+ */
+class LocaleCharsetEncoder : public CharsetEncoder {
+public:
+ LocaleCharsetEncoder() : pool(), mutex(pool), encoder(), encoding() {
+ }
+ virtual ~LocaleCharsetEncoder() {
+ }
+ virtual log4cxx_status_t encode(const LogString& in,
+ LogString::const_iterator& iter,
+ ByteBuffer& out) {
+#if !LOG4CXX_CHARSET_EBCDIC
+ char* current = out.current();
+ size_t remain = out.remaining();
+ for(;
+ iter != in.end() && ((unsigned int) *iter) < 0x80 && remain > 0;
+ iter++, remain--, current++) {
+ *current = *iter;
+ }
+ out.position(current - out.data());
+#endif
+ if (iter != in.end() && out.remaining() > 0) {
+ Pool subpool;
+ const char* enc = apr_os_locale_encoding(subpool.getAPRPool());
+ {
+ synchronized sync(mutex);
+ if (enc == 0) {
+ if (encoder == 0) {
+ encoding = "C";
+ encoder = new USASCIICharsetEncoder();
+ }
+ } else if (encoding != enc) {
+ encoding = enc;
+ LogString ename;
+ Transcoder::decode(encoding, ename);
+ try {
+ encoder = CharsetEncoder::getEncoder(ename);
+ } catch(IllegalArgumentException ex) {
+ encoder = new USASCIICharsetEncoder();
+ }
+ }
+ }
+ return encoder->encode(in, iter, out);
+ }
+ return APR_SUCCESS;
+ }
+
+private:
+ LocaleCharsetEncoder(const LocaleCharsetEncoder&);
+ LocaleCharsetEncoder& operator=(const LocaleCharsetEncoder&);
+ Pool pool;
+ Mutex mutex;
+ CharsetEncoderPtr encoder;
+ std::string encoding;
+};
+
+
+ } // namespace helpers
+
+} //namespace log4cxx
+
+
+
+CharsetEncoder::CharsetEncoder() {
+}
+
+CharsetEncoder::~CharsetEncoder() {
+}
+
+CharsetEncoderPtr CharsetEncoder::getDefaultEncoder() {
+ static CharsetEncoderPtr encoder(createDefaultEncoder());
+ //
+ // if invoked after static variable destruction
+ // (if logging is called in the destructor of a static object)
+ // then create a new decoder.
+ //
+ if (encoder == 0) {
+ return createDefaultEncoder();
+ }
+ return encoder;
+}
+
+CharsetEncoder* CharsetEncoder::createDefaultEncoder() {
+#if LOG4CXX_CHARSET_UTF8
+ return new UTF8CharsetEncoder();
+#elif LOG4CXX_CHARSET_ISO88591
+ return new ISOLatinCharsetEncoder();
+#elif LOG4CXX_CHARSET_USASCII
+ return new USASCIICharsetEncoder();
+#elif LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_WCSTOMBS
+ return new WcstombsCharsetEncoder();
+#else
+ return new LocaleCharsetEncoder();
+#endif
+}
+
+
+CharsetEncoderPtr CharsetEncoder::getUTF8Encoder() {
+ return new UTF8CharsetEncoder();
+}
+
+
+
+CharsetEncoderPtr CharsetEncoder::getEncoder(const LogString& charset) {
+ if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF-8"), LOG4CXX_STR("utf-8"))) {
+ return new UTF8CharsetEncoder();
+ } else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("C"), LOG4CXX_STR("c")) ||
+ charset == LOG4CXX_STR("646") ||
+ StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("US-ASCII"), LOG4CXX_STR("us-ascii")) ||
+ StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO646-US"), LOG4CXX_STR("iso646-US")) ||
+ StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ANSI_X3.4-1968"), LOG4CXX_STR("ansi_x3.4-1968"))) {
+ return new USASCIICharsetEncoder();
+ } else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-8859-1"), LOG4CXX_STR("iso-8859-1")) ||
+ StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-LATIN-1"), LOG4CXX_STR("iso-latin-1"))) {
+ return new ISOLatinCharsetEncoder();
+ } else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF-16BE"), LOG4CXX_STR("utf-16be"))
+ || StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF-16"), LOG4CXX_STR("utf-16"))) {
+ return new UTF16BECharsetEncoder();
+ } else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF-16LE"), LOG4CXX_STR("utf-16le"))) {
+ return new UTF16LECharsetEncoder();
+ }
+#if APR_HAS_XLATE || !defined(_WIN32)
+ return new APRCharsetEncoder(charset);
+#else
+ throw IllegalArgumentException(charset);
+#endif
+}
+
+
+void CharsetEncoder::reset() {
+}
+
+void CharsetEncoder::flush(ByteBuffer& /* out */ ) {
+}
+
+
+void CharsetEncoder::encode(CharsetEncoderPtr& enc,
+ const LogString& src,
+ LogString::const_iterator& iter,
+ ByteBuffer& dst) {
+ log4cxx_status_t stat = enc->encode(src, iter, dst);
+ if (stat != APR_SUCCESS && iter != src.end()) {
+#if LOG4CXX_LOGCHAR_IS_WCHAR || LOG4CXX_LOGCHAR_IS_UNICHAR
+ iter++;
+#elif LOG4CXX_LOGCHAR_IS_UTF8
+ // advance past this character and all continuation characters
+ while((*(++iter) & 0xC0) == 0x80);
+#else
+#error logchar is unrecognized
+#endif
+ dst.put(Transcoder::LOSSCHAR);
+ }
+}
diff --git a/src/main/cpp/class.cpp b/src/main/cpp/class.cpp
new file mode 100644
index 0000000..423f877
--- /dev/null
+++ b/src/main/cpp/class.cpp
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/class.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/object.h>
+#include <map>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/log4cxx.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+#include <log4cxx/rollingfileappender.h>
+#include <log4cxx/dailyrollingfileappender.h>
+
+
+#include <log4cxx/asyncappender.h>
+#include <log4cxx/consoleappender.h>
+#include <log4cxx/fileappender.h>
+#include <log4cxx/db/odbcappender.h>
+#if defined(WIN32) || defined(_WIN32)
+#if !defined(_WIN32_WCE)
+#include <log4cxx/nt/nteventlogappender.h>
+#endif
+#include <log4cxx/nt/outputdebugstringappender.h>
+#endif
+#include <log4cxx/net/smtpappender.h>
+#include <log4cxx/net/socketappender.h>
+#include <log4cxx/net/sockethubappender.h>
+#include <log4cxx/helpers/datagramsocket.h>
+#include <log4cxx/net/syslogappender.h>
+#include <log4cxx/net/telnetappender.h>
+#include <log4cxx/writerappender.h>
+#include <log4cxx/net/xmlsocketappender.h>
+#include <log4cxx/layout.h>
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/htmllayout.h>
+#include <log4cxx/simplelayout.h>
+#include <log4cxx/xml/xmllayout.h>
+#include <log4cxx/ttcclayout.h>
+
+#include <log4cxx/filter/levelmatchfilter.h>
+#include <log4cxx/filter/levelrangefilter.h>
+#include <log4cxx/filter/stringmatchfilter.h>
+#include <log4cxx/rolling/filterbasedtriggeringpolicy.h>
+#include <log4cxx/rolling/fixedwindowrollingpolicy.h>
+#include <log4cxx/rolling/manualtriggeringpolicy.h>
+#include <log4cxx/rolling/rollingfileappender.h>
+#include <log4cxx/rolling/sizebasedtriggeringpolicy.h>
+#include <log4cxx/rolling/timebasedrollingpolicy.h>
+
+#include <log4cxx/xml/domconfigurator.h>
+#include <log4cxx/propertyconfigurator.h>
+#include <apr.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::net;
+using namespace log4cxx::filter;
+using namespace log4cxx::xml;
+using namespace log4cxx::rolling;
+
+Class::Class() {
+}
+
+Class::~Class()
+{
+}
+
+LogString Class::toString() const
+{
+ return getName();
+}
+
+ObjectPtr Class::newInstance() const
+{
+ throw InstantiationException(LOG4CXX_STR("Cannot create new instances of Class."));
+#if LOG4CXX_RETURN_AFTER_THROW
+ return 0;
+#endif
+}
+
+
+
+Class::ClassMap& Class::getRegistry() {
+ static ClassMap registry;
+ return registry;
+}
+
+const Class& Class::forName(const LogString& className)
+{
+ LogString lowerName(StringHelper::toLowerCase(className));
+ //
+ // check registry using full class name
+ //
+ const Class* clazz = getRegistry()[lowerName];
+ if (clazz == 0) {
+ LogString::size_type pos = className.find_last_of(LOG4CXX_STR(".$"));
+ if (pos != LogString::npos) {
+ LogString terminalName(lowerName, pos + 1, LogString::npos);
+ clazz = getRegistry()[terminalName];
+ if (clazz == 0) {
+ registerClasses();
+ clazz = getRegistry()[lowerName];
+ if (clazz == 0) {
+ clazz = getRegistry()[terminalName];
+ }
+ }
+ } else {
+ registerClasses();
+ clazz = getRegistry()[lowerName];
+ }
+ }
+ if (clazz == 0) {
+ throw ClassNotFoundException(className);
+ }
+
+ return *clazz;
+}
+
+bool Class::registerClass(const Class& newClass)
+{
+ getRegistry()[StringHelper::toLowerCase(newClass.getName())] = &newClass;
+ return true;
+}
+
+void Class::registerClasses() {
+#if APR_HAS_THREADS
+ AsyncAppender::registerClass();
+#endif
+ ConsoleAppender::registerClass();
+ FileAppender::registerClass();
+ log4cxx::db::ODBCAppender::registerClass();
+#if (defined(WIN32) || defined(_WIN32))
+#if !defined(_WIN32_WCE)
+ log4cxx::nt::NTEventLogAppender::registerClass();
+#endif
+ log4cxx::nt::OutputDebugStringAppender::registerClass();
+#endif
+ log4cxx::RollingFileAppender::registerClass();
+ SMTPAppender::registerClass();
+ SocketAppender::registerClass();
+#if APR_HAS_THREADS
+ SocketHubAppender::registerClass();
+#endif
+ SyslogAppender::registerClass();
+#if APR_HAS_THREADS
+ TelnetAppender::registerClass();
+#endif
+ XMLSocketAppender::registerClass();
+ DateLayout::registerClass();
+ HTMLLayout::registerClass();
+ PatternLayout::registerClass();
+ SimpleLayout::registerClass();
+ TTCCLayout::registerClass();
+ XMLLayout::registerClass();
+ LevelMatchFilter::registerClass();
+ LevelRangeFilter::registerClass();
+ StringMatchFilter::registerClass();
+ log4cxx::RollingFileAppender::registerClass();
+ log4cxx::rolling::RollingFileAppender::registerClass();
+ DailyRollingFileAppender::registerClass();
+ log4cxx::rolling::SizeBasedTriggeringPolicy::registerClass();
+ log4cxx::rolling::TimeBasedRollingPolicy::registerClass();
+ log4cxx::rolling::ManualTriggeringPolicy::registerClass();
+ log4cxx::rolling::FixedWindowRollingPolicy::registerClass();
+ log4cxx::rolling::FilterBasedTriggeringPolicy::registerClass();
+ log4cxx::xml::DOMConfigurator::registerClass();
+ log4cxx::PropertyConfigurator::registerClass();
+}
+
diff --git a/src/main/cpp/classnamepatternconverter.cpp b/src/main/cpp/classnamepatternconverter.cpp
new file mode 100644
index 0000000..26246b9
--- /dev/null
+++ b/src/main/cpp/classnamepatternconverter.cpp
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/classnamepatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+
+ using namespace log4cxx;
+ using namespace log4cxx::pattern;
+ using namespace log4cxx::spi;
+ using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(ClassNamePatternConverter)
+
+ClassNamePatternConverter::ClassNamePatternConverter(
+ const std::vector<LogString>& options) :
+ NamePatternConverter(LOG4CXX_STR("Class Name"),
+ LOG4CXX_STR("class name"), options) {
+}
+
+PatternConverterPtr ClassNamePatternConverter::newInstance(
+ const std::vector<LogString>& options) {
+ if (options.size() == 0) {
+ static PatternConverterPtr def(new ClassNamePatternConverter(options));
+ return def;
+ }
+ return new ClassNamePatternConverter(options);
+}
+
+void ClassNamePatternConverter::format(
+ const LoggingEventPtr& event,
+ LogString& toAppendTo,
+ Pool& /* p */) const {
+ int initialLength = toAppendTo.length();
+ append(toAppendTo, event->getLocationInformation().getClassName());
+ abbreviate(initialLength, toAppendTo);
+ }
diff --git a/src/main/cpp/classregistration.cpp b/src/main/cpp/classregistration.cpp
new file mode 100644
index 0000000..094177e
--- /dev/null
+++ b/src/main/cpp/classregistration.cpp
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/classregistration.h>
+#include <log4cxx/helpers/class.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+ClassRegistration::ClassRegistration(ClassAccessor accessor) {
+ Class::registerClass((*accessor)());
+}
+
+
diff --git a/src/main/cpp/condition.cpp b/src/main/cpp/condition.cpp
new file mode 100755
index 0000000..fdb7815
--- /dev/null
+++ b/src/main/cpp/condition.cpp
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/condition.h>
+#include <log4cxx/helpers/exception.h>
+
+#include <apr_thread_cond.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/thread.h>
+
+using namespace log4cxx::helpers;
+using namespace log4cxx;
+
+
+Condition::Condition(Pool& p)
+{
+#if APR_HAS_THREADS
+ apr_status_t stat = apr_thread_cond_create(&condition, p.getAPRPool());
+ if (stat != APR_SUCCESS) {
+ throw RuntimeException(stat);
+ }
+#endif
+}
+
+Condition::~Condition()
+{
+#if APR_HAS_THREADS
+ apr_thread_cond_destroy(condition);
+#endif
+}
+
+log4cxx_status_t Condition::signalAll()
+{
+#if APR_HAS_THREADS
+ return apr_thread_cond_broadcast(condition);
+#else
+ return APR_SUCCESS;
+#endif
+}
+
+void Condition::await(Mutex& mutex)
+{
+#if APR_HAS_THREADS
+ if (Thread::interrupted()) {
+ throw InterruptedException();
+ }
+ apr_status_t stat = apr_thread_cond_wait(
+ condition,
+ mutex.getAPRMutex());
+ if (stat != APR_SUCCESS) {
+ throw InterruptedException(stat);
+ }
+#endif
+}
+
diff --git a/src/main/cpp/configurator.cpp b/src/main/cpp/configurator.cpp
new file mode 100644
index 0000000..78e910b
--- /dev/null
+++ b/src/main/cpp/configurator.cpp
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/spi/configurator.h>
+#include <assert.h>
+#include <log4cxx/logger.h>
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+
+IMPLEMENT_LOG4CXX_OBJECT(Configurator)
+
+
+
+
+Configurator::Configurator() {
+}
diff --git a/src/main/cpp/consoleappender.cpp b/src/main/cpp/consoleappender.cpp
new file mode 100644
index 0000000..4a2ff5d
--- /dev/null
+++ b/src/main/cpp/consoleappender.cpp
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/consoleappender.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/systemoutwriter.h>
+#include <log4cxx/helpers/systemerrwriter.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/layout.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(ConsoleAppender)
+
+ConsoleAppender::ConsoleAppender()
+ : target(getSystemOut())
+{
+}
+
+ConsoleAppender::ConsoleAppender(const LayoutPtr& layout1)
+ :target(getSystemOut())
+{
+ setLayout(layout1);
+ WriterPtr wr(createWriter(getSystemOut()));
+ setWriter(wr);
+ Pool p;
+ WriterAppender::activateOptions(p);
+}
+
+ConsoleAppender::ConsoleAppender(const LayoutPtr& layout1, const LogString& target1)
+ : target(target1)
+{
+ setLayout(layout1);
+ WriterPtr wr(createWriter(target1));
+ setWriter(wr);
+ Pool p;
+ WriterAppender::activateOptions(p);
+}
+
+ConsoleAppender::~ConsoleAppender()
+{
+ finalize();
+}
+
+const LogString& ConsoleAppender::getSystemOut() {
+ static const LogString name(LOG4CXX_STR("System.out"));
+ return name;
+}
+
+const LogString& ConsoleAppender::getSystemErr() {
+ static const LogString name(LOG4CXX_STR("System.err"));
+ return name;
+}
+
+WriterPtr ConsoleAppender::createWriter(const LogString& value) {
+ LogString v = StringHelper::trim(value);
+
+ if (StringHelper::equalsIgnoreCase(v,
+ LOG4CXX_STR("SYSTEM.ERR"), LOG4CXX_STR("system.err"))) {
+ return new SystemErrWriter();
+ }
+ return new SystemOutWriter();
+}
+
+void ConsoleAppender::setTarget(const LogString& value)
+{
+ LogString v = StringHelper::trim(value);
+
+ if (StringHelper::equalsIgnoreCase(v,
+ LOG4CXX_STR("SYSTEM.OUT"), LOG4CXX_STR("system.out")))
+ {
+ target = getSystemOut();
+ }
+ else if (StringHelper::equalsIgnoreCase(v,
+ LOG4CXX_STR("SYSTEM.ERR"), LOG4CXX_STR("system.err")))
+ {
+ target = getSystemErr();
+ }
+ else
+ {
+ targetWarn(value);
+ }
+}
+
+LogString ConsoleAppender::getTarget() const
+{
+ return target;
+}
+
+void ConsoleAppender::targetWarn(const LogString& val)
+{
+ LogLog::warn(((LogString) LOG4CXX_STR("["))
+ + val + LOG4CXX_STR("] should be system.out or system.err."));
+ LogLog::warn(LOG4CXX_STR("Using previously set target, System.out by default."));
+}
+
+void ConsoleAppender::activateOptions(Pool& p)
+{
+ if(StringHelper::equalsIgnoreCase(target,
+ LOG4CXX_STR("SYSTEM.OUT"), LOG4CXX_STR("system.out")))
+ {
+ WriterPtr writer1(new SystemOutWriter());
+ setWriter(writer1);
+ }
+ else if (StringHelper::equalsIgnoreCase(target,
+ LOG4CXX_STR("SYSTEM.ERR"), LOG4CXX_STR("system.err")))
+ {
+ WriterPtr writer1(new SystemErrWriter());
+ setWriter(writer1);
+ }
+ WriterAppender::activateOptions(p);
+}
+
+void ConsoleAppender::setOption(const LogString& option, const LogString& value)
+{
+ if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("TARGET"), LOG4CXX_STR("target")))
+ {
+ setTarget(value);
+ }
+ else
+ {
+ WriterAppender::setOption(option, value);
+ }
+}
+
+
+
+
+
+
diff --git a/src/main/cpp/cyclicbuffer.cpp b/src/main/cpp/cyclicbuffer.cpp
new file mode 100644
index 0000000..9167238
--- /dev/null
+++ b/src/main/cpp/cyclicbuffer.cpp
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/cyclicbuffer.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/stringhelper.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+
+/**
+Instantiate a new CyclicBuffer of at most <code>maxSize</code> events.
+The <code>maxSize</code> argument must a positive integer.
+@param maxSize The maximum number of elements in the buffer.
+*/
+CyclicBuffer::CyclicBuffer(int maxSize1)
+: ea(maxSize1), first(0), last(0), numElems(0), maxSize(maxSize1)
+{
+ if(maxSize1 < 1)
+ {
+ LogString msg(LOG4CXX_STR("The maxSize argument ("));
+ Pool p;
+ StringHelper::toString(maxSize1, p, msg);
+ msg.append(LOG4CXX_STR(") is not a positive integer."));
+ throw IllegalArgumentException(msg);
+ }
+ }
+
+CyclicBuffer::~CyclicBuffer()
+{
+}
+
+/**
+Add an <code>event</code> as the last event in the buffer.
+*/
+void CyclicBuffer::add(const spi::LoggingEventPtr& event)
+{
+ ea[last] = event;
+ if(++last == maxSize)
+ {
+ last = 0;
+ }
+
+ if(numElems < maxSize)
+ {
+ numElems++;
+ }
+ else if(++first == maxSize)
+ {
+ first = 0;
+ }
+ }
+
+
+/**
+Get the <i>i</i>th oldest event currently in the buffer. If
+<em>i</em> is outside the range 0 to the number of elements
+currently in the buffer, then <code>null</code> is returned.
+*/
+spi::LoggingEventPtr CyclicBuffer::get(int i)
+{
+ if(i < 0 || i >= numElems)
+ return 0;
+
+ return ea[(first + i) % maxSize];
+}
+
+/**
+Get the oldest (first) element in the buffer. The oldest element
+is removed from the buffer.
+*/
+spi::LoggingEventPtr CyclicBuffer::get()
+{
+ LoggingEventPtr r;
+ if(numElems > 0)
+ {
+ numElems--;
+ r = ea[first];
+ ea[first] = 0;
+ if(++first == maxSize)
+ {
+ first = 0;
+ }
+ }
+ return r;
+}
+
+/**
+Resize the cyclic buffer to <code>newSize</code>.
+@throws IllegalArgumentException if <code>newSize</code> is negative.
+*/
+void CyclicBuffer::resize(int newSize)
+{
+ if(newSize < 0)
+ {
+ LogString msg(LOG4CXX_STR("Negative array size ["));
+ Pool p;
+ StringHelper::toString(newSize, p, msg);
+ msg.append(LOG4CXX_STR("] not allowed."));
+ throw IllegalArgumentException(msg);
+ }
+ if(newSize == numElems)
+ return; // nothing to do
+
+ LoggingEventList temp(newSize);
+
+ int loopLen = newSize < numElems ? newSize : numElems;
+ int i;
+
+ for(i = 0; i < loopLen; i++)
+ {
+ temp[i] = ea[first];
+ ea[first] = 0;
+ if(++first == numElems)
+ first = 0;
+ }
+
+ ea = temp;
+ first = 0;
+ numElems = loopLen;
+ maxSize = newSize;
+ if (loopLen == newSize)
+ {
+ last = 0;
+ }
+ else
+ {
+ last = loopLen;
+ }
+}
diff --git a/src/main/cpp/dailyrollingfileappender.cpp b/src/main/cpp/dailyrollingfileappender.cpp
new file mode 100644
index 0000000..62ef3f6
--- /dev/null
+++ b/src/main/cpp/dailyrollingfileappender.cpp
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/dailyrollingfileappender.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/rolling/rollingfileappender.h>
+#include <log4cxx/rolling/timebasedrollingpolicy.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::rolling;
+
+IMPLEMENT_LOG4CXX_OBJECT(DailyRollingFileAppender)
+
+
+
+DailyRollingFileAppender::DailyRollingFileAppender()
+{
+}
+
+
+DailyRollingFileAppender::DailyRollingFileAppender(
+ const LayoutPtr& layout,
+ const LogString& filename,
+ const LogString& datePattern1)
+ : datePattern(datePattern1) {
+ setLayout(layout);
+ setFile(filename);
+ Pool p;
+ activateOptions(p);
+}
+
+void DailyRollingFileAppender::setDatePattern(const LogString& pattern) {
+ datePattern = pattern;
+}
+
+LogString DailyRollingFileAppender::getDatePattern() {
+ return datePattern;
+}
+
+void DailyRollingFileAppender::activateOptions(log4cxx::helpers::Pool& pool) {
+ TimeBasedRollingPolicyPtr policy = new TimeBasedRollingPolicy();
+ LogString pattern(getFile());
+ bool inLiteral = false;
+ bool inPattern = false;
+
+ for (size_t i = 0; i < datePattern.length(); i++) {
+ if (datePattern[i] == 0x27 /* '\'' */) {
+ inLiteral = !inLiteral;
+
+ if (inLiteral && inPattern) {
+ pattern.append(1, (logchar) 0x7D /* '}' */);
+ inPattern = false;
+ }
+ } else {
+ if (!inLiteral && !inPattern) {
+ const logchar dbrace[] = { 0x25, 0x64, 0x7B, 0 }; // "%d{"
+ pattern.append(dbrace);
+ inPattern = true;
+ }
+
+ pattern.append(1, datePattern[i]);
+ }
+ }
+
+ if (inPattern) {
+ pattern.append(1, (logchar) 0x7D /* '}' */);
+ }
+
+ policy->setFileNamePattern(pattern);
+ policy->activateOptions(pool);
+ setTriggeringPolicy(policy);
+ setRollingPolicy(policy);
+
+ RollingFileAppenderSkeleton::activateOptions(pool);
+}
+
+
+void DailyRollingFileAppender::setOption(const LogString& option,
+ const LogString& value) {
+ if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("DATEPATTERN"), LOG4CXX_STR("datepattern"))) {
+ setDatePattern(value);
+ } else {
+ RollingFileAppenderSkeleton::setOption(option, value);
+ }
+}
+
+
+
+
diff --git a/src/main/cpp/datagrampacket.cpp b/src/main/cpp/datagrampacket.cpp
new file mode 100644
index 0000000..b815f62
--- /dev/null
+++ b/src/main/cpp/datagrampacket.cpp
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/datagrampacket.h>
+
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(DatagramPacket)
+
+/** Constructs a DatagramPacket for receiving packets of length
+<code>length</code>. */
+DatagramPacket::DatagramPacket(void * buf1, int length1)
+: buf(buf1), offset(0), length(length1), address(), port(0)
+{
+}
+
+/** Constructs a datagram packet for sending packets of length
+<code>length/<code> to the specified port number on the specified
+host. */
+DatagramPacket::DatagramPacket(void * buf1, int length1, InetAddressPtr address1,
+int port1)
+: buf(buf1), offset(0), length(length1), address(address1), port(port1)
+{
+}
+
+/** Constructs a DatagramPacket for receiving packets of length
+<code>length</code>, specifying an offset into the buffer. */
+DatagramPacket::DatagramPacket(void * buf1, int offset1, int length1)
+: buf(buf1), offset(offset1), length(length1), address(), port(0)
+{
+}
+/** Constructs a datagram packet for sending packets of length
+<code>length</code> with offset <code>offset</code> to the
+specified port number on the specified host. */
+DatagramPacket::DatagramPacket(void * buf1, int offset1, int length1,
+InetAddressPtr address1, int port1)
+: buf(buf1), offset(offset1), length(length1), address(address1), port(port1)
+{
+}
+
+DatagramPacket::~DatagramPacket()
+{
+}
diff --git a/src/main/cpp/datagramsocket.cpp b/src/main/cpp/datagramsocket.cpp
new file mode 100644
index 0000000..617980a
--- /dev/null
+++ b/src/main/cpp/datagramsocket.cpp
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/datagramsocket.h>
+#include <log4cxx/helpers/datagrampacket.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/transcoder.h>
+
+#include "apr_network_io.h"
+#include "apr_lib.h"
+
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(DatagramSocket)
+
+DatagramSocket::DatagramSocket()
+ : socket(0), address(), localAddress(), port(0), localPort(0)
+{
+ create();
+}
+
+DatagramSocket::DatagramSocket(int localPort1)
+ : socket(0), address(), localAddress(), port(0), localPort(0)
+{
+ InetAddressPtr bindAddr = InetAddress::anyAddress();
+
+ create();
+ bind(localPort1, bindAddr);
+}
+
+DatagramSocket::DatagramSocket(int localPort1, InetAddressPtr localAddress1)
+ : socket(0), address(), localAddress(), port(0), localPort(0)
+{
+ create();
+ bind(localPort1, localAddress1);
+}
+
+DatagramSocket::~DatagramSocket()
+{
+ try
+ {
+ close();
+ }
+ catch(SocketException&)
+ {
+ }
+}
+
+/** Binds a datagram socket to a local port and address.*/
+void DatagramSocket::bind(int localPort1, InetAddressPtr localAddress1)
+{
+ Pool addrPool;
+
+ // Create server socket address (including port number)
+ LOG4CXX_ENCODE_CHAR(hostAddr, localAddress1->getHostAddress());
+ apr_sockaddr_t *server_addr;
+ apr_status_t status =
+ apr_sockaddr_info_get(&server_addr, hostAddr.c_str(), APR_INET,
+ localPort1, 0, addrPool.getAPRPool());
+ if (status != APR_SUCCESS) {
+ throw BindException(status);
+ }
+
+ // bind the socket to the address
+ status = apr_socket_bind(socket, server_addr);
+ if (status != APR_SUCCESS) {
+ throw BindException(status);
+ }
+
+ this->localPort = localPort1;
+ this->localAddress = localAddress1;
+}
+
+/** Close the socket.*/
+void DatagramSocket::close()
+{
+ if (socket != 0) {
+ apr_status_t status = apr_socket_close(socket);
+ if (status != APR_SUCCESS) {
+ throw SocketException(status);
+ }
+
+ socket = 0;
+ localPort = 0;
+ }
+}
+
+void DatagramSocket::connect(InetAddressPtr address1, int port1)
+{
+
+ this->address = address1;
+ this->port = port1;
+
+ Pool addrPool;
+
+ // create socket address
+ LOG4CXX_ENCODE_CHAR(hostAddr, address1->getHostAddress());
+ apr_sockaddr_t *client_addr;
+ apr_status_t status =
+ apr_sockaddr_info_get(&client_addr, hostAddr.c_str(), APR_INET,
+ port, 0, addrPool.getAPRPool());
+ if (status != APR_SUCCESS) {
+ throw ConnectException(status);
+ }
+
+ // connect the socket
+ status = apr_socket_connect(socket, client_addr);
+ if (status != APR_SUCCESS) {
+ throw ConnectException(status);
+ }
+}
+
+/** Creates a datagram socket.*/
+void DatagramSocket::create()
+{
+ apr_socket_t* newSocket;
+ apr_status_t status =
+ apr_socket_create(&newSocket, APR_INET, SOCK_DGRAM,
+ APR_PROTO_UDP, socketPool.getAPRPool());
+ socket = newSocket;
+ if (status != APR_SUCCESS) {
+ throw SocketException(status);
+ }
+}
+
+/** Receive the datagram packet.*/
+void DatagramSocket::receive(DatagramPacketPtr& p)
+{
+ Pool addrPool;
+
+ // Create the address from which to receive the datagram packet
+ LOG4CXX_ENCODE_CHAR(hostAddr, p->getAddress()->getHostAddress());
+ apr_sockaddr_t *addr;
+ apr_status_t status =
+ apr_sockaddr_info_get(&addr, hostAddr.c_str(), APR_INET,
+ p->getPort(), 0, addrPool.getAPRPool());
+ if (status != APR_SUCCESS) {
+ throw SocketException(status);
+ }
+
+ // receive the datagram packet
+ apr_size_t len = p->getLength();
+ status = apr_socket_recvfrom(addr, socket, 0,
+ (char *)p->getData(), &len);
+ if (status != APR_SUCCESS) {
+ throw IOException(status);
+ }
+}
+
+/** Sends a datagram packet.*/
+void DatagramSocket::send(DatagramPacketPtr& p)
+{
+ Pool addrPool;
+
+ // create the adress to which to send the datagram packet
+ LOG4CXX_ENCODE_CHAR(hostAddr, p->getAddress()->getHostAddress());
+ apr_sockaddr_t *addr;
+ apr_status_t status =
+ apr_sockaddr_info_get(&addr, hostAddr.c_str(), APR_INET, p->getPort(),
+ 0, addrPool.getAPRPool());
+ if (status != APR_SUCCESS) {
+ throw SocketException(status);
+ }
+
+ // send the datagram packet
+ apr_size_t len = p->getLength();
+ status = apr_socket_sendto(socket, addr, 0,
+ (char *)p->getData(), &len);
+ if (status != APR_SUCCESS) {
+ throw IOException(status);
+ }
+}
diff --git a/src/main/cpp/date.cpp b/src/main/cpp/date.cpp
new file mode 100644
index 0000000..81e4546
--- /dev/null
+++ b/src/main/cpp/date.cpp
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/date.h>
+
+
+#ifndef INT64_C
+#define INT64_C(x) x ## LL
+#endif
+
+
+#include <apr_time.h>
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(Date)
+
+
+Date::Date() : time(apr_time_now()) {
+}
+
+Date::Date(log4cxx_time_t t) : time(t) {
+}
+
+Date::~Date() {
+}
+
+log4cxx_time_t Date::getMicrosecondsPerDay() {
+ return APR_INT64_C(86400000000);
+}
+
+log4cxx_time_t Date::getMicrosecondsPerSecond() {
+ return APR_USEC_PER_SEC;
+}
+
+
+log4cxx_time_t Date::getNextSecond() const {
+ return ((time / APR_USEC_PER_SEC) + 1) * APR_USEC_PER_SEC;
+}
diff --git a/src/main/cpp/dateformat.cpp b/src/main/cpp/dateformat.cpp
new file mode 100644
index 0000000..19fd1a1
--- /dev/null
+++ b/src/main/cpp/dateformat.cpp
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/dateformat.h>
+#include <log4cxx/helpers/stringhelper.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(DateFormat)
+
+DateFormat::~DateFormat() {}
+
+void DateFormat::setTimeZone(const TimeZonePtr&) {}
+
+void DateFormat::numberFormat(LogString& s, int n, Pool& p) const {
+ StringHelper::toString(n, p, s);
+}
+
+DateFormat::DateFormat() {}
+
diff --git a/src/main/cpp/datelayout.cpp b/src/main/cpp/datelayout.cpp
new file mode 100644
index 0000000..63bc7e5
--- /dev/null
+++ b/src/main/cpp/datelayout.cpp
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/datelayout.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/dateformat.h>
+#include <log4cxx/helpers/relativetimedateformat.h>
+#include <log4cxx/helpers/absolutetimedateformat.h>
+#include <log4cxx/helpers/datetimedateformat.h>
+#include <log4cxx/helpers/iso8601dateformat.h>
+#include <log4cxx/helpers/timezone.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+DateLayout::DateLayout(const LogString& dateFormatOption1) :
+ timeZoneID(), dateFormatOption(dateFormatOption1), dateFormat(0)
+{
+}
+
+DateLayout::~DateLayout()
+{
+}
+
+
+void DateLayout::setOption(const LogString& option, const LogString& value)
+{
+
+ if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("DATEFORMAT"), LOG4CXX_STR("dateformat")))
+ {
+ dateFormatOption = value;
+ }
+ else if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("TIMEZONE"), LOG4CXX_STR("timezone")))
+ {
+ timeZoneID = value;
+ }
+}
+
+void DateLayout::activateOptions(Pool&)
+{
+ if(!dateFormatOption.empty())
+ {
+
+ if(dateFormatOption.empty())
+ {
+ dateFormat = 0;
+ }
+ else if(StringHelper::equalsIgnoreCase(dateFormatOption,
+ LOG4CXX_STR("NULL"), LOG4CXX_STR("null")))
+ {
+ dateFormat = 0;
+ dateFormatOption = LOG4CXX_STR("NULL");
+ }
+ else if(StringHelper::equalsIgnoreCase(dateFormatOption,
+ LOG4CXX_STR("RELATIVE"), LOG4CXX_STR("relative")))
+ {
+ dateFormat = new RelativeTimeDateFormat();
+ dateFormatOption = LOG4CXX_STR("RELATIVE");
+ }
+ else if(StringHelper::equalsIgnoreCase(dateFormatOption,
+ LOG4CXX_STR("ABSOLUTE"), LOG4CXX_STR("absolute")))
+ {
+ dateFormat = new AbsoluteTimeDateFormat();
+ dateFormatOption = LOG4CXX_STR("ABSOLUTE");
+ }
+ else if(StringHelper::equalsIgnoreCase(dateFormatOption,
+ LOG4CXX_STR("DATE"), LOG4CXX_STR("date")))
+ {
+ dateFormat = new DateTimeDateFormat();
+ dateFormatOption = LOG4CXX_STR("DATE");
+ }
+ else if(StringHelper::equalsIgnoreCase(dateFormatOption,
+ LOG4CXX_STR("ISO8601"), LOG4CXX_STR("iso8601")))
+ {
+ dateFormat = new ISO8601DateFormat();
+ dateFormatOption = LOG4CXX_STR("iso8601");
+ }
+ else
+ {
+ dateFormat = new SimpleDateFormat(dateFormatOption);
+ }
+ }
+ if (dateFormat != NULL) {
+ if (timeZoneID.empty()) {
+ dateFormat->setTimeZone(TimeZone::getDefault());
+ } else {
+ dateFormat->setTimeZone(TimeZone::getTimeZone(timeZoneID));
+ }
+ }
+}
+
+
+void DateLayout::formatDate(LogString &s,
+ const spi::LoggingEventPtr& event,
+ Pool& p) const {
+
+ if(dateFormat != 0)
+ {
+ dateFormat->format(s, event->getTimeStamp(), p);
+ s.append(1, (logchar) 0x20 /* ' ' */);
+ }
+}
+
diff --git a/src/main/cpp/datepatternconverter.cpp b/src/main/cpp/datepatternconverter.cpp
new file mode 100644
index 0000000..b869e36
--- /dev/null
+++ b/src/main/cpp/datepatternconverter.cpp
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/datepatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+#include <log4cxx/helpers/absolutetimedateformat.h>
+#include <log4cxx/helpers/datetimedateformat.h>
+#include <log4cxx/helpers/iso8601dateformat.h>
+#include <log4cxx/helpers/strftimedateformat.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/date.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(DatePatternConverter)
+
+DatePatternConverter::DatePatternConverter(
+ const std::vector<LogString>& options) :
+ LoggingEventPatternConverter(LOG4CXX_STR("Class Name"),
+ LOG4CXX_STR("class name")), df(getDateFormat(options)) {
+}
+
+DateFormatPtr DatePatternConverter::getDateFormat(const OptionsList& options) {
+ DateFormatPtr df;
+ int maximumCacheValidity = 1000000;
+ if (options.size() == 0) {
+ df = new ISO8601DateFormat();
+ } else {
+ LogString dateFormatStr(options[0]);
+
+ if(dateFormatStr.empty() ||
+ StringHelper::equalsIgnoreCase(dateFormatStr,
+ LOG4CXX_STR("ISO8601"), LOG4CXX_STR("iso8601"))) {
+ df = new ISO8601DateFormat();
+ } else if(StringHelper::equalsIgnoreCase(dateFormatStr,
+ LOG4CXX_STR("ABSOLUTE"), LOG4CXX_STR("absolute"))) {
+ df = new AbsoluteTimeDateFormat();
+ } else if(StringHelper::equalsIgnoreCase(dateFormatStr,
+ LOG4CXX_STR("DATE"), LOG4CXX_STR("date"))) {
+ df = new DateTimeDateFormat();
+ } else {
+ if (dateFormatStr.find(0x25 /*'%'*/) == std::string::npos) {
+ try {
+ df = new SimpleDateFormat(dateFormatStr);
+ maximumCacheValidity =
+ CachedDateFormat::getMaximumCacheValidity(dateFormatStr);
+ } catch(IllegalArgumentException& e) {
+ df = new ISO8601DateFormat();
+ LogLog::warn(((LogString)
+ LOG4CXX_STR("Could not instantiate SimpleDateFormat with pattern "))
+ + dateFormatStr, e);
+ }
+ } else {
+ df = new StrftimeDateFormat(dateFormatStr);
+ }
+ }
+ if (options.size() >= 2) {
+ TimeZonePtr tz(TimeZone::getTimeZone(options[1]));
+ if (tz != NULL) {
+ df->setTimeZone(tz);
+ }
+ }
+ }
+ if (maximumCacheValidity > 0) {
+ df = new CachedDateFormat(df, maximumCacheValidity);
+ }
+ return df;
+}
+
+PatternConverterPtr DatePatternConverter::newInstance(
+ const std::vector<LogString>& options) {
+ return new DatePatternConverter(options);
+}
+
+void DatePatternConverter::format(
+ const LoggingEventPtr& event,
+ LogString& toAppendTo,
+ Pool& p) const {
+ df->format(toAppendTo, event->getTimeStamp(), p);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+void DatePatternConverter::format(
+ const ObjectPtr& obj,
+ LogString& toAppendTo,
+ Pool& p) const {
+ DatePtr date(obj);
+ if (date != NULL) {
+ format(date, toAppendTo, p);
+ } else {
+ LoggingEventPtr event(obj);
+ if (event != NULL) {
+ format(event, toAppendTo, p);
+ }
+ }
+}
+
+ /**
+ * Append formatted date to string buffer.
+ * @param date date
+ * @param toAppendTo buffer to which formatted date is appended.
+ */
+void DatePatternConverter::format(
+ const DatePtr& date,
+ LogString& toAppendTo,
+ Pool& p) const {
+ df->format(toAppendTo, date->getTime(), p);
+}
diff --git a/src/main/cpp/defaultconfigurator.cpp b/src/main/cpp/defaultconfigurator.cpp
new file mode 100755
index 0000000..4e10667
--- /dev/null
+++ b/src/main/cpp/defaultconfigurator.cpp
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/defaultconfigurator.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/spi/loggerrepository.h>
+#include <log4cxx/file.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/optionconverter.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+void DefaultConfigurator::configure(LoggerRepository* repository)
+{
+ repository->setConfigured(true);
+ const LogString configuratorClassName(getConfiguratorClass());
+
+ LogString configurationOptionStr(getConfigurationFileName());
+ Pool pool;
+ File configuration;
+ if (configurationOptionStr.empty())
+ {
+ const char* names[] = { "log4cxx.xml", "log4cxx.properties", "log4j.xml", "log4j.properties", 0 };
+ for (int i = 0; names[i] != 0; i++) {
+ File candidate(names[i]);
+ if (candidate.exists(pool)) {
+ configuration = candidate;
+ break;
+ }
+ }
+ } else {
+ configuration.setPath(configurationOptionStr);
+ }
+
+ if (configuration.exists(pool))
+ {
+ LogString msg(LOG4CXX_STR("Using configuration file ["));
+ msg += configuration.getPath();
+ msg += LOG4CXX_STR("] for automatic log4cxx configuration");
+ LogLog::debug(msg);
+
+ LoggerRepositoryPtr repo(repository);
+ OptionConverter::selectAndConfigure(
+ configuration,
+ configuratorClassName,
+ repo);
+ }
+ else
+ {
+ if (configurationOptionStr.empty()) {
+ LogLog::debug(LOG4CXX_STR("Could not find default configuration file."));
+ } else {
+ LogString msg(LOG4CXX_STR("Could not find configuration file: ["));
+ msg += configurationOptionStr;
+ msg += LOG4CXX_STR("].");
+ LogLog::debug(msg);
+ }
+ }
+
+}
+
+
+const LogString DefaultConfigurator::getConfiguratorClass() {
+
+ // Use automatic configration to configure the default hierarchy
+ const LogString log4jConfiguratorClassName(
+ OptionConverter::getSystemProperty(LOG4CXX_STR("log4j.configuratorClass"),LOG4CXX_STR("")));
+ const LogString configuratorClassName(
+ OptionConverter::getSystemProperty(LOG4CXX_STR("LOG4CXX_CONFIGURATOR_CLASS"),
+ log4jConfiguratorClassName));
+ return configuratorClassName;
+}
+
+
+const LogString DefaultConfigurator::getConfigurationFileName() {
+ static const LogString LOG4CXX_DEFAULT_CONFIGURATION_KEY(LOG4CXX_STR("LOG4CXX_CONFIGURATION"));
+ static const LogString LOG4J_DEFAULT_CONFIGURATION_KEY(LOG4CXX_STR("log4j.configuration"));
+ const LogString log4jConfigurationOptionStr(
+ OptionConverter::getSystemProperty(LOG4J_DEFAULT_CONFIGURATION_KEY, LOG4CXX_STR("")));
+ const LogString configurationOptionStr(
+ OptionConverter::getSystemProperty(LOG4CXX_DEFAULT_CONFIGURATION_KEY,
+ log4jConfigurationOptionStr));
+ return configurationOptionStr;
+}
+
+
+
+
diff --git a/src/main/cpp/defaultloggerfactory.cpp b/src/main/cpp/defaultloggerfactory.cpp
new file mode 100644
index 0000000..64c1124
--- /dev/null
+++ b/src/main/cpp/defaultloggerfactory.cpp
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/defaultloggerfactory.h>
+#include <log4cxx/logger.h>
+
+using namespace log4cxx;
+
+IMPLEMENT_LOG4CXX_OBJECT(DefaultLoggerFactory)
+
+LoggerPtr DefaultLoggerFactory::makeNewLoggerInstance(
+ log4cxx::helpers::Pool& pool,
+ const LogString& name) const
+{
+ return new Logger(pool, name);
+}
diff --git a/src/main/cpp/defaultrepositoryselector.cpp b/src/main/cpp/defaultrepositoryselector.cpp
new file mode 100644
index 0000000..3ef75ea
--- /dev/null
+++ b/src/main/cpp/defaultrepositoryselector.cpp
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/spi/defaultrepositoryselector.h>
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+
+DefaultRepositorySelector::DefaultRepositorySelector(const LoggerRepositoryPtr& repository1)
+ : repository(repository1) {
+}
+
+void DefaultRepositorySelector::addRef() const {
+ ObjectImpl::addRef();
+}
+
+
+void DefaultRepositorySelector::releaseRef() const {
+ ObjectImpl::releaseRef();
+}
+
+LoggerRepositoryPtr& DefaultRepositorySelector::getLoggerRepository() {
+ return repository;
+}
diff --git a/src/main/cpp/domconfigurator.cpp b/src/main/cpp/domconfigurator.cpp
new file mode 100644
index 0000000..8d66df4
--- /dev/null
+++ b/src/main/cpp/domconfigurator.cpp
@@ -0,0 +1,969 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/xml/domconfigurator.h>
+#include <log4cxx/appender.h>
+#include <log4cxx/layout.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/level.h>
+#include <log4cxx/spi/filter.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/loader.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/config/propertysetter.h>
+#include <log4cxx/spi/errorhandler.h>
+#include <log4cxx/spi/loggerfactory.h>
+#include <log4cxx/defaultloggerfactory.h>
+#include <log4cxx/helpers/filewatchdog.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/spi/loggerrepository.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/pool.h>
+#include <sstream>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/rolling/rollingfileappender.h>
+#include <log4cxx/rolling/filterbasedtriggeringpolicy.h>
+#include <apr_xml.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/charsetdecoder.h>
+#include <log4cxx/net/smtpappender.h>
+
+using namespace log4cxx;
+using namespace log4cxx::xml;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+using namespace log4cxx::config;
+using namespace log4cxx::rolling;
+
+
+#if APR_HAS_THREADS
+class XMLWatchdog : public FileWatchdog
+{
+public:
+ XMLWatchdog(const File& filename) : FileWatchdog(filename)
+ {
+ }
+
+ /**
+ Call DOMConfigurator#doConfigure with the
+ <code>filename</code> to reconfigure log4cxx.
+ */
+ void doOnChange()
+ {
+ DOMConfigurator().doConfigure(file,
+ LogManager::getLoggerRepository());
+ }
+};
+#endif
+
+
+IMPLEMENT_LOG4CXX_OBJECT(DOMConfigurator)
+
+#define CONFIGURATION_TAG "log4j:configuration"
+#define OLD_CONFIGURATION_TAG "configuration"
+#define APPENDER_TAG "appender"
+#define APPENDER_REF_TAG "appender-ref"
+#define PARAM_TAG "param"
+#define LAYOUT_TAG "layout"
+#define ROLLING_POLICY_TAG "rollingPolicy"
+#define TRIGGERING_POLICY_TAG "triggeringPolicy"
+#define CATEGORY "category"
+#define LOGGER "logger"
+#define LOGGER_REF "logger-ref"
+#define CATEGORY_FACTORY_TAG "categoryFactory"
+#define NAME_ATTR "name"
+#define CLASS_ATTR "class"
+#define VALUE_ATTR "value"
+#define ROOT_TAG "root"
+#define ROOT_REF "root-ref"
+#define LEVEL_TAG "level"
+#define PRIORITY_TAG "priority"
+#define FILTER_TAG "filter"
+#define ERROR_HANDLER_TAG "errorHandler"
+#define REF_ATTR "ref"
+#define ADDITIVITY_ATTR "additivity"
+#define THRESHOLD_ATTR "threshold"
+#define CONFIG_DEBUG_ATTR "configDebug"
+#define INTERNAL_DEBUG_ATTR "debug"
+
+DOMConfigurator::DOMConfigurator()
+ : props(), repository() {
+}
+
+void DOMConfigurator::addRef() const {
+ ObjectImpl::addRef();
+}
+
+void DOMConfigurator::releaseRef() const {
+ ObjectImpl::releaseRef();
+}
+
+/**
+Used internally to parse appenders by IDREF name.
+*/
+AppenderPtr DOMConfigurator::findAppenderByName(log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ apr_xml_doc* doc,
+ const LogString& appenderName,
+ AppenderMap& appenders) {
+ AppenderPtr appender;
+ std::string tagName(element->name);
+ if (tagName == APPENDER_TAG) {
+ if (appenderName == getAttribute(utf8Decoder, element, NAME_ATTR)) {
+ appender = parseAppender(p, utf8Decoder, element, doc, appenders);
+ }
+ }
+ if (element->first_child && !appender) {
+ appender = findAppenderByName(p, utf8Decoder, element->first_child, doc, appenderName, appenders);
+ }
+ if (element->next && !appender) {
+ appender = findAppenderByName(p, utf8Decoder, element->next, doc, appenderName, appenders);
+ }
+ return appender;
+}
+
+/**
+ Used internally to parse appenders by IDREF element.
+*/
+AppenderPtr DOMConfigurator::findAppenderByReference(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* appenderRef,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{
+ LogString appenderName(subst(getAttribute(utf8Decoder, appenderRef, REF_ATTR)));
+ AppenderMap::const_iterator match = appenders.find(appenderName);
+ AppenderPtr appender;
+ if (match != appenders.end()) {
+ appender = match->second;
+ } else if (doc) {
+ appender = findAppenderByName(p, utf8Decoder, doc->root, doc, appenderName, appenders);
+ if (appender) {
+ appenders.insert(AppenderMap::value_type(appenderName, appender));
+ }
+ }
+ if (!appender) {
+ LogLog::error(LOG4CXX_STR("No appender named [")+
+ appenderName+LOG4CXX_STR("] could be found."));
+ }
+ return appender;
+}
+
+/**
+Used internally to parse an appender element.
+*/
+AppenderPtr DOMConfigurator::parseAppender(Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* appenderElement,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{
+
+ LogString className(subst(getAttribute(utf8Decoder, appenderElement, CLASS_ATTR)));
+ LogLog::debug(LOG4CXX_STR("Class name: [") + className+LOG4CXX_STR("]"));
+ try
+ {
+ ObjectPtr instance = Loader::loadClass(className).newInstance();
+ AppenderPtr appender = instance;
+ PropertySetter propSetter(appender);
+
+ appender->setName(subst(getAttribute(utf8Decoder, appenderElement, NAME_ATTR)));
+
+ for(apr_xml_elem* currentElement = appenderElement->first_child;
+ currentElement;
+ currentElement = currentElement->next) {
+
+ std::string tagName(currentElement->name);
+
+ // Parse appender parameters
+ if (tagName == PARAM_TAG)
+ {
+ setParameter(p, utf8Decoder, currentElement, propSetter);
+ }
+ // Set appender layout
+ else if (tagName == LAYOUT_TAG)
+ {
+ appender->setLayout(parseLayout(p, utf8Decoder, currentElement));
+ }
+ // Add filters
+ else if (tagName == FILTER_TAG)
+ {
+ std::vector<log4cxx::spi::FilterPtr> filters;
+ parseFilters(p, utf8Decoder, currentElement, filters);
+ for(std::vector<log4cxx::spi::FilterPtr>::iterator iter = filters.begin();
+ iter != filters.end();
+ iter++) {
+ appender->addFilter(*iter);
+ }
+ }
+ else if (tagName == ERROR_HANDLER_TAG)
+ {
+ parseErrorHandler(p, utf8Decoder, currentElement, appender, doc, appenders);
+ }
+ else if (tagName == ROLLING_POLICY_TAG)
+ {
+ RollingPolicyPtr rollPolicy(parseRollingPolicy(p, utf8Decoder, currentElement));
+ RollingFileAppenderPtr rfa(appender);
+ if (rfa != NULL) {
+ rfa->setRollingPolicy(rollPolicy);
+ }
+ }
+ else if (tagName == TRIGGERING_POLICY_TAG)
+ {
+ ObjectPtr policy(parseTriggeringPolicy(p, utf8Decoder, currentElement));
+ RollingFileAppenderPtr rfa(appender);
+ if (rfa != NULL) {
+ rfa->setTriggeringPolicy(policy);
+ } else {
+ log4cxx::net::SMTPAppenderPtr smtpa(appender);
+ if (smtpa != NULL) {
+ log4cxx::spi::TriggeringEventEvaluatorPtr evaluator(policy);
+ smtpa->setEvaluator(evaluator);
+ }
+ }
+ }
+ else if (tagName == APPENDER_REF_TAG)
+ {
+ LogString refName = subst(getAttribute(utf8Decoder, currentElement, REF_ATTR));
+ if(appender->instanceof(AppenderAttachable::getStaticClass()))
+ {
+ AppenderAttachablePtr aa(appender);
+ LogLog::debug(LOG4CXX_STR("Attaching appender named [")+
+ refName+LOG4CXX_STR("] to appender named [")+
+ appender->getName()+LOG4CXX_STR("]."));
+ aa->addAppender(findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders));
+ }
+ else
+ {
+ LogLog::error(LOG4CXX_STR("Requesting attachment of appender named [")+
+ refName+ LOG4CXX_STR("] to appender named [")+ appender->getName()+
+ LOG4CXX_STR("] which does not implement AppenderAttachable."));
+ }
+ }
+ }
+ propSetter.activate(p);
+ return appender;
+ }
+ /* Yes, it's ugly. But all of these exceptions point to the same
+ problem: we can't create an Appender */
+ catch (Exception& oops)
+ {
+ LogLog::error(LOG4CXX_STR("Could not create an Appender. Reported error follows."),
+ oops);
+ return 0;
+ }
+}
+
+/**
+Used internally to parse an {@link ErrorHandler} element.
+*/
+void DOMConfigurator::parseErrorHandler(Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ AppenderPtr& appender,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{
+ ErrorHandlerPtr eh = OptionConverter::instantiateByClassName(
+ subst(getAttribute(utf8Decoder, element, CLASS_ATTR)),
+ ErrorHandler::getStaticClass(),
+ 0);
+
+ if(eh != 0)
+ {
+ eh->setAppender(appender);
+
+ PropertySetter propSetter(eh);
+
+ for (apr_xml_elem* currentElement = element->first_child;
+ currentElement;
+ currentElement = currentElement->next) {
+ std::string tagName(currentElement->name);
+ if(tagName == PARAM_TAG)
+ {
+ setParameter(p, utf8Decoder, currentElement, propSetter);
+ }
+ else if(tagName == APPENDER_REF_TAG)
+ {
+ eh->setBackupAppender(findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders));
+ }
+ else if(tagName == LOGGER_REF)
+ {
+ LogString loggerName(getAttribute(utf8Decoder, currentElement, REF_ATTR));
+ LoggerPtr logger = repository->getLogger(loggerName, loggerFactory);
+ eh->setLogger(logger);
+ }
+ else if(tagName == ROOT_REF)
+ {
+ LoggerPtr root = repository->getRootLogger();
+ eh->setLogger(root);
+ }
+ }
+ propSetter.activate(p);
+// appender->setErrorHandler(eh);
+ }
+}
+
+/**
+ Used internally to parse a filter element.
+*/
+void DOMConfigurator::parseFilters(Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ std::vector<log4cxx::spi::FilterPtr>& filters)
+{
+ LogString clazz = subst(getAttribute(utf8Decoder, element, CLASS_ATTR));
+ FilterPtr filter = OptionConverter::instantiateByClassName(clazz,
+ Filter::getStaticClass(), 0);
+
+ if(filter != 0)
+ {
+ PropertySetter propSetter(filter);
+
+ for (apr_xml_elem* currentElement = element->first_child;
+ currentElement;
+ currentElement = currentElement->next)
+ {
+ std::string tagName(currentElement->name);
+ if(tagName == PARAM_TAG)
+ {
+ setParameter(p, utf8Decoder, currentElement, propSetter);
+ }
+ }
+ propSetter.activate(p);
+ filters.push_back(filter);
+ }
+}
+
+/**
+Used internally to parse an category or logger element.
+*/
+void DOMConfigurator::parseLogger(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* loggerElement,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{
+ // Create a new Logger object from the <category> element.
+ LogString loggerName = subst(getAttribute(utf8Decoder, loggerElement, NAME_ATTR));
+
+ LogLog::debug(LOG4CXX_STR("Retreiving an instance of Logger."));
+ LoggerPtr logger = repository->getLogger(loggerName, loggerFactory);
+
+ // Setting up a logger needs to be an atomic operation, in order
+ // to protect potential log operations while logger
+ // configuration is in progress.
+ synchronized sync(logger->getMutex());
+ bool additivity = OptionConverter::toBoolean(
+ subst(getAttribute(utf8Decoder, loggerElement, ADDITIVITY_ATTR)),
+ true);
+
+ LogLog::debug(LOG4CXX_STR("Setting [")+logger->getName()+LOG4CXX_STR("] additivity to [")+
+ (additivity ? LogString(LOG4CXX_STR("true")) : LogString(LOG4CXX_STR("false")))+LOG4CXX_STR("]."));
+ logger->setAdditivity(additivity);
+ parseChildrenOfLoggerElement(p, utf8Decoder, loggerElement, logger, false, doc, appenders);
+}
+
+/**
+ Used internally to parse the logger factory element.
+*/
+void DOMConfigurator::parseLoggerFactory(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* factoryElement)
+{
+ LogString className(subst(getAttribute(utf8Decoder, factoryElement, CLASS_ATTR)));
+
+ if(className.empty())
+ {
+ LogLog::error(LOG4CXX_STR("Logger Factory tag class attribute not found."));
+ LogLog::debug(LOG4CXX_STR("No Logger Factory configured."));
+ }
+ else
+ {
+ LogLog::debug(LOG4CXX_STR("Desired logger factory: [")+className+LOG4CXX_STR("]"));
+ loggerFactory = OptionConverter::instantiateByClassName(
+ className,
+ LoggerFactory::getStaticClass(),
+ 0);
+ PropertySetter propSetter(loggerFactory);
+
+ for (apr_xml_elem* currentElement = factoryElement->first_child;
+ currentElement;
+ currentElement = currentElement->next) {
+ std::string tagName(currentElement->name);
+ if (tagName == PARAM_TAG) {
+ setParameter(p, utf8Decoder, currentElement, propSetter);
+ }
+ }
+ }
+}
+
+/**
+ Used internally to parse the root logger element.
+*/
+void DOMConfigurator::parseRoot(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* rootElement,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{
+ LoggerPtr root = repository->getRootLogger();
+ // logger configuration needs to be atomic
+ synchronized sync(root->getMutex());
+ parseChildrenOfLoggerElement(p, utf8Decoder, rootElement, root, true, doc, appenders);
+}
+
+/**
+ Used internally to parse the children of a logger element.
+*/
+void DOMConfigurator::parseChildrenOfLoggerElement(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* loggerElement, LoggerPtr logger, bool isRoot,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{
+
+ PropertySetter propSetter(logger);
+
+ // Remove all existing appenders from logger. They will be
+ // reconstructed if need be.
+ logger->removeAllAppenders();
+
+
+ for (apr_xml_elem* currentElement = loggerElement->first_child;
+ currentElement;
+ currentElement = currentElement->next) {
+ std::string tagName(currentElement->name);
+
+ if (tagName == APPENDER_REF_TAG)
+ {
+ AppenderPtr appender = findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders);
+ LogString refName = subst(getAttribute(utf8Decoder, currentElement, REF_ATTR));
+ if(appender != 0)
+ {
+ LogLog::debug(LOG4CXX_STR("Adding appender named [")+ refName+
+ LOG4CXX_STR("] to logger [")+logger->getName()+LOG4CXX_STR("]."));
+ }
+ else
+ {
+ LogLog::debug(LOG4CXX_STR("Appender named [")+ refName +
+ LOG4CXX_STR("] not found."));
+ }
+
+ logger->addAppender(appender);
+
+ }
+ else if(tagName == LEVEL_TAG)
+ {
+ parseLevel(p, utf8Decoder, currentElement, logger, isRoot);
+ }
+ else if(tagName == PRIORITY_TAG)
+ {
+ parseLevel(p, utf8Decoder, currentElement, logger, isRoot);
+ }
+ else if(tagName == PARAM_TAG)
+ {
+ setParameter(p, utf8Decoder, currentElement, propSetter);
+ }
+ }
+ propSetter.activate(p);
+}
+
+/**
+ Used internally to parse a layout element.
+*/
+LayoutPtr DOMConfigurator::parseLayout (
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* layout_element)
+{
+ LogString className(subst(getAttribute(utf8Decoder, layout_element, CLASS_ATTR)));
+ LogLog::debug(LOG4CXX_STR("Parsing layout of class: \"")+className+LOG4CXX_STR("\""));
+ try
+ {
+ ObjectPtr instance = Loader::loadClass(className).newInstance();
+ LayoutPtr layout = instance;
+ PropertySetter propSetter(layout);
+
+ for(apr_xml_elem* currentElement = layout_element->first_child;
+ currentElement;
+ currentElement = currentElement->next) {
+ std::string tagName(currentElement->name);
+ if(tagName == PARAM_TAG)
+ {
+ setParameter(p, utf8Decoder, currentElement, propSetter);
+ }
+ }
+
+ propSetter.activate(p);
+ return layout;
+ }
+ catch (Exception& oops)
+ {
+ LogLog::error(LOG4CXX_STR("Could not create the Layout. Reported error follows."),
+ oops);
+ return 0;
+ }
+}
+
+/**
+ Used internally to parse a triggering policy
+*/
+ObjectPtr DOMConfigurator::parseTriggeringPolicy (
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* layout_element)
+{
+ LogString className = subst(getAttribute(utf8Decoder, layout_element, CLASS_ATTR));
+ LogLog::debug(LOG4CXX_STR("Parsing triggering policy of class: \"")+className+LOG4CXX_STR("\""));
+ try
+ {
+ ObjectPtr instance = Loader::loadClass(className).newInstance();
+ PropertySetter propSetter(instance);
+
+ for (apr_xml_elem* currentElement = layout_element->first_child;
+ currentElement;
+ currentElement = currentElement->next) {
+ std::string tagName(currentElement->name);
+ if(tagName == PARAM_TAG)
+ {
+ setParameter(p, utf8Decoder, currentElement, propSetter);
+ }
+ else if (tagName == FILTER_TAG) {
+ std::vector<log4cxx::spi::FilterPtr> filters;
+ parseFilters(p, utf8Decoder, currentElement, filters);
+ FilterBasedTriggeringPolicyPtr fbtp(instance);
+ if (fbtp != NULL) {
+ for(std::vector<log4cxx::spi::FilterPtr>::iterator iter = filters.begin();
+ iter != filters.end();
+ iter++) {
+ fbtp->addFilter(*iter);
+ }
+ }
+ }
+ }
+
+ propSetter.activate(p);
+ return instance;
+ }
+ catch (Exception& oops)
+ {
+ LogLog::error(LOG4CXX_STR("Could not create the TriggeringPolicy. Reported error follows."),
+ oops);
+ return 0;
+ }
+}
+
+/**
+ Used internally to parse a triggering policy
+*/
+RollingPolicyPtr DOMConfigurator::parseRollingPolicy (
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* layout_element)
+{
+ LogString className = subst(getAttribute(utf8Decoder, layout_element, CLASS_ATTR));
+ LogLog::debug(LOG4CXX_STR("Parsing rolling policy of class: \"")+className+LOG4CXX_STR("\""));
+ try
+ {
+ ObjectPtr instance = Loader::loadClass(className).newInstance();
+ RollingPolicyPtr layout = instance;
+ PropertySetter propSetter(layout);
+
+ for(apr_xml_elem* currentElement = layout_element->first_child;
+ currentElement;
+ currentElement = currentElement->next) {
+ std::string tagName(currentElement->name);
+ if(tagName == PARAM_TAG)
+ {
+ setParameter(p, utf8Decoder, currentElement, propSetter);
+ }
+ }
+
+ propSetter.activate(p);
+ return layout;
+ }
+ catch (Exception& oops)
+ {
+ LogLog::error(LOG4CXX_STR("Could not create the RollingPolicy. Reported error follows."),
+ oops);
+ return 0;
+ }
+}
+
+
+
+/**
+ Used internally to parse a level element.
+*/
+void DOMConfigurator::parseLevel(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element, LoggerPtr logger, bool isRoot)
+{
+ LogString loggerName = logger->getName();
+ if(isRoot)
+ {
+ loggerName = LOG4CXX_STR("root");
+ }
+
+ LogString levelStr(subst(getAttribute(utf8Decoder, element, VALUE_ATTR)));
+ LogLog::debug(LOG4CXX_STR("Level value for ")+loggerName+LOG4CXX_STR(" is [")+levelStr+LOG4CXX_STR("]."));
+
+ if (StringHelper::equalsIgnoreCase(levelStr,LOG4CXX_STR("INHERITED"), LOG4CXX_STR("inherited"))
+ || StringHelper::equalsIgnoreCase(levelStr, LOG4CXX_STR("NULL"), LOG4CXX_STR("null")))
+ {
+ if(isRoot)
+ {
+ LogLog::error(LOG4CXX_STR("Root level cannot be inherited. Ignoring directive."));
+ }
+ else
+ {
+ logger->setLevel(0);
+ }
+ }
+ else
+ {
+ LogString className(subst(getAttribute(utf8Decoder, element, CLASS_ATTR)));
+
+ if (className.empty())
+ {
+ logger->setLevel(OptionConverter::toLevel(levelStr, Level::getDebug()));
+ }
+ else
+ {
+ LogLog::debug(LOG4CXX_STR("Desired Level sub-class: [") + className + LOG4CXX_STR("]"));
+
+ try
+ {
+ Level::LevelClass& levelClass =
+ (Level::LevelClass&)Loader::loadClass(className);
+ LevelPtr level = levelClass.toLevel(levelStr);
+ logger->setLevel(level);
+ }
+ catch (Exception& oops)
+ {
+ LogLog::error(
+ LOG4CXX_STR("Could not create level [") + levelStr +
+ LOG4CXX_STR("]. Reported error follows."),
+ oops);
+
+ return;
+ }
+ catch (...)
+ {
+ LogLog::error(
+ LOG4CXX_STR("Could not create level [") + levelStr);
+
+ return;
+ }
+ }
+ }
+
+ LogLog::debug(loggerName + LOG4CXX_STR(" level set to ") +
+ logger->getEffectiveLevel()->toString());
+}
+
+void DOMConfigurator::setParameter(log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* elem,
+ PropertySetter& propSetter)
+{
+ LogString name(subst(getAttribute(utf8Decoder, elem, NAME_ATTR)));
+ LogString value(subst(getAttribute(utf8Decoder, elem, VALUE_ATTR)));
+ value = subst(value);
+ propSetter.setProperty(name, value, p);
+}
+
+void DOMConfigurator::doConfigure(const File& filename, spi::LoggerRepositoryPtr& repository1)
+{
+ repository1->setConfigured(true);
+ this->repository = repository1;
+ LogString msg(LOG4CXX_STR("DOMConfigurator configuring file "));
+ msg.append(filename.getPath());
+ msg.append(LOG4CXX_STR("..."));
+ LogLog::debug(msg);
+
+ loggerFactory = new DefaultLoggerFactory();
+
+ Pool p;
+ apr_file_t *fd;
+
+ log4cxx_status_t rv = filename.open(&fd, APR_READ, APR_OS_DEFAULT, p);
+ if (rv != APR_SUCCESS) {
+ LogString msg2(LOG4CXX_STR("Could not open file ["));
+ msg2.append(filename.getPath());
+ msg2.append(LOG4CXX_STR("]."));
+ LogLog::error(msg2);
+ } else {
+ apr_xml_parser *parser;
+ apr_xml_doc *doc;
+ rv = apr_xml_parse_file(p.getAPRPool(), &parser, &doc, fd, 2000);
+ if (rv != APR_SUCCESS) {
+ char errbuf[2000];
+ char errbufXML[2000];
+ LogString msg2(LOG4CXX_STR("Error parsing file ["));
+ msg2.append(filename.getPath());
+ msg2.append(LOG4CXX_STR("], "));
+ apr_strerror(rv, errbuf, sizeof(errbuf));
+ LOG4CXX_DECODE_CHAR(lerrbuf, std::string(errbuf));
+ apr_xml_parser_geterror(parser, errbufXML, sizeof(errbufXML));
+ LOG4CXX_DECODE_CHAR(lerrbufXML, std::string(errbufXML));
+ msg2.append(lerrbuf);
+ msg2.append(lerrbufXML);
+ LogLog::error(msg2);
+ } else {
+ AppenderMap appenders;
+ CharsetDecoderPtr utf8Decoder(CharsetDecoder::getUTF8Decoder());
+ parse(p, utf8Decoder, doc->root, doc, appenders);
+ }
+ }
+}
+
+void DOMConfigurator::configure(const std::string& filename)
+{
+ File file(filename);
+ DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
+}
+
+#if LOG4CXX_WCHAR_T_API
+void DOMConfigurator::configure(const std::wstring& filename)
+{
+ File file(filename);
+ DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
+}
+#endif
+
+#if LOG4CXX_UNICHAR_API
+void DOMConfigurator::configure(const std::basic_string<UniChar>& filename)
+{
+ File file(filename);
+ DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
+}
+#endif
+
+#if LOG4CXX_CFSTRING_API
+void DOMConfigurator::configure(const CFStringRef& filename)
+{
+ File file(filename);
+ DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
+}
+#endif
+
+
+void DOMConfigurator::configureAndWatch(const std::string& filename)
+{
+ configureAndWatch(filename, FileWatchdog::DEFAULT_DELAY);
+}
+
+#if LOG4CXX_WCHAR_T_API
+void DOMConfigurator::configureAndWatch(const std::wstring& filename)
+{
+ configureAndWatch(filename, FileWatchdog::DEFAULT_DELAY);
+}
+#endif
+
+#if LOG4CXX_UNICHAR_API
+void DOMConfigurator::configureAndWatch(const std::basic_string<UniChar>& filename)
+{
+ configureAndWatch(filename, FileWatchdog::DEFAULT_DELAY);
+}
+#endif
+
+#if LOG4CXX_CFSTRING_API
+void DOMConfigurator::configureAndWatch(const CFStringRef& filename)
+{
+ configureAndWatch(filename, FileWatchdog::DEFAULT_DELAY);
+}
+#endif
+
+void DOMConfigurator::configureAndWatch(const std::string& filename, long delay)
+{
+ File file(filename);
+#if APR_HAS_THREADS
+ XMLWatchdog * xdog = new XMLWatchdog(file);
+ xdog->setDelay(delay);
+ xdog->start();
+#else
+ DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
+#endif
+}
+
+#if LOG4CXX_WCHAR_T_API
+void DOMConfigurator::configureAndWatch(const std::wstring& filename, long delay)
+{
+ File file(filename);
+#if APR_HAS_THREADS
+ XMLWatchdog * xdog = new XMLWatchdog(file);
+ xdog->setDelay(delay);
+ xdog->start();
+#else
+ DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
+#endif
+}
+#endif
+
+#if LOG4CXX_UNICHAR_API
+void DOMConfigurator::configureAndWatch(const std::basic_string<UniChar>& filename, long delay)
+{
+ File file(filename);
+#if APR_HAS_THREADS
+ XMLWatchdog * xdog = new XMLWatchdog(file);
+ xdog->setDelay(delay);
+ xdog->start();
+#else
+ DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
+#endif
+}
+#endif
+
+#if LOG4CXX_CFSTRING_API
+void DOMConfigurator::configureAndWatch(const CFStringRef& filename, long delay)
+{
+ File file(filename);
+#if APR_HAS_THREADS
+ XMLWatchdog * xdog = new XMLWatchdog(file);
+ xdog->setDelay(delay);
+ xdog->start();
+#else
+ DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
+#endif
+}
+#endif
+
+void DOMConfigurator::parse(
+ Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{
+ std::string rootElementName(element->name);
+
+ if (rootElementName != CONFIGURATION_TAG)
+ {
+ if(rootElementName == OLD_CONFIGURATION_TAG)
+ {
+ //LogLog::warn(LOG4CXX_STR("The <")+String(OLD_CONFIGURATION_TAG)+
+ // LOG4CXX_STR("> element has been deprecated."));
+ //LogLog::warn(LOG4CXX_STR("Use the <")+String(CONFIGURATION_TAG)+
+ // LOG4CXX_STR("> element instead."));
+ }
+ else
+ {
+ LogLog::error(LOG4CXX_STR("DOM element is - not a <configuration> element."));
+ return;
+ }
+ }
+
+ LogString debugAttrib = subst(getAttribute(utf8Decoder, element, INTERNAL_DEBUG_ATTR));
+
+ static const LogString NuLL(LOG4CXX_STR("NULL"));
+ LogLog::debug(LOG4CXX_STR("debug attribute= \"") + debugAttrib +LOG4CXX_STR("\"."));
+ // if the log4j.dtd is not specified in the XML file, then the
+ // "debug" attribute is returned as the empty string.
+ if(!debugAttrib.empty() && debugAttrib != NuLL)
+ {
+ LogLog::setInternalDebugging(OptionConverter::toBoolean(debugAttrib, true));
+ }
+ else
+ {
+ LogLog::debug(LOG4CXX_STR("Ignoring internalDebug attribute."));
+ }
+
+
+ LogString confDebug = subst(getAttribute(utf8Decoder, element, CONFIG_DEBUG_ATTR));
+ if(!confDebug.empty() && confDebug != NuLL)
+ {
+ LogLog::warn(LOG4CXX_STR("The \"configDebug\" attribute is deprecated."));
+ LogLog::warn(LOG4CXX_STR("Use the \"internalDebug\" attribute instead."));
+ LogLog::setInternalDebugging(OptionConverter::toBoolean(confDebug, true));
+ }
+
+ LogString thresholdStr = subst(getAttribute(utf8Decoder, element, THRESHOLD_ATTR));
+ LogLog::debug(LOG4CXX_STR("Threshold =\"") + thresholdStr +LOG4CXX_STR("\"."));
+ if(!thresholdStr.empty() && thresholdStr != NuLL)
+ {
+ repository->setThreshold(thresholdStr);
+ }
+
+ apr_xml_elem* currentElement;
+ for(currentElement = element->first_child;
+ currentElement;
+ currentElement = currentElement->next) {
+ std::string tagName(currentElement->name);
+
+ if (tagName == CATEGORY_FACTORY_TAG)
+ {
+ parseLoggerFactory(p, utf8Decoder, currentElement);
+ }
+ }
+
+ for(currentElement = element->first_child;
+ currentElement;
+ currentElement = currentElement->next) {
+ std::string tagName(currentElement->name);
+
+ if (tagName == CATEGORY || tagName == LOGGER)
+ {
+ parseLogger(p, utf8Decoder, currentElement, doc, appenders);
+ }
+ else if (tagName == ROOT_TAG)
+ {
+ parseRoot(p, utf8Decoder, currentElement, doc, appenders);
+ }
+ }
+}
+
+LogString DOMConfigurator::subst(const LogString& value)
+{
+ try
+ {
+ return OptionConverter::substVars(value, props);
+ }
+ catch(IllegalArgumentException& e)
+ {
+ LogLog::warn(LOG4CXX_STR("Could not perform variable substitution."), e);
+ return value;
+ }
+}
+
+
+LogString DOMConfigurator::getAttribute(
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ const std::string& attrName) {
+ LogString attrValue;
+ for(apr_xml_attr* attr = element->attr;
+ attr;
+ attr = attr->next) {
+ if (attrName == attr->name) {
+ ByteBuffer buf((char*) attr->value, strlen(attr->value));
+ utf8Decoder->decode(buf, attrValue);
+ }
+ }
+ return attrValue;
+}
diff --git a/src/main/cpp/exception.cpp b/src/main/cpp/exception.cpp
new file mode 100644
index 0000000..19e17d0
--- /dev/null
+++ b/src/main/cpp/exception.cpp
@@ -0,0 +1,427 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/exception.h>
+#include <string.h>
+#include <string>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/pool.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+Exception::Exception(const LogString& msg1) {
+ std::string m;
+ Transcoder::encode(msg1, m);
+ size_t len = m.size();
+ if (len > MSG_SIZE) {
+ len = MSG_SIZE;
+ }
+#if defined(__STDC_LIB_EXT1__) || defined(__STDC_SECURE_LIB__)
+ memcpy_s(msg, sizeof msg, m.data(), len);
+#else
+ memcpy(msg, m.data(), len);
+#endif
+ msg[len] = 0;
+}
+
+Exception::Exception(const char* m) {
+#if defined(__STDC_LIB_EXT1__) || defined(__STDC_SECURE_LIB__)
+ strncpy_s(msg, sizeof msg, m, MSG_SIZE);
+#else
+ strncpy(msg, m, MSG_SIZE);
+#endif
+ msg[MSG_SIZE] = 0;
+}
+
+
+Exception::Exception(const Exception& src) : std::exception() {
+#if defined(__STDC_LIB_EXT1__) || defined(__STDC_SECURE_LIB__)
+ strcpy_s(msg, sizeof msg, src.msg);
+#else
+ strcpy(msg, src.msg);
+#endif
+}
+
+Exception& Exception::operator=(const Exception& src) {
+#if defined(__STDC_LIB_EXT1__) || defined(__STDC_SECURE_LIB__)
+ strcpy_s(msg, sizeof msg, src.msg);
+#else
+ strcpy(msg, src.msg);
+#endif
+ return *this;
+}
+
+const char* Exception::what() const throw() {
+ return msg;
+}
+
+RuntimeException::RuntimeException(log4cxx_status_t stat)
+ : Exception(formatMessage(stat)) {
+}
+
+RuntimeException::RuntimeException(const LogString& msg1)
+ : Exception(msg1) {
+}
+
+RuntimeException::RuntimeException(const RuntimeException& src)
+ : Exception(src) {
+}
+
+RuntimeException& RuntimeException::operator=(const RuntimeException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+LogString RuntimeException::formatMessage(log4cxx_status_t stat) {
+ LogString s(LOG4CXX_STR("RuntimeException: return code = "));
+ Pool p;
+ StringHelper::toString(stat, p, s);
+ return s;
+}
+
+NullPointerException::NullPointerException(const LogString& msg1)
+ : RuntimeException(msg1) {
+}
+
+NullPointerException::NullPointerException(const NullPointerException& src)
+ : RuntimeException(src) {
+}
+
+NullPointerException& NullPointerException::operator=(const NullPointerException& src) {
+ RuntimeException::operator=(src);
+ return *this;
+}
+
+IllegalArgumentException::IllegalArgumentException(const LogString& msg1)
+ : RuntimeException(msg1) {
+}
+
+IllegalArgumentException::IllegalArgumentException(const IllegalArgumentException& src)
+ : RuntimeException(src) {
+}
+
+IllegalArgumentException& IllegalArgumentException::operator=(const IllegalArgumentException& src) {
+ RuntimeException::operator=(src);
+ return *this;
+}
+
+IOException::IOException()
+ : Exception(LOG4CXX_STR("IO exception")) {
+}
+
+IOException::IOException(log4cxx_status_t stat)
+ : Exception(formatMessage(stat)) {
+}
+
+
+IOException::IOException(const LogString& msg1)
+ : Exception(msg1) {
+}
+
+IOException::IOException(const IOException& src)
+ : Exception(src) {
+}
+
+IOException& IOException::operator=(const IOException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+LogString IOException::formatMessage(log4cxx_status_t stat) {
+ LogString s(LOG4CXX_STR("IO Exception : status code = "));
+ Pool p;
+ StringHelper::toString(stat, p, s);
+ return s;
+}
+
+
+MissingResourceException::MissingResourceException(const LogString& key)
+ : Exception(formatMessage(key)) {
+}
+
+
+MissingResourceException::MissingResourceException(const MissingResourceException& src)
+ : Exception(src) {
+}
+
+MissingResourceException& MissingResourceException::operator=(const MissingResourceException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+LogString MissingResourceException::formatMessage(const LogString& key) {
+ LogString s(LOG4CXX_STR("MissingResourceException: resource key = \""));
+ s.append(key);
+ s.append(LOG4CXX_STR("\"."));
+ return s;
+}
+
+PoolException::PoolException(log4cxx_status_t stat)
+ : Exception(formatMessage(stat)) {
+}
+
+PoolException::PoolException(const PoolException &src)
+ : Exception(src) {
+}
+
+PoolException& PoolException::operator=(const PoolException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+LogString PoolException::formatMessage(log4cxx_status_t) {
+ return LOG4CXX_STR("Pool exception");
+}
+
+
+TranscoderException::TranscoderException(log4cxx_status_t stat)
+ : Exception(formatMessage(stat)) {
+}
+
+TranscoderException::TranscoderException(const TranscoderException &src)
+ : Exception(src) {
+}
+
+TranscoderException& TranscoderException::operator=(const TranscoderException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+LogString TranscoderException::formatMessage(log4cxx_status_t) {
+ return LOG4CXX_STR("Transcoder exception");
+}
+
+
+MutexException::MutexException(log4cxx_status_t stat)
+ : Exception(formatMessage(stat)) {
+}
+
+MutexException::MutexException(const MutexException &src)
+ : Exception(src) {
+}
+
+MutexException& MutexException::operator=(const MutexException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+LogString MutexException::formatMessage(log4cxx_status_t stat) {
+ LogString s(LOG4CXX_STR("Mutex exception: stat = "));
+ Pool p;
+ StringHelper::toString(stat, p, s);
+ return s;
+}
+
+InterruptedException::InterruptedException() : Exception(LOG4CXX_STR("Thread was interrupted")) {
+}
+
+InterruptedException::InterruptedException(log4cxx_status_t stat)
+ : Exception(formatMessage(stat)) {
+}
+
+InterruptedException::InterruptedException(const InterruptedException &src)
+ : Exception(src) {
+}
+
+InterruptedException& InterruptedException::operator=(const InterruptedException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+LogString InterruptedException::formatMessage(log4cxx_status_t stat) {
+ LogString s(LOG4CXX_STR("InterruptedException: stat = "));
+ Pool p;
+ StringHelper::toString(stat, p, s);
+ return s;
+}
+
+ThreadException::ThreadException(log4cxx_status_t stat)
+ : Exception(formatMessage(stat)) {
+}
+
+ThreadException::ThreadException(const LogString& msg)
+ : Exception(msg) {
+}
+
+ThreadException::ThreadException(const ThreadException &src)
+ : Exception(src) {
+}
+
+ThreadException& ThreadException::operator=(const ThreadException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+LogString ThreadException::formatMessage(log4cxx_status_t stat) {
+ LogString s(LOG4CXX_STR("Thread exception: stat = "));
+ Pool p;
+ StringHelper::toString(stat, p, s);
+ return s;
+}
+
+IllegalMonitorStateException::IllegalMonitorStateException(const LogString& msg1)
+ : Exception(msg1) {
+}
+
+IllegalMonitorStateException::IllegalMonitorStateException(const IllegalMonitorStateException& src)
+ : Exception(src) {
+}
+
+IllegalMonitorStateException& IllegalMonitorStateException::operator=(const IllegalMonitorStateException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+InstantiationException::InstantiationException(const LogString& msg1)
+ : Exception(msg1) {
+}
+
+InstantiationException::InstantiationException(const InstantiationException& src)
+ : Exception(src) {
+}
+
+InstantiationException& InstantiationException::operator=(const InstantiationException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+ClassNotFoundException::ClassNotFoundException(const LogString& className)
+ : Exception(formatMessage(className)) {
+}
+
+ClassNotFoundException::ClassNotFoundException(const ClassNotFoundException& src)
+ : Exception(src) {
+}
+
+
+ClassNotFoundException& ClassNotFoundException::operator=(const ClassNotFoundException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+LogString ClassNotFoundException::formatMessage(const LogString& className) {
+ LogString s(LOG4CXX_STR("Class not found: "));
+ s.append(className);
+ return s;
+}
+
+
+NoSuchElementException::NoSuchElementException()
+ : Exception(LOG4CXX_STR("No such element")) {
+}
+
+NoSuchElementException::NoSuchElementException(const NoSuchElementException& src)
+ : Exception(src) {
+}
+
+NoSuchElementException& NoSuchElementException::operator=(const NoSuchElementException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+
+IllegalStateException::IllegalStateException()
+ : Exception(LOG4CXX_STR("Illegal state")) {
+}
+
+IllegalStateException::IllegalStateException(const IllegalStateException& src)
+ : Exception(src) {
+}
+
+IllegalStateException& IllegalStateException::operator=(const IllegalStateException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+SocketException::SocketException(const LogString& msg) : IOException(msg) {
+}
+
+SocketException::SocketException(log4cxx_status_t status) : IOException(status) {
+}
+
+SocketException::SocketException(const SocketException& src)
+ : IOException(src) {
+}
+
+SocketException& SocketException::operator=(const SocketException& src) {
+ IOException::operator=(src);
+ return *this;
+}
+
+ConnectException::ConnectException(log4cxx_status_t status) : SocketException(status) {
+}
+
+ConnectException::ConnectException(const ConnectException& src)
+ : SocketException(src) {
+}
+
+ConnectException& ConnectException::operator=(const ConnectException& src) {
+ SocketException::operator=(src);
+ return *this;
+}
+
+ClosedChannelException::ClosedChannelException() : SocketException(LOG4CXX_STR("Attempt to write to closed socket")) {
+}
+
+ClosedChannelException::ClosedChannelException(const ClosedChannelException& src)
+ : SocketException(src) {
+}
+
+ClosedChannelException& ClosedChannelException::operator=(const ClosedChannelException& src) {
+ SocketException::operator=(src);
+ return *this;
+}
+
+BindException::BindException(log4cxx_status_t status) : SocketException(status) {
+}
+
+BindException::BindException(const BindException& src)
+ : SocketException(src) {
+}
+
+BindException& BindException::operator=(const BindException& src) {
+ SocketException::operator=(src);
+ return *this;
+}
+
+InterruptedIOException::InterruptedIOException(const LogString& msg) : IOException(msg) {
+}
+
+InterruptedIOException::InterruptedIOException(const InterruptedIOException& src)
+ : IOException(src) {
+}
+
+InterruptedIOException& InterruptedIOException::operator=(const InterruptedIOException& src) {
+ IOException::operator=(src);
+ return *this;
+}
+
+SocketTimeoutException::SocketTimeoutException()
+ : InterruptedIOException(LOG4CXX_STR("SocketTimeoutException")) {
+}
+
+SocketTimeoutException::SocketTimeoutException(const SocketTimeoutException& src)
+ : InterruptedIOException(src) {
+}
+
+SocketTimeoutException& SocketTimeoutException::operator=(const SocketTimeoutException& src) {
+ InterruptedIOException::operator=(src);
+ return *this;
+}
diff --git a/src/main/cpp/fallbackerrorhandler.cpp b/src/main/cpp/fallbackerrorhandler.cpp
new file mode 100644
index 0000000..972621d
--- /dev/null
+++ b/src/main/cpp/fallbackerrorhandler.cpp
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/appender.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/varia/fallbackerrorhandler.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/spi/loggingevent.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+using namespace log4cxx::varia;
+
+IMPLEMENT_LOG4CXX_OBJECT(FallbackErrorHandler)
+
+FallbackErrorHandler::FallbackErrorHandler()
+ : backup(), primary(), loggers()
+{
+}
+
+void FallbackErrorHandler::addRef() const {
+ ObjectImpl::addRef();
+}
+
+void FallbackErrorHandler::releaseRef() const {
+ ObjectImpl::releaseRef();
+}
+
+void FallbackErrorHandler::setLogger(const LoggerPtr& logger)
+{
+ LogLog::debug(((LogString) LOG4CXX_STR("FB: Adding logger ["))
+ + logger->getName() + LOG4CXX_STR("]."));
+ loggers.push_back(logger);
+}
+
+void FallbackErrorHandler::error(const LogString& message,
+ const std::exception& e,
+ int errorCode) const
+{
+ error(message, e, errorCode, 0);
+}
+
+void FallbackErrorHandler::error(const LogString& message,
+ const std::exception& e,
+ int, const spi::LoggingEventPtr&) const
+{
+ LogLog::debug(((LogString) LOG4CXX_STR("FB: The following error reported: "))
+ + message, e);
+ LogLog::debug(LOG4CXX_STR("FB: INITIATING FALLBACK PROCEDURE."));
+ for(size_t i = 0; i < loggers.size(); i++)
+ {
+ LoggerPtr& l = (LoggerPtr&)loggers.at(i);
+ LogLog::debug(((LogString) LOG4CXX_STR("FB: Searching for ["))
+ + primary->getName() + LOG4CXX_STR("] in logger [")
+ + l->getName() + LOG4CXX_STR("]."));
+ LogLog::debug(((LogString) LOG4CXX_STR("FB: Replacing ["))
+ + primary->getName() + LOG4CXX_STR("] by [")
+ + backup->getName() + LOG4CXX_STR("] in logger [")
+ + l->getName() + LOG4CXX_STR("]."));
+ l->removeAppender(primary);
+ LogLog::debug(((LogString) LOG4CXX_STR("FB: Adding appender ["))
+ + backup->getName() + LOG4CXX_STR("] to logger ")
+ + l->getName());
+ l->addAppender(backup);
+ }
+}
+
+void FallbackErrorHandler::setAppender(const AppenderPtr& primary1)
+{
+ LogLog::debug(((LogString) LOG4CXX_STR("FB: Setting primary appender to ["))
+ + primary1->getName() + LOG4CXX_STR("]."));
+ this->primary = primary1;
+}
+
+void FallbackErrorHandler::setBackupAppender(const AppenderPtr& backup1)
+{
+ LogLog::debug(((LogString) LOG4CXX_STR("FB: Setting backup appender to ["))
+ + backup1->getName() + LOG4CXX_STR("]."));
+ this->backup = backup1;
+}
+
+void FallbackErrorHandler::activateOptions(Pool&)
+{
+}
+
+void FallbackErrorHandler::setOption(const LogString&, const LogString&)
+{
+}
+
diff --git a/src/main/cpp/file.cpp b/src/main/cpp/file.cpp
new file mode 100644
index 0000000..30ff411
--- /dev/null
+++ b/src/main/cpp/file.cpp
@@ -0,0 +1,240 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/file.h>
+#include <apr_file_io.h>
+#include <apr_file_info.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/pool.h>
+#include <assert.h>
+#include <log4cxx/helpers/exception.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+File::File() {
+}
+
+template<class S>
+static LogString decodeLS(const S* src) {
+ LogString dst;
+ if (src != 0) {
+ Transcoder::decode(src, dst);
+ }
+ return dst;
+}
+
+template<class S>
+static LogString decodeLS(const std::basic_string<S>& src) {
+ LogString dst;
+ Transcoder::decode(src, dst);
+ return dst;
+}
+
+
+File::File(const std::string& name1)
+ : path(decodeLS(name1)) {
+}
+
+File::File(const char* name1)
+ : path(decodeLS(name1)) {
+}
+
+#if LOG4CXX_WCHAR_T_API
+File::File(const std::wstring& name1)
+ : path(decodeLS(name1)) {
+}
+
+File::File(const wchar_t* name1)
+ : path(decodeLS(name1)) {
+}
+#endif
+
+#if LOG4CXX_UNICHAR_API
+File::File(const std::basic_string<UniChar>& name1)
+ : path(decodeLS(name1)) {
+}
+
+File::File(const UniChar* name1)
+ : path(decodeLS(name1)) {
+}
+#endif
+
+#if LOG4CXX_CFSTRING_API
+File::File(const CFStringRef& name1)
+ : path(decodeLS(name1)) {
+}
+#endif
+
+File::File(const File& src)
+ : path(src.path) {
+}
+
+File& File::operator=(const File& src) {
+ if (this == &src) return *this;
+
+ path.assign(src.path);
+
+ return *this;
+}
+
+
+File::~File() {
+}
+
+
+LogString File::getPath() const {
+ return path;
+}
+
+File& File::setPath(const LogString& newName) {
+ path.assign(newName);
+ return *this;
+}
+
+LogString File::getName() const {
+ const logchar slashes[] = { 0x2F, 0x5C, 0 };
+ size_t lastSlash = path.find_last_of(slashes);
+ if (lastSlash != LogString::npos) {
+ return path.substr(lastSlash+1);
+ }
+ return path;
+}
+
+char* File::getPath(Pool& p) const {
+ int style = APR_FILEPATH_ENCODING_UNKNOWN;
+ apr_filepath_encoding(&style, p.getAPRPool());
+ char* retval = NULL;
+ if (style == APR_FILEPATH_ENCODING_UTF8) {
+ retval = Transcoder::encodeUTF8(path, p);
+ } else {
+ retval = Transcoder::encode(path, p);
+ }
+ return retval;
+}
+
+log4cxx_status_t File::open(apr_file_t** file, int flags,
+ int perm, Pool& p) const {
+ return apr_file_open(file, getPath(p), flags, perm, p.getAPRPool());
+}
+
+
+
+bool File::exists(Pool& p) const {
+ apr_finfo_t finfo;
+ apr_status_t rv = apr_stat(&finfo, getPath(p),
+ 0, p.getAPRPool());
+ return rv == APR_SUCCESS;
+}
+
+char* File::convertBackSlashes(char* src) {
+ for(char* c = src; *c != 0; c++) {
+ if(*c == '\\') {
+ *c = '/';
+ }
+ }
+ return src;
+}
+
+bool File::deleteFile(Pool& p) const {
+ apr_status_t rv = apr_file_remove(convertBackSlashes(getPath(p)),
+ p.getAPRPool());
+ return rv == APR_SUCCESS;
+}
+
+bool File::renameTo(const File& dest, Pool& p) const {
+ apr_status_t rv = apr_file_rename(convertBackSlashes(getPath(p)),
+ convertBackSlashes(dest.getPath(p)),
+ p.getAPRPool());
+ return rv == APR_SUCCESS;
+}
+
+
+size_t File::length(Pool& pool) const {
+ apr_finfo_t finfo;
+ apr_status_t rv = apr_stat(&finfo, getPath(pool),
+ APR_FINFO_SIZE, pool.getAPRPool());
+ if (rv == APR_SUCCESS) {
+ return (size_t) finfo.size;
+ }
+ return 0;
+}
+
+
+log4cxx_time_t File::lastModified(Pool& pool) const {
+ apr_finfo_t finfo;
+ apr_status_t rv = apr_stat(&finfo, getPath(pool),
+ APR_FINFO_MTIME, pool.getAPRPool());
+ if (rv == APR_SUCCESS) {
+ return finfo.mtime;
+ }
+ return 0;
+}
+
+
+std::vector<LogString> File::list(Pool& p) const {
+ apr_dir_t *dir;
+ apr_finfo_t entry;
+ std::vector<LogString> filenames;
+
+ apr_status_t stat = apr_dir_open(&dir,
+ convertBackSlashes(getPath(p)),
+ p.getAPRPool());
+ if(stat == APR_SUCCESS) {
+ int style = APR_FILEPATH_ENCODING_UNKNOWN;
+ apr_filepath_encoding(&style, p.getAPRPool());
+ stat = apr_dir_read(&entry, APR_FINFO_DIRENT, dir);
+ while(stat == APR_SUCCESS) {
+ if (entry.name != NULL) {
+ LogString filename;
+ if(style == APR_FILEPATH_ENCODING_UTF8) {
+ Transcoder::decodeUTF8(entry.name, filename);
+ } else {
+ Transcoder::decode(entry.name, filename);
+ }
+ filenames.push_back(filename);
+ }
+ stat = apr_dir_read(&entry, APR_FINFO_DIRENT, dir);
+ }
+ stat = apr_dir_close(dir);
+ }
+ return filenames;
+}
+
+LogString File::getParent(Pool&) const {
+ LogString::size_type slashPos = path.rfind(LOG4CXX_STR('/'));
+ LogString::size_type backPos = path.rfind(LOG4CXX_STR('\\'));
+ if (slashPos == LogString::npos) {
+ slashPos = backPos;
+ } else {
+ if (backPos != LogString::npos && backPos > slashPos) {
+ slashPos = backPos;
+ }
+ }
+ LogString parent;
+ if (slashPos != LogString::npos && slashPos > 0) {
+ parent.assign(path, 0, slashPos);
+ }
+ return parent;
+}
+
+bool File::mkdirs(Pool& p) const {
+ apr_status_t stat = apr_dir_make_recursive(convertBackSlashes(getPath(p)),
+ APR_OS_DEFAULT, p.getAPRPool());
+ return stat == APR_SUCCESS;
+}
diff --git a/src/main/cpp/fileappender.cpp b/src/main/cpp/fileappender.cpp
new file mode 100644
index 0000000..ae752ee
--- /dev/null
+++ b/src/main/cpp/fileappender.cpp
@@ -0,0 +1,309 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/fileappender.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/fileoutputstream.h>
+#include <log4cxx/helpers/outputstreamwriter.h>
+#include <log4cxx/helpers/bufferedwriter.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/synchronized.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+IMPLEMENT_LOG4CXX_OBJECT(FileAppender)
+
+
+FileAppender::FileAppender() {
+ synchronized sync(mutex);
+ fileAppend = true;
+ bufferedIO = false;
+ bufferSize = 8 * 1024;
+}
+
+FileAppender::FileAppender(const LayoutPtr& layout1, const LogString& fileName1,
+ bool append1, bool bufferedIO1, int bufferSize1)
+ : WriterAppender(layout1) {
+ {
+ synchronized sync(mutex);
+ fileAppend = append1;
+ fileName = fileName1;
+ bufferedIO = bufferedIO1;
+ bufferSize = bufferSize1;
+ }
+ Pool p;
+ activateOptions(p);
+}
+
+FileAppender::FileAppender(const LayoutPtr& layout1, const LogString& fileName1,
+ bool append1)
+: WriterAppender(layout1) {
+ {
+ synchronized sync(mutex);
+ fileAppend = append1;
+ fileName = fileName1;
+ bufferedIO = false;
+ bufferSize = 8 * 1024;
+ }
+ Pool p;
+ activateOptions(p);
+}
+
+FileAppender::FileAppender(const LayoutPtr& layout1, const LogString& fileName1)
+: WriterAppender(layout1) {
+ {
+ synchronized sync(mutex);
+ fileAppend = true;
+ fileName = fileName1;
+ bufferedIO = false;
+ bufferSize = 8 * 1024;
+ }
+ Pool p;
+ activateOptions(p);
+}
+
+FileAppender::~FileAppender()
+{
+ finalize();
+}
+
+void FileAppender::setAppend(bool fileAppend1) {
+ synchronized sync(mutex);
+ this->fileAppend = fileAppend1;
+}
+
+void FileAppender::setFile(const LogString& file)
+{
+ synchronized sync(mutex);
+ fileName = file;
+}
+
+
+
+void FileAppender::setBufferedIO(bool bufferedIO1)
+{
+ synchronized sync(mutex);
+ this->bufferedIO = bufferedIO1;
+ if(bufferedIO1)
+ {
+ setImmediateFlush(false);
+ }
+}
+
+void FileAppender::setOption(const LogString& option,
+ const LogString& value)
+{
+ if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("FILE"), LOG4CXX_STR("file"))
+ || StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("FILENAME"), LOG4CXX_STR("filename")))
+ {
+ synchronized sync(mutex);
+ fileName = stripDuplicateBackslashes(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("APPEND"), LOG4CXX_STR("append")))
+ {
+ synchronized sync(mutex);
+ fileAppend = OptionConverter::toBoolean(value, true);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BUFFEREDIO"), LOG4CXX_STR("bufferedio")))
+ {
+ synchronized sync(mutex);
+ bufferedIO = OptionConverter::toBoolean(value, true);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("IMMEDIATEFLUSH"), LOG4CXX_STR("immediateflush")))
+ {
+ synchronized sync(mutex);
+ bufferedIO = !OptionConverter::toBoolean(value, false);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BUFFERSIZE"), LOG4CXX_STR("buffersize")))
+ {
+ synchronized sync(mutex);
+ bufferSize = OptionConverter::toFileSize(value, 8*1024);
+ }
+ else
+ {
+ WriterAppender::setOption(option, value);
+ }
+}
+
+void FileAppender::activateOptions(Pool& p)
+{
+ synchronized sync(mutex);
+ int errors = 0;
+ if (!fileName.empty()) {
+ try {
+ setFile(fileName, fileAppend, bufferedIO, bufferSize, p);
+ } catch (IOException& e) {
+ errors++;
+ LogString msg(LOG4CXX_STR("setFile("));
+ msg.append(fileName);
+ msg.append(1, (logchar) 0x2C /* ',' */);
+ StringHelper::toString(fileAppend, msg);
+ msg.append(LOG4CXX_STR(") call failed."));
+ LogLog::error(msg, e);
+ }
+ } else {
+ errors++;
+ LogLog::error(LogString(LOG4CXX_STR("File option not set for appender ["))
+ + name + LOG4CXX_STR("]."));
+ LogLog::warn(LOG4CXX_STR("Are you using FileAppender instead of ConsoleAppender?"));
+ }
+ if(errors == 0) {
+ WriterAppender::activateOptions(p);
+ }
+}
+
+
+/**
+ * Replaces double backslashes (except the leading doubles of UNC's)
+ * with single backslashes for compatibility with existing path
+ * specifications that were working around use of
+ * OptionConverter::convertSpecialChars in XML configuration files.
+ *
+ * @param src source string
+ * @return modified string
+ *
+ *
+ */
+LogString FileAppender::stripDuplicateBackslashes(const LogString& src) {
+ logchar backslash = 0x5C; // '\\'
+ LogString::size_type i = src.find_last_of(backslash);
+ if (i != LogString::npos) {
+ LogString tmp(src);
+ for(;
+ i != LogString::npos && i > 0;
+ i = tmp.find_last_of(backslash, i - 1)) {
+ //
+ // if the preceding character is a slash then
+ // remove the preceding character
+ // and continue processing
+ if (tmp[i - 1] == backslash) {
+ tmp.erase(i, 1);
+ i--;
+ if (i == 0) break;
+ } else {
+ //
+ // if there an odd number of slashes
+ // the string wasn't trying to work around
+ // OptionConverter::convertSpecialChars
+ return src;
+ }
+ }
+ return tmp;
+ }
+ return src;
+}
+
+/**
+ <p>Sets and <i>opens</i> the file where the log output will
+ go. The specified file must be writable.
+
+ <p>If there was already an opened file, then the previous file
+ is closed first.
+
+ <p><b>Do not use this method directly. To configure a FileAppender
+ or one of its subclasses, set its properties one by one and then
+ call activateOptions.</b>
+
+ @param filename The path to the log file.
+ @param append If true will append to fileName. Otherwise will
+ truncate fileName.
+ @param bufferedIO
+ @param bufferSize
+
+ @throws IOException
+
+ */
+void FileAppender::setFile(
+ const LogString& filename,
+ bool append1,
+ bool bufferedIO1,
+ size_t bufferSize1,
+ Pool& p) {
+ synchronized sync(mutex);
+
+ // It does not make sense to have immediate flush and bufferedIO.
+ if (bufferedIO1) {
+ setImmediateFlush(false);
+ }
+
+ closeWriter();
+
+ bool writeBOM = false;
+ if(StringHelper::equalsIgnoreCase(getEncoding(),
+ LOG4CXX_STR("utf-16"), LOG4CXX_STR("UTF-16"))) {
+ //
+ // don't want to write a byte order mark if the file exists
+ //
+ if (append1) {
+ File outFile;
+ outFile.setPath(filename);
+ writeBOM = !outFile.exists(p);
+ } else {
+ writeBOM = true;
+ }
+ }
+
+ OutputStreamPtr outStream;
+ try {
+ outStream = new FileOutputStream(filename, append1);
+ } catch(IOException& ex) {
+ LogString parentName = File().setPath(filename).getParent(p);
+ if (!parentName.empty()) {
+ File parentDir;
+ parentDir.setPath(parentName);
+ if(!parentDir.exists(p) && parentDir.mkdirs(p)) {
+ outStream = new FileOutputStream(filename, append1);
+ } else {
+ throw ex;
+ }
+ } else {
+ throw ex;
+ }
+ }
+
+
+ //
+ // if a new file and UTF-16, then write a BOM
+ //
+ if (writeBOM) {
+ char bom[] = { (char) 0xFE, (char) 0xFF };
+ ByteBuffer buf(bom, 2);
+ outStream->write(buf, p);
+ }
+
+ WriterPtr newWriter(createWriter(outStream));
+
+ if (bufferedIO1) {
+ newWriter = new BufferedWriter(newWriter, bufferSize1);
+ }
+ setWriter(newWriter);
+
+ this->fileAppend = append1;
+ this->bufferedIO = bufferedIO1;
+ this->fileName = filename;
+ this->bufferSize = bufferSize1;
+ writeHeader(p);
+
+}
+
diff --git a/src/main/cpp/filedatepatternconverter.cpp b/src/main/cpp/filedatepatternconverter.cpp
new file mode 100644
index 0000000..950fa70
--- /dev/null
+++ b/src/main/cpp/filedatepatternconverter.cpp
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/filedatepatternconverter.h>
+#include <log4cxx/pattern/datepatternconverter.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+PatternConverterPtr FileDatePatternConverter::newInstance(
+ const std::vector<LogString>& options) {
+ if (options.size() == 0) {
+ std::vector<LogString> altOptions;
+ altOptions.push_back(LOG4CXX_STR("yyyy-MM-dd"));
+ return DatePatternConverter::newInstance(altOptions);
+ }
+ return DatePatternConverter::newInstance(options);
+}
+
diff --git a/src/main/cpp/fileinputstream.cpp b/src/main/cpp/fileinputstream.cpp
new file mode 100644
index 0000000..24dae1a
--- /dev/null
+++ b/src/main/cpp/fileinputstream.cpp
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/fileinputstream.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <apr_file_io.h>
+#include <log4cxx/helpers/transcoder.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/helpers/aprinitializer.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(FileInputStream)
+
+FileInputStream::FileInputStream(const LogString& filename) : fileptr(0) {
+ open(filename);
+}
+
+FileInputStream::FileInputStream(const logchar* filename) : fileptr(0) {
+ LogString fn(filename);
+ open(fn);
+}
+
+
+void FileInputStream::open(const LogString& filename) {
+ apr_fileperms_t perm = APR_OS_DEFAULT;
+ apr_int32_t flags = APR_READ;
+ apr_status_t stat = File().setPath(filename).open(&fileptr, flags, perm, pool);
+ if (stat != APR_SUCCESS) {
+ throw IOException(stat);
+ }
+}
+
+
+FileInputStream::FileInputStream(const File& aFile) {
+ apr_fileperms_t perm = APR_OS_DEFAULT;
+ apr_int32_t flags = APR_READ;
+ apr_status_t stat = aFile.open(&fileptr, flags, perm, pool);
+ if (stat != APR_SUCCESS) {
+ throw IOException(stat);
+ }
+}
+
+
+FileInputStream::~FileInputStream() {
+ if (fileptr != NULL && !APRInitializer::isDestructed) {
+ apr_file_close(fileptr);
+ }
+}
+
+
+void FileInputStream::close() {
+ apr_status_t stat = apr_file_close(fileptr);
+ if (stat == APR_SUCCESS) {
+ fileptr = NULL;
+ } else {
+ throw IOException(stat);
+ }
+}
+
+
+int FileInputStream::read(ByteBuffer& buf) {
+ apr_size_t bytesRead = buf.remaining();
+ apr_status_t stat = apr_file_read(fileptr, buf.current(), &bytesRead);
+ int retval = -1;
+ if (!APR_STATUS_IS_EOF(stat)) {
+ if (stat != APR_SUCCESS) {
+ throw IOException(stat);
+ }
+ buf.position(buf.position() + bytesRead);
+ retval = bytesRead;
+ }
+
+ return retval;
+}
diff --git a/src/main/cpp/filelocationpatternconverter.cpp b/src/main/cpp/filelocationpatternconverter.cpp
new file mode 100644
index 0000000..950659a
--- /dev/null
+++ b/src/main/cpp/filelocationpatternconverter.cpp
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/filelocationpatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+
+ using namespace log4cxx;
+ using namespace log4cxx::pattern;
+ using namespace log4cxx::spi;
+ using namespace helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(FileLocationPatternConverter)
+
+FileLocationPatternConverter::FileLocationPatternConverter() :
+ LoggingEventPatternConverter(LOG4CXX_STR("File Location"),
+ LOG4CXX_STR("file")) {
+}
+
+PatternConverterPtr FileLocationPatternConverter::newInstance(
+ const std::vector<LogString>& /* options */ ) {
+ static PatternConverterPtr instance(new FileLocationPatternConverter());
+ return instance;
+}
+
+void FileLocationPatternConverter::format(
+ const LoggingEventPtr& event,
+ LogString& toAppendTo,
+ Pool& /* p */ ) const {
+ append(toAppendTo, event->getLocationInformation().getFileName());
+}
diff --git a/src/main/cpp/fileoutputstream.cpp b/src/main/cpp/fileoutputstream.cpp
new file mode 100644
index 0000000..18a9df0
--- /dev/null
+++ b/src/main/cpp/fileoutputstream.cpp
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/fileoutputstream.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <apr_file_io.h>
+#include <log4cxx/helpers/transcoder.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/helpers/aprinitializer.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(FileOutputStream)
+
+FileOutputStream::FileOutputStream(const LogString& filename,
+ bool append) : pool(), fileptr(open(filename, append, pool)) {
+}
+
+FileOutputStream::FileOutputStream(const logchar* filename,
+ bool append) : pool(), fileptr(open(filename, append, pool)) {
+}
+
+apr_file_t* FileOutputStream::open(const LogString& filename,
+ bool append, Pool& pool) {
+ apr_fileperms_t perm = APR_OS_DEFAULT;
+ apr_int32_t flags = APR_WRITE | APR_CREATE;
+ if (append) {
+ flags |= APR_APPEND;
+ } else {
+ flags |= APR_TRUNCATE;
+ }
+ File fn;
+ fn.setPath(filename);
+ apr_file_t* fileptr = 0;
+ apr_status_t stat = fn.open(&fileptr, flags, perm, pool);
+ if (stat != APR_SUCCESS) {
+ throw IOException(stat);
+ }
+ return fileptr;
+}
+
+FileOutputStream::~FileOutputStream() {
+ if (fileptr != NULL && !APRInitializer::isDestructed) {
+ apr_file_close(fileptr);
+ }
+}
+
+void FileOutputStream::close(Pool& /* p */) {
+ if (fileptr != NULL) {
+ apr_status_t stat = apr_file_close(fileptr);
+ if (stat != APR_SUCCESS) {
+ throw IOException(stat);
+ }
+ fileptr = NULL;
+ }
+}
+
+void FileOutputStream::flush(Pool& /* p */) {
+}
+
+void FileOutputStream::write(ByteBuffer& buf, Pool& /* p */ ) {
+ if (fileptr == NULL) {
+ throw IOException(-1);
+ }
+ size_t nbytes = buf.remaining();
+ size_t pos = buf.position();
+ const char* data = buf.data();
+ while(nbytes > 0) {
+ apr_status_t stat = apr_file_write(
+ fileptr, data + pos, &nbytes);
+ if (stat != APR_SUCCESS) {
+ throw IOException(stat);
+ }
+ pos += nbytes;
+ buf.position(pos);
+ nbytes = buf.remaining();
+ }
+}
+
diff --git a/src/main/cpp/filerenameaction.cpp b/src/main/cpp/filerenameaction.cpp
new file mode 100644
index 0000000..03818f2
--- /dev/null
+++ b/src/main/cpp/filerenameaction.cpp
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/rolling/filerenameaction.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(FileRenameAction)
+
+FileRenameAction::FileRenameAction(const File& toRename,
+ const File& renameTo,
+ bool renameEmptyFile1)
+ : source(toRename), destination(renameTo), renameEmptyFile(renameEmptyFile1) {
+}
+
+bool FileRenameAction::execute(log4cxx::helpers::Pool& pool1) const {
+ return source.renameTo(destination, pool1);
+}
diff --git a/src/main/cpp/filewatchdog.cpp b/src/main/cpp/filewatchdog.cpp
new file mode 100644
index 0000000..d41f80a
--- /dev/null
+++ b/src/main/cpp/filewatchdog.cpp
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define __STDC_CONSTANT_MACROS
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/filewatchdog.h>
+#include <log4cxx/helpers/loglog.h>
+#include <apr_time.h>
+#include <apr_thread_proc.h>
+#include <apr_atomic.h>
+#include <log4cxx/helpers/transcoder.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+long FileWatchdog::DEFAULT_DELAY = 60000;
+
+#if APR_HAS_THREADS
+
+FileWatchdog::FileWatchdog(const File& file1)
+ : file(file1), delay(DEFAULT_DELAY), lastModif(0),
+warnedAlready(false), interrupted(0), thread()
+{
+}
+
+FileWatchdog::~FileWatchdog() {
+ apr_atomic_set32(&interrupted, 0xFFFF);
+ thread.join();
+}
+
+void FileWatchdog::checkAndConfigure()
+{
+ Pool pool1;
+ if (!file.exists(pool1))
+ {
+ if(!warnedAlready)
+ {
+ LogLog::debug(((LogString) LOG4CXX_STR("["))
+ + file.getPath()
+ + LOG4CXX_STR("] does not exist."));
+ warnedAlready = true;
+ }
+ }
+ else
+ {
+ apr_time_t thisMod = file.lastModified(pool1);
+ if (thisMod > lastModif)
+ {
+ lastModif = thisMod;
+ doOnChange();
+ warnedAlready = false;
+ }
+ }
+}
+
+void* APR_THREAD_FUNC FileWatchdog::run(apr_thread_t* /* thread */, void* data) {
+ FileWatchdog* pThis = (FileWatchdog*) data;
+
+ unsigned int interrupted = apr_atomic_read32(&pThis->interrupted);
+ while(!interrupted)
+ {
+ apr_sleep(APR_INT64_C(1000) * pThis->delay);
+ interrupted = apr_atomic_read32(&pThis->interrupted);
+ if (!interrupted) {
+ pThis->checkAndConfigure();
+ interrupted = apr_atomic_read32(&pThis->interrupted);
+ }
+ }
+ return NULL;
+}
+
+void FileWatchdog::start()
+{
+ checkAndConfigure();
+
+ thread.run(run, this);
+}
+
+#endif
diff --git a/src/main/cpp/filter.cpp b/src/main/cpp/filter.cpp
new file mode 100644
index 0000000..2d1855d
--- /dev/null
+++ b/src/main/cpp/filter.cpp
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/spi/filter.h>
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+Filter::Filter() : next() {
+}
+
+void Filter::addRef() const {
+ ObjectImpl::addRef();
+}
+
+void Filter::releaseRef() const {
+ ObjectImpl::releaseRef();
+}
+
+FilterPtr Filter::getNext() const {
+ return next;
+}
+
+void Filter::setNext(const FilterPtr& newNext) {
+ next = newNext;
+}
+
+void Filter::activateOptions(Pool&) {
+}
+
+void Filter::setOption(const LogString&, const LogString&) {
+}
+
diff --git a/src/main/cpp/filterbasedtriggeringpolicy.cpp b/src/main/cpp/filterbasedtriggeringpolicy.cpp
new file mode 100644
index 0000000..549d1e4
--- /dev/null
+++ b/src/main/cpp/filterbasedtriggeringpolicy.cpp
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/rolling/filterbasedtriggeringpolicy.h>
+#include <log4cxx/spi/filter.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::spi;
+
+IMPLEMENT_LOG4CXX_OBJECT(FilterBasedTriggeringPolicy)
+
+FilterBasedTriggeringPolicy::FilterBasedTriggeringPolicy() {
+}
+
+
+FilterBasedTriggeringPolicy::~FilterBasedTriggeringPolicy() {
+}
+
+
+bool FilterBasedTriggeringPolicy::isTriggeringEvent(
+ Appender* /* appender */,
+ const log4cxx::spi::LoggingEventPtr& event,
+ const LogString& /* filename */,
+ size_t /* fileLength */ ) {
+ if (headFilter == NULL) {
+ return false;
+ }
+ for(log4cxx::spi::FilterPtr f = headFilter; f != NULL; f = f->getNext()) {
+ switch(f->decide(event)) {
+ case Filter::DENY:
+ return false;
+
+ case Filter::ACCEPT:
+ return true;
+
+ case Filter::NEUTRAL:
+ break;
+ }
+ }
+ return true;
+}
+
+/**
+ * Add a filter to end of the filter list.
+ * @param newFilter filter to add to end of list.
+ */
+void FilterBasedTriggeringPolicy::addFilter(const log4cxx::spi::FilterPtr& newFilter) {
+ if (headFilter == NULL) {
+ headFilter = newFilter;
+ tailFilter = newFilter;
+ } else {
+ tailFilter->setNext(newFilter);
+ tailFilter = newFilter;
+ }
+}
+
+void FilterBasedTriggeringPolicy::clearFilters() {
+ log4cxx::spi::FilterPtr empty;
+ headFilter = empty;
+ tailFilter = empty;
+}
+
+log4cxx::spi::FilterPtr& FilterBasedTriggeringPolicy::getFilter() {
+ return headFilter;
+}
+
+/**
+ * Prepares the instance for use.
+ */
+void FilterBasedTriggeringPolicy::activateOptions(log4cxx::helpers::Pool& p) {
+ for(log4cxx::spi::FilterPtr f = headFilter; f != NULL; f = f->getNext()) {
+ f->activateOptions(p);
+ }
+}
+
+void FilterBasedTriggeringPolicy::setOption(const LogString& /* option */, const LogString& /* value */ ) {
+}
+
+
diff --git a/src/main/cpp/fixedwindowrollingpolicy.cpp b/src/main/cpp/fixedwindowrollingpolicy.cpp
new file mode 100644
index 0000000..0e94007
--- /dev/null
+++ b/src/main/cpp/fixedwindowrollingpolicy.cpp
@@ -0,0 +1,295 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/rolling/fixedwindowrollingpolicy.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/integer.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/rolling/rolloverdescription.h>
+#include <log4cxx/rolling/filerenameaction.h>
+#include <log4cxx/rolling/gzcompressaction.h>
+#include <log4cxx/rolling/zipcompressaction.h>
+#include <log4cxx/pattern/integerpatternconverter.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::helpers;
+using namespace log4cxx::pattern;
+
+IMPLEMENT_LOG4CXX_OBJECT(FixedWindowRollingPolicy)
+
+FixedWindowRollingPolicy::FixedWindowRollingPolicy() :
+ minIndex(1), maxIndex(7) {
+}
+
+void FixedWindowRollingPolicy::setMaxIndex(int maxIndex1) {
+ this->maxIndex = maxIndex1;
+}
+
+void FixedWindowRollingPolicy::setMinIndex(int minIndex1) {
+ this->minIndex = minIndex1;
+}
+
+
+
+void FixedWindowRollingPolicy::setOption(const LogString& option,
+ const LogString& value) {
+ if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("MININDEX"),
+ LOG4CXX_STR("minindex"))) {
+ minIndex = OptionConverter::toInt(value, 1);
+ } else if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("MAXINDEX"),
+ LOG4CXX_STR("maxindex"))) {
+ maxIndex = OptionConverter::toInt(value, 7);
+ } else {
+ RollingPolicyBase::setOption(option, value);
+ }
+}
+
+/**
+ * {@inheritDoc}
+ */
+void FixedWindowRollingPolicy::activateOptions(Pool& p) {
+ RollingPolicyBase::activateOptions(p);
+
+ if (maxIndex < minIndex) {
+ LogLog::warn(
+ LOG4CXX_STR("MaxIndex cannot be smaller than MinIndex."));
+ maxIndex = minIndex;
+ }
+
+ if ((maxIndex - minIndex) > MAX_WINDOW_SIZE) {
+ LogLog::warn(LOG4CXX_STR("Large window sizes are not allowed."));
+ maxIndex = minIndex + MAX_WINDOW_SIZE;
+ }
+
+ PatternConverterPtr itc = getIntegerPatternConverter();
+
+ if (itc == NULL) {
+ throw IllegalStateException();
+ }
+}
+
+/**
+ * {@inheritDoc}
+ */
+RolloverDescriptionPtr FixedWindowRollingPolicy::initialize(
+ const LogString& file, bool append, log4cxx::helpers::Pool& p) {
+ LogString newActiveFile(file);
+ explicitActiveFile = false;
+
+ if (file.length() > 0) {
+ explicitActiveFile = true;
+ newActiveFile = file;
+ }
+
+ if (!explicitActiveFile) {
+ LogString buf;
+ ObjectPtr obj(new Integer(minIndex));
+ formatFileName(obj, buf, p);
+ newActiveFile = buf;
+ }
+
+ ActionPtr noAction;
+
+ return new RolloverDescription(newActiveFile, append, noAction, noAction);
+}
+
+/**
+ * {@inheritDoc}
+ */
+RolloverDescriptionPtr FixedWindowRollingPolicy::rollover(
+ const LogString& currentFileName,
+ log4cxx::helpers::Pool& p) {
+ RolloverDescriptionPtr desc;
+ if (maxIndex >= 0) {
+ int purgeStart = minIndex;
+
+ if (!explicitActiveFile) {
+ purgeStart++;
+ }
+
+ if (!purge(purgeStart, maxIndex, p)) {
+ return desc;
+ }
+
+ LogString buf;
+ ObjectPtr obj(new Integer(purgeStart));
+ formatFileName(obj, buf, p);
+
+ LogString renameTo(buf);
+ LogString compressedName(renameTo);
+ ActionPtr compressAction ;
+
+ if (StringHelper::endsWith(renameTo, LOG4CXX_STR(".gz"))) {
+ renameTo.resize(renameTo.size() - 3);
+ compressAction =
+ new GZCompressAction(
+ File().setPath(renameTo), File().setPath(compressedName), true);
+ } else if (StringHelper::endsWith(renameTo, LOG4CXX_STR(".zip"))) {
+ renameTo.resize(renameTo.size() - 4);
+ compressAction =
+ new ZipCompressAction(
+ File().setPath(renameTo), File().setPath(compressedName), true);
+ }
+
+ FileRenameActionPtr renameAction =
+ new FileRenameAction(
+ File().setPath(currentFileName), File().setPath(renameTo), false);
+
+ desc = new RolloverDescription(
+ currentFileName, false, renameAction, compressAction);
+ }
+
+ return desc;
+}
+
+/**
+ * Get index of oldest log file to be retained.
+ * @return index of oldest log file.
+ */
+int FixedWindowRollingPolicy::getMaxIndex() const {
+ return maxIndex;
+}
+
+/**
+ * Get index of most recent log file.
+ * @return index of oldest log file.
+ */
+int FixedWindowRollingPolicy::getMinIndex() const {
+ return minIndex;
+}
+
+
+/**
+ * Purge and rename old log files in preparation for rollover
+ * @param lowIndex low index
+ * @param highIndex high index. Log file associated with high
+ * index will be deleted if needed.
+ * @return true if purge was successful and rollover should be attempted.
+ */
+bool FixedWindowRollingPolicy::purge(int lowIndex, int highIndex, Pool& p) const {
+ int suffixLength = 0;
+
+ std::vector<FileRenameActionPtr> renames;
+ LogString buf;
+ ObjectPtr obj = new Integer(lowIndex);
+ formatFileName(obj, buf, p);
+
+ LogString lowFilename(buf);
+
+ if (lowFilename.compare(lowFilename.length() - 3, 3, LOG4CXX_STR(".gz")) == 0) {
+ suffixLength = 3;
+ } else if (lowFilename.compare(lowFilename.length() - 4, 4, LOG4CXX_STR(".zip")) == 0) {
+ suffixLength = 4;
+ }
+
+ for (int i = lowIndex; i <= highIndex; i++) {
+ File toRenameCompressed;
+ toRenameCompressed.setPath(lowFilename);
+ File toRenameBase;
+ toRenameBase.setPath(lowFilename.substr(0, lowFilename.length() - suffixLength));
+ File* toRename = &toRenameCompressed;
+ bool isBase = false;
+ bool exists = toRenameCompressed.exists(p);
+
+ if (suffixLength > 0) {
+ if (exists) {
+ if (toRenameBase.exists(p)) {
+ toRenameBase.deleteFile(p);
+ }
+ } else {
+ toRename = &toRenameBase;
+ exists = toRenameBase.exists(p);
+ isBase = true;
+ }
+ }
+
+ if (exists) {
+ //
+ // if at upper index then
+ // attempt to delete last file
+ // if that fails then abandon purge
+ if (i == highIndex) {
+ if (!toRename->deleteFile(p)) {
+ return false;
+ }
+
+ break;
+ }
+
+ //
+ // if intermediate index
+ // add a rename action to the list
+ buf.erase(buf.begin(), buf.end());
+ obj = new Integer(i + 1);
+ formatFileName(obj, buf, p);
+
+ LogString highFilename(buf);
+ LogString renameTo(highFilename);
+
+ if (isBase) {
+ renameTo =
+ highFilename.substr(0, highFilename.length() - suffixLength);
+ }
+
+ renames.push_back(new FileRenameAction(*toRename, File().setPath(renameTo), true));
+ lowFilename = highFilename;
+ } else {
+ break;
+ }
+ }
+
+ //
+ // work renames backwards
+ //
+ for(std::vector<FileRenameActionPtr>::reverse_iterator iter = renames.rbegin();
+ iter != renames.rend();
+ iter++) {
+
+ try {
+ if (!(*iter)->execute(p)) {
+ return false;
+ }
+ } catch (std::exception& ex) {
+ LogLog::warn(LOG4CXX_STR("Exception during purge in RollingFileAppender"));
+
+ return false;
+ }
+ }
+ return true;
+}
+
+#define RULES_PUT(spec, cls) \
+specs.insert(PatternMap::value_type(LogString(LOG4CXX_STR(spec)), (PatternConstructor) cls ::newInstance))
+
+
+log4cxx::pattern::PatternMap FixedWindowRollingPolicy::getFormatSpecifiers() const {
+ PatternMap specs;
+ RULES_PUT("i", IntegerPatternConverter);
+ RULES_PUT("index", IntegerPatternConverter);
+ return specs;
+}
diff --git a/src/main/cpp/formattinginfo.cpp b/src/main/cpp/formattinginfo.cpp
new file mode 100644
index 0000000..5c900c0
--- /dev/null
+++ b/src/main/cpp/formattinginfo.cpp
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/pattern/formattinginfo.h>
+#include <limits.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+
+IMPLEMENT_LOG4CXX_OBJECT(FormattingInfo)
+
+ /**
+ * Creates new instance.
+ * @param leftAlign left align if true.
+ * @param minLength minimum length.
+ * @param maxLength maximum length.
+ */
+FormattingInfo::FormattingInfo(
+ const bool leftAlign1, const int minLength1, const int maxLength1) :
+ minLength(minLength1),
+ maxLength(maxLength1),
+ leftAlign(leftAlign1) {
+}
+
+ /**
+ * Gets default instance.
+ * @return default instance.
+ */
+FormattingInfoPtr FormattingInfo::getDefault() {
+ static FormattingInfoPtr def(new FormattingInfo(false, 0, INT_MAX));
+ return def;
+}
+
+ /**
+ * Adjust the content of the buffer based on the specified lengths and alignment.
+ *
+ * @param fieldStart start of field in buffer.
+ * @param buffer buffer to be modified.
+ */
+void FormattingInfo::format(const int fieldStart, LogString& buffer) const {
+ int rawLength = buffer.length() - fieldStart;
+
+ if (rawLength > maxLength) {
+ buffer.erase(buffer.begin() + fieldStart,
+ buffer.begin() + fieldStart + (rawLength - maxLength));
+ } else if (rawLength < minLength) {
+ if (leftAlign) {
+ buffer.append(minLength - rawLength, (logchar) 0x20 /* ' ' */);
+ } else {
+ buffer.insert(fieldStart, minLength - rawLength, 0x20 /* ' ' */);
+ }
+ }
+ }
diff --git a/src/main/cpp/fulllocationpatternconverter.cpp b/src/main/cpp/fulllocationpatternconverter.cpp
new file mode 100644
index 0000000..a73da7b
--- /dev/null
+++ b/src/main/cpp/fulllocationpatternconverter.cpp
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/fulllocationpatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+#include <log4cxx/helpers/stringhelper.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(FullLocationPatternConverter)
+
+FullLocationPatternConverter::FullLocationPatternConverter() :
+ LoggingEventPatternConverter(LOG4CXX_STR("Full Location"),
+ LOG4CXX_STR("fullLocation")) {
+}
+
+PatternConverterPtr FullLocationPatternConverter::newInstance(
+ const std::vector<LogString>& /* options */) {
+ static PatternConverterPtr instance(new FullLocationPatternConverter());
+ return instance;
+}
+
+void FullLocationPatternConverter::format(
+ const LoggingEventPtr& event,
+ LogString& toAppendTo,
+ Pool& p) const {
+ append(toAppendTo, event->getLocationInformation().getFileName());
+ toAppendTo.append(1, (logchar) 0x28 /* '(' */);
+ StringHelper::toString(
+ event->getLocationInformation().getLineNumber(),
+ p, toAppendTo);
+ toAppendTo.append(1, (logchar) 0x29 /* ')' */);
+}
diff --git a/src/main/cpp/gzcompressaction.cpp b/src/main/cpp/gzcompressaction.cpp
new file mode 100644
index 0000000..f43f5d0
--- /dev/null
+++ b/src/main/cpp/gzcompressaction.cpp
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/rolling/gzcompressaction.h>
+#include <apr_thread_proc.h>
+#include <apr_strings.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/transcoder.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(GZCompressAction)
+
+GZCompressAction::GZCompressAction(const File& src,
+ const File& dest,
+ bool del)
+ : source(src), destination(dest), deleteSource(del) {
+}
+
+bool GZCompressAction::execute(log4cxx::helpers::Pool& p) const {
+ if (source.exists(p)) {
+ apr_pool_t* pool = p.getAPRPool();
+ apr_procattr_t* attr;
+ apr_status_t stat = apr_procattr_create(&attr, pool);
+ if (stat != APR_SUCCESS) throw IOException(stat);
+
+ stat = apr_procattr_io_set(attr, APR_NO_PIPE, APR_FULL_BLOCK, APR_FULL_BLOCK);
+ if (stat != APR_SUCCESS) throw IOException(stat);
+
+ stat = apr_procattr_cmdtype_set(attr, APR_PROGRAM_PATH);
+ if (stat != APR_SUCCESS) throw IOException(stat);
+
+ //
+ // set child process output to destination file
+ //
+ apr_file_t* child_out;
+ apr_int32_t flags = APR_FOPEN_READ | APR_FOPEN_WRITE |
+ APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE;
+ stat = destination.open(&child_out, flags, APR_OS_DEFAULT, p);
+ if (stat != APR_SUCCESS) throw IOException(stat);
+
+ stat = apr_procattr_child_out_set(attr, child_out, NULL);
+ if (stat != APR_SUCCESS) throw IOException(stat);
+
+ //
+ // redirect the child's error stream to this processes' error stream
+ //
+ apr_file_t* child_err;
+ stat = apr_file_open_stderr(&child_err, pool);
+ if (stat == APR_SUCCESS) {
+ stat = apr_procattr_child_err_set(attr, child_err, NULL);
+ if (stat != APR_SUCCESS) throw IOException(stat);
+ }
+
+ const char** args = (const char**)
+ apr_palloc(pool, 4 *sizeof(*args));
+ int i = 0;
+ args[i++] = "gzip";
+ args[i++] = "-c";
+ args[i++] = Transcoder::encode(source.getPath(), p);
+ args[i++] = NULL;
+
+
+ apr_proc_t pid;
+ stat = apr_proc_create(&pid, "gzip", args, NULL, attr, pool);
+ if (stat != APR_SUCCESS) throw IOException(stat);
+
+ apr_proc_wait(&pid, NULL, NULL, APR_WAIT);
+ stat = apr_file_close(child_out);
+ if (stat != APR_SUCCESS) throw IOException(stat);
+
+ if (deleteSource) {
+ source.deleteFile(p);
+ }
+ return true;
+ }
+ return false;
+}
+
diff --git a/src/main/cpp/hierarchy.cpp b/src/main/cpp/hierarchy.cpp
new file mode 100644
index 0000000..ed40421
--- /dev/null
+++ b/src/main/cpp/hierarchy.cpp
@@ -0,0 +1,399 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/spi/loggerfactory.h>
+#include <log4cxx/hierarchy.h>
+#include <log4cxx/defaultloggerfactory.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/spi/hierarchyeventlistener.h>
+#include <log4cxx/level.h>
+#include <algorithm>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/appender.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/stringhelper.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/helpers/aprinitializer.h>
+#include <log4cxx/defaultconfigurator.h>
+#include <log4cxx/spi/rootlogger.h>
+#include <apr_atomic.h>
+#include "assert.h"
+
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(Hierarchy)
+
+Hierarchy::Hierarchy() :
+pool(),
+mutex(pool),
+loggers(new LoggerMap()),
+provisionNodes(new ProvisionNodeMap())
+{
+ synchronized sync(mutex);
+ root = new RootLogger(pool, Level::getDebug());
+ root->setHierarchy(this);
+ defaultFactory = new DefaultLoggerFactory();
+ emittedNoAppenderWarning = false;
+ configured = false;
+ thresholdInt = Level::ALL_INT;
+ threshold = Level::getAll();
+ emittedNoResourceBundleWarning = false;
+}
+
+Hierarchy::~Hierarchy()
+{
+ delete loggers;
+ delete provisionNodes;
+}
+
+void Hierarchy::addRef() const {
+ ObjectImpl::addRef();
+}
+
+void Hierarchy::releaseRef() const {
+ ObjectImpl::releaseRef();
+}
+
+void Hierarchy::addHierarchyEventListener(const spi::HierarchyEventListenerPtr& listener)
+{
+ synchronized sync(mutex);
+ if (std::find(listeners.begin(), listeners.end(), listener) != listeners.end())
+ {
+ LogLog::warn(LOG4CXX_STR("Ignoring attempt to add an existent listener."));
+ }
+ else
+ {
+ listeners.push_back(listener);
+ }
+}
+
+void Hierarchy::clear()
+{
+ synchronized sync(mutex);
+ loggers->clear();
+}
+
+void Hierarchy::emitNoAppenderWarning(const LoggerPtr& logger)
+{
+ bool emitWarning = false;
+ {
+ synchronized sync(mutex);
+ emitWarning = !emittedNoAppenderWarning;
+ emittedNoAppenderWarning = true;
+ }
+
+ // No appender in hierarchy, warn user only once.
+ if(emitWarning)
+ {
+ LogLog::warn(((LogString) LOG4CXX_STR("No appender could be found for logger ("))
+ + logger->getName() + LOG4CXX_STR(")."));
+ LogLog::warn(LOG4CXX_STR("Please initialize the log4cxx system properly."));
+ }
+}
+
+
+LoggerPtr Hierarchy::exists(const LogString& name)
+{
+ synchronized sync(mutex);
+
+ LoggerPtr logger;
+ LoggerMap::iterator it = loggers->find(name);
+ if (it != loggers->end())
+ {
+ logger = it->second;
+ }
+
+
+ return logger;
+}
+
+void Hierarchy::setThreshold(const LevelPtr& l)
+{
+ if (l != 0)
+ {
+ synchronized sync(mutex);
+ thresholdInt = l->toInt();
+ threshold = l;
+ if (thresholdInt != Level::ALL_INT) {
+ setConfigured(true);
+ }
+ }
+}
+
+void Hierarchy::setThreshold(const LogString& levelStr) {
+ LevelPtr l(Level::toLevelLS(levelStr, 0));
+
+ if(l != 0)
+ {
+ setThreshold(l);
+ }
+ else
+ {
+ LogLog::warn(((LogString) LOG4CXX_STR("No level could be found named \""))
+ + levelStr + LOG4CXX_STR("\"."));
+ }
+}
+
+void Hierarchy::fireAddAppenderEvent(const LoggerPtr& logger, const AppenderPtr& appender)
+{
+ setConfigured(true);
+ HierarchyEventListenerList clonedList;
+ {
+ synchronized sync(mutex);
+ clonedList = listeners;
+ }
+
+ HierarchyEventListenerList::iterator it, itEnd = clonedList.end();
+ HierarchyEventListenerPtr listener;
+
+ for(it = clonedList.begin(); it != itEnd; it++)
+ {
+ listener = *it;
+ listener->addAppenderEvent(logger, appender);
+ }
+}
+
+void Hierarchy::fireRemoveAppenderEvent(const LoggerPtr& logger, const AppenderPtr& appender)
+
+{
+ HierarchyEventListenerList clonedList;
+ {
+ synchronized sync(mutex);
+ clonedList = listeners;
+ }
+ HierarchyEventListenerList::iterator it, itEnd = clonedList.end();
+ HierarchyEventListenerPtr listener;
+
+ for(it = clonedList.begin(); it != itEnd; it++)
+ {
+ listener = *it;
+ listener->removeAppenderEvent(logger, appender);
+ }
+}
+
+const LevelPtr& Hierarchy::getThreshold() const
+{
+ return threshold;
+}
+
+LoggerPtr Hierarchy::getLogger(const LogString& name)
+{
+ return getLogger(name, defaultFactory);
+}
+
+LoggerPtr Hierarchy::getLogger(const LogString& name,
+ const spi::LoggerFactoryPtr& factory)
+{
+ synchronized sync(mutex);
+
+ LoggerMap::iterator it = loggers->find(name);
+
+ if (it != loggers->end())
+ {
+ return it->second;
+ }
+ else
+ {
+ LoggerPtr logger(factory->makeNewLoggerInstance(pool, name));
+ logger->setHierarchy(this);
+ loggers->insert(LoggerMap::value_type(name, logger));
+
+ ProvisionNodeMap::iterator it2 = provisionNodes->find(name);
+ if (it2 != provisionNodes->end())
+ {
+ updateChildren(it2->second, logger);
+ provisionNodes->erase(it2);
+ }
+
+ updateParents(logger);
+ return logger;
+ }
+
+}
+
+LoggerList Hierarchy::getCurrentLoggers() const
+{
+ synchronized sync(mutex);
+
+ LoggerList v;
+ LoggerMap::const_iterator it, itEnd = loggers->end();
+
+ for (it = loggers->begin(); it != itEnd; it++)
+ {
+ v.push_back(it->second);
+ }
+
+
+ return v;
+}
+
+LoggerPtr Hierarchy::getRootLogger() const
+{
+ return root;
+}
+
+bool Hierarchy::isDisabled(int level) const
+{
+ if(!configured) {
+ synchronized sync(mutex);
+ if (!configured) {
+ DefaultConfigurator::configure(
+ const_cast<Hierarchy*>(this));
+ }
+ }
+
+ return thresholdInt > level;
+}
+
+
+void Hierarchy::resetConfiguration()
+{
+ synchronized sync(mutex);
+
+ getRootLogger()->setLevel(Level::getDebug());
+ root->setResourceBundle(0);
+ setThreshold(Level::getAll());
+
+ shutdown(); // nested locks are OK
+
+ LoggerList loggers1 = getCurrentLoggers();
+ LoggerList::iterator it, itEnd = loggers1.end();
+
+ for (it = loggers1.begin(); it != itEnd; it++)
+ {
+ LoggerPtr& logger = *it;
+ logger->setLevel(0);
+ logger->setAdditivity(true);
+ logger->setResourceBundle(0);
+ }
+
+ //rendererMap.clear();
+}
+
+void Hierarchy::shutdown()
+{
+ synchronized sync(mutex);
+
+ setConfigured(false);
+
+ LoggerPtr root1 = getRootLogger();
+
+ // begin by closing nested appenders
+ root1->closeNestedAppenders();
+
+ LoggerList loggers1 = getCurrentLoggers();
+ LoggerList::iterator it, itEnd = loggers1.end();
+
+ for (it = loggers1.begin(); it != itEnd; it++)
+ {
+ LoggerPtr& logger = *it;
+ logger->closeNestedAppenders();
+ }
+
+ // then, remove all appenders
+ root1->removeAllAppenders();
+ for (it = loggers1.begin(); it != itEnd; it++)
+ {
+ LoggerPtr& logger = *it;
+ logger->removeAllAppenders();
+ }
+}
+
+
+void Hierarchy::updateParents(LoggerPtr logger)
+{
+ synchronized sync(mutex);
+ const LogString name(logger->getName());
+ int length = name.size();
+ 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(0x2E /* '.' */, length-1);
+ i != LogString::npos;
+ i = name.find_last_of(0x2E /* '.' */, i-1))
+ {
+ LogString substr = name.substr(0, i);
+
+ LoggerMap::iterator it = loggers->find(substr);
+ if(it != loggers->end())
+ {
+ parentFound = true;
+ logger->parent = it->second;
+ 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(1, logger);
+ provisionNodes->insert(
+ ProvisionNodeMap::value_type(substr, node));
+ }
+ }
+ }
+
+ // If we could not find any existing parents, then link with root.
+ if(!parentFound)
+ {
+ logger->parent = root;
+ }
+}
+
+void Hierarchy::updateChildren(ProvisionNode& pn, LoggerPtr logger)
+{
+
+ ProvisionNode::iterator it, itEnd = pn.end();
+
+ for(it = pn.begin(); it != itEnd; it++)
+ {
+ LoggerPtr& l = *it;
+
+ // Unless this child already points to a correct (lower) parent,
+ // make cat.parent point to l.parent and l.parent to cat.
+ if(!StringHelper::startsWith(l->parent->name, logger->name))
+ {
+ logger->parent = l->parent;
+ l->parent = logger;
+ }
+ }
+}
+
+void Hierarchy::setConfigured(bool newValue) {
+ synchronized sync(mutex);
+ configured = newValue;
+}
+
+bool Hierarchy::isConfigured() {
+ return configured;
+}
diff --git a/src/main/cpp/htmllayout.cpp b/src/main/cpp/htmllayout.cpp
new file mode 100644
index 0000000..8538b82
--- /dev/null
+++ b/src/main/cpp/htmllayout.cpp
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/htmllayout.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/level.h>
+#include <log4cxx/helpers/transform.h>
+#include <log4cxx/helpers/iso8601dateformat.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/transcoder.h>
+
+#include <apr_time.h>
+#include <apr_strings.h>
+#include <string.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+IMPLEMENT_LOG4CXX_OBJECT(HTMLLayout)
+
+
+HTMLLayout::HTMLLayout()
+: locationInfo(false), title(LOG4CXX_STR("Log4cxx Log Messages")),
+dateFormat()
+{
+ dateFormat.setTimeZone(TimeZone::getGMT());
+}
+
+
+void HTMLLayout::setOption(const LogString& option,
+ const LogString& value)
+{
+
+ if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("TITLE"), LOG4CXX_STR("title")))
+ {
+ setTitle(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("LOCATIONINFO"), LOG4CXX_STR("locationinfo")))
+ {
+ setLocationInfo(OptionConverter::toBoolean(value, false));
+ }
+}
+
+void HTMLLayout::format(LogString& output,
+ const spi::LoggingEventPtr& event,
+ Pool& p) const
+{
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<tr>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<td>"));
+
+ dateFormat.format(output, event->getTimeStamp(), p);
+
+
+ output.append(LOG4CXX_STR("</td>"));
+ output.append(LOG4CXX_EOL);
+
+ output.append(LOG4CXX_STR("<td title=\""));
+ LogString threadName(event->getThreadName());
+ output.append(threadName);
+ output.append(LOG4CXX_STR(" thread\">"));
+ output.append(threadName);
+ output.append(LOG4CXX_STR("</td>"));
+ output.append(LOG4CXX_EOL);
+
+ output.append(LOG4CXX_STR("<td title=\"Level\">"));
+ if (event->getLevel()->equals(Level::getDebug()))
+ {
+ output.append(LOG4CXX_STR("<font color=\"#339933\">"));
+ output.append(event->getLevel()->toString());
+ output.append(LOG4CXX_STR("</font>"));
+ }
+ else if(event->getLevel()->isGreaterOrEqual(Level::getWarn()))
+ {
+ output.append(LOG4CXX_STR("<font color=\"#993300\"><strong>"));
+ output.append(event->getLevel()->toString());
+ output.append(LOG4CXX_STR("</strong></font>"));
+ }
+ else
+ {
+ output.append(event->getLevel()->toString());
+ }
+
+ output.append(LOG4CXX_STR("</td>"));
+ output.append(LOG4CXX_EOL);
+
+ output.append(LOG4CXX_STR("<td title=\""));
+ output.append(event->getLoggerName());
+ output.append(LOG4CXX_STR(" logger\">"));
+ Transform::appendEscapingTags(output, event->getLoggerName());
+ output.append(LOG4CXX_STR("</td>"));
+ output.append(LOG4CXX_EOL);
+
+ if(locationInfo)
+ {
+ output.append(LOG4CXX_STR("<td>"));
+ const LocationInfo& locInfo = event->getLocationInformation();
+ LOG4CXX_DECODE_CHAR(fileName, locInfo.getFileName());
+ Transform::appendEscapingTags(output, fileName);
+ output.append(1, (logchar) 0x3A /* ':' */);
+ int line = event->getLocationInformation().getLineNumber();
+ if (line != 0)
+ {
+ StringHelper::toString(line, p, output);
+ }
+ output.append(LOG4CXX_STR("</td>"));
+ output.append(LOG4CXX_EOL);
+ }
+
+ output.append(LOG4CXX_STR("<td title=\"Message\">"));
+ Transform::appendEscapingTags(output, event->getRenderedMessage());
+ output.append(LOG4CXX_STR("</td>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("</tr>"));
+ output.append(LOG4CXX_EOL);
+
+ LogString ndcVal;
+ if (event->getNDC(ndcVal))
+ {
+ output.append(LOG4CXX_STR("<tr><td bgcolor=\"#EEEEEE\" "));
+ output.append(LOG4CXX_STR("style=\"font-size : xx-small;\" colspan=\"6\" "));
+ output.append(LOG4CXX_STR("title=\"Nested Diagnostic Context\">"));
+ output.append(LOG4CXX_STR("NDC: "));
+ Transform::appendEscapingTags(output, ndcVal);
+ output.append(LOG4CXX_STR("</td></tr>"));
+ output.append(LOG4CXX_EOL);
+ }
+}
+
+void HTMLLayout::appendHeader(LogString& output, Pool& p)
+{
+ output.append(LOG4CXX_STR("<!DOCTYPE HTML PUBLIC "));
+ output.append(LOG4CXX_STR("\"-//W3C//DTD HTML 4.01 Transitional//EN\" "));
+ output.append(LOG4CXX_STR("\"http://www.w3.org/TR/html4/loose.dtd\">"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<html>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<head>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<title>"));
+ output.append(title);
+ output.append(LOG4CXX_STR("</title>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<style type=\"text/css\">"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<!--"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("body, table {font-family: arial,sans-serif; font-size: x-small;}"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("th {background: #336699; color: #FFFFFF; text-align: left;}"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("-->"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("</style>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("</head>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<body bgcolor=\"#FFFFFF\" topmargin=\"6\" leftmargin=\"6\">"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<hr size=\"1\" noshade>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("Log session start time "));
+
+ dateFormat.format(output, apr_time_now(), p);
+
+ output.append(LOG4CXX_STR("<br>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<br>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<table cellspacing=\"0\" cellpadding=\"4\" border=\"1\" bordercolor=\"#224466\" width=\"100%\">"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<tr>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<th>Time</th>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<th>Thread</th>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<th>Level</th>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<th>Logger</th>"));
+ output.append(LOG4CXX_EOL);
+ if(locationInfo)
+ {
+ output.append(LOG4CXX_STR("<th>File:Line</th>"));
+ output.append(LOG4CXX_EOL);
+ }
+ output.append(LOG4CXX_STR("<th>Message</th>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("</tr>"));
+ output.append(LOG4CXX_EOL);
+}
+
+void HTMLLayout::appendFooter(LogString& output, Pool& /* pool */ )
+{
+ output.append(LOG4CXX_STR("</table>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("<br>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_STR("</body></html>"));
+}
diff --git a/src/main/cpp/inetaddress.cpp b/src/main/cpp/inetaddress.cpp
new file mode 100644
index 0000000..a0cce3c
--- /dev/null
+++ b/src/main/cpp/inetaddress.cpp
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/inetaddress.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/pool.h>
+
+#include "apr_network_io.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(InetAddress)
+
+UnknownHostException::UnknownHostException(const LogString& msg1)
+ : Exception(msg1) {
+}
+
+UnknownHostException::UnknownHostException(const UnknownHostException& src)
+ : Exception(src) {
+}
+
+UnknownHostException& UnknownHostException::operator=(const UnknownHostException& src) {
+ Exception::operator=(src);
+ return *this;
+}
+
+
+InetAddress::InetAddress(const LogString& hostName, const LogString& hostAddr)
+ : ipAddrString(hostAddr), hostNameString(hostName) {
+}
+
+
+/** Determines all the IP addresses of a host, given the host's name.
+*/
+std::vector<InetAddressPtr> InetAddress::getAllByName(const LogString& host) {
+ LOG4CXX_ENCODE_CHAR(encodedHost, host);
+
+ // retrieve information about the given host
+ Pool addrPool;
+
+ apr_sockaddr_t *address = 0;
+ apr_status_t status =
+ apr_sockaddr_info_get(&address, encodedHost.c_str(),
+ APR_INET, 0, 0, addrPool.getAPRPool());
+ if (status != APR_SUCCESS) {
+ LogString msg(LOG4CXX_STR("Cannot get information about host: "));
+ msg.append(host);
+ LogLog::error(msg);
+ throw UnknownHostException(msg);
+ }
+
+ std::vector<InetAddressPtr> result;
+ apr_sockaddr_t *currentAddr = address;
+ while(currentAddr != NULL) {
+ // retrieve the IP address of this InetAddress.
+ LogString ipAddrString;
+ char *ipAddr;
+ status = apr_sockaddr_ip_get(&ipAddr, currentAddr);
+ if (status == APR_SUCCESS) {
+ std::string ip(ipAddr);
+ Transcoder::decode(ip, ipAddrString);
+ }
+
+ // retrieve the host name of this InetAddress.
+ LogString hostNameString;
+ char *hostName;
+ status = apr_getnameinfo(&hostName, currentAddr, 0);
+ if (status == APR_SUCCESS) {
+ std::string host(hostName);
+ Transcoder::decode(host, hostNameString);
+ }
+
+ result.push_back(new InetAddress(hostNameString, ipAddrString));
+ currentAddr = currentAddr->next;
+ }
+
+ return result;
+}
+
+
+/** Determines the IP address of a host, given the host's name.
+*/
+InetAddressPtr InetAddress::getByName(const LogString& host) {
+ return getAllByName(host)[0];
+}
+
+/** Returns the IP address string "%d.%d.%d.%d".
+*/
+LogString InetAddress::getHostAddress() const
+{
+ return ipAddrString;
+}
+
+/** Gets the host name for this IP address.
+*/
+LogString InetAddress::getHostName() const
+{
+ return hostNameString;
+}
+
+/** Returns the local host.
+*/
+InetAddressPtr InetAddress::getLocalHost()
+{
+ return getByName(LOG4CXX_STR("127.0.0.1"));
+}
+
+
+InetAddressPtr InetAddress::anyAddress() {
+ // APR_ANYADDR does not work with the LOG4CXX_STR macro
+ return getByName(LOG4CXX_STR("0.0.0.0"));
+}
+
+
+/** Converts this IP address to a String.
+*/
+LogString InetAddress::toString() const
+{
+ LogString rv(getHostName());
+ rv.append(LOG4CXX_STR("/"));
+ rv.append(getHostAddress());
+ return rv;
+}
+
diff --git a/src/main/cpp/inputstream.cpp b/src/main/cpp/inputstream.cpp
new file mode 100644
index 0000000..dec830b
--- /dev/null
+++ b/src/main/cpp/inputstream.cpp
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/inputstream.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(InputStream)
+
+InputStream::InputStream() {
+}
+
+InputStream::~InputStream() {
+}
diff --git a/src/main/cpp/inputstreamreader.cpp b/src/main/cpp/inputstreamreader.cpp
new file mode 100644
index 0000000..52b1c0a
--- /dev/null
+++ b/src/main/cpp/inputstreamreader.cpp
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/inputstreamreader.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/bytebuffer.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(InputStreamReader)
+
+InputStreamReader::InputStreamReader(const InputStreamPtr& in1)
+ : in(in1), dec(CharsetDecoder::getDefaultDecoder()) {
+ if (in1 == 0) {
+ throw NullPointerException(LOG4CXX_STR("in parameter may not be null."));
+ }
+}
+
+InputStreamReader::InputStreamReader(const InputStreamPtr& in1, const CharsetDecoderPtr &dec1)
+ : in(in1), dec(dec1) {
+ if (in1 == 0) {
+ throw NullPointerException(LOG4CXX_STR("in parameter may not be null."));
+ }
+ if (dec1 == 0) {
+ throw NullPointerException(LOG4CXX_STR("dec parameter may not be null."));
+ }
+}
+
+InputStreamReader::~InputStreamReader() {
+}
+
+void InputStreamReader::close(Pool& ) {
+ in->close();
+}
+
+LogString InputStreamReader::read(Pool& p) {
+ const size_t BUFSIZE = 4096;
+ ByteBuffer buf(p.pstralloc(BUFSIZE), BUFSIZE);
+ LogString output;
+
+ // read whole file
+ while(in->read(buf) >= 0) {
+ buf.flip();
+ log4cxx_status_t stat = dec->decode(buf, output);
+ if (stat != 0) {
+ throw IOException(stat);
+ }
+ if (buf.remaining() > 0) {
+ memmove(buf.data(), buf.current(), buf.remaining());
+ buf.limit(buf.remaining());
+ } else {
+ buf.clear();
+ }
+ }
+
+ return output;
+}
diff --git a/src/main/cpp/integer.cpp b/src/main/cpp/integer.cpp
new file mode 100644
index 0000000..1523c06
--- /dev/null
+++ b/src/main/cpp/integer.cpp
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/integer.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(Integer)
+
+
+Integer::Integer() : val(0){
+}
+
+Integer::Integer(int val1) : val(val1) {
+}
+
+Integer::~Integer() {
+}
diff --git a/src/main/cpp/integerpatternconverter.cpp b/src/main/cpp/integerpatternconverter.cpp
new file mode 100644
index 0000000..1f3d9f7
--- /dev/null
+++ b/src/main/cpp/integerpatternconverter.cpp
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/integerpatternconverter.h>
+#include <log4cxx/helpers/integer.h>
+#include <log4cxx/helpers/stringhelper.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(IntegerPatternConverter)
+
+IntegerPatternConverter::IntegerPatternConverter() :
+ PatternConverter(LOG4CXX_STR("Integer"),
+ LOG4CXX_STR("integer")) {
+}
+
+PatternConverterPtr IntegerPatternConverter::newInstance(
+ const std::vector<LogString>& /* options */) {
+ static PatternConverterPtr instance(new IntegerPatternConverter());
+ return instance;
+}
+
+void IntegerPatternConverter::format(
+ const ObjectPtr& obj,
+ LogString& toAppendTo,
+ Pool& p) const {
+ IntegerPtr i(obj);
+ if (i != NULL) {
+ StringHelper::toString(i->intValue(), p, toAppendTo);
+ }
+}
diff --git a/src/main/cpp/layout.cpp b/src/main/cpp/layout.cpp
new file mode 100644
index 0000000..8f75554
--- /dev/null
+++ b/src/main/cpp/layout.cpp
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/layout.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(Layout)
+
+
+Layout::~Layout() {}
+
+void Layout::addRef() const {
+ ObjectImpl::addRef();
+}
+
+void Layout::releaseRef() const {
+ ObjectImpl::releaseRef();
+}
+
+LogString Layout::getContentType() const { return LOG4CXX_STR("text/plain"); }
+
+void Layout::appendHeader(LogString&, log4cxx::helpers::Pool&) {}
+
+void Layout::appendFooter(LogString&, log4cxx::helpers::Pool&) {}
diff --git a/src/main/cpp/level.cpp b/src/main/cpp/level.cpp
new file mode 100644
index 0000000..f784203
--- /dev/null
+++ b/src/main/cpp/level.cpp
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/level.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/transcoder.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/helpers/aprinitializer.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT_WITH_CUSTOM_CLASS(Level, LevelClass)
+
+LevelPtr Level::getOff() {
+ static LevelPtr level(new Level(Level::OFF_INT, LOG4CXX_STR("OFF"), 0));
+ return level;
+}
+
+LevelPtr Level::getFatal() {
+ static LevelPtr level(new Level(Level::FATAL_INT, LOG4CXX_STR("FATAL"), 0));
+ return level;
+}
+
+LevelPtr Level::getError() {
+ static LevelPtr level(new Level(Level::ERROR_INT, LOG4CXX_STR("ERROR"), 3));
+ return level;
+}
+
+LevelPtr Level::getWarn() {
+ static LevelPtr level(new Level(Level::WARN_INT, LOG4CXX_STR("WARN"), 4));
+ return level;
+}
+
+LevelPtr Level::getInfo() {
+ static LevelPtr level(new Level(Level::INFO_INT, LOG4CXX_STR("INFO"), 6));
+ return level;
+}
+
+LevelPtr Level::getDebug() {
+ static LevelPtr level(new Level(Level::DEBUG_INT, LOG4CXX_STR("DEBUG"), 7));
+ return level;
+}
+
+LevelPtr Level::getTrace() {
+ static LevelPtr level(new Level(Level::TRACE_INT, LOG4CXX_STR("TRACE"), 7));
+ return level;
+}
+
+
+LevelPtr Level::getAll() {
+ static LevelPtr level(new Level(Level::ALL_INT, LOG4CXX_STR("ALL"), 7));
+ return level;
+}
+
+
+
+Level::Level(int level1,
+ const LogString& name1, int syslogEquivalent1)
+: level(level1), name(name1), syslogEquivalent(syslogEquivalent1)
+{
+ APRInitializer::initialize();
+}
+
+
+LevelPtr Level::toLevelLS(const LogString& sArg)
+{
+ return toLevelLS(sArg, Level::getDebug());
+}
+
+LogString Level::toString() const {
+ return name;
+}
+
+
+LevelPtr Level::toLevel(int val)
+{
+ return toLevel(val, Level::getDebug());
+}
+
+LevelPtr Level::toLevel(int val, const LevelPtr& defaultLevel)
+{
+ switch(val)
+ {
+ case ALL_INT: return getAll();
+ case DEBUG_INT: return getDebug();
+ case TRACE_INT: return getTrace();
+ case INFO_INT: return getInfo();
+ case WARN_INT: return getWarn();
+ case ERROR_INT: return getError();
+ case FATAL_INT: return getFatal();
+ case OFF_INT: return getOff();
+ default: return defaultLevel;
+ }
+}
+
+LevelPtr Level::toLevel(const std::string& sArg)
+{
+ return toLevel(sArg, Level::getDebug());
+}
+
+LevelPtr Level::toLevel(const std::string& sArg, const LevelPtr& defaultLevel)
+{
+ LOG4CXX_DECODE_CHAR(s, sArg);
+ return toLevelLS(s, defaultLevel);
+}
+
+void Level::toString(std::string& dst) const {
+ Transcoder::encode(name, dst);
+}
+
+#if LOG4CXX_WCHAR_T_API
+LevelPtr Level::toLevel(const std::wstring& sArg)
+{
+ return toLevel(sArg, Level::getDebug());
+}
+
+LevelPtr Level::toLevel(const std::wstring& sArg, const LevelPtr& defaultLevel)
+{
+ LOG4CXX_DECODE_WCHAR(s, sArg);
+ return toLevelLS(s, defaultLevel);
+}
+
+void Level::toString(std::wstring& dst) const {
+ Transcoder::encode(name, dst);
+}
+
+#endif
+
+#if LOG4CXX_UNICHAR_API
+LevelPtr Level::toLevel(const std::basic_string<UniChar>& sArg)
+{
+ return toLevel(sArg, Level::getDebug());
+}
+
+LevelPtr Level::toLevel(const std::basic_string<UniChar>& sArg, const LevelPtr& defaultLevel)
+{
+ LOG4CXX_DECODE_UNICHAR(s, sArg);
+ return toLevelLS(s, defaultLevel);
+}
+
+void Level::toString(std::basic_string<UniChar>& dst) const {
+ Transcoder::encode(name, dst);
+}
+
+#endif
+
+#if LOG4CXX_CFSTRING_API
+LevelPtr Level::toLevel(const CFStringRef& sArg)
+{
+ return toLevel(sArg, Level::getDebug());
+}
+
+LevelPtr Level::toLevel(const CFStringRef& sArg, const LevelPtr& defaultLevel)
+{
+ LogString s;
+ Transcoder::decode(sArg, s);
+ return toLevelLS(s, defaultLevel);
+}
+
+void Level::toString(CFStringRef& dst) const {
+ dst = Transcoder::encode(name);
+}
+#endif
+
+
+LevelPtr Level::toLevelLS(const LogString& sArg, const LevelPtr& defaultLevel)
+{
+ const size_t len = sArg.length();
+
+ if (len == 4) {
+ if (StringHelper::equalsIgnoreCase(sArg, LOG4CXX_STR("INFO"), LOG4CXX_STR("info"))) {
+ return getInfo();
+ }
+ if (StringHelper::equalsIgnoreCase(sArg, LOG4CXX_STR("WARN"), LOG4CXX_STR("warn"))) {
+ return getWarn();
+ }
+ } else {
+ if (len == 5) {
+ if (StringHelper::equalsIgnoreCase(sArg, LOG4CXX_STR("DEBUG"), LOG4CXX_STR("debug"))) {
+ return getDebug();
+ }
+ if (StringHelper::equalsIgnoreCase(sArg, LOG4CXX_STR("TRACE"), LOG4CXX_STR("trace"))) {
+ return getTrace();
+ }
+ if (StringHelper::equalsIgnoreCase(sArg, LOG4CXX_STR("ERROR"), LOG4CXX_STR("error"))) {
+ return getError();
+ }
+ if (StringHelper::equalsIgnoreCase(sArg, LOG4CXX_STR("FATAL"), LOG4CXX_STR("fatal"))) {
+ return getFatal();
+ }
+ } else {
+ if (len == 3) {
+ if (StringHelper::equalsIgnoreCase(sArg, LOG4CXX_STR("OFF"), LOG4CXX_STR("off"))) {
+ return getOff();
+ }
+ if (StringHelper::equalsIgnoreCase(sArg, LOG4CXX_STR("ALL"), LOG4CXX_STR("all"))) {
+ return getAll();
+ }
+ }
+ }
+ }
+
+ return defaultLevel;
+}
+
+
+bool Level::equals(const LevelPtr& level1) const
+{
+ return (this->level == level1->level);
+}
+
+bool Level::isGreaterOrEqual(const LevelPtr& level1) const
+{
+ return this->level >= level1->level;
+}
+
diff --git a/src/main/cpp/levelmatchfilter.cpp b/src/main/cpp/levelmatchfilter.cpp
new file mode 100644
index 0000000..1f7d74e
--- /dev/null
+++ b/src/main/cpp/levelmatchfilter.cpp
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/filter/levelmatchfilter.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/level.h>
+
+using namespace log4cxx;
+using namespace log4cxx::filter;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(LevelMatchFilter)
+
+
+LevelMatchFilter::LevelMatchFilter()
+: acceptOnMatch(true)
+{
+}
+
+void LevelMatchFilter::setOption(const LogString& option,
+ const LogString& value)
+{
+
+
+ if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("LEVELTOMATCH"), LOG4CXX_STR("leveltomatch")))
+ {
+ setLevelToMatch(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("ACCEPTONMATCH"), LOG4CXX_STR("acceptonmatch")))
+ {
+ acceptOnMatch = OptionConverter::toBoolean(value, acceptOnMatch);
+ }
+}
+
+void LevelMatchFilter::setLevelToMatch(const LogString& levelToMatch1)
+{
+ this->levelToMatch = OptionConverter::toLevel(levelToMatch1, this->levelToMatch);
+}
+
+LogString LevelMatchFilter::getLevelToMatch() const
+{
+ return levelToMatch->toString();
+}
+
+Filter::FilterDecision LevelMatchFilter::decide(
+ const log4cxx::spi::LoggingEventPtr& event) const
+{
+ if(levelToMatch != 0 && levelToMatch->equals(event->getLevel()))
+ {
+ if(acceptOnMatch)
+ {
+ return Filter::ACCEPT;
+ }
+ else
+ {
+ return Filter::DENY;
+ }
+ }
+ else
+ {
+ return Filter::NEUTRAL;
+ }
+}
+
diff --git a/src/main/cpp/levelpatternconverter.cpp b/src/main/cpp/levelpatternconverter.cpp
new file mode 100644
index 0000000..7ae2bdc
--- /dev/null
+++ b/src/main/cpp/levelpatternconverter.cpp
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/levelpatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+#include <log4cxx/level.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(LevelPatternConverter)
+
+LevelPatternConverter::LevelPatternConverter() :
+ LoggingEventPatternConverter(LOG4CXX_STR("Level"),
+ LOG4CXX_STR("level")) {
+}
+
+PatternConverterPtr LevelPatternConverter::newInstance(
+ const std::vector<LogString>& /* options */) {
+ static PatternConverterPtr def(new LevelPatternConverter());
+ return def;
+}
+
+void LevelPatternConverter::format(
+ const LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& /* p */) const {
+ toAppendTo.append(event->getLevel()->toString());
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+LogString LevelPatternConverter::getStyleClass(const ObjectPtr& obj) const {
+ LoggingEventPtr e(obj);
+ if (e != NULL) {
+ int lint = e->getLevel()->toInt();
+
+ switch (lint) {
+ case Level::TRACE_INT:
+ return LOG4CXX_STR("level trace");
+
+ case Level::DEBUG_INT:
+ return LOG4CXX_STR("level debug");
+
+ case Level::INFO_INT:
+ return LOG4CXX_STR("level info");
+
+ case Level::WARN_INT:
+ return LOG4CXX_STR("level warn");
+
+ case Level::ERROR_INT:
+ return LOG4CXX_STR("level error");
+
+ case Level::FATAL_INT:
+ return LOG4CXX_STR("level fatal");
+
+ default:
+ return LogString(LOG4CXX_STR("level ")) + e->getLevel()->toString();
+ }
+ }
+
+ return LOG4CXX_STR("level");
+ }
diff --git a/src/main/cpp/levelrangefilter.cpp b/src/main/cpp/levelrangefilter.cpp
new file mode 100644
index 0000000..4bf2963
--- /dev/null
+++ b/src/main/cpp/levelrangefilter.cpp
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/filter/levelrangefilter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/level.h>
+
+using namespace log4cxx;
+using namespace log4cxx::filter;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(LevelRangeFilter)
+
+
+LevelRangeFilter::LevelRangeFilter()
+: acceptOnMatch(true), levelMin(Level::getAll()), levelMax(Level::getOff())
+{
+}
+
+void LevelRangeFilter::setOption(const LogString& option,
+ const LogString& value)
+{
+
+ if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("LEVELMIN"), LOG4CXX_STR("levelmin")))
+ {
+ levelMin = OptionConverter::toLevel(value, levelMin);
+ }
+ else if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("LEVELMAX"), LOG4CXX_STR("levelmax")))
+ {
+ levelMax = OptionConverter::toLevel(value, levelMax);
+ }
+ else if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("ACCEPTONMATCH"), LOG4CXX_STR("acceptonmatch")))
+ {
+ acceptOnMatch = OptionConverter::toBoolean(value, acceptOnMatch);
+ }
+}
+
+Filter::FilterDecision LevelRangeFilter::decide(
+ const spi::LoggingEventPtr& event) const
+{
+ if (levelMin != 0 && !event->getLevel()->isGreaterOrEqual(levelMin))
+ {
+ // level of event is less than minimum
+ return Filter::DENY;
+ }
+
+ if (levelMax != 0 && event->getLevel()->toInt() > levelMax->toInt())
+ {
+ // level of event is greater than maximum
+ // Alas, there is no Level.isGreater method. and using
+ // a combo of isGreaterOrEqual && !Equal seems worse than
+ // checking the int values of the level objects..
+ return Filter::DENY;
+ }
+
+ if (acceptOnMatch)
+ {
+ // this filter set up to bypass later filters and always return
+ // accept if level in range
+ return Filter::ACCEPT;
+ }
+ else
+ {
+ // event is ok for this filter; allow later filters to have a look..
+ return Filter::NEUTRAL;
+ }
+}
+
diff --git a/src/main/cpp/linelocationpatternconverter.cpp b/src/main/cpp/linelocationpatternconverter.cpp
new file mode 100644
index 0000000..4e3c739
--- /dev/null
+++ b/src/main/cpp/linelocationpatternconverter.cpp
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/linelocationpatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+#include <log4cxx/helpers/stringhelper.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(LineLocationPatternConverter)
+
+LineLocationPatternConverter::LineLocationPatternConverter() :
+ LoggingEventPatternConverter(LOG4CXX_STR("Line"),
+ LOG4CXX_STR("line")) {
+}
+
+PatternConverterPtr LineLocationPatternConverter::newInstance(
+ const std::vector<LogString>& /* options */) {
+ static PatternConverterPtr instance(new LineLocationPatternConverter());
+ return instance;
+}
+
+void LineLocationPatternConverter::format(
+ const LoggingEventPtr& event,
+ LogString& toAppendTo,
+ Pool& p) const {
+ StringHelper::toString(
+ event->getLocationInformation().getLineNumber(),
+ p, toAppendTo);
+}
diff --git a/src/main/cpp/lineseparatorpatternconverter.cpp b/src/main/cpp/lineseparatorpatternconverter.cpp
new file mode 100644
index 0000000..799e7ce
--- /dev/null
+++ b/src/main/cpp/lineseparatorpatternconverter.cpp
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/lineseparatorpatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(LineSeparatorPatternConverter)
+
+LineSeparatorPatternConverter::LineSeparatorPatternConverter() :
+ LoggingEventPatternConverter(LOG4CXX_STR("Line Sep"),
+ LOG4CXX_STR("lineSep")) {
+}
+
+PatternConverterPtr LineSeparatorPatternConverter::newInstance(
+ const std::vector<LogString>& /* options */) {
+ static PatternConverterPtr instance(new LineSeparatorPatternConverter());
+ return instance;
+}
+
+void LineSeparatorPatternConverter::format(
+ const LoggingEventPtr& /* event */,
+ LogString& toAppendTo,
+ Pool& /* p */) const {
+ toAppendTo.append(LOG4CXX_EOL);
+ }
+
+void LineSeparatorPatternConverter::format(
+ const ObjectPtr& /* event */,
+ LogString& toAppendTo,
+ Pool& /* p */) const {
+ toAppendTo.append(LOG4CXX_EOL);
+ }
diff --git a/src/main/cpp/literalpatternconverter.cpp b/src/main/cpp/literalpatternconverter.cpp
new file mode 100644
index 0000000..b010be4
--- /dev/null
+++ b/src/main/cpp/literalpatternconverter.cpp
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/literalpatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(LiteralPatternConverter)
+
+LiteralPatternConverter::LiteralPatternConverter(const LogString& literal1) :
+ LoggingEventPatternConverter(LOG4CXX_STR("Literal"),LOG4CXX_STR("literal")),
+ literal(literal1) {
+}
+
+PatternConverterPtr LiteralPatternConverter::newInstance(
+ const LogString& literal) {
+ if (literal.length() == 1 && literal[0] == 0x20 /* ' ' */) {
+ static PatternConverterPtr blank(new LiteralPatternConverter(literal));
+ return blank;
+ }
+ PatternConverterPtr pattern(new LiteralPatternConverter(literal));
+ return pattern;
+}
+
+void LiteralPatternConverter::format(
+ const LoggingEventPtr& /* event */,
+ LogString& toAppendTo,
+ Pool& /* p */) const {
+ toAppendTo.append(literal);
+ }
+
+void LiteralPatternConverter::format(
+ const ObjectPtr& /* event */,
+ LogString& toAppendTo,
+ Pool& /* p */) const {
+ toAppendTo.append(literal);
+ }
+
diff --git a/src/main/cpp/loader.cpp b/src/main/cpp/loader.cpp
new file mode 100644
index 0000000..8b13390
--- /dev/null
+++ b/src/main/cpp/loader.cpp
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/loader.h>
+#include <log4cxx/appender.h>
+#include <log4cxx/spi/filter.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/spi/loggerfactory.h>
+#include <log4cxx/spi/loggerrepository.h>
+#include <log4cxx/helpers/object.h>
+#include <log4cxx/spi/errorhandler.h>
+#include <log4cxx/filter/denyallfilter.h>
+#include <log4cxx/spi/repositoryselector.h>
+#include <log4cxx/spi/appenderattachable.h>
+#include <log4cxx/helpers/xml.h>
+#include <log4cxx/spi/triggeringeventevaluator.h>
+#include <fstream>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/fileinputstream.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+using namespace log4cxx::filter;
+
+IMPLEMENT_LOG4CXX_OBJECT(Object)
+IMPLEMENT_LOG4CXX_OBJECT(OptionHandler)
+IMPLEMENT_LOG4CXX_OBJECT(ErrorHandler)
+IMPLEMENT_LOG4CXX_OBJECT(Appender)
+IMPLEMENT_LOG4CXX_OBJECT(Filter)
+IMPLEMENT_LOG4CXX_OBJECT(AppenderAttachable)
+IMPLEMENT_LOG4CXX_OBJECT(LoggerFactory)
+IMPLEMENT_LOG4CXX_OBJECT(LoggerRepository)
+IMPLEMENT_LOG4CXX_OBJECT(DenyAllFilter)
+IMPLEMENT_LOG4CXX_OBJECT(RepositorySelector)
+IMPLEMENT_LOG4CXX_OBJECT(XMLDOMNode)
+IMPLEMENT_LOG4CXX_OBJECT(XMLDOMDocument)
+IMPLEMENT_LOG4CXX_OBJECT(XMLDOMElement)
+IMPLEMENT_LOG4CXX_OBJECT(XMLDOMNodeList)
+IMPLEMENT_LOG4CXX_OBJECT(TriggeringEventEvaluator)
+
+const Class& Loader::loadClass(const LogString& clazz)
+{
+ return Class::forName(clazz);
+}
+
+
+InputStreamPtr Loader::getResourceAsStream(const LogString& name) {
+
+ try {
+ return new FileInputStream(name);
+ } catch(const IOException& ioex) {
+ }
+
+ return 0;
+}
diff --git a/src/main/cpp/locale.cpp b/src/main/cpp/locale.cpp
new file mode 100644
index 0000000..d4db617
--- /dev/null
+++ b/src/main/cpp/locale.cpp
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/locale.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+Locale::Locale(const LogString& language1)
+ : language(language1)
+{
+}
+
+Locale::Locale(const LogString& language1, const LogString& country1)
+ : language(language1), country(country1)
+{
+}
+
+Locale::Locale(const LogString& language1, const LogString& country1,
+ const LogString& variant1)
+: language(language1), country(country1), variant(variant1)
+{
+}
+
+
+const LogString& Locale::getLanguage() const
+{
+ return language;
+}
+
+const LogString& Locale::getCountry() const
+{
+ return country;
+}
+
+const LogString& Locale::getVariant() const
+{
+ return variant;
+}
+
diff --git a/src/main/cpp/locationinfo.cpp b/src/main/cpp/locationinfo.cpp
new file mode 100644
index 0000000..e76ea29
--- /dev/null
+++ b/src/main/cpp/locationinfo.cpp
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/spi/location/locationinfo.h>
+#include <log4cxx/helpers/objectoutputstream.h>
+#include <log4cxx/helpers/pool.h>
+#include "apr_pools.h"
+#include "apr_strings.h"
+
+using namespace ::log4cxx::spi;
+using namespace log4cxx::helpers;
+
+ /**
+ When location information is not available the constant
+ <code>NA</code> is returned. Current value of this string
+ constant is <b>?</b>. */
+ const char* const LocationInfo::NA = "?";
+ const char* const LocationInfo::NA_METHOD = "?::?";
+
+ const LocationInfo& LocationInfo::getLocationUnavailable() {
+ static const LocationInfo unavailable;
+ return unavailable;
+ }
+
+/**
+* Constructor.
+* @remarks Used by LOG4CXX_LOCATION to generate
+* location info for current code site
+*/
+ LocationInfo::LocationInfo( const char * const fileName1,
+ const char * const methodName1,
+ int lineNumber1 )
+ : lineNumber( lineNumber1 ),
+ fileName( fileName1 ),
+ methodName( methodName1 ) {
+}
+
+/**
+* Default constructor.
+*/
+ LocationInfo::LocationInfo()
+ : lineNumber( -1 ),
+ fileName(LocationInfo::NA),
+ methodName(LocationInfo::NA_METHOD) {
+}
+
+/**
+* Copy constructor.
+* @param src source location
+*/
+ LocationInfo::LocationInfo( const LocationInfo & src )
+ : lineNumber( src.lineNumber ),
+ fileName( src.fileName ),
+ methodName( src.methodName ) {
+}
+
+/**
+* Assignment operator.
+* @param src source location
+*/
+ LocationInfo & LocationInfo::operator = ( const LocationInfo & src )
+{
+ fileName = src.fileName;
+ methodName = src.methodName;
+ lineNumber = src.lineNumber;
+ return * this;
+}
+
+/**
+ * Resets location info to default state.
+ */
+ void LocationInfo::clear() {
+ fileName = NA;
+ methodName = NA_METHOD;
+ lineNumber = -1;
+}
+
+
+/**
+ * Return the file name of the caller.
+ * @returns file name, may be null.
+ */
+ const char * LocationInfo::getFileName() const
+{
+ return fileName;
+}
+
+/**
+ * Returns the line number of the caller.
+ * @returns line number, -1 if not available.
+ */
+ int LocationInfo::getLineNumber() const
+{
+ return lineNumber;
+}
+
+/** Returns the method name of the caller. */
+ const std::string LocationInfo::getMethodName() const
+{
+ std::string tmp(methodName);
+ size_t colonPos = tmp.find("::");
+ if (colonPos != std::string::npos) {
+ tmp.erase(0, colonPos + 2);
+ } else {
+ size_t spacePos = tmp.find(' ');
+ if (spacePos != std::string::npos) {
+ tmp.erase(0, spacePos + 1);
+ }
+ }
+ size_t parenPos = tmp.find('(');
+ if (parenPos != std::string::npos) {
+ tmp.erase(parenPos);
+ }
+ return tmp;
+}
+
+
+const std::string LocationInfo::getClassName() const {
+ std::string tmp(methodName);
+ size_t colonPos = tmp.find("::");
+ if (colonPos != std::string::npos) {
+ tmp.erase(colonPos);
+ size_t spacePos = tmp.find_last_of(' ');
+ if (spacePos != std::string::npos) {
+ tmp.erase(0, spacePos + 1);
+ }
+ return tmp;
+ }
+ tmp.erase(0, tmp.length() );
+ return tmp;
+}
+
+void LocationInfo::write(ObjectOutputStream& os, Pool& p) const {
+ if (lineNumber == -1 && fileName == NA && methodName == NA_METHOD) {
+ os.writeNull(p);
+ } else {
+ char prolog[] = {
+ 0x72, 0x00, 0x21, 0x6F, 0x72, 0x67, 0x2E,
+ 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2E, 0x6C,
+ 0x6F, 0x67, 0x34, 0x6A, 0x2E, 0x73, 0x70, 0x69,
+ 0x2E, 0x4C, 0x6F, 0x63, 0x61, 0x74, 0x69, 0x6F,
+ 0x6E, 0x49, 0x6E, 0x66, 0x6F, 0xED, 0x99, 0xBB,
+ 0xE1, 0x4A, 0x91, 0xA5, 0x7C, 0x02, 0x00, 0x01,
+ 0x4C, 0x00, 0x08, 0x66, 0x75, 0x6C, 0x6C, 0x49,
+ 0x6E, 0x66, 0x6F,
+ 0x74, 0x00, 0x12, 0x4C, 0x6A,
+ 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67,
+ 0x2F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B,
+ 0x78, 0x70 };
+ os.writeProlog("org.apache.log4j.spi.LocationInfo", 2, prolog, sizeof(prolog), p);
+ char* line = p.itoa(lineNumber);
+ //
+ // construct Java-like fullInfo (replace "::" with ".")
+ //
+ std::string fullInfo(methodName);
+ size_t openParen = fullInfo.find('(');
+ if (openParen != std::string::npos) {
+ size_t space = fullInfo.find(' ');
+ if (space != std::string::npos && space < openParen) {
+ fullInfo.erase(0, space + 1);
+ }
+ }
+ openParen = fullInfo.find('(');
+ if (openParen != std::string::npos) {
+ size_t classSep = fullInfo.rfind("::", openParen);
+ if (classSep != std::string::npos) {
+ fullInfo.replace(classSep, 2, ".");
+ } else {
+ fullInfo.insert(0, ".");
+ }
+ }
+ fullInfo.append(1, '(');
+ fullInfo.append(fileName);
+ fullInfo.append(1, ':');
+ fullInfo.append(line);
+ fullInfo.append(1, ')');
+ os.writeUTFString(fullInfo, p);
+ }
+}
+
+
diff --git a/src/main/cpp/logger.cpp b/src/main/cpp/logger.cpp
new file mode 100644
index 0000000..2fcb044
--- /dev/null
+++ b/src/main/cpp/logger.cpp
@@ -0,0 +1,975 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/spi/loggerfactory.h>
+#include <log4cxx/appender.h>
+#include <log4cxx/level.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/spi/loggerrepository.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/appenderattachableimpl.h>
+#include <log4cxx/helpers/exception.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+#include <log4cxx/helpers/aprinitializer.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+IMPLEMENT_LOG4CXX_OBJECT(Logger)
+
+Logger::Logger(Pool& p, const LogString& name1)
+: pool(&p), name(), level(), parent(), resourceBundle(),
+repository(), aai(), mutex(p)
+{
+ synchronized sync(mutex);
+ name = name1;
+ additive = true;
+}
+
+Logger::~Logger()
+{
+}
+
+void Logger::addRef() const {
+ ObjectImpl::addRef();
+}
+
+void Logger::releaseRef() const {
+ ObjectImpl::releaseRef();
+}
+
+void Logger::addAppender(const AppenderPtr& newAppender)
+{
+ synchronized sync(mutex);
+
+ if (aai == 0)
+ {
+ aai = new AppenderAttachableImpl(*pool);
+ }
+ aai->addAppender(newAppender);
+ if (repository != 0) {
+ repository->fireAddAppenderEvent(this, newAppender);
+ }
+}
+
+
+void Logger::callAppenders(const spi::LoggingEventPtr& event, Pool& p) const
+{
+ int writes = 0;
+
+ for(LoggerPtr logger(const_cast<Logger*>(this));
+ logger != 0;
+ logger = logger->parent)
+ {
+ // Protected against simultaneous call to addAppender, removeAppender,...
+ synchronized sync(logger->mutex);
+
+ if (logger->aai != 0)
+ {
+ writes += logger->aai->appendLoopOnAppenders(event, p);
+ }
+
+ if(!logger->additive)
+ {
+ break;
+ }
+ }
+
+ if(writes == 0 && repository != 0)
+ {
+ repository->emitNoAppenderWarning(const_cast<Logger*>(this));
+ }
+}
+
+void Logger::closeNestedAppenders()
+{
+ AppenderList appenders = getAllAppenders();
+ for(AppenderList::iterator it=appenders.begin(); it!=appenders.end(); ++it)
+ {
+ (*it)->close();
+ }
+}
+
+
+void Logger::forcedLog(const LevelPtr& level1, const std::string& message,
+ const LocationInfo& location) const
+{
+ Pool p;
+ LOG4CXX_DECODE_CHAR(msg, message);
+ LoggingEventPtr event(new LoggingEvent(name, level1, msg, location));
+ callAppenders(event, p);
+}
+
+
+void Logger::forcedLog(const LevelPtr& level1, const std::string& message) const
+{
+ Pool p;
+ LOG4CXX_DECODE_CHAR(msg, message);
+ LoggingEventPtr event(new LoggingEvent(name, level1, msg,
+ LocationInfo::getLocationUnavailable()));
+ callAppenders(event, p);
+}
+
+void Logger::forcedLogLS(const LevelPtr& level1, const LogString& message,
+ const LocationInfo& location) const
+{
+ Pool p;
+ LoggingEventPtr event(new LoggingEvent(name, level1, message, location));
+ callAppenders(event, p);
+}
+
+
+bool Logger::getAdditivity() const
+{
+ return additive;
+}
+
+AppenderList Logger::getAllAppenders() const
+{
+ synchronized sync(mutex);
+
+ if (aai == 0)
+ {
+ return AppenderList();
+ }
+ else
+ {
+ return aai->getAllAppenders();
+ }
+}
+
+AppenderPtr Logger::getAppender(const LogString& name1) const
+{
+ synchronized sync(mutex);
+
+ if (aai == 0 || name1.empty())
+ {
+ return 0;
+ }
+
+ return aai->getAppender(name1);
+}
+
+const LevelPtr& Logger::getEffectiveLevel() const
+{
+ for(const Logger * l = this; l != 0; l=l->parent)
+ {
+ if(l->level != 0)
+ {
+ return l->level;
+ }
+ }
+
+ throw NullPointerException(LOG4CXX_STR("No level specified for logger or ancestors."));
+#if LOG4CXX_RETURN_AFTER_THROW
+ return this->level;
+#endif
+}
+
+LoggerRepositoryPtr Logger::getLoggerRepository() const
+{
+ return repository;
+}
+
+ResourceBundlePtr Logger::getResourceBundle() const
+{
+ for (LoggerPtr l(const_cast<Logger*>(this)); l != 0; l = l->parent)
+ {
+ if (l->resourceBundle != 0)
+ {
+ return l->resourceBundle;
+ }
+ }
+
+ // It might be the case that there is no resource bundle
+ return 0;
+}
+
+
+LogString Logger::getResourceBundleString(const LogString& key) const
+{
+ ResourceBundlePtr rb = getResourceBundle();
+
+ // This is one of the rare cases where we can use logging in order
+ // to report errors from within log4j.
+ if (rb == 0)
+ {
+ return LogString();
+ }
+ else
+ {
+ try
+ {
+ return rb->getString(key);
+ }
+ catch (MissingResourceException&)
+ {
+ logLS(Level::getError(), LOG4CXX_STR("No resource is associated with key \"") +
+ key + LOG4CXX_STR("\"."), LocationInfo::getLocationUnavailable());
+
+ return LogString();
+ }
+ }
+}
+
+
+LoggerPtr Logger::getParent() const
+{
+ return parent;
+}
+
+LevelPtr Logger::getLevel() const
+{
+ return level;
+}
+
+
+bool Logger::isAttached(const AppenderPtr& appender) const
+{
+ synchronized sync(mutex);
+
+ if (appender == 0 || aai == 0)
+ {
+ return false;
+ }
+ else
+ {
+ return aai->isAttached(appender);
+ }
+}
+
+bool Logger::isTraceEnabled() const
+{
+ if(repository == 0 || repository->isDisabled(Level::TRACE_INT))
+ {
+ return false;
+ }
+
+ return getEffectiveLevel()->toInt() <= Level::TRACE_INT;
+}
+
+bool Logger::isDebugEnabled() const
+{
+ if(repository == 0 || repository->isDisabled(Level::DEBUG_INT))
+ {
+ return false;
+ }
+
+ return getEffectiveLevel()->toInt() <= Level::DEBUG_INT;
+}
+
+bool Logger::isEnabledFor(const LevelPtr& level1) const
+{
+ if(repository == 0 || repository->isDisabled(level1->toInt()))
+ {
+ return false;
+ }
+
+ return level1->isGreaterOrEqual(getEffectiveLevel());
+}
+
+
+bool Logger::isInfoEnabled() const
+{
+ if(repository == 0 || repository->isDisabled(Level::INFO_INT))
+ {
+ return false;
+ }
+
+ return getEffectiveLevel()->toInt() <= Level::INFO_INT;
+}
+
+bool Logger::isErrorEnabled() const
+{
+ if(repository == 0 || repository->isDisabled(Level::ERROR_INT))
+ {
+ return false;
+ }
+
+ return getEffectiveLevel()->toInt() <= Level::ERROR_INT;
+}
+
+bool Logger::isWarnEnabled() const
+{
+ if(repository == 0 || repository->isDisabled(Level::WARN_INT))
+ {
+ return false;
+ }
+
+ return getEffectiveLevel()->toInt() <= Level::WARN_INT;
+}
+
+bool Logger::isFatalEnabled() const
+{
+ if(repository == 0 || repository->isDisabled(Level::FATAL_INT))
+ {
+ return false;
+ }
+
+ return getEffectiveLevel()->toInt() <= Level::FATAL_INT;
+}
+
+/*void Logger::l7dlog(const LevelPtr& level, const String& key,
+ const char* file, int line)
+{
+ if (repository == 0 || repository->isDisabled(level->level))
+ {
+ return;
+ }
+
+ if (level->isGreaterOrEqual(getEffectiveLevel()))
+ {
+ String msg = getResourceBundleString(key);
+
+ // if message corresponding to 'key' could not be found in the
+ // resource bundle, then default to 'key'.
+ if (msg.empty())
+ {
+ msg = key;
+ }
+
+ forcedLog(FQCN, level, msg, file, line);
+ }
+}*/
+
+
+
+void Logger::l7dlog(const LevelPtr& level1, const LogString& key,
+ const LocationInfo& location, const std::vector<LogString>& params) const
+{
+ if (repository == 0 || repository->isDisabled(level1->toInt()))
+ {
+ return;
+ }
+
+ if (level1->isGreaterOrEqual(getEffectiveLevel()))
+ {
+ LogString pattern = getResourceBundleString(key);
+ LogString msg;
+
+ if (pattern.empty())
+ {
+ msg = key;
+ }
+ else
+ {
+ msg = StringHelper::format(pattern, params);
+ }
+
+ forcedLogLS(level1, msg, location);
+ }
+}
+
+void Logger::l7dlog(const LevelPtr& level1, const std::string& key,
+ const LocationInfo& location) const {
+ LOG4CXX_DECODE_CHAR(lkey, key);
+
+ std::vector<LogString> values(0);
+ l7dlog(level1, lkey, location, values);
+}
+
+void Logger::l7dlog(const LevelPtr& level1, const std::string& key,
+ const LocationInfo& location, const std::string& val1) const {
+ LOG4CXX_DECODE_CHAR(lkey, key);
+ LOG4CXX_DECODE_CHAR(lval1, val1);
+
+ std::vector<LogString> values(1);
+ values[0] = lval1;
+ l7dlog(level1, lkey, location, values);
+}
+
+void Logger::l7dlog(const LevelPtr& level1, const std::string& key,
+ const LocationInfo& location,
+ const std::string& val1, const std::string& val2) const {
+ LOG4CXX_DECODE_CHAR(lkey, key);
+ LOG4CXX_DECODE_CHAR(lval1, val1);
+ LOG4CXX_DECODE_CHAR(lval2, val2);
+
+ std::vector<LogString> values(2);
+ values[0] = lval1;
+ values[1] = lval2;
+ l7dlog(level1, lkey, location, values);
+}
+
+void Logger::l7dlog(const LevelPtr& level1, const std::string& key,
+ const LocationInfo& location,
+ const std::string& val1, const std::string& val2, const std::string& val3) const {
+ LOG4CXX_DECODE_CHAR(lkey, key);
+ LOG4CXX_DECODE_CHAR(lval1, val1);
+ LOG4CXX_DECODE_CHAR(lval2, val2);
+ LOG4CXX_DECODE_CHAR(lval3, val3);
+
+ std::vector<LogString> values(3);
+ values[0] = lval1;
+ values[1] = lval2;
+ values[3] = lval3;
+ l7dlog(level1, lkey, location, values);
+}
+
+
+
+void Logger::removeAllAppenders()
+{
+ synchronized sync(mutex);
+
+ if(aai != 0)
+ {
+ aai->removeAllAppenders();
+ aai = 0;
+ }
+}
+
+void Logger::removeAppender(const AppenderPtr& appender)
+{
+ synchronized sync(mutex);
+
+ if(appender == 0 || aai == 0)
+ {
+ return;
+ }
+
+ aai->removeAppender(appender);
+}
+
+void Logger::removeAppender(const LogString& name1)
+{
+ synchronized sync(mutex);
+
+ if(name1.empty() || aai == 0)
+ {
+ return;
+ }
+
+ aai->removeAppender(name1);
+}
+
+void Logger::setAdditivity(bool additive1)
+{
+ synchronized sync(mutex);
+ this->additive = additive1;
+}
+
+void Logger::setHierarchy(spi::LoggerRepository * repository1)
+{
+ this->repository = repository1;
+}
+
+void Logger::setLevel(const LevelPtr& level1)
+{
+ this->level = level1;
+}
+
+
+
+LoggerPtr Logger::getLogger(const std::string& name)
+{
+ return LogManager::getLogger(name);
+}
+
+
+LoggerPtr Logger::getLogger(const char* const name)
+{
+ return LogManager::getLogger(name);
+}
+
+
+
+LoggerPtr Logger::getRootLogger() {
+ return LogManager::getRootLogger();
+}
+
+LoggerPtr Logger::getLoggerLS(const LogString& name,
+ const spi::LoggerFactoryPtr& factory)
+{
+ return LogManager::getLoggerLS(name, factory);
+}
+
+void Logger::getName(std::string& rv) const {
+ Transcoder::encode(name, rv);
+}
+
+
+void Logger::trace(const std::string& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isTraceEnabled()) {
+ forcedLog(log4cxx::Level::getTrace(), msg, location);
+ }
+}
+
+
+void Logger::trace(const std::string& msg) const {
+ if (isTraceEnabled()) {
+ forcedLog(log4cxx::Level::getTrace(), msg);
+ }
+}
+
+void Logger::debug(const std::string& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isDebugEnabled()) {
+ forcedLog(log4cxx::Level::getDebug(), msg, location);
+ }
+}
+
+void Logger::debug(const std::string& msg) const {
+ if (isDebugEnabled()) {
+ forcedLog(log4cxx::Level::getDebug(), msg);
+ }
+}
+
+
+void Logger::error(const std::string& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isErrorEnabled()) {
+ forcedLog(log4cxx::Level::getError(), msg, location);
+ }
+}
+
+
+void Logger::error(const std::string& msg) const {
+ if (isErrorEnabled()) {
+ forcedLog(log4cxx::Level::getError(), msg);
+ }
+}
+
+void Logger::fatal(const std::string& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isFatalEnabled()) {
+ forcedLog(log4cxx::Level::getFatal(), msg, location);
+ }
+}
+
+void Logger::fatal(const std::string& msg) const {
+ if (isFatalEnabled()) {
+ forcedLog(log4cxx::Level::getFatal(), msg);
+ }
+}
+
+void Logger::info(const std::string& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isInfoEnabled()) {
+ forcedLog(log4cxx::Level::getInfo(), msg, location);
+ }
+}
+
+void Logger::info(const std::string& msg) const {
+ if (isInfoEnabled()) {
+ forcedLog(log4cxx::Level::getInfo(), msg);
+ }
+}
+
+void Logger::log(const LevelPtr& level1, const std::string& message,
+ const log4cxx::spi::LocationInfo& location) const {
+ if (isEnabledFor(level1)) {
+ forcedLog(level1, message, location);
+ }
+}
+
+void Logger::log(const LevelPtr& level1, const std::string& message) const {
+ if (isEnabledFor(level1)) {
+ forcedLog(level1, message);
+ }
+}
+
+void Logger::logLS(const LevelPtr& level1, const LogString& message,
+ const log4cxx::spi::LocationInfo& location) const {
+ if (isEnabledFor(level1)) {
+ forcedLogLS(level1, message, location);
+ }
+}
+
+void Logger::warn(const std::string& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isWarnEnabled()) {
+ forcedLog(log4cxx::Level::getWarn(), msg, location);
+ }
+}
+
+void Logger::warn(const std::string& msg) const {
+ if (isWarnEnabled()) {
+ forcedLog(log4cxx::Level::getWarn(), msg);
+ }
+}
+
+LoggerPtr Logger::getLoggerLS(const LogString& name) {
+ return LogManager::getLoggerLS(name);
+}
+
+
+
+
+#if LOG4CXX_WCHAR_T_API
+void Logger::forcedLog(const LevelPtr& level1, const std::wstring& message,
+ const LocationInfo& location) const
+{
+ Pool p;
+ LOG4CXX_DECODE_WCHAR(msg, message);
+ LoggingEventPtr event(new LoggingEvent(name, level1, msg, location));
+ callAppenders(event, p);
+}
+
+void Logger::forcedLog(const LevelPtr& level1, const std::wstring& message) const
+{
+ Pool p;
+ LOG4CXX_DECODE_WCHAR(msg, message);
+ LoggingEventPtr event(new LoggingEvent(name, level1, msg,
+ LocationInfo::getLocationUnavailable()));
+ callAppenders(event, p);
+}
+
+void Logger::getName(std::wstring& rv) const {
+ Transcoder::encode(name, rv);
+}
+
+LoggerPtr Logger::getLogger(const std::wstring& name)
+{
+ return LogManager::getLogger(name);
+}
+
+LoggerPtr Logger::getLogger(const wchar_t* const name)
+{
+ return LogManager::getLogger(name);
+}
+
+void Logger::trace(const std::wstring& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isTraceEnabled()) {
+ forcedLog(log4cxx::Level::getTrace(), msg, location);
+ }
+}
+
+
+void Logger::trace(const std::wstring& msg) const {
+ if (isTraceEnabled()) {
+ forcedLog(log4cxx::Level::getTrace(), msg);
+ }
+}
+
+void Logger::debug(const std::wstring& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isDebugEnabled()) {
+ forcedLog(log4cxx::Level::getDebug(), msg, location);
+ }
+}
+
+void Logger::debug(const std::wstring& msg) const {
+ if (isDebugEnabled()) {
+ forcedLog(log4cxx::Level::getDebug(), msg);
+ }
+}
+
+void Logger::error(const std::wstring& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isErrorEnabled()) {
+ forcedLog(log4cxx::Level::getError(), msg, location);
+ }
+}
+
+void Logger::error(const std::wstring& msg) const {
+ if (isErrorEnabled()) {
+ forcedLog(log4cxx::Level::getError(), msg);
+ }
+}
+
+void Logger::fatal(const std::wstring& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isFatalEnabled()) {
+ forcedLog(log4cxx::Level::getFatal(), msg, location);
+ }
+}
+
+void Logger::fatal(const std::wstring& msg) const {
+ if (isFatalEnabled()) {
+ forcedLog(log4cxx::Level::getFatal(), msg);
+ }
+}
+
+void Logger::info(const std::wstring& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isInfoEnabled()) {
+ forcedLog(log4cxx::Level::getInfo(), msg, location);
+ }
+}
+
+void Logger::info(const std::wstring& msg) const {
+ if (isInfoEnabled()) {
+ forcedLog(log4cxx::Level::getInfo(), msg);
+ }
+}
+
+void Logger::log(const LevelPtr& level1, const std::wstring& message,
+ const log4cxx::spi::LocationInfo& location) const {
+ if (isEnabledFor(level1)) {
+ forcedLog(level1, message, location);
+ }
+}
+
+void Logger::log(const LevelPtr& level1, const std::wstring& message) const {
+ if (isEnabledFor(level1)) {
+ forcedLog(level1, message);
+ }
+}
+
+void Logger::warn(const std::wstring& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isWarnEnabled()) {
+ forcedLog(log4cxx::Level::getWarn(), msg, location);
+ }
+}
+
+void Logger::warn(const std::wstring& msg) const {
+ if (isWarnEnabled()) {
+ forcedLog(log4cxx::Level::getWarn(), msg);
+ }
+}
+
+#endif
+
+
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+void Logger::forcedLog(const LevelPtr& level1, const std::basic_string<UniChar>& message,
+ const LocationInfo& location) const
+{
+ Pool p;
+ LOG4CXX_DECODE_UNICHAR(msg, message);
+ LoggingEventPtr event(new LoggingEvent(name, level1, msg, location));
+ callAppenders(event, p);
+}
+
+void Logger::forcedLog(const LevelPtr& level1, const std::basic_string<UniChar>& message) const
+{
+ Pool p;
+ LOG4CXX_DECODE_UNICHAR(msg, message);
+ LoggingEventPtr event(new LoggingEvent(name, level1, msg,
+ LocationInfo::getLocationUnavailable()));
+ callAppenders(event, p);
+}
+#endif
+
+#if LOG4CXX_UNICHAR_API
+void Logger::getName(std::basic_string<UniChar>& rv) const {
+ Transcoder::encode(name, rv);
+}
+
+LoggerPtr Logger::getLogger(const std::basic_string<UniChar>& name)
+{
+ return LogManager::getLogger(name);
+}
+
+void Logger::trace(const std::basic_string<UniChar>& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isTraceEnabled()) {
+ forcedLog(log4cxx::Level::getTrace(), msg, location);
+ }
+}
+
+
+void Logger::trace(const std::basic_string<UniChar>& msg) const {
+ if (isTraceEnabled()) {
+ forcedLog(log4cxx::Level::getTrace(), msg);
+ }
+}
+
+void Logger::debug(const std::basic_string<UniChar>& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isDebugEnabled()) {
+ forcedLog(log4cxx::Level::getDebug(), msg, location);
+ }
+}
+
+void Logger::debug(const std::basic_string<UniChar>& msg) const {
+ if (isDebugEnabled()) {
+ forcedLog(log4cxx::Level::getDebug(), msg);
+ }
+}
+
+void Logger::error(const std::basic_string<UniChar>& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isErrorEnabled()) {
+ forcedLog(log4cxx::Level::getError(), msg, location);
+ }
+}
+
+void Logger::error(const std::basic_string<UniChar>& msg) const {
+ if (isErrorEnabled()) {
+ forcedLog(log4cxx::Level::getError(), msg);
+ }
+}
+
+void Logger::fatal(const std::basic_string<UniChar>& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isFatalEnabled()) {
+ forcedLog(log4cxx::Level::getFatal(), msg, location);
+ }
+}
+
+void Logger::fatal(const std::basic_string<UniChar>& msg) const {
+ if (isFatalEnabled()) {
+ forcedLog(log4cxx::Level::getFatal(), msg);
+ }
+}
+
+void Logger::info(const std::basic_string<UniChar>& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isInfoEnabled()) {
+ forcedLog(log4cxx::Level::getInfo(), msg, location);
+ }
+}
+
+void Logger::info(const std::basic_string<UniChar>& msg) const {
+ if (isInfoEnabled()) {
+ forcedLog(log4cxx::Level::getInfo(), msg);
+ }
+}
+
+void Logger::log(const LevelPtr& level1, const std::basic_string<UniChar>& message,
+ const log4cxx::spi::LocationInfo& location) const {
+ if (isEnabledFor(level1)) {
+ forcedLog(level1, message, location);
+ }
+}
+
+void Logger::log(const LevelPtr& level1, const std::basic_string<UniChar>& message) const {
+ if (isEnabledFor(level1)) {
+ forcedLog(level1, message);
+ }
+}
+
+void Logger::warn(const std::basic_string<UniChar>& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isWarnEnabled()) {
+ forcedLog(log4cxx::Level::getWarn(), msg, location);
+ }
+}
+
+void Logger::warn(const std::basic_string<UniChar>& msg) const {
+ if (isWarnEnabled()) {
+ forcedLog(log4cxx::Level::getWarn(), msg);
+ }
+}
+
+#endif
+
+
+#if LOG4CXX_CFSTRING_API
+void Logger::forcedLog(const LevelPtr& level1, const CFStringRef& message,
+ const LocationInfo& location) const
+{
+ Pool p;
+ LOG4CXX_DECODE_CFSTRING(msg, message);
+ LoggingEventPtr event(new LoggingEvent(name, level1, msg, location));
+ callAppenders(event, p);
+}
+
+void Logger::forcedLog(const LevelPtr& level1, const CFStringRef& message) const
+{
+ Pool p;
+ LOG4CXX_DECODE_CFSTRING(msg, message);
+ LoggingEventPtr event(new LoggingEvent(name, level1, msg,
+ LocationInfo::getLocationUnavailable()));
+ callAppenders(event, p);
+}
+
+void Logger::getName(CFStringRef& rv) const {
+ rv = Transcoder::encode(name);
+}
+
+LoggerPtr Logger::getLogger(const CFStringRef& name)
+{
+ return LogManager::getLogger(name);
+}
+
+void Logger::trace(const CFStringRef& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isTraceEnabled()) {
+ forcedLog(log4cxx::Level::getTrace(), msg, location);
+ }
+}
+
+
+void Logger::trace(const CFStringRef& msg) const {
+ if (isTraceEnabled()) {
+ forcedLog(log4cxx::Level::getTrace(), msg);
+ }
+}
+
+void Logger::debug(const CFStringRef& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isDebugEnabled()) {
+ forcedLog(log4cxx::Level::getDebug(), msg, location);
+ }
+}
+
+void Logger::debug(const CFStringRef& msg) const {
+ if (isDebugEnabled()) {
+ forcedLog(log4cxx::Level::getDebug(), msg);
+ }
+}
+
+void Logger::error(const CFStringRef& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isErrorEnabled()) {
+ forcedLog(log4cxx::Level::getError(), msg, location);
+ }
+}
+
+void Logger::error(const CFStringRef& msg) const {
+ if (isErrorEnabled()) {
+ forcedLog(log4cxx::Level::getError(), msg);
+ }
+}
+
+void Logger::fatal(const CFStringRef& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isFatalEnabled()) {
+ forcedLog(log4cxx::Level::getFatal(), msg, location);
+ }
+}
+
+void Logger::fatal(const CFStringRef& msg) const {
+ if (isFatalEnabled()) {
+ forcedLog(log4cxx::Level::getFatal(), msg);
+ }
+}
+
+void Logger::info(const CFStringRef& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isInfoEnabled()) {
+ forcedLog(log4cxx::Level::getInfo(), msg, location);
+ }
+}
+
+void Logger::info(const CFStringRef& msg) const {
+ if (isInfoEnabled()) {
+ forcedLog(log4cxx::Level::getInfo(), msg);
+ }
+}
+
+void Logger::log(const LevelPtr& level1, const CFStringRef& message,
+ const log4cxx::spi::LocationInfo& location) const {
+ if (isEnabledFor(level1)) {
+ forcedLog(level1, message, location);
+ }
+}
+
+void Logger::log(const LevelPtr& level1, const CFStringRef& message) const {
+ if (isEnabledFor(level1)) {
+ forcedLog(level1, message);
+ }
+}
+
+void Logger::warn(const CFStringRef& msg, const log4cxx::spi::LocationInfo& location) const {
+ if (isWarnEnabled()) {
+ forcedLog(log4cxx::Level::getWarn(), msg, location);
+ }
+}
+
+void Logger::warn(const CFStringRef& msg) const {
+ if (isWarnEnabled()) {
+ forcedLog(log4cxx::Level::getWarn(), msg);
+ }
+}
+
+#endif
+
+
diff --git a/src/main/cpp/loggerpatternconverter.cpp b/src/main/cpp/loggerpatternconverter.cpp
new file mode 100644
index 0000000..2c5a677
--- /dev/null
+++ b/src/main/cpp/loggerpatternconverter.cpp
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/loggerpatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(LoggerPatternConverter)
+
+LoggerPatternConverter::LoggerPatternConverter(
+ const std::vector<LogString>& options) :
+ NamePatternConverter(LOG4CXX_STR("Logger"),
+ LOG4CXX_STR("logger"), options) {
+}
+
+PatternConverterPtr LoggerPatternConverter::newInstance(
+ const std::vector<LogString>& options) {
+ if (options.size() == 0) {
+ static PatternConverterPtr def(new LoggerPatternConverter(options));
+ return def;
+ }
+ return new LoggerPatternConverter(options);
+}
+
+void LoggerPatternConverter::format(
+ const LoggingEventPtr& event,
+ LogString& toAppendTo,
+ Pool& /* p */ ) const {
+ int initialLength = toAppendTo.length();
+ toAppendTo.append(event->getLoggerName());
+ abbreviate(initialLength, toAppendTo);
+ }
diff --git a/src/main/cpp/loggingevent.cpp b/src/main/cpp/loggingevent.cpp
new file mode 100644
index 0000000..1c0d4be
--- /dev/null
+++ b/src/main/cpp/loggingevent.cpp
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/spi/loggingevent.h>
+#include <log4cxx/ndc.h>
+
+#include <log4cxx/level.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/system.h>
+#include <log4cxx/helpers/socket.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/helpers/aprinitializer.h>
+#include <log4cxx/helpers/threadspecificdata.h>
+#include <log4cxx/helpers/transcoder.h>
+
+#include <apr_time.h>
+#include <apr_portable.h>
+#include <apr_strings.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/objectoutputstream.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/private/log4cxx_private.h>
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(LoggingEvent)
+
+
+//
+// Accessor for start time.
+//
+log4cxx_time_t LoggingEvent::getStartTime() {
+ return log4cxx::helpers::APRInitializer::initialize();
+}
+
+LoggingEvent::LoggingEvent() :
+ ndc(0),
+ mdcCopy(0),
+ properties(0),
+ ndcLookupRequired(true),
+ mdcCopyLookupRequired(true),
+ timeStamp(0),
+ locationInfo() {
+}
+
+LoggingEvent::LoggingEvent(
+ const LogString& logger1, const LevelPtr& level1,
+ const LogString& message1, const LocationInfo& locationInfo1) :
+ logger(logger1),
+ level(level1),
+ ndc(0),
+ mdcCopy(0),
+ properties(0),
+ ndcLookupRequired(true),
+ mdcCopyLookupRequired(true),
+ message(message1),
+ timeStamp(apr_time_now()),
+ locationInfo(locationInfo1),
+ threadName(getCurrentThreadName()) {
+}
+
+LoggingEvent::~LoggingEvent()
+{
+ delete ndc;
+ delete mdcCopy;
+ delete properties;
+}
+
+bool LoggingEvent::getNDC(LogString& dest) const
+{
+ if(ndcLookupRequired)
+ {
+ ndcLookupRequired = false;
+ LogString val;
+ if(NDC::get(val)) {
+ ndc = new LogString(val);
+ }
+ }
+ if (ndc) {
+ dest.append(*ndc);
+ return true;
+ }
+ return false;
+}
+
+bool LoggingEvent::getMDC(const LogString& key, LogString& dest) const
+{
+ // Note the mdcCopy is used if it exists. Otherwise we use the MDC
+ // that is associated with the thread.
+ if (mdcCopy != 0 && !mdcCopy->empty())
+ {
+ MDC::Map::const_iterator it = mdcCopy->find(key);
+
+ if (it != mdcCopy->end())
+ {
+ if (!it->second.empty())
+ {
+ dest.append(it->second);
+ return true;
+ }
+ }
+ }
+
+ return MDC::get(key, dest);
+
+}
+
+LoggingEvent::KeySet LoggingEvent::getMDCKeySet() const
+{
+ LoggingEvent::KeySet set;
+
+ if (mdcCopy != 0 && !mdcCopy->empty())
+ {
+ MDC::Map::const_iterator it;
+ for (it = mdcCopy->begin(); it != mdcCopy->end(); it++)
+ {
+ set.push_back(it->first);
+
+ }
+ }
+ else
+ {
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ MDC::Map& m = data->getMap();
+
+ for(MDC::Map::const_iterator it = m.begin(); it != m.end(); it++) {
+ set.push_back(it->first);
+ }
+ }
+ }
+
+ return set;
+}
+
+void LoggingEvent::getMDCCopy() const
+{
+ if(mdcCopyLookupRequired)
+ {
+ mdcCopyLookupRequired = false;
+ // the clone call is required for asynchronous logging.
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ mdcCopy = new MDC::Map(data->getMap());
+ } else {
+ mdcCopy = new MDC::Map();
+ }
+ }
+}
+
+bool LoggingEvent::getProperty(const LogString& key, LogString& dest) const
+{
+ if (properties == 0)
+ {
+ return false;
+ }
+
+ std::map<LogString, LogString>::const_iterator it = properties->find(key);
+
+ if (it != properties->end())
+ {
+ dest.append(it->second);
+ return true;
+ }
+
+ return false;
+}
+
+LoggingEvent::KeySet LoggingEvent::getPropertyKeySet() const
+{
+ LoggingEvent::KeySet set;
+
+ if (properties != 0)
+ {
+ std::map<LogString, LogString>::const_iterator it;
+ for (it = properties->begin(); it != properties->end(); it++)
+ {
+ set.push_back(it->first);
+ }
+ }
+
+ return set;
+}
+
+
+const LogString LoggingEvent::getCurrentThreadName() {
+#if APR_HAS_THREADS
+#if defined(_WIN32)
+ char result[20];
+ DWORD threadId = GetCurrentThreadId();
+ apr_snprintf(result, sizeof(result), LOG4CXX_WIN32_THREAD_FMTSPEC, threadId);
+#else
+ // apr_os_thread_t encoded in HEX takes needs as many characters
+ // as two times the size of the type, plus an additional null byte.
+ char result[sizeof(apr_os_thread_t) * 3 + 10];
+ apr_os_thread_t threadId = apr_os_thread_current();
+ apr_snprintf(result, sizeof(result), LOG4CXX_APR_THREAD_FMTSPEC, (void*) &threadId);
+#endif
+ LOG4CXX_DECODE_CHAR(str, (const char*) result);
+ return str;
+#else
+ return LOG4CXX_STR("0x00000000");
+#endif
+}
+
+
+void LoggingEvent::setProperty(const LogString& key, const LogString& value)
+{
+ if (properties == 0)
+ {
+ properties = new std::map<LogString, LogString>;
+ }
+
+ (*properties)[key] = value;
+}
+
+
+
+void LoggingEvent::writeProlog(ObjectOutputStream& os, Pool& p) {
+ char classDesc[] = {
+ 0x72, 0x00, 0x21,
+ 0x6F, 0x72, 0x67, 0x2E, 0x61, 0x70, 0x61, 0x63,
+ 0x68, 0x65, 0x2E, 0x6C, 0x6F, 0x67, 0x34, 0x6A,
+ 0x2E, 0x73, 0x70, 0x69, 0x2E, 0x4C, 0x6F, 0x67,
+ 0x67, 0x69, 0x6E, 0x67, 0x45, 0x76, 0x65, 0x6E,
+ 0x74, 0xF3, 0xF2, 0xB9, 0x23, 0x74, 0x0B, 0xB5,
+ 0x3F, 0x03, 0x00, 0x0A, 0x5A, 0x00, 0x15, 0x6D,
+ 0x64, 0x63, 0x43, 0x6F, 0x70, 0x79, 0x4C, 0x6F,
+ 0x6F, 0x6B, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75,
+ 0x69, 0x72, 0x65, 0x64, 0x5A, 0x00, 0x11, 0x6E,
+ 0x64, 0x63, 0x4C, 0x6F, 0x6F, 0x6B, 0x75, 0x70,
+ 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64,
+ 0x4A, 0x00, 0x09, 0x74, 0x69, 0x6D, 0x65, 0x53,
+ 0x74, 0x61, 0x6D, 0x70, 0x4C, 0x00, 0x0C, 0x63,
+ 0x61, 0x74, 0x65, 0x67, 0x6F, 0x72, 0x79, 0x4E,
+ 0x61, 0x6D, 0x65, 0x74, 0x00, 0x12, 0x4C, 0x6A,
+ 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67,
+ 0x2F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B,
+ 0x4C, 0x00, 0x0C, 0x6C, 0x6F, 0x63, 0x61, 0x74,
+ 0x69, 0x6F, 0x6E, 0x49, 0x6E, 0x66, 0x6F, 0x74,
+ 0x00, 0x23, 0x4C, 0x6F, 0x72, 0x67, 0x2F, 0x61,
+ 0x70, 0x61, 0x63, 0x68, 0x65, 0x2F, 0x6C, 0x6F,
+ 0x67, 0x34, 0x6A, 0x2F, 0x73, 0x70, 0x69, 0x2F,
+ 0x4C, 0x6F, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E,
+ 0x49, 0x6E, 0x66, 0x6F, 0x3B, 0x4C, 0x00, 0x07,
+ 0x6D, 0x64, 0x63, 0x43, 0x6F, 0x70, 0x79, 0x74,
+ 0x00, 0x15, 0x4C, 0x6A, 0x61, 0x76, 0x61, 0x2F,
+ 0x75, 0x74, 0x69, 0x6C, 0x2F, 0x48, 0x61, 0x73,
+ 0x68, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x3B, 0x4C,
+ 0x00, 0x03, 0x6E, 0x64, 0x63,
+ 0x74, 0x00, 0x12, 0x4C, 0x6A,
+ 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67,
+ 0x2F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B,
+ 0x4C, 0x00, 0x0F, 0x72, 0x65, 0x6E,
+ 0x64, 0x65, 0x72, 0x65, 0x64, 0x4D, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65,
+ 0x74, 0x00, 0x12, 0x4C, 0x6A,
+ 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67,
+ 0x2F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B,
+ 0x4C, 0x00, 0x0A, 0x74, 0x68, 0x72, 0x65,
+ 0x61, 0x64, 0x4E, 0x61, 0x6D, 0x65,
+ 0x74, 0x00, 0x12, 0x4C, 0x6A,
+ 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67,
+ 0x2F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B,
+ 0x4C, 0x00, 0x0D, 0x74, 0x68,
+ 0x72, 0x6F, 0x77, 0x61, 0x62, 0x6C, 0x65, 0x49,
+ 0x6E, 0x66, 0x6F, 0x74, 0x00, 0x2B, 0x4C, 0x6F,
+ 0x72, 0x67, 0x2F, 0x61, 0x70, 0x61, 0x63, 0x68,
+ 0x65, 0x2F, 0x6C, 0x6F, 0x67, 0x34, 0x6A, 0x2F,
+ 0x73, 0x70, 0x69, 0x2F, 0x54, 0x68, 0x72, 0x6F,
+ 0x77, 0x61, 0x62, 0x6C, 0x65, 0x49, 0x6E, 0x66,
+ 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x69, 0x6F, 0x6E,
+ 0x3B, 0x78, 0x70 };
+
+ os.writeProlog("org.apache.log4j.spi.LoggingEvent",
+ 8, classDesc, sizeof(classDesc), p);
+}
+
+void LoggingEvent::write(helpers::ObjectOutputStream& os, Pool& p) const {
+ writeProlog(os, p);
+ // mdc and ndc lookup required should always be false
+ char lookupsRequired[] = { 0, 0 };
+ os.writeBytes(lookupsRequired, sizeof(lookupsRequired), p);
+ os.writeLong(timeStamp/1000, p);
+ os.writeObject(logger, p);
+ locationInfo.write(os, p);
+ if (mdcCopy == 0 || mdcCopy->size() == 0) {
+ os.writeNull(p);
+ } else {
+ os.writeObject(*mdcCopy, p);
+ }
+ if (ndc == 0) {
+ os.writeNull(p);
+ } else {
+ os.writeObject(*ndc, p);
+ }
+ os.writeObject(message, p);
+ os.writeObject(threadName, p);
+ // throwable
+ os.writeNull(p);
+ os.writeByte(ObjectOutputStream::TC_BLOCKDATA, p);
+ os.writeByte(0x04, p);
+ os.writeInt(level->toInt(), p);
+ os.writeNull(p);
+ os.writeByte(ObjectOutputStream::TC_ENDBLOCKDATA, p);
+}
+
diff --git a/src/main/cpp/loggingeventpatternconverter.cpp b/src/main/cpp/loggingeventpatternconverter.cpp
new file mode 100644
index 0000000..ce59965
--- /dev/null
+++ b/src/main/cpp/loggingeventpatternconverter.cpp
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(LoggingEventPatternConverter)
+
+
+
+LoggingEventPatternConverter::LoggingEventPatternConverter(
+ const LogString& name1, const LogString& style1) : PatternConverter(name1, style1) {
+ }
+
+void LoggingEventPatternConverter::format(const ObjectPtr& obj,
+ LogString& output,
+ log4cxx::helpers::Pool& p) const {
+ LoggingEventPtr le(obj);
+ if (le != NULL) {
+ format(le, output, p);
+ }
+}
+
+bool LoggingEventPatternConverter::handlesThrowable() const {
+ return false;
+}
diff --git a/src/main/cpp/loglog.cpp b/src/main/cpp/loglog.cpp
new file mode 100644
index 0000000..d3498f2
--- /dev/null
+++ b/src/main/cpp/loglog.cpp
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <iostream>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/helpers/aprinitializer.h>
+#include <log4cxx/helpers/systemerrwriter.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+LogLog::LogLog() : mutex(APRInitializer::getRootPool()) {
+ synchronized sync(mutex);
+ debugEnabled = false;
+ quietMode = false;
+}
+
+LogLog& LogLog::getInstance() {
+ static LogLog internalLogger;
+ return internalLogger;
+}
+
+
+void LogLog::setInternalDebugging(bool debugEnabled1)
+{
+ synchronized sync(getInstance().mutex);
+ getInstance().debugEnabled = debugEnabled1;
+}
+
+void LogLog::debug(const LogString& msg)
+{
+ synchronized sync(getInstance().mutex);
+ if(getInstance().debugEnabled && !getInstance().quietMode)
+ {
+ emit(msg);
+ }
+}
+
+void LogLog::debug(const LogString& msg, const std::exception& e)
+{
+ synchronized sync(getInstance().mutex);
+ debug(msg);
+ emit(e);
+}
+
+
+void LogLog::error(const LogString& msg)
+{
+ synchronized sync(getInstance().mutex);
+ if(!getInstance().quietMode) {
+ emit(msg);
+ }
+}
+
+void LogLog::error(const LogString& msg, const std::exception& e)
+{
+ synchronized sync(getInstance().mutex);
+ error(msg);
+ emit(e);
+}
+
+void LogLog::setQuietMode(bool quietMode1)
+{
+ synchronized sync(getInstance().mutex);
+ getInstance().quietMode = quietMode1;
+}
+
+void LogLog::warn(const LogString& msg)
+{
+ synchronized sync(getInstance().mutex);
+ if(!getInstance().quietMode) {
+ emit(msg);
+ }
+}
+
+void LogLog::warn(const LogString& msg, const std::exception& e)
+{
+ synchronized sync(getInstance().mutex);
+ warn(msg);
+ emit(e);
+}
+
+void LogLog::emit(const LogString& msg) {
+ LogString out(LOG4CXX_STR("log4cxx: "));
+ out.append(msg);
+ out.append(1, (logchar) 0x0A);
+ SystemErrWriter::write(out);
+}
+
+void LogLog::emit(const std::exception& ex) {
+ LogString out(LOG4CXX_STR("log4cxx: "));
+ const char* raw = ex.what();
+ if (raw != 0) {
+ Transcoder::decode(raw, out);
+ } else {
+ out.append(LOG4CXX_STR("std::exception::what() == null"));
+ }
+ out.append(1, (logchar) 0x0A);
+ SystemErrWriter::write(out);
+}
diff --git a/src/main/cpp/logmanager.cpp b/src/main/cpp/logmanager.cpp
new file mode 100644
index 0000000..1af3f43
--- /dev/null
+++ b/src/main/cpp/logmanager.cpp
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logmanager.h>
+#include <log4cxx/spi/defaultrepositoryselector.h>
+#include <log4cxx/hierarchy.h>
+#include <log4cxx/spi/rootlogger.h>
+#include <log4cxx/spi/loggerfactory.h>
+#include <stdexcept>
+#include <log4cxx/level.h>
+#include <log4cxx/spi/loggerrepository.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/helpers/loglog.h>
+
+#include <apr_general.h>
+
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/file.h>
+#include <log4cxx/helpers/transcoder.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/helpers/aprinitializer.h>
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(DefaultRepositorySelector)
+
+void * LogManager::guard = 0;
+
+
+
+RepositorySelectorPtr& LogManager::getRepositorySelector() {
+ //
+ // call to initialize APR and trigger "start" of logging clock
+ //
+ APRInitializer::initialize();
+ static spi::RepositorySelectorPtr selector;
+ return selector;
+}
+
+void LogManager::setRepositorySelector(spi::RepositorySelectorPtr selector,
+ void * guard1)
+{
+ if((LogManager::guard != 0) && (LogManager::guard != guard1))
+ {
+ throw IllegalArgumentException(LOG4CXX_STR("Attempted to reset the LoggerFactory without possessing the guard."));
+ }
+
+ if(selector == 0)
+ {
+ throw IllegalArgumentException(LOG4CXX_STR("RepositorySelector must be non-null."));
+ }
+
+ LogManager::guard = guard1;
+ LogManager::getRepositorySelector() = selector;
+}
+
+
+
+LoggerRepositoryPtr& LogManager::getLoggerRepository()
+{
+ if (getRepositorySelector() == 0)
+ {
+ LoggerRepositoryPtr hierarchy(new Hierarchy());
+ RepositorySelectorPtr selector(new DefaultRepositorySelector(hierarchy));
+ getRepositorySelector() = selector;
+ }
+
+ return getRepositorySelector()->getLoggerRepository();
+}
+
+LoggerPtr LogManager::getRootLogger()
+{
+ // Delegate the actual manufacturing of the logger to the logger repository.
+ return getLoggerRepository()->getRootLogger();
+}
+
+/**
+Retrieve the appropriate Logger instance.
+*/
+LoggerPtr LogManager::getLoggerLS(const LogString& name)
+{
+ return getLoggerRepository()->getLogger(name);
+}
+
+/**
+Retrieve the appropriate Logger instance.
+*/
+LoggerPtr LogManager::getLoggerLS(const LogString& name,
+ const spi::LoggerFactoryPtr& factory)
+{
+ // Delegate the actual manufacturing of the logger to the logger repository.
+ return getLoggerRepository()->getLogger(name, factory);
+}
+
+LoggerPtr LogManager::getLogger(const std::string& name) {
+ LOG4CXX_DECODE_CHAR(n, name);
+ return getLoggerLS(n);
+}
+
+LoggerPtr LogManager::getLogger(const std::string& name,
+ const spi::LoggerFactoryPtr& factory) {
+ LOG4CXX_DECODE_CHAR(n, name);
+ return getLoggerLS(n, factory);
+}
+
+LoggerPtr LogManager::exists(const std::string& name)
+{
+ LOG4CXX_DECODE_CHAR(n, name);
+ return existsLS(n);
+}
+
+#if LOG4CXX_WCHAR_T_API
+LoggerPtr LogManager::getLogger(const std::wstring& name) {
+ LOG4CXX_DECODE_WCHAR(n, name);
+ return getLoggerLS(n);
+}
+
+LoggerPtr LogManager::getLogger(const std::wstring& name,
+ const spi::LoggerFactoryPtr& factory) {
+ LOG4CXX_DECODE_WCHAR(n, name);
+ return getLoggerLS(n, factory);
+}
+
+LoggerPtr LogManager::exists(const std::wstring& name)
+{
+ LOG4CXX_DECODE_WCHAR(n, name);
+ return existsLS(n);
+}
+#endif
+
+#if LOG4CXX_UNICHAR_API
+LoggerPtr LogManager::getLogger(const std::basic_string<UniChar>& name) {
+ LOG4CXX_DECODE_UNICHAR(n, name);
+ return getLoggerLS(n);
+}
+
+LoggerPtr LogManager::getLogger(const std::basic_string<UniChar>& name,
+ const spi::LoggerFactoryPtr& factory) {
+ LOG4CXX_DECODE_UNICHAR(n, name);
+ return getLoggerLS(n, factory);
+}
+
+LoggerPtr LogManager::exists(const std::basic_string<UniChar>& name)
+{
+ LOG4CXX_DECODE_UNICHAR(n, name);
+ return existsLS(n);
+}
+#endif
+
+#if LOG4CXX_CFSTRING_API
+LoggerPtr LogManager::getLogger(const CFStringRef& name) {
+ LOG4CXX_DECODE_CFSTRING(n, name);
+ return getLoggerLS(n);
+}
+
+LoggerPtr LogManager::getLogger(const CFStringRef& name,
+ const spi::LoggerFactoryPtr& factory) {
+ LOG4CXX_DECODE_CFSTRING(n, name);
+ return getLoggerLS(n, factory);
+}
+
+LoggerPtr LogManager::exists(const CFStringRef& name)
+{
+ LOG4CXX_DECODE_CFSTRING(n, name);
+ return existsLS(n);
+}
+#endif
+
+LoggerPtr LogManager::existsLS(const LogString& name)
+{
+ return getLoggerRepository()->exists(name);
+}
+
+LoggerList LogManager::getCurrentLoggers()
+{
+ return getLoggerRepository()->getCurrentLoggers();
+}
+
+void LogManager::shutdown()
+{
+ getLoggerRepository()->shutdown();
+}
+
+void LogManager::resetConfiguration()
+{
+ getLoggerRepository()->resetConfiguration();
+}
diff --git a/src/main/cpp/logstream.cpp b/src/main/cpp/logstream.cpp
new file mode 100644
index 0000000..ebf4a38
--- /dev/null
+++ b/src/main/cpp/logstream.cpp
@@ -0,0 +1,504 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/stream.h>
+#include <log4cxx/helpers/transcoder.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+
+using namespace log4cxx;
+
+logstream_base::logstream_ios_base::logstream_ios_base(std::ios_base::fmtflags initval,
+ int initsize) {
+#if LOG4CXX_MEMSET_IOS_BASE
+ //
+ // the destructor for std::ios_base in the MSVC STL
+ // releases a pointer that was not initialized in the constructor.
+ //
+ memset(this, 0, sizeof(*this));
+#endif
+ flags(initval);
+ precision(initsize);
+ width(initsize);
+
+}
+
+
+logstream_base::logstream_base(const LoggerPtr& log,
+ const LevelPtr& lvl) : initset((std::ios_base::fmtflags) -1, 1),
+ initclear((std::ios_base::fmtflags) 0, 0), fillchar(0), fillset(false), logger(log), level(lvl), location() {
+ enabled = logger->isEnabledFor(level);
+}
+
+logstream_base::~logstream_base() {
+}
+
+void logstream_base::insert(std::ios_base& (*manip)(std::ios_base&)) {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ (*manip)(initset);
+ (*manip)(initclear);
+ refresh_stream_state();
+}
+
+bool logstream_base::set_stream_state(std::ios_base& dest, int& dstchar) {
+ std::ios_base::fmtflags setval = initset.flags();
+ std::ios_base::fmtflags clrval = initclear.flags();
+ std::ios_base::fmtflags mask = setval ^ (~clrval);
+ dest.setf(clrval, mask);
+ if (initset.precision() == initclear.precision()) {
+ dest.precision(initset.precision());
+ }
+ if (initset.width() == initclear.width()) {
+ dest.width(initset.width());
+ }
+ dstchar = fillchar;
+ return fillset;
+}
+
+logstream_base& logstream_base::endmsg(logstream_base& stream) {
+ stream.end_message();
+ return stream;
+}
+
+logstream_base& logstream_base::nop(logstream_base& stream) {
+ return stream;
+}
+
+void logstream_base::end_message() {
+ if (isEnabled()) {
+ log(logger, level, location);
+ }
+ erase();
+}
+
+
+
+int log4cxx::logstream_base::precision(int p) {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ initset.precision(p);
+ int oldVal = initclear.precision(p);
+ refresh_stream_state();
+ return oldVal;
+}
+
+int log4cxx::logstream_base::precision() {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ return initclear.precision();
+}
+
+int log4cxx::logstream_base::width(int w) {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ initset.width(w);
+ int oldVal = initclear.width(w);
+ refresh_stream_state();
+ return oldVal;
+}
+
+int log4cxx::logstream_base::width() {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ return initclear.width();
+}
+
+int log4cxx::logstream_base::fill(int newfill) {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ int oldfill = fillchar;
+ fillchar = newfill;
+ fillset = true;
+ refresh_stream_state();
+ return oldfill;
+}
+
+int logstream_base::fill() {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ return fillchar;
+}
+
+std::ios_base::fmtflags logstream_base::flags(std::ios_base::fmtflags newflags) {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ initset.flags(newflags);
+ std::ios_base::fmtflags oldVal = initclear.flags(newflags);
+ refresh_stream_state();
+ return oldVal;
+}
+
+std::ios_base::fmtflags logstream_base::setf(std::ios_base::fmtflags newflags, std::ios_base::fmtflags mask) {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ initset.setf(newflags, mask);
+ std::ios_base::fmtflags oldVal = initclear.setf(newflags, mask);
+ refresh_stream_state();
+ return oldVal;
+}
+
+std::ios_base::fmtflags logstream_base::setf(std::ios_base::fmtflags newflags) {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ initset.setf(newflags);
+ std::ios_base::fmtflags oldVal = initclear.setf(newflags);
+ refresh_stream_state();
+ return oldVal;
+}
+
+
+
+void logstream_base::setLevel(const ::log4cxx::LevelPtr& newlevel) {
+ level = newlevel;
+ bool oldLevel = enabled;
+ enabled = logger->isEnabledFor(level);
+ if (oldLevel != enabled) {
+ erase();
+ }
+}
+
+bool logstream_base::isEnabledFor(const ::log4cxx::LevelPtr& level) const {
+ return logger->isEnabledFor(level);
+}
+
+
+void logstream_base::setLocation(const log4cxx::spi::LocationInfo& newlocation) {
+ if (LOG4CXX_UNLIKELY(enabled)) {
+ location = newlocation;
+ }
+}
+
+
+logstream::logstream(const log4cxx::LoggerPtr& logger,
+ const log4cxx::LevelPtr& level) : logstream_base(logger, level), stream(0) {
+}
+
+logstream::logstream(const Ch* loggerName,
+ const log4cxx::LevelPtr& level)
+ : logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0) {
+}
+
+
+logstream::logstream(const std::basic_string<Ch>& loggerName,
+ const log4cxx::LevelPtr& level) : logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0) {
+}
+
+logstream::~logstream() {
+ delete stream;
+}
+
+logstream& logstream::operator<<(logstream_base& (*manip)(logstream_base&)) {
+ (*manip)(*this);
+ return *this;
+}
+
+logstream& logstream::operator<<(const LevelPtr& level) {
+ setLevel(level);
+ return *this;
+}
+
+logstream& logstream::operator<<(const log4cxx::spi::LocationInfo& newlocation) {
+ setLocation(newlocation);
+ return *this;
+}
+
+logstream& logstream::operator>>(const log4cxx::spi::LocationInfo& newlocation) {
+ setLocation(newlocation);
+ return *this;
+}
+
+logstream& logstream::operator<<(std::ios_base& (*manip)(std::ios_base&)) {
+ logstream_base::insert(manip);
+ return *this;
+}
+
+logstream::operator std::basic_ostream<char>&() {
+ if (stream == 0) {
+ stream = new std::basic_stringstream<Ch>();
+ refresh_stream_state();
+ }
+ return *stream;
+}
+
+void logstream::log(LoggerPtr& logger,
+ const LevelPtr& level,
+ const log4cxx::spi::LocationInfo& location) {
+ if (stream != 0) {
+ std::basic_string<Ch> msg = stream->str();
+ if (!msg.empty()) {
+ logger->log(level, msg, location);
+ }
+ }
+}
+
+
+void logstream::erase() {
+ if (stream != 0) {
+ std::basic_string<Ch> emptyStr;
+ stream->str(emptyStr);
+ }
+}
+
+
+void logstream::get_stream_state(std::ios_base& base,
+ std::ios_base& mask,
+ int& fill,
+ bool& fillSet) const {
+ if (stream != 0) {
+ std::ios_base::fmtflags flags = stream->flags();
+ base.flags(flags);
+ mask.flags(flags);
+ int width = stream->width();
+ base.width(width);
+ mask.width(width);
+ int precision = stream->precision();
+ base.precision(precision);
+ mask.precision(precision);
+ fill = stream->fill();
+ fillSet = true;
+ }
+}
+
+void logstream::refresh_stream_state() {
+ if (stream != 0) {
+ int fillchar;
+ if(logstream_base::set_stream_state(*stream, fillchar)) {
+ stream->fill(fillchar);
+ }
+ }
+}
+
+
+#if LOG4CXX_WCHAR_T_API
+
+wlogstream::wlogstream(const log4cxx::LoggerPtr& logger,
+ const log4cxx::LevelPtr& level) : logstream_base(logger, level), stream(0) {
+}
+
+wlogstream::wlogstream(const Ch* loggerName,
+ const log4cxx::LevelPtr& level)
+ : logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0) {
+}
+
+
+wlogstream::wlogstream(const std::basic_string<Ch>& loggerName,
+ const log4cxx::LevelPtr& level) : logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0) {
+}
+
+wlogstream::~wlogstream() {
+ delete stream;
+}
+
+wlogstream& wlogstream::operator<<(logstream_base& (*manip)(logstream_base&)) {
+ (*manip)(*this);
+ return *this;
+}
+
+wlogstream& wlogstream::operator<<(const LevelPtr& level) {
+ setLevel(level);
+ return *this;
+}
+
+wlogstream& wlogstream::operator<<(const log4cxx::spi::LocationInfo& newlocation) {
+ setLocation(newlocation);
+ return *this;
+}
+
+wlogstream& wlogstream::operator>>(const log4cxx::spi::LocationInfo& newlocation) {
+ setLocation(newlocation);
+ return *this;
+}
+
+
+
+
+wlogstream& wlogstream::operator<<(std::ios_base& (*manip)(std::ios_base&)) {
+ logstream_base::insert(manip);
+ return *this;
+}
+
+wlogstream::operator std::basic_ostream<wchar_t>&() {
+ if (stream == 0) {
+ stream = new std::basic_stringstream<Ch>();
+ refresh_stream_state();
+ }
+ return *stream;
+}
+
+void wlogstream::log(LoggerPtr& logger,
+ const LevelPtr& level,
+ const log4cxx::spi::LocationInfo& location) {
+ if (stream != 0) {
+ std::basic_string<Ch> msg = stream->str();
+ if (!msg.empty()) {
+ logger->log(level, msg, location);
+ }
+ }
+}
+
+
+void wlogstream::erase() {
+ if (stream != 0) {
+ std::basic_string<Ch> emptyStr;
+ stream->str(emptyStr);
+ }
+}
+
+
+void wlogstream::get_stream_state(std::ios_base& base,
+ std::ios_base& mask,
+ int& fill,
+ bool& fillSet) const {
+ if (stream != 0) {
+ std::ios_base::fmtflags flags = stream->flags();
+ base.flags(flags);
+ mask.flags(flags);
+ int width = stream->width();
+ base.width(width);
+ mask.width(width);
+ int precision = stream->precision();
+ base.precision(precision);
+ mask.precision(precision);
+ fill = stream->fill();
+ fillSet = true;
+ }
+}
+
+void wlogstream::refresh_stream_state() {
+ if (stream != 0) {
+ int fillchar;
+ if(logstream_base::set_stream_state(*stream, fillchar)) {
+ stream->fill(fillchar);
+ }
+ }
+}
+#endif
+
+#if LOG4CXX_UNICHAR_API
+ulogstream::ulogstream(const Ch* loggerName,
+ const log4cxx::LevelPtr& level)
+ : logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0) {
+}
+
+
+ulogstream::ulogstream(const std::basic_string<Ch>& loggerName,
+ const log4cxx::LevelPtr& level) : logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0) {
+}
+#endif
+
+#if LOG4CXX_CFSTRING_API
+ulogstream::ulogstream(const CFStringRef& loggerName,
+ const log4cxx::LevelPtr& level)
+ : logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0) {
+}
+
+#endif
+
+
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+
+ulogstream::ulogstream(const log4cxx::LoggerPtr& logger,
+ const log4cxx::LevelPtr& level) : logstream_base(logger, level), stream(0) {
+}
+
+
+
+ulogstream::~ulogstream() {
+ delete stream;
+}
+
+ulogstream& ulogstream::operator<<(logstream_base& (*manip)(logstream_base&)) {
+ (*manip)(*this);
+ return *this;
+}
+
+ulogstream& ulogstream::operator<<(const LevelPtr& level) {
+ setLevel(level);
+ return *this;
+}
+
+ulogstream& ulogstream::operator<<(const log4cxx::spi::LocationInfo& newlocation) {
+ setLocation(newlocation);
+ return *this;
+}
+
+ulogstream& ulogstream::operator>>(const log4cxx::spi::LocationInfo& newlocation) {
+ setLocation(newlocation);
+ return *this;
+}
+
+
+
+
+ulogstream& ulogstream::operator<<(std::ios_base& (*manip)(std::ios_base&)) {
+ logstream_base::insert(manip);
+ return *this;
+}
+
+ulogstream::operator std::basic_ostream<UniChar>&() {
+ if (stream == 0) {
+ stream = new std::basic_stringstream<Ch>();
+ refresh_stream_state();
+ }
+ return *stream;
+}
+
+void ulogstream::log(LoggerPtr& logger,
+ const LevelPtr& level,
+ const log4cxx::spi::LocationInfo& location) {
+ if (stream != 0) {
+ std::basic_string<Ch> msg = stream->str();
+ if (!msg.empty() && logger->isEnabledFor(level)) {
+ LOG4CXX_DECODE_UNICHAR(lsmsg, msg);
+ logger->forcedLogLS(level, lsmsg, location);
+ }
+ }
+}
+
+
+void ulogstream::erase() {
+ if (stream != 0) {
+ std::basic_string<Ch> emptyStr;
+ stream->str(emptyStr);
+ }
+}
+
+
+void ulogstream::get_stream_state(std::ios_base& base,
+ std::ios_base& mask,
+ int& fill,
+ bool& fillSet) const {
+ if (stream != 0) {
+ std::ios_base::fmtflags flags = stream->flags();
+ base.flags(flags);
+ mask.flags(flags);
+ int width = stream->width();
+ base.width(width);
+ mask.width(width);
+ int precision = stream->precision();
+ base.precision(precision);
+ mask.precision(precision);
+ fill = stream->fill();
+ fillSet = true;
+ }
+}
+
+void ulogstream::refresh_stream_state() {
+ if (stream != 0) {
+ int fillchar;
+ if(logstream_base::set_stream_state(*stream, fillchar)) {
+ stream->fill(fillchar);
+ }
+ }
+}
+#endif
+
+
diff --git a/src/main/cpp/manualtriggeringpolicy.cpp b/src/main/cpp/manualtriggeringpolicy.cpp
new file mode 100644
index 0000000..5d8958e
--- /dev/null
+++ b/src/main/cpp/manualtriggeringpolicy.cpp
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/rolling/manualtriggeringpolicy.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/optionconverter.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(ManualTriggeringPolicy)
+
+ManualTriggeringPolicy::ManualTriggeringPolicy() {
+}
+
+bool ManualTriggeringPolicy::isTriggeringEvent(Appender* /* appender */,
+ const log4cxx::spi::LoggingEventPtr& /* event */,
+ const LogString& /* file */,
+ size_t /* fileLength */ ) {
+ return false;
+}
+
+void ManualTriggeringPolicy::activateOptions(Pool& /* p */ ) {
+}
+
+void ManualTriggeringPolicy::setOption(const LogString& /* option */ , const LogString& /* value */ ) {
+}
diff --git a/src/main/cpp/mdc.cpp b/src/main/cpp/mdc.cpp
new file mode 100644
index 0000000..a91bef6
--- /dev/null
+++ b/src/main/cpp/mdc.cpp
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/mdc.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/threadspecificdata.h>
+
+#if LOG4CXX_CFSTRING_API
+#include <CoreFoundation/CFString.h>
+#endif
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+MDC::MDC(const std::string& key1, const std::string& value) : key()
+{
+ Transcoder::decode(key1, key);
+ LOG4CXX_DECODE_CHAR(v, value);
+ putLS(key, v);
+}
+
+MDC::~MDC()
+{
+ LogString prevVal;
+ remove(key, prevVal);
+}
+
+void MDC::putLS(const LogString& key, const LogString& value)
+{
+ ThreadSpecificData::put(key, value);
+}
+
+void MDC::put(const std::string& key, const std::string& value)
+{
+ LOG4CXX_DECODE_CHAR(lkey, key);
+ LOG4CXX_DECODE_CHAR(lvalue, value);
+ putLS(lkey, lvalue);
+}
+
+bool MDC::get(const LogString& key, LogString& value)
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Map& map = data->getMap();
+
+ Map::iterator it = map.find(key);
+ if (it != map.end()) {
+ value.append(it->second);
+ return true;
+ }
+ data->recycle();
+ }
+ return false;
+}
+
+std::string MDC::get(const std::string& key)
+{
+ LOG4CXX_DECODE_CHAR(lkey, key);
+ LogString lvalue;
+ if (get(lkey, lvalue)) {
+ LOG4CXX_ENCODE_CHAR(value, lvalue);
+ return value;
+ }
+ return std::string();
+}
+
+bool MDC::remove(const LogString& key, LogString& value)
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Map& map = data->getMap();
+ Map::iterator it;
+ if ((it = map.find(key)) != map.end()) {
+ value = it->second;
+ map.erase(it);
+ data->recycle();
+ return true;
+ }
+ }
+ return false;
+}
+
+std::string MDC::remove(const std::string& key)
+{
+ LOG4CXX_DECODE_CHAR(lkey, key);
+ LogString lvalue;
+ if (remove(lkey, lvalue)) {
+ LOG4CXX_ENCODE_CHAR(value, lvalue);
+ return value;
+ }
+ return std::string();
+}
+
+
+void MDC::clear()
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Map& map = data->getMap();
+ map.erase(map.begin(), map.end());
+ data->recycle();
+ }
+}
+
+
+#if LOG4CXX_WCHAR_T_API
+MDC::MDC(const std::wstring& key1, const std::wstring& value) : key()
+{
+ Transcoder::decode(key1, key);
+ LOG4CXX_DECODE_WCHAR(v, value);
+ putLS(key, v);
+}
+
+std::wstring MDC::get(const std::wstring& key)
+{
+ LOG4CXX_DECODE_WCHAR(lkey, key);
+ LogString lvalue;
+ if (get(lkey, lvalue)) {
+ LOG4CXX_ENCODE_WCHAR(value, lvalue);
+ return value;
+ }
+ return std::wstring();
+}
+
+void MDC::put(const std::wstring& key, const std::wstring& value)
+{
+ LOG4CXX_DECODE_WCHAR(lkey, key);
+ LOG4CXX_DECODE_WCHAR(lvalue, value);
+ putLS(lkey, lvalue);
+}
+
+
+std::wstring MDC::remove(const std::wstring& key)
+{
+ LOG4CXX_DECODE_WCHAR(lkey, key);
+ LogString lvalue;
+ if (remove(lkey, lvalue)) {
+ LOG4CXX_ENCODE_WCHAR(value, lvalue);
+ return value;
+ }
+ return std::wstring();
+}
+#endif
+
+#if LOG4CXX_UNICHAR_API
+MDC::MDC(const std::basic_string<UniChar>& key1, const std::basic_string<UniChar>& value) {
+ Transcoder::decode(key1, key);
+ LOG4CXX_DECODE_UNICHAR(v, value);
+ putLS(key, v);
+}
+
+std::basic_string<log4cxx::UniChar> MDC::get(const std::basic_string<log4cxx::UniChar>& key)
+{
+ LOG4CXX_DECODE_UNICHAR(lkey, key);
+ LogString lvalue;
+ if (get(lkey, lvalue)) {
+ LOG4CXX_ENCODE_UNICHAR(value, lvalue);
+ return value;
+ }
+ return std::basic_string<UniChar>();
+}
+
+void MDC::put(const std::basic_string<UniChar>& key, const std::basic_string<log4cxx::UniChar>& value)
+{
+ LOG4CXX_DECODE_UNICHAR(lkey, key);
+ LOG4CXX_DECODE_UNICHAR(lvalue, value);
+ putLS(lkey, lvalue);
+}
+
+
+std::basic_string<log4cxx::UniChar> MDC::remove(const std::basic_string<log4cxx::UniChar>& key)
+{
+ LOG4CXX_DECODE_UNICHAR(lkey, key);
+ LogString lvalue;
+ if (remove(lkey, lvalue)) {
+ LOG4CXX_ENCODE_UNICHAR(value, lvalue);
+ return value;
+ }
+ return std::basic_string<UniChar>();
+}
+#endif
+
+#if LOG4CXX_CFSTRING_API
+
+MDC::MDC(const CFStringRef& key1, const CFStringRef& value) {
+ Transcoder::decode(key1, key);
+ LOG4CXX_DECODE_CFSTRING(v, value);
+ putLS(key, v);
+}
+
+CFStringRef MDC::get(const CFStringRef& key)
+{
+ LOG4CXX_DECODE_CFSTRING(lkey, key);
+ LogString lvalue;
+ if (get(lkey, lvalue)) {
+ LOG4CXX_ENCODE_CFSTRING(value, lvalue);
+ return value;
+ }
+ return CFSTR("");
+}
+
+void MDC::put(const CFStringRef& key, const CFStringRef& value)
+{
+ LOG4CXX_DECODE_CFSTRING(lkey, key);
+ LOG4CXX_DECODE_CFSTRING(lvalue, value);
+ putLS(lkey, lvalue);
+}
+
+
+CFStringRef MDC::remove(const CFStringRef& key)
+{
+ LOG4CXX_DECODE_CFSTRING(lkey, key);
+ LogString lvalue;
+ if (remove(lkey, lvalue)) {
+ LOG4CXX_ENCODE_CFSTRING(value, lvalue);
+ return value;
+ }
+ return CFSTR("");
+}
+#endif
+
diff --git a/src/main/cpp/messagebuffer.cpp b/src/main/cpp/messagebuffer.cpp
new file mode 100644
index 0000000..42a6439
--- /dev/null
+++ b/src/main/cpp/messagebuffer.cpp
@@ -0,0 +1,430 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/messagebuffer.h>
+#include <log4cxx/helpers/transcoder.h>
+
+using namespace log4cxx::helpers;
+
+CharMessageBuffer::CharMessageBuffer() : stream(0) {}
+
+CharMessageBuffer::~CharMessageBuffer() {
+ delete stream;
+}
+
+CharMessageBuffer& CharMessageBuffer::operator<<(const std::basic_string<char>& msg) {
+ if (stream == 0) {
+ buf.append(msg);
+ } else {
+ *stream << msg;
+ }
+ return *this;
+}
+
+CharMessageBuffer& CharMessageBuffer::operator<<(const char* msg) {
+ const char* actualMsg = msg;
+ if (actualMsg == 0) {
+ actualMsg = "null";
+ }
+ if (stream == 0) {
+ buf.append(actualMsg);
+ } else {
+ *stream << actualMsg;
+ }
+ return *this;
+}
+CharMessageBuffer& CharMessageBuffer::operator<<(char* msg) {
+ return operator<<((const char*) msg);
+}
+
+CharMessageBuffer& CharMessageBuffer::operator<<(const char msg) {
+ if (stream == 0) {
+ buf.append(1, msg);
+ } else {
+ buf.assign(1, msg);
+ *stream << buf;
+ }
+ return *this;
+}
+
+CharMessageBuffer::operator std::basic_ostream<char>&() {
+ if (stream == 0) {
+ stream = new std::basic_ostringstream<char>();
+ if (!buf.empty()) {
+ *stream << buf;
+ }
+ }
+ return *stream;
+}
+
+const std::basic_string<char>& CharMessageBuffer::str(std::basic_ostream<char>&) {
+ buf = stream->str();
+ return buf;
+}
+
+const std::basic_string<char>& CharMessageBuffer::str(CharMessageBuffer&) {
+ return buf;
+}
+
+bool CharMessageBuffer::hasStream() const {
+ return (stream != 0);
+}
+
+std::ostream& CharMessageBuffer::operator<<(ios_base_manip manip) {
+ std::ostream& s = *this;
+ (*manip)(s);
+ return s;
+}
+
+std::ostream& CharMessageBuffer::operator<<(bool val) { return ((std::ostream&) *this).operator<<(val); }
+std::ostream& CharMessageBuffer::operator<<(short val) { return ((std::ostream&) *this).operator<<(val); }
+std::ostream& CharMessageBuffer::operator<<(int val) { return ((std::ostream&) *this).operator<<(val); }
+std::ostream& CharMessageBuffer::operator<<(unsigned int val) { return ((std::ostream&) *this).operator<<(val); }
+std::ostream& CharMessageBuffer::operator<<(long val) { return ((std::ostream&) *this).operator<<(val); }
+std::ostream& CharMessageBuffer::operator<<(unsigned long val) { return ((std::ostream&) *this).operator<<(val); }
+std::ostream& CharMessageBuffer::operator<<(float val) { return ((std::ostream&) *this).operator<<(val); }
+std::ostream& CharMessageBuffer::operator<<(double val) { return ((std::ostream&) *this).operator<<(val); }
+std::ostream& CharMessageBuffer::operator<<(long double val) { return ((std::ostream&) *this).operator<<(val); }
+std::ostream& CharMessageBuffer::operator<<(void* val) { return ((std::ostream&) *this).operator<<(val); }
+
+
+#if LOG4CXX_WCHAR_T_API
+WideMessageBuffer::WideMessageBuffer() : stream(0) {}
+
+WideMessageBuffer::~WideMessageBuffer() {
+ delete stream;
+}
+
+WideMessageBuffer& WideMessageBuffer::operator<<(const std::basic_string<wchar_t>& msg) {
+ if (stream == 0) {
+ buf.append(msg);
+ } else {
+ *stream << msg;
+ }
+ return *this;
+}
+
+WideMessageBuffer& WideMessageBuffer::operator<<(const wchar_t* msg) {
+ const wchar_t* actualMsg = msg;
+ if (actualMsg == 0) {
+ actualMsg = L"null";
+ }
+ if (stream == 0) {
+ buf.append(actualMsg);
+ } else {
+ *stream << actualMsg;
+ }
+ return *this;
+}
+
+WideMessageBuffer& WideMessageBuffer::operator<<(wchar_t* msg) {
+ return operator<<((const wchar_t*) msg);
+}
+
+WideMessageBuffer& WideMessageBuffer::operator<<(const wchar_t msg) {
+ if (stream == 0) {
+ buf.append(1, msg);
+ } else {
+ buf.assign(1, msg);
+ *stream << buf;
+ }
+ return *this;
+}
+
+WideMessageBuffer::operator std::basic_ostream<wchar_t>&() {
+ if (stream == 0) {
+ stream = new std::basic_ostringstream<wchar_t>();
+ if (!buf.empty()) {
+ *stream << buf;
+ }
+ }
+ return *stream;
+}
+
+const std::basic_string<wchar_t>& WideMessageBuffer::str(std::basic_ostream<wchar_t>&) {
+ buf = stream->str();
+ return buf;
+}
+
+const std::basic_string<wchar_t>& WideMessageBuffer::str(WideMessageBuffer&) {
+ return buf;
+}
+
+bool WideMessageBuffer::hasStream() const {
+ return (stream != 0);
+}
+
+std::basic_ostream<wchar_t>& WideMessageBuffer::operator<<(ios_base_manip manip) {
+ std::basic_ostream<wchar_t>& s = *this;
+ (*manip)(s);
+ return s;
+}
+
+std::basic_ostream<wchar_t>& WideMessageBuffer::operator<<(bool val) { return ((std::basic_ostream<wchar_t>&) *this).operator<<(val); }
+std::basic_ostream<wchar_t>& WideMessageBuffer::operator<<(short val) { return ((std::basic_ostream<wchar_t>&) *this).operator<<(val); }
+std::basic_ostream<wchar_t>& WideMessageBuffer::operator<<(int val) { return ((std::basic_ostream<wchar_t>&) *this).operator<<(val); }
+std::basic_ostream<wchar_t>& WideMessageBuffer::operator<<(unsigned int val) { return ((std::basic_ostream<wchar_t>&) *this).operator<<(val); }
+std::basic_ostream<wchar_t>& WideMessageBuffer::operator<<(long val) { return ((std::basic_ostream<wchar_t>&) *this).operator<<(val); }
+std::basic_ostream<wchar_t>& WideMessageBuffer::operator<<(unsigned long val) { return ((std::basic_ostream<wchar_t>&) *this).operator<<(val); }
+std::basic_ostream<wchar_t>& WideMessageBuffer::operator<<(float val) { return ((std::basic_ostream<wchar_t>&) *this).operator<<(val); }
+std::basic_ostream<wchar_t>& WideMessageBuffer::operator<<(double val) { return ((std::basic_ostream<wchar_t>&) *this).operator<<(val); }
+std::basic_ostream<wchar_t>& WideMessageBuffer::operator<<(long double val) { return ((std::basic_ostream<wchar_t>&) *this).operator<<(val); }
+std::basic_ostream<wchar_t>& WideMessageBuffer::operator<<(void* val) { return ((std::basic_ostream<wchar_t>&) *this).operator<<(val); }
+
+
+MessageBuffer::MessageBuffer() : wbuf(0)
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+ , ubuf(0)
+#endif
+{
+}
+
+MessageBuffer::~MessageBuffer() {
+ delete wbuf;
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+ delete ubuf;
+#endif
+}
+
+bool MessageBuffer::hasStream() const {
+ bool retval = cbuf.hasStream() || (wbuf != 0 && wbuf->hasStream());
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+ retval = retval || (ubuf != 0 && ubuf->hasStream());
+#endif
+ return retval;
+}
+
+std::ostream& MessageBuffer::operator<<(ios_base_manip manip) {
+ std::ostream& s = *this;
+ (*manip)(s);
+ return s;
+}
+
+MessageBuffer::operator std::ostream&() {
+ return (std::ostream&) cbuf;
+}
+
+CharMessageBuffer& MessageBuffer::operator<<(const std::string& msg) {
+ return cbuf.operator<<(msg);
+}
+
+CharMessageBuffer& MessageBuffer::operator<<(const char* msg) {
+ return cbuf.operator<<(msg);
+}
+CharMessageBuffer& MessageBuffer::operator<<(char* msg) {
+ return cbuf.operator<<((const char*) msg);
+}
+
+CharMessageBuffer& MessageBuffer::operator<<(const char msg) {
+ return cbuf.operator<<(msg);
+}
+
+const std::string& MessageBuffer::str(CharMessageBuffer& buf) {
+ return cbuf.str(buf);
+}
+
+const std::string& MessageBuffer::str(std::ostream& os) {
+ return cbuf.str(os);
+}
+
+WideMessageBuffer& MessageBuffer::operator<<(const std::wstring& msg) {
+ wbuf = new WideMessageBuffer();
+ return (*wbuf) << msg;
+}
+
+WideMessageBuffer& MessageBuffer::operator<<(const wchar_t* msg) {
+ wbuf = new WideMessageBuffer();
+ return (*wbuf) << msg;
+}
+WideMessageBuffer& MessageBuffer::operator<<(wchar_t* msg) {
+ wbuf = new WideMessageBuffer();
+ return (*wbuf) << (const wchar_t*) msg;
+}
+
+WideMessageBuffer& MessageBuffer::operator<<(const wchar_t msg) {
+ wbuf = new WideMessageBuffer();
+ return (*wbuf) << msg;
+}
+
+const std::wstring& MessageBuffer::str(WideMessageBuffer& buf) {
+ return wbuf->str(buf);
+}
+
+const std::wstring& MessageBuffer::str(std::basic_ostream<wchar_t>& os) {
+ return wbuf->str(os);
+}
+
+std::ostream& MessageBuffer::operator<<(bool val) { return cbuf.operator<<(val); }
+std::ostream& MessageBuffer::operator<<(short val) { return cbuf.operator<<(val); }
+std::ostream& MessageBuffer::operator<<(int val) { return cbuf.operator<<(val); }
+std::ostream& MessageBuffer::operator<<(unsigned int val) { return cbuf.operator<<(val); }
+std::ostream& MessageBuffer::operator<<(long val) { return cbuf.operator<<(val); }
+std::ostream& MessageBuffer::operator<<(unsigned long val) { return cbuf.operator<<(val); }
+std::ostream& MessageBuffer::operator<<(float val) { return cbuf.operator<<(val); }
+std::ostream& MessageBuffer::operator<<(double val) { return cbuf.operator<<(val); }
+std::ostream& MessageBuffer::operator<<(long double val) { return cbuf.operator<<(val); }
+std::ostream& MessageBuffer::operator<<(void* val) { return cbuf.operator<<(val); }
+
+
+#endif
+
+
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+UniCharMessageBuffer& MessageBuffer::operator<<(const std::basic_string<log4cxx::UniChar>& msg) {
+ ubuf = new UniCharMessageBuffer();
+ return (*ubuf) << msg;
+}
+
+UniCharMessageBuffer& MessageBuffer::operator<<(const log4cxx::UniChar* msg) {
+ ubuf = new UniCharMessageBuffer();
+ return (*ubuf) << msg;
+}
+UniCharMessageBuffer& MessageBuffer::operator<<(log4cxx::UniChar* msg) {
+ ubuf = new UniCharMessageBuffer();
+ return (*ubuf) << (const log4cxx::UniChar*) msg;
+}
+
+UniCharMessageBuffer& MessageBuffer::operator<<(const log4cxx::UniChar msg) {
+ ubuf = new UniCharMessageBuffer();
+ return (*ubuf) << msg;
+}
+
+const std::basic_string<log4cxx::UniChar>& MessageBuffer::str(UniCharMessageBuffer& buf) {
+ return ubuf->str(buf);
+}
+
+const std::basic_string<log4cxx::UniChar>& MessageBuffer::str(std::basic_ostream<log4cxx::UniChar>& os) {
+ return ubuf->str(os);
+}
+
+
+UniCharMessageBuffer::UniCharMessageBuffer() : stream(0) {}
+
+UniCharMessageBuffer::~UniCharMessageBuffer() {
+ delete stream;
+}
+
+
+UniCharMessageBuffer& UniCharMessageBuffer::operator<<(const std::basic_string<log4cxx::UniChar>& msg) {
+ if (stream == 0) {
+ buf.append(msg);
+ } else {
+ *stream << buf;
+ }
+ return *this;
+}
+
+UniCharMessageBuffer& UniCharMessageBuffer::operator<<(const log4cxx::UniChar* msg) {
+ const log4cxx::UniChar* actualMsg = msg;
+ static log4cxx::UniChar nullLiteral[] = { 0x6E, 0x75, 0x6C, 0x6C, 0};
+ if (actualMsg == 0) {
+ actualMsg = nullLiteral;
+ }
+ if (stream == 0) {
+ buf.append(actualMsg);
+ } else {
+ *stream << actualMsg;
+ }
+ return *this;
+}
+
+UniCharMessageBuffer& UniCharMessageBuffer::operator<<(log4cxx::UniChar* msg) {
+ return operator<<((const log4cxx::UniChar*) msg);
+}
+
+UniCharMessageBuffer& UniCharMessageBuffer::operator<<(const log4cxx::UniChar msg) {
+ if (stream == 0) {
+ buf.append(1, msg);
+ } else {
+ *stream << msg;
+ }
+ return *this;
+}
+
+UniCharMessageBuffer::operator UniCharMessageBuffer::uostream&() {
+ if (stream == 0) {
+ stream = new std::basic_ostringstream<UniChar>();
+ if (!buf.empty()) {
+ *stream << buf;
+ }
+ }
+ return *stream;
+}
+
+const std::basic_string<log4cxx::UniChar>& UniCharMessageBuffer::str(UniCharMessageBuffer::uostream&) {
+ buf = stream->str();
+ return buf;
+}
+
+const std::basic_string<log4cxx::UniChar>& UniCharMessageBuffer::str(UniCharMessageBuffer&) {
+ return buf;
+}
+
+bool UniCharMessageBuffer::hasStream() const {
+ return (stream != 0);
+}
+
+UniCharMessageBuffer::uostream& UniCharMessageBuffer::operator<<(ios_base_manip manip) {
+ UniCharMessageBuffer::uostream& s = *this;
+ (*manip)(s);
+ return s;
+}
+
+UniCharMessageBuffer::uostream& UniCharMessageBuffer::operator<<(bool val) { return ((UniCharMessageBuffer::uostream&) *this).operator<<(val); }
+UniCharMessageBuffer::uostream& UniCharMessageBuffer::operator<<(short val) { return ((UniCharMessageBuffer::uostream&) *this).operator<<(val); }
+UniCharMessageBuffer::uostream& UniCharMessageBuffer::operator<<(int val) { return ((UniCharMessageBuffer::uostream&) *this).operator<<(val); }
+UniCharMessageBuffer::uostream& UniCharMessageBuffer::operator<<(unsigned int val) { return ((UniCharMessageBuffer::uostream&) *this).operator<<(val); }
+UniCharMessageBuffer::uostream& UniCharMessageBuffer::operator<<(long val) { return ((UniCharMessageBuffer::uostream&) *this).operator<<(val); }
+UniCharMessageBuffer::uostream& UniCharMessageBuffer::operator<<(unsigned long val) { return ((UniCharMessageBuffer::uostream&) *this).operator<<(val); }
+UniCharMessageBuffer::uostream& UniCharMessageBuffer::operator<<(float val) { return ((UniCharMessageBuffer::uostream&) *this).operator<<(val); }
+UniCharMessageBuffer::uostream& UniCharMessageBuffer::operator<<(double val) { return ((UniCharMessageBuffer::uostream&) *this).operator<<(val); }
+UniCharMessageBuffer::uostream& UniCharMessageBuffer::operator<<(long double val) { return ((UniCharMessageBuffer::uostream&) *this).operator<<(val); }
+UniCharMessageBuffer::uostream& UniCharMessageBuffer::operator<<(void* val) { return ((UniCharMessageBuffer::uostream&) *this).operator<<(val); }
+
+
+
+#endif
+
+#if LOG4CXX_CFSTRING_API
+#include <CoreFoundation/CFString.h>
+#include <vector>
+
+UniCharMessageBuffer& UniCharMessageBuffer::operator<<(const CFStringRef& msg) {
+ const log4cxx::UniChar* chars = CFStringGetCharactersPtr(msg);
+ if (chars != 0) {
+ return operator<<(chars);
+ } else {
+ size_t length = CFStringGetLength(msg);
+ std::vector<log4cxx::UniChar> tmp(length);
+ CFStringGetCharacters(msg, CFRangeMake(0, length), &tmp[0]);
+ if (stream) {
+ std::basic_string<UniChar> s(&tmp[0], tmp.size());
+ *stream << s;
+ } else {
+ buf.append(&tmp[0], tmp.size());
+ }
+ }
+ return *this;
+}
+
+
+UniCharMessageBuffer& MessageBuffer::operator<<(const CFStringRef& msg) {
+ ubuf = new UniCharMessageBuffer();
+ return (*ubuf) << msg;
+}
+#endif
+
diff --git a/src/main/cpp/messagepatternconverter.cpp b/src/main/cpp/messagepatternconverter.cpp
new file mode 100644
index 0000000..7fe5bf0
--- /dev/null
+++ b/src/main/cpp/messagepatternconverter.cpp
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/messagepatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(MessagePatternConverter)
+
+MessagePatternConverter::MessagePatternConverter() :
+ LoggingEventPatternConverter(LOG4CXX_STR("Message"),
+ LOG4CXX_STR("message")) {
+}
+
+PatternConverterPtr MessagePatternConverter::newInstance(
+ const std::vector<LogString>& /* options */) {
+ static PatternConverterPtr def(new MessagePatternConverter());
+ return def;
+}
+
+void MessagePatternConverter::format(
+ const LoggingEventPtr& event,
+ LogString& toAppendTo,
+ Pool& /* p */) const {
+ toAppendTo.append(event->getRenderedMessage());
+ }
+
diff --git a/src/main/cpp/methodlocationpatternconverter.cpp b/src/main/cpp/methodlocationpatternconverter.cpp
new file mode 100644
index 0000000..e687112
--- /dev/null
+++ b/src/main/cpp/methodlocationpatternconverter.cpp
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/methodlocationpatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(MethodLocationPatternConverter)
+
+MethodLocationPatternConverter::MethodLocationPatternConverter() :
+ LoggingEventPatternConverter(LOG4CXX_STR("Method"),
+ LOG4CXX_STR("method")) {
+}
+
+PatternConverterPtr MethodLocationPatternConverter::newInstance(
+ const std::vector<LogString>& /* options */ ) {
+ static PatternConverterPtr def(new MethodLocationPatternConverter());
+ return def;
+}
+
+void MethodLocationPatternConverter::format(
+ const LoggingEventPtr& event,
+ LogString& toAppendTo,
+ Pool& /* p */ ) const {
+ append(toAppendTo, event->getLocationInformation().getMethodName());
+ }
diff --git a/src/main/cpp/mutex.cpp b/src/main/cpp/mutex.cpp
new file mode 100755
index 0000000..2fa836e
--- /dev/null
+++ b/src/main/cpp/mutex.cpp
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/mutex.h>
+#include <log4cxx/helpers/exception.h>
+#include <apr_thread_mutex.h>
+#include <assert.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/helpers/aprinitializer.h>
+
+using namespace log4cxx::helpers;
+using namespace log4cxx;
+
+
+Mutex::Mutex(Pool& p) {
+#if APR_HAS_THREADS
+ apr_status_t stat = apr_thread_mutex_create(&mutex,
+ APR_THREAD_MUTEX_NESTED, p.getAPRPool());
+ if (stat != APR_SUCCESS) {
+ throw MutexException(stat);
+ }
+#endif
+}
+
+Mutex::Mutex(apr_pool_t* p) {
+#if APR_HAS_THREADS
+ apr_status_t stat = apr_thread_mutex_create(&mutex,
+ APR_THREAD_MUTEX_NESTED, p);
+ if (stat != APR_SUCCESS) {
+ throw MutexException(stat);
+ }
+#endif
+}
+
+
+Mutex::~Mutex() {
+#if APR_HAS_THREADS
+ apr_thread_mutex_destroy(mutex);
+#endif
+}
+
+apr_thread_mutex_t* Mutex::getAPRMutex() const {
+ return mutex;
+}
diff --git a/src/main/cpp/nameabbreviator.cpp b/src/main/cpp/nameabbreviator.cpp
new file mode 100644
index 0000000..90fcc13
--- /dev/null
+++ b/src/main/cpp/nameabbreviator.cpp
@@ -0,0 +1,325 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/pattern/nameabbreviator.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <vector>
+#include <limits.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(NameAbbreviator)
+
+NameAbbreviator::NameAbbreviator() {
+}
+
+NameAbbreviator::~NameAbbreviator() {
+}
+
+namespace log4cxx {
+ namespace pattern {
+ /**
+ * Abbreviator that simply appends full name to buffer.
+ */
+class NOPAbbreviator : public NameAbbreviator {
+public:
+DECLARE_ABSTRACT_LOG4CXX_OBJECT(NOPAbbreviator)
+BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(NOPAbbreviator)
+ LOG4CXX_CAST_ENTRY_CHAIN(NameAbbreviator)
+END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Constructor.
+ */
+ NOPAbbreviator() {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ void abbreviate(LogString::size_type /* nameStart */, LogString& /* buf */) const {
+ }
+};
+
+
+ /**
+ * Abbreviator that drops starting path elements.
+ */
+ class MaxElementAbbreviator : public NameAbbreviator {
+ /**
+ * Maximum number of path elements to output.
+ */
+ const int count;
+
+public:
+DECLARE_ABSTRACT_LOG4CXX_OBJECT(MaxElementAbbreviator)
+BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(MaxElementAbbreviator)
+ LOG4CXX_CAST_ENTRY_CHAIN(NameAbbreviator)
+END_LOG4CXX_CAST_MAP()
+ /**
+ * Create new instance.
+ * @param count maximum number of path elements to output.
+ */
+ MaxElementAbbreviator(const int count1) : count(count1) {
+ }
+
+ /**
+ * Abbreviate name.
+ * @param buf buffer to append abbreviation.
+ * @param nameStart start of name to abbreviate.
+ */
+ void abbreviate(LogString::size_type nameStart, LogString& buf) const {
+ // 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.
+ LogString::size_type end = buf.length() - 1;
+
+ for (LogString::size_type i = count; i > 0; i--) {
+ end = buf.rfind(0x2E /* '.' */, end - 1);
+
+ if ((end == LogString::npos) || (end < nameStart)) {
+ return;
+ }
+ }
+
+ buf.erase(buf.begin() + nameStart, buf.begin() + (end + 1));
+ }
+ };
+
+ /**
+ * Fragment of an pattern abbreviator.
+ *
+ */
+ class PatternAbbreviatorFragment {
+ /**
+ * Count of initial characters of element to output.
+ */
+ LogString::size_type charCount;
+
+ /**
+ * Character used to represent dropped characters.
+ * '\0' indicates no representation of dropped characters.
+ */
+ logchar ellipsis;
+
+public:
+ /**
+ * Creates a PatternAbbreviatorFragment.
+ * @param charCount number of initial characters to preserve.
+ * @param ellipsis character to represent elimination of characters,
+ * '\0' if no ellipsis is desired.
+ */
+ PatternAbbreviatorFragment(
+ const int charCount1, const logchar ellipsis1)
+ : charCount(charCount1), ellipsis(ellipsis1) {
+ }
+ PatternAbbreviatorFragment() : charCount(0), ellipsis(0) {
+ }
+
+ PatternAbbreviatorFragment(const PatternAbbreviatorFragment& src)
+ : charCount(src.charCount), ellipsis(src.ellipsis) {
+ }
+
+ PatternAbbreviatorFragment& operator=(const PatternAbbreviatorFragment& src) {
+ charCount = src.charCount;
+ ellipsis = src.ellipsis;
+ return *this;
+ }
+
+ /**
+ * Abbreviate element of name.
+ * @param buf buffer to receive element.
+ * @param startPos starting index of name element.
+ * @return starting index of next element.
+ */
+ LogString::size_type abbreviate(LogString& buf, LogString::size_type startPos) const {
+ LogString::size_type nextDot = buf.find(0x2E /* '.' */, startPos);
+
+ if (nextDot != LogString::npos) {
+ if ((nextDot - startPos) > charCount) {
+ buf.erase(buf.begin() + (startPos + charCount), buf.begin() + nextDot);
+ nextDot = startPos + charCount;
+
+ if (ellipsis != 0x00) {
+ buf.insert(nextDot, 1, ellipsis);
+ nextDot++;
+ }
+ }
+
+ nextDot++;
+ }
+
+ return nextDot;
+ }
+ };
+
+ /**
+ * Pattern abbreviator.
+ *
+ *
+ */
+ class PatternAbbreviator : public NameAbbreviator {
+ /**
+ * Element abbreviation patterns.
+ */
+ std::vector<PatternAbbreviatorFragment> fragments;
+
+public:
+DECLARE_ABSTRACT_LOG4CXX_OBJECT(PatternAbbreviator)
+BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(PatternAbbreviator)
+ LOG4CXX_CAST_ENTRY_CHAIN(NameAbbreviator)
+END_LOG4CXX_CAST_MAP()
+ /**
+ * Create PatternAbbreviator.
+ *
+ * @param fragments element abbreviation patterns.
+ */
+ PatternAbbreviator(const std::vector<PatternAbbreviatorFragment>& fragments1) :
+ fragments(fragments1) {
+ if (fragments1.size() == 0) {
+ throw IllegalArgumentException(LOG4CXX_STR("fragments parameter must contain at least one element"));
+ }
+ }
+
+ /**
+ * Abbreviate name.
+ * @param buf buffer that abbreviated name is appended.
+ * @param nameStart start of name.
+ */
+ void abbreviate(LogString::size_type nameStart, LogString& buf) const {
+ //
+ // all non-terminal patterns are executed once
+ //
+ LogString::size_type pos = nameStart;
+
+ for (LogString::size_type i = 0; (i < (fragments.size() - 1)) && (pos < buf.length());
+ i++) {
+ pos = fragments[i].abbreviate(buf, pos);
+ }
+
+ //
+ // last pattern in executed repeatedly
+ //
+ PatternAbbreviatorFragment terminalFragment =
+ fragments[fragments.size() - 1];
+
+ while (pos < buf.length()) {
+ pos = terminalFragment.abbreviate(buf, pos);
+ }
+ }
+ };
+}
+}
+
+IMPLEMENT_LOG4CXX_OBJECT(NOPAbbreviator)
+IMPLEMENT_LOG4CXX_OBJECT(MaxElementAbbreviator)
+IMPLEMENT_LOG4CXX_OBJECT(PatternAbbreviator)
+
+
+
+NameAbbreviatorPtr NameAbbreviator::getAbbreviator(const LogString& pattern) {
+ if (pattern.length() > 0) {
+ // if pattern is just spaces and numbers then
+ // use MaxElementAbbreviator
+ LogString trimmed(StringHelper::trim(pattern));
+
+ if (trimmed.length() == 0) {
+ return getDefaultAbbreviator();
+ }
+
+ LogString::size_type i = 0;
+
+ while (
+ (i < trimmed.length()) && (trimmed[i] >= 0x30 /* '0' */)
+ && (trimmed[i] <= 0x39 /* '9' */)) {
+ i++;
+ }
+
+ //
+ // if all blanks and digits
+ //
+ if (i == trimmed.length()) {
+ return new MaxElementAbbreviator(StringHelper::toInt(trimmed));
+ }
+
+ std::vector<PatternAbbreviatorFragment> fragments;
+ logchar ellipsis;
+ int charCount;
+ LogString::size_type pos = 0;
+
+ while (pos < trimmed.length()) {
+ LogString::size_type ellipsisPos = pos;
+
+ if (trimmed[pos] == 0x2A /* '*' */) {
+ charCount = INT_MAX;
+ ellipsisPos++;
+ } else {
+ if ((trimmed[pos] >= 0x30 /* '0' */)
+ && (trimmed[pos] <= 0x39 /* '9' */)) {
+ charCount = trimmed[pos] - 0x30 /* '0' */;
+ ellipsisPos++;
+ } else {
+ charCount = 0;
+ }
+ }
+
+ ellipsis = 0;
+
+ if (ellipsisPos < trimmed.length()) {
+ ellipsis = trimmed[ellipsisPos];
+
+ if (ellipsis == 0x2E /* '.' */) {
+ ellipsis = 0;
+ }
+ }
+
+ fragments.push_back(PatternAbbreviatorFragment(charCount, ellipsis));
+ pos = trimmed.find(0x2E /* '.' */, pos);
+
+ if (pos == LogString::npos) {
+ break;
+ }
+
+ pos++;
+ }
+
+ NameAbbreviatorPtr abbrev(new PatternAbbreviator(fragments));
+ return abbrev;
+ }
+
+ //
+ // no matching abbreviation, return defaultAbbreviator
+ //
+ return getDefaultAbbreviator();
+ }
+
+ /**
+ * Gets default abbreviator.
+ *
+ * @return default abbreviator.
+ */
+NameAbbreviatorPtr NameAbbreviator::getDefaultAbbreviator() {
+ static NameAbbreviatorPtr def(new NOPAbbreviator());
+ return def;
+}
+
diff --git a/src/main/cpp/namepatternconverter.cpp b/src/main/cpp/namepatternconverter.cpp
new file mode 100644
index 0000000..49068dd
--- /dev/null
+++ b/src/main/cpp/namepatternconverter.cpp
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/namepatternconverter.h>
+#include <log4cxx/pattern/nameabbreviator.h>
+#include <log4cxx/spi/loggingevent.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+
+IMPLEMENT_LOG4CXX_OBJECT(NamePatternConverter)
+
+NamePatternConverter::NamePatternConverter(
+ const LogString& name1,
+ const LogString& style1,
+ const std::vector<LogString>& options) :
+ LoggingEventPatternConverter(name1, style1),
+ abbreviator(getAbbreviator(options)) {
+}
+
+NameAbbreviatorPtr NamePatternConverter::getAbbreviator(
+ const std::vector<LogString>& options) {
+ if (options.size() > 0) {
+ return NameAbbreviator::getAbbreviator(options[0]);
+ }
+ return NameAbbreviator::getDefaultAbbreviator();
+}
+
+ /**
+ * Abbreviate name in string buffer.
+ * @param nameStart starting position of name to abbreviate.
+ * @param buf string buffer containing name.
+ */
+void NamePatternConverter::abbreviate(int nameStart, LogString& buf) const {
+ abbreviator->abbreviate(nameStart, buf);
+}
diff --git a/src/main/cpp/ndc.cpp b/src/main/cpp/ndc.cpp
new file mode 100644
index 0000000..4ab612d
--- /dev/null
+++ b/src/main/cpp/ndc.cpp
@@ -0,0 +1,338 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/ndc.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/threadspecificdata.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+NDC::NDC(const std::string& message)
+{
+ push(message);
+}
+
+NDC::~NDC()
+{
+ pop();
+}
+
+
+LogString& NDC::getMessage(NDC::DiagnosticContext& ctx) {
+ return ctx.first;
+}
+
+LogString& NDC::getFullMessage(NDC::DiagnosticContext& ctx) {
+ return ctx.second;
+}
+
+void NDC::clear()
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ while(!stack.empty()) {
+ stack.pop();
+ }
+ data->recycle();
+ }
+}
+
+NDC::Stack* NDC::cloneStack()
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ if (!stack.empty()) {
+ return new Stack(stack);
+ }
+ }
+ return new Stack();
+}
+
+void NDC::inherit(NDC::Stack * stack) {
+ if (stack != NULL) {
+ ThreadSpecificData::inherit(*stack);
+ delete stack;
+ }
+}
+
+
+bool NDC::get(LogString& dest)
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ if(!stack.empty()) {
+ dest.append(getFullMessage(stack.top()));
+ return true;
+ }
+ data->recycle();
+ }
+ return false;
+}
+
+int NDC::getDepth() {
+ int size = 0;
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ size = data->getStack().size();
+ if (size == 0) {
+ data->recycle();
+ }
+ }
+ return size;
+}
+
+LogString NDC::pop()
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ if(!stack.empty())
+ {
+ LogString value(getMessage(stack.top()));
+ stack.pop();
+ data->recycle();
+ return value;
+ }
+ data->recycle();
+ }
+ return LogString();
+}
+
+bool NDC::pop(std::string& dst)
+{
+ bool retval = false;
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ if(!stack.empty())
+ {
+ Transcoder::encode(getMessage(stack.top()), dst);
+ stack.pop();
+ retval = true;
+ }
+ data->recycle();
+ }
+ return retval;
+}
+
+LogString NDC::peek()
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ if(!stack.empty())
+ {
+ return getMessage(stack.top());
+ }
+ data->recycle();
+ }
+ return LogString();
+}
+
+bool NDC::peek(std::string& dst)
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ if(!stack.empty())
+ {
+ Transcoder::encode(getMessage(stack.top()), dst);
+ return true;
+ }
+ data->recycle();
+ }
+ return false;
+}
+
+void NDC::pushLS(const LogString& message)
+{
+ ThreadSpecificData::push(message);
+}
+
+void NDC::push(const std::string& message)
+{
+ LOG4CXX_DECODE_CHAR(msg, message);
+ pushLS(msg);
+}
+
+void NDC::remove()
+{
+ clear();
+}
+
+bool NDC::empty() {
+ bool empty = true;
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ empty = stack.empty();
+ if (empty) {
+ data->recycle();
+ }
+ }
+ return empty;
+}
+
+#if LOG4CXX_WCHAR_T_API
+NDC::NDC(const std::wstring& message)
+{
+ push(message);
+}
+
+void NDC::push(const std::wstring& message)
+{
+ LOG4CXX_DECODE_WCHAR(msg, message);
+ pushLS(msg);
+}
+
+bool NDC::pop(std::wstring& dst)
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ if(!stack.empty())
+ {
+ Transcoder::encode(getMessage(stack.top()), dst);
+ stack.pop();
+ data->recycle();
+ return true;
+ }
+ data->recycle();
+ }
+ return false;
+}
+
+bool NDC::peek(std::wstring& dst)
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ if(!stack.empty())
+ {
+ Transcoder::encode(getMessage(stack.top()), dst);
+ return true;
+ }
+ data->recycle();
+ }
+ return false;
+}
+
+#endif
+
+
+#if LOG4CXX_UNICHAR_API
+NDC::NDC(const std::basic_string<UniChar>& message)
+{
+ push(message);
+}
+
+void NDC::push(const std::basic_string<UniChar>& message)
+{
+ LOG4CXX_DECODE_UNICHAR(msg, message);
+ pushLS(msg);
+}
+
+bool NDC::pop(std::basic_string<UniChar>& dst)
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ if(!stack.empty())
+ {
+ Transcoder::encode(stack.top().message, dst);
+ stack.pop();
+ data->recycle();
+ return true;
+ }
+ data->recycle();
+ }
+ return false;
+}
+
+bool NDC::peek(std::basic_string<UniChar>& dst)
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ if(!stack.empty())
+ {
+ Transcoder::encode(stack.top().message, dst);
+ return true;
+ }
+ data->recycle();
+ }
+ return false;
+}
+
+#endif
+
+
+#if LOG4CXX_CFSTRING_API
+NDC::NDC(const CFStringRef& message)
+{
+ push(message);
+}
+
+void NDC::push(const CFStringRef& message)
+{
+ LOG4CXX_DECODE_CFSTRING(msg, message);
+ pushLS(msg);
+}
+
+bool NDC::pop(CFStringRef& dst)
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ if(!stack.empty())
+ {
+ dst = Transcoder::encode(stack.top().message);
+ stack.pop();
+ data->recycle();
+ return true;
+ }
+ data->recycle();
+ }
+ return false;
+}
+
+bool NDC::peek(CFStringRef& dst)
+{
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ if(!stack.empty())
+ {
+ dst = Transcoder::encode(stack.top().message);
+ return true;
+ }
+ data->recycle();
+ }
+ return false;
+}
+
+#endif
+
diff --git a/src/main/cpp/ndcpatternconverter.cpp b/src/main/cpp/ndcpatternconverter.cpp
new file mode 100644
index 0000000..c965541
--- /dev/null
+++ b/src/main/cpp/ndcpatternconverter.cpp
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/ndcpatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(NDCPatternConverter)
+
+NDCPatternConverter::NDCPatternConverter() :
+ LoggingEventPatternConverter(LOG4CXX_STR("NDC"),
+ LOG4CXX_STR("ndc")) {
+}
+
+PatternConverterPtr NDCPatternConverter::newInstance(
+ const std::vector<LogString>& /* options */) {
+ static PatternConverterPtr def(new NDCPatternConverter());
+ return def;
+}
+
+void NDCPatternConverter::format(
+ const LoggingEventPtr& event,
+ LogString& toAppendTo,
+ Pool& /* p */) const {
+ if(!event->getNDC(toAppendTo)) {
+ toAppendTo.append(LOG4CXX_STR("null"));
+ }
+ }
diff --git a/src/main/cpp/nteventlogappender.cpp b/src/main/cpp/nteventlogappender.cpp
new file mode 100644
index 0000000..363b015
--- /dev/null
+++ b/src/main/cpp/nteventlogappender.cpp
@@ -0,0 +1,316 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if (defined(WIN32) || defined(_WIN32)) && !defined(_WIN32_WCE)
+
+#include <windows.h>
+#undef ERROR
+#include <log4cxx/nt/nteventlogappender.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/level.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/pool.h>
+#include <apr_strings.h>
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+using namespace log4cxx::nt;
+
+class CCtUserSIDHelper
+{
+public:
+ static bool FreeSid(SID * pSid)
+ {
+ return ::HeapFree(GetProcessHeap(), 0, (LPVOID)pSid) != 0;
+ }
+
+ static 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;
+ }
+
+ static 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;
+ }
+};
+
+IMPLEMENT_LOG4CXX_OBJECT(NTEventLogAppender)
+
+NTEventLogAppender::NTEventLogAppender() : hEventLog(NULL), pCurrentUserSID(NULL)
+{
+}
+
+NTEventLogAppender::NTEventLogAppender(const LogString& server, const LogString& log, const LogString& source, const LayoutPtr& layout)
+: server(server), log(log), source(source), hEventLog(NULL), pCurrentUserSID(NULL)
+{
+ this->layout = layout;
+ Pool pool;
+ activateOptions(pool);
+}
+
+NTEventLogAppender::~NTEventLogAppender()
+{
+ finalize();
+}
+
+
+void NTEventLogAppender::close()
+{
+ if (hEventLog != NULL)
+ {
+ ::DeregisterEventSource(hEventLog);
+ hEventLog = NULL;
+ }
+
+ if (pCurrentUserSID != NULL)
+ {
+ CCtUserSIDHelper::FreeSid((::SID*) pCurrentUserSID);
+ pCurrentUserSID = NULL;
+ }
+}
+
+void NTEventLogAppender::setOption(const LogString& option, const LogString& value)
+{
+ if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SERVER"), LOG4CXX_STR("server")))
+ {
+ server = value;
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("LOG"), LOG4CXX_STR("log")))
+ {
+ log = value;
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SOURCE"), LOG4CXX_STR("source")))
+ {
+ source = value;
+ }
+ else
+ {
+ AppenderSkeleton::setOption(option, value);
+ }
+}
+
+void NTEventLogAppender::activateOptions(Pool&)
+{
+ if (source.empty())
+ {
+ LogLog::warn(
+ ((LogString) LOG4CXX_STR("Source option not set for appender ["))
+ + name + LOG4CXX_STR("]."));
+ return;
+ }
+
+ if (log.empty())
+ {
+ log = LOG4CXX_STR("Application");
+ }
+
+ close();
+
+ // current user security identifier
+ CCtUserSIDHelper::GetCurrentUserSID((::SID**) &pCurrentUserSID);
+
+ addRegistryInfo();
+
+ LOG4CXX_ENCODE_WCHAR(wsource, source);
+ LOG4CXX_ENCODE_WCHAR(wserver, server);
+ hEventLog = ::RegisterEventSourceW(
+ wserver.empty() ? NULL : wserver.c_str(),
+ wsource.c_str());
+ if (hEventLog == NULL) {
+ LogString msg(LOG4CXX_STR("Cannot register NT EventLog -- server: '"));
+ msg.append(server);
+ msg.append(LOG4CXX_STR("' source: '"));
+ msg.append(source);
+ LogLog::error(msg);
+ LogLog::error(getErrorString(LOG4CXX_STR("RegisterEventSource")));
+ }
+}
+
+void NTEventLogAppender::append(const LoggingEventPtr& event, Pool& p)
+{
+ if (hEventLog == NULL)
+ {
+ LogLog::warn(LOG4CXX_STR("NT EventLog not opened."));
+ return;
+ }
+
+ LogString oss;
+ layout->format(oss, event, p);
+ wchar_t* msgs = Transcoder::wencode(oss, p);
+ BOOL bSuccess = ::ReportEventW(
+ hEventLog,
+ getEventType(event),
+ getEventCategory(event),
+ 0x1000,
+ pCurrentUserSID,
+ 1,
+ 0,
+ (LPCWSTR*) &msgs,
+ NULL);
+
+ if (!bSuccess)
+ {
+ LogLog::error(getErrorString(LOG4CXX_STR("ReportEvent")));
+ }
+}
+
+/*
+ * Add this source with appropriate configuration keys to the registry.
+ */
+void NTEventLogAppender::addRegistryInfo()
+{
+ DWORD disposition = 0;
+ ::HKEY hkey = 0;
+ LogString subkey(LOG4CXX_STR("SYSTEM\\CurrentControlSet\\Services\\EventLog\\"));
+ subkey.append(log);
+ subkey.append(1, (logchar) 0x5C /* '\\' */);
+ subkey.append(source);
+ LOG4CXX_ENCODE_WCHAR(wsubkey, subkey);
+
+ long stat = RegCreateKeyExW(HKEY_LOCAL_MACHINE, wsubkey.c_str(), 0, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL,
+ &hkey, &disposition);
+ if (stat == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY) {
+ HMODULE hmodule = GetModuleHandleW(L"log4cxx");
+ if (hmodule == NULL) {
+ hmodule = GetModuleHandleW(0);
+ }
+ wchar_t modpath[_MAX_PATH];
+ DWORD modlen = GetModuleFileNameW(hmodule, modpath, _MAX_PATH - 1);
+ if (modlen > 0) {
+ modpath[modlen] = 0;
+ RegSetValueExW(hkey, L"EventMessageFile", 0, REG_SZ,
+ (LPBYTE) modpath, wcslen(modpath) * sizeof(wchar_t));
+ RegSetValueExW(hkey, L"CategoryMessageFile", 0, REG_SZ,
+ (LPBYTE) modpath, wcslen(modpath) * sizeof(wchar_t));
+ DWORD typesSupported = 7;
+ DWORD categoryCount = 6;
+ RegSetValueExW(hkey, L"TypesSupported", 0, REG_DWORD,
+ (LPBYTE)&typesSupported, sizeof(DWORD));
+ RegSetValueExW(hkey, L"CategoryCount", 0, REG_DWORD,
+ (LPBYTE)&categoryCount, sizeof(DWORD));
+ }
+ }
+
+ RegCloseKey(hkey);
+ return;
+}
+
+WORD NTEventLogAppender::getEventType(const LoggingEventPtr& event)
+{
+ int priority = event->getLevel()->toInt();
+ WORD type = EVENTLOG_SUCCESS;
+ if (priority >= Level::INFO_INT) {
+ type = EVENTLOG_INFORMATION_TYPE;
+ if (priority >= Level::WARN_INT) {
+ type = EVENTLOG_WARNING_TYPE;
+ if (priority >= Level::ERROR_INT) {
+ type = EVENTLOG_ERROR_TYPE;
+ }
+ }
+ }
+ return type;
+}
+
+WORD NTEventLogAppender::getEventCategory(const LoggingEventPtr& event)
+{
+ int priority = event->getLevel()->toInt();
+ WORD category = 1;
+ if (priority >= Level::DEBUG_INT) {
+ category = 2;
+ if (priority >= Level::INFO_INT) {
+ category = 3;
+ if (priority >= Level::WARN_INT) {
+ category = 4;
+ if (priority >= Level::ERROR_INT) {
+ category = 5;
+ if (priority >= Level::FATAL_INT) {
+ category = 6;
+ }
+ }
+ }
+ }
+ }
+ return category;
+}
+
+LogString NTEventLogAppender::getErrorString(const LogString& function)
+{
+ Pool p;
+ enum { MSGSIZE = 5000 };
+
+ wchar_t* lpMsgBuf = (wchar_t*) p.palloc(MSGSIZE * sizeof(wchar_t));
+ DWORD dw = GetLastError();
+
+ FormatMessageW(
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ dw,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ lpMsgBuf,
+ MSGSIZE, NULL );
+
+ LogString msg(function);
+ msg.append(LOG4CXX_STR(" failed with error "));
+ StringHelper::toString((size_t) dw, p, msg);
+ msg.append(LOG4CXX_STR(": "));
+ Transcoder::decode(lpMsgBuf, msg);
+
+ return msg;
+}
+
+#endif // WIN32
diff --git a/src/main/cpp/objectimpl.cpp b/src/main/cpp/objectimpl.cpp
new file mode 100644
index 0000000..db26558
--- /dev/null
+++ b/src/main/cpp/objectimpl.cpp
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <apr_atomic.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/helpers/aprinitializer.h>
+
+using namespace log4cxx::helpers;
+
+ObjectImpl::ObjectImpl() : ref( 0 )
+{
+ log4cxx::helpers::APRInitializer::initialize();
+}
+
+ObjectImpl::~ObjectImpl()
+{
+}
+
+void ObjectImpl::addRef() const
+{
+ apr_atomic_inc32( & ref );
+}
+
+void ObjectImpl::releaseRef() const
+{
+ if ( apr_atomic_dec32( & ref ) == 0 )
+ {
+ delete this;
+ }
+}
diff --git a/src/main/cpp/objectoutputstream.cpp b/src/main/cpp/objectoutputstream.cpp
new file mode 100644
index 0000000..7cd696b
--- /dev/null
+++ b/src/main/cpp/objectoutputstream.cpp
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/objectoutputstream.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/outputstream.h>
+#include <log4cxx/helpers/charsetencoder.h>
+#include "apr_pools.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(ObjectOutputStream)
+
+ObjectOutputStream::ObjectOutputStream(OutputStreamPtr outputStream, Pool& p)
+ : os(outputStream) ,
+ utf8Encoder(CharsetEncoder::getUTF8Encoder()),
+ objectHandle(0x7E0000),
+ classDescriptions(new ClassDescriptionMap())
+{
+ char start[] = { 0xAC, 0xED, 0x00, 0x05 };
+ ByteBuffer buf(start, sizeof(start));
+ os->write(buf, p);
+}
+
+ObjectOutputStream::~ObjectOutputStream() {
+ delete classDescriptions;
+}
+
+void ObjectOutputStream::close(Pool& p) {
+ os->close(p);
+}
+
+void ObjectOutputStream::flush(Pool& p) {
+ os->flush(p);
+}
+
+void ObjectOutputStream::writeObject(const LogString& val, Pool& p) {
+ objectHandle++;
+ writeByte(TC_STRING, p);
+ char bytes[2];
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ size_t len = val.size();
+ ByteBuffer dataBuf(const_cast<char*>(val.data()), val.size());
+#else
+ size_t maxSize = 6 * val.size();
+ char* data = p.pstralloc(maxSize);
+ ByteBuffer dataBuf(data, maxSize);
+ LogString::const_iterator iter(val.begin());
+ utf8Encoder->encode(val, iter, dataBuf);
+ dataBuf.flip();
+ size_t len = dataBuf.limit();
+#endif
+ bytes[1] = (char) (len & 0xFF);
+ bytes[0] = (char) ((len >> 8) & 0xFF);
+ ByteBuffer lenBuf(bytes, sizeof(bytes));
+ os->write(lenBuf, p);
+ os->write(dataBuf, p);
+}
+
+
+void ObjectOutputStream::writeObject(const MDC::Map& val, Pool& p) {
+ //
+ // TC_OBJECT and the classDesc for java.util.Hashtable
+ //
+ char prolog[] = {
+ 0x72, 0x00, 0x13, 0x6A, 0x61, 0x76, 0x61,
+ 0x2E, 0x75, 0x74, 0x69, 0x6C, 0x2E, 0x48, 0x61,
+ 0x73, 0x68, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x13,
+ 0xBB, 0x0F, 0x25, 0x21, 0x4A, 0xE4, 0xB8, 0x03,
+ 0x00, 0x02, 0x46, 0x00, 0x0A, 0x6C, 0x6F, 0x61,
+ 0x64, 0x46, 0x61, 0x63, 0x74, 0x6F, 0x72, 0x49,
+ 0x00, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68,
+ 0x6F, 0x6C, 0x64, 0x78, 0x70 };
+ writeProlog("java.util.Hashtable", 1, prolog, sizeof(prolog), p);
+ //
+ // loadFactor = 0.75, threshold = 5, blockdata start, buckets.size = 7
+ char data[] = { 0x3F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ TC_BLOCKDATA, 0x08, 0x00, 0x00, 0x00, 0x07 };
+ ByteBuffer dataBuf(data, sizeof(data));
+ os->write(dataBuf, p);
+ char size[4];
+ size_t sz = val.size();
+ size[3] = (char) (sz & 0xFF);
+ size[2] = (char) ((sz >> 8) & 0xFF);
+ size[1] = (char) ((sz >> 16) & 0xFF);
+ size[0] = (char) ((sz >> 24) & 0xFF);
+ ByteBuffer sizeBuf(size, sizeof(size));
+ os->write(sizeBuf, p);
+ for(MDC::Map::const_iterator iter = val.begin();
+ iter != val.end();
+ iter++) {
+ writeObject(iter->first, p);
+ writeObject(iter->second, p);
+ }
+ writeByte(TC_ENDBLOCKDATA, p);
+}
+
+void ObjectOutputStream::writeUTFString(const std::string& val, Pool& p) {
+ char bytes[3];
+ size_t len = val.size();
+ ByteBuffer dataBuf(const_cast<char*>(val.data()), val.size());
+ objectHandle++;
+ bytes[0] = 0x74;
+ bytes[1] = (char) ((len >> 8) & 0xFF);
+ bytes[2] = (char) (len & 0xFF);
+ ByteBuffer lenBuf(bytes, sizeof(bytes));
+ os->write(lenBuf, p);
+ os->write(dataBuf, p);
+}
+
+
+
+void ObjectOutputStream::writeByte(char val, Pool& p) {
+ ByteBuffer buf(&val, 1);
+ os->write(buf, p);
+}
+
+void ObjectOutputStream::writeInt(int val, Pool& p) {
+ char bytes[4];
+ bytes[3] = (char) (val & 0xFF);
+ bytes[2] = (char) ((val >> 8) & 0xFF);
+ bytes[1] = (char) ((val >> 16) & 0xFF);
+ bytes[0] = (char) ((val >> 24) & 0xFF);
+ ByteBuffer buf(bytes, sizeof(bytes));
+ os->write(buf, p);
+}
+
+void ObjectOutputStream::writeLong(log4cxx_time_t val, Pool& p) {
+ char bytes[8];
+ bytes[7] = (char) (val & 0xFF);
+ bytes[6] = (char) ((val >> 8) & 0xFF);
+ bytes[5] = (char) ((val >> 16) & 0xFF);
+ bytes[4] = (char) ((val >> 24) & 0xFF);
+ bytes[3] = (char) ((val >> 32) & 0xFF);
+ bytes[2] = (char) ((val >> 40) & 0xFF);
+ bytes[1] = (char) ((val >> 48) & 0xFF);
+ bytes[0] = (char) ((val >> 56) & 0xFF);
+ ByteBuffer buf(bytes, sizeof(bytes));
+ os->write(buf, p);
+}
+
+void ObjectOutputStream::writeBytes(const char* bytes, size_t len, Pool& p) {
+ ByteBuffer buf(const_cast<char*>(bytes), len);
+ os->write(buf, p);
+}
+
+void ObjectOutputStream::writeNull(Pool& p) {
+ writeByte(TC_NULL, p);
+}
+
+void ObjectOutputStream::writeProlog(const char* className,
+ int classDescIncrement,
+ char* classDesc,
+ size_t len,
+ Pool& p) {
+ ClassDescriptionMap::const_iterator match = classDescriptions->find(className);
+ if (match != classDescriptions->end()) {
+ char bytes[6];
+ bytes[0] = TC_OBJECT;
+ bytes[1] = TC_REFERENCE;
+ bytes[2] = (char) ((match->second >> 24) & 0xFF);
+ bytes[3] = (char) ((match->second >> 16) & 0xFF);
+ bytes[4] = (char) ((match->second >> 8) & 0xFF);
+ bytes[5] = (char) (match->second & 0xFF);
+ ByteBuffer buf(bytes, sizeof(bytes));
+ os->write(buf, p);
+ objectHandle++;
+ } else {
+ classDescriptions->insert(ClassDescriptionMap::value_type(className, objectHandle));
+ writeByte(TC_OBJECT, p);
+ ByteBuffer buf(classDesc, len);
+ os->write(buf, p);
+ objectHandle += (classDescIncrement + 1);
+ }
+}
diff --git a/src/main/cpp/objectptr.cpp b/src/main/cpp/objectptr.cpp
new file mode 100755
index 0000000..0c4f306
--- /dev/null
+++ b/src/main/cpp/objectptr.cpp
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/exception.h>
+#include <apr_atomic.h>
+
+using namespace log4cxx::helpers;
+
+ObjectPtrBase::ObjectPtrBase() {
+}
+
+ObjectPtrBase::~ObjectPtrBase() {
+}
+
+void ObjectPtrBase::checkNull(const int& null) {
+ if (null != 0) {
+ throw IllegalArgumentException(LOG4CXX_STR("Attempt to set pointer to a non-zero numeric value."));
+ }
+}
+
+void* ObjectPtrBase::exchange(void** destination, void* newValue) {
+#if _WIN32 && (!defined(_MSC_VER) || _MSC_VER >= 1300)
+ return InterlockedExchangePointer(destination, newValue);
+#elif APR_SIZEOF_VOIDP == 4
+ return (void*) apr_atomic_xchg32((volatile apr_uint32_t*) destination,
+ (apr_uint32_t) newValue);
+#else
+ void* oldValue = *destination;
+ *destination = newValue;
+ return oldValue;
+#endif
+}
diff --git a/src/main/cpp/obsoleterollingfileappender.cpp b/src/main/cpp/obsoleterollingfileappender.cpp
new file mode 100644
index 0000000..2b218e6
--- /dev/null
+++ b/src/main/cpp/obsoleterollingfileappender.cpp
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/rollingfileappender.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/rolling/rollingfileappenderskeleton.h>
+#include <log4cxx/rolling/sizebasedtriggeringpolicy.h>
+#include <log4cxx/rolling/fixedwindowrollingpolicy.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+namespace log4cxx {
+ class ClassRollingFileAppender : public Class
+ {
+ public:
+ ClassRollingFileAppender() : helpers::Class() {}
+ virtual LogString getName() const {
+ return LOG4CXX_STR("org.apache.log4j.RollingFileAppender");
+ }
+ virtual ObjectPtr newInstance() const {
+ return new RollingFileAppender();
+ }
+ };
+}
+
+const log4cxx::helpers::Class& RollingFileAppender::getClass() const { return getStaticClass(); }
+const log4cxx::helpers::Class& RollingFileAppender::getStaticClass() {
+ static ClassRollingFileAppender theClass;
+ return theClass;
+}
+const log4cxx::helpers::ClassRegistration& RollingFileAppender::registerClass() {
+ static log4cxx::helpers::ClassRegistration classReg(RollingFileAppender::getStaticClass);
+ return classReg;
+}
+namespace log4cxx { namespace classes {
+const log4cxx::helpers::ClassRegistration& ObsoleteRollingFileAppenderRegistration =
+ RollingFileAppender::registerClass();
+} }
+
+
+
+RollingFileAppender::RollingFileAppender()
+ : maxFileSize(10*1024*1024), maxBackupIndex(1) {
+}
+
+RollingFileAppender::RollingFileAppender(
+ const LayoutPtr& layout,
+ const LogString& filename,
+ bool append)
+ : maxFileSize(10*1024*1024), maxBackupIndex(1) {
+ setLayout(layout);
+ setFile(filename);
+ setAppend(append);
+ Pool pool;
+ activateOptions(pool);
+}
+
+RollingFileAppender::RollingFileAppender(const LayoutPtr& layout,
+ const LogString& filename)
+ : maxFileSize(10*1024*1024), maxBackupIndex(1) {
+ setLayout(layout);
+ setFile(filename);
+ Pool pool;
+ activateOptions(pool);
+}
+
+RollingFileAppender::~RollingFileAppender() {
+}
+
+
+void RollingFileAppender::setOption(const LogString& option,
+ const LogString& value)
+{
+ if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("MAXFILESIZE"), LOG4CXX_STR("maxfilesize"))
+ || StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("MAXIMUMFILESIZE"), LOG4CXX_STR("maximumfilesize")))
+ {
+ setMaxFileSize(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("MAXBACKUPINDEX"), LOG4CXX_STR("maxbackupindex"))
+ || StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("MAXIMUMBACKUPINDEX"), LOG4CXX_STR("maximumbackupindex")))
+ {
+ maxBackupIndex = StringHelper::toInt(value);
+ }
+ else
+ {
+ using namespace log4cxx::rolling;
+ RollingFileAppenderSkeleton::setOption(option, value);
+ }
+}
+
+
+int RollingFileAppender::getMaxBackupIndex() const {
+ return maxBackupIndex;
+}
+
+long RollingFileAppender::getMaximumFileSize() const {
+ return maxFileSize;
+}
+
+void RollingFileAppender::setMaxBackupIndex(int maxBackups) {
+ maxBackupIndex = maxBackups;
+}
+
+void RollingFileAppender::setMaximumFileSize(int maxFileSize1) {
+ maxFileSize = maxFileSize1;
+}
+
+void RollingFileAppender::setMaxFileSize(const LogString& value) {
+ maxFileSize = OptionConverter::toFileSize(value, maxFileSize + 1);
+}
+
+void RollingFileAppender::activateOptions(Pool& pool) {
+ log4cxx::rolling::SizeBasedTriggeringPolicyPtr trigger(
+ new log4cxx::rolling::SizeBasedTriggeringPolicy());
+ trigger->setMaxFileSize(maxFileSize);
+ trigger->activateOptions(pool);
+ setTriggeringPolicy(trigger);
+
+ log4cxx::rolling::FixedWindowRollingPolicyPtr rolling(
+ new log4cxx::rolling::FixedWindowRollingPolicy());
+ rolling->setMinIndex(1);
+ rolling->setMaxIndex(maxBackupIndex);
+ rolling->setFileNamePattern(getFile() + LOG4CXX_STR(".%i"));
+ rolling->activateOptions(pool);
+ setRollingPolicy(rolling);
+
+ using namespace log4cxx::rolling;
+ RollingFileAppenderSkeleton::activateOptions(pool);
+}
+
+
diff --git a/src/main/cpp/odbcappender.cpp b/src/main/cpp/odbcappender.cpp
new file mode 100644
index 0000000..f1e1f35
--- /dev/null
+++ b/src/main/cpp/odbcappender.cpp
@@ -0,0 +1,333 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/db/odbcappender.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/patternlayout.h>
+#include <apr_strings.h>
+
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+#if LOG4CXX_HAVE_ODBC
+#if defined(WIN32) || defined(_WIN32)
+#include <windows.h>
+#endif
+#include <sqlext.h>
+#endif
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::db;
+using namespace log4cxx::spi;
+
+SQLException::SQLException(short fHandleType,
+ void* hInput, const char* prolog,
+ log4cxx::helpers::Pool& p)
+ : Exception(formatMessage(fHandleType, hInput, prolog, p)) {
+}
+
+
+SQLException::SQLException(const char* msg)
+ : Exception(msg) {
+}
+
+SQLException::SQLException(const SQLException& src)
+ : Exception(src) {
+}
+
+const char* SQLException::formatMessage(short fHandleType,
+ void* hInput, const char* prolog, log4cxx::helpers::Pool& p) {
+ std::string strReturn(prolog);
+ strReturn.append(" - ");
+#if LOG4CXX_HAVE_ODBC
+ SQLCHAR SqlState[6];
+ SQLCHAR Msg[SQL_MAX_MESSAGE_LENGTH];
+ SQLINTEGER NativeError;
+ SQLSMALLINT i;
+ SQLSMALLINT MsgLen;
+ SQLRETURN rc2;
+
+ // Get the status records.
+ i = 1;
+ while ((rc2 = SQLGetDiagRecA(fHandleType, hInput, i, SqlState, &NativeError,
+ Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA)
+ {
+ strReturn.append((char*) Msg);
+ i++;
+ }
+#else
+ strReturn.append("log4cxx built without ODBC support");
+#endif
+
+ return apr_pstrdup((apr_pool_t*) p.getAPRPool(), strReturn.c_str());
+}
+
+
+IMPLEMENT_LOG4CXX_OBJECT(ODBCAppender)
+
+
+
+ODBCAppender::ODBCAppender()
+: connection(0), env(0), bufferSize(1)
+{
+}
+
+ODBCAppender::~ODBCAppender()
+{
+ finalize();
+}
+
+void ODBCAppender::setOption(const LogString& option, const LogString& value)
+{
+ if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BUFFERSIZE"), LOG4CXX_STR("buffersize")))
+ {
+ setBufferSize((size_t)OptionConverter::toInt(value, 1));
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("PASSWORD"), LOG4CXX_STR("password")))
+ {
+ setPassword(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SQL"), LOG4CXX_STR("sql")))
+ {
+ setSql(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("URL"), LOG4CXX_STR("url"))
+ || StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("DSN"), LOG4CXX_STR("dsn"))
+ || StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("CONNECTIONSTRING"), LOG4CXX_STR("connectionstring")) )
+ {
+ setURL(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("USER"), LOG4CXX_STR("user")))
+ {
+ setUser(value);
+ }
+ else
+ {
+ AppenderSkeleton::setOption(option, value);
+ }
+}
+
+void ODBCAppender::activateOptions(log4cxx::helpers::Pool&) {
+#if !LOG4CXX_HAVE_ODBC
+ LogLog::error(LOG4CXX_STR("Can not activate ODBCAppender unless compiled with ODBC support."));
+#endif
+}
+
+
+void ODBCAppender::append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p)
+{
+#if LOG4CXX_HAVE_ODBC
+ buffer.push_back(event);
+
+ if (buffer.size() >= bufferSize)
+ flushBuffer(p);
+#endif
+}
+
+LogString ODBCAppender::getLogStatement(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) const
+{
+ LogString sbuf;
+ getLayout()->format(sbuf, event, p);
+ return sbuf;
+}
+
+void ODBCAppender::execute(const LogString& sql, log4cxx::helpers::Pool& p)
+{
+#if LOG4CXX_HAVE_ODBC
+ SQLRETURN ret;
+ SQLHDBC con = SQL_NULL_HDBC;
+ SQLHSTMT stmt = SQL_NULL_HSTMT;
+
+ try
+ {
+ con = getConnection(p);
+
+ ret = SQLAllocHandle( SQL_HANDLE_STMT, con, &stmt);
+ if (ret < 0)
+ {
+ throw SQLException( SQL_HANDLE_DBC, con, "Failed to allocate sql handle.", p);
+ }
+
+ SQLWCHAR* wsql = Transcoder::wencode(sql, p);
+ ret = SQLExecDirectW(stmt, wsql, SQL_NTS);
+
+ if (ret < 0)
+ {
+ throw SQLException(SQL_HANDLE_STMT, stmt, "Failed to execute sql statement.", p);
+ }
+ }
+ catch (SQLException& e)
+ {
+ if (stmt != SQL_NULL_HSTMT)
+ {
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ }
+
+ throw e;
+ }
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ closeConnection(con);
+#else
+ throw SQLException("log4cxx build without ODBC support");
+#endif
+}
+
+/* The default behavior holds a single connection open until the appender
+is closed (typically when garbage collected).*/
+void ODBCAppender::closeConnection(ODBCAppender::SQLHDBC /* con */)
+{
+}
+
+
+
+
+
+ODBCAppender::SQLHDBC ODBCAppender::getConnection(log4cxx::helpers::Pool& p)
+{
+#if LOG4CXX_HAVE_ODBC
+ SQLRETURN ret;
+
+ if (env == SQL_NULL_HENV)
+ {
+ ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
+ if (ret < 0)
+ {
+ SQLException ex(SQL_HANDLE_ENV, env, "Failed to allocate SQL handle.", p);
+ env = SQL_NULL_HENV;
+ throw ex;
+ }
+
+ ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER);
+ if (ret < 0)
+ {
+ SQLException ex(SQL_HANDLE_ENV, env, "Failed to set odbc version.", p);
+ SQLFreeHandle(SQL_HANDLE_ENV, env);
+ env = SQL_NULL_HENV;
+ throw ex;
+ }
+ }
+
+ if (connection == SQL_NULL_HDBC)
+ {
+ ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &connection);
+ if (ret < 0)
+ {
+ SQLException ex(SQL_HANDLE_DBC, connection, "Failed to allocate sql handle.", p);
+ connection = SQL_NULL_HDBC;
+ throw ex;
+ }
+
+
+ SQLWCHAR* wURL = Transcoder::wencode(databaseURL, p);
+
+ wchar_t szOutConnectionString[1024];
+ SQLSMALLINT nOutConnctionLength = 0;
+
+ ret = SQLDriverConnectW( connection, NULL,
+ wURL, SQL_NTS,
+ szOutConnectionString, sizeof( szOutConnectionString ),
+ &nOutConnctionLength, SQL_DRIVER_NOPROMPT );
+
+
+ if (ret < 0)
+ {
+ SQLException ex(SQL_HANDLE_DBC, connection, "Failed to connect to database.", p);
+ SQLFreeHandle(SQL_HANDLE_DBC, connection);
+ connection = SQL_NULL_HDBC;
+ throw ex;
+ }
+ }
+
+ return connection;
+#else
+ return 0;
+#endif
+}
+
+void ODBCAppender::close()
+{
+ if (closed) {
+ return;
+ }
+ Pool p;
+ try
+ {
+ flushBuffer(p);
+ }
+ catch (SQLException& e)
+ {
+ errorHandler->error(LOG4CXX_STR("Error closing connection"),
+ e, ErrorCode::GENERIC_FAILURE);
+ }
+#if LOG4CXX_HAVE_ODBC
+ if (connection != SQL_NULL_HDBC)
+ {
+ SQLDisconnect(connection);
+ SQLFreeHandle(SQL_HANDLE_DBC, connection);
+ }
+
+ if (env != SQL_NULL_HENV)
+ {
+ SQLFreeHandle(SQL_HANDLE_ENV, env);
+ }
+#endif
+ this->closed = true;
+}
+
+void ODBCAppender::flushBuffer(Pool& p)
+{
+ std::list<spi::LoggingEventPtr>::iterator i;
+ for (i = buffer.begin(); i != buffer.end(); i++)
+ {
+ try
+ {
+ const LoggingEventPtr& logEvent = *i;
+ LogString sql = getLogStatement(logEvent, p);
+ execute(sql, p);
+ }
+ catch (SQLException& e)
+ {
+ errorHandler->error(LOG4CXX_STR("Failed to excute sql"), e,
+ ErrorCode::FLUSH_FAILURE);
+ }
+ }
+
+ // clear the buffer of reported events
+ buffer.clear();
+}
+
+void ODBCAppender::setSql(const LogString& s)
+{
+ sqlStatement = s;
+ if (getLayout() == 0)
+ {
+ this->setLayout(new PatternLayout(s));
+ }
+ else
+ {
+ PatternLayoutPtr patternLayout = this->getLayout();
+ if (patternLayout != 0)
+ {
+ patternLayout->setConversionPattern(s);
+ }
+ }
+}
diff --git a/src/main/cpp/onlyonceerrorhandler.cpp b/src/main/cpp/onlyonceerrorhandler.cpp
new file mode 100644
index 0000000..49a6963
--- /dev/null
+++ b/src/main/cpp/onlyonceerrorhandler.cpp
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/appender.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/helpers/onlyonceerrorhandler.h>
+#include <log4cxx/helpers/loglog.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+IMPLEMENT_LOG4CXX_OBJECT(OnlyOnceErrorHandler)
+
+OnlyOnceErrorHandler::OnlyOnceErrorHandler() :
+ WARN_PREFIX(LOG4CXX_STR("log4cxx warning: ")),
+ERROR_PREFIX(LOG4CXX_STR("log4cxx error: ")), firstTime(true)
+{
+}
+
+ void OnlyOnceErrorHandler::addRef() const {
+ ObjectImpl::addRef();
+ }
+
+ void OnlyOnceErrorHandler::releaseRef() const {
+ ObjectImpl::releaseRef();
+ }
+
+void OnlyOnceErrorHandler::setLogger(const LoggerPtr&)
+{
+}
+
+void OnlyOnceErrorHandler::activateOptions(Pool&)
+{
+}
+
+void OnlyOnceErrorHandler::setOption(const LogString&, const LogString&)
+{
+}
+
+void OnlyOnceErrorHandler::error(const LogString& message, const std::exception& e,
+ int) const
+{
+ if(firstTime)
+ {
+ LogLog::error(message, e);
+ firstTime = false;
+ }
+}
+
+void OnlyOnceErrorHandler::error(const LogString& message, const std::exception& e,
+ int errorCode, const log4cxx::spi::LoggingEventPtr&) const
+{
+ error(message, e, errorCode);
+}
+
+
+void OnlyOnceErrorHandler::error(const LogString& message) const
+{
+ if(firstTime)
+ {
+ LogLog::error(message);
+ firstTime = false;
+ }
+}
+
+
+void OnlyOnceErrorHandler::setAppender(const AppenderPtr&)
+{
+}
+
+
+void OnlyOnceErrorHandler::setBackupAppender(const AppenderPtr&)
+{
+}
diff --git a/src/main/cpp/optionconverter.cpp b/src/main/cpp/optionconverter.cpp
new file mode 100644
index 0000000..030e2e7
--- /dev/null
+++ b/src/main/cpp/optionconverter.cpp
@@ -0,0 +1,381 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/spi/loggerfactory.h>
+#include <log4cxx/spi/loggerrepository.h>
+#include <log4cxx/appenderskeleton.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <algorithm>
+#include <ctype.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/exception.h>
+#include <stdlib.h>
+#include <log4cxx/helpers/properties.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/level.h>
+#include <log4cxx/helpers/object.h>
+#include <log4cxx/helpers/class.h>
+#include <log4cxx/helpers/loader.h>
+#include <log4cxx/helpers/system.h>
+#include <log4cxx/propertyconfigurator.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/file.h>
+#include <log4cxx/xml/domconfigurator.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+
+LogString OptionConverter::convertSpecialChars(const LogString& s)
+{
+ logchar c;
+ LogString sbuf;
+
+ LogString::const_iterator i = s.begin();
+ while(i != s.end())
+ {
+ c = *i++;
+ if (c == 0x5C /* '\\' */)
+ {
+ c = *i++;
+
+ switch (c)
+ {
+ case 0x6E: //'n'
+ c = 0x0A;
+ break;
+
+ case 0x72: //'r'
+ c = 0x0D;
+ break;
+
+ case 0x74: //'t'
+ c = 0x09;
+ break;
+
+ case 0x66: //'f'
+ c = 0x0C;
+ break;
+ default:
+ break;
+ }
+ }
+ sbuf.append(1, c);
+ }
+ return sbuf;
+}
+
+
+bool OptionConverter::toBoolean(const LogString& value, bool dEfault)
+{
+ if (value.length() >= 4) {
+ if (StringHelper::equalsIgnoreCase(value.substr(0,4),
+ LOG4CXX_STR("TRUE"), LOG4CXX_STR("true"))) {
+ return true;
+ }
+ }
+
+ if (dEfault && value.length() >= 5) {
+ if (StringHelper::equalsIgnoreCase(value.substr(0,5),
+ LOG4CXX_STR("FALSE"), LOG4CXX_STR("false"))) {
+ return false;
+ }
+ }
+
+ return dEfault;
+}
+
+int OptionConverter::toInt(const LogString& value, int dEfault)
+{
+ LogString trimmed(StringHelper::trim(value));
+ if (trimmed.empty())
+ {
+ return dEfault;
+ }
+ LOG4CXX_ENCODE_CHAR(cvalue, trimmed);
+
+ return (int) atol(cvalue.c_str());
+}
+
+long OptionConverter::toFileSize(const LogString& s, long dEfault)
+{
+ if(s.empty())
+ {
+ return dEfault;
+ }
+
+ size_t index = s.find_first_of(LOG4CXX_STR("bB"));
+ if (index != LogString::npos && index > 0) {
+ long multiplier = 1;
+ index--;
+ if (s[index] == 0x6B /* 'k' */ || s[index] == 0x4B /* 'K' */) {
+ multiplier = 1024;
+ } else if(s[index] == 0x6D /* 'm' */ || s[index] == 0x4D /* 'M' */) {
+ multiplier = 1024*1024;
+ } else if(s[index] == 0x67 /* 'g'*/ || s[index] == 0x47 /* 'G' */) {
+ multiplier = 1024*1024*1024;
+ }
+ return toInt(s.substr(0, index), 1) * multiplier;
+ }
+
+ return toInt(s, 1);
+}
+
+LogString OptionConverter::findAndSubst(const LogString& key, Properties& props)
+{
+ LogString value(props.getProperty(key));
+
+ if(value.empty())
+ return value;
+
+ try
+ {
+ return substVars(value, props);
+ }
+ catch(IllegalArgumentException& e)
+ {
+ LogLog::error(((LogString) LOG4CXX_STR("Bad option value ["))
+ + value + LOG4CXX_STR("]."), e);
+ return value;
+ }
+}
+
+LogString OptionConverter::substVars(const LogString& val, Properties& props)
+{
+ LogString sbuf;
+ const logchar delimStartArray[] = { 0x24, 0x7B, 0 };
+ const LogString delimStart(delimStartArray);
+ const logchar delimStop = 0x7D; // '}';
+ const size_t DELIM_START_LEN = 2;
+ const size_t DELIM_STOP_LEN = 1;
+
+ int i = 0;
+ int j, k;
+
+ while(true)
+ {
+ j = val.find(delimStart, i);
+ if(j == -1)
+ {
+ // no more variables
+ if(i==0)
+ { // this is a simple string
+ return val;
+ }
+ else
+ { // add the tail string which contails no variables and return the result.
+ sbuf.append(val.substr(i, val.length() - i));
+ return sbuf;
+ }
+ }
+ else
+ {
+ sbuf.append(val.substr(i, j - i));
+ k = val.find(delimStop, j);
+ if(k == -1)
+ {
+ LogString msg(1, (logchar) 0x22 /* '\"' */);
+ msg.append(val);
+ msg.append(LOG4CXX_STR("\" has no closing brace. Opening brace at position "));
+ Pool p;
+ StringHelper::toString(j, p, msg);
+ msg.append(1, (logchar) 0x2E /* '.' */);
+ throw IllegalArgumentException(msg);
+ }
+ else
+ {
+ j += DELIM_START_LEN;
+ LogString key = val.substr(j, k - j);
+ // first try in System properties
+ LogString replacement(getSystemProperty(key, LogString()));
+ // then try props parameter
+ if(replacement.empty())
+ {
+ replacement = props.getProperty(key);
+ }
+
+ if(!replacement.empty())
+ {
+ // Do variable substitution on the replacement string
+ // such that we can solve "Hello ${x2}" as "Hello p1"
+ // the where the properties are
+ // x1=p1
+ // x2=${x1}
+ LogString recursiveReplacement = substVars(replacement, props);
+ sbuf.append(recursiveReplacement);
+ }
+ i = k + DELIM_STOP_LEN;
+ }
+ }
+ }
+}
+
+LogString OptionConverter::getSystemProperty(const LogString& key, const LogString& def)
+{
+ if (!key.empty())
+ {
+ LogString value(System::getProperty(key));
+
+ if (!value.empty())
+ {
+ return value;
+ }
+ }
+ return def;
+}
+
+LevelPtr OptionConverter::toLevel(const LogString& value,
+ const LevelPtr& defaultValue)
+{
+ size_t hashIndex = value.find(LOG4CXX_STR("#"));
+
+ if (hashIndex == LogString::npos)
+ {
+ if (value.empty())
+ {
+ return defaultValue;
+ }
+ else
+ {
+ LogLog::debug(
+ ((LogString) LOG4CXX_STR("OptionConverter::toLevel: no class name specified, level=["))
+ + value
+ +LOG4CXX_STR("]"));
+ // no class name specified : use standard Level class
+ return Level::toLevelLS(value, defaultValue);
+ }
+ }
+
+ LogString clazz = value.substr(hashIndex + 1);
+ LogString levelName = value.substr(0, hashIndex);
+ LogLog::debug(((LogString) LOG4CXX_STR("OptionConverter::toLevel: class=["))
+ + clazz + LOG4CXX_STR("], level=[") + levelName + LOG4CXX_STR("]"));
+
+ // This is degenerate case but you never know.
+ if (levelName.empty())
+ {
+ return Level::toLevelLS(value, defaultValue);
+ }
+
+ try
+ {
+ Level::LevelClass& levelClass =
+ (Level::LevelClass&)Loader::loadClass(clazz);
+ return levelClass.toLevel(levelName);
+ }
+ catch (ClassNotFoundException&)
+ {
+ LogLog::warn(((LogString) LOG4CXX_STR("custom level class ["))
+ + clazz + LOG4CXX_STR("] not found."));
+ }
+ catch(Exception& oops)
+ {
+ LogLog::warn(
+ LOG4CXX_STR("class [") + clazz + LOG4CXX_STR("], level [") + levelName +
+ LOG4CXX_STR("] conversion) failed."), oops);
+ }
+ catch(...)
+ {
+ LogLog::warn(
+ LOG4CXX_STR("class [") + clazz + LOG4CXX_STR("], level [") + levelName +
+ LOG4CXX_STR("] conversion) failed."));
+ }
+
+ return defaultValue;
+}
+
+
+ObjectPtr OptionConverter::instantiateByKey(Properties& props, const LogString& key,
+ const Class& superClass, const ObjectPtr& defaultValue)
+{
+ // Get the value of the property in string form
+ LogString className(findAndSubst(key, props));
+ if(className.empty())
+ {
+ LogLog::error(
+ ((LogString) LOG4CXX_STR("Could not find value for key ")) + key);
+ return defaultValue;
+ }
+
+ // Trim className to avoid trailing spaces that cause problems.
+ return OptionConverter::instantiateByClassName(
+ StringHelper::trim(className), superClass, defaultValue);
+}
+
+ObjectPtr OptionConverter::instantiateByClassName(const LogString& className,
+ const Class& superClass, const ObjectPtr& defaultValue)
+{
+ if(!className.empty())
+ {
+ try
+ {
+ const Class& classObj = Loader::loadClass(className);
+ ObjectPtr newObject = classObj.newInstance();
+ if (!newObject->instanceof(superClass))
+ {
+ return defaultValue;
+ }
+
+ return newObject;
+ }
+ catch (Exception& e)
+ {
+ LogLog::error(LOG4CXX_STR("Could not instantiate class [") +
+ className + LOG4CXX_STR("]."), e);
+ }
+ }
+ return defaultValue;
+}
+
+void OptionConverter::selectAndConfigure(const File& configFileName,
+ const LogString& _clazz, spi::LoggerRepositoryPtr& hierarchy)
+{
+ ConfiguratorPtr configurator;
+ LogString clazz = _clazz;
+
+ LogString filename(configFileName.getPath());
+ if(clazz.empty()
+ && filename.length() > 4
+ && StringHelper::equalsIgnoreCase(
+ filename.substr(filename.length() -4),
+ LOG4CXX_STR(".XML"), LOG4CXX_STR(".xml")))
+ {
+ clazz = log4cxx::xml::DOMConfigurator::getStaticClass().toString();
+ }
+
+ if(!clazz.empty())
+ {
+ LogLog::debug(LOG4CXX_STR("Preferred configurator class: ") + clazz);
+ configurator = instantiateByClassName(clazz,
+ Configurator::getStaticClass(),
+ 0);
+ if(configurator == 0)
+ {
+ LogLog::error(LOG4CXX_STR("Could not instantiate configurator [")
+ + clazz + LOG4CXX_STR("]."));
+ return;
+ }
+ }
+ else
+ {
+ configurator = new PropertyConfigurator();
+ }
+
+ configurator->doConfigure(configFileName, hierarchy);
+}
diff --git a/src/main/cpp/outputdebugstringappender.cpp b/src/main/cpp/outputdebugstringappender.cpp
new file mode 100644
index 0000000..5e3687f
--- /dev/null
+++ b/src/main/cpp/outputdebugstringappender.cpp
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(_WIN32)
+#include <log4cxx/nt/outputdebugstringappender.h>
+#include <log4cxx/helpers/transcoder.h>
+
+#include "windows.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::nt;
+
+IMPLEMENT_LOG4CXX_OBJECT(OutputDebugStringAppender)
+
+OutputDebugStringAppender::OutputDebugStringAppender() {
+}
+
+void OutputDebugStringAppender::append(const spi::LoggingEventPtr& event, Pool& p)
+{
+ LogString buf;
+ layout->format(buf, event, p);
+#if LOG4CXX_WCHAR_T_API
+ LOG4CXX_ENCODE_WCHAR(wstr, buf);
+ ::OutputDebugStringW(wstr.c_str());
+#else
+ LOG4CXX_ENCODE_CHAR(str, buf);
+ ::OutputDebugStringA(str.c_str());
+#endif
+}
+
+#endif
+
diff --git a/src/main/cpp/outputstream.cpp b/src/main/cpp/outputstream.cpp
new file mode 100644
index 0000000..f7d3691
--- /dev/null
+++ b/src/main/cpp/outputstream.cpp
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/outputstream.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(OutputStream)
+
+OutputStream::OutputStream() {
+}
+
+OutputStream::~OutputStream() {
+}
diff --git a/src/main/cpp/outputstreamwriter.cpp b/src/main/cpp/outputstreamwriter.cpp
new file mode 100644
index 0000000..7c95619
--- /dev/null
+++ b/src/main/cpp/outputstreamwriter.cpp
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/outputstreamwriter.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/charsetencoder.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/stringhelper.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(OutputStreamWriter)
+
+OutputStreamWriter::OutputStreamWriter(OutputStreamPtr& out1)
+ : out(out1), enc(CharsetEncoder::getDefaultEncoder()) {
+ if (out1 == 0) {
+ throw NullPointerException(LOG4CXX_STR("out parameter may not be null."));
+ }
+}
+
+OutputStreamWriter::OutputStreamWriter(OutputStreamPtr& out1,
+ CharsetEncoderPtr &enc1)
+ : out(out1), enc(enc1) {
+ if (out1 == 0) {
+ throw NullPointerException(LOG4CXX_STR("out parameter may not be null."));
+ }
+ if (enc1 == 0) {
+ throw NullPointerException(LOG4CXX_STR("enc parameter may not be null."));
+ }
+}
+
+OutputStreamWriter::~OutputStreamWriter() {
+}
+
+void OutputStreamWriter::close(Pool& p) {
+ out->close(p);
+}
+
+void OutputStreamWriter::flush(Pool& p) {
+ out->flush(p);
+}
+
+void OutputStreamWriter::write(const LogString& str, Pool& p) {
+ if (str.length() > 0) {
+ enum { BUFSIZE = 1024 };
+ char rawbuf[BUFSIZE];
+ ByteBuffer buf(rawbuf, (size_t) BUFSIZE);
+ enc->reset();
+ LogString::const_iterator iter = str.begin();
+ while(iter != str.end()) {
+ CharsetEncoder::encode(enc, str, iter, buf);
+ buf.flip();
+ out->write(buf, p);
+ buf.clear();
+ }
+ CharsetEncoder::encode(enc, str, iter, buf);
+ enc->flush(buf);
+ buf.flip();
+ out->write(buf, p);
+ }
+}
+
diff --git a/src/main/cpp/patternconverter.cpp b/src/main/cpp/patternconverter.cpp
new file mode 100644
index 0000000..9b7ab26
--- /dev/null
+++ b/src/main/cpp/patternconverter.cpp
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/patternconverter.h>
+#include <log4cxx/helpers/transcoder.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+
+IMPLEMENT_LOG4CXX_OBJECT(PatternConverter)
+
+PatternConverter::PatternConverter(
+ const LogString& name1, const LogString& style1) :
+ name(name1), style(style1) {
+}
+
+PatternConverter::~PatternConverter() {
+}
+
+LogString PatternConverter::getName() const {
+ return name;
+}
+
+LogString PatternConverter::getStyleClass(const log4cxx::helpers::ObjectPtr& /* e */) const {
+ return style;
+ }
+
+void PatternConverter::append(LogString& toAppendTo, const std::string& src) {
+ LOG4CXX_DECODE_CHAR(decoded, src);
+ toAppendTo.append(decoded);
+}
+
diff --git a/src/main/cpp/patternlayout.cpp b/src/main/cpp/patternlayout.cpp
new file mode 100644
index 0000000..030262f
--- /dev/null
+++ b/src/main/cpp/patternlayout.cpp
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/pattern/patternparser.h>
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+#include <log4cxx/pattern/formattinginfo.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/optionconverter.h>
+
+#include <log4cxx/pattern/loggerpatternconverter.h>
+#include <log4cxx/pattern/literalpatternconverter.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/pattern/classnamepatternconverter.h>
+#include <log4cxx/pattern/datepatternconverter.h>
+#include <log4cxx/pattern/filedatepatternconverter.h>
+#include <log4cxx/pattern/filelocationpatternconverter.h>
+#include <log4cxx/pattern/fulllocationpatternconverter.h>
+#include <log4cxx/pattern/integerpatternconverter.h>
+#include <log4cxx/pattern/linelocationpatternconverter.h>
+#include <log4cxx/pattern/messagepatternconverter.h>
+#include <log4cxx/pattern/lineseparatorpatternconverter.h>
+#include <log4cxx/pattern/methodlocationpatternconverter.h>
+#include <log4cxx/pattern/levelpatternconverter.h>
+#include <log4cxx/pattern/relativetimepatternconverter.h>
+#include <log4cxx/pattern/threadpatternconverter.h>
+#include <log4cxx/pattern/ndcpatternconverter.h>
+#include <log4cxx/pattern/propertiespatternconverter.h>
+#include <log4cxx/pattern/throwableinformationpatternconverter.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+using namespace log4cxx::pattern;
+
+IMPLEMENT_LOG4CXX_OBJECT(PatternLayout)
+
+
+PatternLayout::PatternLayout()
+{
+}
+
+/**
+Constructs a PatternLayout using the supplied conversion pattern.
+*/
+PatternLayout::PatternLayout(const LogString& pattern)
+ : conversionPattern(pattern) {
+ Pool pool;
+ activateOptions(pool);
+}
+
+void PatternLayout::setConversionPattern(const LogString& pattern)
+{
+ conversionPattern = pattern;
+ Pool pool;
+ activateOptions(pool);
+}
+
+void PatternLayout::format(LogString& output,
+ const spi::LoggingEventPtr& event,
+ Pool& pool) const
+{
+ std::vector<FormattingInfoPtr>::const_iterator formatterIter =
+ patternFields.begin();
+ for(std::vector<LoggingEventPatternConverterPtr>::const_iterator
+ converterIter = patternConverters.begin();
+ converterIter != patternConverters.end();
+ converterIter++, formatterIter++) {
+ int startField = output.length();
+ (*converterIter)->format(event, output, pool);
+ (*formatterIter)->format(startField, output);
+ }
+
+}
+
+void PatternLayout::setOption(const LogString& option, const LogString& value)
+{
+ if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("CONVERSIONPATTERN"),
+ LOG4CXX_STR("conversionpattern")))
+ {
+ conversionPattern = OptionConverter::convertSpecialChars(value);
+ }
+}
+
+void PatternLayout::activateOptions(Pool&)
+{
+ LogString pat(conversionPattern);
+ if (pat.empty()) {
+ pat = LOG4CXX_STR("%m%n");
+ }
+ patternConverters.erase(patternConverters.begin(), patternConverters.end());
+ patternFields.erase(patternFields.begin(), patternFields.end());
+ std::vector<PatternConverterPtr> converters;
+ PatternParser::parse(pat,
+ converters,
+ patternFields,
+ getFormatSpecifiers());
+
+ //
+ // strip out any pattern converters that don't handle LoggingEvents
+ //
+ //
+ for(std::vector<PatternConverterPtr>::const_iterator converterIter = converters.begin();
+ converterIter != converters.end();
+ converterIter++) {
+ LoggingEventPatternConverterPtr eventConverter(*converterIter);
+ if (eventConverter != NULL) {
+ patternConverters.push_back(eventConverter);
+ }
+ }
+}
+
+#define RULES_PUT(spec, cls) \
+specs.insert(PatternMap::value_type(LogString(LOG4CXX_STR(spec)), (PatternConstructor) cls ::newInstance))
+
+
+log4cxx::pattern::PatternMap PatternLayout::getFormatSpecifiers() {
+ PatternMap specs;
+ RULES_PUT("c", LoggerPatternConverter);
+ RULES_PUT("logger", LoggerPatternConverter);
+
+ RULES_PUT("C", ClassNamePatternConverter);
+ RULES_PUT("class", ClassNamePatternConverter);
+
+ RULES_PUT("d", DatePatternConverter);
+ RULES_PUT("date", DatePatternConverter);
+
+ RULES_PUT("F", FileLocationPatternConverter);
+ RULES_PUT("file", FileLocationPatternConverter);
+
+ RULES_PUT("l", FullLocationPatternConverter);
+
+ RULES_PUT("L", LineLocationPatternConverter);
+ RULES_PUT("line", LineLocationPatternConverter);
+
+ RULES_PUT("m", MessagePatternConverter);
+ RULES_PUT("message", MessagePatternConverter);
+
+ RULES_PUT("n", LineSeparatorPatternConverter);
+
+ RULES_PUT("M", MethodLocationPatternConverter);
+ RULES_PUT("method", MethodLocationPatternConverter);
+
+ RULES_PUT("p", LevelPatternConverter);
+ RULES_PUT("level", LevelPatternConverter);
+
+ RULES_PUT("r", RelativeTimePatternConverter);
+ RULES_PUT("relative", RelativeTimePatternConverter);
+
+ RULES_PUT("t", ThreadPatternConverter);
+ RULES_PUT("thread", ThreadPatternConverter);
+
+ RULES_PUT("x", NDCPatternConverter);
+ RULES_PUT("ndc", NDCPatternConverter);
+
+ RULES_PUT("X", PropertiesPatternConverter);
+ RULES_PUT("properties", PropertiesPatternConverter);
+
+ RULES_PUT("throwable", ThrowableInformationPatternConverter);
+ return specs;
+}
+
+
+
+
+
diff --git a/src/main/cpp/patternparser.cpp b/src/main/cpp/patternparser.cpp
new file mode 100644
index 0000000..7cf7df8
--- /dev/null
+++ b/src/main/cpp/patternparser.cpp
@@ -0,0 +1,341 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/pattern/patternparser.h>
+#include <log4cxx/pattern/literalpatternconverter.h>
+#include <log4cxx/helpers/loglog.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::helpers;
+
+const logchar PatternParser::ESCAPE_CHAR = 0x25; // '%'
+
+
+/**
+ * Private constructor.
+ */
+PatternParser::PatternParser() {
+}
+
+bool PatternParser::isUnicodeIdentifierStart(logchar ch) {
+ //
+ // greatly simplified version checks if
+ // character is USACII alpha or number
+ //
+ return (ch >= 0x41 /* 'A' */ && ch <= 0x5A /* 'Z' */) ||
+ (ch >= 0x61 /* 'a' */ && ch <= 0x7A /* 'z' */) ||
+ (ch >= 0x30 /* '0' */ && ch <= 0x39 /* '9' */);
+}
+
+bool PatternParser::isUnicodeIdentifierPart(logchar ch) {
+ //
+ // greatly simplified version checks if
+ // character is USACII alpha or number
+ //
+ return isUnicodeIdentifierStart(ch)
+ || (ch == 0x5F /* '_' */);
+}
+
+int PatternParser::extractConverter(
+ logchar lastChar, const LogString& pattern,
+ LogString::size_type i, LogString& convBuf,
+ LogString& currentLiteral) {
+ if (!convBuf.empty()) {
+ convBuf.erase(convBuf.begin(), convBuf.end());
+ }
+
+ // When this method is called, lastChar points to the first character of the
+ // conversion word. For example:
+ // For "%hello" lastChar = 'h'
+ // For "%-5hello" lastChar = 'h'
+ //System.out.println("lastchar is "+lastChar);
+ if (!isUnicodeIdentifierStart(lastChar)) {
+ return i;
+ }
+
+ convBuf.append(1, lastChar);
+
+ while (
+ (i < pattern.length())
+ && isUnicodeIdentifierPart(pattern[i])) {
+ convBuf.append(1, pattern[i]);
+ currentLiteral.append(1, pattern[i]);
+
+ //System.out.println("conv buffer is now ["+convBuf+"].");
+ i++;
+ }
+
+ return i;
+}
+
+
+int PatternParser::extractOptions(const LogString& pattern, LogString::size_type i,
+ std::vector<LogString>& options) {
+ while ((i < pattern.length()) && (pattern[i] == 0x7B /* '{' */)) {
+ int end = pattern.find(0x7D /* '}' */, i);
+
+ if (end == -1) {
+ break;
+ }
+
+ LogString r(pattern.substr(i + 1, end - i - 1));
+ options.push_back(r);
+ i = end + 1;
+ }
+
+ return i;
+}
+
+void PatternParser::parse(
+ const LogString& pattern,
+ std::vector<PatternConverterPtr>& patternConverters,
+ std::vector<FormattingInfoPtr>& formattingInfos,
+ const PatternMap& rules) {
+
+ LogString currentLiteral;
+
+ int patternLength = pattern.length();
+ int state = LITERAL_STATE;
+ logchar c;
+ int i = 0;
+ FormattingInfoPtr formattingInfo(FormattingInfo::getDefault());
+
+ while (i < patternLength) {
+ c = pattern[i++];
+
+ switch (state) {
+ case LITERAL_STATE:
+
+ // In literal state, the last char is always a literal.
+ if (i == patternLength) {
+ currentLiteral.append(1, c);
+
+ continue;
+ }
+
+ if (c == ESCAPE_CHAR) {
+ // peek at the next char.
+ if(pattern[i] == ESCAPE_CHAR) {
+ currentLiteral.append(1, c);
+ i++; // move pointer
+ } else {
+ if (!currentLiteral.empty()) {
+ patternConverters.push_back(
+ LiteralPatternConverter::newInstance(currentLiteral));
+ formattingInfos.push_back(FormattingInfo::getDefault());
+ currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
+ }
+
+ currentLiteral.append(1, c); // append %
+ state = CONVERTER_STATE;
+ formattingInfo = FormattingInfo::getDefault();
+ }
+ } else {
+ currentLiteral.append(1, c);
+ }
+
+ break;
+
+ case CONVERTER_STATE:
+ currentLiteral.append(1, c);
+
+ switch (c) {
+ case 0x2D: // '-'
+ formattingInfo =
+ new FormattingInfo(
+ true, formattingInfo->getMinLength(),
+ formattingInfo->getMaxLength());
+
+ break;
+
+ case 0x2E: // '.'
+ state = DOT_STATE;
+
+ break;
+
+ default:
+
+ if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */)) {
+ formattingInfo =
+ new FormattingInfo(
+ formattingInfo->isLeftAligned(), c - 0x30 /* '0' */,
+ formattingInfo->getMaxLength());
+ state = MIN_STATE;
+ } else {
+ i = finalizeConverter(
+ c, pattern, i, currentLiteral, formattingInfo,
+ rules, patternConverters, formattingInfos);
+
+ // Next pattern is assumed to be a literal.
+ state = LITERAL_STATE;
+ formattingInfo = FormattingInfo::getDefault();
+ if (!currentLiteral.empty()) {
+ currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
+ }
+ }
+ } // switch
+
+ break;
+
+ case MIN_STATE:
+ currentLiteral.append(1, c);
+
+ if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */)) {
+ formattingInfo =
+ new FormattingInfo(
+ formattingInfo->isLeftAligned(),
+ (formattingInfo->getMinLength() * 10) + (c - 0x30 /* '0' */),
+ formattingInfo->getMaxLength());
+ } else if (c == 0x2E /* '.' */) {
+ state = DOT_STATE;
+ } else {
+ i = finalizeConverter(
+ c, pattern, i, currentLiteral, formattingInfo,
+ rules, patternConverters, formattingInfos);
+ state = LITERAL_STATE;
+ formattingInfo = FormattingInfo::getDefault();
+ if (!currentLiteral.empty()) {
+ currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
+ }
+ }
+
+ break;
+
+ case DOT_STATE:
+ currentLiteral.append(1, c);
+
+ if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */)) {
+ formattingInfo =
+ new FormattingInfo(
+ formattingInfo->isLeftAligned(), formattingInfo->getMinLength(),
+ c - 0x30 /* '0' */);
+ state = MAX_STATE;
+ } else {
+ LogLog::error(LOG4CXX_STR("Error in pattern, was expecting digit."));
+
+ state = LITERAL_STATE;
+ }
+
+ break;
+
+ case MAX_STATE:
+ currentLiteral.append(1, c);
+
+ if ((c >= 0x30 /* '0' */) && (c <= 0x39 /* '9' */)) {
+ formattingInfo =
+ new FormattingInfo(
+ formattingInfo->isLeftAligned(), formattingInfo->getMinLength(),
+ (formattingInfo->getMaxLength() * 10) + (c - 0x30 /* '0' */));
+ } else {
+ i = finalizeConverter(
+ c, pattern, i, currentLiteral, formattingInfo,
+ rules, patternConverters, formattingInfos);
+ state = LITERAL_STATE;
+ formattingInfo = FormattingInfo::getDefault();
+ if (!currentLiteral.empty()) {
+ currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
+ }
+ }
+
+ break;
+ } // switch
+ }
+
+ // while
+ if (currentLiteral.length() != 0) {
+ patternConverters.push_back(
+ LiteralPatternConverter::newInstance(currentLiteral));
+ formattingInfos.push_back(FormattingInfo::getDefault());
+ }
+}
+
+
+PatternConverterPtr PatternParser::createConverter(
+ const LogString& converterId,
+ LogString& currentLiteral,
+ const PatternMap& rules,
+ std::vector<LogString>& options) {
+
+ LogString converterName(converterId);
+
+ for (int i = converterId.length(); i > 0; i--) {
+ converterName = converterName.substr(0, i);
+ PatternMap::const_iterator iter = rules.find(converterName);
+ if (iter != rules.end()) {
+ currentLiteral.erase(currentLiteral.begin(),
+ currentLiteral.end() - (converterId.length() - i));
+ return (iter->second)(options);
+ }
+ }
+
+ LogLog::error(LogString(LOG4CXX_STR("Unrecognized format specifier ")) + converterId);
+ ObjectPtr converterObj;
+
+ return converterObj;
+}
+
+int PatternParser::finalizeConverter(
+ logchar c, const LogString& pattern, int i,
+ LogString& currentLiteral, const FormattingInfoPtr& formattingInfo,
+ const PatternMap& rules,
+ std::vector<PatternConverterPtr>& patternConverters,
+ std::vector<FormattingInfoPtr>& formattingInfos) {
+ LogString convBuf;
+ i = extractConverter(c, pattern, i, convBuf, currentLiteral);
+ if (convBuf.empty()) {
+ LogLog::error(LOG4CXX_STR("Empty conversion specifier"));
+ patternConverters.push_back(
+ LiteralPatternConverter::newInstance(currentLiteral));
+ formattingInfos.push_back(FormattingInfo::getDefault());
+ } else {
+ LogString converterId(convBuf);
+
+ std::vector<LogString> options;
+ i = extractOptions(pattern, i, options);
+
+ PatternConverterPtr pc(
+ createConverter(
+ converterId, currentLiteral, rules, options));
+
+ if (pc == NULL) {
+ LogString msg(LOG4CXX_STR("Unrecognized conversion specifier ["));
+ msg.append(converterId);
+ msg.append(LOG4CXX_STR("] in conversion pattern."));
+ LogLog::error(msg);
+ patternConverters.push_back(
+ LiteralPatternConverter::newInstance(currentLiteral));
+ formattingInfos.push_back(FormattingInfo::getDefault());
+ } else {
+ patternConverters.push_back(pc);
+ formattingInfos.push_back(formattingInfo);
+
+ if (currentLiteral.length() > 0) {
+ patternConverters.push_back(
+ LiteralPatternConverter::newInstance(currentLiteral));
+ formattingInfos.push_back(FormattingInfo::getDefault());
+ }
+ }
+ }
+
+ if (!currentLiteral.empty()) {
+ currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
+ }
+
+ return i;
+}
diff --git a/src/main/cpp/pool.cpp b/src/main/cpp/pool.cpp
new file mode 100755
index 0000000..f2e5615
--- /dev/null
+++ b/src/main/cpp/pool.cpp
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/pool.h>
+#include <apr_strings.h>
+#include <log4cxx/helpers/exception.h>
+#include <apr_pools.h>
+#include <assert.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/helpers/aprinitializer.h>
+
+using namespace log4cxx::helpers;
+using namespace log4cxx;
+
+
+Pool::Pool() : pool(0), release(true) {
+ apr_status_t stat = apr_pool_create(&pool, APRInitializer::getRootPool());
+ if (stat != APR_SUCCESS) {
+ throw PoolException(stat);
+ }
+}
+
+Pool::Pool(apr_pool_t* p, bool release1) : pool(p), release(release1) {
+ assert(p != NULL);
+}
+
+Pool::~Pool() {
+ if (release) {
+ apr_pool_destroy(pool);
+ }
+}
+
+
+apr_pool_t* Pool::getAPRPool() {
+ return pool;
+}
+
+apr_pool_t* Pool::create() {
+ apr_pool_t* child;
+ apr_status_t stat = apr_pool_create(&child, pool);
+ if (stat != APR_SUCCESS) {
+ throw PoolException(stat);
+ }
+ return child;
+}
+
+void* Pool::palloc(size_t size) {
+ return apr_palloc(pool, size);
+}
+
+char* Pool::pstralloc(size_t size) {
+ return (char*) palloc(size);
+}
+
+char* Pool::itoa(int n) {
+ return apr_itoa(pool, n);
+}
+
+char* Pool::pstrndup(const char* s, size_t len) {
+ return apr_pstrndup(pool, s, len);
+}
+
+char* Pool::pstrdup(const char* s) {
+ return apr_pstrdup(pool, s);
+}
+
+char* Pool::pstrdup(const std::string& s) {
+ return apr_pstrndup(pool, s.data(), s.length());
+}
diff --git a/src/main/cpp/properties.cpp b/src/main/cpp/properties.cpp
new file mode 100644
index 0000000..db6a1cb
--- /dev/null
+++ b/src/main/cpp/properties.cpp
@@ -0,0 +1,370 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/properties.h>
+#include <log4cxx/helpers/inputstreamreader.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/pool.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+class PropertyParser
+{
+public:
+ void parse(LogString& in, Properties& properties)
+ {
+ LogString key, element;
+ LexemType lexemType = BEGIN;
+ logchar c;
+ bool finished = false;
+
+ if (!get(in, c))
+ {
+ return;
+ }
+
+ while (!finished)
+ {
+ switch(lexemType)
+ {
+ case BEGIN:
+ switch(c)
+ {
+ case 0x20: // ' '
+ case 0x08: // '\t'
+ case 0x0A: // '\n'
+ case 0x0D: // '\r'
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ case 0x23: // '#'
+ case 0x21: // '!'
+ lexemType = COMMENT;
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ default:
+ lexemType = KEY;
+ break;
+ }
+ break;
+
+ case KEY:
+ switch(c)
+ {
+ case 0x5C: // '\\'
+ lexemType = KEY_ESCAPE;
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ case 0x08: // '\t'
+ case 0x20: // ' '
+ case 0x3A: // ':'
+ case 0x3D: // '='
+ lexemType = DELIMITER;
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ case 0x0A:
+ case 0x0D:
+ // key associated with an empty string element
+ properties.setProperty(key, LogString());
+ key.erase(key.begin(), key.end());
+ lexemType = BEGIN;
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ default:
+ key.append(1, c);
+ if (!get(in, c))
+ finished = true;
+ break;
+ }
+ break;
+
+ case KEY_ESCAPE:
+ switch(c)
+ {
+ case 0x08: // '\t'
+ case 0x20: // ' '
+ case 0x3A: // ':'
+ case 0x3D: // '='
+ case 0x5C: // '\\'
+ key.append(1, c);
+ lexemType = KEY;
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ case 0x0A: // '\n'
+ lexemType = KEY_CONTINUE;
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ case 0x0D: // '\r'
+ lexemType = KEY_CONTINUE2;
+ if (!get(in, c))
+ finished = true;
+ break;
+ }
+ break;
+
+ case KEY_CONTINUE:
+ switch(c)
+ {
+ case 0x20: // ' '
+ case 0x08: // '\t'
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ default:
+ lexemType = KEY;
+ break;
+ }
+ break;
+
+ case KEY_CONTINUE2:
+ switch(c)
+ {
+ case 0x0A: // '\n'
+ if (!get(in, c))
+ finished = true;
+ lexemType = KEY_CONTINUE;
+ break;
+
+ default:
+ lexemType = KEY_CONTINUE;
+ break;
+ }
+ break;
+
+ case DELIMITER:
+ switch(c)
+ {
+ case 0x08: // '\t'
+ case 0x20: // ' '
+ case 0x3A: // ':'
+ case 0x3D: // '='
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ default:
+ lexemType = ELEMENT;
+ break;
+ }
+ break;
+
+ case ELEMENT:
+ switch(c)
+ {
+ case 0x5C: // '\\'
+ lexemType = ELEMENT_ESCAPE;
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ case 0x0A: // '\n'
+ case 0x0D: // '\r'
+ // key associated with an empty string element
+ properties.setProperty(key, element);
+ key.erase(key.begin(), key.end());
+ element.erase(element.begin(), element.end());
+ lexemType = BEGIN;
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ default:
+ element.append(1, c);
+ if (!get(in, c))
+ finished = true;
+ break;
+ }
+ break;
+
+ case ELEMENT_ESCAPE:
+ switch(c)
+ {
+ case 0x08: // '\t'
+ case 0x20: // ' '
+ case 0x6E: // 'n'
+ case 0x72: // 'r'
+ case 0x27: // '\''
+ case 0x5C: // '\\'
+ case 0x22: // '\"'
+ case 0x3A: // ':'
+ default:
+ element.append(1, c);
+ lexemType = ELEMENT;
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ case 0x0A: // '\n'
+ lexemType = ELEMENT_CONTINUE;
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ case 0x0D: // '\r'
+ lexemType = ELEMENT_CONTINUE2;
+ if (!get(in, c))
+ finished = true;
+ break;
+ }
+ break;
+
+ case ELEMENT_CONTINUE:
+ switch(c)
+ {
+ case 0x20: // ' '
+ case 0x08: // '\t'
+ if (!get(in, c))
+ finished = true;
+ break;
+
+ default:
+ lexemType = ELEMENT;
+ break;
+ }
+ break;
+
+ case ELEMENT_CONTINUE2:
+ switch(c)
+ {
+ case 0x20: // '\n'
+ if (!get(in, c))
+ finished = true;
+ lexemType = ELEMENT_CONTINUE;
+ break;
+
+ default:
+ lexemType = ELEMENT_CONTINUE;
+ break;
+ }
+ break;
+
+ case COMMENT:
+ if (c == 0x0A || c == 0x0D)
+ {
+ lexemType = BEGIN;
+ }
+ if (!get(in, c))
+ finished = true;
+ break;
+ }
+ }
+
+ if (!key.empty())
+ {
+ properties.setProperty(key, element);
+ }
+ }
+
+protected:
+ bool get(LogString& in, logchar& c)
+ {
+ if (in.empty()) {
+ c = 0;
+ return false;
+ }
+ c = in[0];
+ in.erase(in.begin());
+ return true;
+ }
+
+ typedef enum
+ {
+ BEGIN,
+ KEY,
+ KEY_ESCAPE,
+ KEY_CONTINUE,
+ KEY_CONTINUE2,
+ DELIMITER,
+ ELEMENT,
+ ELEMENT_ESCAPE,
+ ELEMENT_CONTINUE,
+ ELEMENT_CONTINUE2,
+ COMMENT
+ }
+ LexemType;
+};
+
+Properties::Properties() : properties(new PropertyMap()) {
+}
+
+Properties::~Properties() {
+ delete properties;
+}
+
+LogString Properties::setProperty(const LogString& key, const LogString& value) {
+ return put(key, value);
+}
+
+LogString Properties::put(const LogString& key, const LogString& value)
+{
+ LogString oldValue((*properties)[key]);
+ (*properties)[key] = value;
+ //tcout << ASCII_STR("setting property key=") << key << ASCII_STR(", value=") << value << std::endl;
+ return oldValue;
+}
+
+LogString Properties::getProperty(const LogString& key) const {
+ return get(key);
+}
+
+LogString Properties::get(const LogString& key) const
+{
+ PropertyMap::const_iterator it = properties->find(key);
+ return (it != properties->end()) ? it->second : LogString();
+}
+
+void Properties::load(InputStreamPtr inStream) {
+ Pool pool;
+ InputStreamReaderPtr lineReader(
+ new InputStreamReader(inStream, CharsetDecoder::getISOLatinDecoder()));
+ LogString contents = lineReader->read(pool);
+ properties->clear();
+ PropertyParser parser;
+ parser.parse(contents, *this);
+}
+
+std::vector<LogString> Properties::propertyNames() const
+{
+ std::vector<LogString> names;
+ names.reserve(properties->size());
+
+ PropertyMap::const_iterator it;
+ for (it = properties->begin(); it != properties->end(); it++)
+ {
+ const LogString& key = it->first;
+ names.push_back(key);
+ }
+
+ return names;
+}
+
diff --git a/src/main/cpp/propertiespatternconverter.cpp b/src/main/cpp/propertiespatternconverter.cpp
new file mode 100644
index 0000000..5cf281c
--- /dev/null
+++ b/src/main/cpp/propertiespatternconverter.cpp
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/propertiespatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(PropertiesPatternConverter)
+
+PropertiesPatternConverter::PropertiesPatternConverter(const LogString& name1,
+ const LogString& propertyName) :
+ LoggingEventPatternConverter(name1,LOG4CXX_STR("property")),
+ option(propertyName) {
+}
+
+PatternConverterPtr PropertiesPatternConverter::newInstance(
+ const std::vector<LogString>& options) {
+ if (options.size() == 0) {
+ static PatternConverterPtr def(new PropertiesPatternConverter(
+ LOG4CXX_STR("Properties"), LOG4CXX_STR("")));
+ return def;
+ }
+ LogString converterName(LOG4CXX_STR("Property{"));
+ converterName.append(options[0]);
+ converterName.append(LOG4CXX_STR("}"));
+ PatternConverterPtr converter(new PropertiesPatternConverter(
+ converterName, options[0]));
+ return converter;
+}
+
+void PropertiesPatternConverter::format(
+ const LoggingEventPtr& event,
+ LogString& toAppendTo,
+ Pool& /* p */) const {
+ if (option.length() == 0) {
+ toAppendTo.append(1, (logchar) 0x7B /* '{' */);
+
+ LoggingEvent::KeySet keySet(event->getMDCKeySet());
+
+ for(LoggingEvent::KeySet::const_iterator iter = keySet.begin();
+ iter != keySet.end();
+ iter++) {
+ toAppendTo.append(1, (logchar) 0x7B /* '{' */);
+ toAppendTo.append(*iter);
+ toAppendTo.append(1, (logchar) 0x2C /* ',' */);
+ event->getMDC(*iter, toAppendTo);
+ toAppendTo.append(1, (logchar) 0x7D /* '}' */);
+ }
+
+ toAppendTo.append(1, (logchar) 0x7D /* '}' */);
+
+ } else {
+ event->getMDC(option, toAppendTo);
+ }
+ }
+
diff --git a/src/main/cpp/propertyconfigurator.cpp b/src/main/cpp/propertyconfigurator.cpp
new file mode 100644
index 0000000..d0950b8
--- /dev/null
+++ b/src/main/cpp/propertyconfigurator.cpp
@@ -0,0 +1,451 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/propertyconfigurator.h>
+#include <log4cxx/spi/loggerfactory.h>
+#include <log4cxx/helpers/properties.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/level.h>
+#include <log4cxx/defaultloggerfactory.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/appender.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/layout.h>
+#include <log4cxx/config/propertysetter.h>
+#include <log4cxx/spi/loggerrepository.h>
+#include <log4cxx/helpers/stringtokenizer.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <apr_file_io.h>
+#include <apr_file_info.h>
+#include <apr_pools.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/fileinputstream.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+using namespace log4cxx::config;
+
+
+#if APR_HAS_THREADS
+#include <log4cxx/helpers/filewatchdog.h>
+
+class PropertyWatchdog : public FileWatchdog
+{
+public:
+ PropertyWatchdog(const File& filename) : FileWatchdog(filename)
+ {
+ }
+
+ /**
+ Call PropertyConfigurator#doConfigure(const String& configFileName,
+ const spi::LoggerRepositoryPtr& hierarchy) with the
+ <code>filename</code> to reconfigure log4cxx.
+ */
+ void doOnChange()
+ {
+ PropertyConfigurator().doConfigure(file,
+ LogManager::getLoggerRepository());
+ }
+};
+#endif
+
+IMPLEMENT_LOG4CXX_OBJECT(PropertyConfigurator)
+
+
+
+PropertyConfigurator::PropertyConfigurator()
+: registry(new std::map<LogString, AppenderPtr>()), loggerFactory(new DefaultLoggerFactory())
+{
+}
+
+PropertyConfigurator::~PropertyConfigurator() {
+ delete registry;
+}
+
+void PropertyConfigurator::addRef() const {
+ ObjectImpl::addRef();
+}
+
+void PropertyConfigurator::releaseRef() const {
+ ObjectImpl::releaseRef();
+}
+
+void PropertyConfigurator::doConfigure(const File& configFileName,
+ spi::LoggerRepositoryPtr& hierarchy)
+{
+ hierarchy->setConfigured(true);
+
+ Properties props;
+ try {
+ InputStreamPtr inputStream = new FileInputStream(configFileName);
+ props.load(inputStream);
+ } catch(const IOException& ie) {
+ LogLog::error(((LogString) LOG4CXX_STR("Could not read configuration file ["))
+ + configFileName.getPath() + LOG4CXX_STR("]."));
+ return;
+ }
+
+ try {
+ doConfigure(props, hierarchy);
+ } catch(const std::exception& ex) {
+ LogLog::error(((LogString) LOG4CXX_STR("Could not parse configuration file ["))
+ + configFileName.getPath() + LOG4CXX_STR("]."), ex);
+ }
+}
+
+void PropertyConfigurator::configure(const File& configFilename)
+{
+ PropertyConfigurator().doConfigure(configFilename, LogManager::getLoggerRepository());
+}
+
+void PropertyConfigurator::configure(helpers::Properties& properties)
+{
+ PropertyConfigurator().doConfigure(properties, LogManager::getLoggerRepository());
+}
+
+#if APR_HAS_THREADS
+void PropertyConfigurator::configureAndWatch(const File& configFilename)
+{
+ configureAndWatch(configFilename, FileWatchdog::DEFAULT_DELAY);
+}
+
+
+
+void PropertyConfigurator::configureAndWatch(
+ const File& configFilename, long delay)
+{
+ PropertyWatchdog * pdog = new PropertyWatchdog(configFilename);
+ pdog->setDelay(delay);
+ pdog->start();
+}
+#endif
+
+void PropertyConfigurator::doConfigure(helpers::Properties& properties,
+ spi::LoggerRepositoryPtr& hierarchy)
+{
+ hierarchy->setConfigured(true);
+
+ static const LogString DEBUG_KEY(LOG4CXX_STR("log4j.debug"));
+ LogString value(properties.getProperty(DEBUG_KEY));
+
+ if (!value.empty())
+ {
+ LogLog::setInternalDebugging(OptionConverter::toBoolean(value, true));
+ }
+
+ static const LogString THRESHOLD_PREFIX(LOG4CXX_STR("log4j.threshold"));
+ LogString thresholdStr =
+ OptionConverter::findAndSubst(THRESHOLD_PREFIX, properties);
+
+ if (!thresholdStr.empty())
+ {
+ hierarchy->setThreshold(OptionConverter::toLevel(thresholdStr, Level::getAll()));
+ LogLog::debug(((LogString) LOG4CXX_STR("Hierarchy threshold set to ["))
+ + hierarchy->getThreshold()->toString()
+ + LOG4CXX_STR("]."));
+ }
+
+ configureRootLogger(properties, hierarchy);
+ configureLoggerFactory(properties);
+ parseCatsAndRenderers(properties, hierarchy);
+
+ LogLog::debug(LOG4CXX_STR("Finished configuring."));
+
+ // We don't want to hold references to appenders preventing their
+ // destruction.
+ registry->clear();
+}
+
+void PropertyConfigurator::configureLoggerFactory(helpers::Properties& props)
+{
+ static const LogString LOGGER_FACTORY_KEY(LOG4CXX_STR("log4j.loggerFactory"));
+
+ LogString factoryClassName =
+ OptionConverter::findAndSubst(LOGGER_FACTORY_KEY, props);
+
+ if (!factoryClassName.empty())
+ {
+ LogString msg(LOG4CXX_STR("Setting logger factory to ["));
+ msg += factoryClassName;
+ msg += LOG4CXX_STR("].");
+ LogLog::debug(msg);
+ loggerFactory =
+ OptionConverter::instantiateByClassName(
+ factoryClassName, LoggerFactory::getStaticClass(), loggerFactory);
+ static const LogString FACTORY_PREFIX(LOG4CXX_STR("log4j.factory."));
+ Pool p;
+ PropertySetter::setProperties(loggerFactory, props, FACTORY_PREFIX, p);
+ }
+}
+
+void PropertyConfigurator::configureRootLogger(helpers::Properties& props,
+ spi::LoggerRepositoryPtr& hierarchy)
+{
+ static const LogString ROOT_CATEGORY_PREFIX(LOG4CXX_STR("log4j.rootCategory"));
+ static const LogString ROOT_LOGGER_PREFIX(LOG4CXX_STR("log4j.rootLogger"));
+
+
+
+ LogString effectiveFrefix(ROOT_LOGGER_PREFIX);
+ LogString value = OptionConverter::findAndSubst(ROOT_LOGGER_PREFIX, props);
+
+ if (value.empty())
+ {
+ value = OptionConverter::findAndSubst(ROOT_CATEGORY_PREFIX, props);
+ effectiveFrefix = ROOT_CATEGORY_PREFIX;
+ }
+
+ if (value.empty())
+ {
+ LogLog::debug(LOG4CXX_STR("Could not find root logger information. Is this OK?"));
+ }
+ else
+ {
+ LoggerPtr root = hierarchy->getRootLogger();
+
+ synchronized sync(root->getMutex());
+ static const LogString INTERNAL_ROOT_NAME(LOG4CXX_STR("root"));
+ parseLogger(props, root, effectiveFrefix, INTERNAL_ROOT_NAME, value);
+ }
+}
+
+void PropertyConfigurator::parseCatsAndRenderers(helpers::Properties& props,
+ spi::LoggerRepositoryPtr& hierarchy)
+{
+ static const LogString CATEGORY_PREFIX(LOG4CXX_STR("log4j.category."));
+ static const LogString LOGGER_PREFIX(LOG4CXX_STR("log4j.logger."));
+
+ std::vector<LogString> names = props.propertyNames();
+
+ std::vector<LogString>::iterator it = names.begin();
+ std::vector<LogString>::iterator itEnd = names.end();
+ while (it != itEnd)
+ {
+ LogString key = *it++;
+
+ if (key.find(CATEGORY_PREFIX) == 0 || key.find(LOGGER_PREFIX) == 0)
+ {
+ LogString loggerName;
+
+ if (key.find(CATEGORY_PREFIX) == 0)
+ {
+ loggerName = key.substr(CATEGORY_PREFIX.length());
+ }
+ else if (key.find(LOGGER_PREFIX) == 0)
+ {
+ loggerName = key.substr(LOGGER_PREFIX.length());
+ }
+
+ LogString value = OptionConverter::findAndSubst(key, props);
+ LoggerPtr logger = hierarchy->getLogger(loggerName, loggerFactory);
+
+ synchronized sync(logger->getMutex());
+ parseLogger(props, logger, key, loggerName, value);
+ parseAdditivityForLogger(props, logger, loggerName);
+ }
+ }
+}
+
+void PropertyConfigurator::parseAdditivityForLogger(helpers::Properties& props,
+ LoggerPtr& cat, const LogString& loggerName)
+{
+
+ static const LogString ADDITIVITY_PREFIX(LOG4CXX_STR("log4j.additivity."));
+
+
+
+ LogString value(OptionConverter::findAndSubst(ADDITIVITY_PREFIX + loggerName, props));
+ LogLog::debug((LogString) LOG4CXX_STR("Handling ") + ADDITIVITY_PREFIX
+ + loggerName + LOG4CXX_STR("=[") + value + LOG4CXX_STR("]"));
+
+ // touch additivity only if necessary
+ if (!value.empty())
+ {
+ bool additivity = OptionConverter::toBoolean(value, true);
+ LogLog::debug(((LogString) LOG4CXX_STR("Setting additivity for \""))
+ + loggerName
+ + ((additivity) ? LOG4CXX_STR("\" to true") :
+ LOG4CXX_STR("\" to false")));
+ cat->setAdditivity(additivity);
+ }
+}
+
+/**
+ This method must work for the root logger as well.
+*/
+void PropertyConfigurator::parseLogger(
+ helpers::Properties& props, LoggerPtr& logger, const LogString& /* optionKey */,
+ const LogString& loggerName, const LogString& value)
+{
+ LogLog::debug(((LogString) LOG4CXX_STR("Parsing for ["))
+ + loggerName
+ + LOG4CXX_STR("] with value=[")
+ + value + LOG4CXX_STR("]."));
+
+ // We must skip over ',' but not white space
+ StringTokenizer st(value, LOG4CXX_STR(","));
+
+ // If value is not in the form ", appender.." or "", then we should set
+ // the level of the logger.
+ if (!(value.find(LOG4CXX_STR(",")) == 0 || value.empty()))
+ {
+ // just to be on the safe side...
+ if (!st.hasMoreTokens())
+ {
+ return;
+ }
+
+ LogString levelStr = st.nextToken();
+ LogLog::debug((LogString) LOG4CXX_STR("Level token is [")
+ + levelStr + LOG4CXX_STR("]."));
+
+
+ // If the level value is inherited, set logger level value to
+ // null. We also check that the user has not specified inherited for the
+ // root logger.
+ if (StringHelper::equalsIgnoreCase(levelStr, LOG4CXX_STR("INHERITED"), LOG4CXX_STR("inherited"))
+ || StringHelper::equalsIgnoreCase(levelStr, LOG4CXX_STR("NULL"), LOG4CXX_STR("null")))
+ {
+ static const LogString INTERNAL_ROOT_NAME(LOG4CXX_STR("root"));
+ if (loggerName == INTERNAL_ROOT_NAME)
+ {
+ LogLog::warn(LOG4CXX_STR("The root logger cannot be set to null."));
+ }
+ else
+ {
+ logger->setLevel(0);
+ LogLog::debug((LogString) LOG4CXX_STR("Logger ")
+ + loggerName + LOG4CXX_STR(" set to null"));
+ }
+ }
+ else
+ {
+ logger->setLevel(OptionConverter::toLevel(levelStr, Level::getDebug()));
+
+ LogLog::debug((LogString) LOG4CXX_STR("Logger ")
+ + loggerName + LOG4CXX_STR(" set to ")
+ + logger->getLevel()->toString());
+ }
+
+ }
+
+ // Begin by removing all existing appenders.
+ logger->removeAllAppenders();
+
+ AppenderPtr appender;
+ LogString appenderName;
+
+ while (st.hasMoreTokens())
+ {
+ appenderName = StringHelper::trim(st.nextToken());
+
+ if (appenderName.empty() || appenderName == LOG4CXX_STR(","))
+ {
+ continue;
+ }
+
+ LogLog::debug(LOG4CXX_STR("Parsing appender named ")
+ + appenderName + LOG4CXX_STR("\"."));
+ appender = parseAppender(props, appenderName);
+
+ if (appender != 0)
+ {
+ logger->addAppender(appender);
+ }
+ }
+}
+
+AppenderPtr PropertyConfigurator::parseAppender(
+ helpers::Properties& props, const LogString& appenderName)
+{
+ AppenderPtr appender = registryGet(appenderName);
+
+ if (appender != 0)
+ {
+ LogLog::debug((LogString) LOG4CXX_STR("Appender \"")
+ + appenderName + LOG4CXX_STR("\" was already parsed."));
+
+ return appender;
+ }
+
+ static const LogString APPENDER_PREFIX(LOG4CXX_STR("log4j.appender."));
+
+ // Appender was not previously initialized.
+ LogString prefix = APPENDER_PREFIX + appenderName;
+ LogString layoutPrefix = prefix + LOG4CXX_STR(".layout");
+
+ appender =
+ OptionConverter::instantiateByKey(
+ props, prefix, Appender::getStaticClass(), 0);
+
+ if (appender == 0)
+ {
+ LogLog::error((LogString) LOG4CXX_STR("Could not instantiate appender named \"")
+ + appenderName + LOG4CXX_STR("\"."));
+ return 0;
+ }
+
+ appender->setName(appenderName);
+
+ if (appender->instanceof(OptionHandler::getStaticClass()))
+ {
+ Pool p;
+ if (appender->requiresLayout())
+ {
+ LayoutPtr layout =
+ OptionConverter::instantiateByKey(
+ props, layoutPrefix, Layout::getStaticClass(), 0);
+
+ if (layout != 0)
+ {
+ appender->setLayout(layout);
+ LogLog::debug((LogString) LOG4CXX_STR("Parsing layout options for \"")
+ + appenderName + LOG4CXX_STR("\"."));
+
+ //configureOptionHandler(layout, layoutPrefix + ".", props);
+ PropertySetter::setProperties(layout, props, layoutPrefix + LOG4CXX_STR("."), p);
+ LogLog::debug((LogString) LOG4CXX_STR("End of parsing for \"")
+ + appenderName + LOG4CXX_STR("\"."));
+ }
+ }
+
+ //configureOptionHandler((OptionHandler) appender, prefix + _T("."), props);
+ PropertySetter::setProperties(appender, props, prefix + LOG4CXX_STR("."), p);
+ LogLog::debug((LogString) LOG4CXX_STR("Parsed \"")
+ + appenderName + LOG4CXX_STR("\" options."));
+ }
+
+ registryPut(appender);
+
+ return appender;
+}
+
+void PropertyConfigurator::registryPut(const AppenderPtr& appender)
+{
+ (*registry)[appender->getName()] = appender;
+}
+
+AppenderPtr PropertyConfigurator::registryGet(const LogString& name)
+{
+ return (*registry)[name];
+}
diff --git a/src/main/cpp/propertyresourcebundle.cpp b/src/main/cpp/propertyresourcebundle.cpp
new file mode 100644
index 0000000..b6e5f64
--- /dev/null
+++ b/src/main/cpp/propertyresourcebundle.cpp
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/propertyresourcebundle.h>
+#include <log4cxx/helpers/exception.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(PropertyResourceBundle)
+
+
+PropertyResourceBundle::PropertyResourceBundle(InputStreamPtr inStream)
+{
+ properties.load(inStream);
+}
+
+LogString PropertyResourceBundle::getString(const LogString& key) const
+{
+ LogString resource;
+ PropertyResourceBundlePtr resourceBundle(const_cast<PropertyResourceBundle*>(this));
+
+ do
+ {
+ resource = resourceBundle->properties.getProperty(key);
+ if (!resource.empty())
+ {
+ return resource;
+ }
+
+ resourceBundle = resourceBundle->parent;
+ }
+ while (resourceBundle != 0);
+
+ throw MissingResourceException(key);
+#if LOG4CXX_RETURN_AFTER_THROW
+ return resource;
+#endif
+}
diff --git a/src/main/cpp/propertysetter.cpp b/src/main/cpp/propertysetter.cpp
new file mode 100644
index 0000000..88a6dd7
--- /dev/null
+++ b/src/main/cpp/propertysetter.cpp
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/config/propertysetter.h>
+#include <log4cxx/helpers/object.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/spi/optionhandler.h>
+#include <log4cxx/helpers/properties.h>
+#include <log4cxx/appender.h>
+#include <log4cxx/layout.h>
+#include <log4cxx/helpers/pool.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+using namespace log4cxx::config;
+
+PropertySetter::PropertySetter(const helpers::ObjectPtr& obj1) : obj(obj1)
+{
+}
+
+void PropertySetter::setProperties(const helpers::ObjectPtr& obj,
+ helpers::Properties& properties,
+ const LogString& prefix,
+ Pool& p)
+{
+ PropertySetter(obj).setProperties(properties, prefix, p);
+}
+
+
+void PropertySetter::setProperties(helpers::Properties& properties,
+ const LogString& prefix,
+ Pool& p)
+{
+ int len = prefix.length();
+
+ std::vector<LogString> names = properties.propertyNames();
+ std::vector<LogString>::iterator it;
+
+ for (it = names.begin(); it != names.end(); it++)
+ {
+ LogString key = *it;
+
+ // handle only properties that start with the desired frefix.
+ if (key.find(prefix) == 0)
+ {
+ // ignore key if it contains dots after the prefix
+ if (key.find(0x2E /* '.' */, len + 1) != LogString::npos)
+ {
+ continue;
+ }
+
+ LogString value = OptionConverter::findAndSubst(key, properties);
+ key = key.substr(len);
+ if (key == LOG4CXX_STR("layout")
+ && obj != 0
+ && obj->instanceof(Appender::getStaticClass()))
+ {
+ continue;
+ }
+ setProperty(key, value, p);
+ }
+ }
+ activate(p);
+}
+
+void PropertySetter::setProperty(const LogString& option,
+ const LogString& value,
+ Pool&)
+{
+ if (value.empty())
+ return;
+
+ if (obj != 0 && obj->instanceof(OptionHandler::getStaticClass()))
+ {
+ LogLog::debug(LOG4CXX_STR("Setting option name=[") +
+ option + LOG4CXX_STR("], value=[") + value + LOG4CXX_STR("]"));
+ OptionHandlerPtr(obj)->setOption(option, value);
+ }
+}
+
+void PropertySetter::activate(Pool& p)
+{
+ if (obj != 0 && obj->instanceof(OptionHandler::getStaticClass()))
+ {
+ OptionHandlerPtr(obj)->activateOptions(p);
+ }
+}
diff --git a/src/main/cpp/reader.cpp b/src/main/cpp/reader.cpp
new file mode 100644
index 0000000..ec53ef7
--- /dev/null
+++ b/src/main/cpp/reader.cpp
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/reader.h>
+
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(Reader)
+
+Reader::Reader() {
+}
+
+Reader::~Reader() {
+}
diff --git a/src/main/cpp/relativetimedateformat.cpp b/src/main/cpp/relativetimedateformat.cpp
new file mode 100644
index 0000000..2cce37a
--- /dev/null
+++ b/src/main/cpp/relativetimedateformat.cpp
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define __STDC_CONSTANT_MACROS
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/relativetimedateformat.h>
+#include <log4cxx/spi/loggingevent.h>
+
+#include <apr.h>
+#include <apr_time.h>
+#include <log4cxx/helpers/stringhelper.h>
+
+
+log4cxx::helpers::RelativeTimeDateFormat::RelativeTimeDateFormat()
+ : DateFormat(), startTime(log4cxx::spi::LoggingEvent::getStartTime())
+{
+}
+
+void log4cxx::helpers::RelativeTimeDateFormat::format(
+ LogString &s,
+ log4cxx_time_t date,
+ Pool& p) const {
+ log4cxx_int64_t interval = (date - startTime) / APR_INT64_C(1000);
+ StringHelper::toString(interval, p, s);
+}
diff --git a/src/main/cpp/relativetimepatternconverter.cpp b/src/main/cpp/relativetimepatternconverter.cpp
new file mode 100644
index 0000000..db7eaa6
--- /dev/null
+++ b/src/main/cpp/relativetimepatternconverter.cpp
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/relativetimepatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+#include <log4cxx/helpers/stringhelper.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(RelativeTimePatternConverter)
+
+RelativeTimePatternConverter::RelativeTimePatternConverter() :
+ LoggingEventPatternConverter(LOG4CXX_STR("Time"),
+ LOG4CXX_STR("time")) {
+}
+
+PatternConverterPtr RelativeTimePatternConverter::newInstance(
+ const std::vector<LogString>& /* options */) {
+ static PatternConverterPtr def(new RelativeTimePatternConverter());
+ return def;
+}
+
+void RelativeTimePatternConverter::format(
+ const LoggingEventPtr& event,
+ LogString& toAppendTo,
+ Pool& p) const {
+ log4cxx_time_t delta = (event->getTimeStamp() - LoggingEvent::getStartTime())/1000;
+ StringHelper::toString(delta, p, toAppendTo);
+ }
+
diff --git a/src/main/cpp/resourcebundle.cpp b/src/main/cpp/resourcebundle.cpp
new file mode 100644
index 0000000..4e8c569
--- /dev/null
+++ b/src/main/cpp/resourcebundle.cpp
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/resourcebundle.h>
+#include <log4cxx/helpers/propertyresourcebundle.h>
+#include <log4cxx/helpers/loader.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/locale.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(ResourceBundle)
+
+ResourceBundlePtr ResourceBundle::getBundle(const LogString& baseName,
+ const Locale& locale)
+{
+ LogString bundleName;
+ PropertyResourceBundlePtr resourceBundle, previous;
+
+ std::vector<LogString> bundlesNames;
+
+ if (!locale.getVariant().empty())
+ {
+ bundlesNames.push_back(baseName + LOG4CXX_STR("_") +
+ locale.getLanguage() + LOG4CXX_STR("_") +
+ locale.getCountry() + LOG4CXX_STR("_") +
+ locale.getVariant());
+ }
+
+ if (!locale.getCountry().empty())
+ {
+ bundlesNames.push_back(baseName + LOG4CXX_STR("_") +
+ locale.getLanguage() + LOG4CXX_STR("_") +
+ locale.getCountry());
+ }
+
+ if (!locale.getLanguage().empty())
+ {
+ bundlesNames.push_back(baseName + LOG4CXX_STR("_") +
+ locale.getLanguage());
+ }
+
+ bundlesNames.push_back(baseName);
+
+ for (std::vector<LogString>::iterator it = bundlesNames.begin();
+ it != bundlesNames.end(); it++)
+ {
+
+ bundleName = *it;
+
+ PropertyResourceBundlePtr current;
+
+ // Try loading a class which implements ResourceBundle
+ try
+ {
+ const Class& classObj = Loader::loadClass(bundleName);
+ current = classObj.newInstance();
+ }
+ catch(ClassNotFoundException&)
+ {
+ current = 0;
+ }
+
+ // No class found, then try to create a PropertyResourceBundle from a file
+ if (current == 0)
+ {
+ InputStreamPtr bundleStream =
+ Loader::getResourceAsStream(
+ bundleName + LOG4CXX_STR(".properties"));
+ if (bundleStream == 0) {
+ continue;
+ }
+
+ try
+ {
+ current = new PropertyResourceBundle(bundleStream);
+ }
+ catch(Exception&)
+ {
+ throw;
+ }
+ }
+
+ // Add the new resource bundle to the hierarchy
+ if (resourceBundle == 0)
+ {
+ resourceBundle = current;
+ previous = current;
+ }
+ else
+ {
+ previous->setParent(current);
+ previous = current;
+ }
+ }
+
+ // no resource bundle found at all, then throw exception
+ if (resourceBundle == 0)
+ {
+ throw MissingResourceException(
+ ((LogString) LOG4CXX_STR("Missing resource bundle ")) + baseName);
+ }
+
+ return resourceBundle;
+}
+
diff --git a/src/main/cpp/rollingfileappender.cpp b/src/main/cpp/rollingfileappender.cpp
new file mode 100644
index 0000000..5acab77
--- /dev/null
+++ b/src/main/cpp/rollingfileappender.cpp
@@ -0,0 +1,384 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/rolling/rollingfileappender.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/rolling/rolloverdescription.h>
+#include <log4cxx/helpers/fileoutputstream.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/rolling/fixedwindowrollingpolicy.h>
+#include <log4cxx/rolling/manualtriggeringpolicy.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+
+IMPLEMENT_LOG4CXX_OBJECT(RollingFileAppenderSkeleton)
+IMPLEMENT_LOG4CXX_OBJECT(RollingFileAppender)
+
+
+/**
+ * Construct a new instance.
+ */
+RollingFileAppenderSkeleton::RollingFileAppenderSkeleton() {
+}
+
+RollingFileAppender::RollingFileAppender() {
+}
+
+/**
+ * Prepare instance of use.
+ */
+void RollingFileAppenderSkeleton::activateOptions(Pool &p) {
+ if (rollingPolicy == NULL) {
+ FixedWindowRollingPolicy* fwrp = new FixedWindowRollingPolicy();
+ fwrp->setFileNamePattern(getFile() + LOG4CXX_STR(".%i"));
+ rollingPolicy = fwrp;
+ }
+
+ //
+ // if no explicit triggering policy and rolling policy is both.
+ //
+ if (triggeringPolicy == NULL) {
+ TriggeringPolicyPtr trig(rollingPolicy);
+ if (trig != NULL) {
+ triggeringPolicy = trig;
+ }
+ }
+
+ if (triggeringPolicy == NULL) {
+ triggeringPolicy = new ManualTriggeringPolicy();
+ }
+
+ {
+ synchronized sync(mutex);
+ triggeringPolicy->activateOptions(p);
+ rollingPolicy->activateOptions(p);
+
+ try {
+ RolloverDescriptionPtr rollover1 =
+ rollingPolicy->initialize(getFile(), getAppend(), p);
+
+ if (rollover1 != NULL) {
+ ActionPtr syncAction(rollover1->getSynchronous());
+
+ if (syncAction != NULL) {
+ syncAction->execute(p);
+ }
+
+ setFile(rollover1->getActiveFileName());
+ setAppend(rollover1->getAppend());
+
+ //
+ // async action not yet implemented
+ //
+ ActionPtr asyncAction(rollover1->getAsynchronous());
+ if (asyncAction != NULL) {
+ asyncAction->execute(p);
+ }
+ }
+
+ File activeFile;
+ activeFile.setPath(getFile());
+
+ if (getAppend()) {
+ fileLength = activeFile.length(p);
+ } else {
+ fileLength = 0;
+ }
+
+ FileAppender::activateOptions(p);
+ } catch (std::exception& ex) {
+ LogLog::warn(
+ LogString(LOG4CXX_STR("Exception will initializing RollingFileAppender named "))
+ + getName());
+ }
+ }
+
+}
+
+/**
+ Implements the usual roll over behaviour.
+
+ <p>If <code>MaxBackupIndex</code> is positive, then files
+ {<code>File.1</code>, ..., <code>File.MaxBackupIndex -1</code>}
+ are renamed to {<code>File.2</code>, ...,
+ <code>File.MaxBackupIndex</code>}. Moreover, <code>File</code> is
+ renamed <code>File.1</code> and closed. A new <code>File</code> is
+ created to receive further log output.
+
+ <p>If <code>MaxBackupIndex</code> is equal to zero, then the
+ <code>File</code> is truncated with no backup files created.
+
+ * @return true if rollover performed.
+ */
+bool RollingFileAppenderSkeleton::rollover(Pool& p) {
+ //
+ // can't roll without a policy
+ //
+ if (rollingPolicy != NULL) {
+
+{
+ synchronized sync(mutex);
+ try {
+ RolloverDescriptionPtr rollover1(rollingPolicy->rollover(getFile(), p));
+
+ if (rollover1 != NULL) {
+ if (rollover1->getActiveFileName() == getFile()) {
+ closeWriter();
+
+ bool success = true;
+
+ if (rollover1->getSynchronous() != NULL) {
+ success = false;
+
+ try {
+ success = rollover1->getSynchronous()->execute(p);
+ } catch (std::exception& ex) {
+ LogLog::warn(LOG4CXX_STR("Exception on rollover"));
+ }
+ }
+
+ if (success) {
+ if (rollover1->getAppend()) {
+ fileLength = File().setPath(rollover1->getActiveFileName()).length(p);
+ } else {
+ fileLength = 0;
+ }
+
+ //
+ // async action not yet implemented
+ //
+ ActionPtr asyncAction(rollover1->getAsynchronous());
+ if (asyncAction != NULL) {
+ asyncAction->execute(p);
+ }
+
+ setFile(
+ rollover1->getActiveFileName(), rollover1->getAppend(),
+ bufferedIO, bufferSize, p);
+ } else {
+ setFile(
+ rollover1->getActiveFileName(), true, bufferedIO, bufferSize, p);
+ }
+ } else {
+ OutputStreamPtr os(new FileOutputStream(
+ rollover1->getActiveFileName(), rollover1->getAppend()));
+ WriterPtr newWriter(createWriter(os));
+ closeWriter();
+ setFile(rollover1->getActiveFileName());
+ setWriter(newWriter);
+
+ bool success = true;
+
+ if (rollover1->getSynchronous() != NULL) {
+ success = false;
+
+ try {
+ success = rollover1->getSynchronous()->execute(p);
+ } catch (std::exception& ex) {
+ LogLog::warn(LOG4CXX_STR("Exception during rollover"));
+ }
+ }
+
+ if (success) {
+ if (rollover1->getAppend()) {
+ fileLength = File().setPath(rollover1->getActiveFileName()).length(p);
+ } else {
+ fileLength = 0;
+ }
+
+ //
+ // async action not yet implemented
+ //
+ ActionPtr asyncAction(rollover1->getAsynchronous());
+ if (asyncAction != NULL) {
+ asyncAction->execute(p);
+ }
+ }
+
+ writeHeader(p);
+ }
+
+ return true;
+ }
+ } catch (std::exception& ex) {
+ LogLog::warn(LOG4CXX_STR("Exception during rollover"));
+ }
+ }
+
+ }
+
+ return false;
+}
+
+/**
+ * {@inheritDoc}
+*/
+void RollingFileAppenderSkeleton::subAppend(const LoggingEventPtr& event, Pool& p) {
+ // The rollover check must precede actual writing. This is the
+ // only correct behavior for time driven triggers.
+ if (
+ triggeringPolicy->isTriggeringEvent(
+ this, event, getFile(), getFileLength())) {
+ //
+ // wrap rollover request in try block since
+ // rollover may fail in case read access to directory
+ // is not provided. However appender should still be in good
+ // condition and the append should still happen.
+ try {
+ rollover(p);
+ } catch (std::exception& ex) {
+ LogLog::warn(LOG4CXX_STR("Exception during rollover attempt."));
+ }
+ }
+ FileAppender::subAppend(event, p);
+}
+
+/**
+ * Get rolling policy.
+ * @return rolling policy.
+ */
+RollingPolicyPtr RollingFileAppenderSkeleton::getRollingPolicy() const {
+ return rollingPolicy;
+}
+
+/**
+ * Get triggering policy.
+ * @return triggering policy.
+ */
+TriggeringPolicyPtr RollingFileAppenderSkeleton::getTriggeringPolicy() const {
+ return triggeringPolicy;
+}
+
+/**
+ * Sets the rolling policy.
+ * @param policy rolling policy.
+ */
+void RollingFileAppenderSkeleton::setRollingPolicy(const RollingPolicyPtr& policy) {
+ rollingPolicy = policy;
+}
+
+/**
+ * Set triggering policy.
+ * @param policy triggering policy.
+ */
+void RollingFileAppenderSkeleton::setTriggeringPolicy(const TriggeringPolicyPtr& policy) {
+ triggeringPolicy = policy;
+}
+
+/**
+ * Close appender. Waits for any asynchronous file compression actions to be completed.
+ */
+void RollingFileAppenderSkeleton::close() {
+ FileAppender::close();
+}
+
+namespace log4cxx {
+ namespace rolling {
+/**
+ * Wrapper for OutputStream that will report all write
+ * operations back to this class for file length calculations.
+ */
+class CountingOutputStream : public OutputStream {
+ /**
+ * Wrapped output stream.
+ */
+ private:
+ OutputStreamPtr os;
+
+ /**
+ * Rolling file appender to inform of stream writes.
+ */
+ RollingFileAppenderSkeleton* rfa;
+
+ public:
+ /**
+ * Constructor.
+ * @param os output stream to wrap.
+ * @param rfa rolling file appender to inform.
+ */
+ CountingOutputStream(
+ OutputStreamPtr& os1, RollingFileAppenderSkeleton* rfa1) :
+ os(os1), rfa(rfa1) {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ void close(Pool& p) {
+ os->close(p);
+ rfa = 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ void flush(Pool& p) {
+ os->flush(p);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ void write(ByteBuffer& buf, Pool& p) {
+ os->write(buf, p);
+ if (rfa != 0) {
+ rfa->incrementFileLength(buf.limit());
+ }
+ }
+
+};
+ }
+}
+
+/**
+ Returns an OutputStreamWriter when passed an OutputStream. The
+ encoding used will depend on the value of the
+ <code>encoding</code> property. If the encoding value is
+ specified incorrectly the writer will be opened using the default
+ system encoding (an error message will be printed to the loglog.
+ @param os output stream, may not be null.
+ @return new writer.
+ */
+WriterPtr RollingFileAppenderSkeleton::createWriter(OutputStreamPtr& os) {
+ OutputStreamPtr cos(new CountingOutputStream(os, this));
+ return FileAppender::createWriter(cos);
+}
+
+/**
+ * Get byte length of current active log file.
+ * @return byte length of current active log file.
+ */
+size_t RollingFileAppenderSkeleton::getFileLength() const {
+ return fileLength;
+}
+
+/**
+ * Increments estimated byte length of current active log file.
+ * @param increment additional bytes written to log file.
+ */
+void RollingFileAppenderSkeleton::incrementFileLength(size_t increment) {
+ fileLength += increment;
+}
diff --git a/src/main/cpp/rollingpolicy.cpp b/src/main/cpp/rollingpolicy.cpp
new file mode 100644
index 0000000..a3f49df
--- /dev/null
+++ b/src/main/cpp/rollingpolicy.cpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/rolling/rollingpolicy.h>
+
+ using namespace log4cxx::rolling;
+
+
+ IMPLEMENT_LOG4CXX_OBJECT(RollingPolicy)
+
diff --git a/src/main/cpp/rollingpolicybase.cpp b/src/main/cpp/rollingpolicybase.cpp
new file mode 100644
index 0000000..ee8233c
--- /dev/null
+++ b/src/main/cpp/rollingpolicybase.cpp
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/rolling/rollingpolicybase.h>
+#include <log4cxx/pattern/formattinginfo.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/pattern/patternparser.h>
+#include <log4cxx/pattern/integerpatternconverter.h>
+#include <log4cxx/pattern/datepatternconverter.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::helpers;
+using namespace log4cxx::pattern;
+
+IMPLEMENT_LOG4CXX_OBJECT(RollingPolicyBase)
+
+RollingPolicyBase::RollingPolicyBase() {
+}
+
+RollingPolicyBase::~RollingPolicyBase() {
+}
+
+void RollingPolicyBase::addRef() const {
+ ObjectImpl::addRef();
+}
+
+void RollingPolicyBase::releaseRef() const {
+ ObjectImpl::releaseRef();
+}
+
+void RollingPolicyBase::activateOptions(log4cxx::helpers::Pool& /* pool */) {
+ if (fileNamePatternStr.length() > 0) {
+ parseFileNamePattern();
+ } else {
+ LogString msg(LOG4CXX_STR("The FileNamePattern option must be set before using FixedWindowRollingPolicy."));
+ LogString ref1(LOG4CXX_STR("See also http://logging.apache.org/log4j/codes.html#tbr_fnp_not_set"));
+ LogLog::warn(msg);
+ LogLog::warn(ref1);
+ throw IllegalStateException();
+ }
+}
+
+
+void RollingPolicyBase::setOption(const LogString& option, const LogString& value) {
+ if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("FILENAMEPATTERN"),
+ LOG4CXX_STR("filenamepattern"))) {
+ fileNamePatternStr = value;
+ }
+}
+
+void RollingPolicyBase::setFileNamePattern(const LogString& fnp) {
+ fileNamePatternStr = fnp;
+}
+
+
+LogString RollingPolicyBase::getFileNamePattern() const {
+ return fileNamePatternStr;
+}
+
+/**
+ * Parse file name pattern.
+ */
+void RollingPolicyBase::parseFileNamePattern() {
+ patternConverters.erase(patternConverters.begin(), patternConverters.end());
+ patternFields.erase(patternFields.begin(), patternFields.end());
+ PatternParser::parse(fileNamePatternStr,
+ patternConverters,
+ patternFields,
+ getFormatSpecifiers());
+}
+
+/**
+ * Format file name.
+ *
+ * @param obj object to be evaluted in formatting, may not be null.
+ * @param buf string buffer to which formatted file name is appended, may not be null.
+ */
+void RollingPolicyBase::formatFileName(
+ ObjectPtr& obj,
+ LogString& toAppendTo,
+ Pool& pool) const {
+ std::vector<FormattingInfoPtr>::const_iterator formatterIter =
+ patternFields.begin();
+ for(std::vector<PatternConverterPtr>::const_iterator
+ converterIter = patternConverters.begin();
+ converterIter != patternConverters.end();
+ converterIter++, formatterIter++) {
+ int startField = toAppendTo.length();
+ (*converterIter)->format(obj, toAppendTo, pool);
+ (*formatterIter)->format(startField, toAppendTo);
+ }
+}
+
+
+PatternConverterPtr RollingPolicyBase::getIntegerPatternConverter() const {
+ for(std::vector<PatternConverterPtr>::const_iterator
+ converterIter = patternConverters.begin();
+ converterIter != patternConverters.end();
+ converterIter++) {
+ IntegerPatternConverterPtr intPattern(*converterIter);
+ if (intPattern != NULL) {
+ return *converterIter;
+ }
+ }
+ PatternConverterPtr noMatch;
+ return noMatch;
+}
+
+PatternConverterPtr RollingPolicyBase::getDatePatternConverter() const {
+ for(std::vector<PatternConverterPtr>::const_iterator
+ converterIter = patternConverters.begin();
+ converterIter != patternConverters.end();
+ converterIter++) {
+ DatePatternConverterPtr datePattern(*converterIter);
+ if (datePattern != NULL) {
+ return *converterIter;
+ }
+ }
+ PatternConverterPtr noMatch;
+ return noMatch;
+}
+
+
diff --git a/src/main/cpp/rolloverdescription.cpp b/src/main/cpp/rolloverdescription.cpp
new file mode 100644
index 0000000..eef7fe5
--- /dev/null
+++ b/src/main/cpp/rolloverdescription.cpp
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/rolling/rolloverdescription.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(RolloverDescription)
+
+
+RolloverDescription::RolloverDescription() {
+}
+
+RolloverDescription::RolloverDescription(
+ const LogString& activeFileName1,
+ const bool append1,
+ const ActionPtr& synchronous1,
+ const ActionPtr& asynchronous1)
+ : activeFileName(activeFileName1),
+ append(append1),
+ synchronous(synchronous1),
+ asynchronous(asynchronous1) {
+}
+
+LogString RolloverDescription::getActiveFileName() const {
+ return activeFileName;
+}
+
+bool RolloverDescription::getAppend() const {
+ return append;
+}
+
+ActionPtr RolloverDescription::getSynchronous() const {
+ return synchronous;
+}
+
+ /**
+ * Action to be completed after close of current active log file
+ * and before next rollover attempt, may be executed asynchronously.
+ *
+ * @return action, may be null.
+ */
+ActionPtr RolloverDescription::getAsynchronous() const {
+ return asynchronous;
+}
diff --git a/src/main/cpp/rootlogger.cpp b/src/main/cpp/rootlogger.cpp
new file mode 100644
index 0000000..ceb3e5e
--- /dev/null
+++ b/src/main/cpp/rootlogger.cpp
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/spi/rootlogger.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/level.h>
+#include <log4cxx/appender.h>
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+RootLogger::RootLogger(Pool& pool, const LevelPtr& level1) :
+ Logger(pool, LOG4CXX_STR("root"))
+{
+ setLevel(level1);
+}
+
+const LevelPtr& RootLogger::getEffectiveLevel() const
+{
+ return level;
+}
+
+void RootLogger::setLevel(const LevelPtr& level1)
+{
+ if(level1 == 0)
+ {
+ LogLog::error(LOG4CXX_STR("You have tried to set a null level to root."));
+ }
+ else
+ {
+
+ this->level = level1;
+ }
+}
+
+
+
diff --git a/src/main/cpp/serversocket.cpp b/src/main/cpp/serversocket.cpp
new file mode 100644
index 0000000..32e4f1a
--- /dev/null
+++ b/src/main/cpp/serversocket.cpp
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/serversocket.h>
+#include <log4cxx/helpers/synchronized.h>
+#include "apr_network_io.h"
+#include "apr_pools.h"
+#include "apr_poll.h"
+
+using namespace log4cxx::helpers;
+
+/** Creates a server socket on a specified port.
+*/
+ServerSocket::ServerSocket(int port) : pool(), mutex(pool), socket(0), timeout(0)
+{
+ apr_status_t status =
+ apr_socket_create(&socket, APR_INET, SOCK_STREAM,
+ APR_PROTO_TCP, pool.getAPRPool());
+ if (status != APR_SUCCESS) {
+ throw SocketException(status);
+ }
+
+ status = apr_socket_opt_set(socket, APR_SO_NONBLOCK, 1);
+ if (status != APR_SUCCESS) {
+ throw SocketException(status);
+ }
+
+ // Create server socket address (including port number)
+ apr_sockaddr_t *server_addr;
+ status =
+ apr_sockaddr_info_get(&server_addr, NULL, APR_INET,
+ port, 0, pool.getAPRPool());
+ if (status != APR_SUCCESS) {
+ throw ConnectException(status);
+ }
+
+ // bind the socket to the address
+ status = apr_socket_bind(socket, server_addr);
+ if (status != APR_SUCCESS) {
+ throw BindException(status);
+ }
+
+
+ status = apr_socket_listen(socket, 50);
+ if (status != APR_SUCCESS) {
+ throw SocketException(status);
+ }
+}
+
+
+ServerSocket::~ServerSocket()
+{
+}
+
+void ServerSocket::close() {
+ synchronized sync(mutex);
+ if (socket != 0) {
+ apr_status_t status = apr_socket_close(socket);
+ if (status != APR_SUCCESS) {
+ throw SocketException(status);
+ }
+ socket = 0;
+ }
+}
+
+/** Listens for a connection to be made to this socket and
+accepts it
+*/
+SocketPtr ServerSocket::accept() {
+ synchronized sync(mutex);
+ if (socket == 0) {
+ throw IOException();
+ }
+
+ apr_pollfd_t poll;
+ poll.p = pool.getAPRPool();
+ poll.desc_type = APR_POLL_SOCKET;
+ poll.reqevents = APR_POLLIN;
+ poll.rtnevents = 0;
+ poll.desc.s = socket;
+ poll.client_data = NULL;
+
+ apr_int32_t signaled;
+ apr_interval_time_t to = timeout * 1000;
+ apr_status_t status = apr_poll(&poll, 1, &signaled, to);
+
+ if (APR_STATUS_IS_TIMEUP(status)) {
+ throw SocketTimeoutException();
+ } else if (status != APR_SUCCESS) {
+ throw SocketException(status);
+ }
+
+ apr_pool_t* newPool;
+ status = apr_pool_create(&newPool, 0);
+ if (status != APR_SUCCESS) {
+ throw PoolException(status);
+ }
+ apr_socket_t* newSocket;
+ status = apr_socket_accept(&newSocket, socket, newPool);
+ if (status != APR_SUCCESS) {
+ apr_pool_destroy(newPool);
+ throw SocketException(status);
+ }
+
+ status = apr_socket_opt_set(newSocket, APR_SO_NONBLOCK, 0);
+ if (status != APR_SUCCESS) {
+ apr_pool_destroy(newPool);
+ throw SocketException(status);
+ }
+
+ return new Socket(newSocket, newPool);
+}
+
+/** Retrive setting for SO_TIMEOUT.
+*/
+int ServerSocket::getSoTimeout() const
+{
+ return timeout;
+}
+
+/** Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
+*/
+void ServerSocket::setSoTimeout(int newVal)
+{
+ timeout = newVal;
+}
diff --git a/src/main/cpp/simpledateformat.cpp b/src/main/cpp/simpledateformat.cpp
new file mode 100644
index 0000000..f18dfc7
--- /dev/null
+++ b/src/main/cpp/simpledateformat.cpp
@@ -0,0 +1,781 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/simpledateformat.h>
+
+#include <apr_time.h>
+#include <apr_strings.h>
+#include <sstream>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <assert.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+#include <log4cxx/helpers/pool.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+using namespace std;
+
+#if LOG4CXX_HAS_STD_LOCALE
+#include <locale>
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#define HAS_FACET(locale, type) _HAS(locale, type)
+#define USE_FACET(locale, type) _USE(locale, type)
+#define PUT_FACET(facet, os, time, spec) facet.put(os, os, time, spec)
+#else
+#if defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE)
+#define HAS_FACET(locale, type) std::has_facet(locale, (type*) 0)
+#define USE_FACET(locale, type) std::use_facet(locale, (type*) 0)
+#else
+#define HAS_FACET(locale, type) std::has_facet < type >(locale)
+#define USE_FACET(locale, type) std::use_facet < type >(locale)
+#endif
+#define PUT_FACET(facet, os, time, spec) facet.put(os, os, os.fill(), time, spec)
+#endif
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ namespace SimpleDateFormatImpl
+ {
+ typedef void (*incrementFunction)(tm& time, apr_time_exp_t& apr_time);
+
+ /**
+ * Abstract inner class representing one format token
+ * (one or more instances of a character).
+ */
+ class PatternToken {
+ public:
+ PatternToken() {
+ }
+
+ virtual ~PatternToken() {
+ }
+
+ /**
+ * Sets the time zone.
+ * @param zone new time zone.
+ */
+ virtual void setTimeZone(const TimeZonePtr& zone) {
+ }
+
+ /**
+ * Appends the formatted content to the string.
+ * @param s string to which format contribution is appended.
+ * @param date exploded date/time.
+ * @param p memory pool.
+ */
+ virtual void format(LogString& s,
+ const apr_time_exp_t& date,
+ log4cxx::helpers::Pool& p) const = 0;
+
+ protected:
+
+ static void incrementMonth(tm& time, apr_time_exp_t& aprtime) {
+ time.tm_mon++;
+ aprtime.tm_mon++;
+ }
+
+ static void incrementDay(tm& time, apr_time_exp_t& aprtime) {
+ time.tm_wday++;
+ aprtime.tm_wday++;
+ }
+
+ static void incrementHalfDay(tm& time, apr_time_exp_t& aprtime) {
+ time.tm_hour += 12;
+ aprtime.tm_hour += 12;
+ }
+
+ static void renderFacet(const std::locale* locale,
+ incrementFunction inc,
+ char spec,
+ unsigned int wspec,
+ const char* aprspec,
+ std::vector<LogString>& values) {
+ std::vector<LogString>::iterator valueIter = values.begin();
+ tm time;
+ memset(&time, 0, sizeof(time));
+ apr_time_exp_t aprtime;
+ memset(&aprtime, 0, sizeof(aprtime));
+#if LOG4CXX_HAS_STD_LOCALE
+ if (locale != NULL) {
+#if LOG4CXX_WCHAR_T_API
+ if (HAS_FACET(*locale, std::time_put<wchar_t>)) {
+ const std::time_put<wchar_t>& facet = USE_FACET(*locale, std::time_put<wchar_t>);
+ size_t start = 0;
+ std::basic_ostringstream<wchar_t> os;
+ for(; valueIter != values.end(); valueIter++) {
+ PUT_FACET(facet, os, &time, (wchar_t) wspec);
+ Transcoder::decode(os.str().substr(start), *valueIter);
+ start = os.str().length();
+ (*inc)(time, aprtime);
+ }
+ } else
+#endif
+ if (HAS_FACET(*locale, std::time_put<char>)) {
+ const std::time_put<char>& facet = USE_FACET(*locale, std::time_put<char> );
+ size_t start = 0;
+ std::ostringstream os;
+ for(; valueIter != values.end(); valueIter++) {
+ PUT_FACET(facet, os, &time, spec);
+ Transcoder::decode(os.str().substr(start), *valueIter);
+ start = os.str().length();
+ (*inc)(time, aprtime);
+ }
+ }
+ }
+#endif
+ const size_t BUFSIZE = 256;
+ char buf[BUFSIZE];
+ memset(buf, 0, BUFSIZE);
+ apr_size_t retsize = 0;
+ for(; valueIter != values.end(); valueIter++) {
+ apr_status_t stat = apr_strftime(buf, &retsize, BUFSIZE, aprspec, &aprtime);
+ (*inc)(time, aprtime);
+ if (stat == APR_SUCCESS) {
+ Transcoder::decode(std::string(buf, retsize), *valueIter);
+ } else {
+ valueIter->append(1, (logchar) 0x3F);
+ }
+ }
+ }
+
+ private:
+ /**
+ * Private copy constructor.
+ */
+ PatternToken(const PatternToken&);
+
+ /**
+ * Private assignment operator.
+ */
+ PatternToken& operator=(const PatternToken&);
+ };
+
+
+class LiteralToken : public PatternToken
+{
+public:
+ LiteralToken( logchar ch1, int count1 ) : ch( ch1 ), count( count1 )
+ {
+ }
+
+ void format( LogString& s, const apr_time_exp_t & , Pool & /* p */ ) const
+ {
+ s.append( count, ch );
+ }
+
+private:
+ logchar ch;
+ int count;
+};
+
+
+
+class EraToken : public PatternToken
+{
+public:
+ EraToken( int /* count */ , const std::locale * /* locale */ )
+ {
+ }
+
+ void format(LogString& s, const apr_time_exp_t & /* tm */, Pool & /* p */ ) const
+ {
+ s.append(1, (logchar) 0x41 /* 'A' */);
+ s.append(1, (logchar) 0x44 /* 'D' */);
+ }
+};
+
+
+
+class NumericToken : public PatternToken
+{
+public:
+ NumericToken( size_t width1 ) : width( width1 )
+ {
+ }
+
+ virtual int getField( const apr_time_exp_t & tm ) const = 0;
+
+ void format( LogString& s, const apr_time_exp_t & tm, Pool & p ) const
+ {
+ size_t initialLength = s.length();
+
+ StringHelper::toString( getField( tm ), p, s );
+ size_t finalLength = s.length();
+ if ( initialLength + width > finalLength )
+ {
+ s.insert( initialLength, ( initialLength + width ) - finalLength, (logchar) 0x30 /* '0' */);
+ }
+ }
+
+private:
+ size_t width;
+ char zeroDigit;
+};
+
+
+
+class YearToken : public NumericToken
+{
+public:
+ YearToken( int width1 ) : NumericToken( width1 )
+ {
+ }
+
+ int getField( const apr_time_exp_t & tm ) const
+ {
+ return 1900 + tm.tm_year;
+ }
+};
+
+
+
+class MonthToken : public NumericToken
+{
+public:
+ MonthToken( int width1 ) : NumericToken( width1 )
+ {
+ }
+
+ int getField( const apr_time_exp_t & tm ) const
+ {
+ return tm.tm_mon + 1;
+ }
+};
+
+
+
+class AbbreviatedMonthNameToken : public PatternToken
+{
+public:
+ AbbreviatedMonthNameToken(int, const std::locale *locale) : names( 12 ) {
+ renderFacet(locale, PatternToken::incrementMonth, 'b', 0x62, "%b", names);
+ }
+
+ void format(LogString& s, const apr_time_exp_t & tm, Pool & /* p */ ) const
+ {
+ s.append( names[tm.tm_mon] );
+ }
+
+private:
+ std::vector < LogString > names;
+};
+
+
+
+class FullMonthNameToken : public PatternToken
+{
+public:
+ FullMonthNameToken( int width, const std::locale *locale) : names( 12 )
+ {
+ renderFacet(locale, PatternToken::incrementMonth, 'B', 0x42, "%B", names);
+ }
+
+ void format( LogString& s, const apr_time_exp_t & tm, Pool & /* p */ ) const
+ {
+ s.append( names[tm.tm_mon] );
+ }
+
+private:
+ std::vector < LogString > names;
+};
+
+
+
+class WeekInYearToken : public NumericToken
+{
+public:
+ WeekInYearToken( int width1 ) : NumericToken( width1 )
+ {
+ }
+
+ int getField( const apr_time_exp_t & tm ) const
+ {
+ return tm.tm_yday / 7;
+ }
+};
+
+
+
+class WeekInMonthToken : public NumericToken
+{
+public:
+ WeekInMonthToken( int width1 ) : NumericToken( width1 )
+ {
+ }
+
+ int getField( const apr_time_exp_t & tm ) const
+ {
+ return tm.tm_mday / 7;
+ }
+};
+
+
+
+class DayInMonthToken : public NumericToken
+{
+public:
+ DayInMonthToken( int width1 ) : NumericToken( width1 )
+ {
+ }
+
+ int getField( const apr_time_exp_t & tm ) const
+ {
+ return tm.tm_mday;
+ }
+};
+
+
+
+class DayInYearToken : public NumericToken
+{
+public:
+ DayInYearToken( int width1 ) : NumericToken( width1 )
+ {
+ }
+
+ int getField( const apr_time_exp_t & tm ) const
+ {
+ return tm.tm_yday;
+ }
+};
+
+
+
+class DayOfWeekInMonthToken : public NumericToken
+{
+public:
+ DayOfWeekInMonthToken( int width1 ) : NumericToken( width1 )
+ {
+ }
+
+ int getField( const apr_time_exp_t & /* tm */ ) const
+ {
+ return -1;
+ }
+};
+
+
+
+class AbbreviatedDayNameToken : public PatternToken
+{
+public:
+ AbbreviatedDayNameToken( int width, const std::locale *locale) : names( 7 ) {
+ renderFacet(locale, PatternToken::incrementDay, 'a', 0x61, "%a", names);
+ }
+
+ void format( LogString& s, const apr_time_exp_t & tm, Pool & /* p */ ) const
+ {
+ s.append( names[tm.tm_wday] );
+ }
+
+private:
+ std::vector < LogString > names;
+
+};
+
+
+
+class FullDayNameToken : public PatternToken
+{
+public:
+ FullDayNameToken( int width, const std::locale *locale) : names( 7 ) {
+ renderFacet(locale, PatternToken::incrementDay, 'A', 0x41, "%A", names);
+ }
+
+ void format( LogString& s, const apr_time_exp_t & tm, Pool & /* p */ ) const
+ {
+ s.append( names[tm.tm_wday] );
+ }
+
+private:
+ std::vector < LogString > names;
+
+};
+
+
+
+class MilitaryHourToken : public NumericToken
+{
+public:
+ MilitaryHourToken( int width1, int offset1 ) : NumericToken( width1 ), offset( offset1 )
+ {
+ }
+
+ int getField( const apr_time_exp_t & tm ) const
+ {
+ return tm.tm_hour + offset;
+ }
+
+private:
+ int offset;
+};
+
+
+
+class HourToken : public NumericToken
+{
+public:
+ HourToken( int width1, int /* offset1 */ ) : NumericToken( width1 )
+ {
+ }
+
+ int getField( const apr_time_exp_t & tm ) const
+ {
+ return ( ( tm.tm_hour + 12 - offset ) % 12 ) + offset;
+ }
+
+private:
+ int offset;
+};
+
+
+
+class MinuteToken : public NumericToken
+{
+public:
+ MinuteToken( int width1 ) : NumericToken( width1 )
+ {
+ }
+
+ int getField( const apr_time_exp_t & tm ) const
+ {
+ return tm.tm_min;
+ }
+};
+
+
+
+class SecondToken : public NumericToken
+{
+public:
+ SecondToken( int width1 ) : NumericToken( width1 )
+ {
+ }
+
+ int getField( const apr_time_exp_t & tm ) const
+ {
+ return tm.tm_sec;
+ }
+};
+
+
+
+class MillisecondToken : public NumericToken
+{
+public:
+ MillisecondToken( int width1 ) : NumericToken( width1 )
+ {
+ }
+
+ int getField( const apr_time_exp_t & tm ) const
+ {
+ return tm.tm_usec / 1000;
+ }
+};
+
+
+
+class AMPMToken : public PatternToken
+{
+public:
+ AMPMToken( int width, const std::locale *locale) : names( 2 ) {
+ renderFacet(locale, PatternToken::incrementHalfDay, 'p', 0x70, "%p", names);
+ }
+
+ void format( LogString& s, const apr_time_exp_t & tm, Pool & /* p */ ) const
+ {
+ s.append( names[tm.tm_hour / 12] );
+ }
+
+private:
+ std::vector < LogString > names;
+};
+
+
+
+class GeneralTimeZoneToken : public PatternToken
+{
+public:
+ GeneralTimeZoneToken( int /* width */ )
+ {
+ }
+
+ void format( LogString& s, const apr_time_exp_t & , Pool & /* p */ ) const {
+ s.append(timeZone->getID());
+ }
+
+ void setTimeZone( const TimeZonePtr & zone )
+ {
+ timeZone = zone;
+ }
+
+private:
+ TimeZonePtr timeZone;
+};
+
+
+
+class RFC822TimeZoneToken : public PatternToken
+{
+public:
+ RFC822TimeZoneToken( int /* width */ )
+ {
+ }
+
+ void format( LogString& s, const apr_time_exp_t & tm, Pool & p ) const
+ {
+ if ( tm.tm_gmtoff == 0 )
+ {
+ s.append( 1, (logchar) 0x5A /* 'Z' */ );
+ }
+ else
+ {
+ apr_int32_t off = tm.tm_gmtoff;
+ size_t basePos = s.length();
+ s.append( LOG4CXX_STR( "+0000" ) );
+ if ( off < 0 )
+ {
+ s[basePos] = 0x2D; // '-'
+ off = -off;
+ }
+ LogString hours;
+ StringHelper::toString( off / 3600, p, hours );
+ size_t hourPos = basePos + 2;
+ //
+ // assumes that point values for 0-9 are same between char and wchar_t
+ //
+ for ( size_t i = hours.length(); i-- > 0; )
+ {
+ s[hourPos--] = hours[i];
+ }
+ LogString min;
+ StringHelper::toString( ( off % 3600 ) / 60, p, min );
+ size_t minPos = basePos + 4;
+ //
+ // assumes that point values for 0-9 are same between char and wchar_t
+ //
+ for ( size_t j = min.length(); j-- > 0; )
+ {
+ s[minPos--] = min[j];
+ }
+ }
+ }
+};
+
+
+
+
+ }
+}
+}
+
+
+using namespace log4cxx::helpers::SimpleDateFormatImpl;
+
+void SimpleDateFormat::addToken(const logchar spec, const int repeat, const std::locale * locale,
+ std::vector < PatternToken * > & pattern )
+ {
+ PatternToken * token = NULL;
+ switch ( spec )
+ {
+ case 0x47: // 'G'
+ token = ( new EraToken( repeat, locale ) );
+ break;
+
+ case 0x79: // 'y'
+ token = ( new YearToken( repeat ) );
+ break;
+
+ case 0x4D: // 'M'
+ if ( repeat <= 2 )
+ {
+ token = ( new MonthToken( repeat ) );
+ }
+ else if ( repeat <= 3 )
+ {
+ token = ( new AbbreviatedMonthNameToken( repeat, locale ) );
+ }
+ else
+ {
+ token = ( new FullMonthNameToken( repeat, locale ) );
+ }
+ break;
+
+ case 0x77: // 'w'
+ token = ( new WeekInYearToken( repeat ) );
+ break;
+
+ case 0x57: // 'W'
+ token = ( new WeekInMonthToken( repeat ) );
+ break;
+
+ case 0x44: // 'D'
+ token = ( new DayInYearToken( repeat ) );
+ break;
+
+ case 0x64: // 'd'
+ token = ( new DayInMonthToken( repeat ) );
+ break;
+
+ case 0x46: // 'F'
+ token = ( new DayOfWeekInMonthToken( repeat ) );
+ break;
+
+ case 0x45: // 'E'
+ if ( repeat <= 3 )
+ {
+ token = ( new AbbreviatedDayNameToken( repeat, locale ) );
+ }
+ else
+ {
+ token = ( new FullDayNameToken( repeat, locale ) );
+ }
+ break;
+
+ case 0x61: // 'a'
+ token = ( new AMPMToken( repeat, locale ) );
+ break;
+
+ case 0x48: // 'H'
+ token = ( new MilitaryHourToken( repeat, 0 ) );
+ break;
+
+ case 0x6B: // 'k'
+ token = ( new MilitaryHourToken( repeat, 1 ) );
+ break;
+
+ case 0x4B: // 'K'
+ token = ( new HourToken( repeat, 0 ) );
+ break;
+
+ case 0x68: // 'h'
+ token = ( new HourToken( repeat, 1 ) );
+ break;
+
+ case 0x6D: // 'm'
+ token = ( new MinuteToken( repeat ) );
+ break;
+
+ case 0x73: // 's'
+ token = ( new SecondToken( repeat ) );
+ break;
+
+ case 0x53: // 'S'
+ token = ( new MillisecondToken( repeat ) );
+ break;
+
+ case 0x7A: // 'z'
+ token = ( new GeneralTimeZoneToken( repeat ) );
+ break;
+
+ case 0x5A: // 'Z'
+ token = ( new RFC822TimeZoneToken( repeat ) );
+ break;
+
+ default:
+ token = ( new LiteralToken( spec, repeat ) );
+ }
+ assert( token != NULL );
+ pattern.push_back( token );
+}
+
+
+void SimpleDateFormat::parsePattern( const LogString & fmt, const std::locale * locale,
+ std::vector < PatternToken * > & pattern )
+{
+ if ( !fmt.empty() )
+ {
+ LogString::const_iterator iter = fmt.begin();
+ int repeat = 1;
+ logchar prevChar = * iter;
+ for ( iter++; iter != fmt.end(); iter++ )
+ {
+ if ( * iter == prevChar )
+ {
+ repeat++;
+ }
+ else
+ {
+ addToken( prevChar, repeat, locale, pattern );
+ prevChar = * iter;
+ repeat = 1;
+ }
+ }
+ addToken( prevChar, repeat, locale, pattern );
+ }
+}
+
+
+SimpleDateFormat::SimpleDateFormat( const LogString & fmt ) : timeZone( TimeZone::getDefault() )
+{
+#if LOG4CXX_HAS_STD_LOCALE
+ std::locale defaultLocale;
+ parsePattern( fmt, & defaultLocale, pattern );
+#else
+ parsePattern( fmt, NULL, pattern );
+#endif
+ for ( PatternTokenList::iterator iter = pattern.begin(); iter != pattern.end(); iter++ )
+ {
+ ( * iter )->setTimeZone( timeZone );
+ }
+}
+
+SimpleDateFormat::SimpleDateFormat( const LogString & fmt, const std::locale * locale ) : timeZone( TimeZone::getDefault() )
+{
+ parsePattern( fmt, locale, pattern );
+ for ( PatternTokenList::iterator iter = pattern.begin(); iter != pattern.end(); iter++ )
+ {
+ ( * iter )->setTimeZone( timeZone );
+ }
+}
+
+
+SimpleDateFormat::~SimpleDateFormat()
+{
+ for ( PatternTokenList::iterator iter = pattern.begin(); iter != pattern.end(); iter++ )
+ {
+ delete * iter;
+ }
+}
+
+
+void SimpleDateFormat::format( LogString & s, log4cxx_time_t time, Pool & p ) const
+{
+ apr_time_exp_t exploded;
+ apr_status_t stat = timeZone->explode( & exploded, time );
+ if ( stat == APR_SUCCESS )
+ {
+ for ( PatternTokenList::const_iterator iter = pattern.begin(); iter != pattern.end(); iter++ )
+ {
+ ( * iter )->format( s, exploded, p );
+ }
+ }
+}
+
+void SimpleDateFormat::setTimeZone( const TimeZonePtr & zone )
+{
+ timeZone = zone;
+}
diff --git a/src/main/cpp/simplelayout.cpp b/src/main/cpp/simplelayout.cpp
new file mode 100644
index 0000000..6addedf
--- /dev/null
+++ b/src/main/cpp/simplelayout.cpp
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/simplelayout.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/level.h>
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+
+IMPLEMENT_LOG4CXX_OBJECT(SimpleLayout)
+
+
+
+void SimpleLayout::format(LogString& output,
+ const spi::LoggingEventPtr& event,
+ log4cxx::helpers::Pool&) const
+{
+ output.append(event->getLevel()->toString());
+ output.append(LOG4CXX_STR(" - "));
+ output.append(event->getRenderedMessage());
+ output.append(LOG4CXX_EOL);
+}
diff --git a/src/main/cpp/sizebasedtriggeringpolicy.cpp b/src/main/cpp/sizebasedtriggeringpolicy.cpp
new file mode 100644
index 0000000..7105e91
--- /dev/null
+++ b/src/main/cpp/sizebasedtriggeringpolicy.cpp
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/rolling/sizebasedtriggeringpolicy.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/optionconverter.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(SizeBasedTriggeringPolicy)
+
+SizeBasedTriggeringPolicy::SizeBasedTriggeringPolicy()
+ : maxFileSize(10 * 1024 * 1024) {
+}
+
+bool SizeBasedTriggeringPolicy::isTriggeringEvent(Appender* /* appender */,
+ const log4cxx::spi::LoggingEventPtr& /* event */,
+ const LogString& /* file */,
+ size_t fileLength) {
+ return (fileLength >= maxFileSize);
+}
+
+size_t SizeBasedTriggeringPolicy::getMaxFileSize() {
+ return maxFileSize;
+}
+
+void SizeBasedTriggeringPolicy::setMaxFileSize(size_t l) {
+ maxFileSize = l;
+}
+
+void SizeBasedTriggeringPolicy::activateOptions(Pool& /* p */) {
+}
+
+void SizeBasedTriggeringPolicy::setOption(const LogString& option, const LogString& value) {
+ if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("MAXFILESIZE"),
+ LOG4CXX_STR("maxfilesize"))) {
+ maxFileSize = OptionConverter::toFileSize(value, 10*1024*1024);
+ }
+}
diff --git a/src/main/cpp/smtpappender.cpp b/src/main/cpp/smtpappender.cpp
new file mode 100644
index 0000000..6fe8003
--- /dev/null
+++ b/src/main/cpp/smtpappender.cpp
@@ -0,0 +1,674 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/net/smtpappender.h>
+#include <log4cxx/level.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/stringtokenizer.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/synchronized.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+
+
+
+#include <apr_strings.h>
+#include <vector>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::net;
+using namespace log4cxx::spi;
+
+#if LOG4CXX_HAVE_LIBESMTP
+#include <auth-client.h>
+#include <libesmtp.h>
+#endif
+
+namespace log4cxx {
+ namespace net {
+ //
+ // The following two classes implement an C++ SMTP wrapper over libesmtp.
+ // The same signatures could be implemented over different SMTP implementations
+ // or libesmtp could be combined with libgmime to enable support for non-ASCII
+ // content.
+
+#if LOG4CXX_HAVE_LIBESMTP
+ /**
+ * SMTP Session.
+ */
+ class SMTPSession {
+ public:
+ /**
+ * Create new instance.
+ */
+ SMTPSession(const LogString& smtpHost,
+ int smtpPort,
+ const LogString& smtpUsername,
+ const LogString& smtpPassword,
+ Pool& p) : session(0), authctx(0),
+ user(toAscii(smtpUsername, p)),
+ pwd(toAscii(smtpPassword, p)) {
+ auth_client_init();
+ session = smtp_create_session();
+ if (session == 0) {
+ throw Exception("Could not initialize session.");
+ }
+ std::string host(toAscii(smtpHost, p));
+ host.append(1, ':');
+ host.append(p.itoa(smtpPort));
+ smtp_set_server(session, host.c_str());
+
+ authctx = auth_create_context();
+ auth_set_mechanism_flags(authctx, AUTH_PLUGIN_PLAIN, 0);
+ auth_set_interact_cb(authctx, authinteract, (void*) this);
+
+ if (*user || *pwd) {
+ smtp_auth_set_context(session, authctx);
+ }
+ }
+
+ ~SMTPSession() {
+ smtp_destroy_session(session);
+ auth_destroy_context(authctx);
+ }
+
+ void send(Pool& p) {
+ int status = smtp_start_session(session);
+ if (!status) {
+ size_t bufSize = 128;
+ char* buf = p.pstralloc(bufSize);
+ smtp_strerror(smtp_errno(), buf, bufSize);
+ throw Exception(buf);
+ }
+ }
+
+ operator smtp_session_t() {
+ return session;
+ }
+
+ static char* toAscii(const LogString& str, Pool& p) {
+ char* buf = p.pstralloc(str.length() + 1);
+ char* current = buf;
+ for(LogString::const_iterator iter = str.begin();
+ iter != str.end();
+ iter++) {
+ unsigned int c = *iter;
+ if (c > 0x7F) {
+ c = '?';
+ }
+ *current++ = c;
+ }
+ *current = 0;
+ return buf;
+ }
+
+ private:
+ SMTPSession(SMTPSession&);
+ SMTPSession& operator=(SMTPSession&);
+ smtp_session_t session;
+ auth_context_t authctx;
+ char* user;
+ char* pwd;
+
+ /**
+ * This method is called if the SMTP server requests authentication.
+ */
+ static int authinteract(auth_client_request_t request, char **result, int fields,
+ void *arg) {
+ SMTPSession* pThis = (SMTPSession*) arg;
+ for (int i = 0; i < fields; i++) {
+ int flag = request[i].flags & 0x07;
+ if (flag == AUTH_USER) {
+ result[i] = pThis->user;
+ } else if(flag == AUTH_PASS) {
+ result[i] = pThis->pwd;
+ }
+ }
+ return 1;
+ }
+
+
+ };
+
+ /**
+ * A message in an SMTP session.
+ */
+ class SMTPMessage {
+ public:
+ SMTPMessage(SMTPSession& session,
+ const LogString& from,
+ const LogString& to,
+ const LogString& cc,
+ const LogString& bcc,
+ const LogString& subject,
+ const LogString msg, Pool& p) {
+ message = smtp_add_message(session);
+ body = current = toMessage(msg, p);
+ smtp_set_reverse_path(message, toAscii(from, p));
+ addRecipients(to, "To", p);
+ addRecipients(cc, "Cc", p);
+ addRecipients(bcc, "Bcc", p);
+ if (!subject.empty()) {
+ smtp_set_header(message, "Subject", toAscii(subject, p));
+ }
+ smtp_set_messagecb(message, messagecb, this);
+ }
+ ~SMTPMessage() {
+ }
+
+ private:
+ SMTPMessage(const SMTPMessage&);
+ SMTPMessage& operator=(const SMTPMessage&);
+ smtp_message_t message;
+ const char* body;
+ const char* current;
+ void addRecipients(const LogString& addresses, const char* field, Pool& p) {
+ if (!addresses.empty()) {
+ char* str = p.pstrdup(toAscii(addresses, p));;
+ smtp_set_header(message, field, NULL, str);
+ char* last;
+ for(char* next = apr_strtok(str, ",", &last);
+ next;
+ next = apr_strtok(NULL, ",", &last)) {
+ smtp_add_recipient(message, next);
+ }
+ }
+ }
+ static const char* toAscii(const LogString& str, Pool& p) {
+ return SMTPSession::toAscii(str, p);
+ }
+
+ /**
+ * Message bodies can only contain US-ASCII characters and
+ * CR and LFs can only occur together.
+ */
+ static const char* toMessage(const LogString& str, Pool& p) {
+ //
+ // count the number of carriage returns and line feeds
+ //
+ int feedCount = 0;
+ for(size_t pos = str.find_first_of(LOG4CXX_STR("\n\r"));
+ pos != LogString::npos;
+ pos = str.find_first_of(LOG4CXX_STR("\n\r"), ++pos)) {
+ feedCount++;
+ }
+ //
+ // allocate sufficient space for the modified message
+ char* retval = p.pstralloc(str.length() + feedCount + 1);
+ char* current = retval;
+ char* startOfLine = current;
+ //
+ // iterator through message
+ //
+ for(LogString::const_iterator iter = str.begin();
+ iter != str.end();
+ iter++) {
+ unsigned int c = *iter;
+ //
+ // replace non-ASCII characters with '?'
+ //
+ if (c > 0x7F) {
+ *current++ = 0x3F; // '?'
+ } else if (c == 0x0A || c == 0x0D) {
+ //
+ // replace any stray CR or LF with CRLF
+ // reset start of line
+ *current++ = 0x0D;
+ *current++ = 0x0A;
+ startOfLine = current;
+ LogString::const_iterator next = iter + 1;
+ if (next != str.end() && (*next == 0x0A || *next == 0x0D)) {
+ iter++;
+ }
+ } else {
+ //
+ // truncate any lines to 1000 characters (including CRLF)
+ // as required by RFC.
+ if (current < startOfLine + 998) {
+ *current++ = (char) c;
+ }
+ }
+ }
+ *current = 0;
+ return retval;
+ }
+
+ /**
+ * Callback for message.
+ */
+ static const char* messagecb(void** ctx, int* len, void* arg) {
+ *ctx = 0;
+ const char* retval = 0;
+ SMTPMessage* pThis = (SMTPMessage*) arg;
+ // rewind message
+ if (len == NULL) {
+ pThis->current = pThis->body;
+ } else {
+ if (pThis->current) {
+ *len = strlen(pThis->current);
+ }
+ retval = pThis->current;
+ pThis->current = 0;
+ }
+ return retval;
+ }
+
+ };
+#endif
+
+ class LOG4CXX_EXPORT DefaultEvaluator :
+ public virtual spi::TriggeringEventEvaluator,
+ public virtual helpers::ObjectImpl
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(DefaultEvaluator)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(DefaultEvaluator)
+ LOG4CXX_CAST_ENTRY(spi::TriggeringEventEvaluator)
+ END_LOG4CXX_CAST_MAP()
+
+ DefaultEvaluator();
+
+ /**
+ Is this <code>event</code> the e-mail triggering event?
+ <p>This method returns <code>true</code>, if the event level
+ has ERROR level or higher. Otherwise it returns
+ <code>false</code>.
+ */
+ virtual bool isTriggeringEvent(const spi::LoggingEventPtr& event);
+ private:
+ DefaultEvaluator(const DefaultEvaluator&);
+ DefaultEvaluator& operator=(const DefaultEvaluator&);
+ }; // class DefaultEvaluator
+
+ }
+}
+
+IMPLEMENT_LOG4CXX_OBJECT(DefaultEvaluator)
+IMPLEMENT_LOG4CXX_OBJECT(SMTPAppender)
+
+DefaultEvaluator::DefaultEvaluator() {
+}
+
+bool DefaultEvaluator::isTriggeringEvent(const spi::LoggingEventPtr& event)
+{
+ return event->getLevel()->isGreaterOrEqual(Level::getError());
+}
+
+SMTPAppender::SMTPAppender()
+: smtpPort(25), bufferSize(512), locationInfo(false), cb(bufferSize),
+evaluator(new DefaultEvaluator())
+{
+}
+
+/**
+Use <code>evaluator</code> passed as parameter as the
+TriggeringEventEvaluator for this SMTPAppender. */
+SMTPAppender::SMTPAppender(spi::TriggeringEventEvaluatorPtr evaluator)
+: smtpPort(25), bufferSize(512), locationInfo(false), cb(bufferSize),
+evaluator(evaluator)
+{
+}
+
+SMTPAppender::~SMTPAppender()
+{
+ finalize();
+}
+
+bool SMTPAppender::requiresLayout() const {
+ return true;
+}
+
+
+LogString SMTPAppender::getFrom() const {
+ return from;
+}
+
+void SMTPAppender::setFrom(const LogString& newVal) {
+ from = newVal;
+}
+
+
+LogString SMTPAppender::getSubject() const {
+ return subject;
+}
+
+void SMTPAppender::setSubject(const LogString& newVal) {
+ subject = newVal;
+}
+
+LogString SMTPAppender::getSMTPHost() const {
+ return smtpHost;
+}
+
+void SMTPAppender::setSMTPHost(const LogString& newVal) {
+ smtpHost = newVal;
+}
+
+int SMTPAppender::getSMTPPort() const {
+ return smtpPort;
+}
+
+void SMTPAppender::setSMTPPort(int newVal) {
+ smtpPort = newVal;
+}
+
+bool SMTPAppender::getLocationInfo() const {
+ return locationInfo;
+}
+
+void SMTPAppender::setLocationInfo(bool newVal) {
+ locationInfo = newVal;
+}
+
+LogString SMTPAppender::getSMTPUsername() const {
+ return smtpUsername;
+}
+
+void SMTPAppender::setSMTPUsername(const LogString& newVal) {
+ smtpUsername = newVal;
+}
+
+LogString SMTPAppender::getSMTPPassword() const {
+ return smtpPassword;
+}
+
+void SMTPAppender::setSMTPPassword(const LogString& newVal) {
+ smtpPassword = newVal;
+}
+
+
+
+
+
+void SMTPAppender::setOption(const LogString& option,
+ const LogString& value)
+{
+ if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BUFFERSIZE"), LOG4CXX_STR("buffersize")))
+ {
+ setBufferSize(OptionConverter::toInt(value, 512));
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("EVALUATORCLASS"), LOG4CXX_STR("evaluatorclass")))
+ {
+ setEvaluatorClass(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("FROM"), LOG4CXX_STR("from")))
+ {
+ setFrom(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SMTPHOST"), LOG4CXX_STR("smtphost")))
+ {
+ setSMTPHost(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SMTPUSERNAME"), LOG4CXX_STR("smtpusername")))
+ {
+ setSMTPUsername(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SMTPPASSWORD"), LOG4CXX_STR("smtppassword")))
+ {
+ setSMTPPassword(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SUBJECT"), LOG4CXX_STR("subject")))
+ {
+ setSubject(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("TO"), LOG4CXX_STR("to")))
+ {
+ setTo(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("CC"), LOG4CXX_STR("cc")))
+ {
+ setCc(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BCC"), LOG4CXX_STR("bcc")))
+ {
+ setBcc(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SMTPPORT"), LOG4CXX_STR("smtpport")))
+ {
+ setSMTPPort(OptionConverter::toInt(value, 25));
+ }
+ else
+ {
+ AppenderSkeleton::setOption(option, value);
+ }
+}
+
+
+bool SMTPAppender::asciiCheck(const LogString& value, const LogString& field) {
+ for(LogString::const_iterator iter = value.begin();
+ iter != value.end();
+ iter++) {
+ if (0x7F < (unsigned int) *iter) {
+ LogLog::warn(field + LOG4CXX_STR(" contains non-ASCII character"));
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+Activate the specified options, such as the smtp host, the
+recipient, from, etc. */
+void SMTPAppender::activateOptions(Pool& p)
+{
+ bool activate = true;
+ if (layout == 0) {
+ LogLog::error(LOG4CXX_STR("No layout set for appender named [") +name+ LOG4CXX_STR("]."));
+ activate = false;
+ }
+ if(evaluator == 0) {
+ LogLog::error(LOG4CXX_STR("No TriggeringEventEvaluator is set for appender [")+
+ name+LOG4CXX_STR("]."));
+ activate = false;
+ }
+ if(smtpHost.empty()) {
+ LogLog::error(LOG4CXX_STR("No smtpHost is set for appender [")+
+ name+LOG4CXX_STR("]."));
+ activate = false;
+ }
+ if(to.empty() && cc.empty() && bcc.empty()) {
+ LogLog::error(LOG4CXX_STR("No recipient address is set for appender [")+
+ name+LOG4CXX_STR("]."));
+ activate = false;
+ }
+ activate &= asciiCheck(to, LOG4CXX_STR("to"));
+ activate &= asciiCheck(cc, LOG4CXX_STR("cc"));
+ activate &= asciiCheck(bcc, LOG4CXX_STR("bcc"));
+ activate &= asciiCheck(from, LOG4CXX_STR("from"));
+
+#if !LOG4CXX_HAS_LIBESMTP
+ LogLog::error(LOG4CXX_STR("log4cxx built without SMTP support."));
+ activate = false;
+#endif
+ if (activate) {
+ AppenderSkeleton::activateOptions(p);
+ }
+}
+
+/**
+Perform SMTPAppender specific appending actions, mainly adding
+the event to a cyclic buffer and checking if the event triggers
+an e-mail to be sent. */
+void SMTPAppender::append(const spi::LoggingEventPtr& event, Pool& p)
+{
+ if(!checkEntryConditions())
+ {
+ return;
+ }
+
+ LogString ndc;
+ event->getNDC(ndc);
+ event->getThreadName();
+ // Get a copy of this thread's MDC.
+ event->getMDCCopy();
+
+ cb.add(event);
+
+ if(evaluator->isTriggeringEvent(event))
+ {
+ sendBuffer(p);
+ }
+}
+
+/**
+This method determines if there is a sense in attempting to append.
+<p>It checks whether there is a set output target and also if
+there is a set layout. If these checks fail, then the boolean
+value <code>false</code> is returned. */
+bool SMTPAppender::checkEntryConditions()
+{
+#if LOG4CXX_HAVE_LIBESMTP
+ if((to.empty() && cc.empty() && bcc.empty()) || from.empty() || smtpHost.empty())
+ {
+ errorHandler->error(LOG4CXX_STR("Message not configured."));
+ return false;
+ }
+
+ if(evaluator == 0)
+ {
+ errorHandler->error(LOG4CXX_STR("No TriggeringEventEvaluator is set for appender [")+
+ name+ LOG4CXX_STR("]."));
+ return false;
+ }
+
+
+ if(layout == 0)
+ {
+ errorHandler->error(LOG4CXX_STR("No layout set for appender named [")+name+LOG4CXX_STR("]."));
+ return false;
+ }
+ return true;
+#else
+ return false;
+#endif
+}
+
+
+
+void SMTPAppender::close() {
+ this->closed = true;
+}
+
+LogString SMTPAppender::getTo() const{
+ return to;
+}
+
+void SMTPAppender::setTo(const LogString& addressStr) {
+ to = addressStr;
+}
+
+LogString SMTPAppender::getCc() const{
+ return cc;
+}
+
+void SMTPAppender::setCc(const LogString& addressStr) {
+ cc = addressStr;
+}
+
+LogString SMTPAppender::getBcc() const{
+ return bcc;
+}
+
+void SMTPAppender::setBcc(const LogString& addressStr) {
+ bcc = addressStr;
+}
+
+/**
+Send the contents of the cyclic buffer as an e-mail message.
+*/
+void SMTPAppender::sendBuffer(Pool& p)
+{
+#if LOG4CXX_HAS_LIBESMTP
+ // Note: this code already owns the monitor for this
+ // appender. This frees us from needing to synchronize on 'cb'.
+ try
+ {
+ LogString sbuf;
+ layout->appendHeader(sbuf, p);
+
+ int len = cb.length();
+ for(int i = 0; i < len; i++)
+ {
+ LoggingEventPtr event = cb.get();
+ layout->format(sbuf, event, p);
+ }
+
+ layout->appendFooter(sbuf, p);
+
+ SMTPSession session(smtpHost, smtpPort, smtpUsername, smtpPassword, p);
+
+ SMTPMessage message(session, from, to, cc,
+ bcc, subject, sbuf, p);
+
+ session.send(p);
+
+ }
+ catch(std::exception& e)
+ {
+ LogLog::error(LOG4CXX_STR("Error occured while sending e-mail notification."), e);
+ }
+#endif
+}
+
+/**
+Returns value of the <b>EvaluatorClass</b> option.
+*/
+LogString SMTPAppender::getEvaluatorClass()
+{
+ return evaluator == 0 ? LogString() : evaluator->getClass().getName();
+}
+
+log4cxx::spi::TriggeringEventEvaluatorPtr SMTPAppender::getEvaluator() const {
+ return evaluator;
+}
+
+void SMTPAppender::setEvaluator(log4cxx::spi::TriggeringEventEvaluatorPtr& trigger) {
+ evaluator = trigger;
+}
+
+/**
+The <b>BufferSize</b> option takes a positive integer
+representing the maximum number of logging events to collect in a
+cyclic buffer. When the <code>BufferSize</code> is reached,
+oldest events are deleted as new events are added to the
+buffer. By default the size of the cyclic buffer is 512 events.
+*/
+void SMTPAppender::setBufferSize(int bufferSize)
+{
+ this->bufferSize = bufferSize;
+ cb.resize(bufferSize);
+}
+
+/**
+The <b>EvaluatorClass</b> option takes a string value
+representing the name of the class implementing the {@link
+TriggeringEventEvaluator} interface. A corresponding object will
+be instantiated and assigned as the triggering event evaluator
+for the SMTPAppender.
+*/
+void SMTPAppender::setEvaluatorClass(const LogString& value)
+{
+ evaluator = OptionConverter::instantiateByClassName(value,
+ TriggeringEventEvaluator::getStaticClass(), evaluator);
+}
+
diff --git a/src/main/cpp/socket.cpp b/src/main/cpp/socket.cpp
new file mode 100644
index 0000000..ae83a3e
--- /dev/null
+++ b/src/main/cpp/socket.cpp
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/socket.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/transcoder.h>
+#include "apr_network_io.h"
+#include "apr_signal.h"
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(Socket)
+
+/** Creates a stream socket and connects it to the specified port
+number at the specified IP address.
+*/
+Socket::Socket(InetAddressPtr& address, int port) : pool(), socket(0), address(address), port(port)
+{
+ apr_status_t status =
+ apr_socket_create(&socket, APR_INET, SOCK_STREAM,
+ APR_PROTO_TCP, pool.getAPRPool());
+ if (status != APR_SUCCESS) {
+ throw SocketException(status);
+ }
+
+ LOG4CXX_ENCODE_CHAR(host, address->getHostAddress());
+
+ // create socket address (including port)
+ apr_sockaddr_t *client_addr;
+ status =
+ apr_sockaddr_info_get(&client_addr, host.c_str(), APR_INET,
+ port, 0, pool.getAPRPool());
+ if (status != APR_SUCCESS) {
+ throw ConnectException(status);
+ }
+
+ // connect the socket
+ status = apr_socket_connect(socket, client_addr);
+ if (status != APR_SUCCESS) {
+ throw ConnectException(status);
+ }
+}
+
+Socket::Socket(apr_socket_t* socket, apr_pool_t* pool) :
+ pool(pool, true), socket(socket) {
+ apr_sockaddr_t* sa;
+ apr_status_t status = apr_socket_addr_get(&sa, APR_REMOTE, socket);
+ if (status == APR_SUCCESS) {
+ port = sa->port;
+ LogString remotename;
+ LogString remoteip;
+ if (sa->hostname != NULL) {
+ Transcoder::decode(sa->hostname, remotename);
+ }
+ char* buf = 0;
+ status = apr_sockaddr_ip_get(&buf, sa);
+ if (status == APR_SUCCESS) {
+ Transcoder::decode(buf, remoteip);
+ }
+ address = new InetAddress(remotename, remoteip);
+ }
+}
+
+Socket::~Socket() {
+}
+
+size_t Socket::write(ByteBuffer& buf) {
+ if (socket == 0) {
+ throw ClosedChannelException();
+ }
+ int totalWritten = 0;
+ while(buf.remaining() > 0) {
+ apr_size_t written = buf.remaining();
+
+ // while writing to the socket, we need to ignore the SIGPIPE
+ // signal. Otherwise, when the client has closed the connection,
+ // the send() function would not return an error but call the
+ // SIGPIPE handler.
+#if APR_HAVE_SIGACTION
+ apr_sigfunc_t* old = apr_signal(SIGPIPE, SIG_IGN);
+ apr_status_t status = apr_socket_send(socket, buf.current(), &written);
+ apr_signal(SIGPIPE, old);
+#else
+ apr_status_t status = apr_socket_send(socket, buf.current(), &written);
+#endif
+
+ buf.position(buf.position() + written);
+ totalWritten += written;
+ if (status != APR_SUCCESS) {
+ throw SocketException(status);
+ }
+ }
+ return totalWritten;
+}
+
+
+void Socket::close() {
+ if (socket != 0) {
+ apr_status_t status = apr_socket_close(socket);
+ if (status != APR_SUCCESS) {
+ throw SocketException(status);
+ }
+ socket = 0;
+ }
+}
+
+InetAddressPtr Socket::getInetAddress() const {
+ return address;
+}
+
+int Socket::getPort() const {
+ return port;
+}
+
+
diff --git a/src/main/cpp/socketappender.cpp b/src/main/cpp/socketappender.cpp
new file mode 100644
index 0000000..833ee4a
--- /dev/null
+++ b/src/main/cpp/socketappender.cpp
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/net/socketappender.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/helpers/objectoutputstream.h>
+#include <apr_time.h>
+#include <apr_atomic.h>
+#include <apr_thread_proc.h>
+#include <log4cxx/helpers/socketoutputstream.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::net;
+
+IMPLEMENT_LOG4CXX_OBJECT(SocketAppender)
+
+
+// The default port number of remote logging server (4560)
+int SocketAppender::DEFAULT_PORT = 4560;
+
+// The default reconnection delay (30000 milliseconds or 30 seconds).
+int SocketAppender::DEFAULT_RECONNECTION_DELAY = 30000;
+
+
+
+SocketAppender::SocketAppender()
+: SocketAppenderSkeleton(DEFAULT_PORT, DEFAULT_RECONNECTION_DELAY) {
+}
+
+SocketAppender::SocketAppender(InetAddressPtr& address1, int port1)
+: SocketAppenderSkeleton(address1, port1, DEFAULT_RECONNECTION_DELAY) {
+ Pool p;
+ activateOptions(p);
+}
+
+SocketAppender::SocketAppender(const LogString& host, int port1)
+: SocketAppenderSkeleton(host, port1, DEFAULT_RECONNECTION_DELAY) {
+ Pool p;
+ activateOptions(p);
+}
+
+SocketAppender::~SocketAppender()
+{
+ finalize();
+}
+
+int SocketAppender::getDefaultDelay() const {
+ return DEFAULT_RECONNECTION_DELAY;
+}
+
+int SocketAppender::getDefaultPort() const {
+ return DEFAULT_PORT;
+}
+
+void SocketAppender::setSocket(log4cxx::helpers::SocketPtr& socket, Pool& p) {
+ synchronized sync(mutex);
+ oos = new ObjectOutputStream(new SocketOutputStream(socket), p);
+}
+
+void SocketAppender::cleanUp(Pool& p) {
+ if (oos != 0) {
+ try {
+ oos->close(p);
+ oos = 0;
+ } catch(std::exception& e) {
+ }
+ }
+}
+
+
+void SocketAppender::append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) {
+ if (oos != 0) {
+ LogString ndcVal;
+ event->getNDC(ndcVal);
+ event->getThreadName();
+ // Get a copy of this thread's MDC.
+ event->getMDCCopy();
+ try {
+ event->write(*oos, p);
+ oos->flush(p);
+ } catch(std::exception& e) {
+ oos = 0;
+ LogLog::warn(LOG4CXX_STR("Detected problem with connection: "), e);
+ if (getReconnectionDelay() > 0) {
+ fireConnector();
+ }
+ }
+ }
+}
diff --git a/src/main/cpp/socketappenderskeleton.cpp b/src/main/cpp/socketappenderskeleton.cpp
new file mode 100755
index 0000000..822e4ac
--- /dev/null
+++ b/src/main/cpp/socketappenderskeleton.cpp
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#define __STDC_CONSTANT_MACROS
+#include <log4cxx/net/socketappenderskeleton.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/bytearrayoutputstream.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::net;
+
+SocketAppenderSkeleton::SocketAppenderSkeleton(int defaultPort, int reconnectionDelay1)
+: remoteHost(),
+ address(),
+ port(defaultPort),
+ reconnectionDelay(reconnectionDelay1),
+ locationInfo(false),
+ thread() {
+}
+
+SocketAppenderSkeleton::SocketAppenderSkeleton(InetAddressPtr address1, int port1, int delay)
+:
+ remoteHost(),
+ address(address1),
+ port(port1),
+ reconnectionDelay(delay),
+ locationInfo(false),
+ thread() {
+ remoteHost = this->address->getHostName();
+}
+
+SocketAppenderSkeleton::SocketAppenderSkeleton(const LogString& host, int port1, int delay)
+: remoteHost(host),
+ address(InetAddress::getByName(host)),
+ port(port1),
+ reconnectionDelay(delay),
+ locationInfo(false),
+ thread() {
+}
+
+SocketAppenderSkeleton::~SocketAppenderSkeleton()
+{
+ finalize();
+}
+
+void SocketAppenderSkeleton::activateOptions(Pool& p)
+{
+ AppenderSkeleton::activateOptions(p);
+ connect(p);
+}
+
+void SocketAppenderSkeleton::close() {
+ synchronized sync(mutex);
+ if (closed) return;
+ closed = true;
+ cleanUp(pool);
+ thread.interrupt();
+}
+
+void SocketAppenderSkeleton::connect(Pool& p) {
+ if (address == 0) {
+ LogLog::error(LogString(LOG4CXX_STR("No remote host is set for Appender named \"")) +
+ name + LOG4CXX_STR("\"."));
+ } else {
+ cleanUp(p);
+ try {
+ SocketPtr socket(new Socket(address, port));
+ setSocket(socket, p);
+ } catch(SocketException& e) {
+ LogString msg = LOG4CXX_STR("Could not connect to remote log4cxx server at [")
+ +address->getHostName()+LOG4CXX_STR("].");
+ if(reconnectionDelay > 0)
+ {
+ msg += LOG4CXX_STR(" We will try again later. ");
+ }
+ fireConnector(); // fire the connector thread
+ LogLog::error(msg, e);
+ }
+ }
+}
+
+void SocketAppenderSkeleton::setOption(const LogString& option, const LogString& value)
+{
+ if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("REMOTEHOST"), LOG4CXX_STR("remotehost")))
+ {
+ setRemoteHost(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("PORT"), LOG4CXX_STR("port")))
+ {
+ setPort(OptionConverter::toInt(value, getDefaultPort()));
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("LOCATIONINFO"), LOG4CXX_STR("locationinfo")))
+ {
+ setLocationInfo(OptionConverter::toBoolean(value, false));
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("RECONNECTIONDELAY"), LOG4CXX_STR("reconnectiondelay")))
+ {
+ setReconnectionDelay(OptionConverter::toInt(value, getDefaultDelay()));
+ }
+ else
+ {
+ AppenderSkeleton::setOption(option, value);
+ }
+}
+
+void SocketAppenderSkeleton::fireConnector()
+{
+ synchronized sync(mutex);
+ if (thread.isActive()) {
+ thread.run(monitor, this);
+ }
+}
+
+void* LOG4CXX_THREAD_FUNC SocketAppenderSkeleton::monitor(apr_thread_t* /* thread */, void* data) {
+ SocketAppenderSkeleton* socketAppender = (SocketAppenderSkeleton*) data;
+ SocketPtr socket;
+ bool isClosed = socketAppender->closed;
+ while(!isClosed)
+ {
+ try
+ {
+ Thread::sleep(socketAppender->reconnectionDelay);
+ LogLog::debug(LogString(LOG4CXX_STR("Attempting connection to "))
+ + socketAppender->address->getHostName());
+ socket = new Socket(socketAppender->address, socketAppender->port);
+ Pool p;
+ socketAppender->setSocket(socket, p);
+ LogLog::debug(LOG4CXX_STR("Connection established. Exiting connector thread."));
+ return NULL;
+ }
+ catch(ConnectException&)
+ {
+ LogLog::debug(LOG4CXX_STR("Remote host ")
+ +socketAppender->address->getHostName()
+ +LOG4CXX_STR(" refused connection."));
+ }
+ catch(IOException& e)
+ {
+ LogString exmsg;
+ log4cxx::helpers::Transcoder::decode(e.what(), exmsg);
+
+ LogLog::debug(((LogString) LOG4CXX_STR("Could not connect to "))
+ + socketAppender->address->getHostName()
+ + LOG4CXX_STR(". Exception is ")
+ + exmsg);
+ }
+ isClosed = socketAppender->closed;
+ }
+
+ LogLog::debug(LOG4CXX_STR("Exiting Connector.run() method."));
+ return NULL;
+}
diff --git a/src/main/cpp/sockethubappender.cpp b/src/main/cpp/sockethubappender.cpp
new file mode 100644
index 0000000..8b92d5e
--- /dev/null
+++ b/src/main/cpp/sockethubappender.cpp
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/net/sockethubappender.h>
+
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/serversocket.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <apr_atomic.h>
+#include <apr_thread_proc.h>
+#include <log4cxx/helpers/objectoutputstream.h>
+#include <log4cxx/helpers/socketoutputstream.h>
+#include <log4cxx/helpers/exception.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::net;
+using namespace log4cxx::spi;
+
+#if APR_HAS_THREADS
+
+IMPLEMENT_LOG4CXX_OBJECT(SocketHubAppender)
+
+int SocketHubAppender::DEFAULT_PORT = 4560;
+
+SocketHubAppender::~SocketHubAppender()
+{
+ finalize();
+}
+
+SocketHubAppender::SocketHubAppender()
+ : port(DEFAULT_PORT), streams(), locationInfo(false), thread()
+{
+}
+
+SocketHubAppender::SocketHubAppender(int port1)
+ : port(port1), streams(), locationInfo(false), thread()
+{
+ startServer();
+}
+
+void SocketHubAppender::activateOptions(Pool& /* p */ )
+{
+ startServer();
+}
+
+void SocketHubAppender::setOption(const LogString& option,
+ const LogString& value)
+{
+ if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("PORT"), LOG4CXX_STR("port")))
+ {
+ setPort(OptionConverter::toInt(value, DEFAULT_PORT));
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("LOCATIONINFO"), LOG4CXX_STR("locationinfo")))
+ {
+ setLocationInfo(OptionConverter::toBoolean(value, true));
+ }
+ else
+ {
+ AppenderSkeleton::setOption(option, value);
+ }
+}
+
+
+void SocketHubAppender::close()
+{
+ {
+ synchronized sync(mutex);
+ if (closed) {
+ return;
+ }
+ closed = true;
+ }
+
+ LogLog::debug(LOG4CXX_STR("closing SocketHubAppender ") + getName());
+ //
+ // wait until the server thread completes
+ //
+ thread.join();
+
+ synchronized sync(mutex);
+ // close all of the connections
+ LogLog::debug(LOG4CXX_STR("closing client connections"));
+ for (std::vector<helpers::ObjectOutputStreamPtr>::iterator iter = streams.begin();
+ iter != streams.end();
+ iter++) {
+ if ( (*iter) != NULL) {
+ try {
+ (*iter)->close(pool);
+ } catch(SocketException& e) {
+ LogLog::error(LOG4CXX_STR("could not close socket: "), e);
+ }
+ }
+ }
+ streams.erase(streams.begin(), streams.end());
+
+
+ LogLog::debug(LOG4CXX_STR("SocketHubAppender ")
+ + getName() + LOG4CXX_STR(" closed"));
+}
+
+void SocketHubAppender::append(const spi::LoggingEventPtr& event, Pool& p)
+{
+
+ // if no open connections, exit now
+ if(streams.empty())
+ {
+ return;
+ }
+
+ LogString ndcVal;
+ event->getNDC(ndcVal);
+ event->getThreadName();
+ // Get a copy of this thread's MDC.
+ event->getMDCCopy();
+
+
+ // loop through the current set of open connections, appending the event to each
+ std::vector<ObjectOutputStreamPtr>::iterator it = streams.begin();
+ std::vector<ObjectOutputStreamPtr>::iterator itEnd = streams.end();
+ while(it != itEnd)
+ {
+ // list size changed unexpectedly? Just exit the append.
+ if (*it == 0)
+ {
+ break;
+ }
+
+ try
+ {
+ event->write(**it, p);
+ (*it)->flush(p);
+ it++;
+ }
+ catch(std::exception& e)
+ {
+ // there was an io exception so just drop the connection
+ it = streams.erase(it);
+ LogLog::debug(LOG4CXX_STR("dropped connection"), e);
+ }
+ }
+}
+
+void SocketHubAppender::startServer()
+{
+ thread.run(monitor, this);
+}
+
+void* APR_THREAD_FUNC SocketHubAppender::monitor(apr_thread_t* /* thread */, void* data) {
+ SocketHubAppender* pThis = (SocketHubAppender*) data;
+
+ ServerSocket* serverSocket = 0;
+
+ try
+ {
+ serverSocket = new ServerSocket(pThis->port);
+ serverSocket->setSoTimeout(1000);
+ }
+ catch (SocketException& e)
+ {
+ LogLog::error(LOG4CXX_STR("exception setting timeout, shutting down server socket."), e);
+ delete serverSocket;
+ return NULL;
+ }
+
+ bool stopRunning = pThis->closed;
+ while (!stopRunning)
+ {
+ SocketPtr socket;
+ try
+ {
+ socket = serverSocket->accept();
+ }
+ catch (InterruptedIOException&)
+ {
+ // timeout occurred, so just loop
+ }
+ catch (SocketException& e)
+ {
+ LogLog::error(LOG4CXX_STR("exception accepting socket, shutting down server socket."), e);
+ stopRunning = true;
+ }
+ catch (IOException& e)
+ {
+ LogLog::error(LOG4CXX_STR("exception accepting socket."), e);
+ }
+
+ // if there was a socket accepted
+ if (socket != 0)
+ {
+ try
+ {
+ InetAddressPtr remoteAddress = socket->getInetAddress();
+ LogLog::debug(LOG4CXX_STR("accepting connection from ")
+ + remoteAddress->getHostName()
+ + LOG4CXX_STR(" (")
+ + remoteAddress->getHostAddress()
+ + LOG4CXX_STR(")"));
+
+ // add it to the oosList.
+ synchronized sync(pThis->mutex);
+ OutputStreamPtr os(new SocketOutputStream(socket));
+ Pool p;
+ ObjectOutputStreamPtr oos(new ObjectOutputStream(os, p));
+ pThis->streams.push_back(oos);
+ }
+ catch (IOException& e)
+ {
+ LogLog::error(LOG4CXX_STR("exception creating output stream on socket."), e);
+ }
+ }
+ stopRunning = (stopRunning || pThis->closed);
+ }
+ delete serverSocket;
+ return NULL;
+}
+
+#endif
diff --git a/src/main/cpp/socketoutputstream.cpp b/src/main/cpp/socketoutputstream.cpp
new file mode 100644
index 0000000..185f835
--- /dev/null
+++ b/src/main/cpp/socketoutputstream.cpp
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/socketoutputstream.h>
+#include <log4cxx/helpers/socket.h>
+#include <log4cxx/helpers/bytebuffer.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(SocketOutputStream)
+
+SocketOutputStream::SocketOutputStream(const SocketPtr& socket1)
+: socket(socket1) {
+}
+
+SocketOutputStream::~SocketOutputStream() {
+}
+
+void SocketOutputStream::close(Pool& p) {
+ flush(p);
+ socket->close();
+}
+
+void SocketOutputStream::flush(Pool& /* p */) {
+ if (array.size() > 0) {
+ ByteBuffer buf((char*) &array[0], array.size());
+ socket->write(buf);
+ array.resize(0);
+ }
+}
+
+void SocketOutputStream::write(ByteBuffer& buf, Pool& /* p */ ) {
+ if (buf.remaining() > 0) {
+ size_t sz = array.size();
+ array.resize(sz + buf.remaining());
+ memcpy(&array[sz], buf.current(), buf.remaining());
+ buf.position(buf.limit());
+ }
+}
+
+
diff --git a/src/main/cpp/strftimedateformat.cpp b/src/main/cpp/strftimedateformat.cpp
new file mode 100644
index 0000000..120f60b
--- /dev/null
+++ b/src/main/cpp/strftimedateformat.cpp
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/strftimedateformat.h>
+
+#include <apr_time.h>
+#include <log4cxx/helpers/transcoder.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+StrftimeDateFormat::StrftimeDateFormat(const LogString& fmt)
+ : timeZone(TimeZone::getDefault()) {
+ log4cxx::helpers::Transcoder::encode(fmt, pattern);
+}
+
+StrftimeDateFormat::~StrftimeDateFormat() {
+}
+
+
+void StrftimeDateFormat::format(LogString& s, log4cxx_time_t time, Pool& /* p */ ) const {
+ apr_time_exp_t exploded;
+ apr_status_t stat = timeZone->explode(&exploded, time);
+ if (stat == APR_SUCCESS) {
+ const apr_size_t bufSize = 255;
+ char buf[bufSize];
+ apr_size_t bufLen;
+ stat = apr_strftime(buf, &bufLen, bufSize, pattern.c_str(), &exploded);
+ if (stat == APR_SUCCESS) {
+ log4cxx::helpers::Transcoder::decode(std::string(buf, bufLen), s);
+ }
+ }
+}
+
+void StrftimeDateFormat::setTimeZone(const TimeZonePtr& zone) {
+ timeZone = zone;
+}
+
+
diff --git a/src/main/cpp/stringhelper.cpp b/src/main/cpp/stringhelper.cpp
new file mode 100644
index 0000000..ca4b1ac
--- /dev/null
+++ b/src/main/cpp/stringhelper.cpp
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define __STDC_CONSTANT_MACROS
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <algorithm>
+#include <vector>
+#include <apr_strings.h>
+#include <log4cxx/helpers/pool.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+#include <cctype>
+#include <apr.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+bool StringHelper::equalsIgnoreCase(const LogString& s1, const logchar* upper, const logchar* lower) {
+ for (LogString::const_iterator iter = s1.begin();
+ iter != s1.end();
+ iter++, upper++, lower++) {
+ if (*iter != *upper && *iter != * lower) return false;
+ }
+ return (*upper == 0);
+}
+
+bool StringHelper::equalsIgnoreCase(const LogString& s1, const LogString& upper, const LogString& lower) {
+ LogString::const_iterator u = upper.begin();
+ LogString::const_iterator l = lower.begin();
+ LogString::const_iterator iter = s1.begin();
+ for (;
+ iter != s1.end() && u != upper.end() && l != lower.end();
+ iter++, u++, l++) {
+ if (*iter != *u && *iter != *l) return false;
+ }
+ return u == upper.end() && iter == s1.end();
+}
+
+
+
+LogString StringHelper::toLowerCase(const LogString& s)
+{
+ LogString d;
+ std::transform(s.begin(), s.end(),
+ std::insert_iterator<LogString>(d, d.begin()), tolower);
+ return d;
+}
+
+LogString StringHelper::trim(const LogString& s)
+{
+ LogString::size_type pos = s.find_first_not_of(' ');
+ if (pos == std::string::npos)
+ {
+ return LogString();
+ }
+
+ LogString::size_type n = s.find_last_not_of(' ') - pos + 1;
+ return s.substr(pos, n);
+}
+
+bool StringHelper::startsWith(const LogString& s, const LogString& prefix)
+{
+ return s.compare(0, prefix.length(), prefix) == 0;
+}
+
+bool StringHelper::endsWith(const LogString& s, const LogString& suffix)
+{
+ if (suffix.length() <= s.length()) {
+ return s.compare(s.length() - suffix.length(), suffix.length(), suffix) == 0;
+ }
+ return false;
+}
+
+
+int StringHelper::toInt(const LogString& s) {
+ std::string as;
+ Transcoder::encode(s, as);
+ return atoi(as.c_str());
+}
+
+log4cxx_int64_t StringHelper::toInt64(const LogString& s) {
+ std::string as;
+ Transcoder::encode(s, as);
+ return apr_atoi64(as.c_str());
+}
+
+void StringHelper::toString(int n, Pool& pool, LogString& s) {
+ char* fmt = pool.itoa(n);
+ Transcoder::decode(fmt, s);
+}
+
+void StringHelper::toString(bool val, LogString& dst) {
+ if (val) {
+ dst.append(LOG4CXX_STR("true"));
+ } else {
+ dst.append(LOG4CXX_STR("false"));
+ }
+}
+
+
+void StringHelper::toString(log4cxx_int64_t n, Pool& pool, LogString& dst) {
+ if (n >= INT_MIN && n <= INT_MAX) {
+ toString((int) n, pool, dst);
+ } else {
+ const log4cxx_int64_t BILLION = APR_INT64_C(1000000000);
+ int billions = (int) (n / BILLION);
+ char* upper = pool.itoa(billions);
+ int remain = (int) (n - billions * BILLION);
+ if (remain < 0) remain *= -1;
+ char* lower = pool.itoa(remain);
+ Transcoder::decode(upper, dst);
+ dst.append(9 - strlen(lower), 0x30 /* '0' */);
+ Transcoder::decode(lower, dst);
+ }
+}
+
+
+void StringHelper::toString(size_t n, Pool& pool, LogString& s) {
+ toString((log4cxx_int64_t) n, pool, s);
+}
+
+LogString StringHelper::format(const LogString& pattern, const std::vector<LogString>& params) {
+
+ LogString result;
+ int i = 0;
+ while(pattern[i] != 0) {
+ if (pattern[i] == 0x7B /* '{' */ && pattern[i + 1] >= 0x30 /* '0' */ &&
+ pattern[i + 1] <= 0x39 /* '9' */ && pattern[i + 2] == 0x7D /* '}' */) {
+ int arg = pattern[i + 1] - 0x30 /* '0' */;
+ result = result + params[arg];
+ i += 3;
+ } else {
+ result = result + pattern[i];
+ i++;
+ }
+ }
+
+ return result;
+}
+
diff --git a/src/main/cpp/stringmatchfilter.cpp b/src/main/cpp/stringmatchfilter.cpp
new file mode 100644
index 0000000..96f1d9b
--- /dev/null
+++ b/src/main/cpp/stringmatchfilter.cpp
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/filter/stringmatchfilter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/optionconverter.h>
+
+using namespace log4cxx;
+using namespace log4cxx::filter;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(StringMatchFilter)
+
+StringMatchFilter::StringMatchFilter() :
+ acceptOnMatch(true),
+ stringToMatch()
+{
+}
+
+void StringMatchFilter::setOption(const LogString& option,
+ const LogString& value)
+{
+
+ if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("STRINGTOMATCH"), LOG4CXX_STR("stringtomatch")))
+ {
+ stringToMatch = value;
+ }
+ else if (StringHelper::equalsIgnoreCase(option,
+ LOG4CXX_STR("ACCEPTONMATCH"), LOG4CXX_STR("acceptonmatch")))
+ {
+ acceptOnMatch = OptionConverter::toBoolean(value, acceptOnMatch);
+ }
+}
+
+Filter::FilterDecision StringMatchFilter::decide(
+ const log4cxx::spi::LoggingEventPtr& event) const
+{
+ const LogString& msg = event->getRenderedMessage();
+
+ if(msg.empty() || stringToMatch.empty())
+ {
+ return Filter::NEUTRAL;
+ }
+
+
+ if( msg.find(stringToMatch) == LogString::npos )
+ {
+ return Filter::NEUTRAL;
+ }
+ else
+ { // we've got a match
+ if(acceptOnMatch)
+ {
+ return Filter::ACCEPT;
+ }
+ else
+ {
+ return Filter::DENY;
+ }
+ }
+}
+
diff --git a/src/main/cpp/stringtokenizer.cpp b/src/main/cpp/stringtokenizer.cpp
new file mode 100644
index 0000000..3f015e5
--- /dev/null
+++ b/src/main/cpp/stringtokenizer.cpp
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/stringtokenizer.h>
+#include <log4cxx/helpers/exception.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+StringTokenizer::StringTokenizer(const LogString& str, const LogString& delim1)
+: src(str), delim(delim1), pos(0)
+{
+}
+
+StringTokenizer::~StringTokenizer()
+{
+}
+
+bool StringTokenizer::hasMoreTokens() const
+{
+ return (pos != LogString::npos
+ && src.find_first_not_of(delim, pos) != LogString::npos);
+}
+
+LogString StringTokenizer::nextToken()
+{
+ if (pos != LogString::npos) {
+ size_t nextPos = src.find_first_not_of(delim, pos);
+ if (nextPos != LogString::npos) {
+ pos = src.find_first_of(delim, nextPos);
+ if (pos == LogString::npos) {
+ return src.substr(nextPos);
+ }
+ return src.substr(nextPos, pos - nextPos);
+ }
+ }
+ throw NoSuchElementException();
+#if LOG4CXX_RETURN_AFTER_THROW
+ return LogString();
+#endif
+}
diff --git a/src/main/cpp/synchronized.cpp b/src/main/cpp/synchronized.cpp
new file mode 100755
index 0000000..cab2715
--- /dev/null
+++ b/src/main/cpp/synchronized.cpp
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/helpers/mutex.h>
+#include <log4cxx/helpers/exception.h>
+
+#include <apr_thread_mutex.h>
+
+using namespace log4cxx::helpers;
+using namespace log4cxx;
+
+synchronized::synchronized(const Mutex& mutex1)
+: mutex(mutex1.getAPRMutex())
+{
+#if APR_HAS_THREADS
+ apr_status_t stat = apr_thread_mutex_lock(
+ (apr_thread_mutex_t*) this->mutex);
+ if (stat != APR_SUCCESS) {
+ throw MutexException(stat);
+ }
+#endif
+}
+
+synchronized::~synchronized()
+{
+#if APR_HAS_THREADS
+ apr_status_t stat = apr_thread_mutex_unlock(
+ (apr_thread_mutex_t*) mutex);
+ if (stat != APR_SUCCESS) {
+ throw MutexException(stat);
+ }
+#endif
+}
diff --git a/src/main/cpp/syslogappender.cpp b/src/main/cpp/syslogappender.cpp
new file mode 100644
index 0000000..83baca7
--- /dev/null
+++ b/src/main/cpp/syslogappender.cpp
@@ -0,0 +1,356 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/net/syslogappender.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/datagramsocket.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/level.h>
+#include <log4cxx/helpers/transcoder.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+
+#if LOG4CXX_HAVE_SYSLOG
+#include <syslog.h>
+#else
+ /* facility codes */
+ #define LOG_KERN (0<<3) /* kernel messages */
+ #define LOG_USER (1<<3) /* random user-level messages */
+ #define LOG_MAIL (2<<3) /* mail system */
+ #define LOG_DAEMON (3<<3) /* system daemons */
+ #define LOG_AUTH (4<<3) /* security/authorization messages */
+ #define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
+ #define LOG_LPR (6<<3) /* line printer subsystem */
+ #define LOG_NEWS (7<<3) /* network news subsystem */
+ #define LOG_UUCP (8<<3) /* UUCP subsystem */
+ #define LOG_CRON (9<<3) /* clock daemon */
+ #define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */
+ #define LOG_FTP (11<<3) /* ftp daemon */
+
+ /* other codes through 15 reserved for system use */
+ #define LOG_LOCAL0 (16<<3) /* reserved for local use */
+ #define LOG_LOCAL1 (17<<3) /* reserved for local use */
+ #define LOG_LOCAL2 (18<<3) /* reserved for local use */
+ #define LOG_LOCAL3 (19<<3) /* reserved for local use */
+ #define LOG_LOCAL4 (20<<3) /* reserved for local use */
+ #define LOG_LOCAL5 (21<<3) /* reserved for local use */
+ #define LOG_LOCAL6 (22<<3) /* reserved for local use */
+ #define LOG_LOCAL7 (23<<3) /* reserved for local use */
+#endif
+
+#define LOG_UNDEF -1
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::net;
+
+IMPLEMENT_LOG4CXX_OBJECT(SyslogAppender)
+
+SyslogAppender::SyslogAppender()
+: syslogFacility(LOG_USER), facilityPrinting(false), sw(0)
+{
+ this->initSyslogFacilityStr();
+
+}
+
+SyslogAppender::SyslogAppender(const LayoutPtr& layout1,
+ int syslogFacility1)
+: syslogFacility(syslogFacility1), facilityPrinting(false), sw(0)
+{
+ this->layout = layout1;
+ this->initSyslogFacilityStr();
+}
+
+SyslogAppender::SyslogAppender(const LayoutPtr& layout1,
+ const LogString& syslogHost1, int syslogFacility1)
+: syslogFacility(syslogFacility1), facilityPrinting(false), sw(0)
+{
+ this->layout = layout1;
+ this->initSyslogFacilityStr();
+ setSyslogHost(syslogHost1);
+}
+
+SyslogAppender::~SyslogAppender()
+{
+ finalize();
+}
+
+/** Release any resources held by this SyslogAppender.*/
+void SyslogAppender::close()
+{
+ closed = true;
+ if (sw != 0)
+ {
+ delete sw;
+ sw = 0;
+ }
+}
+
+void SyslogAppender::initSyslogFacilityStr()
+{
+ facilityStr = getFacilityString(this->syslogFacility);
+
+ if (facilityStr.empty())
+ {
+ Pool p;
+ LogString msg(LOG4CXX_STR("\""));
+ StringHelper::toString(syslogFacility, p, msg);
+ msg.append(LOG4CXX_STR("\" is an unknown syslog facility. Defaulting to \"USER\"."));
+ LogLog::error(msg);
+ this->syslogFacility = LOG_USER;
+ facilityStr = LOG4CXX_STR("user:");
+ }
+ else
+ {
+ facilityStr += LOG4CXX_STR(":");
+ }
+}
+
+/**
+Returns the specified syslog facility as a lower-case String,
+e.g. "kern", "user", etc.
+*/
+LogString SyslogAppender::getFacilityString(
+ int syslogFacility)
+{
+ switch(syslogFacility)
+ {
+ case LOG_KERN: return LOG4CXX_STR("kern");
+ case LOG_USER: return LOG4CXX_STR("user");
+ case LOG_MAIL: return LOG4CXX_STR("mail");
+ case LOG_DAEMON: return LOG4CXX_STR("daemon");
+ case LOG_AUTH: return LOG4CXX_STR("auth");
+ case LOG_SYSLOG: return LOG4CXX_STR("syslog");
+ case LOG_LPR: return LOG4CXX_STR("lpr");
+ case LOG_NEWS: return LOG4CXX_STR("news");
+ case LOG_UUCP: return LOG4CXX_STR("uucp");
+ case LOG_CRON: return LOG4CXX_STR("cron");
+#ifdef LOG_AUTHPRIV
+ case LOG_AUTHPRIV: return LOG4CXX_STR("authpriv");
+#endif
+#ifdef LOG_FTP
+ case LOG_FTP: return LOG4CXX_STR("ftp");
+#endif
+ case LOG_LOCAL0: return LOG4CXX_STR("local0");
+ case LOG_LOCAL1: return LOG4CXX_STR("local1");
+ case LOG_LOCAL2: return LOG4CXX_STR("local2");
+ case LOG_LOCAL3: return LOG4CXX_STR("local3");
+ case LOG_LOCAL4: return LOG4CXX_STR("local4");
+ case LOG_LOCAL5: return LOG4CXX_STR("local5");
+ case LOG_LOCAL6: return LOG4CXX_STR("local6");
+ case LOG_LOCAL7: return LOG4CXX_STR("local7");
+ default: return LogString();
+ }
+}
+
+int SyslogAppender::getFacility(
+ const LogString& s)
+{
+ if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("KERN"), LOG4CXX_STR("kern")))
+ {
+ return LOG_KERN;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("USER"), LOG4CXX_STR("user")))
+ {
+ return LOG_USER;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("MAIL"), LOG4CXX_STR("mail")))
+ {
+ return LOG_MAIL;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("DAEMON"), LOG4CXX_STR("daemon")))
+ {
+ return LOG_DAEMON;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("AUTH"), LOG4CXX_STR("auth")))
+ {
+ return LOG_AUTH;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("SYSLOG"), LOG4CXX_STR("syslog")))
+ {
+ return LOG_SYSLOG;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LPR"), LOG4CXX_STR("lpr")))
+ {
+ return LOG_LPR;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("NEWS"), LOG4CXX_STR("news")))
+ {
+ return LOG_NEWS;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("UUCP"), LOG4CXX_STR("uucp")))
+ {
+ return LOG_UUCP;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("CRON"), LOG4CXX_STR("cron")))
+ {
+ return LOG_CRON;
+ }
+#ifdef LOG_AUTHPRIV
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("AUTHPRIV"), LOG4CXX_STR("authpriv")))
+ {
+ return LOG_AUTHPRIV;
+ }
+#endif
+#ifdef LOG_FTP
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("FTP"), LOG4CXX_STR("ftp")))
+ {
+ return LOG_FTP;
+ }
+#endif
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL0"), LOG4CXX_STR("local0")))
+ {
+ return LOG_LOCAL0;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL1"), LOG4CXX_STR("local1")))
+ {
+ return LOG_LOCAL1;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL1"), LOG4CXX_STR("local2")))
+ {
+ return LOG_LOCAL2;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL1"), LOG4CXX_STR("local3")))
+ {
+ return LOG_LOCAL3;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL1"), LOG4CXX_STR("local4")))
+ {
+ return LOG_LOCAL4;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL1"), LOG4CXX_STR("local5")))
+ {
+ return LOG_LOCAL5;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL1"), LOG4CXX_STR("local6")))
+ {
+ return LOG_LOCAL6;
+ }
+ else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL1"), LOG4CXX_STR("local7")))
+ {
+ return LOG_LOCAL7;
+ }
+ else
+ {
+ return LOG_UNDEF;
+ }
+}
+
+void SyslogAppender::append(const spi::LoggingEventPtr& event, Pool& p)
+{
+ if (!isAsSevereAsThreshold(event->getLevel()))
+ return;
+
+ LogString msg;
+ layout->format(msg, event, p);
+
+// On the local host, we can directly use the system function 'syslog'
+// if it is available
+#if LOG4CXX_HAVE_SYSLOG
+ if (sw == 0)
+ {
+ std::string sbuf;
+ Transcoder::encode(msg, sbuf);
+
+ // use of "%s" to avoid a security hole
+ ::syslog(syslogFacility | event->getLevel()->getSyslogEquivalent(),
+ "%s", sbuf.c_str());
+
+ return;
+ }
+#endif
+
+ // We must not attempt to append if sw is null.
+ if(sw == 0)
+ {
+ errorHandler->error(LOG4CXX_STR("No syslog host is set for SyslogAppedender named \"")+
+ this->name+LOG4CXX_STR("\"."));
+ return;
+ }
+
+ LogString sbuf(1, 0x3C /* '<' */);
+ StringHelper::toString((syslogFacility | event->getLevel()->getSyslogEquivalent()), p, sbuf);
+ sbuf.append(1, (logchar) 0x3E /* '>' */);
+ if (facilityPrinting)
+ {
+ sbuf.append(facilityStr);
+ }
+ sbuf.append(msg);
+ sw->write(sbuf);
+}
+
+void SyslogAppender::activateOptions(Pool&)
+{
+}
+
+void SyslogAppender::setOption(const LogString& option, const LogString& value)
+{
+ if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SYSLOGHOST"), LOG4CXX_STR("sysloghost")))
+ {
+ setSyslogHost(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("FACILITY"), LOG4CXX_STR("facility")))
+ {
+ setFacility(value);
+ }
+ else
+ {
+ AppenderSkeleton::setOption(option, value);
+ }
+}
+
+void SyslogAppender::setSyslogHost(const LogString& syslogHost1)
+{
+ if (this->sw != 0)
+ {
+ delete this->sw;
+ this->sw = 0;
+ }
+
+// On the local host, we can directly use the system function 'syslog'
+// if it is available (cf. append)
+#if LOG4CXX_HAVE_SYSLOG
+ if (syslogHost1 != LOG4CXX_STR("localhost") && syslogHost1 != LOG4CXX_STR("127.0.0.1")
+ && !syslogHost1.empty())
+#endif
+ this->sw = new SyslogWriter(syslogHost1);
+
+ this->syslogHost = syslogHost1;
+}
+
+
+void SyslogAppender::setFacility(const LogString& facilityName)
+{
+ if (facilityName.empty())
+ {
+ return;
+ }
+
+ syslogFacility = getFacility(facilityName);
+ if (syslogFacility == LOG_UNDEF)
+ {
+ LogLog::error(LOG4CXX_STR("[")+facilityName +
+ LOG4CXX_STR("] is an unknown syslog facility. Defaulting to [USER]."));
+ syslogFacility = LOG_USER;
+ }
+
+ this->initSyslogFacilityStr();
+}
+
diff --git a/src/main/cpp/syslogwriter.cpp b/src/main/cpp/syslogwriter.cpp
new file mode 100644
index 0000000..5267907
--- /dev/null
+++ b/src/main/cpp/syslogwriter.cpp
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/syslogwriter.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/inetaddress.h>
+#include <log4cxx/helpers/datagramsocket.h>
+#include <log4cxx/helpers/datagrampacket.h>
+#include <log4cxx/helpers/transcoder.h>
+
+#define SYSLOG_PORT 514
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+SyslogWriter::SyslogWriter(const LogString& syslogHost1)
+: syslogHost(syslogHost1)
+{
+ try
+ {
+ this->address = InetAddress::getByName(syslogHost1);
+ }
+ catch(UnknownHostException& e)
+ {
+ LogLog::error(((LogString) LOG4CXX_STR("Could not find ")) + syslogHost1 +
+ LOG4CXX_STR(". All logging will FAIL."), e);
+ }
+
+ try
+ {
+ this->ds = new DatagramSocket();
+ }
+ catch (SocketException& e)
+ {
+ LogLog::error(((LogString) LOG4CXX_STR("Could not instantiate DatagramSocket to ")) + syslogHost1 +
+ LOG4CXX_STR(". All logging will FAIL."), e);
+ }
+}
+
+void SyslogWriter::write(const LogString& source) {
+ if (this->ds != 0 && this->address != 0) {
+ LOG4CXX_ENCODE_CHAR(data, source);
+
+ DatagramPacketPtr packet(
+ new DatagramPacket((void*) data.data(), data.length(),
+ address, SYSLOG_PORT));
+
+ ds->send(packet);
+ }
+}
diff --git a/src/main/cpp/system.cpp b/src/main/cpp/system.cpp
new file mode 100644
index 0000000..2d3c11b
--- /dev/null
+++ b/src/main/cpp/system.cpp
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/system.h>
+
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/pool.h>
+#include <apr_file_io.h>
+#include <apr_user.h>
+#include <apr_env.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+LogString System::getProperty(const LogString& lkey)
+{
+ if (lkey.empty())
+ {
+ throw IllegalArgumentException(LOG4CXX_STR("key is empty"));
+ }
+
+ LogString rv;
+ if (lkey == LOG4CXX_STR("java.io.tmpdir")) {
+ Pool p;
+ const char* dir = NULL;
+ apr_status_t stat = apr_temp_dir_get(&dir, p.getAPRPool());
+ if (stat == APR_SUCCESS) {
+ Transcoder::decode(dir, rv);
+ }
+ return rv;
+ }
+
+ if (lkey == LOG4CXX_STR("user.dir")) {
+ Pool p;
+ char* dir = NULL;
+ apr_status_t stat = apr_filepath_get(&dir, APR_FILEPATH_NATIVE,
+ p.getAPRPool());
+ if (stat == APR_SUCCESS) {
+ Transcoder::decode(dir, rv);
+ }
+ return rv;
+ }
+#if APR_HAS_USER
+ if (lkey == LOG4CXX_STR("user.home") || lkey == LOG4CXX_STR("user.name")) {
+ Pool pool;
+ apr_uid_t userid;
+ apr_gid_t groupid;
+ apr_pool_t* p = pool.getAPRPool();
+ apr_status_t stat = apr_uid_current(&userid, &groupid, p);
+ if (stat == APR_SUCCESS) {
+ char* username = NULL;
+ stat = apr_uid_name_get(&username, userid, p);
+ if (stat == APR_SUCCESS) {
+ if (lkey == LOG4CXX_STR("user.name")) {
+ Transcoder::decode(username, rv);
+ } else {
+ char* dirname = NULL;
+ stat = apr_uid_homepath_get(&dirname, username, p);
+ if (stat == APR_SUCCESS) {
+ Transcoder::decode(dirname, rv);
+ }
+ }
+ }
+ }
+ return rv;
+ }
+#endif
+
+ LOG4CXX_ENCODE_CHAR(key, lkey);
+ Pool p;
+ char* value = NULL;
+ apr_status_t stat = apr_env_get(&value, key.c_str(),
+ p.getAPRPool());
+ if (stat == APR_SUCCESS) {
+ Transcoder::decode((const char*) value, rv);
+ }
+ return rv;
+}
+
diff --git a/src/main/cpp/systemerrwriter.cpp b/src/main/cpp/systemerrwriter.cpp
new file mode 100644
index 0000000..01b5ba3
--- /dev/null
+++ b/src/main/cpp/systemerrwriter.cpp
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/systemerrwriter.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <stdio.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(SystemErrWriter)
+
+SystemErrWriter::SystemErrWriter() {
+}
+
+SystemErrWriter::~SystemErrWriter() {
+}
+
+void SystemErrWriter::close(Pool& /* p */) {
+}
+
+void SystemErrWriter::flush(Pool& /* p */) {
+ flush();
+}
+
+void SystemErrWriter::write(const LogString& str, Pool& /* p */) {
+ write(str);
+}
+
+bool SystemErrWriter::isWide() {
+#if LOG4CXX_FORCE_WIDE_CONSOLE
+ return true;
+#elif LOG4CXX_FORCE_BYTE_CONSOLE || !LOG4CXX_HAS_FWIDE
+ return false;
+#else
+ return fwide(stderr, 0) > 0;
+#endif
+}
+
+void SystemErrWriter::write(const LogString& str) {
+#if LOG4CXX_WCHAR_T_API
+ if (isWide()) {
+ LOG4CXX_ENCODE_WCHAR(msg, str);
+ fputws(msg.c_str(), stderr);
+ return;
+ }
+#endif
+ LOG4CXX_ENCODE_CHAR(msg, str);
+ fputs(msg.c_str(), stderr);
+}
+
+void SystemErrWriter::flush() {
+ fflush(stderr);
+}
diff --git a/src/main/cpp/systemoutwriter.cpp b/src/main/cpp/systemoutwriter.cpp
new file mode 100644
index 0000000..ee86446
--- /dev/null
+++ b/src/main/cpp/systemoutwriter.cpp
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/systemoutwriter.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <stdio.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(SystemOutWriter)
+
+
+SystemOutWriter::SystemOutWriter() {
+}
+
+SystemOutWriter::~SystemOutWriter() {
+}
+
+void SystemOutWriter::close(Pool& /* p */ ) {
+}
+
+void SystemOutWriter::flush(Pool& /* p */ ) {
+ flush();
+}
+
+void SystemOutWriter::write(const LogString& str, Pool& /* p */ ) {
+ write(str);
+}
+
+bool SystemOutWriter::isWide() {
+#if LOG4CXX_FORCE_WIDE_CONSOLE
+ return true;
+#elif LOG4CXX_FORCE_BYTE_CONSOLE || !LOG4CXX_HAS_FWIDE
+ return false;
+#else
+ return fwide(stdout, 0) > 0;
+#endif
+}
+
+void SystemOutWriter::write(const LogString& str) {
+#if LOG4CXX_WCHAR_T_API
+ if (isWide()) {
+ LOG4CXX_ENCODE_WCHAR(msg, str);
+ fputws(msg.c_str(), stdout);
+ return;
+ }
+#endif
+ LOG4CXX_ENCODE_CHAR(msg, str);
+ fputs(msg.c_str(), stdout);
+}
+
+void SystemOutWriter::flush() {
+ fflush(stdout);
+}
diff --git a/src/main/cpp/telnetappender.cpp b/src/main/cpp/telnetappender.cpp
new file mode 100644
index 0000000..b8bf951
--- /dev/null
+++ b/src/main/cpp/telnetappender.cpp
@@ -0,0 +1,252 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/net/telnetappender.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <apr_thread_proc.h>
+#include <apr_atomic.h>
+#include <apr_strings.h>
+#include <log4cxx/helpers/charsetencoder.h>
+#include <log4cxx/helpers/bytebuffer.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::net;
+
+#if APR_HAS_THREADS
+
+IMPLEMENT_LOG4CXX_OBJECT(TelnetAppender)
+
+/** The default telnet server port */
+const int TelnetAppender::DEFAULT_PORT = 23;
+
+/** The maximum number of concurrent connections */
+const int TelnetAppender::MAX_CONNECTIONS = 20;
+
+TelnetAppender::TelnetAppender()
+ : port(DEFAULT_PORT), connections(MAX_CONNECTIONS),
+ encoding(LOG4CXX_STR("UTF-8")),
+ encoder(CharsetEncoder::getUTF8Encoder()),
+ serverSocket(NULL), sh()
+{
+ synchronized sync(mutex);
+ activeConnections = 0;
+}
+
+TelnetAppender::~TelnetAppender()
+{
+ finalize();
+ delete serverSocket;
+}
+
+void TelnetAppender::activateOptions(Pool& /* p */)
+{
+ if (serverSocket == NULL) {
+ serverSocket = new ServerSocket(port);
+ serverSocket->setSoTimeout(1000);
+ }
+ sh.run(acceptConnections, this);
+}
+
+void TelnetAppender::setOption(const LogString& option,
+ const LogString& value)
+{
+ if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("PORT"), LOG4CXX_STR("port")))
+ {
+ setPort(OptionConverter::toInt(value, DEFAULT_PORT));
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("ENCODING"), LOG4CXX_STR("encoding")))
+ {
+ setEncoding(value);
+ }
+ else
+ {
+ AppenderSkeleton::setOption(option, value);
+ }
+}
+
+LogString TelnetAppender::getEncoding() const {
+ synchronized sync(mutex);
+ return encoding;
+}
+
+void TelnetAppender::setEncoding(const LogString& value) {
+ synchronized sync(mutex);
+ encoder = CharsetEncoder::getEncoder(value);
+ encoding = value;
+}
+
+
+void TelnetAppender::close()
+{
+ synchronized sync(mutex);
+ if (closed) return;
+ closed = true;
+
+ SocketPtr nullSocket;
+ for(ConnectionList::iterator iter = connections.begin();
+ iter != connections.end();
+ iter++) {
+ if (*iter != 0) {
+ (*iter)->close();
+ *iter = nullSocket;
+ }
+ }
+
+ if (serverSocket != NULL) {
+ try {
+ serverSocket->close();
+ } catch(Exception&) {
+ }
+ }
+
+ try {
+ sh.join();
+ } catch(Exception& ex) {
+ }
+
+ activeConnections = 0;
+}
+
+
+void TelnetAppender::write(ByteBuffer& buf) {
+ for (ConnectionList::iterator iter = connections.begin();
+ iter != connections.end();
+ iter++) {
+ if (*iter != 0) {
+ try {
+ ByteBuffer b(buf.current(), buf.remaining());
+ (*iter)->write(b);
+ } catch(Exception& ex) {
+ // The client has closed the connection, remove it from our list:
+ *iter = 0;
+ activeConnections--;
+ }
+ }
+ }
+}
+
+void TelnetAppender::writeStatus(const SocketPtr& socket, const LogString& msg, Pool& p) {
+ size_t bytesSize = msg.size() * 2;
+ char* bytes = p.pstralloc(bytesSize);
+
+ LogString::const_iterator msgIter(msg.begin());
+ ByteBuffer buf(bytes, bytesSize);
+
+ while(msgIter != msg.end()) {
+ encoder->encode(msg, msgIter, buf);
+ buf.flip();
+ socket->write(buf);
+ buf.clear();
+ }
+}
+
+void TelnetAppender::append(const spi::LoggingEventPtr& event, Pool& p)
+{
+ size_t count = activeConnections;
+ if (count > 0) {
+ LogString msg;
+ this->layout->format(msg, event, pool);
+ msg.append(LOG4CXX_STR("\r\n"));
+ size_t bytesSize = msg.size() * 2;
+ char* bytes = p.pstralloc(bytesSize);
+
+ LogString::const_iterator msgIter(msg.begin());
+ ByteBuffer buf(bytes, bytesSize);
+
+ synchronized sync(this->mutex);
+ while(msgIter != msg.end()) {
+ log4cxx_status_t stat = encoder->encode(msg, msgIter, buf);
+ buf.flip();
+ write(buf);
+ buf.clear();
+ if (CharsetEncoder::isError(stat)) {
+ LogString unrepresented(1, 0x3F /* '?' */);
+ LogString::const_iterator unrepresentedIter(unrepresented.begin());
+ stat = encoder->encode(unrepresented, unrepresentedIter, buf);
+ buf.flip();
+ write(buf);
+ buf.clear();
+ msgIter++;
+ }
+ }
+ }
+}
+
+void* APR_THREAD_FUNC TelnetAppender::acceptConnections(apr_thread_t* /* thread */, void* data) {
+ TelnetAppender* pThis = (TelnetAppender*) data;
+
+ // main loop; is left when This->closed is != 0 after an accept()
+ while(true)
+ {
+ try
+ {
+ SocketPtr newClient = pThis->serverSocket->accept();
+ bool done = pThis->closed;
+ if (done) {
+ Pool p;
+ pThis->writeStatus(newClient, LOG4CXX_STR("Log closed.\r\n"), p);
+ newClient->close();
+ return NULL;
+ }
+
+ size_t count = pThis->activeConnections;
+ if (count >= pThis->connections.size()) {
+ Pool p;
+ pThis->writeStatus(newClient, LOG4CXX_STR("Too many connections.\r\n"), p);
+ newClient->close();
+ } else {
+ //
+ // find unoccupied connection
+ //
+ synchronized sync(pThis->mutex);
+ for(ConnectionList::iterator iter = pThis->connections.begin();
+ iter != pThis->connections.end();
+ iter++) {
+ if (*iter == NULL) {
+ *iter = newClient;
+ pThis->activeConnections++;
+ break;
+ }
+ }
+
+ Pool p;
+ LogString oss(LOG4CXX_STR("TelnetAppender v1.0 ("));
+ StringHelper::toString((int) count+1, p, oss);
+ oss += LOG4CXX_STR(" active connections)\r\n\r\n");
+ pThis->writeStatus(newClient, oss, p);
+ }
+ } catch(InterruptedIOException &e) {
+ if (pThis->closed) {
+ return NULL;
+ }
+ } catch(Exception& e) {
+ if (!pThis->closed) {
+ LogLog::error(LOG4CXX_STR("Encountered error while in SocketHandler loop."), e);
+ } else {
+ return NULL;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+#endif
diff --git a/src/main/cpp/threadcxx.cpp b/src/main/cpp/threadcxx.cpp
new file mode 100644
index 0000000..777b128
--- /dev/null
+++ b/src/main/cpp/threadcxx.cpp
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/thread.h>
+#include <log4cxx/helpers/exception.h>
+#include <apr_thread_proc.h>
+#include <apr_atomic.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/threadlocal.h>
+
+using namespace log4cxx::helpers;
+using namespace log4cxx;
+
+Thread::Thread() : thread(NULL), alive(0), interruptedStatus(0) {
+}
+
+Thread::~Thread() {
+ join();
+}
+
+Thread::LaunchPackage::LaunchPackage(Thread* t, Runnable r, void* d) : thread(t), runnable(r), data(d) {
+}
+
+Thread* Thread::LaunchPackage::getThread() const {
+ return thread;
+}
+
+Runnable Thread::LaunchPackage::getRunnable() const {
+ return runnable;
+}
+
+void* Thread::LaunchPackage::getData() const {
+ return data;
+}
+
+void* Thread::LaunchPackage::operator new(size_t sz, Pool& p) {
+ return p.palloc(sz);
+}
+
+void Thread::LaunchPackage::operator delete(void* mem, Pool& p) {
+}
+
+void Thread::run(Runnable start, void* data) {
+#if APR_HAS_THREADS
+ //
+ // if attempting a second run method on the same Thread object
+ // throw an exception
+ //
+ if (thread != NULL) {
+ throw IllegalStateException();
+ }
+ apr_threadattr_t* attrs;
+ apr_status_t stat = apr_threadattr_create(&attrs, p.getAPRPool());
+ if (stat != APR_SUCCESS) {
+ throw ThreadException(stat);
+ }
+
+ // create LaunchPackage on the thread's memory pool
+ LaunchPackage* package = new(p) LaunchPackage(this, start, data);
+ stat = apr_thread_create(&thread, attrs,
+ launcher, package, p.getAPRPool());
+ if (stat != APR_SUCCESS) {
+ throw ThreadException(stat);
+ }
+#else
+ throw ThreadException(LOG4CXX_STR("APR_HAS_THREADS is not true"));
+#endif
+}
+
+
+Thread::LaunchStatus::LaunchStatus(volatile unsigned int* p) : alive(p) {
+ apr_atomic_set32(alive, 0xFFFFFFFF);
+}
+
+Thread::LaunchStatus::~LaunchStatus() {
+ apr_atomic_set32(alive, 0);
+}
+
+#if APR_HAS_THREADS
+void* LOG4CXX_THREAD_FUNC Thread::launcher(apr_thread_t* thread, void* data) {
+ LaunchPackage* package = (LaunchPackage*) data;
+ ThreadLocal& tls = getThreadLocal();
+ tls.set(package->getThread());
+ LaunchStatus alive(&package->getThread()->alive);
+ void* retval = (package->getRunnable())(thread, package->getData());
+ apr_thread_exit(thread, 0);
+ return retval;
+}
+#endif
+
+
+void Thread::join() {
+#if APR_HAS_THREADS
+ if (thread != NULL) {
+ apr_status_t startStat;
+ apr_status_t stat = apr_thread_join(&startStat, thread);
+ thread = NULL;
+ if (stat != APR_SUCCESS) {
+ throw ThreadException(stat);
+ }
+ }
+#endif
+}
+
+ThreadLocal& Thread::getThreadLocal() {
+ static ThreadLocal tls;
+ return tls;
+}
+
+void Thread::currentThreadInterrupt() {
+#if APR_HAS_THREADS
+ void* tls = getThreadLocal().get();
+ if (tls != 0) {
+ ((Thread*) tls)->interrupt();
+ }
+#endif
+}
+
+void Thread::interrupt() {
+ apr_atomic_set32(&interruptedStatus, 0xFFFFFFFF);
+}
+
+bool Thread::interrupted() {
+#if APR_HAS_THREADS
+ void* tls = getThreadLocal().get();
+ if (tls != 0) {
+ return apr_atomic_xchg32(&(((Thread*) tls)->interruptedStatus), 0) != 0;
+ }
+#endif
+ return false;
+}
+
+bool Thread::isCurrentThread() const {
+#if APR_HAS_THREADS
+ const void* tls = getThreadLocal().get();
+ return (tls == this);
+#else
+ return true;
+#endif
+}
+
+bool Thread::isAlive() {
+ return apr_atomic_read32(&alive) != 0;
+}
+
+void Thread::ending() {
+ apr_atomic_set32(&alive, 0);
+}
+
+
+void Thread::sleep(int duration) {
+#if APR_HAS_THREADS
+ if(interrupted()) {
+ throw InterruptedException();
+ }
+#endif
+ if (duration > 0) {
+ apr_sleep(duration*1000);
+ }
+}
diff --git a/src/main/cpp/threadlocal.cpp b/src/main/cpp/threadlocal.cpp
new file mode 100644
index 0000000..ff408ec
--- /dev/null
+++ b/src/main/cpp/threadlocal.cpp
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "log4cxx/helpers/threadlocal.h"
+#include "apr_thread_proc.h"
+#include "log4cxx/helpers/exception.h"
+
+using namespace log4cxx::helpers;
+using namespace log4cxx;
+
+apr_threadkey_t* ThreadLocal::create(Pool& p) {
+ apr_threadkey_t* key = 0;
+#if APR_HAS_THREADS
+ apr_status_t stat = apr_threadkey_private_create(&key, 0, p.getAPRPool());
+ if (stat != APR_SUCCESS) {
+ throw RuntimeException(stat);
+ }
+#endif
+ return key;
+}
+
+ThreadLocal::ThreadLocal() : p(), key(create(p)) {
+}
+
+ThreadLocal::~ThreadLocal() {
+}
+
+void ThreadLocal::set(void* priv) {
+#if APR_HAS_THREADS
+ apr_status_t stat = apr_threadkey_private_set(priv, key);
+ if (stat != APR_SUCCESS) {
+ throw RuntimeException(stat);
+ }
+#endif
+}
+
+void* ThreadLocal::get() {
+ void* retval = 0;
+#if APR_HAS_THREADS
+ apr_status_t stat = apr_threadkey_private_get(&retval, key);
+ if (stat != APR_SUCCESS) {
+ throw RuntimeException(stat);
+ }
+#endif
+ return retval;
+}
diff --git a/src/main/cpp/threadpatternconverter.cpp b/src/main/cpp/threadpatternconverter.cpp
new file mode 100644
index 0000000..c725079
--- /dev/null
+++ b/src/main/cpp/threadpatternconverter.cpp
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/threadpatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+
+ using namespace log4cxx;
+ using namespace log4cxx::pattern;
+ using namespace log4cxx::spi;
+ using namespace log4cxx::helpers;
+
+ IMPLEMENT_LOG4CXX_OBJECT(ThreadPatternConverter)
+
+ ThreadPatternConverter::ThreadPatternConverter() :
+ LoggingEventPatternConverter(LOG4CXX_STR("Thread"),
+ LOG4CXX_STR("Thread")) {
+ }
+
+ PatternConverterPtr ThreadPatternConverter::newInstance(
+ const std::vector<LogString>& /* options */) {
+ static PatternConverterPtr def(new ThreadPatternConverter());
+ return def;
+ }
+
+ void ThreadPatternConverter::format(
+ const LoggingEventPtr& event,
+ LogString& toAppendTo,
+ Pool& /* p */) const {
+ toAppendTo.append(event->getThreadName());
+ }
+
diff --git a/src/main/cpp/threadspecificdata.cpp b/src/main/cpp/threadspecificdata.cpp
new file mode 100644
index 0000000..1bfa269
--- /dev/null
+++ b/src/main/cpp/threadspecificdata.cpp
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/threadspecificdata.h>
+#include <log4cxx/helpers/exception.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/helpers/aprinitializer.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+ThreadSpecificData::ThreadSpecificData()
+ : ndcStack(), mdcMap() {
+}
+
+ThreadSpecificData::~ThreadSpecificData() {
+}
+
+
+log4cxx::NDC::Stack& ThreadSpecificData::getStack() {
+ return ndcStack;
+}
+
+log4cxx::MDC::Map& ThreadSpecificData::getMap() {
+ return mdcMap;
+}
+
+ThreadSpecificData& ThreadSpecificData::getDataNoThreads() {
+ static ThreadSpecificData noThreadData;
+ return noThreadData;
+}
+
+ThreadSpecificData* ThreadSpecificData::getCurrentData() {
+#if APR_HAS_THREADS
+ void* pData = NULL;
+ apr_threadkey_private_get(&pData, APRInitializer::getTlsKey());
+ return (ThreadSpecificData*) pData;
+#else
+ return &getDataNoThreads();
+#endif
+}
+
+void ThreadSpecificData::recycle() {
+#if APR_HAS_THREADS
+ if(ndcStack.empty() && mdcMap.empty()) {
+ void* pData = NULL;
+ apr_status_t stat = apr_threadkey_private_get(&pData, APRInitializer::getTlsKey());
+ if (stat == APR_SUCCESS && pData == this) {
+ stat = apr_threadkey_private_set(0, APRInitializer::getTlsKey());
+ if (stat == APR_SUCCESS) {
+ delete this;
+ }
+ }
+ }
+#endif
+}
+
+void ThreadSpecificData::put(const LogString& key, const LogString& val) {
+ ThreadSpecificData* data = getCurrentData();
+ if (data == 0) {
+ data = createCurrentData();
+ }
+ if (data != 0) {
+ data->getMap().insert(log4cxx::MDC::Map::value_type(key, val));
+ }
+}
+
+
+
+
+void ThreadSpecificData::push(const LogString& val) {
+ ThreadSpecificData* data = getCurrentData();
+ if (data == 0) {
+ data = createCurrentData();
+ }
+ if (data != 0) {
+ NDC::Stack& stack = data->getStack();
+ if(stack.empty()) {
+ stack.push(NDC::DiagnosticContext(val, val));
+ } else {
+ LogString fullMessage(stack.top().second);
+ fullMessage.append(1, (logchar) 0x20);
+ fullMessage.append(val);
+ stack.push(NDC::DiagnosticContext(val, fullMessage));
+ }
+ }
+}
+
+void ThreadSpecificData::inherit(const NDC::Stack& src) {
+ ThreadSpecificData* data = getCurrentData();
+ if (data == 0) {
+ data = createCurrentData();
+ }
+ if (data != 0) {
+ data->getStack() = src;
+ }
+}
+
+
+
+ThreadSpecificData* ThreadSpecificData::createCurrentData() {
+#if APR_HAS_THREADS
+ ThreadSpecificData* newData = new ThreadSpecificData();
+ apr_status_t stat = apr_threadkey_private_set(newData, APRInitializer::getTlsKey());
+ if (stat != APR_SUCCESS) {
+ delete newData;
+ newData = NULL;
+ }
+ return newData;
+#else
+ return 0;
+#endif
+}
diff --git a/src/main/cpp/throwableinformationpatternconverter.cpp b/src/main/cpp/throwableinformationpatternconverter.cpp
new file mode 100644
index 0000000..bba9d5c
--- /dev/null
+++ b/src/main/cpp/throwableinformationpatternconverter.cpp
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/throwableinformationpatternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+#include <log4cxx/helpers/stringhelper.h>
+
+using namespace log4cxx;
+using namespace log4cxx::pattern;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(ThrowableInformationPatternConverter)
+
+ThrowableInformationPatternConverter::ThrowableInformationPatternConverter(bool shortReport1) :
+ LoggingEventPatternConverter(LOG4CXX_STR("Throwable"),
+ LOG4CXX_STR("throwable")),
+ shortReport(shortReport1) {
+}
+
+PatternConverterPtr ThrowableInformationPatternConverter::newInstance(
+ const std::vector<LogString>& options) {
+ if (options.size() > 0 && options[0].compare(LOG4CXX_STR("short")) == 0) {
+ static PatternConverterPtr shortConverter(new ThrowableInformationPatternConverter(true));
+ return shortConverter;
+ }
+ static PatternConverterPtr converter(new ThrowableInformationPatternConverter(false));
+ return converter;
+}
+
+void ThrowableInformationPatternConverter::format(
+ const LoggingEventPtr& /* event */,
+ LogString& /* toAppendTo */,
+ Pool& /* p */) const {
+}
+
+ /**
+ * This converter obviously handles throwables.
+ * @return true.
+ */
+bool ThrowableInformationPatternConverter::handlesThrowable() const {
+ return true;
+}
diff --git a/src/main/cpp/timebasedrollingpolicy.cpp b/src/main/cpp/timebasedrollingpolicy.cpp
new file mode 100644
index 0000000..5214a31
--- /dev/null
+++ b/src/main/cpp/timebasedrollingpolicy.cpp
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/rolling/timebasedrollingpolicy.h>
+#include <log4cxx/pattern/filedatepatternconverter.h>
+#include <log4cxx/helpers/date.h>
+#include <log4cxx/rolling/filerenameaction.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/rolling/gzcompressaction.h>
+#include <log4cxx/rolling/zipcompressaction.h>
+
+#ifndef INT64_C
+#define INT64_C(x) x ## LL
+#endif
+
+#include <apr_time.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::helpers;
+using namespace log4cxx::pattern;
+
+IMPLEMENT_LOG4CXX_OBJECT(TimeBasedRollingPolicy)
+
+TimeBasedRollingPolicy::TimeBasedRollingPolicy() {
+}
+
+void TimeBasedRollingPolicy::addRef() const {
+ TriggeringPolicy::addRef();
+}
+
+void TimeBasedRollingPolicy::releaseRef() const {
+ TriggeringPolicy::releaseRef();
+}
+
+void TimeBasedRollingPolicy::activateOptions(log4cxx::helpers::Pool& pool) {
+ // find out period from the filename pattern
+ if (getFileNamePattern().length() > 0) {
+ parseFileNamePattern();
+ } else {
+ LogLog::warn(
+ LOG4CXX_STR("The FileNamePattern option must be set before using TimeBasedRollingPolicy. "));
+ throw IllegalStateException();
+ }
+
+ PatternConverterPtr dtc(getDatePatternConverter());
+
+ if (dtc == NULL) {
+ throw IllegalStateException();
+ }
+
+ apr_time_t n = apr_time_now();
+ LogString buf;
+ ObjectPtr obj(new Date(n));
+ formatFileName(obj, buf, pool);
+ lastFileName = buf;
+
+ suffixLength = 0;
+
+ if (lastFileName.length() >= 3) {
+ if (lastFileName.compare(lastFileName.length() - 3, 3, LOG4CXX_STR(".gz")) == 0) {
+ suffixLength = 3;
+ } else if (lastFileName.length() >= 4 && lastFileName.compare(lastFileName.length() - 4, 4, LOG4CXX_STR(".zip")) == 0) {
+ suffixLength = 4;
+ }
+ }
+}
+
+
+#define RULES_PUT(spec, cls) \
+specs.insert(PatternMap::value_type(LogString(LOG4CXX_STR(spec)), (PatternConstructor) cls ::newInstance))
+
+log4cxx::pattern::PatternMap TimeBasedRollingPolicy::getFormatSpecifiers() const {
+ PatternMap specs;
+ RULES_PUT("d", FileDatePatternConverter);
+ RULES_PUT("date", FileDatePatternConverter);
+ return specs;
+}
+
+/**
+ * {@inheritDoc}
+ */
+RolloverDescriptionPtr TimeBasedRollingPolicy::initialize(
+ const LogString& currentActiveFile,
+ const bool append,
+ Pool& pool) {
+ apr_time_t n = apr_time_now();
+ nextCheck = ((n / APR_USEC_PER_SEC) + 1) * APR_USEC_PER_SEC;
+
+ LogString buf;
+ ObjectPtr obj(new Date(n));
+ formatFileName(obj, buf, pool);
+ lastFileName = buf;
+
+ ActionPtr noAction;
+
+ if (currentActiveFile.length() > 0) {
+ return new RolloverDescription(
+ currentActiveFile, append, noAction, noAction);
+ } else {
+ return new RolloverDescription(
+ lastFileName.substr(0, lastFileName.length() - suffixLength), append,
+ noAction, noAction);
+ }
+}
+
+
+
+RolloverDescriptionPtr TimeBasedRollingPolicy::rollover(
+ const LogString& currentActiveFile,
+ Pool& pool) {
+ apr_time_t n = apr_time_now();
+ nextCheck = ((n / APR_USEC_PER_SEC) + 1) * APR_USEC_PER_SEC;
+
+ LogString buf;
+ ObjectPtr obj(new Date(n));
+ formatFileName(obj, buf, pool);
+
+ LogString newFileName(buf);
+
+ //
+ // if file names haven't changed, no rollover
+ //
+ if (newFileName == lastFileName) {
+ RolloverDescriptionPtr desc;
+ return desc;
+ }
+
+ ActionPtr renameAction;
+ ActionPtr compressAction;
+ LogString lastBaseName(
+ lastFileName.substr(0, lastFileName.length() - suffixLength));
+ LogString nextActiveFile(
+ newFileName.substr(0, newFileName.length() - suffixLength));
+
+ //
+ // if currentActiveFile is not lastBaseName then
+ // active file name is not following file pattern
+ // and requires a rename plus maintaining the same name
+ if (currentActiveFile != lastBaseName) {
+ renameAction =
+ new FileRenameAction(
+ File().setPath(currentActiveFile), File().setPath(lastBaseName), true);
+ nextActiveFile = currentActiveFile;
+ }
+
+ if (suffixLength == 3) {
+ compressAction =
+ new GZCompressAction(
+ File().setPath(lastBaseName), File().setPath(lastFileName), true);
+ }
+
+ if (suffixLength == 4) {
+ compressAction =
+ new ZipCompressAction(
+ File().setPath(lastBaseName), File().setPath(lastFileName), true);
+ }
+
+ lastFileName = newFileName;
+
+ return new RolloverDescription(
+ nextActiveFile, false, renameAction, compressAction);
+}
+
+
+
+bool TimeBasedRollingPolicy::isTriggeringEvent(
+ Appender* /* appender */,
+ const log4cxx::spi::LoggingEventPtr& /* event */,
+ const LogString& /* filename */,
+ size_t /* fileLength */) {
+ return apr_time_now() > nextCheck;
+}
diff --git a/src/main/cpp/timezone.cpp b/src/main/cpp/timezone.cpp
new file mode 100644
index 0000000..a14aebd
--- /dev/null
+++ b/src/main/cpp/timezone.cpp
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#define __STDC_CONSTANT_MACROS
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/timezone.h>
+#include <stdlib.h>
+
+#include <apr_time.h>
+#include <apr_pools.h>
+#include <apr_strings.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/logger.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT( TimeZone )
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ namespace TimeZoneImpl
+ {
+ /** Time zone object that represents GMT. */
+ class GMTTimeZone : public TimeZone
+ {
+ public:
+ /** Class factory. */
+ static const TimeZonePtr & getInstance()
+ {
+ static TimeZonePtr tz( new GMTTimeZone() );
+ return tz;
+ }
+
+ /** Explode time to human readable form. */
+ log4cxx_status_t explode( apr_time_exp_t * result, log4cxx_time_t input ) const
+ {
+ apr_status_t stat;
+ // APR 1.1 and early mishandles microseconds on dates
+ // before 1970, APR bug 32520
+ if (LOG4CXX_UNLIKELY(input < 0 && apr_time_usec(input) < 0)) {
+ apr_time_t floorTime = (apr_time_sec(input) -1) * APR_USEC_PER_SEC;
+ stat = apr_time_exp_gmt(result, floorTime);
+ result->tm_usec = (int) (input - floorTime);
+ } else {
+ stat = apr_time_exp_gmt( result, input );
+ }
+ return stat;
+ }
+
+ private:
+ GMTTimeZone() : TimeZone( LOG4CXX_STR("GMT") )
+ {
+ }
+ };
+
+
+
+ /** Time zone object that represents GMT. */
+ class LocalTimeZone : public TimeZone
+ {
+ public:
+ /** Class factory. */
+ static const TimeZonePtr & getInstance()
+ {
+ static TimeZonePtr tz( new LocalTimeZone() );
+ return tz;
+ }
+
+ /** Explode time to human readable form. */
+ log4cxx_status_t explode( apr_time_exp_t * result, log4cxx_time_t input ) const
+ {
+ apr_status_t stat;
+ // APR 1.1 and early mishandles microseconds on dates
+ // before 1970, APR bug 32520
+ if (LOG4CXX_UNLIKELY(input < 0 && apr_time_usec(input) < 0)) {
+ apr_time_t floorTime = (apr_time_sec(input) -1) * APR_USEC_PER_SEC;
+ stat = apr_time_exp_lt(result, floorTime);
+ result->tm_usec = (int) (input - floorTime);
+ } else {
+ stat = apr_time_exp_lt( result, input );
+ }
+ return stat;
+ }
+
+
+ private:
+ LocalTimeZone() : TimeZone( getTimeZoneName() )
+ {
+ }
+
+ static const LogString getTimeZoneName()
+ {
+ const int MAX_TZ_LENGTH = 255;
+ char tzName[MAX_TZ_LENGTH];
+ apr_size_t tzLength;
+ apr_time_exp_t tm;
+ apr_time_exp_lt(&tm, 0);
+ apr_strftime(tzName, &tzLength, MAX_TZ_LENGTH, "%Z", &tm);
+ if (tzLength == 0) {
+ apr_strftime(tzName, &tzLength, MAX_TZ_LENGTH, "%z", &tm);
+ }
+ tzName[tzLength] = 0;
+ LogString retval;
+ log4cxx::helpers::Transcoder::decode(tzName, retval);
+ return retval;
+ }
+
+ };
+
+
+
+ /** Time zone object that represents a fixed offset from GMT. */
+ class FixedTimeZone : public TimeZone
+ {
+ public:
+ FixedTimeZone( const LogString & name, apr_int32_t offset1 ) : TimeZone( name ), offset( offset1 )
+ {
+ }
+
+ /** Explode time to human readable form. */
+ log4cxx_status_t explode( apr_time_exp_t * result, log4cxx_time_t input ) const
+ {
+ apr_status_t stat;
+ // APR 1.1 and early mishandles microseconds on dates
+ // before 1970, APR bug 32520
+ if (LOG4CXX_UNLIKELY(input < 0 && apr_time_usec(input) < 0)) {
+ apr_time_t floorTime = (apr_time_sec(input) -1) * APR_USEC_PER_SEC;
+ stat = apr_time_exp_tz(result, floorTime, offset);
+ result->tm_usec = (int) (input - floorTime);
+ } else {
+ stat = apr_time_exp_tz( result, input, offset );
+ }
+ return stat;
+ }
+
+
+ private:
+ const apr_int32_t offset;
+ };
+
+ }
+ }
+}
+
+
+
+TimeZone::TimeZone( const LogString & id1 ) : id( id1 )
+{
+}
+
+TimeZone::~TimeZone()
+{
+}
+
+const TimeZonePtr & TimeZone::getDefault()
+{
+ return log4cxx::helpers::TimeZoneImpl::LocalTimeZone::getInstance();
+}
+
+const TimeZonePtr & TimeZone::getGMT()
+{
+ return log4cxx::helpers::TimeZoneImpl::GMTTimeZone::getInstance();
+}
+
+const TimeZonePtr TimeZone::getTimeZone( const LogString & id )
+{
+ const logchar gmt[] = { 0x47, 0x4D, 0x54, 0 };
+ if ( id == gmt )
+ {
+ return log4cxx::helpers::TimeZoneImpl::GMTTimeZone::getInstance();
+ }
+ if ( id.length() >= 5 && id.substr( 0, 3 ) == gmt )
+ {
+ int hours = 0;
+ int minutes = 0;
+ int sign = 1;
+ if (id[3] == 0x2D /* '-' */) {
+ sign = -1;
+ }
+ LogString off( id.substr( 4 ) );
+ if ( id.length() >= 7 )
+ {
+ size_t colonPos = off.find( 0x3A /* ':' */);
+ if ( colonPos == LogString::npos )
+ {
+ minutes = StringHelper::toInt(off.substr(off.length() - 2));
+ hours = StringHelper::toInt(off.substr(0, off.length() - 2));
+ }
+ else
+ {
+ minutes = StringHelper::toInt(off.substr(colonPos + 1));
+ hours = StringHelper::toInt(off.substr(0, colonPos));
+ }
+ } else {
+ hours = StringHelper::toInt(off);
+ }
+ LogString s(gmt);
+ Pool p;
+ LogString hh;
+ StringHelper::toString(hours, p, hh);
+ if (sign > 0) {
+ s.append(1, (logchar) 0x2B /* '+' */);
+ } else {
+ s.append(1, (logchar) 0x2D /* '-' */);
+ }
+ if (hh.length() == 1) {
+ s.append(1, (logchar) 0x30 /* '0' */);
+ }
+ s.append(hh);
+ s.append(1, (logchar) 0x3A /*' :' */);
+ LogString mm;
+ StringHelper::toString(minutes, p, mm);
+ if (mm.length() == 1) {
+ s.append(1, (logchar) 0x30 /* '0' */);
+ }
+ s.append(mm);
+ apr_int32_t offset = sign * (hours * 3600 + minutes * 60);
+ return new log4cxx::helpers::TimeZoneImpl::FixedTimeZone( s, offset );
+ }
+ const TimeZonePtr & ltz = getDefault();
+ if ( ltz->getID() == id )
+ {
+ return ltz;
+ }
+ return getGMT();
+}
+
diff --git a/src/main/cpp/transcoder.cpp b/src/main/cpp/transcoder.cpp
new file mode 100644
index 0000000..2b4801c
--- /dev/null
+++ b/src/main/cpp/transcoder.cpp
@@ -0,0 +1,538 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/pool.h>
+#include <stdlib.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/charsetdecoder.h>
+#include <log4cxx/helpers/charsetencoder.h>
+#include <vector>
+#include <apr.h>
+#include <apr_strings.h>
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/private/log4cxx_private.h>
+
+#if LOG4CXX_LOGCHAR_IS_UNICHAR || LOG4CXX_CFSTRING_API || LOG4CXX_UNICHAR_API
+#include <CoreFoundation/CFString.h>
+#endif
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+void Transcoder::decodeUTF8(const std::string& src, LogString& dst) {
+ std::string::const_iterator iter = src.begin();
+ while(iter != src.end()) {
+ unsigned int sv = decode(src, iter);
+ if(sv != 0xFFFF) {
+ encode(sv, dst);
+ } else {
+ dst.append(1, LOSSCHAR);
+ iter++;
+ }
+ }
+}
+
+void Transcoder::encodeUTF8(const LogString& src, std::string& dst) {
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ dst.append(src);
+#else
+ LogString::const_iterator iter = src.begin();
+ while(iter != src.end()) {
+ unsigned int sv = decode(src, iter);
+ if(sv != 0xFFFF) {
+ encode(sv, dst);
+ } else {
+ dst.append(1, LOSSCHAR);
+ iter++;
+ }
+ }
+#endif
+}
+
+char* Transcoder::encodeUTF8(const LogString& src, Pool& p) {
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ return p.pstrdup(src);
+#else
+ std::string tmp;
+ encodeUTF8(src, tmp);
+ return p.pstrdup(tmp);
+#endif
+}
+
+
+void Transcoder::encodeUTF8(unsigned int sv, ByteBuffer& dst) {
+ size_t bytes = encodeUTF8(sv, dst.current());
+ dst.position(dst.position() + bytes);
+}
+
+
+size_t Transcoder::encodeUTF8(unsigned int ch, char* dst) {
+ if (ch < 0x80) {
+ dst[0] = (char) ch;
+ return 1;
+ } else if (ch < 0x800) {
+ dst[0] = (char) (0xC0 + (ch >> 6));
+ dst[1] = (char) (0x80 + (ch & 0x3F));
+ return 2;
+ } else if (ch < 0x10000) {
+ dst[0] = (char) (0xE0 + (ch >> 12));
+ dst[1] = (char) (0x80 + ((ch >> 6) & 0x3F));
+ dst[2] = (char) (0x80 + (ch & 0x3F));
+ return 3;
+ } else if (ch <= 0x10FFFF) {
+ dst[0] = (char) (0xF0 + (ch >> 18));
+ dst[1] = (char) (0x80 + ((ch >> 12) & 0x3F));
+ dst[2] = (char) (0x80 + ((ch >> 6) & 0x3F));
+ dst[3] = (char) (0x80 + (ch & 0x3F));
+ return 4;
+ } else {
+ //
+ // output UTF-8 encoding of 0xFFFF
+ //
+ dst[0] = (char) 0xEF;
+ dst[1] = (char) 0xBF;
+ dst[2] = (char) 0xBF;
+ return 3;
+ }
+}
+
+void Transcoder::encodeUTF16BE(unsigned int sv, ByteBuffer& dst) {
+ size_t bytes = encodeUTF16BE(sv, dst.current());
+ dst.position(dst.position() + bytes);
+}
+
+
+size_t Transcoder::encodeUTF16BE(unsigned int ch, char* dst) {
+ if (ch <= 0xFFFF) {
+ dst[0] = (char) (ch >> 8);
+ dst[1] = (char) (ch & 0xFF);
+ return 2;
+ }
+ if (ch <= 0x10FFFF) {
+ unsigned char w = (unsigned char) ((ch >> 16) - 1);
+ dst[0] = (char) (0xD8 + (w >> 2));
+ dst[1] = (char) (((w & 0x03) << 6) + ((ch >> 10) & 0x3F));
+ dst[2] = (char) (0xDC + ((ch & 0x30) >> 4));
+ dst[3] = (char) (ch & 0xFF);
+ return 4;
+ }
+ dst[0] = dst[1] = (char) 0xFF;
+ return 2;
+}
+
+void Transcoder::encodeUTF16LE(unsigned int sv, ByteBuffer& dst) {
+ size_t bytes = encodeUTF16LE(sv, dst.current());
+ dst.position(dst.position() + bytes);
+}
+
+size_t Transcoder::encodeUTF16LE(unsigned int ch, char* dst) {
+ if (ch <= 0xFFFF) {
+ dst[1] = (char) (ch >> 8);
+ dst[0] = (char) (ch & 0xFF);
+ return 2;
+ }
+ if (ch <= 0x10FFFF) {
+ unsigned char w = (unsigned char) ((ch >> 16) - 1);
+ dst[1] = (char) (0xD8 + (w >> 2));
+ dst[0] = (char) (((w & 0x03) << 6) + ((ch >> 10) & 0x3F));
+ dst[3] = (char) (0xDC + ((ch & 0x30) >> 4));
+ dst[2] = (char) (ch & 0xFF);
+ return 4;
+ }
+ dst[0] = dst[1] = (char) 0xFF;
+ return 2;
+}
+
+
+unsigned int Transcoder::decode(const std::string& src,
+ std::string::const_iterator& iter) {
+ std::string::const_iterator start(iter);
+ unsigned char ch1 = *(iter++);
+ if (ch1 <= 0x7F) {
+ return ch1;
+ }
+ //
+ // should not have continuation character here
+ //
+ if ((ch1 & 0xC0) != 0x80 && iter != src.end()) {
+ unsigned char ch2 = *(iter++);
+ //
+ // should be continuation
+ if ((ch2 & 0xC0) != 0x80) {
+ iter = start;
+ return 0xFFFF;
+ }
+ if((ch1 & 0xE0) == 0xC0) {
+ if ((ch2 & 0xC0) == 0x80) {
+ unsigned int rv = ((ch1 & 0x1F) << 6) + (ch2 & 0x3F);
+ if (rv >= 0x80) {
+ return rv;
+ }
+ }
+ iter = start;
+ return 0xFFFF;
+ }
+ if (iter != src.end()) {
+ unsigned char ch3 = *(iter++);
+ //
+ // should be continuation
+ //
+ if ((ch3 & 0xC0) != 0x80) {
+ iter = start;
+ return 0xFFFF;
+ }
+ if ((ch1 & 0xF0) == 0xE0) {
+ unsigned rv = ((ch1 & 0x0F) << 12)
+ + ((ch2 & 0x3F) << 6)
+ + (ch3 & 0x3F);
+ if (rv <= 0x800) {
+ iter = start;
+ return 0xFFFF;
+ }
+ return rv;
+ }
+ if (iter != src.end()) {
+ unsigned char ch4 = *(iter++);
+ if ((ch4 & 0xC0) != 0x80) {
+ iter = start;
+ return 0xFFFF;
+ }
+ unsigned int rv = ((ch1 & 0x07) << 18)
+ + ((ch2 & 0x3F) << 12)
+ + ((ch3 & 0x3F) << 6)
+ + (ch4 & 0x3F);
+ if (rv > 0xFFFF) {
+ return rv;
+ }
+
+ }
+ }
+ }
+ iter = start;
+ return 0xFFFF;
+}
+
+
+void Transcoder::encode(unsigned int sv, std::string& dst) {
+ char tmp[8];
+ size_t bytes = encodeUTF8(sv, tmp);
+ dst.append(tmp, bytes);
+}
+
+
+void Transcoder::decode(const std::string& src, LogString& dst) {
+#if LOG4CXX_CHARSET_UTF8 && LOG4CXX_LOGCHAR_IS_UTF8
+ dst.append(src);
+#else
+ static CharsetDecoderPtr decoder(CharsetDecoder::getDefaultDecoder());
+ dst.reserve(dst.size() + src.size());
+ std::string::const_iterator iter = src.begin();
+#if !LOG4CXX_CHARSET_EBCDIC
+ for(;
+ iter != src.end() && ((unsigned char) *iter) < 0x80;
+ iter++) {
+ dst.append(1, *iter);
+ }
+#endif
+ if (iter != src.end()) {
+ size_t offset = iter - src.begin();
+ ByteBuffer buf(const_cast<char*>(src.data() + offset), src.size() - offset);
+ while(buf.remaining() > 0) {
+ log4cxx_status_t stat = decoder->decode(buf, dst);
+ if(CharsetDecoder::isError(stat)) {
+ dst.append(1, LOSSCHAR);
+ buf.position(buf.position() + 1);
+ }
+ }
+ decoder->decode(buf, dst);
+ }
+#endif
+}
+
+char* Transcoder::encode(const LogString& src, Pool& p) {
+#if LOG4CXX_CHARSET_UTF8 && LOG4CXX_LOGCHAR_IS_UTF8
+ return p.pstrdup(src);
+#else
+ std::string tmp;
+ encode(src, tmp);
+ return p.pstrdup(tmp);
+#endif
+}
+
+
+
+void Transcoder::encode(const LogString& src, std::string& dst) {
+#if LOG4CXX_CHARSET_UTF8 && LOG4CXX_LOGCHAR_IS_UTF8
+ dst.append(src);
+#else
+ static CharsetEncoderPtr encoder(CharsetEncoder::getDefaultEncoder());
+ dst.reserve(dst.size() + src.size());
+ LogString::const_iterator iter = src.begin();
+#if !LOG4CXX_CHARSET_EBCDIC
+ for(;
+ iter != src.end() && ((unsigned int) *iter) < 0x80;
+ iter++) {
+ dst.append(1, *iter);
+ }
+#endif
+ if (iter != src.end()) {
+ char buf[BUFSIZE];
+ ByteBuffer out(buf, BUFSIZE);
+ while(iter != src.end()) {
+ log4cxx_status_t stat = encoder->encode(src, iter, out);
+ out.flip();
+ dst.append(out.data(), out.limit());
+ out.clear();
+ if (CharsetEncoder::isError(stat)) {
+ dst.append(1, LOSSCHAR);
+ iter++;
+ }
+ }
+ encoder->encode(src, iter, out);
+ }
+#endif
+}
+
+
+template<class String, class Iterator>
+static unsigned int decodeUTF16(const String& in, Iterator& iter) {
+ unsigned int ch1 = *iter;
+ //
+ // if not surrogate pair
+ //
+ if (ch1 < 0xD800 || ch1 > 0xDFFF) {
+ //
+ // then advance iterator and return wchar_t value
+ //
+ if(ch1 != 0xFFFF) iter++;
+ return ch1;
+ } else if (ch1 < 0xDC00) {
+ //
+ // started with high-surrogate value
+ // if there is an additional wchar_t
+ Iterator iter2 = iter + 1;
+ if (iter2 != in.end()) {
+ unsigned int ch2 = *iter2;
+ //
+ // if it is a matching low surrogate then
+ // advance the iterator and return the scalar value
+ if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) {
+ iter += 2;
+ return (ch1 - 0xD800) * 0x400 + (ch2 - 0xDC00) + 0x10000;
+ }
+ }
+ }
+ //
+ // unrecognized value, do not advance iterator
+ //
+ return 0xFFFF;
+}
+
+template<class String>
+static void encodeUTF16(unsigned int sv, String& dst) {
+ if (sv < 0x10000) {
+ dst.append(1, sv);
+ } else {
+ unsigned char u = (unsigned char) (sv >> 16);
+ unsigned char w = (unsigned char) (u - 1);
+ unsigned short hs = (0xD800 + ((w & 0xF) << 6) + ((sv & 0xFFFF) >> 10));
+ unsigned short ls = (0xDC00 + (sv && 0x3FF));
+ dst.append(1, hs);
+ dst.append(1, ls);
+ }
+}
+
+
+
+#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR_T || defined(WIN32) || defined(_WIN32)
+void Transcoder::decode(const std::wstring& src, LogString& dst) {
+#if LOG4CXX_LOGCHAR_IS_WCHAR_T
+ dst.append(src, len);
+#else
+ std::wstring::const_iterator i = src.begin();
+ while(i != src.end()) {
+ unsigned int cp = decode(src, i);
+ if (cp != 0xFFFF) {
+ encode(cp, dst);
+ } else {
+ dst.append(1, LOSSCHAR);
+ i++;
+ }
+ }
+#endif
+}
+
+void Transcoder::encode(const LogString& src, std::wstring& dst) {
+#if LOG4CXX_LOGCHAR_IS_WCHAR_T
+ dst.append(src);
+#else
+ for(LogString::const_iterator i = src.begin();
+ i != src.end();) {
+ unsigned int cp = Transcoder::decode(src, i);
+ encode(cp, dst);
+ }
+#endif
+}
+
+wchar_t* Transcoder::wencode(const LogString& src, Pool& p) {
+#if LOG4CXX_LOGCHAR_IS_WCHAR_T
+ std::wstring& tmp = src;
+#else
+ std::wstring tmp;
+ encode(src, tmp);
+#endif
+ wchar_t* dst = (wchar_t*) p.palloc((tmp.length() + 1) * sizeof(wchar_t));
+ dst[tmp.length()] = 0;
+ memcpy(dst, tmp.data(), tmp.length() * sizeof(wchar_t));
+ return dst;
+}
+
+
+unsigned int Transcoder::decode(const std::wstring& in,
+ std::wstring::const_iterator& iter) {
+#if defined(__STDC_ISO_10646__)
+ return *(iter++);
+#else
+ return decodeUTF16(in, iter);
+#endif
+}
+
+
+void Transcoder::encode(unsigned int sv, std::wstring& dst) {
+#if defined(__STDC_ISO_10646__)
+ dst.append(1, sv);
+#else
+ if (sizeof(wchar_t) == 4) {
+ dst.append(1, sv);
+ } else {
+ encodeUTF16(sv, dst);
+ }
+#endif
+}
+
+#endif
+
+
+
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+void Transcoder::decode(const std::basic_string<UniChar>& src, LogString& dst) {
+#if LOG4CXX_LOGCHAR_IS_UNICHAR
+ dst.append(src);
+#else
+ for(std::basic_string<UniChar>::const_iterator i = src.begin();
+ i != src.end();) {
+ unsigned int cp = decode(src, i);
+ encode(cp, dst);
+ }
+#endif
+}
+
+void Transcoder::encode(const LogString& src, std::basic_string<UniChar>& dst) {
+#if LOG4CXX_LOGCHAR_IS_UNICHAR
+ dst.append(src);
+#else
+ for(LogString::const_iterator i = src.begin();
+ i != src.end();) {
+ unsigned int cp = decode(src, i);
+ encode(cp, dst);
+ }
+#endif
+}
+
+unsigned int Transcoder::decode(const std::basic_string<UniChar>& in,
+ std::basic_string<UniChar>::const_iterator& iter) {
+ return decodeUTF16(in, iter);
+}
+
+void Transcoder::encode(unsigned int sv, std::basic_string<UniChar>& dst) {
+ encodeUTF16(sv, dst);
+}
+
+#endif
+
+#if LOG4CXX_CFSTRING_API
+void Transcoder::decode(const CFStringRef& src, LogString& dst) {
+ const UniChar* chars = CFStringGetCharactersPtr(src);
+ if (chars) {
+ decode(chars, dst);
+ } else {
+ size_t length = CFStringGetLength(src);
+ if (length > 0) {
+ std::vector<UniChar> tmp(length);
+ CFStringGetCharacters(src, CFRangeMake(0, length), &tmp[0]);
+#if LOG4CXX_LOGCHAR_IS_UNICHAR
+ dst.append(&tmp[0], tmp.size());
+#else
+ decode(std::basic_string<UniChar>(&tmp[0], tmp.size()), dst);
+#endif
+ }
+ }
+}
+
+CFStringRef Transcoder::encode(const LogString& src) {
+ LOG4CXX_ENCODE_UNICHAR(tmp, src);
+ return CFStringCreateWithCharacters(kCFAllocatorDefault, tmp.data(), tmp.size());
+}
+#endif
+
+
+logchar Transcoder::decode(char val) {
+#if LOG4CXX_CHARSET_EBCDIC
+ LogString dst;
+ Transcoder::decode(std::string(1, val), dst);
+ return dst[0];
+#else
+ return val;
+#endif
+}
+
+LogString Transcoder::decode(const char* val) {
+#if LOG4CXX_LOGCHAR_IS_UTF8 && !LOG4CXX_CHARSET_EBCDIC
+ return val;
+#else
+ LogString dst;
+ Transcoder::decode(val, dst);
+ return dst;
+#endif
+}
+
+
+std::string Transcoder::encodeCharsetName(const LogString& val) {
+ char asciiTable[] = { ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6' , '7', '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', ' ' };
+ std::string out;
+ for(LogString::const_iterator iter = val.begin();
+ iter != val.end();
+ iter++) {
+ if (*iter >= 0x30 && *iter < 0x7F) {
+ out.append(1, asciiTable[*iter - 0x30]);
+ } else {
+ out.append(1, LOSSCHAR);
+ }
+ }
+ return out;
+}
diff --git a/src/main/cpp/transform.cpp b/src/main/cpp/transform.cpp
new file mode 100644
index 0000000..ac0217e
--- /dev/null
+++ b/src/main/cpp/transform.cpp
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/transform.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+
+void Transform::appendEscapingTags(
+ LogString& buf, const LogString& input)
+{
+ //Check if the string is zero length -- if so, return
+ //what was sent in.
+
+ if(input.length() == 0 )
+ {
+ return;
+ }
+
+ logchar specials[] = { 0x22 /* " */, 0x26 /* & */, 0x3C /* < */, 0x3E /* > */, 0x00 };
+ size_t start = 0;
+ size_t special = input.find_first_of(specials, start);
+ while(special != LogString::npos) {
+ if (special > start) {
+ buf.append(input, start, special - start);
+ }
+ switch(input[special]) {
+ case 0x22:
+ buf.append(LOG4CXX_STR("&quot;"));
+ break;
+
+ case 0x26:
+ buf.append(LOG4CXX_STR("&amp;"));
+ break;
+
+ case 0x3C:
+ buf.append(LOG4CXX_STR("&lt;"));
+ break;
+
+ case 0x3E:
+ buf.append(LOG4CXX_STR("&gt;"));
+ break;
+
+ default:
+ buf.append(1, input[special]);
+ break;
+ }
+ start = special+1;
+ if (special < input.size()) {
+ special = input.find_first_of(specials, start);
+ } else {
+ special = LogString::npos;
+ }
+ }
+
+ if (start < input.size()) {
+ buf.append(input, start, input.size() - start);
+ }
+}
+
+void Transform::appendEscapingCDATA(
+ LogString& buf, const LogString& input)
+{
+ static const LogString CDATA_END(LOG4CXX_STR("]]>"));
+ static const LogString CDATA_EMBEDED_END(LOG4CXX_STR("]]>]]&gt;<![CDATA["));
+
+ const LogString::size_type CDATA_END_LEN = 3;
+
+
+ if(input.length() == 0 )
+ {
+ return;
+ }
+
+ LogString::size_type end = input.find(CDATA_END);
+ if (end == LogString::npos)
+ {
+ buf.append(input);
+ return;
+ }
+
+ LogString::size_type start = 0;
+ while (end != LogString::npos)
+ {
+ buf.append(input, start, end-start);
+ buf.append(CDATA_EMBEDED_END);
+ start = end + CDATA_END_LEN;
+ if (start < input.length())
+ {
+ end = input.find(CDATA_END, start);
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ buf.append(input, start, input.length() - start);
+}
+
diff --git a/src/main/cpp/triggeringpolicy.cpp b/src/main/cpp/triggeringpolicy.cpp
new file mode 100644
index 0000000..310e74e
--- /dev/null
+++ b/src/main/cpp/triggeringpolicy.cpp
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/rolling/triggeringpolicy.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(TriggeringPolicy)
+
+TriggeringPolicy::~TriggeringPolicy() {
+}
+
+void TriggeringPolicy::addRef() const {
+ ObjectImpl::addRef();
+}
+
+void TriggeringPolicy::releaseRef() const {
+ ObjectImpl::releaseRef();
+}
diff --git a/src/main/cpp/ttcclayout.cpp b/src/main/cpp/ttcclayout.cpp
new file mode 100644
index 0000000..f66409a
--- /dev/null
+++ b/src/main/cpp/ttcclayout.cpp
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/ttcclayout.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/level.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/ndc.h>
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(TTCCLayout)
+
+TTCCLayout::TTCCLayout()
+: DateLayout(LOG4CXX_STR("RELATIVE")), threadPrinting(true), categoryPrefixing(true),
+contextPrinting(true), filePrinting(false)
+{
+ Pool pool;
+ activateOptions(pool);
+}
+
+TTCCLayout::TTCCLayout(const LogString& dateFormatType)
+: DateLayout(dateFormatType), threadPrinting(true), categoryPrefixing(true),
+contextPrinting(true), filePrinting(false)
+{
+ Pool pool;
+ activateOptions(pool);
+}
+
+void TTCCLayout::format(LogString& output,
+ const spi::LoggingEventPtr& event,
+ Pool& p) const
+{
+ formatDate(output, event, p);
+
+ if(threadPrinting)
+ {
+ output.append(1, (logchar) 0x5B /* '[' */);
+ output.append(event->getThreadName());
+ output.append(1, (logchar) 0x5D /* ']' */);
+ output.append(1, (logchar) 0x20 /* ' ' */);
+ }
+
+ output.append(event->getLevel()->toString());
+ output.append(1, (logchar) 0x20 /* ' ' */);
+ if(categoryPrefixing)
+ {
+ output.append(event->getLoggerName());
+ output.append(1, (logchar) 0x20 /* ' ' */);
+ }
+
+ if(contextPrinting && event->getNDC(output)) {
+ output.append(1, (logchar) 0x20 /* ' ' */);
+ }
+
+ output.append(1, (logchar) 0x2D /* '-' */);
+ output.append(1, (logchar) 0x20 /* ' ' */);
+ output.append(event->getRenderedMessage());
+ output.append(LOG4CXX_EOL);
+}
diff --git a/src/main/cpp/writer.cpp b/src/main/cpp/writer.cpp
new file mode 100644
index 0000000..b1f481f
--- /dev/null
+++ b/src/main/cpp/writer.cpp
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/writer.h>
+
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(Writer)
+
+Writer::Writer() {
+}
+
+Writer::~Writer() {
+}
diff --git a/src/main/cpp/writerappender.cpp b/src/main/cpp/writerappender.cpp
new file mode 100644
index 0000000..c54c5fe
--- /dev/null
+++ b/src/main/cpp/writerappender.cpp
@@ -0,0 +1,264 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/writerappender.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/layout.h>
+#include <log4cxx/helpers/stringhelper.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+IMPLEMENT_LOG4CXX_OBJECT(WriterAppender)
+
+WriterAppender::WriterAppender() {
+ synchronized sync(mutex);
+ immediateFlush = true;
+}
+
+WriterAppender::WriterAppender(const LayoutPtr& layout1,
+ log4cxx::helpers::WriterPtr& writer1)
+ : AppenderSkeleton(layout1), writer(writer1) {
+ Pool p;
+ synchronized sync(mutex);
+ immediateFlush = true;
+ activateOptions(p);
+}
+
+WriterAppender::WriterAppender(const LayoutPtr& layout1)
+ : AppenderSkeleton(layout1) {
+ synchronized sync(mutex);
+ immediateFlush = true;
+}
+
+
+WriterAppender::~WriterAppender()
+{
+ finalize();
+}
+
+void WriterAppender::activateOptions(Pool& p)
+{
+ int errors = 0;
+ if(layout == 0) {
+ errorHandler->error(
+ ((LogString) LOG4CXX_STR("No layout set for the appender named ["))
+ + name+ LOG4CXX_STR("]."));
+ errors++;
+ }
+
+ if(writer == 0) {
+ errorHandler->error(
+ ((LogString) LOG4CXX_STR("No writer set for the appender named ["))
+ + name+ LOG4CXX_STR("]."));
+ errors++;
+ }
+
+ if (errors == 0) {
+ AppenderSkeleton::activateOptions(p);
+ }
+}
+
+
+
+void WriterAppender::append(const spi::LoggingEventPtr& event, Pool& pool1)
+{
+
+ if(!checkEntryConditions())
+ {
+ return;
+ }
+
+ subAppend(event, pool1);
+}
+
+/**
+ This method determines if there is a sense in attempting to append.
+
+ <p>It checks whether there is a set output target and also if
+ there is a set layout. If these checks fail, then the boolean
+ value <code>false</code> is returned. */
+bool WriterAppender::checkEntryConditions() const {
+ static bool warnedClosed = false;
+ static bool warnedNoWriter = false;
+ if (closed) {
+ if(!warnedClosed) {
+ LogLog::warn(LOG4CXX_STR("Not allowed to write to a closed appender."));
+ warnedClosed = true;
+ }
+ return false;
+ }
+
+ if (writer == 0) {
+ if (!warnedNoWriter) {
+ LogLog::error(
+ LogString(LOG4CXX_STR("No output stream or file set for the appender named [")) +
+ name + LOG4CXX_STR("]."));
+ warnedNoWriter = true;
+ }
+
+ return false;
+ }
+
+ return true;
+}
+
+
+
+
+/**
+ Close this appender instance. The underlying stream or writer is
+ also closed.
+
+ <p>Closed appenders cannot be reused.
+
+ @see #setWriter
+ */
+void WriterAppender::close()
+{
+ synchronized sync(mutex);
+
+ if(closed)
+ {
+ return;
+ }
+
+ closed = true;
+ closeWriter();
+}
+
+/**
+ * Close the underlying {@link java.io.Writer}.
+ * */
+void WriterAppender::closeWriter() {
+ if (writer != NULL) {
+ try {
+ // before closing we have to output out layout's footer
+ //
+ // Using the object's pool since this is a one-shot operation
+ // and pool is likely to be reclaimed soon when appender is destructed.
+ //
+ writeFooter(pool);
+ writer->close(pool);
+ writer = 0;
+ } catch (IOException& e) {
+ LogLog::error(LogString(LOG4CXX_STR("Could not close writer for WriterAppender named "))+name, e);
+ }
+ }
+
+}
+
+/**
+ Returns an OutputStreamWriter when passed an OutputStream. The
+ encoding used will depend on the value of the
+ <code>encoding</code> property. If the encoding value is
+ specified incorrectly the writer will be opened using the default
+ system encoding (an error message will be printed to the loglog. */
+WriterPtr WriterAppender::createWriter(OutputStreamPtr& os) {
+
+ LogString enc(getEncoding());
+
+ CharsetEncoderPtr encoder;
+ if (enc.empty()) {
+ encoder = CharsetEncoder::getDefaultEncoder();
+ } else {
+ if(StringHelper::equalsIgnoreCase(enc,
+ LOG4CXX_STR("utf-16"), LOG4CXX_STR("UTF-16"))) {
+ encoder = CharsetEncoder::getEncoder(LOG4CXX_STR("UTF-16BE"));
+ } else {
+ encoder = CharsetEncoder::getEncoder(enc);
+ }
+ if (encoder == NULL) {
+ encoder = CharsetEncoder::getDefaultEncoder();
+ LogLog::warn(LOG4CXX_STR("Error initializing output writer."));
+ LogLog::warn(LOG4CXX_STR("Unsupported encoding?"));
+ }
+ }
+
+ return new OutputStreamWriter(os, encoder);
+}
+
+LogString WriterAppender::getEncoding() const {
+ return encoding;
+}
+
+void WriterAppender::setEncoding(const LogString& enc) {
+ encoding = enc;
+}
+
+void WriterAppender::subAppend(const spi::LoggingEventPtr& event, Pool& p)
+{
+ LogString msg;
+ layout->format(msg, event, p);
+ {
+ synchronized sync(mutex);
+ if (writer != NULL) {
+ writer->write(msg, p);
+ if (immediateFlush) {
+ writer->flush(p);
+ }
+ }
+ }
+}
+
+
+void WriterAppender::writeFooter(Pool& p)
+{
+ if (layout != NULL) {
+ LogString foot;
+ layout->appendFooter(foot, p);
+ synchronized sync(mutex);
+ writer->write(foot, p);
+ }
+}
+
+void WriterAppender::writeHeader(Pool& p)
+{
+ if(layout != NULL) {
+ LogString header;
+ layout->appendHeader(header, p);
+ synchronized sync(mutex);
+ writer->write(header, p);
+ }
+}
+
+
+void WriterAppender::setWriter(const WriterPtr& newWriter) {
+ synchronized sync(mutex);
+ writer = newWriter;
+}
+
+
+bool WriterAppender::requiresLayout() const {
+ return true;
+}
+
+void WriterAppender::setOption(const LogString& option, const LogString& value) {
+ if(StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("ENCODING"), LOG4CXX_STR("encoding"))) {
+ setEncoding(value);
+ } else {
+ AppenderSkeleton::setOption(option, value);
+ }
+}
+
+
+void WriterAppender::setImmediateFlush(bool value) {
+ synchronized sync(mutex);
+ immediateFlush = value;
+}
diff --git a/src/main/cpp/xmllayout.cpp b/src/main/cpp/xmllayout.cpp
new file mode 100644
index 0000000..c42def0
--- /dev/null
+++ b/src/main/cpp/xmllayout.cpp
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/xml/xmllayout.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/level.h>
+#include <log4cxx/helpers/transform.h>
+#include <log4cxx/helpers/iso8601dateformat.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/ndc.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+using namespace log4cxx::xml;
+
+IMPLEMENT_LOG4CXX_OBJECT(XMLLayout)
+
+XMLLayout::XMLLayout()
+: locationInfo(false), properties(false)
+{
+}
+
+void XMLLayout::setOption(const LogString& option,
+ const LogString& value)
+{
+ if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("LOCATIONINFO"), LOG4CXX_STR("locationinfo")))
+ {
+ setLocationInfo(OptionConverter::toBoolean(value, false));
+ }
+ if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("PROPERTIES"), LOG4CXX_STR("properties")))
+ {
+ setProperties(OptionConverter::toBoolean(value, false));
+ }
+}
+
+void XMLLayout::format(LogString& output,
+ const spi::LoggingEventPtr& event,
+ Pool& p) const
+{
+ output.append(LOG4CXX_STR("<log4j:event logger=\""));
+ Transform::appendEscapingTags(output, event->getLoggerName());
+ output.append(LOG4CXX_STR("\" timestamp=\""));
+ StringHelper::toString(event->getTimeStamp()/1000L, p, output);
+ output.append(LOG4CXX_STR("\" level=\""));
+ Transform::appendEscapingTags(output, event->getLevel()->toString());
+ output.append(LOG4CXX_STR("\" thread=\""));
+ Transform::appendEscapingTags(output, event->getThreadName());
+ output.append(LOG4CXX_STR("\">"));
+ output.append(LOG4CXX_EOL);
+
+ output.append(LOG4CXX_STR("<log4j:message><![CDATA["));
+ // Append the rendered message. Also make sure to escape any
+ // existing CDATA sections.
+ Transform::appendEscapingCDATA(output, event->getRenderedMessage());
+ output.append(LOG4CXX_STR("]]></log4j:message>"));
+ output.append(LOG4CXX_EOL);
+
+ LogString ndc;
+ if(event->getNDC(ndc)) {
+ output.append(LOG4CXX_STR("<log4j:NDC><![CDATA["));
+ Transform::appendEscapingCDATA(output, ndc);
+ output.append(LOG4CXX_STR("]]></log4j:NDC>"));
+ output.append(LOG4CXX_EOL);
+ }
+
+ if(locationInfo)
+ {
+ output.append(LOG4CXX_STR("<log4j:locationInfo class=\""));
+ const LocationInfo& locInfo = event->getLocationInformation();
+ LOG4CXX_DECODE_CHAR(className, locInfo.getClassName());
+ Transform::appendEscapingTags(output, className);
+ output.append(LOG4CXX_STR("\" method=\""));
+ LOG4CXX_DECODE_CHAR(method, locInfo.getMethodName());
+ Transform::appendEscapingTags(output, method);
+ output.append(LOG4CXX_STR("\" file=\""));
+ LOG4CXX_DECODE_CHAR(fileName, locInfo.getFileName());
+ Transform::appendEscapingTags(output, fileName);
+ output.append(LOG4CXX_STR("\" line=\""));
+ StringHelper::toString(locInfo.getLineNumber(), p, output);
+ output.append(LOG4CXX_STR("\"/>"));
+ output.append(LOG4CXX_EOL);
+ }
+
+ if (properties) {
+ LoggingEvent::KeySet propertySet(event->getPropertyKeySet());
+ LoggingEvent::KeySet keySet(event->getMDCKeySet());
+ if (!(keySet.empty() && propertySet.empty())) {
+ output.append(LOG4CXX_STR("<log4j:properties>"));
+ output.append(LOG4CXX_EOL);
+ for (LoggingEvent::KeySet::const_iterator i = keySet.begin();
+ i != keySet.end();
+ i++) {
+ LogString key(*i);
+ LogString value;
+ if(event->getMDC(key, value)) {
+ output.append(LOG4CXX_STR("<log4j:data name=\""));
+ Transform::appendEscapingTags(output, key);
+ output.append(LOG4CXX_STR("\" value=\""));
+ Transform::appendEscapingTags(output, value);
+ output.append(LOG4CXX_STR("\"/>"));
+ output.append(LOG4CXX_EOL);
+ }
+ }
+ for (LoggingEvent::KeySet::const_iterator i2 = propertySet.begin();
+ i2 != propertySet.end();
+ i2++) {
+ LogString key(*i2);
+ LogString value;
+ if(event->getProperty(key, value)) {
+ output.append(LOG4CXX_STR("<log4j:data name=\""));
+ Transform::appendEscapingTags(output, key);
+ output.append(LOG4CXX_STR("\" value=\""));
+ Transform::appendEscapingTags(output, value);
+ output.append(LOG4CXX_STR("\"/>"));
+ output.append(LOG4CXX_EOL);
+ }
+ }
+ output.append(LOG4CXX_STR("</log4j:properties>"));
+ output.append(LOG4CXX_EOL);
+ }
+ }
+
+ output.append(LOG4CXX_STR("</log4j:event>"));
+ output.append(LOG4CXX_EOL);
+ output.append(LOG4CXX_EOL);
+}
+
diff --git a/src/main/cpp/xmlsocketappender.cpp b/src/main/cpp/xmlsocketappender.cpp
new file mode 100644
index 0000000..c5ce1a9
--- /dev/null
+++ b/src/main/cpp/xmlsocketappender.cpp
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/net/xmlsocketappender.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/outputstreamwriter.h>
+#include <log4cxx/helpers/charsetencoder.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/xml/xmllayout.h>
+#include <log4cxx/level.h>
+#include <log4cxx/helpers/transform.h>
+#include <apr_time.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/socketoutputstream.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::net;
+using namespace log4cxx::xml;
+
+IMPLEMENT_LOG4CXX_OBJECT(XMLSocketAppender)
+
+// The default port number of remote logging server (4560)
+int XMLSocketAppender::DEFAULT_PORT = 4560;
+
+// The default reconnection delay (30000 milliseconds or 30 seconds).
+int XMLSocketAppender::DEFAULT_RECONNECTION_DELAY = 30000;
+
+const int XMLSocketAppender::MAX_EVENT_LEN = 1024;
+
+XMLSocketAppender::XMLSocketAppender()
+: SocketAppenderSkeleton(DEFAULT_PORT, DEFAULT_RECONNECTION_DELAY)
+{
+ layout = new XMLLayout();
+}
+
+XMLSocketAppender::XMLSocketAppender(InetAddressPtr address1, int port1)
+: SocketAppenderSkeleton(address1, port1, DEFAULT_RECONNECTION_DELAY)
+{
+ layout = new XMLLayout();
+ Pool p;
+ activateOptions(p);
+}
+
+XMLSocketAppender::XMLSocketAppender(const LogString& host, int port1)
+: SocketAppenderSkeleton(host, port1, DEFAULT_RECONNECTION_DELAY)
+{
+ layout = new XMLLayout();
+ Pool p;
+ activateOptions(p);
+}
+
+XMLSocketAppender::~XMLSocketAppender() {
+ finalize();
+}
+
+
+int XMLSocketAppender::getDefaultDelay() const {
+ return DEFAULT_RECONNECTION_DELAY;
+}
+
+int XMLSocketAppender::getDefaultPort() const {
+ return DEFAULT_PORT;
+}
+
+void XMLSocketAppender::setSocket(log4cxx::helpers::SocketPtr& socket, Pool& p) {
+ OutputStreamPtr os(new SocketOutputStream(socket));
+ CharsetEncoderPtr charset(CharsetEncoder::getUTF8Encoder());
+ synchronized sync(mutex);
+ writer = new OutputStreamWriter(os, charset);
+}
+
+void XMLSocketAppender::cleanUp(Pool& p) {
+ if (writer != 0) {
+ try {
+ writer->close(p);
+ writer = 0;
+ } catch(std::exception &e) {
+ }
+ }
+}
+
+void XMLSocketAppender::append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) {
+ if (writer != 0) {
+ LogString output;
+ layout->format(output, event, p);
+ try {
+ writer->write(output, p);
+ writer->flush(p);
+ } catch(std::exception& e) {
+ writer = 0;
+ LogLog::warn(LOG4CXX_STR("Detected problem with connection: "), e);
+ if (getReconnectionDelay() > 0) {
+ fireConnector();
+ }
+ }
+ }
+}
+
+
+
+
diff --git a/src/main/cpp/zipcompressaction.cpp b/src/main/cpp/zipcompressaction.cpp
new file mode 100644
index 0000000..0a76b4f
--- /dev/null
+++ b/src/main/cpp/zipcompressaction.cpp
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/rolling/zipcompressaction.h>
+#include <apr_thread_proc.h>
+#include <apr_strings.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/transcoder.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(ZipCompressAction)
+
+ZipCompressAction::ZipCompressAction(const File& src,
+ const File& dest,
+ bool del)
+ : source(src), destination(dest), deleteSource(del) {
+}
+
+bool ZipCompressAction::execute(log4cxx::helpers::Pool& p) const {
+ if (source.exists(p)) {
+ apr_pool_t* pool = p.getAPRPool();
+ apr_procattr_t* attr;
+ apr_status_t stat = apr_procattr_create(&attr, pool);
+ if (stat != APR_SUCCESS) throw IOException(stat);
+
+ stat = apr_procattr_io_set(attr, APR_NO_PIPE, APR_NO_PIPE, APR_FULL_BLOCK);
+ if (stat != APR_SUCCESS) throw IOException(stat);
+
+ stat = apr_procattr_cmdtype_set(attr, APR_PROGRAM_PATH);
+ if (stat != APR_SUCCESS) throw IOException(stat);
+
+
+ //
+ // redirect the child's error stream to this processes' error stream
+ //
+ apr_file_t* child_err;
+ stat = apr_file_open_stderr(&child_err, pool);
+ if (stat == APR_SUCCESS) {
+ stat = apr_procattr_child_err_set(attr, child_err, NULL);
+ if (stat != APR_SUCCESS) throw IOException(stat);
+ }
+
+ const char** args = (const char**)
+ apr_palloc(pool, 5 *sizeof(*args));
+ int i = 0;
+ args[i++] = "zip";
+ args[i++] = "-q";
+ args[i++] = Transcoder::encode(destination.getPath(), p);
+ args[i++] = Transcoder::encode(source.getPath(), p);
+ args[i++] = NULL;
+
+ if (destination.exists(p)) {
+ destination.deleteFile(p);
+ }
+
+ apr_proc_t pid;
+ stat = apr_proc_create(&pid, "zip", args, NULL, attr, pool);
+ if (stat != APR_SUCCESS) throw IOException(stat);
+
+ apr_proc_wait(&pid, NULL, NULL, APR_WAIT);
+
+ if (deleteSource) {
+ source.deleteFile(p);
+ }
+ return true;
+ }
+ return false;
+}
+
diff --git a/src/main/include/Makefile.am b/src/main/include/Makefile.am
new file mode 100644
index 0000000..072c7bb
--- /dev/null
+++ b/src/main/include/Makefile.am
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+SUBDIRS = log4cxx
diff --git a/src/main/include/log4cxx/Makefile.am b/src/main/include/log4cxx/Makefile.am
new file mode 100644
index 0000000..719c2dd
--- /dev/null
+++ b/src/main/include/log4cxx/Makefile.am
@@ -0,0 +1,24 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+SUBDIRS = helpers net nt rolling spi varia xml config db private pattern filter
+log4cxxincdir = $(includedir)/log4cxx
+log4cxxinc_HEADERS= $(top_srcdir)/src/main/include/log4cxx/*.h log4cxx.h
+DISTCLEANFILES = log4cxx.h
+EXTRA_DIST = log4cxx.hw
+
+dist-hook:
+ -rm -f $(distdir)/log4cxx.h
+
diff --git a/src/main/include/log4cxx/appender.h b/src/main/include/log4cxx/appender.h
new file mode 100644
index 0000000..8fd798e
--- /dev/null
+++ b/src/main/include/log4cxx/appender.h
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_APPENDER_H
+#define _LOG4CXX_APPENDER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/spi/optionhandler.h>
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/object.h>
+#include <vector>
+
+
+namespace log4cxx
+{
+ // Forward declarations
+ namespace spi
+ {
+ class LoggingEvent;
+ typedef helpers::ObjectPtrT<LoggingEvent> LoggingEventPtr;
+
+ class Filter;
+ typedef helpers::ObjectPtrT<Filter> FilterPtr;
+
+ class ErrorHandler;
+ typedef log4cxx::helpers::ObjectPtrT<ErrorHandler> ErrorHandlerPtr;
+ }
+
+ class Layout;
+ typedef log4cxx::helpers::ObjectPtrT<Layout> LayoutPtr;
+
+
+ /**
+ Implement this interface for your own strategies for outputting log
+ statements.
+ */
+ class LOG4CXX_EXPORT Appender :
+ public virtual spi::OptionHandler
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(Appender)
+
+ virtual ~Appender() {}
+
+ /**
+ Add a filter to the end of the filter list.
+ */
+ virtual void addFilter(const spi::FilterPtr& newFilter) = 0;
+
+ /**
+ Returns the head Filter. The Filters are organized in a linked list
+ and so all Filters on this Appender are available through the result.
+
+ @return the head Filter or null, if no Filters are present
+ */
+ virtual spi::FilterPtr getFilter() const = 0;
+
+ /**
+ Clear the list of filters by removing all the filters in it.
+ */
+ virtual void clearFilters() = 0;
+
+ /**
+ Release any resources allocated within the appender such as file
+ handles, network connections, etc.
+ <p>It is a programming error to append to a closed appender.
+ */
+ virtual void close() = 0;
+
+ /**
+ Log in <code>Appender</code> specific way. When appropriate,
+ Loggers will call the <code>doAppend</code> method of appender
+ implementations in order to log.
+ */
+ virtual void doAppend(const spi::LoggingEventPtr& event,
+ log4cxx::helpers::Pool& pool) = 0;
+
+
+ /**
+ Get the name of this appender. The name uniquely identifies the
+ appender.
+ */
+ virtual LogString getName() const = 0;
+
+
+ /**
+ Set the Layout for this appender.
+ */
+ virtual void setLayout(const LayoutPtr& layout) = 0;
+
+ /**
+ Returns this appenders layout.
+ */
+ virtual LayoutPtr getLayout() const = 0;
+
+
+ /**
+ Set the name of this appender. The name is used by other
+ components to identify this appender.
+ */
+ virtual void setName(const LogString& name) = 0;
+
+ /**
+ Configurators call this method to determine if the appender
+ requires a layout. If this method returns <code>true</code>,
+ meaning that layout is required, then the configurator will
+ configure an layout using the configuration information at its
+ disposal. If this method returns <code>false</code>, meaning that
+ a layout is not required, then layout configuration will be
+ skipped even if there is available layout configuration
+ information at the disposal of the configurator..
+
+ <p>In the rather exceptional case, where the appender
+ implementation admits a layout but can also work without it, then
+ the appender should return <code>true</code>.
+ */
+ virtual bool requiresLayout() const = 0;
+ };
+
+ LOG4CXX_PTR_DEF(Appender);
+ LOG4CXX_LIST_DEF(AppenderList, AppenderPtr);
+
+}
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif //_LOG4CXX_APPENDER_H
diff --git a/src/main/include/log4cxx/appenderskeleton.h b/src/main/include/log4cxx/appenderskeleton.h
new file mode 100644
index 0000000..16242bd
--- /dev/null
+++ b/src/main/include/log4cxx/appenderskeleton.h
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_APPENDER_SKELETON_H
+#define _LOG4CXX_APPENDER_SKELETON_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/appender.h>
+#include <log4cxx/layout.h>
+#include <log4cxx/spi/errorhandler.h>
+#include <log4cxx/spi/filter.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/helpers/mutex.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/level.h>
+
+
+namespace log4cxx
+{
+ /**
+ * Implementation base class for all appenders.
+ *
+ * This class provides the code for common functionality, such as
+ * support for threshold filtering and support for general filters.
+ * */
+ class LOG4CXX_EXPORT AppenderSkeleton :
+ public virtual Appender,
+ public virtual helpers::ObjectImpl
+ {
+ protected:
+ /** The layout variable does not need to be set if the appender
+ implementation has its own layout. */
+ LayoutPtr layout;
+
+ /** Appenders are named. */
+ LogString name;
+
+ /**
+ There is no level threshold filtering by default. */
+ LevelPtr threshold;
+
+ /**
+ It is assumed and enforced that errorHandler is never null.
+ */
+ spi::ErrorHandlerPtr errorHandler;
+
+ /** The first filter in the filter chain. Set to <code>null</code>
+ initially. */
+ spi::FilterPtr headFilter;
+
+ /** The last filter in the filter chain. */
+ spi::FilterPtr tailFilter;
+
+ /**
+ Is this appender closed?
+ */
+ bool closed;
+
+ log4cxx::helpers::Pool pool;
+ log4cxx::helpers::Mutex mutex;
+
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(AppenderSkeleton)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(Appender)
+ LOG4CXX_CAST_ENTRY(spi::OptionHandler)
+ END_LOG4CXX_CAST_MAP()
+
+ AppenderSkeleton();
+ AppenderSkeleton(const LayoutPtr& layout);
+
+ void addRef() const;
+ void releaseRef() const;
+
+ /**
+ Finalize this appender by calling the derived class'
+ <code>close</code> method.
+ */
+ void finalize();
+
+ /**
+ Derived appenders should override this method if option structure
+ requires it.
+ */
+ virtual void activateOptions(log4cxx::helpers::Pool& /* pool */) {}
+ virtual void setOption(const LogString& option, const LogString& value);
+
+ /**
+ Add a filter to end of the filter list.
+ */
+ void addFilter(const spi::FilterPtr& newFilter) ;
+
+ /**
+ Subclasses of <code>AppenderSkeleton</code> should implement this
+ method to perform actual logging. See also AppenderSkeleton::doAppend
+ method.
+ */
+ protected:
+ virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) = 0;
+
+ /**
+ Clear the filters chain.
+ */
+ public:
+ void clearFilters();
+
+ /**
+ Return the currently set spi::ErrorHandler for this
+ Appender.
+ */
+ const spi::ErrorHandlerPtr& getErrorHandler() const { return errorHandler; }
+
+ /**
+ Returns the head Filter.
+ */
+ spi::FilterPtr getFilter() const { return headFilter; }
+
+ /**
+ Return the first filter in the filter chain for this
+ Appender. The return value may be <code>0</code> if no is
+ filter is set.
+ */
+ const spi::FilterPtr& getFirstFilter() const { return headFilter; }
+
+ /**
+ Returns the layout of this appender. The value may be 0.
+ */
+ LayoutPtr getLayout() const { return layout; }
+
+
+ /**
+ Returns the name of this Appender.
+ */
+ LogString getName() const { return name; }
+
+ /**
+ Returns this appenders threshold level. See the #setThreshold
+ method for the meaning of this option.
+ */
+ const LevelPtr& getThreshold() { return threshold; }
+
+ /**
+ Check whether the message level is below the appender's
+ threshold. If there is no threshold set, then the return value is
+ always <code>true</code>.
+ */
+ bool isAsSevereAsThreshold(const LevelPtr& level) const;
+
+
+ /**
+ * This method performs threshold checks and invokes filters before
+ * delegating actual logging to the subclasses specific
+ * AppenderSkeleton#append method.
+ * */
+ void doAppend(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool);
+
+ /**
+ Set the {@link spi::ErrorHandler ErrorHandler} for this Appender.
+ */
+ void setErrorHandler(const spi::ErrorHandlerPtr& eh);
+
+ /**
+ Set the layout for this appender. Note that some appenders have
+ their own (fixed) layouts or do not use one. For example, the
+ {@link net::SocketAppender SocketAppender} ignores the layout set
+ here.
+ */
+ void setLayout(const LayoutPtr& layout1) { this->layout = layout1; }
+
+ /**
+ Set the name of this Appender.
+ */
+ void setName(const LogString& name1) { this->name.assign(name1); }
+
+
+ /**
+ Set the threshold level. All log events with lower level
+ than the threshold level are ignored by the appender.
+
+ <p>In configuration files this option is specified by setting the
+ value of the <b>Threshold</b> option to a level
+ string, such as "DEBUG", "INFO" and so on.
+ */
+ void setThreshold(const LevelPtr& threshold);
+
+ }; // class AppenderSkeleton
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+#endif //_LOG4CXX_APPENDER_SKELETON_H
diff --git a/src/main/include/log4cxx/asyncappender.h b/src/main/include/log4cxx/asyncappender.h
new file mode 100644
index 0000000..cbe9b3c
--- /dev/null
+++ b/src/main/include/log4cxx/asyncappender.h
@@ -0,0 +1,292 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_ASYNC_APPENDER_H
+#define _LOG4CXX_ASYNC_APPENDER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/appenderskeleton.h>
+#include <log4cxx/helpers/appenderattachableimpl.h>
+#include <deque>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/thread.h>
+#include <log4cxx/helpers/mutex.h>
+#include <log4cxx/helpers/condition.h>
+
+
+namespace log4cxx
+{
+
+ /**
+ The AsyncAppender lets users log events asynchronously. It uses a
+ bounded buffer to store logging events.
+
+ <p>The AsyncAppender will collect the events sent to it and then
+ dispatch them to all the appenders that are attached to it. You can
+ attach multiple appenders to an AsyncAppender.
+
+ <p>The AsyncAppender uses a separate thread to serve the events in
+ its bounded buffer.
+
+ <p><b>Important note:</b> The <code>AsyncAppender</code> can only
+ be script configured using the {@link xml::DOMConfigurator DOMConfigurator}.
+ */
+ class LOG4CXX_EXPORT AsyncAppender :
+ public virtual spi::AppenderAttachable,
+ public virtual AppenderSkeleton
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(AsyncAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(AsyncAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+ LOG4CXX_CAST_ENTRY(spi::AppenderAttachable)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Create new instance.
+ */
+ AsyncAppender();
+
+ /**
+ * Destructor.
+ */
+ virtual ~AsyncAppender();
+
+ void addRef() const;
+ void releaseRef() const;
+
+ /**
+ * Add appender.
+ *
+ * @param newAppender appender to add, may not be null.
+ */
+ void addAppender(const AppenderPtr& newAppender);
+
+ void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);
+
+ /**
+ Close this <code>AsyncAppender</code> by interrupting the
+ dispatcher thread which will process all pending events before
+ exiting.
+ */
+ void close();
+
+ /**
+ * Get iterator over attached appenders.
+ * @return list of all attached appenders.
+ */
+ AppenderList getAllAppenders() const;
+
+ /**
+ * Get appender by name.
+ *
+ * @param name name, may not be null.
+ * @return matching appender or null.
+ */
+ AppenderPtr getAppender(const LogString& name) const;
+
+ /**
+ * Gets whether the location of the logging request call
+ * should be captured.
+ *
+ * @return the current value of the <b>LocationInfo</b> option.
+ */
+ bool getLocationInfo() const;
+ /**
+ * Determines if specified appender is attached.
+ * @param appender appender.
+ * @return true if attached.
+ */
+ bool isAttached(const AppenderPtr& appender) const;
+
+ virtual bool requiresLayout() const;
+
+ /**
+ * Removes and closes all attached appenders.
+ */
+ void removeAllAppenders();
+
+ /**
+ * Removes an appender.
+ * @param appender appender to remove.
+ */
+ void removeAppender(const AppenderPtr& appender);
+ /**
+ * Remove appender by name.
+ * @param name name.
+ */
+ void removeAppender(const LogString& name);
+
+ /**
+ * The <b>LocationInfo</b> attribute is provided for compatibility
+ * with log4j and has no effect on the log output.
+ * @param flag new value.
+ */
+ void setLocationInfo(bool flag);
+
+ /**
+ * The <b>BufferSize</b> option takes a non-negative integer value.
+ * This integer value determines the maximum size of the bounded
+ * buffer.
+ * */
+ void setBufferSize(int size);
+
+ /**
+ * Gets the current buffer size.
+ * @return the current value of the <b>BufferSize</b> option.
+ */
+ int getBufferSize() const;
+
+ /**
+ * Sets whether appender should wait if there is no
+ * space available in the event buffer or immediately return.
+ *
+ * @param value true if appender should wait until available space in buffer.
+ */
+ void setBlocking(bool value);
+
+ /**
+ * Gets whether appender should block calling thread when buffer is full.
+ * If false, messages will be counted by logger and a summary
+ * message appended after the contents of the buffer have been appended.
+ *
+ * @return true if calling thread will be blocked when buffer is full.
+ */
+ bool getBlocking() const;
+
+
+ /**
+ * Set appender properties by name.
+ * @param option property name.
+ * @param value property value.
+ */
+ void setOption(const LogString& option, const LogString& value);
+
+
+ private:
+ AsyncAppender(const AsyncAppender&);
+ AsyncAppender& operator=(const AsyncAppender&);
+ /**
+ * The default buffer size is set to 128 events.
+ */
+ enum { DEFAULT_BUFFER_SIZE = 128 };
+
+ /**
+ * Event buffer.
+ */
+ LOG4CXX_LIST_DEF(LoggingEventList, log4cxx::spi::LoggingEventPtr);
+ LoggingEventList buffer;
+
+ /**
+ * Mutex used to guard access to buffer and discardMap.
+ */
+ ::log4cxx::helpers::Mutex bufferMutex;
+ ::log4cxx::helpers::Condition bufferNotFull;
+ ::log4cxx::helpers::Condition bufferNotEmpty;
+
+ class DiscardSummary {
+ private:
+ /**
+ * First event of the highest severity.
+ */
+ ::log4cxx::spi::LoggingEventPtr maxEvent;
+
+ /**
+ * Total count of messages discarded.
+ */
+ int count;
+
+ public:
+ /**
+ * Create new instance.
+ *
+ * @param event event, may not be null.
+ */
+ DiscardSummary(const ::log4cxx::spi::LoggingEventPtr& event);
+ /** Copy constructor. */
+ DiscardSummary(const DiscardSummary& src);
+ /** Assignment operator. */
+ DiscardSummary& operator=(const DiscardSummary& src);
+
+ /**
+ * Add discarded event to summary.
+ *
+ * @param event event, may not be null.
+ */
+ void add(const ::log4cxx::spi::LoggingEventPtr& event);
+
+ /**
+ * Create event with summary information.
+ *
+ * @return new event.
+ */
+ ::log4cxx::spi::LoggingEventPtr createEvent(::log4cxx::helpers::Pool& p);
+ };
+
+ /**
+ * Map of DiscardSummary objects keyed by logger name.
+ */
+ typedef std::map<LogString, DiscardSummary> DiscardMap;
+ DiscardMap* discardMap;
+
+ /**
+ * Buffer size.
+ */
+ int bufferSize;
+
+ /**
+ * Nested appenders.
+ */
+ helpers::AppenderAttachableImplPtr appenders;
+
+ /**
+ * Dispatcher.
+ */
+ helpers::Thread dispatcher;
+
+ /**
+ * Should location info be included in dispatched messages.
+ */
+ bool locationInfo;
+
+ /**
+ * Does appender block when buffer is full.
+ */
+ bool blocking;
+
+ /**
+ * Dispatch routine.
+ */
+ static void* LOG4CXX_THREAD_FUNC dispatch(apr_thread_t* thread, void* data);
+
+ }; // class AsyncAppender
+ LOG4CXX_PTR_DEF(AsyncAppender);
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+#endif// _LOG4CXX_ASYNC_APPENDER_H
+
diff --git a/src/main/include/log4cxx/basicconfigurator.h b/src/main/include/log4cxx/basicconfigurator.h
new file mode 100644
index 0000000..3785139
--- /dev/null
+++ b/src/main/include/log4cxx/basicconfigurator.h
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_BASIC_CONFIGURATOR_H
+#define _LOG4CXX_BASIC_CONFIGURATOR_H
+
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/logstring.h>
+#include <log4cxx/spi/configurator.h>
+
+namespace log4cxx
+{
+ class Appender;
+ typedef helpers::ObjectPtrT<Appender> AppenderPtr;
+
+ /**
+ Use this class to quickly configure the package.
+ <p>For file based configuration see
+ PropertyConfigurator. For XML based configuration see
+ DOMConfigurator.
+ */
+ class LOG4CXX_EXPORT BasicConfigurator
+ {
+ protected:
+ BasicConfigurator() {}
+
+ public:
+ /**
+ Add a ConsoleAppender that uses PatternLayout
+ using the PatternLayout#TTCC_CONVERSION_PATTERN and
+ prints to <code>stdout</code> to the root logger.*/
+ static void configure();
+
+ /**
+ Add <code>appender</code> to the root logger.
+ @param appender The appender to add to the root logger.
+ */
+ static void configure(const AppenderPtr& appender);
+
+ /**
+ Reset the default hierarchy to its defaut. It is equivalent to
+ calling
+ <code>Logger::getDefaultHierarchy()->resetConfiguration()</code>.
+ See Hierarchy#resetConfiguration() for more details. */
+ static void resetConfiguration();
+ }; // class BasicConfigurator
+} // namespace log4cxx
+
+#endif //_LOG4CXX_BASIC_CONFIGURATOR_H
diff --git a/src/main/include/log4cxx/config/Makefile.am b/src/main/include/log4cxx/config/Makefile.am
new file mode 100644
index 0000000..0d7a6cf
--- /dev/null
+++ b/src/main/include/log4cxx/config/Makefile.am
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+configincdir = $(includedir)/log4cxx/config
+configinc_HEADERS= $(top_srcdir)/src/main/include/log4cxx/config/*.h
+
diff --git a/src/main/include/log4cxx/config/propertysetter.h b/src/main/include/log4cxx/config/propertysetter.h
new file mode 100644
index 0000000..91dc48c
--- /dev/null
+++ b/src/main/include/log4cxx/config/propertysetter.h
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_CONFIG_PROPERTYSETTER_H
+#define _LOG4CXX_CONFIG_PROPERTYSETTER_H
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/objectptr.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class Object;
+ typedef ObjectPtrT<Object> ObjectPtr;
+
+ class Properties;
+ class Pool;
+ }
+
+ namespace config
+ {
+ /**
+ General purpose Object property setter. Clients repeatedly invokes
+ {@link #setProperty setProperty(name,value)} in order to invoke setters
+ on the Object specified in the constructor.
+
+ <p>Usage:
+ <pre>
+ PropertySetter ps(anObject);
+ ps.set("name", "Joe");
+ ps.set("age", "32");
+ ps.set("isMale", "true");
+ </pre>
+ will cause the invocations anObject->setOption("name", "Joe"),
+ anObject->setOption("age", "32") and anObject->setOption("isMale", "true")
+ if the spi::OptionHandler interface is supported by anObject.
+ */
+ class LOG4CXX_EXPORT PropertySetter
+ {
+ protected:
+ helpers::ObjectPtr obj;
+
+ public:
+ /**
+ Create a new PropertySetter for the specified Object. This is done
+ in prepartion for invoking #setProperty one or more times.
+
+ @param obj the object for which to set properties
+ */
+ PropertySetter(const helpers::ObjectPtr& obj);
+
+ /**
+ Set the properties of an object passed as a parameter in one
+ go. The <code>properties</code> are parsed relative to a
+ <code>prefix</code>.
+
+ @param obj The object to configure.
+ @param properties A java.util.Properties containing keys and values.
+ @param prefix Only keys having the specified prefix will be set.
+ @param p pool to use for any allocations required during call.
+ */
+ static void setProperties(const helpers::ObjectPtr& obj,
+ helpers::Properties& properties,
+ const LogString& prefix,
+ log4cxx::helpers::Pool& p);
+
+ /**
+ Set the properites for the object that match the
+ <code>prefix</code> passed as parameter.
+ */
+ void setProperties(helpers::Properties& properties,
+ const LogString& prefix,
+ log4cxx::helpers::Pool& p);
+
+ /**
+ Set a property on this PropertySetter's Object. If the underlying
+ Object supports the spi::OptionHandler interface, the
+ {@link spi::OptionHandler#setOption setOption} method is called.
+
+ @param option name of the property
+ @param value String value of the property
+ @param p pool to use for any allocations required during call.
+ */
+ void setProperty(const LogString& option,
+ const LogString& value,
+ log4cxx::helpers::Pool& p);
+
+ void activate(log4cxx::helpers::Pool& p);
+ }; // class PropertySetter
+ } // namespace config;
+} // namespace log4cxx
+
+#endif //_LOG4CXX_CONFIG_PROPERTYSETTER_H
diff --git a/src/main/include/log4cxx/config_msvc.h.in b/src/main/include/log4cxx/config_msvc.h.in
new file mode 100644
index 0000000..a1c25ac
--- /dev/null
+++ b/src/main/include/log4cxx/config_msvc.h.in
@@ -0,0 +1,69 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* Name of package */
+#define PACKAGE "log4cxx"
+
+/* Version number of package */
+#define VERSION "@VERSION@"
+
+/* Define to 1 if you have the `ftime' function. */
+#define LOG4CXX_HAVE_FTIME 1
+
+/* ODBC support through Microsoft ODBC. */
+#define LOG4CXX_HAVE_MS_ODBC 1
+
+/* thread support through Microsoft threads. */
+#define LOG4CXX_HAVE_MS_THREAD 1
+
+/* ODBC support */
+#define LOG4CXX_HAVE_ODBC 1
+
+/* thread support */
+#define LOG4CXX_HAVE_THREAD 1
+
+typedef __int64 int64_t;
+
+#if defined(WIN32) || defined(_WIN32)
+#pragma warning(disable : 4250 4251 4786 4290)
+#endif
+
+#ifdef LOG4CXX_STATIC
+#define LOG4CXX_EXPORT
+// cf. file msvc/static/static.cpp
+#pragma comment(linker, "/include:?ForceSymbolReferences@@YAXXZ")
+#else // DLL
+#ifdef LOG4CXX
+ #define LOG4CXX_EXPORT __declspec(dllexport)
+#else
+ #define LOG4CXX_EXPORT __declspec(dllimport)
+#endif
+#endif
+
+#if !defined(LOG4CXX_HAVE_OLD_WIN32_INTERLOCKS)
+#if defined(_MSC_VER)
+#if _MSC_VER <= 1200
+#define LOG4CXX_HAVE_OLD_WIN32_INTERLOCKS 1
+#else
+#define LOG4CXX_HAVE_OLD_WIN32_INTERLOCKS 0
+#endif
+#else
+#define LOG4CXX_HAVE_OLD_WIN32_INTERLOCKS 0
+#endif
+#endif
+
+#define _WIN32_WINNT 0x0400
+
+#include <tchar.h>
diff --git a/src/main/include/log4cxx/consoleappender.h b/src/main/include/log4cxx/consoleappender.h
new file mode 100644
index 0000000..f77ac02
--- /dev/null
+++ b/src/main/include/log4cxx/consoleappender.h
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_CONSOLE_APPENDER_H
+#define _LOG4CXX_CONSOLE_APPENDER_H
+
+#include <log4cxx/writerappender.h>
+
+namespace log4cxx
+{
+
+ /**
+ * ConsoleAppender appends log events to <code>stdout</code> or
+ * <code>stderr</code> using a layout specified by the user. The
+ * default target is <code>stdout</code>.
+ */
+ class LOG4CXX_EXPORT ConsoleAppender : public WriterAppender
+ {
+ private:
+ LogString target;
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(ConsoleAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(ConsoleAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+ END_LOG4CXX_CAST_MAP()
+
+ ConsoleAppender();
+ ConsoleAppender(const LayoutPtr& layout);
+ ConsoleAppender(const LayoutPtr& layout, const LogString& target);
+ ~ConsoleAppender();
+
+
+ /**
+ * Sets the value of the <b>target</b> property. Recognized values
+ * are "System.out" and "System.err". Any other value will be
+ * ignored.
+ * */
+ void setTarget(const LogString& value);
+
+ /**
+ * Returns the current value of the <b>target</b> property. The
+ * default value of the option is "System.out".
+ *
+ * See also #setTarget.
+ * */
+ LogString getTarget() const;
+
+ void activateOptions(log4cxx::helpers::Pool& p);
+ void setOption(const LogString& option, const LogString& value);
+ static const LogString& getSystemOut();
+ static const LogString& getSystemErr();
+
+
+ private:
+ void targetWarn(const LogString& val);
+ static log4cxx::helpers::WriterPtr createWriter(const LogString& target);
+
+ };
+ LOG4CXX_PTR_DEF(ConsoleAppender);
+} //namespace log4cxx
+
+#endif //_LOG4CXX_CONSOLE_APPENDER_H
+
diff --git a/src/main/include/log4cxx/dailyrollingfileappender.h b/src/main/include/log4cxx/dailyrollingfileappender.h
new file mode 100644
index 0000000..628a997
--- /dev/null
+++ b/src/main/include/log4cxx/dailyrollingfileappender.h
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_DAILYROLLINGFILEAPPENDER_H
+#define _LOG4CXX_DAILYROLLINGFILEAPPENDER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/appender.h>
+#include <log4cxx/fileappender.h>
+#include <log4cxx/spi/optionhandler.h>
+#include <log4cxx/rolling/rollingfileappenderskeleton.h>
+
+namespace log4cxx {
+ namespace helpers {
+ class Pool;
+ }
+
+ namespace spi {
+ class ErrorHandler;
+ typedef log4cxx::helpers::ObjectPtrT<ErrorHandler> ErrorHandlerPtr;
+ }
+
+
+/**
+ DailyRollingFileAppender extends {@link log4cxx::FileAppender FileAppender} so that the
+ underlying file is rolled over at a user chosen frequency.
+
+ <p>The rolling schedule is specified by the <b>DatePattern</b>
+ option. This pattern should follow the
+ {@link log4cxx::helpers::SimpleDateFormat SimpleDateFormat}
+ conventions. In particular, you <em>must</em> escape literal text
+ within a pair of single quotes. A formatted version of the date
+ pattern is used as the suffix for the rolled file name.
+
+ <p>For example, if the <b>File</b> option is set to
+ <code>/foo/bar.log</code> and the <b>DatePattern</b> set to
+ <code>'.'yyyy-MM-dd</code>, on 2001-02-16 at midnight, the logging
+ file <code>/foo/bar.log</code> will be copied to
+ <code>/foo/bar.log.2001-02-16</code> and logging for 2001-02-17
+ will continue in <code>/foo/bar.log</code> until it rolls over
+ the next day.
+
+ <p>Is is possible to specify monthly, weekly, half-daily, daily,
+ hourly, or minutely rollover schedules.
+
+ <p><table border="1" cellpadding="2">
+ <tr>
+ <th>DatePattern</th>
+ <th>Rollover schedule</th>
+ <th>Example</th>
+
+ <tr>
+ <td><code>'.'yyyy-MM</code>
+ <td>Rollover at the beginning of each month</td>
+
+ <td>At midnight of May 31st, 2002 <code>/foo/bar.log</code> will be
+ copied to <code>/foo/bar.log.2002-05</code>. Logging for the month
+ of June will be output to <code>/foo/bar.log</code> until it is
+ also rolled over the next month.
+
+ <tr>
+ <td><code>'.'yyyy-ww</code>
+
+ <td>Rollover at the first day of each week. The first day of the
+ week depends on the locale.</td>
+
+ <td>Assuming the first day of the week is Sunday, on Saturday
+ midnight, June 9th 2002, the file <i>/foo/bar.log</i> will be
+ copied to <i>/foo/bar.log.2002-23</i>. Logging for the 24th week
+ of 2002 will be output to <code>/foo/bar.log</code> until it is
+ rolled over the next week.
+
+ <tr>
+ <td><code>'.'yyyy-MM-dd</code>
+
+ <td>Rollover at midnight each day.</td>
+
+ <td>At midnight, on March 8th, 2002, <code>/foo/bar.log</code> will
+ be copied to <code>/foo/bar.log.2002-03-08</code>. Logging for the
+ 9th day of March will be output to <code>/foo/bar.log</code> until
+ it is rolled over the next day.
+
+ <tr>
+ <td><code>'.'yyyy-MM-dd-a</code>
+
+ <td>Rollover at midnight and midday of each day.</td>
+
+ <td>At noon, on March 9th, 2002, <code>/foo/bar.log</code> will be
+ copied to <code>/foo/bar.log.2002-03-09-AM</code>. Logging for the
+ afternoon of the 9th will be output to <code>/foo/bar.log</code>
+ until it is rolled over at midnight.
+
+ <tr>
+ <td><code>'.'yyyy-MM-dd-HH</code>
+
+ <td>Rollover at the top of every hour.</td>
+
+ <td>At approximately 11:00.000 o'clock on March 9th, 2002,
+ <code>/foo/bar.log</code> will be copied to
+ <code>/foo/bar.log.2002-03-09-10</code>. Logging for the 11th hour
+ of the 9th of March will be output to <code>/foo/bar.log</code>
+ until it is rolled over at the beginning of the next hour.
+
+
+ <tr>
+ <td><code>'.'yyyy-MM-dd-HH-mm</code>
+
+ <td>Rollover at the beginning of every minute.</td>
+
+ <td>At approximately 11:23,000, on March 9th, 2001,
+ <code>/foo/bar.log</code> will be copied to
+ <code>/foo/bar.log.2001-03-09-10-22</code>. Logging for the minute
+ of 11:23 (9th of March) will be output to
+ <code>/foo/bar.log</code> until it is rolled over the next minute.
+
+ </table>
+
+ <p>Do not use the colon ":" character in anywhere in the
+ <b>DatePattern</b> option. The text before the colon is interpeted
+ as the protocol specificaion of a URL which is probably not what
+ you want.
+*/
+
+ class LOG4CXX_EXPORT DailyRollingFileAppender : public log4cxx::rolling::RollingFileAppenderSkeleton {
+ DECLARE_LOG4CXX_OBJECT(DailyRollingFileAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(DailyRollingFileAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(FileAppender)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ The date pattern used to initiate rollover.
+ */
+ LogString datePattern;
+
+
+public:
+ /**
+ The default constructor simply calls its {@link
+ FileAppender#FileAppender parents constructor}. */
+ DailyRollingFileAppender();
+
+ /**
+ Instantiate a DailyRollingFileAppender and open the file designated by
+ <code>filename</code>. The opened filename will become the ouput
+ destination for this appender.
+
+ */
+ DailyRollingFileAppender(
+ const LayoutPtr& layout,
+ const LogString& filename,
+ const LogString& datePattern);
+
+
+ /**
+ The <b>DatePattern</b> takes a string in the same format as
+ expected by {@link log4cxx::helpers::SimpleDateFormat SimpleDateFormat}. This options determines the
+ rollover schedule.
+ */
+ void setDatePattern(const LogString& pattern);
+
+ /** Returns the value of the <b>DatePattern</b> option. */
+ LogString getDatePattern();
+
+ void setOption(const LogString& option,
+ const LogString& value);
+
+ /**
+ * Prepares DailyRollingFileAppender for use.
+ */
+ void activateOptions(log4cxx::helpers::Pool&);
+
+};
+
+LOG4CXX_PTR_DEF(DailyRollingFileAppender);
+
+}
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+#endif
diff --git a/src/main/include/log4cxx/db/Makefile.am b/src/main/include/log4cxx/db/Makefile.am
new file mode 100755
index 0000000..7f9677e
--- /dev/null
+++ b/src/main/include/log4cxx/db/Makefile.am
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+dbincdir = $(includedir)/log4cxx/db
+dbinc_HEADERS= $(top_srcdir)/src/main/include/log4cxx/db/*.h
+
diff --git a/src/main/include/log4cxx/db/odbcappender.h b/src/main/include/log4cxx/db/odbcappender.h
new file mode 100644
index 0000000..0d278e2
--- /dev/null
+++ b/src/main/include/log4cxx/db/odbcappender.h
@@ -0,0 +1,292 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_DB_ODBC_APPENDER_H
+#define _LOG4CXX_DB_ODBC_APPENDER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/log4cxx.h>
+
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/appenderskeleton.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <list>
+
+namespace log4cxx
+{
+ namespace db
+ {
+ class LOG4CXX_EXPORT SQLException : public log4cxx::helpers::Exception {
+ public:
+ SQLException(short fHandleType,
+ void* hInput, const char* prolog,
+ log4cxx::helpers::Pool& p);
+ SQLException(const char* msg);
+ SQLException(const SQLException& src);
+ private:
+ const char* formatMessage(short fHandleType,
+ void* hInput, const char* prolog,
+ log4cxx::helpers::Pool& p);
+ };
+
+ /**
+ <p><b>WARNING: This version of ODBCAppender
+ is very likely to be completely replaced in the future. Moreoever,
+ it does not log exceptions.</b> </p>
+
+ The ODBCAppender provides for sending log events to a database.
+
+
+ <p>Each append call adds to an <code>ArrayList</code> buffer. When
+ the buffer is filled each log event is placed in a sql statement
+ (configurable) and executed.
+
+ <b>BufferSize</b>, <b>db URL</b>, <b>User</b>, & <b>Password</b> are
+ configurable options in the standard log4j ways.
+
+ <p>The <code>setSql(String sql)</code> sets the SQL statement to be
+ used for logging -- this statement is sent to a
+ <code>PatternLayout</code> (either created automaticly by the
+ appender or added by the user). Therefore by default all the
+ conversion patterns in <code>PatternLayout</code> can be used
+ inside of the statement. (see the test cases for examples)
+
+ <p>Overriding the {@link #getLogStatement} method allows more
+ explicit control of the statement used for logging.
+
+ <p>For use as a base class:
+
+ <ul>
+
+ <li>Override getConnection() to pass any connection
+ you want. Typically this is used to enable application wide
+ connection pooling.
+
+ <li>Override closeConnection -- if
+ you override getConnection make sure to implement
+ <code>closeConnection</code> to handle the connection you
+ generated. Typically this would return the connection to the
+ pool it came from.
+
+ <li>Override getLogStatement to
+ produce specialized or dynamic statements. The default uses the
+ sql option value.
+
+ </ul>
+ */
+
+ class LOG4CXX_EXPORT ODBCAppender : public AppenderSkeleton
+ {
+ protected:
+ /**
+ * URL of the DB for default connection handling
+ */
+ LogString databaseURL;
+
+ /**
+ * User to connect as for default connection handling
+ */
+ LogString databaseUser;
+
+ /**
+ * User to use for default connection handling
+ */
+ LogString databasePassword;
+
+ typedef void* SQLHDBC;
+ typedef void* SQLHENV;
+ typedef void* SQLHANDLE;
+ typedef short SQLSMALLINT;
+
+ /**
+ * Connection used by default. The connection is opened the first time it
+ * is needed and then held open until the appender is closed (usually at
+ * garbage collection). This behavior is best modified by creating a
+ * sub-class and overriding the <code>getConnection</code> and
+ * <code>closeConnection</code> methods.
+ */
+ SQLHDBC connection;
+ SQLHENV env;
+
+ /**
+ * Stores the string given to the pattern layout for conversion into a SQL
+ * statement, eg: insert into LogTable (Thread, File, Message) values
+ * ("%t", "%F", "%m")
+ *
+ * Be careful of quotes in your messages!
+ *
+ * Also see PatternLayout.
+ */
+ LogString sqlStatement;
+
+ /**
+ * size of LoggingEvent buffer before writing to the database.
+ * Default is 1.
+ */
+ size_t bufferSize;
+
+ /**
+ * ArrayList holding the buffer of Logging Events.
+ */
+ std::list<spi::LoggingEventPtr> buffer;
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(ODBCAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(ODBCAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+ END_LOG4CXX_CAST_MAP()
+
+ ODBCAppender();
+ virtual ~ODBCAppender();
+
+ /**
+ Set options
+ */
+ virtual void setOption(const LogString& option, const LogString& value);
+
+ /**
+ Activate the specified options.
+ */
+ virtual void activateOptions(log4cxx::helpers::Pool& p);
+
+ /**
+ * Adds the event to the buffer. When full the buffer is flushed.
+ */
+ void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool&);
+
+ /**
+ * By default getLogStatement sends the event to the required Layout object.
+ * The layout will format the given pattern into a workable SQL string.
+ *
+ * Overriding this provides direct access to the LoggingEvent
+ * when constructing the logging statement.
+ *
+ */
+ protected:
+ LogString getLogStatement(const spi::LoggingEventPtr& event,
+ helpers::Pool& p) const;
+
+ /**
+ *
+ * Override this to provide an alertnate method of getting
+ * connections (such as caching). One method to fix this is to open
+ * connections at the start of flushBuffer() and close them at the
+ * end. I use a connection pool outside of ODBCAppender which is
+ * accessed in an override of this method.
+ * */
+ virtual void execute(const LogString& sql,
+ log4cxx::helpers::Pool& p) /*throw(SQLException)*/;
+
+ /**
+ * Override this to return the connection to a pool, or to clean up the
+ * resource.
+ *
+ * The default behavior holds a single connection open until the appender
+ * is closed (typically when garbage collected).
+ */
+ virtual void closeConnection(SQLHDBC con);
+
+ /**
+ * Override this to link with your connection pooling system.
+ *
+ * By default this creates a single connection which is held open
+ * until the object is garbage collected.
+ */
+ virtual SQLHDBC getConnection(log4cxx::helpers::Pool& p) /*throw(SQLException)*/;
+
+ /**
+ * Closes the appender, flushing the buffer first then closing the default
+ * connection if it is open.
+ */
+ public:
+ virtual void close();
+
+ /**
+ * loops through the buffer of LoggingEvents, gets a
+ * sql string from getLogStatement() and sends it to execute().
+ * Errors are sent to the errorHandler.
+ *
+ * If a statement fails the LoggingEvent stays in the buffer!
+ */
+ virtual void flushBuffer(log4cxx::helpers::Pool& p);
+
+ /**
+ * ODBCAppender requires a layout.
+ * */
+ virtual bool requiresLayout() const
+ { return true; }
+
+ /**
+ * Set pre-formated statement eg: insert into LogTable (msg) values ("%m")
+ */
+ void setSql(const LogString& s);
+
+ /**
+ * Returns pre-formated statement eg: insert into LogTable (msg) values ("%m")
+ */
+ inline const LogString& getSql() const
+ { return sqlStatement; }
+
+
+ inline void setUser(const LogString& user)
+ { databaseUser = user; }
+
+
+ inline void setURL(const LogString& url)
+ { databaseURL = url; }
+
+
+ inline void setPassword(const LogString& password)
+ { databasePassword = password; }
+
+
+ inline void setBufferSize(size_t newBufferSize)
+ { bufferSize = newBufferSize; }
+
+ inline const LogString& getUser() const
+ { return databaseUser; }
+
+
+ inline const LogString& getURL() const
+ { return databaseURL; }
+
+
+ inline const LogString& getPassword() const
+ { return databasePassword; }
+
+ inline size_t getBufferSize() const
+ { return bufferSize; }
+ private:
+ ODBCAppender(const ODBCAppender&);
+ ODBCAppender& operator=(const ODBCAppender&);
+ }; // class ODBCAppender
+ LOG4CXX_PTR_DEF(ODBCAppender);
+
+ } // namespace db
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif // _LOG4CXX_DB_ODBC_APPENDER_H
diff --git a/src/main/include/log4cxx/defaultconfigurator.h b/src/main/include/log4cxx/defaultconfigurator.h
new file mode 100755
index 0000000..c88d337
--- /dev/null
+++ b/src/main/include/log4cxx/defaultconfigurator.h
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_DEFAULT_CONFIGURATOR_H
+#define _LOG4CXX_DEFAULT_CONFIGURATOR_H
+
+#include <log4cxx/spi/configurator.h>
+
+namespace log4cxx
+{
+ namespace spi {
+ class LoggerRepository;
+ typedef helpers::ObjectPtrT<LoggerRepository> LoggerRepositoryPtr;
+ }
+
+ /**
+ * Configures the repository from environmental settings and files.
+ *
+ */
+ class LOG4CXX_EXPORT DefaultConfigurator
+ {
+ private:
+ DefaultConfigurator() {}
+
+ public:
+ /**
+ Add a ConsoleAppender that uses PatternLayout
+ using the PatternLayout#TTCC_CONVERSION_PATTERN and
+ prints to <code>stdout</code> to the root logger.*/
+ static void configure(log4cxx::spi::LoggerRepository*);
+
+ private:
+ static const LogString getConfigurationFileName();
+ static const LogString getConfiguratorClass();
+
+
+
+ }; // class DefaultConfigurator
+} // namespace log4cxx
+
+#endif //_LOG4CXX_DEFAULT_CONFIGURATOR_H
diff --git a/src/main/include/log4cxx/defaultloggerfactory.h b/src/main/include/log4cxx/defaultloggerfactory.h
new file mode 100644
index 0000000..3f3c674
--- /dev/null
+++ b/src/main/include/log4cxx/defaultloggerfactory.h
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_DEFAULT_LOGGER_FACTORY_H
+#define _LOG4CXX_DEFAULT_LOGGER_FACTORY_H
+
+#include <log4cxx/spi/loggerfactory.h>
+#include <log4cxx/helpers/objectimpl.h>
+
+namespace log4cxx
+{
+ class Logger;
+ typedef helpers::ObjectPtrT<Logger> LoggerPtr;
+
+ class LOG4CXX_EXPORT DefaultLoggerFactory :
+ public virtual spi::LoggerFactory,
+ public virtual helpers::ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(DefaultLoggerFactory)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(spi::LoggerFactory)
+ END_LOG4CXX_CAST_MAP()
+
+ virtual LoggerPtr makeNewLoggerInstance(
+ log4cxx::helpers::Pool& pool,
+ const LogString& name) const;
+ };
+} // namespace log4cxx
+
+#endif //_LOG4CXX_DEFAULT_LOGGER_FACTORY_H
diff --git a/src/main/include/log4cxx/file.h b/src/main/include/log4cxx/file.h
new file mode 100644
index 0000000..a762949
--- /dev/null
+++ b/src/main/include/log4cxx/file.h
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_FILE_H
+#define _LOG4CXX_FILE_H
+
+#include <log4cxx/logger.h>
+#include <log4cxx/logstring.h>
+
+extern "C" {
+struct apr_file_t;
+struct apr_finfo_t;
+}
+
+namespace log4cxx
+{
+ namespace helpers {
+ class Transcoder;
+ class Pool;
+ }
+
+ /**
+ * An abstract representation of file and directory path names.
+ */
+ class LOG4CXX_EXPORT File
+ {
+ public:
+ /**
+ * Construct a new instance.
+ */
+ File();
+ /**
+ * Construct a new instance. Use setPath to specify path using a LogString.
+ * @param path file path in local encoding.
+ */
+ File(const char* path);
+ /**
+ * Construct a new instance. Use setPath to specify path using a LogString.
+ * @param path file path in current encoding.
+ */
+ File(const std::string& path);
+#if LOG4CXX_WCHAR_T_API
+ /**
+ * Construct a new instance. Use setPath to specify path using a LogString.
+ * @param path file path.
+ */
+ File(const wchar_t* path);
+ /**
+ * Construct a new instance. Use setPath to specify path using a LogString.
+ * @param path file path.
+ */
+ File(const std::wstring& path);
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ * Construct a new instance. Use setPath to specify path using a LogString.
+ * @param path file path.
+ */
+ File(const UniChar* path);
+ /**
+ * Construct a new instance. Use setPath to specify path using a LogString.
+ * @param path file path.
+ */
+ File(const std::basic_string<UniChar>& path);
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ * Construct a new instance. Use setPath to specify path using a LogString.
+ * @param path file path.
+ */
+ File(const CFStringRef& path);
+#endif
+ /**
+ * Copy constructor.
+ */
+ File(const File& src);
+ /**
+ * Assignment operator.
+ */
+ File& operator=(const File& src);
+ /**
+ * Destructor.
+ */
+ ~File();
+
+ /**
+ * Determines if file exists.
+ * @param p pool.
+ * @return true if file exists.
+ */
+ bool exists(log4cxx::helpers::Pool& p) const;
+ /**
+ * Determines length of file. May not be accurate if file is current open.
+ * @param p pool.
+ * @return length of file.
+ */
+ size_t length(log4cxx::helpers::Pool& p) const;
+ /**
+ * Determines last modification date.
+ * @param p pool.
+ * @return length of file.
+ */
+ log4cxx_time_t lastModified(log4cxx::helpers::Pool& p) const;
+ /**
+ * Get final portion of file path.
+ * @return file name.
+ */
+ LogString getName() const;
+ /**
+ * Get file path.
+ * @return file path.
+ */
+ LogString getPath() const;
+ /**
+ * Set file path
+ */
+ File& setPath(const LogString&);
+
+ /**
+ * Open file. See apr_file_open for details.
+ * @param file APR file handle.
+ * @param flags flags.
+ * @param perm permissions.
+ * @param p pool.
+ * @return APR_SUCCESS if successful.
+ */
+ log4cxx_status_t open(apr_file_t** file, int flags,
+ int perm, log4cxx::helpers::Pool& p) const;
+
+ /**
+ * List files if current file is a directory.
+ * @param p pool.
+ * @return list of files in this directory, operation of non-directory returns empty list.
+ */
+ std::vector<LogString> list(log4cxx::helpers::Pool& p) const;
+
+ /**
+ * Delete file.
+ * @param p pool.
+ * @return true if file successfully deleted.
+ */
+ bool deleteFile(log4cxx::helpers::Pool& p) const;
+ /**
+ * Rename file.
+ * @param dest new path for file.
+ * @param p pool.
+ * @return true if file successfully renamed.
+ */
+ bool renameTo(const File& dest, log4cxx::helpers::Pool& p) const;
+
+ /**
+ * Get path of parent directory.
+ * @param p pool.
+ * @return path of parent directory.
+ */
+ LogString getParent(log4cxx::helpers::Pool& p) const;
+ /**
+ * Make directories recursively.
+ * @param p pool.
+ * @return true if all requested directories existed or have been created.
+ */
+ bool mkdirs(log4cxx::helpers::Pool& p) const;
+
+ private:
+ LogString path;
+ static char* convertBackSlashes(char*);
+ char* getPath(log4cxx::helpers::Pool& p) const;
+ };
+} // namespace log4cxx
+
+
+#define LOG4CXX_FILE(name) log4cxx::File(name)
+
+#endif // _LOG4CXX_FILE_H
diff --git a/src/main/include/log4cxx/fileappender.h b/src/main/include/log4cxx/fileappender.h
new file mode 100644
index 0000000..d0491db
--- /dev/null
+++ b/src/main/include/log4cxx/fileappender.h
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_FILE_APPENDER_H
+#define _LOG4CXX_FILE_APPENDER_H
+
+#include <log4cxx/logger.h>
+#include <log4cxx/logstring.h>
+#include <log4cxx/writerappender.h>
+#include <log4cxx/file.h>
+#include <log4cxx/helpers/pool.h>
+
+namespace log4cxx
+{
+ namespace helpers {
+ class Pool;
+ }
+
+ /**
+ * FileAppender appends log events to a file.
+ *
+ * <p>Support for <code>java.io.Writer</code> and console appending
+ * has been deprecated and then removed. See the replacement
+ * solutions: WriterAppender and ConsoleAppender.
+ */
+ class LOG4CXX_EXPORT FileAppender : public WriterAppender
+ {
+ protected:
+ /** Append to or truncate the file? The default value for this
+ variable is <code>true</code>, meaning that by default a
+ <code>FileAppender</code> will append to an existing file and
+ not truncate it.
+ <p>This option is meaningful only if the FileAppender opens the
+ file.
+ */
+ bool fileAppend;
+
+ /**
+ The name of the log file. */
+ LogString fileName;
+
+ /**
+ Do we do bufferedIO? */
+ bool bufferedIO;
+
+ /**
+ How big should the IO buffer be? Default is 8K. */
+ int bufferSize;
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(FileAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(FileAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(WriterAppender)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ The default constructor does not do anything.
+ */
+ FileAppender();
+
+ /**
+ Instantiate a <code>FileAppender</code> and open the file
+ designated by <code>filename</code>. The opened filename will
+ become the output destination for this appender.
+
+ <p>If the <code>append</code> parameter is true, the file will be
+ appended to. Otherwise, the file designated by
+ <code>filename</code> will be truncated before being opened.
+
+ <p>If the <code>bufferedIO</code> parameter is <code>true</code>,
+ then buffered IO will be used to write to the output file.
+
+ */
+ FileAppender(const LayoutPtr& layout, const LogString& filename, bool append,
+ bool bufferedIO, int bufferSize);
+
+ /**
+ Instantiate a FileAppender and open the file designated by
+ <code>filename</code>. The opened filename will become the output
+ destination for this appender.
+
+ <p>If the <code>append</code> parameter is true, the file will be
+ appended to. Otherwise, the file designated by
+ <code>filename</code> will be truncated before being opened.
+ */
+ FileAppender(const LayoutPtr& layout, const LogString& filename, bool append);
+
+ /**
+ Instantiate a FileAppender and open the file designated by
+ <code>filename</code>. The opened filename will become the output
+ destination for this appender.
+
+ <p>The file will be appended to. */
+ FileAppender(const LayoutPtr& layout, const LogString& filename);
+
+ ~FileAppender();
+
+ /**
+ The <b>File</b> property takes a string value which should be the
+ name of the file to append to.
+
+ <p><b>Note that the special values
+ "System.out" or "System.err" are no longer honored.</b>
+
+ <p>Note: Actual opening of the file is made when
+ #activateOptions is called, not when the options are set. */
+ virtual void setFile(const LogString& file);
+
+ /**
+ Sets and <i>opens</i> the file where the log output will
+ go. The specified file must be writable.
+
+ <p>If there was already an opened file, then the previous file
+ is closed first.
+
+ <p><b>Do not use this method directly. To configure a FileAppender
+ or one of its subclasses, set its properties one by one and then
+ call activateOptions.</b>
+
+ @param file The path to the log file.
+ @param append If true will append to fileName. Otherwise will
+ truncate fileName.
+ @param bufferedIO Do we do bufferedIO?
+ @param bufferSize How big should the IO buffer be?
+ @param p memory pool for operation.
+ */
+ virtual void setFile(const LogString& file, bool append,
+ bool bufferedIO, size_t bufferSize,
+ log4cxx::helpers::Pool& p);
+
+ /**
+ Returns the value of the <b>Append</b> option.
+ */
+ inline bool getAppend() const { return fileAppend; }
+
+ /** Returns the value of the <b>File</b> option. */
+ inline LogString getFile() const { return fileName; }
+
+ /**
+ <p>Sets and <i>opens</i> the file where the log output will
+ go. The specified file must be writable.
+
+ <p>If there was already an opened file, then the previous file
+ is closed first.*/
+ void activateOptions(log4cxx::helpers::Pool& p);
+ void setOption(const LogString& option,
+ const LogString& value);
+
+ /**
+ Get the value of the <b>BufferedIO</b> option.
+
+ <p>BufferedIO will significatnly increase performance on heavily
+ loaded systems.
+
+ */
+ inline bool getBufferedIO() const { return bufferedIO; }
+
+ /**
+ Get the size of the IO buffer.
+ */
+ inline int getBufferSize() const { return bufferSize; }
+
+ /**
+ The <b>Append</b> option takes a boolean value. It is set to
+ <code>true</code> by default. If true, then <code>File</code>
+ will be opened in append mode by #setFile (see
+ above). Otherwise, setFile will open
+ <code>File</code> in truncate mode.
+
+ <p>Note: Actual opening of the file is made when
+ #activateOptions is called, not when the options are set.
+ */
+ void setAppend(bool fileAppend1);
+
+ /**
+ The <b>BufferedIO</b> option takes a boolean value. It is set to
+ <code>false</code> by default. If true, then <code>File</code>
+ will be opened in buffered mode.
+
+ BufferedIO will significantly increase performance on heavily
+ loaded systems.
+
+ */
+ void setBufferedIO(bool bufferedIO);
+
+ /**
+ Set the size of the IO buffer.
+ */
+ void setBufferSize(int bufferSize1) { this->bufferSize = bufferSize1; }
+
+ /**
+ * Replaces double backslashes with single backslashes
+ * for compatibility with paths from earlier XML configurations files.
+ * @param name file name
+ * @return corrected file name
+ */
+ static LogString stripDuplicateBackslashes(const LogString& name);
+
+ private:
+ FileAppender(const FileAppender&);
+ FileAppender& operator=(const FileAppender&);
+
+ }; // class FileAppender
+ LOG4CXX_PTR_DEF(FileAppender);
+
+} // namespace log4cxx
+
+#endif
diff --git a/src/main/include/log4cxx/filter/Makefile.am b/src/main/include/log4cxx/filter/Makefile.am
new file mode 100644
index 0000000..7dd7d84
--- /dev/null
+++ b/src/main/include/log4cxx/filter/Makefile.am
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+filterincdir = $(includedir)/log4cxx/filter
+filterinc_HEADERS= $(top_srcdir)/src/main/include/log4cxx/filter/*.h
+
diff --git a/src/main/include/log4cxx/filter/andfilter.h b/src/main/include/log4cxx/filter/andfilter.h
new file mode 100644
index 0000000..3bc58a0
--- /dev/null
+++ b/src/main/include/log4cxx/filter/andfilter.h
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_FILTER_ANDFILTER_H
+#define _LOG4CXX_FILTER_ANDFILTER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/spi/filter.h>
+
+namespace log4cxx
+{
+ namespace filter
+ {
+
+/**
+ * A filter that 'and's the results of any number of contained filters together.
+ *
+ * For the filter to process events, all contained filters must return Filter::ACCEPT.
+ *
+ * If the contained filters do not return Filter::ACCEPT, Filter::NEUTRAL is returned.
+ *
+ * If acceptOnMatch is set to true, Filter::ACCEPT is returned.
+ * If acceptOnMatch is set to false, Filter::DENY is returned.
+ *
+ * Here is an example config that will accept only events that contain BOTH
+ * a DEBUG level AND 'test' in the message:
+ *
+ *&lt;appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"&gt;
+ * &lt;filter class="org.apache.log4j.filter.AndFilter"&gt;
+ * &lt;filter class="org.apache.log4j.filter.LevelMatchFilter"&gt;
+ * &lt;param name="levelToMatch" value="DEBUG" /&gt;
+ * &lt;param name="acceptOnMatch" value="true" /&gt;
+ * &lt;/filter>
+ * &lt;filter class="org.apache.log4j.filter.StringMatchFilter"&gt;
+ * &lt;param name="stringToMatch" value="test" /&gt;
+ * &lt;param name="acceptOnMatch" value="true" /&gt;
+ * &lt;/filter>
+ * &lt;param name="acceptOnMatch" value="false"/&gt;
+ * &lt;/filter&gt;
+ * &lt;filter class="org.apache.log4j.filter.DenyAllFilter"/&gt;
+ *&lt;layout class="org.apache.log4j.SimpleLayout"/&gt;
+ *&lt;/appender&gt;
+ *
+ * To accept all events EXCEPT those events that contain a
+ * DEBUG level and 'test' in the message:
+ * change the AndFilter's acceptOnMatch param to false and remove the DenyAllFilter
+ *
+ * NOTE: If you are defining a filter that is only relying on logging event content
+ * (no external or filter-managed state), you could opt instead
+ * to use an ExpressionFilter with one of the following expressions:
+ *
+ * LEVEL == DEBUG && MSG ~= 'test'
+ * or
+ * ! ( LEVEL == DEBUG && MSG ~= 'test' )
+ *
+ *
+ */
+ class LOG4CXX_EXPORT AndFilter:public log4cxx::spi::Filter
+ {
+ private:
+ log4cxx::spi::FilterPtr headFilter;
+ log4cxx::spi::FilterPtr tailFilter;
+ bool acceptOnMatch;
+ AndFilter(const AndFilter &);
+ AndFilter & operator=(const AndFilter &);
+
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(AndFilter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(log4cxx::spi::Filter)
+ END_LOG4CXX_CAST_MAP()
+
+ AndFilter();
+
+ void addFilter(const log4cxx::spi::FilterPtr & filter);
+
+ void setAcceptOnMatch(bool acceptOnMatch);
+
+ FilterDecision decide(const spi::LoggingEventPtr & event) const;
+ };
+
+ }
+}
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif
diff --git a/src/main/include/log4cxx/filter/denyallfilter.h b/src/main/include/log4cxx/filter/denyallfilter.h
new file mode 100644
index 0000000..c370aac
--- /dev/null
+++ b/src/main/include/log4cxx/filter/denyallfilter.h
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_FILTER_DENY_ALL_FILTER_H
+#define _LOG4CXX_FILTER_DENY_ALL_FILTER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/spi/filter.h>
+
+namespace log4cxx
+{
+ namespace filter
+ {
+ /**
+ This filter drops all logging events.
+ <p>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 LOG4CXX_EXPORT DenyAllFilter : public spi::Filter
+ {
+ public:
+ DenyAllFilter() : spi::Filter() {
+ }
+
+ typedef spi::Filter BASE_CLASS;
+ DECLARE_LOG4CXX_OBJECT(DenyAllFilter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(DenyAllFilter)
+ LOG4CXX_CAST_ENTRY_CHAIN(BASE_CLASS)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ Always returns the integer constant {@link spi::Filter#DENY DENY}
+ regardless of the {@link spi::LoggingEvent LoggingEvent} parameter.
+ @param event The LoggingEvent to filter.
+ @return Always returns {@link spi::Filter#DENY DENY}.
+ */
+ FilterDecision decide(const spi::LoggingEventPtr& /* event */) const
+ { return spi::Filter::DENY; }
+ }; // class DenyAllFilter
+
+ LOG4CXX_PTR_DEF(DenyAllFilter);
+ } // namespace filter
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+#endif // _LOG4CXX_FILTER_DENY_ALL_FILTER_H
diff --git a/src/main/include/log4cxx/filter/expressionfilter.h b/src/main/include/log4cxx/filter/expressionfilter.h
new file mode 100644
index 0000000..dfb6cbf
--- /dev/null
+++ b/src/main/include/log4cxx/filter/expressionfilter.h
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_FILTER_EXPRESSIONFILTER_H
+#define _LOG4CXX_FILTER_EXPRESSIONFILTER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/spi/filter.h>
+
+namespace log4cxx
+{
+ namespace rule
+ {
+ class Rule;
+ typedef helpers::ObjectPtrT < Rule > RulePtr;
+ }
+
+
+ namespace filter
+ {
+
+
+/**
+ *A filter supporting complex expressions - supports both infix and postfix
+ * expressions (infix expressions must first be converted to postfix prior
+ * to processing).
+ *
+ * <p>See <code>org.apache.log4j.chainsaw.LoggingEventFieldResolver.java</code>
+ * for the correct names for logging event fields used when building expressions.
+ *
+ * <p>See <code>org.apache.log4j.chainsaw.rule</code> package for a list of available
+ * rules which can be applied using the expression syntax.
+ *
+ * <p>See <code>org.apache.log4j.chainsaw.RuleFactory</code> for the symbols
+ * used to activate the corresponding rules.
+ *
+ *NOTE: Grouping using parentheses is supported - all tokens must be separated by spaces, and
+ *operands which contain spaces are not yet supported.
+ *
+ *Example:
+ *
+ *In order to build a filter that displays all messages with infomsg-45 or infomsg-44 in the message,
+ *as well as all messages with a level of WARN or higher, build an expression using
+ *the LikeRule (supports ORO-based regular expressions) and the InequalityRule.
+ * <b> ( MSG LIKE infomsg-4[4,5] ) && ( LEVEL >= WARN ) </b>
+ *
+ *Three options are required:
+ * <b>Expression</b> - the expression to match
+ * <b>ConvertInFixToPostFix</b> - convert from infix to posfix (default true)
+ * <b>AcceptOnMatch</b> - true or false (default true)
+ *
+ * Meaning of <b>AcceptToMatch</b>:
+ * If there is a match between the value of the
+ * Expression option and the {@link log4cxx::spi::LoggingEvent} and AcceptOnMatch is true,
+ * the {@link #decide} method returns {@link log4cxx::spi::Filter#ACCEPT}.
+ *
+ * If there is a match between the value of the
+ * Expression option and the {@link log4cxx::spi::LoggingEvent} and AcceptOnMatch is false,
+ * {@link log4cxx::spi::Filter#DENY} is returned.
+ *
+ * If there is no match, {@link log4cxx::spi::Filter#NEUTRAL} is returned.
+ *
+ *
+ */
+ class LOG4CXX_EXPORT ExpressionFilter:public log4cxx::spi::Filter
+ {
+ private:
+ bool acceptOnMatch;
+ bool convertInFixToPostFix;
+ LogString expression;
+ log4cxx::rule::RulePtr expressionRule;
+ ExpressionFilter(const ExpressionFilter &);
+ ExpressionFilter & operator=(const ExpressionFilter &);
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(ExpressionFilter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(log4cxx::spi::Filter)
+ END_LOG4CXX_CAST_MAP()
+
+
+ ExpressionFilter();
+
+ void activateOptions(log4cxx::helpers::Pool & p);
+
+ void setExpression(const LogString & expression);
+
+ LogString getExpression() const;
+
+ void setConvertInFixToPostFix(bool convertInFixToPostFix);
+
+ bool getConvertInFixToPostFix() const;
+
+ void setAcceptOnMatch(bool acceptOnMatch);
+
+ bool getAcceptOnMatch() const;
+
+ /**
+ Returns {@link log4cxx::spi::Filter#NEUTRAL} is there is no string match.
+ */
+ FilterDecision decide(const spi::LoggingEventPtr & event) const;
+ };
+ }
+}
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+#endif
diff --git a/src/main/include/log4cxx/filter/levelmatchfilter.h b/src/main/include/log4cxx/filter/levelmatchfilter.h
new file mode 100644
index 0000000..f357f67
--- /dev/null
+++ b/src/main/include/log4cxx/filter/levelmatchfilter.h
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_FILTER_LEVEL_MATCH_FILTER_H
+#define _LOG4CXX_FILTER_LEVEL_MATCH_FILTER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/spi/filter.h>
+#include <log4cxx/level.h>
+
+namespace log4cxx
+{
+ class Level;
+
+ namespace filter
+ {
+ /**
+ This is a very simple filter based on level matching.
+
+ <p>The filter admits two options <b>LevelToMatch</b> and
+ <b>AcceptOnMatch</b>. If there is an exact match between the value
+ of the <b>LevelToMatch</b> option and the level of the {@link
+ spi::LoggingEvent LoggingEvent}, then the #decide method returns {@link
+ spi::Filter#ACCEPT ACCEPT} in case the <b>AcceptOnMatch</b>
+ option value is set to <code>true</code>, if it is <code>false</code>
+ then {@link spi::Filter#DENY DENY} is returned. If there is no match,
+ {@link spi::Filter#NEUTRAL NEUTRAL} is returned.
+ */
+
+ class LOG4CXX_EXPORT LevelMatchFilter : public spi::Filter
+ {
+ private:
+ bool acceptOnMatch;
+ LevelPtr levelToMatch;
+
+ public:
+ typedef spi::Filter BASE_CLASS;
+ DECLARE_LOG4CXX_OBJECT(LevelMatchFilter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(LevelMatchFilter)
+ LOG4CXX_CAST_ENTRY_CHAIN(BASE_CLASS)
+ END_LOG4CXX_CAST_MAP()
+
+ LevelMatchFilter();
+
+ /**
+ Set options
+ */
+ virtual void setOption(const LogString& option,
+ const LogString& value);
+
+ void setLevelToMatch(const LogString& levelToMatch);
+
+ LogString getLevelToMatch() const;
+
+ inline void setAcceptOnMatch(bool acceptOnMatch1)
+ { this->acceptOnMatch = acceptOnMatch1; }
+
+ inline bool getAcceptOnMatch() const
+ { return acceptOnMatch; }
+
+ /**
+ Return the decision of this filter.
+
+ Returns {@link spi::Filter#NEUTRAL NEUTRAL} if the
+ <b>LevelToMatch</b> option is not set or if there is not match.
+ Otherwise, if there is a match, then the returned decision is
+ {@link spi::Filter#ACCEPT ACCEPT} if the <b>AcceptOnMatch</b>
+ property is set to <code>true</code>. The returned decision is
+ {@link spi::Filter#DENY DENY} if the
+ <b>AcceptOnMatch</b> property is set to false.
+ */
+ FilterDecision decide(const spi::LoggingEventPtr& event) const;
+ }; // class LevelMatchFilter
+ LOG4CXX_PTR_DEF(LevelMatchFilter);
+ } // namespace filter
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif // _LOG4CXX_FILTER_STRING_MATCH_FILTER_H
diff --git a/src/main/include/log4cxx/filter/levelrangefilter.h b/src/main/include/log4cxx/filter/levelrangefilter.h
new file mode 100644
index 0000000..326d7c9
--- /dev/null
+++ b/src/main/include/log4cxx/filter/levelrangefilter.h
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_FILTER_LEVEL_RANGE_FILTER_H
+#define _LOG4CXX_FILTER_LEVEL_RANGE_FILTER_H
+
+#include <log4cxx/spi/filter.h>
+#include <log4cxx/level.h>
+
+namespace log4cxx
+{
+ namespace filter
+ {
+ /**
+ This is a very simple filter based on level matching, which can be
+ used to reject messages with priorities outside a certain range.
+
+ <p>The filter admits three options <b>LevelMin</b>, <b>LevelMax</b>
+ and <b>AcceptOnMatch</b>.
+
+ <p>If the level of the {@link spi::LoggingEvent LoggingEvent} is not
+ between Min and Max (inclusive), then {@link spi::Filter#DENY DENY}
+ is returned.
+
+ <p> If the Logging event level is within the specified range, then if
+ <b>AcceptOnMatch</b> is true, {@link spi::Filter#ACCEPT ACCEPT} is
+ returned, and if <b>AcceptOnMatch</b> is false,
+ {@link spi::Filter#NEUTRAL NEUTRAL} is returned.
+
+ <p>If <code>LevelMin</code>w is not defined, then there is no
+ minimum acceptable level (ie a level is never rejected for
+ being too "low"/unimportant). If <code>LevelMax</code> is not
+ defined, then there is no maximum acceptable level (ie a
+ level is never rejected for beeing too "high"/important).
+
+ <p>Refer to the {@link
+ AppenderSkeleton#setThreshold setThreshold} method
+ available to <code>all</code> appenders extending
+ AppenderSkeleton for a more convenient way to
+ filter out events by level.
+ */
+
+ class LOG4CXX_EXPORT LevelRangeFilter : public spi::Filter
+ {
+ private:
+ /**
+ Do we return ACCEPT when a match occurs. Default is
+ <code>false</code>, so that later filters get run by default
+ */
+ bool acceptOnMatch;
+ LevelPtr levelMin;
+ LevelPtr levelMax;
+
+ public:
+ typedef spi::Filter BASE_CLASS;
+ DECLARE_LOG4CXX_OBJECT(LevelRangeFilter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(LevelRangeFilter)
+ LOG4CXX_CAST_ENTRY_CHAIN(BASE_CLASS)
+ END_LOG4CXX_CAST_MAP()
+
+ LevelRangeFilter();
+
+ /**
+ Set options
+ */
+ virtual void setOption(const LogString& option,
+ const LogString& value);
+
+ /**
+ Set the <code>LevelMin</code> option.
+ */
+ void setLevelMin(const LevelPtr& levelMin1)
+ { this->levelMin = levelMin1; }
+
+ /**
+ Get the value of the <code>LevelMin</code> option.
+ */
+ const LevelPtr& getLevelMin() const
+ { return levelMin; }
+
+ /**
+ Set the <code>LevelMax</code> option.
+ */
+ void setLevelMax(const LevelPtr& levelMax1)
+ { this->levelMax = levelMax1; }
+
+ /**
+ Get the value of the <code>LevelMax</code> option.
+ */
+ const LevelPtr& getLevelMax() const
+ { return levelMax; }
+
+ /**
+ Set the <code>AcceptOnMatch</code> option.
+ */
+ inline void setAcceptOnMatch(bool acceptOnMatch1)
+ { this->acceptOnMatch = acceptOnMatch1; }
+
+ /**
+ Get the value of the <code>AcceptOnMatch</code> option.
+ */
+ inline bool getAcceptOnMatch() const
+ { return acceptOnMatch; }
+
+ /**
+ Return the decision of this filter.
+
+ Returns {@link spi::Filter#NEUTRAL NEUTRAL} if the
+ <b>LevelToMatch</b> option is not set or if there is not match.
+ Otherwise, if there is a match, then the returned decision is
+ {@link spi::Filter#ACCEPT ACCEPT} if the
+ <b>AcceptOnMatch</b> property is set to <code>true</code>. The
+ returned decision is {@link spi::Filter#DENY DENY} if the
+ <b>AcceptOnMatch</b> property is set to false.
+ */
+ FilterDecision decide(const spi::LoggingEventPtr& event) const;
+ }; // class LevelRangeFilter
+ LOG4CXX_PTR_DEF(LevelRangeFilter);
+ } // namespace filter
+} // namespace log4cxx
+
+#endif // _LOG4CXX_FILTER_LEVEL_RANGE_FILTER_H
diff --git a/src/main/include/log4cxx/filter/locationinfofilter.h b/src/main/include/log4cxx/filter/locationinfofilter.h
new file mode 100644
index 0000000..81d8b18
--- /dev/null
+++ b/src/main/include/log4cxx/filter/locationinfofilter.h
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_FILTER_LOCATIONINFOFILTER_H
+#define _LOG4CXX_FILTER_LOCATIONINFOFILTER_H
+
+#include <log4cxx/spi/filter.h>
+
+namespace log4cxx
+{
+ namespace rule
+ {
+ class ExpressionRule;
+ class Rule;
+ typedef helpers::ObjectPtrT < Rule > RulePtr;
+ typedef helpers::ObjectPtrT < ExpressionRule > ExpressionRulePtr;
+ }
+
+ namespace filter
+ {
+/**
+ * Location information is usually specified at the appender level - all events associated
+ * with an appender either create and parse stack traces or they do not. This is
+ * an expensive operation and in some cases not needed for all events associated with
+ * an appender.
+ *
+ * This filter creates event-level location information only if the provided expression evaluates to true.
+ *
+ * For information on expression syntax, see org.apache.log4j.rule.ExpressionRule
+ *
+ *
+ */
+ class LOG4CXX_EXPORT LocationInfoFilter:public log4cxx::spi::Filter
+ {
+ bool convertInFixToPostFix;
+ LogString expression;
+ log4cxx::rule::RulePtr expressionRule;
+ //HACK: Category is the last of the internal layers - pass this in as the class name
+ //in order for parsing to work correctly
+ LogString className;
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(LocationInfoFilter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(log4cxx::spi::Filter)
+ END_LOG4CXX_CAST_MAP()
+
+ LocationInfoFilter();
+
+ void activateOptions(log4cxx::helpers::Pool &);
+
+ void setExpression(const LogString & expression);
+
+ LogString getExpression() const;
+
+ void setConvertInFixToPostFix(bool convertInFixToPostFix);
+
+ bool getConvertInFixToPostFix() const;
+
+ /**
+ * If this event does not already contain location information,
+ * evaluate the event against the expression.
+ *
+ * If the expression evaluates to true, generate a LocationInfo instance
+ * by creating an exception and set this LocationInfo on the event.
+ *
+ * Returns {@link log4cxx::spi::Filter#NEUTRAL}
+ */
+ FilterDecision decide(const spi::LoggingEventPtr & event) const;
+
+ };
+ }
+}
+#endif
diff --git a/src/main/include/log4cxx/filter/mapfilter.h b/src/main/include/log4cxx/filter/mapfilter.h
new file mode 100644
index 0000000..e956bef
--- /dev/null
+++ b/src/main/include/log4cxx/filter/mapfilter.h
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_FILTER_MAPFILTER_H
+#define _LOG4CXX_FILTER_MAPFILTER_H
+
+#include <log4cxx/spi/filter.h>
+
+namespace log4cxx
+{
+ namespace filter
+ {
+
+
+ class LOG4CXX_EXPORT MapFilter:public log4cxx::spi::Filter
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(MapFilter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(log4cxx::spi::Filter)
+ END_LOG4CXX_CAST_MAP()
+
+ MapFilter();
+
+
+ FilterDecision decide(const spi::LoggingEventPtr & event) const;
+
+ };
+ }
+}
+#endif
diff --git a/src/main/include/log4cxx/filter/propertyfilter.h b/src/main/include/log4cxx/filter/propertyfilter.h
new file mode 100644
index 0000000..4d830e1
--- /dev/null
+++ b/src/main/include/log4cxx/filter/propertyfilter.h
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_FILTER_PROPERTYFILTER_H
+#define _LOG4CXX_FILTER_PROPERTYFILTER_H
+
+#if defined(_MSC_VER)
+#pragma warning (push)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/spi/filter.h>
+#include <map>
+
+namespace log4cxx
+{
+ namespace filter
+ {
+
+/**
+ * NOTE: This filter modifies logging events by adding properties to the event.
+ *
+ * The 'properties' param is converted to event properties, which are
+ * set on every event processed by the filter.
+ *
+ * Individual properties are only set if they do not already exist on the
+ * logging event (will not override existing properties).
+ *
+ * This class relies on the convention that property name/value pairs are
+ * equals-symbol delimited, and each name/value pair is comma-delimited
+ *
+ * Example properties param:
+ * somename=somevalue,anothername=anothervalue,thirdname=third value
+ *
+ *
+ */
+ class LOG4CXX_EXPORT PropertyFilter : public log4cxx::spi::Filter
+ {
+ typedef std::map < LogString, LogString > PropertyMap;
+ PropertyMap* properties;
+ PropertyFilter(const PropertyFilter &);
+ PropertyFilter & operator=(const PropertyFilter &);
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(PropertyFilter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(log4cxx::spi::Filter)
+ END_LOG4CXX_CAST_MAP()
+
+ PropertyFilter();
+ ~PropertyFilter();
+ void setProperties(const LogString & props);
+
+ FilterDecision decide(const spi::LoggingEventPtr & event) const;
+
+ };
+
+ }
+}
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+#endif
diff --git a/src/main/include/log4cxx/filter/stringmatchfilter.h b/src/main/include/log4cxx/filter/stringmatchfilter.h
new file mode 100644
index 0000000..77a78da
--- /dev/null
+++ b/src/main/include/log4cxx/filter/stringmatchfilter.h
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_FILTER_STRING_MATCH_FILTER_H
+#define _LOG4CXX_FILTER_STRING_MATCH_FILTER_H
+
+#include <log4cxx/spi/filter.h>
+
+namespace log4cxx
+{
+ namespace filter
+ {
+ /**
+ This is a very simple filter based on string matching.
+
+ <p>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 {@link spi::LoggingEvent
+ LoggingEvent}, then the #decide method returns
+ {@link log4cxx::spi::Filter#ACCEPT ACCEPT} if the <b>AcceptOnMatch</b> option
+ value is true, if it is false then {@link log4cxx::spi::Filter#DENY DENY} is
+ returned. If there is no match, {@link log4cxx::spi::Filter#NEUTRAL NEUTRAL}
+ is returned.
+
+ <p>See configuration files <a
+ href="../xml/doc-files/test6.xml">test6.xml</a>, <a
+ href="../xml/doc-files/test7.xml">test7.xml</a>, <a
+ href="../xml/doc-files/test8.xml">test8.xml</a>, <a
+ href="../xml/doc-files/test9.xml">test9.xml</a>, and <a
+ href="../xml/doc-files/test10.xml">test10.xml</a> for examples of
+ seeting up a <code>StringMatchFilter</code>.
+ */
+
+ class LOG4CXX_EXPORT StringMatchFilter : public spi::Filter
+ {
+ private:
+ bool acceptOnMatch;
+ LogString stringToMatch;
+
+ public:
+ typedef spi::Filter BASE_CLASS;
+ DECLARE_LOG4CXX_OBJECT(StringMatchFilter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(StringMatchFilter)
+ LOG4CXX_CAST_ENTRY_CHAIN(BASE_CLASS)
+ END_LOG4CXX_CAST_MAP()
+
+ StringMatchFilter();
+
+ /**
+ Set options
+ */
+ virtual void setOption(const LogString& option,
+ const LogString& value);
+
+ inline void setStringToMatch(const LogString& stringToMatch1)
+ { this->stringToMatch.assign(stringToMatch1); }
+
+ inline const LogString& getStringToMatch() const
+ { return stringToMatch; }
+
+ inline void setAcceptOnMatch(bool acceptOnMatch1)
+ { this->acceptOnMatch = acceptOnMatch1; }
+
+ inline bool getAcceptOnMatch() const
+ { return acceptOnMatch; }
+
+ /**
+ Returns {@link log4cxx::spi::Filter#NEUTRAL NEUTRAL}
+ is there is no string match.
+ */
+ FilterDecision decide(const spi::LoggingEventPtr& event) const;
+ }; // class StringMatchFilter
+ LOG4CXX_PTR_DEF(StringMatchFilter);
+ } // namespace filter
+} // namespace log4cxx
+
+#endif // _LOG4CXX_FILTER_STRING_MATCH_FILTER_H
diff --git a/src/main/include/log4cxx/helpers/Makefile.am b/src/main/include/log4cxx/helpers/Makefile.am
new file mode 100644
index 0000000..e5e25a5
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/Makefile.am
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+helpersincdir = $(includedir)/log4cxx/helpers
+helpersinc_HEADERS= $(top_srcdir)/src/main/include/log4cxx/helpers/*.h
+
diff --git a/src/main/include/log4cxx/helpers/absolutetimedateformat.h b/src/main/include/log4cxx/helpers/absolutetimedateformat.h
new file mode 100644
index 0000000..a06cfa6
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/absolutetimedateformat.h
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_ABSOLUTE_TIME_DATE_FORMAT_H
+#define _LOG4CXX_HELPERS_ABSOLUTE_TIME_DATE_FORMAT_H
+
+#include <log4cxx/helpers/simpledateformat.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /**
+ Formats a date in the format <b>HH:mm:ss,SSS</b> for example,
+ "15:49:37,459".
+ */
+ class LOG4CXX_EXPORT AbsoluteTimeDateFormat : public SimpleDateFormat
+ {
+ public:
+ AbsoluteTimeDateFormat()
+ : SimpleDateFormat(LOG4CXX_STR("HH:mm:ss,SSS")) {}
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif // _LOG4CXX_HELPERS_ABSOLUTE_TIME_DATE_FORMAT_H
diff --git a/src/main/include/log4cxx/helpers/appenderattachableimpl.h b/src/main/include/log4cxx/helpers/appenderattachableimpl.h
new file mode 100644
index 0000000..d254e34
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/appenderattachableimpl.h
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_APPENDER_ATTACHABLE_IMPL_H
+#define _LOG4CXX_HELPERS_APPENDER_ATTACHABLE_IMPL_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/spi/appenderattachable.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/helpers/mutex.h>
+#include <log4cxx/helpers/pool.h>
+
+namespace log4cxx
+{
+ namespace spi
+ {
+ class LoggingEvent;
+ typedef helpers::ObjectPtrT<LoggingEvent> LoggingEventPtr;
+ }
+
+ namespace helpers
+ {
+
+ class LOG4CXX_EXPORT AppenderAttachableImpl :
+ public virtual spi::AppenderAttachable,
+ public virtual helpers::ObjectImpl
+ {
+ protected:
+ /** Array of appenders. */
+ AppenderList appenderList;
+
+ public:
+ /**
+ * Create new instance.
+ * @param pool pool, must be longer-lived than instance.
+ */
+ AppenderAttachableImpl(Pool& pool);
+
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(AppenderAttachableImpl)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(AppenderAttachableImpl)
+ LOG4CXX_CAST_ENTRY(spi::AppenderAttachable)
+ END_LOG4CXX_CAST_MAP()
+
+ void addRef() const;
+ void releaseRef() const;
+
+ // Methods
+ /**
+ * Add an appender.
+ */
+ virtual void addAppender(const AppenderPtr& newAppender);
+
+ /**
+ Call the <code>doAppend</code> method on all attached appenders.
+ */
+ int appendLoopOnAppenders(const spi::LoggingEventPtr& event,
+ log4cxx::helpers::Pool& p);
+
+ /**
+ * Get all previously added appenders as an Enumeration.
+ */
+ virtual AppenderList getAllAppenders() const;
+
+ /**
+ * Get an appender by name.
+ */
+ virtual AppenderPtr getAppender(const LogString& name) const;
+
+ /**
+ Returns <code>true</code> if the specified appender is in the
+ list of attached appenders, <code>false</code> otherwise.
+ */
+ virtual bool isAttached(const AppenderPtr& appender) const;
+
+ /**
+ * Remove all previously added appenders.
+ */
+ virtual void removeAllAppenders();
+
+ /**
+ * Remove the appender passed as parameter from the list of appenders.
+ */
+ virtual void removeAppender(const AppenderPtr& appender);
+
+ /**
+ * Remove the appender with the name passed as parameter from the
+ * list of appenders.
+ */
+ virtual void removeAppender(const LogString& name);
+
+ inline const log4cxx::helpers::Mutex& getMutex() const { return mutex; }
+
+ private:
+ log4cxx::helpers::Mutex mutex;
+ AppenderAttachableImpl(const AppenderAttachableImpl&);
+ AppenderAttachableImpl& operator=(const AppenderAttachableImpl&);
+ };
+
+ LOG4CXX_PTR_DEF(AppenderAttachableImpl);
+
+ }
+}
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif //_LOG4CXX_HELPERS_APPENDER_ATTACHABLE_IMPL_H
diff --git a/src/main/include/log4cxx/helpers/aprinitializer.h b/src/main/include/log4cxx/helpers/aprinitializer.h
new file mode 100644
index 0000000..154ecaa
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/aprinitializer.h
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_APRINITIALIZER_H
+#define _LOG4CXX_HELPERS_APRINITIALIZER_H
+
+#ifndef LOG4CXX
+#error "aprinitializer.h should only be included by log4cxx implementation"
+#endif
+
+#include <log4cxx/helpers/pool.h>
+#include <apr_pools.h>
+#include <apr_thread_proc.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class APRInitializer
+ {
+ public:
+ static log4cxx_time_t initialize();
+ static apr_pool_t* getRootPool();
+ static apr_threadkey_t* getTlsKey();
+ static bool isDestructed;
+
+ private:
+ APRInitializer();
+ APRInitializer(const APRInitializer&);
+ APRInitializer& operator=(const APRInitializer&);
+ apr_pool_t* p;
+ log4cxx_time_t startTime;
+ apr_threadkey_t* tlsKey;
+ static APRInitializer& getInstance();
+ static void tlsDestruct(void*);
+
+ public:
+ ~APRInitializer();
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_APRINITIALIZER_H
diff --git a/src/main/include/log4cxx/helpers/bufferedoutputstream.h b/src/main/include/log4cxx/helpers/bufferedoutputstream.h
new file mode 100644
index 0000000..9d4aa18
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/bufferedoutputstream.h
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_BUFFEREDOUTPUTSTREAM_H
+#define _LOG4CXX_HELPERS_BUFFEREDOUTPUTSTREAM_H
+
+#include <log4cxx/helpers/outputstream.h>
+
+namespace log4cxx
+{
+
+ namespace helpers {
+
+ /**
+ * Abstract class for writing to character streams.
+ */
+ class LOG4CXX_EXPORT BufferedOutputStream : public OutputStream
+ {
+ private:
+ size_t count;
+ LogString buf;
+
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(BufferedOutputStream)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(BufferedOutputStream)
+ LOG4CXX_CAST_ENTRY_CHAIN(OutputStream)
+ END_LOG4CXX_CAST_MAP()
+
+ protected:
+ BufferedOutputStream(OutputStreamPtr& out, size_t size = 4096);
+ ~BufferedOutputStream();
+
+ public:
+ void close(Pool& p);
+ void flush(Pool& p);
+ void write(ByteBuffer& buf, Pool& p);
+
+ private:
+ BufferedOutputStream(const BufferedOutputStream&);
+ BufferedOutputStream& operator=(const BufferedOutputStream&);
+ };
+
+ LOG4CXX_PTR_DEF(BufferedOutputStream);
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_BUFFEREDOUTPUTSTREAM_H
diff --git a/src/main/include/log4cxx/helpers/bufferedwriter.h b/src/main/include/log4cxx/helpers/bufferedwriter.h
new file mode 100644
index 0000000..570da09
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/bufferedwriter.h
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_BUFFEREDWRITER_H
+#define _LOG4CXX_HELPERS_BUFFEREDWRITER_H
+
+#include <log4cxx/helpers/writer.h>
+
+namespace log4cxx
+{
+
+ namespace helpers {
+
+ /**
+ * Writes text to a character-output stream buffering
+ * requests to increase efficiency.
+ */
+ class LOG4CXX_EXPORT BufferedWriter : public Writer
+ {
+ private:
+ WriterPtr out;
+ size_t sz;
+ LogString buf;
+
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(BufferedWriter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(BufferedWriter)
+ LOG4CXX_CAST_ENTRY_CHAIN(Writer)
+ END_LOG4CXX_CAST_MAP()
+
+ BufferedWriter(WriterPtr& out);
+ BufferedWriter(WriterPtr& out, size_t sz);
+ virtual ~BufferedWriter();
+
+ virtual void close(Pool& p);
+ virtual void flush(Pool& p);
+ virtual void write(const LogString& str, Pool& p);
+
+ private:
+ BufferedWriter(const BufferedWriter&);
+ BufferedWriter& operator=(const BufferedWriter&);
+ };
+
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_BUFFEREDWRITER_H
diff --git a/src/main/include/log4cxx/helpers/bytearrayinputstream.h b/src/main/include/log4cxx/helpers/bytearrayinputstream.h
new file mode 100755
index 0000000..92bcb59
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/bytearrayinputstream.h
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_BYTEARRAYINPUTSTREAM_H
+#define _LOG4CXX_HELPERS_BYTEARRAYINPUTSTREAM_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <vector>
+#include <log4cxx/helpers/inputstream.h>
+
+
+namespace log4cxx
+{
+
+ namespace helpers {
+
+ /**
+ * InputStream implemented on top of a byte array.
+ */
+ class LOG4CXX_EXPORT ByteArrayInputStream : public InputStream
+ {
+ private:
+ LOG4CXX_LIST_DEF(ByteList, unsigned char);
+ ByteList buf;
+ size_t pos;
+
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(ByteArrayInputStream)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(ByteArrayInputStream)
+ LOG4CXX_CAST_ENTRY_CHAIN(InputStream)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Creates a ByteArrayInputStream.
+ *
+ * @param bytes array of bytes to copy into stream.
+ */
+ ByteArrayInputStream(const ByteList& bytes);
+
+ virtual ~ByteArrayInputStream();
+
+ /**
+ * Closes this file input stream and releases any system
+ * resources associated with the stream.
+ */
+ virtual void close();
+
+ /**
+ * Reads a sequence of bytes into the given buffer.
+ *
+ * @param buf The buffer into which bytes are to be transferred.
+ * @return the total number of bytes read into the buffer, or -1 if there
+ * is no more data because the end of the stream has been reached.
+ */
+ virtual int read(ByteBuffer& buf);
+
+ private:
+
+ ByteArrayInputStream(const ByteArrayInputStream&);
+
+ ByteArrayInputStream& operator=(const ByteArrayInputStream&);
+
+ };
+
+ LOG4CXX_PTR_DEF(ByteArrayInputStream);
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif //_LOG4CXX_HELPERS_BYTEARRAYINPUTSTREAM_H
diff --git a/src/main/include/log4cxx/helpers/bytearrayoutputstream.h b/src/main/include/log4cxx/helpers/bytearrayoutputstream.h
new file mode 100644
index 0000000..34e3d09
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/bytearrayoutputstream.h
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_BYTEARRAYOUTPUTSTREAM_H
+#define _LOG4CXX_HELPERS_BYTEARRAYOUTPUTSTREAM_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+
+#include <log4cxx/helpers/outputstream.h>
+#include <vector>
+
+
+namespace log4cxx
+{
+
+ namespace helpers {
+ class Pool;
+
+ /**
+ * OutputStream implemented on top of std::vector
+ */
+ class LOG4CXX_EXPORT ByteArrayOutputStream : public OutputStream
+ {
+ private:
+ LOG4CXX_LIST_DEF(ByteList, unsigned char);
+ ByteList array;
+
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(ByteArrayOutputStream)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(ByteArrayOutputStream)
+ LOG4CXX_CAST_ENTRY_CHAIN(OutputStream)
+ END_LOG4CXX_CAST_MAP()
+
+ ByteArrayOutputStream();
+ virtual ~ByteArrayOutputStream();
+
+ virtual void close(Pool& p);
+ virtual void flush(Pool& p);
+ virtual void write(ByteBuffer& buf, Pool& p);
+ ByteList toByteArray() const;
+
+ private:
+ ByteArrayOutputStream(const ByteArrayOutputStream&);
+ ByteArrayOutputStream& operator=(const ByteArrayOutputStream&);
+ };
+
+ LOG4CXX_PTR_DEF(ByteArrayOutputStream);
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+#endif //_LOG4CXX_HELPERS_BYTEARRAYOUTPUTSTREAM_H
diff --git a/src/main/include/log4cxx/helpers/bytebuffer.h b/src/main/include/log4cxx/helpers/bytebuffer.h
new file mode 100644
index 0000000..da235b6
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/bytebuffer.h
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_BYTEBUFFER_H
+#define _LOG4CXX_HELPERS_BYTEBUFFER_H
+
+#include <log4cxx/log4cxx.h>
+#include <stdio.h>
+
+namespace log4cxx
+{
+
+ namespace helpers {
+
+ /**
+ * A byte buffer.
+ */
+ class LOG4CXX_EXPORT ByteBuffer
+ {
+ private:
+ char* base;
+ size_t pos;
+ size_t lim;
+ size_t cap;
+
+ public:
+ ByteBuffer(char* data, size_t capacity);
+ ~ByteBuffer();
+
+ void clear();
+ void flip();
+
+ inline char* data() { return base; }
+ inline const char* data() const { return base; }
+ inline char* current() { return base + pos; }
+ inline const char* current() const { return base + pos; }
+ inline size_t limit() const { return lim; }
+ void limit(size_t newLimit);
+ inline size_t position() const { return pos; }
+ inline size_t remaining() const { return lim - pos; }
+ void position(size_t newPosition);
+
+ bool put(char byte);
+
+
+ private:
+ ByteBuffer(const ByteBuffer&);
+ ByteBuffer& operator=(const ByteBuffer&);
+ };
+
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_BYTEBUFFER_H
diff --git a/src/main/include/log4cxx/helpers/cacheddateformat.h b/src/main/include/log4cxx/helpers/cacheddateformat.h
new file mode 100644
index 0000000..527ed25
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/cacheddateformat.h
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_CACHED_DATE_FORMAT_H
+#define _LOG4CXX_HELPERS_CACHED_DATE_FORMAT_H
+
+#include <log4cxx/helpers/dateformat.h>
+
+namespace log4cxx
+{
+ namespace pattern
+ {
+ class LOG4CXX_EXPORT CachedDateFormat : public log4cxx::helpers::DateFormat {
+ public:
+ enum {
+ /*
+ * Constant used to represent that there was no change
+ * observed when changing the millisecond count.
+ */
+ NO_MILLISECONDS = -2,
+ /*
+ * Constant used to represent that there was an
+ * observed change, but was an expected change.
+ */
+ UNRECOGNIZED_MILLISECONDS = -1
+ };
+
+ private:
+ /**
+ * Supported digit set. If the wrapped DateFormat uses
+ * a different unit set, the millisecond pattern
+ * will not be recognized and duplicate requests
+ * will use the cache.
+ */
+ static const logchar digits[];
+
+ enum {
+ /**
+ * First magic number used to detect the millisecond position.
+ */
+ magic1 = 654000,
+ /**
+ * Second magic number used to detect the millisecond position.
+ */
+ magic2 = 987000
+ };
+
+ /**
+ * Expected representation of first magic number.
+ */
+ static const logchar magicString1[];
+
+
+ /**
+ * Expected representation of second magic number.
+ */
+ static const logchar magicString2[];
+
+
+ /**
+ * Expected representation of 0 milliseconds.
+ */
+ static const logchar zeroString[];
+
+ /**
+ * Wrapped formatter.
+ */
+ log4cxx::helpers::DateFormatPtr formatter;
+
+ /**
+ * Index of initial digit of millisecond pattern or
+ * UNRECOGNIZED_MILLISECONDS or NO_MILLISECONDS.
+ */
+ mutable int millisecondStart;
+
+ /**
+ * Integral second preceding the previous convered Date.
+ */
+ mutable log4cxx_time_t slotBegin;
+
+
+ /**
+ * Cache of previous conversion.
+ */
+ mutable LogString cache;
+
+
+ /**
+ * Maximum validity period for the cache.
+ * Typically 1, use cache for duplicate requests only, or
+ * 1000000, use cache for requests within the same integral second.
+ */
+ const int expiration;
+
+ /**
+ * Date requested in previous conversion.
+ */
+ mutable log4cxx_time_t previousTime;
+
+ public:
+ /**
+ * Creates a new CachedDateFormat object.
+ * @param dateFormat Date format, may not be null.
+ * @param expiration maximum cached range in microseconds.
+ * If the dateFormat is known to be incompatible with the
+ * caching algorithm, use a value of 0 to totally disable
+ * caching or 1 to only use cache for duplicate requests.
+ */
+ CachedDateFormat(const log4cxx::helpers::DateFormatPtr& dateFormat, int expiration);
+
+ /**
+ * Finds start of millisecond field in formatted time.
+ * @param time long time, must be integral number of seconds
+ * @param formatted String corresponding formatted string
+ * @param formatter DateFormat date format
+ * @param pool pool.
+ * @return int position in string of first digit of milliseconds,
+ * -1 indicates no millisecond field, -2 indicates unrecognized
+ * field (likely RelativeTimeDateFormat)
+ */
+ static int findMillisecondStart(
+ log4cxx_time_t time, const LogString& formatted,
+ const log4cxx::helpers::DateFormatPtr& formatter,
+ log4cxx::helpers::Pool& pool);
+
+ /**
+ * Formats a Date into a date/time string.
+ *
+ * @param date the date to format.
+ * @param sbuf the string buffer to write to.
+ * @param p memory pool.
+ */
+ virtual void format(LogString &sbuf,
+ log4cxx_time_t date,
+ log4cxx::helpers::Pool& p) const;
+
+ private:
+ /**
+ * Formats a count of milliseconds (0-999) into a numeric representation.
+ * @param millis Millisecond coun between 0 and 999.
+ * @buf String buffer, may not be null.
+ * @offset Starting position in buffer, the length of the
+ * buffer must be at least offset + 3.
+ */
+ static void millisecondFormat(int millis,
+ LogString& buf,
+ int offset);
+
+
+ public:
+ /**
+ * Set timezone.
+ *
+ * @remarks Setting the timezone using getCalendar().setTimeZone()
+ * will likely cause caching to misbehave.
+ * @param zone TimeZone new timezone
+ */
+ virtual void setTimeZone(const log4cxx::helpers::TimeZonePtr& zone);
+
+ /**
+ * Format an integer consistent with the format method.
+ * @param s string to which the numeric string is appended.
+ * @param n integer value.
+ * @param p memory pool used during formatting.
+ */
+ virtual void numberFormat(LogString& s,
+ int n,
+ log4cxx::helpers::Pool& p) const;
+
+ /**
+ * Gets maximum cache validity for the specified SimpleDateTime
+ * conversion pattern.
+ * @param pattern conversion pattern, may not be null.
+ * @returns Duration in microseconds from an integral second
+ * that the cache will return consistent results.
+ */
+ static int getMaximumCacheValidity(const LogString& pattern);
+
+ private:
+ CachedDateFormat(const CachedDateFormat&);
+ CachedDateFormat& operator=(const CachedDateFormat&);
+
+ /**
+ * Tests if two string regions are equal.
+ * @param target target string.
+ * @param toffset character position in target to start comparison.
+ * @param other other string.
+ * @param ooffset character position in other to start comparison.
+ * @param len length of region.
+ * @return true if regions are equal.
+ */
+ static bool regionMatches(
+ const LogString& target,
+ size_t toffset,
+ const LogString& other,
+ size_t ooffset,
+ size_t len);
+
+ };
+
+
+
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif // _LOG4CXX_HELPERS_SIMPLE_DATE_FORMAT_H
diff --git a/src/main/include/log4cxx/helpers/charsetdecoder.h b/src/main/include/log4cxx/helpers/charsetdecoder.h
new file mode 100644
index 0000000..cb8320a
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/charsetdecoder.h
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_CHARSETDECODER_H
+#define _LOG4CXX_HELPERS_CHARSETDECODER_H
+
+#include <log4cxx/helpers/objectimpl.h>
+
+namespace log4cxx
+{
+ namespace helpers {
+ class CharsetDecoder;
+ LOG4CXX_PTR_DEF(CharsetDecoder);
+ class ByteBuffer;
+
+
+ /**
+ * An abstract engine to transform a sequences of bytes in a specific charset
+ * into a LogString.
+ */
+ class LOG4CXX_EXPORT CharsetDecoder : public ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(CharsetDecoder)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(CharsetDecoder)
+ END_LOG4CXX_CAST_MAP()
+ protected:
+ /**
+ * Protected constructor.
+ */
+ CharsetDecoder();
+ public:
+ /**
+ * Destructor.
+ */
+ virtual ~CharsetDecoder();
+
+ /**
+ * Get decoder for default charset.
+ */
+ static CharsetDecoderPtr getDefaultDecoder();
+ /**
+ * Get decoder for specified character set.
+ * @param charset the following values should be recognized:
+ * "US-ASCII", "ISO-8859-1", "UTF-8",
+ * "UTF-16BE", "UTF-16LE".
+ * @return decoder
+ * @throws IllegalArgumentException if charset is not recognized.
+ */
+ static CharsetDecoderPtr getDecoder(const LogString& charset);
+
+ /**
+ * Get decoder for UTF-8.
+ */
+ static CharsetDecoderPtr getUTF8Decoder();
+ /**
+ * Get decoder for ISO-8859-1.
+ */
+ static CharsetDecoderPtr getISOLatinDecoder();
+
+
+
+ /**
+ * Decodes as many bytes as possible from the given
+ * input buffer, writing the results to the given output string.
+ * @param in input buffer.
+ * @param out output string.
+ * @return APR_SUCCESS if not encoding errors were found.
+ */
+ virtual log4cxx_status_t decode(ByteBuffer& in,
+ LogString& out) = 0;
+
+ /**
+ * Determins if status value indicates an invalid byte sequence.
+ */
+ inline static bool isError(log4cxx_status_t stat) {
+ return (stat != 0);
+ }
+
+ private:
+ /**
+ * Private copy constructor.
+ */
+ CharsetDecoder(const CharsetDecoder&);
+ /**
+ * Private assignment operator.
+ */
+ CharsetDecoder& operator=(const CharsetDecoder&);
+ /**
+ * Creates a new decoder for the default charset.
+ */
+ static CharsetDecoder* createDefaultDecoder();
+ };
+
+ } // namespace helpers
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_CHARSETENCODER_H
diff --git a/src/main/include/log4cxx/helpers/charsetencoder.h b/src/main/include/log4cxx/helpers/charsetencoder.h
new file mode 100644
index 0000000..c815ebc
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/charsetencoder.h
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_CHARSETENCODER_H
+#define _LOG4CXX_HELPERS_CHARSETENCODER_H
+
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/helpers/pool.h>
+
+namespace log4cxx
+{
+
+ namespace helpers {
+ class ByteBuffer;
+ class CharsetEncoder;
+ LOG4CXX_PTR_DEF(CharsetEncoder);
+
+ /**
+ * An engine to transform LogStrings into bytes
+ * for the specific character set.
+ */
+ class LOG4CXX_EXPORT CharsetEncoder : public ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(CharsetEncoder)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(CharsetEncoder)
+ END_LOG4CXX_CAST_MAP()
+
+ protected:
+ /**
+ * Protected constructor.
+ */
+ CharsetEncoder();
+
+ public:
+ /**
+ * Destructor.
+ */
+ virtual ~CharsetEncoder();
+ /**
+ * Get encoder for default charset.
+ */
+ static CharsetEncoderPtr getDefaultEncoder();
+
+ /**
+ * Get encoder for specified character set.
+ * @param charset the following values should be recognized:
+ * "US-ASCII", "ISO-8859-1", "UTF-8",
+ * "UTF-16BE", "UTF-16LE".
+ * @return encoder.
+ * @throws IllegalArgumentException if encoding is not recognized.
+ */
+ static CharsetEncoderPtr getEncoder(const LogString& charset);
+
+
+ /**
+ * Get encoder for UTF-8.
+ */
+ static CharsetEncoderPtr getUTF8Encoder();
+
+ /**
+ * Encodes a string replacing unmappable
+ * characters with escape sequences.
+ *
+ */
+ static void encode(CharsetEncoderPtr& enc,
+ const LogString& src,
+ LogString::const_iterator& iter,
+ ByteBuffer& dst);
+
+ /**
+ * Encodes as many characters from the input string as possible
+ * to the output buffer.
+ * @param in input string
+ * @param iter position in string to start.
+ * @param out output buffer.
+ * @return APR_SUCCESS unless a character can not be represented in
+ * the encoding.
+ */
+ virtual log4cxx_status_t encode(const LogString& in,
+ LogString::const_iterator& iter,
+ ByteBuffer& out) = 0;
+
+ /**
+ * Resets any internal state.
+ */
+ virtual void reset();
+
+ /**
+ * Flushes the encoder.
+ */
+ virtual void flush(ByteBuffer& out);
+
+ /**
+ * Determines if the return value from encode indicates
+ * an unconvertable character.
+ */
+ inline static bool isError(log4cxx_status_t stat) {
+ return (stat != 0);
+ }
+
+
+ private:
+ /**
+ * Private copy constructor.
+ */
+ CharsetEncoder(const CharsetEncoder&);
+ /**
+ * Private assignment operator.
+ */
+ CharsetEncoder& operator=(const CharsetEncoder&);
+
+ static CharsetEncoder* createDefaultEncoder();
+ };
+
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_CHARSETENCODER_H
diff --git a/src/main/include/log4cxx/helpers/class.h b/src/main/include/log4cxx/helpers/class.h
new file mode 100644
index 0000000..c7f708b
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/class.h
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_CLASS_H
+#define _LOG4CXX_HELPERS_CLASS_H
+
+#if defined(_MSC_VER)
+#pragma warning (push)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/objectptr.h>
+#include <map>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class Object;
+ typedef ObjectPtrT<Object> ObjectPtr;
+
+
+ class LOG4CXX_EXPORT Class
+ {
+ public:
+ virtual ~Class();
+ virtual ObjectPtr newInstance() const;
+ LogString toString() const;
+ virtual LogString getName() const = 0;
+ static const Class& forName(const LogString& className);
+ static bool registerClass(const Class& newClass);
+
+ protected:
+ Class();
+
+ private:
+ Class(const Class&);
+ Class& operator=(const Class&);
+ typedef std::map<LogString, const Class *> ClassMap;
+ static ClassMap& getRegistry();
+ static void registerClasses();
+ };
+ } // namespace log4cxx
+} // namespace helper
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+
+#endif //_LOG4CXX_HELPERS_CLASS_H
diff --git a/src/main/include/log4cxx/helpers/classregistration.h b/src/main/include/log4cxx/helpers/classregistration.h
new file mode 100644
index 0000000..af06319
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/classregistration.h
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_CLASSREGISTRATION_H
+#define _LOG4CXX_HELPERS_CLASSREGISTRATION_H
+
+#include <log4cxx/log4cxx.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class Class;
+ class LOG4CXX_EXPORT ClassRegistration
+ {
+ public:
+ typedef const Class& (*ClassAccessor)();
+ ClassRegistration(ClassAccessor classAccessor);
+
+ private:
+ ClassRegistration(const ClassRegistration&);
+ ClassRegistration& operator=(const ClassRegistration&);
+ };
+ } // namespace log4cxx
+} // namespace helper
+
+#endif //_LOG4CXX_HELPERS_CLASSREGISTRATION_H
diff --git a/src/main/include/log4cxx/helpers/condition.h b/src/main/include/log4cxx/helpers/condition.h
new file mode 100755
index 0000000..7adb3bc
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/condition.h
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_CONDITION_H
+#define _LOG4CXX_HELPERS_CONDITION_H
+
+#include <log4cxx/log4cxx.h>
+#include <log4cxx/helpers/mutex.h>
+
+extern "C" {
+ struct apr_thread_cond_t;
+}
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class Pool;
+
+ /**
+ * This class provides a means for one thread to suspend exception until
+ * notified by another thread to resume. This class should have
+ * similar semantics to java.util.concurrent.locks.Condition.
+ */
+ class LOG4CXX_EXPORT Condition
+ {
+ public:
+ /**
+ * Create new instance.
+ * @param p pool on which condition will be created. Needs to be
+ * longer-lived than created instance.
+ */
+ Condition(log4cxx::helpers::Pool& p);
+ /**
+ * Destructor.
+ */
+ ~Condition();
+ /**
+ * Signal all waiting threads.
+ */
+ log4cxx_status_t signalAll();
+ /**
+ * Await signaling of condition.
+ * @param lock lock associated with condition, calling thread must
+ * own lock. Lock will be released while waiting and reacquired
+ * before returning from wait.
+ * @throws InterruptedException if thread is interrupted.
+ */
+ void await(Mutex& lock);
+
+ private:
+ apr_thread_cond_t* condition;
+ Condition(const Condition&);
+ Condition& operator=(const Condition&);
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_CONDITION_H
diff --git a/src/main/include/log4cxx/helpers/cyclicbuffer.h b/src/main/include/log4cxx/helpers/cyclicbuffer.h
new file mode 100644
index 0000000..2cd913d
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/cyclicbuffer.h
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_CYCLICBUFFER_H
+#define _LOG4CXX_HELPERS_CYCLICBUFFER_H
+
+#include <log4cxx/spi/loggingevent.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /**
+ CyclicBuffer is used by other appenders to hold instances of
+ {@link log4cxx::spi::LoggingEvent LoggingEvent} for immediate
+ or deferred display.
+ <p>This buffer gives read access to any element in the buffer not
+ just the first or last element.
+ */
+ class LOG4CXX_EXPORT CyclicBuffer
+ {
+ log4cxx::spi::LoggingEventList ea;
+ int first;
+ int last;
+ int numElems;
+ int maxSize;
+
+ public:
+ /**
+ Instantiate a new CyclicBuffer of at most <code>maxSize</code>
+ events.
+ The <code>maxSize</code> argument must a positive integer.
+ @param maxSize The maximum number of elements in the buffer.
+ @throws IllegalArgumentException if <code>maxSize</code>
+ is negative.
+ */
+ CyclicBuffer(int maxSize);
+ ~CyclicBuffer();
+
+ /**
+ Add an <code>event</code> as the last event in the buffer.
+ */
+ void add(const spi::LoggingEventPtr& event);
+
+ /**
+ Get the <i>i</i>th oldest event currently in the buffer. If
+ <em>i</em> is outside the range 0 to the number of elements
+ currently in the buffer, then <code>null</code> is returned.
+ */
+ spi::LoggingEventPtr get(int i);
+
+ int getMaxSize() const
+ { return maxSize; }
+
+ /**
+ Get the oldest (first) element in the buffer. The oldest element
+ is removed from the buffer.
+ */
+ spi::LoggingEventPtr get();
+
+ /**
+ Get the number of elements in the buffer. This number is
+ guaranteed to be in the range 0 to <code>maxSize</code>
+ (inclusive).
+ */
+ int length() const
+ { return numElems; }
+
+ /**
+ Resize the cyclic buffer to <code>newSize</code>.
+ @throws IllegalArgumentException if <code>newSize</code> is negative.
+ */
+ void resize(int newSize);
+ }; // class CyclicBuffer
+ } //namespace helpers
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_CYCLICBUFFER_H
diff --git a/src/main/include/log4cxx/helpers/datagrampacket.h b/src/main/include/log4cxx/helpers/datagrampacket.h
new file mode 100644
index 0000000..5bdbf48
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/datagrampacket.h
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_DATAGRAM_PACKET
+#define _LOG4CXX_HELPERS_DATAGRAM_PACKET
+
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/inetaddress.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+
+ /** This class represents a datagram packet.
+ <p>Datagram packets are used to implement a connectionless packet
+ delivery service. Each message is routed from one machine to another
+ based solely on information contained within that packet. Multiple
+ packets sent from one machine to another might be routed differently,
+ and might arrive in any order.
+ */
+ class LOG4CXX_EXPORT DatagramPacket : public helpers::ObjectImpl
+ {
+ protected:
+ /** the data for this packet. */
+ void * buf;
+
+ /** The offset of the data for this packet. */
+ int offset;
+
+ /** The length of the data for this packet. */
+ int length;
+
+ /** The IP address for this packet. */
+ InetAddressPtr address;
+
+ /** The UDP port number of the remote host. */
+ int port;
+
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(DatagramPacket)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(DatagramPacket)
+ END_LOG4CXX_CAST_MAP()
+
+ /** Constructs a DatagramPacket for receiving packets of length
+ <code>length</code>. */
+ DatagramPacket(void * buf, int length);
+
+ /** Constructs a datagram packet for sending packets of length
+ <code>length</code> to the specified port number on the specified
+ host. */
+ DatagramPacket(void * buf, int length, InetAddressPtr address, int port);
+
+ /** Constructs a DatagramPacket for receiving packets of length
+ <code>length</code>, specifying an offset into the buffer. */
+ DatagramPacket(void * buf, int offset, int length);
+
+ /** Constructs a datagram packet for sending packets of length
+ <code>length</code> with offset <code>offset</code> to the
+ specified port number on the specified host. */
+ DatagramPacket(void * buf, int offset, int length, InetAddressPtr address,
+ int port);
+
+ ~DatagramPacket();
+
+ /** Returns the IP address of the machine to which this datagram
+ is being sent or from which the datagram was received. */
+ inline InetAddressPtr getAddress() const
+ { return address; }
+
+ /** Returns the data received or the data to be sent. */
+ inline void * getData() const
+ { return buf; }
+
+ /** Returns the length of the data to be sent or the length of the
+ data received. */
+ inline int getLength() const
+ { return length; }
+
+ /** Returns the offset of the data to be sent or the offset of the
+ data received. */
+ inline int getOffset() const
+ { return offset; }
+
+ /** Returns the port number on the remote host to which this
+ datagram is being sent or from which the datagram was received. */
+ inline int getPort() const
+ { return port; }
+
+ inline void setAddress(InetAddressPtr address1)
+ { this->address = address1; }
+
+ /** Set the data buffer for this packet. */
+ inline void setData(void * buf1)
+ { this->buf = buf1; }
+
+ /** Set the data buffer for this packet. */
+ inline void setData(void * buf1, int offset1, int length1)
+ { this->buf = buf1; this->offset = offset1; this->length = length1; }
+
+ /** Set the length for this packet. */
+ inline void setLength(int length1)
+ { this->length = length1; }
+
+ inline void setPort(int port1)
+ { this->port = port1; }
+
+ private:
+ //
+ // prevent copy and assignment statements
+ DatagramPacket(const DatagramPacket&);
+ DatagramPacket& operator=(const DatagramPacket&);
+
+ }; // class DatagramPacket
+ LOG4CXX_PTR_DEF(DatagramPacket);
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif // _LOG4CXX_HELPERS_DATAGRAM_PACKET
diff --git a/src/main/include/log4cxx/helpers/datagramsocket.h b/src/main/include/log4cxx/helpers/datagramsocket.h
new file mode 100644
index 0000000..5e7db94
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/datagramsocket.h
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_DATAGRAM_SOCKET_H
+#define _LOG4CXX_HELPERS_DATAGRAM_SOCKET_H
+
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/inetaddress.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/datagrampacket.h>
+
+extern "C" { struct apr_socket_t; }
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /** This class represents a socket for sending and receiving
+ datagram packets.*/
+ class LOG4CXX_EXPORT DatagramSocket : public helpers::ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(DatagramSocket)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(DatagramSocket)
+ END_LOG4CXX_CAST_MAP()
+
+ /** Constructs a datagram socket and binds it to any available port
+ on the local host machine.*/
+ DatagramSocket();
+
+ /** Constructs a datagram socket and binds it to the specified
+ port on the local host machine. */
+ DatagramSocket(int port);
+
+ /** Creates a datagram socket, bound to the specified local
+ address. */
+ DatagramSocket(int port, InetAddressPtr laddr);
+
+ /** ensure the socket is closed. */
+ ~DatagramSocket();
+
+ /** Binds a datagram socket to a local port and address.*/
+ void bind(int lport, InetAddressPtr laddress);
+
+ /** Creates a datagram socket.*/
+ void create();
+
+ /** Closes this datagram socket */
+ void close();
+
+ /** Connects the socket to a remote address for this socket. */
+ void connect(InetAddressPtr address, int port);
+
+ /** Returns the address to which this socket is connected. */
+ inline InetAddressPtr getInetAddress() const
+ { return address; }
+
+ /** Gets the local address to which the socket is bound. */
+ inline InetAddressPtr getLocalAddress() const
+ { return localAddress; }
+
+ /** Returns the port number on the local host to which this
+ socket is bound. */
+ inline int getLocalPort() const
+ { return localPort; }
+
+ /** Returns the port for this socket */
+ inline int getPort() const
+ { return port; }
+
+ /** Returns the binding state of the socket. **/
+ inline bool isBound() const
+ { return localPort != 0; }
+
+ /** Returns wether the socket is closed or not. */
+ inline bool isClosed() const
+ { return socket != 0; }
+
+ /** Returns the connection state of the socket. */
+ inline bool isConnected() const
+ { return port != 0; }
+
+ /** Receives a datagram packet from this socket. */
+ void receive(DatagramPacketPtr& p);
+
+ /** Sends a datagram packet from this socket. */
+ void send(DatagramPacketPtr& p);
+
+ private:
+ DatagramSocket(const DatagramSocket&);
+ DatagramSocket& operator=(const DatagramSocket&);
+ /** The APR socket */
+ apr_socket_t *socket;
+
+ /** The memory pool for the socket */
+ Pool socketPool;
+
+ InetAddressPtr address;
+
+ InetAddressPtr localAddress;
+
+ int port;
+
+ /** The local port number to which this socket is connected. */
+ int localPort;
+
+ };
+ LOG4CXX_PTR_DEF(DatagramSocket);
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_DATAGRAM_SOCKET_H
diff --git a/src/main/include/log4cxx/helpers/date.h b/src/main/include/log4cxx/helpers/date.h
new file mode 100644
index 0000000..6e3dc04
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/date.h
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_DATE_H
+#define _LOG4CXX_HELPERS_DATE_H
+
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/log4cxx.h>
+
+
+namespace log4cxx {
+ namespace helpers {
+ /**
+ * Simple transcoder for converting between
+ * external char and wchar_t strings and
+ * internal strings.
+ *
+ */
+ class LOG4CXX_EXPORT Date : public ObjectImpl {
+ const log4cxx_time_t time;
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(Date)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(Date)
+ END_LOG4CXX_CAST_MAP()
+
+ Date();
+ Date(log4cxx_time_t time);
+ virtual ~Date();
+
+ inline log4cxx_time_t getTime() const {
+ return time;
+ }
+
+ /**
+ * Get start of next second
+ */
+ log4cxx_time_t getNextSecond() const;
+
+
+ static log4cxx_time_t getMicrosecondsPerDay();
+ static log4cxx_time_t getMicrosecondsPerSecond();
+
+ };
+
+ LOG4CXX_PTR_DEF(Date);
+
+ }
+}
+
+
+#endif
diff --git a/src/main/include/log4cxx/helpers/dateformat.h b/src/main/include/log4cxx/helpers/dateformat.h
new file mode 100644
index 0000000..86bf1a9
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/dateformat.h
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_DATE_FORMAT_H
+#define _LOG4CXX_HELPERS_DATE_FORMAT_H
+
+#include <log4cxx/helpers/timezone.h>
+
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+
+ /**
+ * DateFormat is an abstract class for date/time formatting
+ * patterned after java.text.DateFormat.
+ */
+ class LOG4CXX_EXPORT DateFormat : public ObjectImpl {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(DateFormat)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(DateFormat)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Destructor
+ */
+ virtual ~DateFormat();
+
+ /**
+ * Formats an log4cxx_time_t into a date/time string.
+ * @param s string to which the date/time string is appended.
+ * @param tm date to be formatted.
+ * @param p memory pool used during formatting.
+ */
+ virtual void format(LogString &s, log4cxx_time_t tm, log4cxx::helpers::Pool& p) const = 0;
+
+ /**
+ * Sets the time zone.
+ * @param zone the given new time zone.
+ */
+ virtual void setTimeZone(const TimeZonePtr& zone);
+
+ /**
+ * Format an integer consistent with the format method.
+ * @param s string to which the numeric string is appended.
+ * @param n integer value.
+ * @param p memory pool used during formatting.
+ * @remarks This method is used by CachedDateFormat to
+ * format the milliseconds.
+ */
+ virtual void numberFormat(LogString& s, int n, log4cxx::helpers::Pool& p) const;
+
+
+ protected:
+ /**
+ * Constructor.
+ */
+ DateFormat();
+
+ private:
+ /**
+ * Copy constructor definition to prevent copying.
+ */
+ DateFormat(const DateFormat&);
+ /**
+ * Assignment definition to prevent assignment.
+ */
+ DateFormat& operator=(const DateFormat&);
+ };
+ LOG4CXX_PTR_DEF(DateFormat);
+
+
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_DATE_FORMAT_H
diff --git a/src/main/include/log4cxx/helpers/datelayout.h b/src/main/include/log4cxx/helpers/datelayout.h
new file mode 100644
index 0000000..ca271ca
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/datelayout.h
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_DATE_LAYOUT_H
+#define _LOG4CXX_HELPERS_DATE_LAYOUT_H
+
+#include <log4cxx/layout.h>
+#include <log4cxx/helpers/dateformat.h>
+#include <log4cxx/helpers/timezone.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /**
+ This abstract layout takes care of all the date related options and
+ formatting work.
+ */
+ class LOG4CXX_EXPORT DateLayout : public Layout
+ {
+ private:
+ LogString timeZoneID;
+ LogString dateFormatOption;
+
+ protected:
+ DateFormatPtr dateFormat;
+
+ public:
+ DateLayout(const LogString& dateLayoutOption);
+ virtual ~DateLayout();
+
+ virtual void activateOptions(log4cxx::helpers::Pool& p);
+ virtual void setOption(const LogString& option, const LogString& value);
+
+ /**
+ The value of the <b>DateFormat</b> option should be either an
+ argument to the constructor of helpers::DateFormat or one of
+ the strings <b>"NULL"</b>, <b>"RELATIVE"</b>, <b>"ABSOLUTE"</b>,
+ <b>"DATE"</b> or <b>"ISO8601</b>.
+ */
+ inline void setDateFormat(const LogString& dateFormat1)
+ { this->dateFormatOption.assign(dateFormat1); }
+
+ /**
+ Returns value of the <b>DateFormat</b> option.
+ */
+ inline const LogString& getDateFormat() const
+ { return dateFormatOption; }
+
+ /**
+ The <b>TimeZoneID</b> option is a time zone ID string in the format
+ expected by the <code>locale</code> C++ standard class.
+ */
+ inline void setTimeZone(const LogString& timeZone)
+ { this->timeZoneID.assign(timeZone); }
+
+ /**
+ Returns value of the <b>TimeZone</b> option.
+ */
+ inline const LogString& getTimeZone() const
+ { return timeZoneID; }
+
+ void formatDate(LogString &s,
+ const spi::LoggingEventPtr& event,
+ log4cxx::helpers::Pool& p) const;
+
+ private:
+ //
+ // prevent copy and assignment
+ DateLayout(const DateLayout&);
+ DateLayout& operator=(const DateLayout&);
+
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif // _LOG4CXX_HELPERS_DATE_LAYOUT_H
diff --git a/src/main/include/log4cxx/helpers/datetimedateformat.h b/src/main/include/log4cxx/helpers/datetimedateformat.h
new file mode 100644
index 0000000..1ed8988
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/datetimedateformat.h
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_DATE_TIME_DATE_FORMAT_H
+#define _LOG4CXX_HELPERS_DATE_TIME_DATE_FORMAT_H
+
+#include <log4cxx/helpers/simpledateformat.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /**
+ Formats a date in the format <b>dd MMM yyyy HH:mm:ss,SSS</b> for example,
+ "06 Nov 1994 15:49:37,459".
+ */
+ class LOG4CXX_EXPORT DateTimeDateFormat : public SimpleDateFormat
+ {
+ public:
+ DateTimeDateFormat()
+ : SimpleDateFormat(LOG4CXX_STR("dd MMM yyyy HH:mm:ss,SSS")) {}
+ DateTimeDateFormat(const std::locale* locale)
+ : SimpleDateFormat(LOG4CXX_STR("dd MMM yyyy HH:mm:ss,SSS"), locale) {}
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif // _LOG4CXX_HELPERS_DATE_TIME_DATE_FORMAT_H
diff --git a/src/main/include/log4cxx/helpers/exception.h b/src/main/include/log4cxx/helpers/exception.h
new file mode 100644
index 0000000..fb1daf5
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/exception.h
@@ -0,0 +1,287 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_EXCEPTION_H
+#define _LOG4CXX_HELPERS_EXCEPTION_H
+
+#include <exception>
+#include <log4cxx/log4cxx.h>
+#include <log4cxx/logstring.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /** The class Exception and its subclasses indicate conditions that a
+ reasonable application might want to catch.
+ */
+ class LOG4CXX_EXPORT Exception : public ::std::exception
+ {
+ public:
+ Exception(const char* msg);
+ Exception(const LogString& msg);
+ Exception(const Exception& src);
+ Exception& operator=(const Exception& src);
+ const char* what() const throw();
+ private:
+ enum { MSG_SIZE = 128 };
+ char msg[MSG_SIZE + 1];
+ }; // class Exception
+
+ /** RuntimeException is the parent class of those exceptions that can be
+ thrown during the normal operation of the process.
+ */
+ class LOG4CXX_EXPORT RuntimeException : public Exception
+ {
+ public:
+ RuntimeException(log4cxx_status_t stat);
+ RuntimeException(const LogString& msg);
+ RuntimeException(const RuntimeException& msg);
+ RuntimeException& operator=(const RuntimeException& src);
+ private:
+ static LogString formatMessage(log4cxx_status_t stat);
+ }; // class RuntimeException
+
+ /** Thrown when an application attempts to use null in a case where an
+ object is required.
+ */
+ class LOG4CXX_EXPORT NullPointerException : public RuntimeException
+ {
+ public:
+ NullPointerException(const LogString& msg);
+ NullPointerException(const NullPointerException& msg);
+ NullPointerException& operator=(const NullPointerException& src);
+ }; // class NullPointerException
+
+ /** Thrown to indicate that a method has been passed
+ an illegal or inappropriate argument.*/
+ class LOG4CXX_EXPORT IllegalArgumentException : public RuntimeException
+ {
+ public:
+ IllegalArgumentException(const LogString& msg);
+ IllegalArgumentException(const IllegalArgumentException&);
+ IllegalArgumentException& operator=(const IllegalArgumentException&);
+ }; // class IllegalArgumentException
+
+ /** Signals that an I/O exception of some sort has occurred. This class
+ is the general class of exceptions produced by failed or interrupted
+ I/O operations.
+ */
+ class LOG4CXX_EXPORT IOException : public Exception
+ {
+ public:
+ IOException();
+ IOException(log4cxx_status_t stat);
+ IOException(const LogString& msg);
+ IOException(const IOException &src);
+ IOException& operator=(const IOException&);
+ private:
+ static LogString formatMessage(log4cxx_status_t stat);
+ };
+
+ class LOG4CXX_EXPORT MissingResourceException : public Exception
+ {
+ public:
+ MissingResourceException(const LogString& key);
+ MissingResourceException(const MissingResourceException &src);
+ MissingResourceException& operator=(const MissingResourceException&);
+ private:
+ static LogString formatMessage(const LogString& key);
+ };
+
+ class LOG4CXX_EXPORT PoolException : public Exception
+ {
+ public:
+ PoolException(log4cxx_status_t stat);
+ PoolException(const PoolException &src);
+ PoolException& operator=(const PoolException&);
+ private:
+ static LogString formatMessage(log4cxx_status_t stat);
+ };
+
+
+ class LOG4CXX_EXPORT MutexException : public Exception
+ {
+ public:
+ MutexException(log4cxx_status_t stat);
+ MutexException(const MutexException &src);
+ MutexException& operator=(const MutexException&);
+ private:
+ static LogString formatMessage(log4cxx_status_t stat);
+ };
+
+ class LOG4CXX_EXPORT InterruptedException : public Exception
+ {
+ public:
+ InterruptedException();
+ InterruptedException(log4cxx_status_t stat);
+ InterruptedException(const InterruptedException &src);
+ InterruptedException& operator=(const InterruptedException&);
+ private:
+ static LogString formatMessage(log4cxx_status_t stat);
+ };
+
+ class LOG4CXX_EXPORT ThreadException
+ : public Exception {
+ public:
+ ThreadException(log4cxx_status_t stat);
+ ThreadException(const LogString& msg);
+ ThreadException(const ThreadException &src);
+ ThreadException& operator=(const ThreadException&);
+ private:
+ static LogString formatMessage(log4cxx_status_t stat);
+ };
+
+ class LOG4CXX_EXPORT TranscoderException : public Exception
+ {
+ public:
+ TranscoderException(log4cxx_status_t stat);
+ TranscoderException(const TranscoderException &src);
+ TranscoderException& operator=(const TranscoderException&);
+ private:
+ static LogString formatMessage(log4cxx_status_t stat);
+ };
+
+ class LOG4CXX_EXPORT IllegalMonitorStateException
+ : public Exception {
+ public:
+ IllegalMonitorStateException(const LogString& msg);
+ IllegalMonitorStateException(const IllegalMonitorStateException& msg);
+ IllegalMonitorStateException& operator=(const IllegalMonitorStateException& msg);
+ };
+
+ /**
+ Thrown when an application tries to create an instance of a class using
+ the newInstance method in class Class, but the specified class object
+ cannot be instantiated because it is an interface or is an abstract class.
+ */
+ class LOG4CXX_EXPORT InstantiationException : public Exception
+ {
+ public:
+ InstantiationException(const LogString& msg);
+ InstantiationException(const InstantiationException& msg);
+ InstantiationException& operator=(const InstantiationException& msg);
+ };
+
+ /**
+ Thrown when an application tries to load in a class through its
+ string name but no definition for the class with the specified name
+ could be found.
+ */
+ class LOG4CXX_EXPORT ClassNotFoundException : public Exception
+ {
+ public:
+ ClassNotFoundException(const LogString& className);
+ ClassNotFoundException(const ClassNotFoundException& msg);
+ ClassNotFoundException& operator=(const ClassNotFoundException& msg);
+ private:
+ static LogString formatMessage(const LogString& className);
+ };
+
+
+ class NoSuchElementException : public Exception {
+ public:
+ NoSuchElementException();
+ NoSuchElementException(const NoSuchElementException&);
+ NoSuchElementException& operator=(const NoSuchElementException&);
+ };
+
+ class IllegalStateException : public Exception {
+ public:
+ IllegalStateException();
+ IllegalStateException(const IllegalStateException&);
+ IllegalStateException& operator=(const IllegalStateException&);
+ };
+
+ /** Thrown to indicate that there is an error in the underlying
+ protocol, such as a TCP error.
+ */
+ class LOG4CXX_EXPORT SocketException : public IOException
+ {
+ public:
+ SocketException(const LogString& msg);
+ SocketException(log4cxx_status_t status);
+ SocketException(const SocketException&);
+ SocketException& operator=(const SocketException&);
+ };
+
+ /** Signals that an error occurred while attempting to connect a socket
+ to a remote address and port. Typically, the connection was refused
+ remotely (e.g., no process is listening on the remote address/port).
+ */
+ class LOG4CXX_EXPORT ConnectException : public SocketException
+ {
+ public:
+ ConnectException(log4cxx_status_t status);
+ ConnectException(const ConnectException& src);
+ ConnectException& operator=(const ConnectException&);
+ };
+
+ class LOG4CXX_EXPORT ClosedChannelException : public SocketException
+ {
+ public:
+ ClosedChannelException();
+ ClosedChannelException(const ClosedChannelException& src);
+ ClosedChannelException& operator=(const ClosedChannelException&);
+ };
+
+ /** Signals that an error occurred while attempting to bind a socket to
+ a local address and port. Typically, the port is in use, or the
+ requested local address could not be assigned.
+ */
+ class LOG4CXX_EXPORT BindException : public SocketException
+ {
+ public:
+ BindException(log4cxx_status_t status);
+ BindException(const BindException&);
+ BindException& operator=(const BindException&);
+ };
+
+ /** Signals that an I/O operation has been interrupted. An
+ InterruptedIOException is thrown to indicate that an input or output
+ transfer has been terminated because the thread performing it was
+ interrupted. The field bytesTransferred indicates how many bytes were
+ successfully transferred before the interruption occurred.
+ */
+ class LOG4CXX_EXPORT InterruptedIOException : public IOException
+ {
+ public:
+ InterruptedIOException(const LogString& msg);
+ InterruptedIOException(const InterruptedIOException&);
+ InterruptedIOException& operator=(const InterruptedIOException&);
+ };
+
+
+ /** Signals that an I/O operation has been interrupted. An
+ InterruptedIOException is thrown to indicate that an input or output
+ transfer has been terminated because the thread performing it was
+ interrupted. The field bytesTransferred indicates how many bytes were
+ successfully transferred before the interruption occurred.
+ */
+ class LOG4CXX_EXPORT SocketTimeoutException : public InterruptedIOException
+ {
+ public:
+ SocketTimeoutException();
+ SocketTimeoutException(const SocketTimeoutException&);
+ SocketTimeoutException& operator=(const SocketTimeoutException&);
+ };
+
+
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif // _LOG4CXX_HELPERS_EXCEPTION_H
diff --git a/src/main/include/log4cxx/helpers/fileinputstream.h b/src/main/include/log4cxx/helpers/fileinputstream.h
new file mode 100644
index 0000000..fdf658a
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/fileinputstream.h
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_FILEINPUTSTREAM_H
+#define _LOG4CXX_HELPERS_FILEINPUTSTREAM_H
+
+#include <log4cxx/helpers/inputstream.h>
+#include <log4cxx/file.h>
+#include <log4cxx/helpers/pool.h>
+
+
+namespace log4cxx
+{
+
+ namespace helpers {
+
+ /**
+ * InputStream implemented on top of APR file IO.
+ *
+ */
+ class LOG4CXX_EXPORT FileInputStream : public InputStream
+ {
+ private:
+ Pool pool;
+ apr_file_t* fileptr;
+
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(FileInputStream)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(FileInputStream)
+ LOG4CXX_CAST_ENTRY_CHAIN(InputStream)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Creates a FileInputStream by opening a connection to an actual
+ * file, the file named by the path name name in the file system.
+ *
+ * @param filename The system-dependent file name.
+ */
+ FileInputStream(const LogString& filename);
+ FileInputStream(const logchar* filename);
+
+ /**
+ * Creates a FileInputStream by opening a connection to an actual
+ * file, the file named by the File object file in the file system.
+ *
+ * @param aFile The file to be opened for reading.
+ */
+ FileInputStream(const File& aFile);
+
+ virtual ~FileInputStream();
+
+ /**
+ * Closes this file input stream and releases any system
+ * resources associated with the stream.
+ */
+ virtual void close();
+
+ /**
+ * Reads a sequence of bytes into the given buffer.
+ *
+ * @param buf The buffer into which bytes are to be transferred.
+ * @return the total number of bytes read into the buffer, or -1 if there
+ * is no more data because the end of the stream has been reached.
+ */
+ virtual int read(ByteBuffer& buf);
+
+ private:
+
+ FileInputStream(const FileInputStream&);
+
+ FileInputStream& operator=(const FileInputStream&);
+ void open(const LogString&);
+
+ };
+
+ LOG4CXX_PTR_DEF(FileInputStream);
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_FILEINPUTSTREAM_H
diff --git a/src/main/include/log4cxx/helpers/fileoutputstream.h b/src/main/include/log4cxx/helpers/fileoutputstream.h
new file mode 100644
index 0000000..b9e405a
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/fileoutputstream.h
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_FILEOUTPUTSTREAM_H
+#define _LOG4CXX_HELPERS_FILEOUTPUTSTREAM_H
+
+#include <log4cxx/helpers/outputstream.h>
+#include <log4cxx/file.h>
+#include <log4cxx/helpers/pool.h>
+
+
+namespace log4cxx
+{
+
+ namespace helpers {
+
+ /**
+ * OutputStream implemented on top of APR file IO.
+ */
+ class LOG4CXX_EXPORT FileOutputStream : public OutputStream
+ {
+ private:
+ Pool pool;
+ apr_file_t* fileptr;
+
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(FileOutputStream)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(FileOutputStream)
+ LOG4CXX_CAST_ENTRY_CHAIN(OutputStream)
+ END_LOG4CXX_CAST_MAP()
+
+ FileOutputStream(const LogString& filename, bool append = false);
+ FileOutputStream(const logchar* filename, bool append = false);
+ virtual ~FileOutputStream();
+
+ virtual void close(Pool& p);
+ virtual void flush(Pool& p);
+ virtual void write(ByteBuffer& buf, Pool& p);
+
+ private:
+ FileOutputStream(const FileOutputStream&);
+ FileOutputStream& operator=(const FileOutputStream&);
+ static apr_file_t* open(const LogString& fn, bool append,
+ log4cxx::helpers::Pool& p);
+ };
+
+ LOG4CXX_PTR_DEF(FileOutputStream);
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_FILEOUTPUTSTREAM_H
diff --git a/src/main/include/log4cxx/helpers/filewatchdog.h b/src/main/include/log4cxx/helpers/filewatchdog.h
new file mode 100644
index 0000000..0b8aa65
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/filewatchdog.h
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_FILEWATCHDOG_H
+#define _LOG4CXX_HELPERS_FILEWATCHDOG_H
+
+#include <log4cxx/logstring.h>
+#include <time.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/thread.h>
+#include <log4cxx/file.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+
+ /**
+ Check every now and then that a certain file has not changed. If it
+ has, then call the #doOnChange method.
+ */
+ class LOG4CXX_EXPORT FileWatchdog
+ {
+ public:
+ virtual ~FileWatchdog();
+ /**
+ The default delay between every file modification check, set to 60
+ seconds. */
+ static long DEFAULT_DELAY /*= 60000*/;
+
+ protected:
+ /**
+ The name of the file to observe for changes.
+ */
+ File file;
+
+ /**
+ The delay to observe between every check.
+ By default set DEFAULT_DELAY.*/
+ long delay;
+ log4cxx_time_t lastModif;
+ bool warnedAlready;
+ volatile unsigned int interrupted;
+
+ protected:
+ FileWatchdog(const File& filename);
+ virtual void doOnChange() = 0;
+ void checkAndConfigure();
+
+ public:
+ /**
+ Set the delay to observe between each check of the file changes.
+ */
+ void setDelay(long delay1)
+ { this->delay = delay1; }
+
+ void start();
+
+ private:
+ static void* LOG4CXX_THREAD_FUNC run(apr_thread_t* thread, void* data);
+ Pool pool;
+ Thread thread;
+
+ FileWatchdog(const FileWatchdog&);
+ FileWatchdog& operator=(const FileWatchdog&);
+
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+
+#endif // _LOG4CXX_HELPERS_FILEWATCHDOG_H
diff --git a/src/main/include/log4cxx/helpers/inetaddress.h b/src/main/include/log4cxx/helpers/inetaddress.h
new file mode 100644
index 0000000..155205e
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/inetaddress.h
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPER_INETADDRESS_H
+#define _LOG4CXX_HELPER_INETADDRESS_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/logstring.h>
+#include <vector>
+#include <log4cxx/helpers/exception.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class LOG4CXX_EXPORT UnknownHostException : public Exception
+ {
+ public:
+ UnknownHostException(const LogString& msg);
+ UnknownHostException(const UnknownHostException& src);
+ UnknownHostException& operator=(const UnknownHostException& src);
+ };
+
+
+ class InetAddress;
+ LOG4CXX_PTR_DEF(InetAddress);
+ LOG4CXX_LIST_DEF(InetAddressList, InetAddressPtr);
+
+ class LOG4CXX_EXPORT InetAddress : public ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(InetAddress)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(InetAddress)
+ END_LOG4CXX_CAST_MAP()
+
+ InetAddress(const LogString& hostName, const LogString& hostAddr);
+
+ /** Determines all the IP addresses of a host, given the host's name.
+ */
+ static InetAddressList getAllByName(const LogString& host);
+
+ /** Determines the IP address of a host, given the host's name.
+ */
+ static InetAddressPtr getByName(const LogString& host);
+
+ /** Returns the IP address string "%d.%d.%d.%d".
+ */
+ LogString getHostAddress() const;
+
+ /** Gets the host name for this IP address.
+ */
+ LogString getHostName() const;
+
+ /** Returns the local host.
+ */
+ static InetAddressPtr getLocalHost();
+
+ /** Returns an InetAddress which can be used as any
+ * address, for example when listening on a port from any
+ * remote addresss.
+ */
+ static InetAddressPtr anyAddress();
+
+ /** Converts this IP address to a String.
+ */
+ LogString toString() const;
+
+ private:
+ LogString ipAddrString;
+
+ LogString hostNameString;
+
+ }; // class InetAddress
+ } // namespace helpers
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+#endif // _LOG4CXX_HELPER_INETADDRESS_H
+
diff --git a/src/main/include/log4cxx/helpers/inputstream.h b/src/main/include/log4cxx/helpers/inputstream.h
new file mode 100644
index 0000000..585d4f0
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/inputstream.h
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_INPUTSTREAM_H
+#define _LOG4CXX_HELPERS_INPUTSTREAM_H
+
+#include <log4cxx/helpers/objectimpl.h>
+
+namespace log4cxx
+{
+
+ namespace helpers {
+ class ByteBuffer;
+
+ /**
+ * Abstract class for reading from character streams.
+ *
+ */
+ class LOG4CXX_EXPORT InputStream : public ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(InputStream)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(InputStream)
+ END_LOG4CXX_CAST_MAP()
+
+ protected:
+ InputStream();
+
+ virtual ~InputStream();
+
+ public:
+ /**
+ * Reads a sequence of bytes into the given buffer.
+ *
+ * @param dst The buffer into which bytes are to be transferred.
+ * @return the total number of bytes read into the buffer, or -1 if there
+ * is no more data because the end of the stream has been reached.
+ */
+ virtual int read(ByteBuffer& dst) = 0;
+
+ /**
+ * Closes this input stream and releases any system
+ * resources associated with the stream.
+ */
+ virtual void close() = 0;
+
+ private:
+ InputStream(const InputStream&);
+ InputStream& operator=(const InputStream&);
+ };
+
+ LOG4CXX_PTR_DEF(InputStream);
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_INPUTSTREAM_H
diff --git a/src/main/include/log4cxx/helpers/inputstreamreader.h b/src/main/include/log4cxx/helpers/inputstreamreader.h
new file mode 100644
index 0000000..1f186d9
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/inputstreamreader.h
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_INPUTSTREAMREADER_H
+#define _LOG4CXX_HELPERS_INPUTSTREAMREADER_H
+
+#include <log4cxx/helpers/reader.h>
+#include <log4cxx/helpers/inputstream.h>
+#include <log4cxx/helpers/charsetdecoder.h>
+
+namespace log4cxx
+{
+
+ namespace helpers {
+
+ /**
+ * Class for reading from character streams.
+ * Decorates a byte based InputStream and provides appropriate
+ * conversion to characters.
+ */
+ class LOG4CXX_EXPORT InputStreamReader : public Reader
+ {
+ private:
+ InputStreamPtr in;
+ CharsetDecoderPtr dec;
+
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(InputStreamReader)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(InputStreamReader)
+ LOG4CXX_CAST_ENTRY_CHAIN(Reader)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Creates an InputStreamReader that uses the default charset.
+ *
+ * @param in The input stream to decorate.
+ */
+ InputStreamReader(const InputStreamPtr& in);
+
+ /**
+ * Creates an InputStreamReader that uses the given charset decoder.
+ *
+ * @param in The input stream to decorate.
+ * @param enc The charset decoder to use for the conversion.
+ */
+ InputStreamReader(const InputStreamPtr& in, const CharsetDecoderPtr &enc);
+
+ ~InputStreamReader();
+
+ /**
+ * Closes the stream.
+ *
+ * @param p The memory pool associated with the reader.
+ */
+ virtual void close(Pool& p);
+
+ /**
+ * @return The complete stream contents as a LogString.
+ * @param p The memory pool associated with the reader.
+ */
+ virtual LogString read(Pool& p);
+
+ /**
+ * @return The name of the character encoding being used by this stream.
+ */
+ LogString getEncoding() const;
+
+ private:
+ InputStreamReader(const InputStreamReader&);
+
+ InputStreamReader& operator=(const InputStreamReader&);
+ };
+
+ LOG4CXX_PTR_DEF(InputStreamReader);
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_INPUTSTREAMREADER_H
diff --git a/src/main/include/log4cxx/helpers/integer.h b/src/main/include/log4cxx/helpers/integer.h
new file mode 100644
index 0000000..957edb0
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/integer.h
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_INTEGER_H
+#define _LOG4CXX_HELPERS_INTEGER_H
+
+#include <log4cxx/helpers/objectimpl.h>
+
+
+namespace log4cxx {
+ namespace helpers {
+ class LOG4CXX_EXPORT Integer : public ObjectImpl {
+ const int val;
+ public:
+ DECLARE_LOG4CXX_OBJECT(Integer)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(Integer)
+ END_LOG4CXX_CAST_MAP()
+
+ Integer();
+ Integer(int i);
+ virtual ~Integer();
+
+ inline int intValue() const {
+ return val;
+ }
+
+ };
+
+ LOG4CXX_PTR_DEF(Integer);
+
+ }
+}
+
+
+#endif
diff --git a/src/main/include/log4cxx/helpers/iso8601dateformat.h b/src/main/include/log4cxx/helpers/iso8601dateformat.h
new file mode 100644
index 0000000..b4e7e6e
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/iso8601dateformat.h
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_ISO_8601_DATE_FORMAT_H
+#define _LOG4CXX_HELPERS_ISO_8601_DATE_FORMAT_H
+
+#include <log4cxx/helpers/simpledateformat.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /**
+ Formats a date in the format <b>yyyy-MM-dd HH:mm:ss,SSS</b> for example
+ "1999-11-27 15:49:37,459".
+
+ <p>Refer to the
+ <a href=http://www.cl.cam.ac.uk/~mgk25/iso-time.html>summary of the
+ International Standard Date and Time Notation</a> for more
+ information on this format.
+ */
+ class LOG4CXX_EXPORT ISO8601DateFormat : public SimpleDateFormat
+ {
+ public:
+ ISO8601DateFormat()
+ : SimpleDateFormat(LOG4CXX_STR("yyyy-MM-dd HH:mm:ss,SSS")) {}
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif // _LOG4CXX_HELPERS_ISO_8601_DATE_FORMAT_H
+
diff --git a/src/main/include/log4cxx/helpers/loader.h b/src/main/include/log4cxx/helpers/loader.h
new file mode 100644
index 0000000..613b323
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/loader.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_LOADER_H
+#define _LOG4CXX_HELPERS_LOADER_H
+
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/inputstream.h>
+
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class Class;
+
+ class LOG4CXX_EXPORT Loader
+ {
+ public:
+ static const Class& loadClass(const LogString& clazz);
+
+ static InputStreamPtr getResourceAsStream(
+ const LogString& name);
+ };
+ } // namespace helpers
+} // namespace log4cxx
+#endif //_LOG4CXX_HELPERS_LOADER_H
diff --git a/src/main/include/log4cxx/helpers/locale.h b/src/main/include/log4cxx/helpers/locale.h
new file mode 100644
index 0000000..6b0c881
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/locale.h
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_LOCALE_H
+#define _LOG4CXX_HELPERS_LOCALE_H
+
+#include <log4cxx/logstring.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class LOG4CXX_EXPORT Locale
+ {
+ public:
+ Locale(const LogString& language);
+ Locale(const LogString& language, const LogString& country);
+ Locale(const LogString& language, const LogString& country,
+ const LogString& variant);
+
+ const LogString& getLanguage() const;
+ const LogString& getCountry() const;
+ const LogString& getVariant() const;
+
+ protected:
+ Locale(const Locale&);
+ Locale& operator=(const Locale&);
+ const LogString language;
+ const LogString country;
+ const LogString variant;
+ }; // class Locale
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif // _LOG4CXX_HELPERS_LOCALE_H
diff --git a/src/main/include/log4cxx/helpers/loglog.h b/src/main/include/log4cxx/helpers/loglog.h
new file mode 100644
index 0000000..3c1f133
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/loglog.h
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_LOG_LOG_H
+#define _LOG4CXX_HELPERS_LOG_LOG_H
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/mutex.h>
+#include <exception>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /**
+ This class used to output log statements from within the log4cxx package.
+
+ <p>Log4cxx components cannot make log4cxx logging calls. However, it is
+ sometimes useful for the user to learn about what log4cxx is
+ doing. You can enable log4cxx internal logging by calling the
+ <b>#setInternalDebugging</b> method.
+
+ <p>All log4cxx internal debug calls go to standard output
+ where as internal error messages are sent to
+ standard error output. All internal messages are prepended with
+ the string "log4cxx: ".
+ */
+ class LOG4CXX_EXPORT LogLog
+ {
+ private:
+ bool debugEnabled;
+
+ /**
+ In quietMode not even errors generate any output.
+ */
+ bool quietMode;
+ Mutex mutex;
+ LogLog();
+ LogLog(const LogLog&);
+ LogLog& operator=(const LogLog&);
+ static LogLog& getInstance();
+
+
+ public:
+ /**
+ Allows to enable/disable log4cxx internal logging.
+ */
+ static void setInternalDebugging(bool enabled);
+
+ /**
+ This method is used to output log4cxx internal debug
+ statements. Output goes to the standard output.
+ */
+ static void debug(const LogString& msg);
+ static void debug(const LogString& msg, const std::exception& e);
+
+
+ /**
+ This method is used to output log4cxx internal error
+ statements. There is no way to disable error statements.
+ Output goes to stderr.
+ */
+ static void error(const LogString& msg);
+ static void error(const LogString& msg, const std::exception& e);
+
+
+ /**
+ In quiet mode LogLog generates strictly no output, not even
+ for errors.
+
+ @param quietMode <code>true</code> for no output.
+ */
+ static void setQuietMode(bool quietMode);
+
+ /**
+ This method is used to output log4cxx internal warning
+ statements. There is no way to disable warning statements.
+ Output goes to stderr.
+ */
+ static void warn(const LogString& msg);
+ static void warn(const LogString& msg, const std::exception& e);
+
+ private:
+ static void emit(const LogString& msg);
+ static void emit(const std::exception& ex);
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#define LOGLOG_DEBUG(log) { \
+ log4cxx::helpers::LogLog::debug(log) ; }
+
+#define LOGLOG_WARN(log) { \
+ log4cxx::helpers::LogLog::warn(log) ; }
+
+#define LOGLOG_ERROR(log) { \
+ log4cxx::helpers::LogLog::warn(log); }
+
+#endif //_LOG4CXX_HELPERS_LOG_LOG_H
diff --git a/src/main/include/log4cxx/helpers/messagebuffer.h b/src/main/include/log4cxx/helpers/messagebuffer.h
new file mode 100644
index 0000000..c026dc5
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/messagebuffer.h
@@ -0,0 +1,828 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_MESSAGE_BUFFER_H
+#define _LOG4CXX_MESSAGE_BUFFER_H
+
+#include <log4cxx/log4cxx.h>
+#include <log4cxx/logstring.h>
+#include <sstream>
+
+namespace log4cxx {
+
+
+ namespace helpers {
+
+ typedef std::ios_base& (*ios_base_manip)(std::ios_base&);
+
+ /**
+ * This class is used by the LOG4CXX_INFO and similar
+ * macros to support insertion operators in the message parameter.
+ * The class is not intended for use outside of that context.
+ */
+ class LOG4CXX_EXPORT CharMessageBuffer {
+ public:
+ /**
+ * Creates a new instance.
+ */
+ CharMessageBuffer();
+ /**
+ * Destructor.
+ */
+ ~CharMessageBuffer();
+
+
+ /**
+ * Appends string to buffer.
+ * @param msg string append.
+ * @return this buffer.
+ */
+ CharMessageBuffer& operator<<(const std::basic_string<char>& msg);
+ /**
+ * Appends string to buffer.
+ * @param msg string to append.
+ * @return this buffer.
+ */
+ CharMessageBuffer& operator<<(const char* msg);
+ /**
+ * Appends string to buffer.
+ * @param msg string to append.
+ * @return this buffer.
+ */
+ CharMessageBuffer& operator<<(char* msg);
+
+ /**
+ * Appends character to buffer.
+ * @param msg character to append.
+ * @return this buffer.
+ */
+ CharMessageBuffer& operator<<(const char msg);
+
+ /**
+ * Insertion operator for STL manipulators such as std::fixed.
+ * @param manip manipulator.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(ios_base_manip manip);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(bool val);
+
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(short val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(int val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(unsigned int val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(long val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(unsigned long val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(float val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(double val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(long double val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(void* val);
+
+ /**
+ * Cast to ostream.
+ */
+ operator std::basic_ostream<char>&();
+
+ /**
+ * Get content of buffer.
+ * @param os used only to signal that
+ * the embedded stream was used.
+ */
+ const std::basic_string<char>& str(std::basic_ostream<char>& os);
+
+ /**
+ * Get content of buffer.
+ * @param buf used only to signal that
+ * the embedded stream was not used.
+ */
+ const std::basic_string<char>& str(CharMessageBuffer& buf);
+
+ /**
+ * Returns true if buffer has an encapsulated STL stream.
+ * @return true if STL stream was created.
+ */
+ bool hasStream() const;
+
+ private:
+ /**
+ * Prevent use of default copy constructor.
+ */
+ CharMessageBuffer(const CharMessageBuffer&);
+ /**
+ * Prevent use of default assignment operator.
+ */
+ CharMessageBuffer& operator=(const CharMessageBuffer&);
+
+ /**
+ * Encapsulated std::string.
+ */
+ std::basic_string<char> buf;
+ /**
+ * Encapsulated stream, created on demand.
+ */
+ std::basic_ostringstream<char>* stream;
+ };
+
+template<class V>
+std::basic_ostream<char>& operator<<(CharMessageBuffer& os, const V& val) {
+ return ((std::basic_ostream<char>&) os) << val;
+}
+
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API || LOG4CXX_LOGCHAR_IS_UNICHAR
+ /**
+ * This class is designed to support insertion operations
+ * in the message argument to the LOG4CXX_INFO and similar
+ * macros and is not designed for general purpose use.
+ */
+ class LOG4CXX_EXPORT UniCharMessageBuffer {
+ public:
+ /**
+ * Creates a new instance.
+ */
+ UniCharMessageBuffer();
+ /**
+ * Destructor.
+ */
+ ~UniCharMessageBuffer();
+
+ typedef std::basic_ostream<UniChar> uostream;
+
+
+ /**
+ * Appends string to buffer.
+ * @param msg string append.
+ * @return this buffer.
+ */
+ UniCharMessageBuffer& operator<<(const std::basic_string<UniChar>& msg);
+ /**
+ * Appends string to buffer.
+ * @param msg string to append.
+ * @return this buffer.
+ */
+ UniCharMessageBuffer& operator<<(const UniChar* msg);
+ /**
+ * Appends string to buffer.
+ * @param msg string to append.
+ * @return this buffer.
+ */
+ UniCharMessageBuffer& operator<<(UniChar* msg);
+
+ /**
+ * Appends character to buffer.
+ * @param msg character to append.
+ * @return this buffer.
+ */
+ UniCharMessageBuffer& operator<<(const UniChar msg);
+
+#if LOG4CXX_CFSTRING_API
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ UniCharMessageBuffer& operator<<(const CFStringRef& msg);
+#endif
+
+ /**
+ * Insertion operator for STL manipulators such as std::fixed.
+ * @param manip manipulator.
+ * @return encapsulated STL stream.
+ */
+ uostream& operator<<(ios_base_manip manip);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ uostream& operator<<(bool val);
+
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ uostream& operator<<(short val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ uostream& operator<<(int val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ uostream& operator<<(unsigned int val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ uostream& operator<<(long val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ uostream& operator<<(unsigned long val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ uostream& operator<<(float val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ uostream& operator<<(double val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ uostream& operator<<(long double val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ uostream& operator<<(void* val);
+
+
+ /**
+ * Cast to ostream.
+ */
+ operator uostream&();
+
+ /**
+ * Get content of buffer.
+ * @param os used only to signal that
+ * the embedded stream was used.
+ */
+ const std::basic_string<UniChar>& str(uostream& os);
+
+ /**
+ * Get content of buffer.
+ * @param buf used only to signal that
+ * the embedded stream was not used.
+ */
+ const std::basic_string<UniChar>& str(UniCharMessageBuffer& buf);
+
+ /**
+ * Returns true if buffer has an encapsulated STL stream.
+ * @return true if STL stream was created.
+ */
+ bool hasStream() const;
+
+ private:
+ /**
+ * Prevent use of default copy constructor.
+ */
+ UniCharMessageBuffer(const UniCharMessageBuffer&);
+ /**
+ * Prevent use of default assignment operator.
+ */
+ UniCharMessageBuffer& operator=(const UniCharMessageBuffer&);
+
+ /**
+ * Encapsulated std::string.
+ */
+ std::basic_string<UniChar> buf;
+ /**
+ * Encapsulated stream, created on demand.
+ */
+ std::basic_ostringstream<UniChar>* stream;
+ };
+
+template<class V>
+UniCharMessageBuffer::uostream& operator<<(UniCharMessageBuffer& os, const V& val) {
+ return ((UniCharMessageBuffer::uostream&) os) << val;
+}
+#endif
+
+#if LOG4CXX_WCHAR_T_API
+ /**
+ * This class is designed to support insertion operations
+ * in the message argument to the LOG4CXX_INFO and similar
+ * macros and is not designed for general purpose use.
+ */
+ class LOG4CXX_EXPORT WideMessageBuffer {
+ public:
+ /**
+ * Creates a new instance.
+ */
+ WideMessageBuffer();
+ /**
+ * Destructor.
+ */
+ ~WideMessageBuffer();
+
+
+ /**
+ * Appends string to buffer.
+ * @param msg string append.
+ * @return this buffer.
+ */
+ WideMessageBuffer& operator<<(const std::basic_string<wchar_t>& msg);
+ /**
+ * Appends string to buffer.
+ * @param msg string to append.
+ * @return this buffer.
+ */
+ WideMessageBuffer& operator<<(const wchar_t* msg);
+ /**
+ * Appends string to buffer.
+ * @param msg string to append.
+ * @return this buffer.
+ */
+ WideMessageBuffer& operator<<(wchar_t* msg);
+
+ /**
+ * Appends character to buffer.
+ * @param msg character to append.
+ * @return this buffer.
+ */
+ WideMessageBuffer& operator<<(const wchar_t msg);
+
+ /**
+ * Insertion operator for STL manipulators such as std::fixed.
+ * @param manip manipulator.
+ * @return encapsulated STL stream.
+ */
+ std::basic_ostream<wchar_t>& operator<<(ios_base_manip manip);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::basic_ostream<wchar_t>& operator<<(bool val);
+
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::basic_ostream<wchar_t>& operator<<(short val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::basic_ostream<wchar_t>& operator<<(int val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::basic_ostream<wchar_t>& operator<<(unsigned int val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::basic_ostream<wchar_t>& operator<<(long val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::basic_ostream<wchar_t>& operator<<(unsigned long val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::basic_ostream<wchar_t>& operator<<(float val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::basic_ostream<wchar_t>& operator<<(double val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::basic_ostream<wchar_t>& operator<<(long double val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::basic_ostream<wchar_t>& operator<<(void* val);
+
+
+ /**
+ * Cast to ostream.
+ */
+ operator std::basic_ostream<wchar_t>&();
+
+ /**
+ * Get content of buffer.
+ * @param os used only to signal that
+ * the embedded stream was used.
+ */
+ const std::basic_string<wchar_t>& str(std::basic_ostream<wchar_t>& os);
+
+ /**
+ * Get content of buffer.
+ * @param buf used only to signal that
+ * the embedded stream was not used.
+ */
+ const std::basic_string<wchar_t>& str(WideMessageBuffer& buf);
+
+ /**
+ * Returns true if buffer has an encapsulated STL stream.
+ * @return true if STL stream was created.
+ */
+ bool hasStream() const;
+
+ private:
+ /**
+ * Prevent use of default copy constructor.
+ */
+ WideMessageBuffer(const WideMessageBuffer&);
+ /**
+ * Prevent use of default assignment operator.
+ */
+ WideMessageBuffer& operator=(const WideMessageBuffer&);
+
+ /**
+ * Encapsulated std::string.
+ */
+ std::basic_string<wchar_t> buf;
+ /**
+ * Encapsulated stream, created on demand.
+ */
+ std::basic_ostringstream<wchar_t>* stream;
+ };
+
+template<class V>
+std::basic_ostream<wchar_t>& operator<<(WideMessageBuffer& os, const V& val) {
+ return ((std::basic_ostream<wchar_t>&) os) << val;
+}
+
+ /**
+ * This class is used by the LOG4CXX_INFO and similar
+ * macros to support insertion operators in the message parameter.
+ * The class is not intended for use outside of that context.
+ */
+ class LOG4CXX_EXPORT MessageBuffer {
+ public:
+ /**
+ * Creates a new instance.
+ */
+ MessageBuffer();
+ /**
+ * Destructor.
+ */
+ ~MessageBuffer();
+
+ /**
+ * Cast to ostream.
+ */
+ operator std::ostream&();
+
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ CharMessageBuffer& operator<<(const std::string& msg);
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ CharMessageBuffer& operator<<(const char* msg);
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ CharMessageBuffer& operator<<(char* msg);
+
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ CharMessageBuffer& operator<<(const char msg);
+
+ /**
+ * Get content of buffer.
+ * @param buf used only to signal
+ * the character type and that
+ * the embedded stream was not used.
+ */
+ const std::string& str(CharMessageBuffer& buf);
+
+ /**
+ * Get content of buffer.
+ * @param os used only to signal
+ * the character type and that
+ * the embedded stream was used.
+ */
+ const std::string& str(std::ostream& os);
+
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ WideMessageBuffer& operator<<(const std::wstring& msg);
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ WideMessageBuffer& operator<<(const wchar_t* msg);
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ WideMessageBuffer& operator<<(wchar_t* msg);
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ WideMessageBuffer& operator<<(const wchar_t msg);
+
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ UniCharMessageBuffer& operator<<(const std::basic_string<UniChar>& msg);
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ UniCharMessageBuffer& operator<<(const UniChar* msg);
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ UniCharMessageBuffer& operator<<(UniChar* msg);
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ UniCharMessageBuffer& operator<<(const UniChar msg);
+#endif
+
+#if LOG4CXX_CFSTRING_API
+ /**
+ * Appends a string into the buffer and
+ * fixes the buffer to use char characters.
+ * @param msg message to append.
+ * @return encapsulated CharMessageBuffer.
+ */
+ UniCharMessageBuffer& operator<<(const CFStringRef& msg);
+#endif
+
+ /**
+ * Insertion operator for STL manipulators such as std::fixed.
+ * @param manip manipulator.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(ios_base_manip manip);
+
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(bool val);
+
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(short val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(int val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(unsigned int val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(long val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(unsigned long val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(float val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(double val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(long double val);
+ /**
+ * Insertion operator for built-in type.
+ * @param val build in type.
+ * @return encapsulated STL stream.
+ */
+ std::ostream& operator<<(void* val);
+ /**
+ * Get content of buffer.
+ * @param buf used only to signal
+ * the character type and that
+ * the embedded stream was not used.
+ */
+ const std::wstring& str(WideMessageBuffer& buf);
+
+ /**
+ * Get content of buffer.
+ * @param os used only to signal
+ * the character type and that
+ * the embedded stream was used.
+ */
+ const std::wstring& str(std::basic_ostream<wchar_t>& os);
+
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+ /**
+ * Get content of buffer.
+ * @param buf used only to signal
+ * the character type and that
+ * the embedded stream was not used.
+ */
+ const std::basic_string<UniChar>& str(UniCharMessageBuffer& buf);
+
+ /**
+ * Get content of buffer.
+ * @param os used only to signal
+ * the character type and that
+ * the embedded stream was used.
+ */
+ const std::basic_string<UniChar>& str(UniCharMessageBuffer::uostream& os);
+#endif
+
+ /**
+ * Returns true if buffer has an encapsulated STL stream.
+ * @return true if STL stream was created.
+ */
+ bool hasStream() const;
+
+ private:
+ /**
+ * Prevent use of default copy constructor.
+ */
+ MessageBuffer(const MessageBuffer&);
+ /**
+ * Prevent use of default assignment operator.
+ */
+ MessageBuffer& operator=(const MessageBuffer&);
+
+ /**
+ * Character message buffer.
+ */
+ CharMessageBuffer cbuf;
+
+ /**
+ * Encapsulated wide message buffer, created on demand.
+ */
+ WideMessageBuffer* wbuf;
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+ /**
+ * Encapsulated wide message buffer, created on demand.
+ */
+ UniCharMessageBuffer* ubuf;
+#endif
+ };
+
+template<class V>
+std::ostream& operator<<(MessageBuffer& os, const V& val) {
+ return ((std::ostream&) os) << val;
+}
+
+#if LOG4CXX_LOGCHAR_IS_UTF8
+typedef CharMessageBuffer LogCharMessageBuffer;
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_WCHAR
+typedef WideMessageBuffer LogCharMessageBuffer;
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_UNICHAR
+typedef UniCharMessageBuffer LogCharMessageBuffer;
+#endif
+
+#else
+typedef CharMessageBuffer MessageBuffer;
+typedef CharMessageBuffer LogCharMessageBuffer;
+#endif
+
+}}
+#endif
+
diff --git a/src/main/include/log4cxx/helpers/mutex.h b/src/main/include/log4cxx/helpers/mutex.h
new file mode 100755
index 0000000..d26487b
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/mutex.h
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_MUTEX_H
+#define _LOG4CXX_HELPERS_MUTEX_H
+
+#include <log4cxx/log4cxx.h>
+
+extern "C" {
+ struct apr_thread_mutex_t;
+ struct apr_pool_t;
+}
+
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class Pool;
+
+ class LOG4CXX_EXPORT Mutex
+ {
+ public:
+ Mutex(log4cxx::helpers::Pool& p);
+ Mutex(apr_pool_t* p);
+ ~Mutex();
+ apr_thread_mutex_t* getAPRMutex() const;
+
+ private:
+ Mutex(const Mutex&);
+ Mutex& operator=(const Mutex&);
+ apr_thread_mutex_t* mutex;
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_MUTEX_H
diff --git a/src/main/include/log4cxx/helpers/object.h b/src/main/include/log4cxx/helpers/object.h
new file mode 100644
index 0000000..92d44c5
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/object.h
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_OBJECT_H
+#define _LOG4CXX_HELPERS_OBJECT_H
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/class.h>
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/classregistration.h>
+
+
+#define DECLARE_ABSTRACT_LOG4CXX_OBJECT(object)\
+public:\
+class Clazz##object : public helpers::Class\
+{\
+public:\
+ Clazz##object() : helpers::Class() {}\
+ virtual ~Clazz##object() {}\
+ virtual log4cxx::LogString getName() const { return LOG4CXX_STR(#object); } \
+};\
+virtual const helpers::Class& getClass() const;\
+static const helpers::Class& getStaticClass(); \
+static const log4cxx::helpers::ClassRegistration& registerClass();
+
+#define DECLARE_LOG4CXX_OBJECT(object)\
+public:\
+class Clazz##object : public helpers::Class\
+{\
+public:\
+ Clazz##object() : helpers::Class() {}\
+ virtual ~Clazz##object() {}\
+ virtual log4cxx::LogString getName() const { return LOG4CXX_STR(#object); } \
+ virtual helpers::ObjectPtr newInstance() const\
+ {\
+ return new object();\
+ }\
+};\
+virtual const helpers::Class& getClass() const;\
+static const helpers::Class& getStaticClass(); \
+static const log4cxx::helpers::ClassRegistration& registerClass();
+
+#define DECLARE_LOG4CXX_OBJECT_WITH_CUSTOM_CLASS(object, class)\
+public:\
+virtual const helpers::Class& getClass() const;\
+static const helpers::Class& getStaticClass();\
+static const log4cxx::helpers::ClassRegistration& registerClass();
+
+#define IMPLEMENT_LOG4CXX_OBJECT(object)\
+const log4cxx::helpers::Class& object::getClass() const { return getStaticClass(); }\
+const log4cxx::helpers::Class& object::getStaticClass() { \
+ static Clazz##object theClass; \
+ return theClass; \
+} \
+const log4cxx::helpers::ClassRegistration& object::registerClass() { \
+ static log4cxx::helpers::ClassRegistration classReg(object::getStaticClass); \
+ return classReg; \
+}\
+namespace log4cxx { namespace classes { \
+const log4cxx::helpers::ClassRegistration& object##Registration = object::registerClass(); \
+} }
+
+
+#define IMPLEMENT_LOG4CXX_OBJECT_WITH_CUSTOM_CLASS(object, class)\
+const log4cxx::helpers::Class& object::getClass() const { return getStaticClass(); }\
+const log4cxx::helpers::Class& object::getStaticClass() { \
+ static class theClass; \
+ return theClass; \
+} \
+const log4cxx::helpers::ClassRegistration& object::registerClass() { \
+ static log4cxx::helpers::ClassRegistration classReg(object::getStaticClass); \
+ return classReg; \
+}\
+namespace log4cxx { namespace classes { \
+const log4cxx::helpers::ClassRegistration& object##Registration = object::registerClass(); \
+} }
+
+namespace log4cxx
+{
+ class AppenderSkeleton;
+ class Logger;
+
+ namespace helpers
+ {
+ class Pool;
+
+ /** base class for java-like objects.*/
+ class LOG4CXX_EXPORT Object
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(Object)
+ virtual ~Object() {}
+ virtual void addRef() const = 0;
+ virtual void releaseRef() const = 0;
+ virtual bool instanceof(const Class& clazz) const = 0;
+ virtual const void * cast(const Class& clazz) const = 0;
+ };
+ LOG4CXX_PTR_DEF(Object);
+ }
+}
+
+#define BEGIN_LOG4CXX_CAST_MAP()\
+const void * cast(const helpers::Class& clazz) const\
+{\
+ const void * object = 0;\
+ if (&clazz == &helpers::Object::getStaticClass()) return (const helpers::Object *)this;
+
+#define END_LOG4CXX_CAST_MAP()\
+ return object;\
+}\
+bool instanceof(const helpers::Class& clazz) const\
+{ return cast(clazz) != 0; }
+
+#define LOG4CXX_CAST_ENTRY(Interface)\
+if (&clazz == &Interface::getStaticClass()) return (const Interface *)this;
+
+#define LOG4CXX_CAST_ENTRY2(Interface, interface2)\
+if (&clazz == &Interface::getStaticClass()) return (Interface *)(interface2 *)this;
+
+#define LOG4CXX_CAST_ENTRY_CHAIN(Interface)\
+object = Interface::cast(clazz);\
+if (object != 0) return object;
+
+#endif //_LOG4CXX_HELPERS_OBJECT_H
diff --git a/src/main/include/log4cxx/helpers/objectimpl.h b/src/main/include/log4cxx/helpers/objectimpl.h
new file mode 100644
index 0000000..7de9417
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/objectimpl.h
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_OBJECT_IMPL_H
+#define _LOG4CXX_HELPERS_OBJECT_IMPL_H
+
+#include <log4cxx/helpers/object.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /** Implementation class for Object.*/
+ class LOG4CXX_EXPORT ObjectImpl : public virtual Object
+ {
+ public:
+ ObjectImpl();
+ virtual ~ObjectImpl();
+ void addRef() const;
+ void releaseRef() const;
+
+ protected:
+ mutable unsigned int volatile ref;
+
+ private:
+ //
+ // prevent object copy and assignment
+ //
+ ObjectImpl(const ObjectImpl&);
+ ObjectImpl& operator=(const ObjectImpl&);
+ };
+ }
+}
+
+#endif //_LOG4CXX_HELPERS_OBJECT_IMPL_H
diff --git a/src/main/include/log4cxx/helpers/objectoutputstream.h b/src/main/include/log4cxx/helpers/objectoutputstream.h
new file mode 100644
index 0000000..92f56fe
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/objectoutputstream.h
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_OBJECTOUTPUTSTREAM_H
+#define _LOG4CXX_HELPERS_OBJECTOUTPUTSTREAM_H
+
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/mdc.h>
+#include <log4cxx/helpers/outputstream.h>
+#include <log4cxx/helpers/charsetencoder.h>
+
+namespace log4cxx
+{
+
+ namespace helpers {
+
+ /**
+ * Emulates java serialization.
+ */
+ class LOG4CXX_EXPORT ObjectOutputStream : public ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(ObjectOutputStream)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(ObjectOutputStream)
+ END_LOG4CXX_CAST_MAP()
+
+ ObjectOutputStream(OutputStreamPtr os, Pool& p);
+ virtual ~ObjectOutputStream();
+
+ void close(Pool& p);
+ void flush(Pool& p);
+ void writeObject(const LogString&, Pool& p);
+ void writeUTFString(const std::string&, Pool& p);
+ void writeObject(const MDC::Map& mdc, Pool& p);
+ void writeInt(int val, Pool& p);
+ void writeLong(log4cxx_time_t val, Pool& p);
+ void writeProlog(const char* className,
+ int classDescIncrement,
+ char* bytes,
+ size_t len,
+ Pool& p);
+ void writeNull(Pool& p);
+
+ enum { STREAM_MAGIC = 0xACED };
+ enum { STREAM_VERSION = 5 };
+ enum { TC_NULL = 0x70,
+ TC_REFERENCE = 0x71,
+ TC_CLASSDESC = 0x72,
+ TC_OBJECT = 0x73,
+ TC_STRING = 0x74,
+ TC_ARRAY = 0x75,
+ TC_CLASS = 0x76,
+ TC_BLOCKDATA = 0x77,
+ TC_ENDBLOCKDATA = 0x78 };
+ enum {
+ SC_WRITE_METHOD = 0x01,
+ SC_SERIALIZABLE = 0x02 };
+
+ void writeByte(char val, Pool& p);
+ void writeBytes(const char* bytes, size_t len, Pool& p);
+
+ private:
+ ObjectOutputStream(const ObjectOutputStream&);
+ ObjectOutputStream& operator=(const ObjectOutputStream&);
+
+ OutputStreamPtr os;
+ log4cxx::helpers::CharsetEncoderPtr utf8Encoder;
+ unsigned int objectHandle;
+ typedef std::map<std::string, unsigned int> ClassDescriptionMap;
+ ClassDescriptionMap* classDescriptions;
+ };
+
+ LOG4CXX_PTR_DEF(ObjectOutputStream);
+
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_OUTPUTSTREAM_H
+
diff --git a/src/main/include/log4cxx/helpers/objectptr.h b/src/main/include/log4cxx/helpers/objectptr.h
new file mode 100644
index 0000000..4271ba1
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/objectptr.h
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_OBJECT_PTR_H
+#define _LOG4CXX_HELPERS_OBJECT_PTR_H
+
+#include <log4cxx/log4cxx.h>
+
+//
+// Helgrind (race detection tool for Valgrind) will complain if pointer
+// is not initialized in an atomic operation. Static analysis tools
+// (gcc's -Weffc++, for example) will complain if pointer is not initialized
+// in member initialization list. The use of a macro allows quick
+// switching between the initialization styles.
+//
+#if LOG4CXX_HELGRIND
+#define _LOG4CXX_OBJECTPTR_INIT(x) { exchange(x);
+#else
+#define _LOG4CXX_OBJECTPTR_INIT(x) : p(x) {
+#endif
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class Class;
+
+ class LOG4CXX_EXPORT ObjectPtrBase {
+ public:
+ ObjectPtrBase();
+ virtual ~ObjectPtrBase();
+ static void checkNull(const int& null);
+ static void* exchange(void** destination, void* newValue);
+ virtual void* cast(const Class& cls) const = 0;
+ };
+
+
+ /** smart pointer to a Object descendant */
+ template<typename T> class ObjectPtrT : public ObjectPtrBase
+ {
+ public:
+ ObjectPtrT(const int& null)
+ _LOG4CXX_OBJECTPTR_INIT(0)
+ ObjectPtrBase::checkNull(null);
+ }
+
+ ObjectPtrT()
+ _LOG4CXX_OBJECTPTR_INIT(0)
+ }
+
+ ObjectPtrT(T * p1)
+ _LOG4CXX_OBJECTPTR_INIT(p1)
+ if (this->p != 0)
+ {
+ this->p->addRef();
+ }
+ }
+
+
+ ObjectPtrT(const ObjectPtrT& p1)
+ _LOG4CXX_OBJECTPTR_INIT(p1.p)
+ if (this->p != 0)
+ {
+ this->p->addRef();
+ }
+ }
+
+ ObjectPtrT(const ObjectPtrBase& p1)
+ _LOG4CXX_OBJECTPTR_INIT(reinterpret_cast<T*>(p1.cast(T::getStaticClass())))
+ if (this->p != 0) {
+ this->p->addRef();
+ }
+ }
+
+ ObjectPtrT(ObjectPtrBase& p1)
+ _LOG4CXX_OBJECTPTR_INIT(reinterpret_cast<T*>(p1.cast(T::getStaticClass())))
+ if (this->p != 0) {
+ this->p->addRef();
+ }
+ }
+
+
+ ~ObjectPtrT()
+ {
+ if (p != 0) {
+ p->releaseRef();
+ }
+ }
+
+ ObjectPtrT& operator=(const ObjectPtrT& p1) {
+ T* newPtr = p1.p;
+ if (newPtr != 0) {
+ newPtr->addRef();
+ }
+ T* oldPtr = exchange(newPtr);
+ if (oldPtr != 0) {
+ oldPtr->releaseRef();
+ }
+ return *this;
+ }
+
+ ObjectPtrT& operator=(const int& null) //throw(IllegalArgumentException)
+ {
+ //
+ // throws IllegalArgumentException if null != 0
+ //
+ ObjectPtrBase::checkNull(null);
+ T* oldPtr = exchange(0);
+ if (oldPtr != 0) {
+ oldPtr->releaseRef();
+ }
+ return *this;
+ }
+
+ ObjectPtrT& operator=(T* p1) {
+ if (p1 != 0) {
+ p1->addRef();
+ }
+ T* oldPtr = exchange(p1);
+ if (oldPtr != 0) {
+ oldPtr->releaseRef();
+ }
+ return *this;
+ }
+
+
+ ObjectPtrT& operator=(ObjectPtrBase& p1) {
+ T* newPtr = reinterpret_cast<T*>(p1.cast(T::getStaticClass()));
+ return operator=(newPtr);
+ }
+
+ ObjectPtrT& operator=(const ObjectPtrBase& p1) {
+ T* newPtr = reinterpret_cast<T*>(p1.cast(T::getStaticClass()));
+ return operator=(newPtr);
+ }
+
+ bool operator==(const ObjectPtrT& p1) const { return (this->p == p1.p); }
+ bool operator!=(const ObjectPtrT& p1) const { return (this->p != p1.p); }
+ bool operator<(const ObjectPtrT& p1) const { return (this->p < p1.p); }
+ bool operator==(const T* p1) const { return (this->p == p1); }
+ bool operator!=(const T* p1) const { return (this->p != p1); }
+ bool operator<(const T* p1) const { return (this->p < p1); }
+ T* operator->() const {return p; }
+ T& operator*() const {return *p; }
+ operator T*() const {return p; }
+
+
+
+ private:
+ T * p;
+ virtual void* cast(const Class& cls) const {
+ if (p != 0) {
+ return const_cast<void*>(p->cast(cls));
+ }
+ return 0;
+ }
+ T* exchange(const T* newValue) {
+ return static_cast<T*>(ObjectPtrBase::exchange(
+ reinterpret_cast<void**>(&p),
+ const_cast<T*>(newValue)));
+ }
+
+ };
+
+
+ }
+}
+
+#endif //_LOG4CXX_HELPERS_OBJECT_PTR_H
diff --git a/src/main/include/log4cxx/helpers/onlyonceerrorhandler.h b/src/main/include/log4cxx/helpers/onlyonceerrorhandler.h
new file mode 100644
index 0000000..296aa94
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/onlyonceerrorhandler.h
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_ONLY_ONCE_ERROR_HANDLER_H
+#define _LOG4CXX_HELPERS_ONLY_ONCE_ERROR_HANDLER_H
+
+#include <log4cxx/spi/errorhandler.h>
+#include <log4cxx/helpers/objectimpl.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /**
+ The <code>OnlyOnceErrorHandler</code> implements log4cxx's default
+ error handling policy which consists of emitting a message for the
+ first error in an appender and ignoring all following errors.
+
+ <p>The error message is printed on <code>System.err</code>.
+
+ <p>This policy aims at protecting an otherwise working application
+ from being flooded with error messages when logging fails
+ */
+ class LOG4CXX_EXPORT OnlyOnceErrorHandler :
+ public virtual spi::ErrorHandler,
+ public virtual ObjectImpl
+ {
+ private:
+ LogString WARN_PREFIX;
+ LogString ERROR_PREFIX;
+ mutable bool firstTime;
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(OnlyOnceErrorHandler)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(spi::OptionHandler)
+ LOG4CXX_CAST_ENTRY(spi::ErrorHandler)
+ END_LOG4CXX_CAST_MAP()
+
+ OnlyOnceErrorHandler();
+ void addRef() const;
+ void releaseRef() const;
+
+ /**
+ Does not do anything.
+ */
+ void setLogger(const LoggerPtr& logger);
+
+
+ /**
+ No options to activate.
+ */
+ void activateOptions(log4cxx::helpers::Pool& p);
+ void setOption(const LogString& option, const LogString& value);
+
+
+ /**
+ Prints the message and the stack trace of the exception on
+ <code>System.err</code>. */
+ void error(const LogString& message, const std::exception& e,
+ int errorCode) const;
+ /**
+ Prints the message and the stack trace of the exception on
+ <code>System.err</code>.
+ */
+ void error(const LogString& message, const std::exception& e,
+ int errorCode, const spi::LoggingEventPtr& event) const;
+
+ /**
+ Print a the error message passed as parameter on
+ <code>System.err</code>.
+ */
+ void error(const LogString& message) const;
+
+ /**
+ Does not do anything.
+ */
+ void setAppender(const AppenderPtr& appender);
+
+ /**
+ Does not do anything.
+ */
+ void setBackupAppender(const AppenderPtr& appender);
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_ONLY_ONCE_ERROR_HANDLER_H
+
diff --git a/src/main/include/log4cxx/helpers/optionconverter.h b/src/main/include/log4cxx/helpers/optionconverter.h
new file mode 100644
index 0000000..6b4561c
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/optionconverter.h
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPER_OPTION_CONVERTER_H
+#define _LOG4CXX_HELPER_OPTION_CONVERTER_H
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/objectptr.h>
+
+namespace log4cxx
+{
+ class Level;
+ class File;
+ typedef helpers::ObjectPtrT<Level> LevelPtr;
+
+ namespace spi
+ {
+ class LoggerRepository;
+ typedef helpers::ObjectPtrT<LoggerRepository> LoggerRepositoryPtr;
+ }
+
+ namespace helpers
+ {
+ class Properties;
+
+ class Object;
+ typedef ObjectPtrT<Object> ObjectPtr;
+
+ class Class;
+
+ /** A convenience class to convert property values to specific types.*/
+ class LOG4CXX_EXPORT OptionConverter
+ {
+ /** OptionConverter is a static class. */
+ private:
+ OptionConverter() {}
+
+ public:
+ static LogString convertSpecialChars(const LogString& s);
+
+ /**
+ If <code>value</code> is "true", then <code>true</code> is
+ returned. If <code>value</code> is "false", then
+ <code>true</code> is returned. Otherwise, <code>default</code> is
+ returned.
+
+ <p>Case of value is unimportant.
+ */
+ static bool toBoolean(const LogString& value, bool dEfault);
+ static int toInt(const LogString& value, int dEfault);
+ static long toFileSize(const LogString& value, long dEfault);
+ static LevelPtr toLevel(const LogString& value,
+ const LevelPtr& defaultValue);
+
+ /**
+ Find the value corresponding to <code>key</code> in
+ <code>props</code>. Then perform variable substitution on the
+ found value.
+ */
+ static LogString findAndSubst(const LogString& key, Properties& props);
+
+/**
+Perform variable substitution in string <code>val</code> from the
+values of keys found in the system propeties.
+
+<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 = OptionConverter.substituteVars("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 the
+<code>props</code> parameter is searched, if the value could not
+be found there, then substitution defaults to the empty string.
+
+<p>For example, if system propeties contains no value for the key
+"inexistentKey", then the call
+
+<pre>
+String s = OptionConverter.subsVars("Value of inexistentKey is [${inexistentKey}]");
+</pre>
+will set <code>s</code> to "Value of inexistentKey is []"
+
+<p>An IllegalArgumentException is thrown if
+<code>val</code> contains a start delimeter "${" which is not
+balanced by a stop delimeter "}". </p>
+
+@param val The string on which variable substitution is performed.
+@param props The properties from which variable substitution is performed.
+@throws IllegalArgumentException if <code>val</code> is malformed.
+*/
+ static LogString substVars(const LogString& val, Properties& props);
+
+ /**
+ * Gets the specified system property.
+ @param key The key to search for.
+ @param def The default value to return.
+ @return the string value of the system property, or the default
+ value if there is no property with that key.
+ */
+ static LogString getSystemProperty(const LogString& key, const LogString& def);
+
+ /**
+ Instantiate an object given a class name. Check that the
+ <code>className</code> is a subclass of
+ <code>superClass</code>. If that test fails or the object could
+ not be instantiated, then <code>defaultValue</code> is returned.
+
+ @param className The fully qualified class name of the object to instantiate.
+ @param superClass The class to which the new object should belong.
+ @param defaultValue The object to return in case of non-fulfillment
+ */
+ static ObjectPtr instantiateByClassName(const LogString& className,
+ const Class& superClass, const ObjectPtr& defaultValue);
+
+ static ObjectPtr instantiateByKey(Properties& props,
+ const LogString& key, const Class& superClass,
+ const ObjectPtr& defaultValue);
+
+ /**
+ Configure log4cxx given a configFileName.
+
+ <p>The configFileName must point to a file which will be
+ interpreted by a new instance of a log4cxx configurator.
+
+ <p>All configurations steps are taken on the
+ <code>hierarchy</code> passed as a parameter.
+
+ <p>
+ @param configFileName The location of the configuration file.
+ @param clazz The classname, of the log4cxx configurator which
+ will parse the file <code>configFileName</code>. This must be
+ a subclass of Configurator, or null. If this value is null then
+ a default configurator of PropertyConfigurator is used, unless the
+ filename pointed to by <code>configFileName</code> ends in '.xml',
+ in which case DOMConfigurator is used.
+ @param hierarchy The Hierarchy to act on.
+ */
+ static void selectAndConfigure(const File& configFileName,
+ const LogString& clazz, spi::LoggerRepositoryPtr& hierarchy);
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif //_LOG4CXX_HELPER_OPTION_CONVERTER_H
+
diff --git a/src/main/include/log4cxx/helpers/outputstream.h b/src/main/include/log4cxx/helpers/outputstream.h
new file mode 100644
index 0000000..2c145c8
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/outputstream.h
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_OUTPUTSTREAM_H
+#define _LOG4CXX_HELPERS_OUTPUTSTREAM_H
+
+#include <log4cxx/helpers/objectimpl.h>
+
+namespace log4cxx
+{
+
+ namespace helpers {
+ class ByteBuffer;
+
+ /**
+ * Abstract class for writing to character streams.
+ */
+ class LOG4CXX_EXPORT OutputStream : public ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(OutputStream)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(OutputStream)
+ END_LOG4CXX_CAST_MAP()
+
+ protected:
+ OutputStream();
+ virtual ~OutputStream();
+
+ public:
+ virtual void close(Pool& p) = 0;
+ virtual void flush(Pool& p) = 0;
+ virtual void write(ByteBuffer& buf, Pool& p) = 0;
+
+ private:
+ OutputStream(const OutputStream&);
+ OutputStream& operator=(const OutputStream&);
+ };
+
+ LOG4CXX_PTR_DEF(OutputStream);
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_OUTPUTSTREAM_H
diff --git a/src/main/include/log4cxx/helpers/outputstreamwriter.h b/src/main/include/log4cxx/helpers/outputstreamwriter.h
new file mode 100644
index 0000000..bbcd907
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/outputstreamwriter.h
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_OUTPUTSTREAMWRITER_H
+#define _LOG4CXX_HELPERS_OUTPUTSTREAMWRITER_H
+
+#include <log4cxx/helpers/writer.h>
+#include <log4cxx/helpers/outputstream.h>
+#include <log4cxx/helpers/charsetencoder.h>
+
+namespace log4cxx
+{
+
+ namespace helpers {
+
+ /**
+ * Abstract class for writing to character streams.
+ */
+ class LOG4CXX_EXPORT OutputStreamWriter : public Writer
+ {
+ private:
+ OutputStreamPtr out;
+ CharsetEncoderPtr enc;
+
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(OutputStreamWriter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(OutputStreamWriter)
+ LOG4CXX_CAST_ENTRY_CHAIN(Writer)
+ END_LOG4CXX_CAST_MAP()
+
+ OutputStreamWriter(OutputStreamPtr& out);
+ OutputStreamWriter(OutputStreamPtr& out, CharsetEncoderPtr &enc);
+ ~OutputStreamWriter();
+
+ virtual void close(Pool& p);
+ virtual void flush(Pool& p);
+ virtual void write(const LogString& str, Pool& p);
+ LogString getEncoding() const;
+
+ private:
+ OutputStreamWriter(const OutputStreamWriter&);
+ OutputStreamWriter& operator=(const OutputStreamWriter&);
+ };
+
+ LOG4CXX_PTR_DEF(OutputStreamWriter);
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_OUTPUTSTREAMWRITER_H
diff --git a/src/main/include/log4cxx/helpers/pool.h b/src/main/include/log4cxx/helpers/pool.h
new file mode 100755
index 0000000..2c902f6
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/pool.h
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_POOL_H
+#define _LOG4CXX_HELPERS_POOL_H
+
+#include <log4cxx/log4cxx.h>
+#include <string>
+
+extern "C" {
+ struct apr_pool_t;
+}
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class LOG4CXX_EXPORT Pool
+ {
+ public:
+ Pool();
+ Pool(apr_pool_t* pool, bool release);
+ ~Pool();
+
+ apr_pool_t* getAPRPool();
+ apr_pool_t* create();
+ void* palloc(size_t length);
+ char* pstralloc(size_t length);
+ char* itoa(int n);
+ char* pstrndup(const char* s, size_t len);
+ char* pstrdup(const char*s);
+ char* pstrdup(const std::string&);
+
+ protected:
+ apr_pool_t* pool;
+ const bool release;
+
+ private:
+ Pool(const log4cxx::helpers::Pool&);
+ Pool& operator=(const Pool&);
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_POOL_H
diff --git a/src/main/include/log4cxx/helpers/properties.h b/src/main/include/log4cxx/helpers/properties.h
new file mode 100644
index 0000000..c238496
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/properties.h
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPER_PROPERTIES_H
+#define _LOG4CXX_HELPER_PROPERTIES_H
+
+#if defined(_MSC_VER)
+#pragma warning (push)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/helpers/inputstream.h>
+#include <map>
+#include <vector>
+#include <istream>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class LOG4CXX_EXPORT Properties
+ {
+ private:
+ typedef std::map<LogString, LogString> PropertyMap;
+ PropertyMap* properties;
+ Properties(const Properties&);
+ Properties& operator=(const Properties&);
+
+ public:
+ /**
+ * Create new instance.
+ */
+ Properties();
+ /**
+ * Destructor.
+ */
+ ~Properties();
+ /**
+ Reads a property list (key and element pairs) from the input stream.
+ The stream is assumed to be using the ISO 8859-1 character encoding.
+
+ <p>Every property occupies one line of the input stream.
+ Each line is terminated by a line terminator (<code>\\n</code> or
+ <code>\\r</code> or <code>\\r\\n</code>).
+ Lines from the input stream are processed until end of file is reached
+ on the input stream.
+
+ <p>A line that contains only whitespace or whose first non-whitespace
+ character is an ASCII <code>#</code> or <code>!</code> is ignored
+ (thus, <code>#</code> or <code>!</code> indicate comment lines).
+
+ <p>Every line other than a blank line or a comment line describes one
+ property to be added to the table (except that if a line ends with \,
+ then the following line, if it exists, is treated as a continuation
+ line, as described below). The key consists of all the characters in
+ the line starting with the first non-whitespace character and up to,
+ but not including, the first ASCII <code>=</code>, <code>:</code>,
+ or whitespace character. All of the
+ key termination characters may be included in the key by preceding them
+ with a <code>\\</code>. Any whitespace after the key is skipped;
+ if the first
+ non-whitespace character after the key is <code>=</code> or
+ <code>:</code>, then it is ignored
+ and any whitespace characters after it are also skipped. All remaining
+ characters on the line become part of the associated element string.
+ Within the element string, the ASCII escape sequences <code>\\t</code>,
+ <code>\\n</code>, <code>\\r</code>, <code>\\</code>, <code>\\"</code>,
+ <code>\\'</code>, <code>\\</code> (a backslash and a space), and
+ <code>\\uxxxx</code> are recognized
+ and converted to single characters. Moreover, if the last character on
+ the line is <code>\\</code>, then the next line is treated as a
+ continuation of the
+ current line; the <code>\\</code> and line terminator are simply
+ discarded, and any
+ leading whitespace characters on the continuation line are also
+ discarded and are not part of the element string.
+
+ <p>As an example, each of the following four lines specifies the key
+ "Truth" and the associated element value "Beauty":
+
+ <pre>
+ Truth = Beauty
+ Truth:Beauty
+ Truth :Beauty
+ </pre>
+
+ As another example, the following three lines specify a single
+ property:
+ <pre>
+ fruits apple, banana, pear, \
+ cantaloupe, watermelon, \
+ kiwi, mango
+ </pre>
+ The key is "<code>fruits</code>" and the associated element is:
+ <pre>
+"apple, banana, pear, cantaloupe, watermelon, kiwi, mango"
+ </pre>
+ Note that a space appears before each \ so that a space will appear
+ after each comma in the final result; the \, line terminator, and
+ leading whitespace on the continuation line are merely discarded and are
+ not replaced by one or more other characters.
+
+ <p>As a third example, the line:
+ <pre>
+cheeses
+ </pre>
+ specifies that the key is "<code>cheeses</code>" and the associated
+ element is the empty string.
+
+ @param inStream the input stream.
+
+ @throw IOException if an error occurred when reading from the input
+ stream.
+ */
+ void load(InputStreamPtr inStream);
+
+ /**
+ * Calls Properties::put.
+ * @param key the key to be placed into this property list.
+ * @param value the value corresponding to key.
+ * @return the previous value of the specified key in this
+ * property list, or an empty string if it did not have one.
+ */
+ LogString setProperty(const LogString& key, const LogString& value);
+ /**
+ * Puts a property value into the collection.
+ * @param key the key to be placed into this property list.
+ * @param value the value corresponding to key.
+ * @return the previous value of the specified key in this
+ * property list, or an empty string if it did not have one.
+ */
+ LogString put(const LogString& key, const LogString& value);
+
+
+ /**
+ * Calls Properties::get.
+ * @param key the property key.
+ * @return the value in this property list with the specified
+ * key value or empty string.
+ */
+ LogString getProperty(const LogString& key) const;
+ /**
+ * Gets a property value.
+ * @param key the property key.
+ * @return the value in this property list with the specified
+ * key value or empty string.
+ */
+ LogString get(const LogString& key) const;
+
+ /**
+ Returns an enumeration of all the keys in this property list,
+ including distinct keys in the default property list if a key
+ of the same name has not already been found from the main
+ properties list.
+ @return an array of all the keys in this
+ property list, including the keys in the default property list.
+ */
+ std::vector<LogString> propertyNames() const;
+ }; // class Properties
+ } // namespace helpers
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+
+#endif //_LOG4CXX_HELPER_PROPERTIES_H
diff --git a/src/main/include/log4cxx/helpers/propertyresourcebundle.h b/src/main/include/log4cxx/helpers/propertyresourcebundle.h
new file mode 100644
index 0000000..5032873
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/propertyresourcebundle.h
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_PROPERTY_RESOURCE_BUNDLE_H
+#define _LOG4CXX_HELPERS_PROPERTY_RESOURCE_BUNDLE_H
+
+#include <log4cxx/helpers/resourcebundle.h>
+#include <log4cxx/helpers/properties.h>
+#include <log4cxx/helpers/inputstream.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+
+ /**
+ PropertyResourceBundle is a concrete subclass of ResourceBundle that
+ manages resources for a locale using a set of static strings from a
+ property file.
+ */
+ class LOG4CXX_EXPORT PropertyResourceBundle : public ResourceBundle
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(PropertyResourceBundle)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(PropertyResourceBundle)
+ LOG4CXX_CAST_ENTRY_CHAIN(ResourceBundle)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ Creates a property resource bundle.
+ @param inStream property file to read from.
+ @throw IOException if an error occurred when reading from the
+ input stream.
+ */
+ PropertyResourceBundle(InputStreamPtr inStream);
+
+ virtual LogString getString(const LogString& key) const;
+
+ protected:
+ Properties properties;
+ }; // class PropertyResourceBundle
+ LOG4CXX_PTR_DEF(PropertyResourceBundle);
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif // _LOG4CXX_HELPERS_PROPERTY_RESOURCE_BUNDLE_H
+
diff --git a/src/main/include/log4cxx/helpers/reader.h b/src/main/include/log4cxx/helpers/reader.h
new file mode 100644
index 0000000..f61ca66
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/reader.h
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_READER_H
+#define _LOG4CXX_HELPERS_READER_H
+
+#include <log4cxx/helpers/objectimpl.h>
+
+namespace log4cxx
+{
+
+ namespace helpers {
+
+ /**
+ * Abstract class for reading from character streams.
+ *
+ */
+ class LOG4CXX_EXPORT Reader : public ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(Reader)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(Reader)
+ END_LOG4CXX_CAST_MAP()
+
+ protected:
+ /**
+ * Creates a new character-stream reader.
+ */
+ Reader();
+
+ virtual ~Reader();
+
+ public:
+ /**
+ * Closes the stream.
+ * @param p The memory pool associated with the reader.
+ */
+ virtual void close(Pool& p) = 0;
+
+ /**
+ * @return The complete stream contents as a LogString.
+ * @param p The memory pool associated with the reader.
+ */
+ virtual LogString read(Pool& p) = 0;
+
+ private:
+ Reader(const Reader&);
+
+ Reader& operator=(const Reader&);
+ };
+
+ LOG4CXX_PTR_DEF(Reader);
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_READER_H
diff --git a/src/main/include/log4cxx/helpers/relativetimedateformat.h b/src/main/include/log4cxx/helpers/relativetimedateformat.h
new file mode 100644
index 0000000..b60d62f
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/relativetimedateformat.h
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_RELATIVE_TIME_DATE_FORMAT_H
+#define _LOG4CXX_HELPERS_RELATIVE_TIME_DATE_FORMAT_H
+
+#include <log4cxx/helpers/dateformat.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /**
+ Formats a date by printing the number of seconds
+ elapsed since the start of the application. This is the fastest
+ printing DateFormat in the package.
+ */
+ class LOG4CXX_EXPORT RelativeTimeDateFormat : public DateFormat
+ {
+ public:
+ RelativeTimeDateFormat();
+ virtual void format(LogString &s,
+ log4cxx_time_t tm,
+ log4cxx::helpers::Pool& p) const;
+
+ private:
+ log4cxx_time_t startTime;
+
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif // _LOG4CXX_HELPERS_RELATIVE_TIME_DATE_FORMAT_H
diff --git a/src/main/include/log4cxx/helpers/resourcebundle.h b/src/main/include/log4cxx/helpers/resourcebundle.h
new file mode 100644
index 0000000..44c52e2
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/resourcebundle.h
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_RESOURCE_BUNDLE_H
+#define _LOG4CXX_HELPERS_RESOURCE_BUNDLE_H
+
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/helpers/objectptr.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class Locale;
+
+ class ResourceBundle;
+ LOG4CXX_PTR_DEF(ResourceBundle);
+
+ /**
+ Resource bundles contain locale-specific objects
+ */
+ class LOG4CXX_EXPORT ResourceBundle : public ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(ResourceBundle)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(ResourceBundle)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ Gets a string for the given key from this resource bundle or one of
+ its parents. Calling this method is equivalent to calling
+
+ @param key the key for the desired string
+ @return the string for the given key
+ @throw MissingResourceException - if no object for the given key
+ can be found
+ */
+ virtual LogString getString(const LogString& key) const = 0;
+
+ /**
+ Gets a resource bundle using the specified base name and locale
+
+ @param baseName the base name of the resource bundle, a fully
+ qualified class name or property filename
+ @param locale the locale for which a resource bundle is desired
+ */
+ static ResourceBundlePtr getBundle(const LogString& baseName,
+ const Locale& locale);
+
+ protected:
+ /*
+ Sets the parent bundle of this bundle. The parent bundle is
+ searched by #getString when this bundle does not contain a particular
+ resource.
+
+ Parameters:
+ parent - this bundle's parent bundle.
+ */
+ inline void setParent(const ResourceBundlePtr& parent1)
+ { this->parent = parent1; }
+
+ /**
+ The parent bundle of this bundle.
+
+ The parent bundle is searched by #getString when this bundle does
+ not contain a particular resource.
+ */
+ ResourceBundlePtr parent;
+ }; // class ResourceBundle
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif
+
diff --git a/src/main/include/log4cxx/helpers/serversocket.h b/src/main/include/log4cxx/helpers/serversocket.h
new file mode 100644
index 0000000..7f0c90b
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/serversocket.h
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_SERVER_SOCKET_H
+#define _LOG4CXX_HELPERS_SERVER_SOCKET_H
+
+#include <log4cxx/helpers/socket.h>
+#include <log4cxx/helpers/mutex.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class LOG4CXX_EXPORT ServerSocket
+ {
+ public:
+ /** Creates a server socket on a specified port.
+ */
+ ServerSocket(int port);
+
+ virtual ~ServerSocket();
+
+ /** Listens for a connection to be made to this socket and
+ accepts it
+ */
+ SocketPtr accept();
+
+ /** Closes this socket.
+ */
+ void close();
+
+ /** Retrive setting for SO_TIMEOUT.
+ */
+ int getSoTimeout() const;
+
+ /** Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
+ */
+ void setSoTimeout(int timeout);
+
+ private:
+ Pool pool;
+ Mutex mutex;
+ apr_socket_t* socket;
+ int timeout;
+
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_SERVER_SOCKET_H
diff --git a/src/main/include/log4cxx/helpers/simpledateformat.h b/src/main/include/log4cxx/helpers/simpledateformat.h
new file mode 100644
index 0000000..9c27f68
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/simpledateformat.h
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_SIMPLE_DATE_FORMAT_H
+#define _LOG4CXX_HELPERS_SIMPLE_DATE_FORMAT_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+
+#include <log4cxx/helpers/dateformat.h>
+#include <vector>
+#include <time.h>
+
+namespace std { class locale; }
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ namespace SimpleDateFormatImpl {
+ class PatternToken;
+ }
+
+ /**
+ * Concrete class for formatting and parsing dates in a
+ * locale-sensitive manner.
+ */
+ class LOG4CXX_EXPORT SimpleDateFormat : public DateFormat
+ {
+ public:
+ /**
+ * Constructs a DateFormat using the given pattern and the default
+ * time zone.
+ *
+ * @param pattern the pattern describing the date and time format
+ */
+ SimpleDateFormat(const LogString& pattern);
+ SimpleDateFormat(const LogString& pattern, const std::locale* locale);
+ ~SimpleDateFormat();
+
+ virtual void format(LogString& s,
+ log4cxx_time_t tm,
+ log4cxx::helpers::Pool& p) const;
+
+ /**
+ * Set time zone.
+ * @param zone new time zone.
+ */
+ void setTimeZone(const TimeZonePtr& zone);
+
+ private:
+ /**
+ * Time zone.
+ */
+ TimeZonePtr timeZone;
+
+ /**
+ * List of tokens.
+ */
+ LOG4CXX_LIST_DEF(PatternTokenList, log4cxx::helpers::SimpleDateFormatImpl::PatternToken*);
+
+ PatternTokenList pattern;
+
+ static void addToken(const logchar spec, const int repeat, const std::locale* locale, PatternTokenList& pattern);
+ static void parsePattern(const LogString& spec, const std::locale* locale, PatternTokenList& pattern);
+ };
+
+
+ } // namespace helpers
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+
+#endif // _LOG4CXX_HELPERS_SIMPLE_DATE_FORMAT_H
diff --git a/src/main/include/log4cxx/helpers/socket.h b/src/main/include/log4cxx/helpers/socket.h
new file mode 100644
index 0000000..2f1636b
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/socket.h
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_SOCKET_H
+#define _LOG4CXX_HELPERS_SOCKET_H
+
+extern "C" {
+ struct apr_socket_t;
+}
+
+
+#include <log4cxx/helpers/inetaddress.h>
+#include <log4cxx/helpers/pool.h>
+
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class ByteBuffer;
+ /**
+ <p>This class implements client sockets (also called just "sockets"). A socket
+ is an endpoint for communication between two machines.
+ <p>The actual work of the socket is performed by an instance of the SocketImpl
+ class. An application, by changing the socket factory that creates the socket
+ implementation, can configure itself to create sockets appropriate to the
+ local firewall.
+ */
+ class LOG4CXX_EXPORT Socket : public helpers::ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(Socket)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(Socket)
+ END_LOG4CXX_CAST_MAP()
+
+ /** Creates a stream socket and connects it to the specified port
+ number at the specified IP address.
+ */
+ Socket(InetAddressPtr& address, int port);
+ Socket(apr_socket_t* socket, apr_pool_t* pool);
+ ~Socket();
+
+ size_t write(ByteBuffer&);
+
+ /** Closes this socket. */
+ void close();
+
+ /** Returns the value of this socket's address field. */
+ InetAddressPtr getInetAddress() const;
+
+ /** Returns the value of this socket's port field. */
+ int getPort() const;
+ private:
+ Socket(const Socket&);
+ Socket& operator=(const Socket&);
+
+ Pool pool;
+
+ apr_socket_t* socket;
+
+
+ /** The IP address of the remote end of this socket. */
+ InetAddressPtr address;
+
+ /** The port number on the remote host to which
+ this socket is connected. */
+ int port;
+ };
+
+ LOG4CXX_PTR_DEF(Socket);
+
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif // _LOG4CXX_HELPERS_SOCKET_H
diff --git a/src/main/include/log4cxx/helpers/socketoutputstream.h b/src/main/include/log4cxx/helpers/socketoutputstream.h
new file mode 100644
index 0000000..6bca173
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/socketoutputstream.h
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_SOCKET_OUTPUT_STREAM_H
+#define _LOG4CXX_HELPERS_SOCKET_OUTPUT_STREAM_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/outputstream.h>
+#include <log4cxx/helpers/socket.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+
+ class LOG4CXX_EXPORT SocketOutputStream : public OutputStream
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(SocketOutputStream)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(SocketOutputStream)
+ LOG4CXX_CAST_ENTRY_CHAIN(OutputStream)
+ END_LOG4CXX_CAST_MAP()
+
+ SocketOutputStream(const SocketPtr& socket);
+ ~SocketOutputStream();
+
+ virtual void close(Pool& p);
+ virtual void flush(Pool& p);
+ virtual void write(ByteBuffer& buf, Pool& p);
+
+ private:
+ LOG4CXX_LIST_DEF(ByteList, unsigned char);
+ ByteList array;
+ SocketPtr socket;
+ //
+ // prevent copy and assignment statements
+ SocketOutputStream(const SocketOutputStream&);
+ SocketOutputStream& operator=(const SocketOutputStream&);
+
+ };
+
+ LOG4CXX_PTR_DEF(SocketOutputStream);
+
+ } // namespace helpers
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+
+#endif // _LOG4CXX_HELPERS_SOCKET_OUTPUT_STREAM_H
diff --git a/src/main/include/log4cxx/helpers/strftimedateformat.h b/src/main/include/log4cxx/helpers/strftimedateformat.h
new file mode 100644
index 0000000..043205b
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/strftimedateformat.h
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_STRFTIME_DATE_FORMAT_H
+#define _LOG4CXX_HELPERS_STRFTIME_DATE_FORMAT_H
+
+#include <log4cxx/helpers/dateformat.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+
+ /**
+ Concrete class for formatting and parsing dates in a
+ locale-sensitive manner.
+
+ */
+ class LOG4CXX_EXPORT StrftimeDateFormat : public DateFormat
+ {
+ public:
+ /**
+ Constructs a DateFormat using the given pattern and the default
+ time zone.
+
+ @param pattern the pattern describing the date and time format
+ */
+ StrftimeDateFormat(const LogString& pattern);
+ ~StrftimeDateFormat();
+
+ virtual void format(LogString& s,
+ log4cxx_time_t tm,
+ log4cxx::helpers::Pool& p) const;
+
+ /**
+ * Set time zone.
+ * @param zone new time zone.
+ */
+ void setTimeZone(const TimeZonePtr& zone);
+
+
+ private:
+ /**
+ * Time zone.
+ */
+ TimeZonePtr timeZone;
+ std::string pattern;
+ };
+
+
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif // _LOG4CXX_HELPERS_STRFTIME_DATE_FORMAT_H
diff --git a/src/main/include/log4cxx/helpers/strictmath.h b/src/main/include/log4cxx/helpers/strictmath.h
new file mode 100644
index 0000000..8c4194b
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/strictmath.h
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_STRICTMATH_H
+#define _LOG4CXX_HELPERS_STRICTMATH_H
+
+#include <log4cxx/log4cxx.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /**
+ The class StrictMath contains methods for performing basic numeric
+ operations
+ */
+ class StrictMath
+ {
+ public:
+ template<typename _type> static inline const _type&
+ minimum(const _type& a, const _type& b)
+ {
+ return (a < b) ? a : b;
+ }
+
+ template<typename _type> static inline const _type&
+ maximum(const _type& a, const _type& b)
+ {
+ return (a > b) ? a : b;
+ }
+ }; // class StrictMath
+ } // namespace helpers
+} // namespace log4cx
+
+#endif //_LOG4CXX_HELPERS_STRICTMATH_H
diff --git a/src/main/include/log4cxx/helpers/stringhelper.h b/src/main/include/log4cxx/helpers/stringhelper.h
new file mode 100644
index 0000000..e8e170d
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/stringhelper.h
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_STRING_HELPER_H
+#define _LOG4CXX_HELPERS_STRING_HELPER_H
+
+#include <log4cxx/logstring.h>
+#include <vector>
+
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class Pool;
+ /**
+ String manipulation routines
+ */
+ class LOG4CXX_EXPORT StringHelper
+ {
+ public:
+ static LogString trim(const LogString& s);
+ static bool startsWith(const LogString& s, const LogString& suffix);
+ static bool endsWith(const LogString& s, const LogString& suffix);
+ static bool equalsIgnoreCase(const LogString& s1,
+ const logchar* upper, const logchar* lower);
+ static bool equalsIgnoreCase(const LogString& s1,
+ const LogString& upper, const LogString& lower);
+
+
+ static int toInt(const LogString& s);
+ static log4cxx_int64_t toInt64(const LogString& s);
+
+ static void toString(int i, log4cxx::helpers::Pool& pool, LogString& dst);
+ static void toString(log4cxx_int64_t i, log4cxx::helpers::Pool& pool, LogString& dst);
+ static void toString(size_t i, log4cxx::helpers::Pool& pool, LogString& dst);
+
+ static void toString(bool val, LogString& dst);
+
+ static LogString toLowerCase(const LogString& s);
+
+ static LogString format(const LogString& pattern, const std::vector<LogString>& params);
+ };
+ }
+}
+
+#endif //_LOG4CXX_HELPERS_STRING_HELPER_H
diff --git a/src/main/include/log4cxx/helpers/stringtokenizer.h b/src/main/include/log4cxx/helpers/stringtokenizer.h
new file mode 100644
index 0000000..18320c4
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/stringtokenizer.h
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_STRING_TOKENIZER_H
+#define _LOG4CXX_HELPERS_STRING_TOKENIZER_H
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/exception.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class LOG4CXX_EXPORT StringTokenizer
+ {
+ public:
+ StringTokenizer(const LogString& str, const LogString& delim);
+ ~StringTokenizer();
+ bool hasMoreTokens() const;
+ LogString nextToken();
+
+ protected:
+ LogString src;
+ LogString delim;
+ size_t pos;
+
+ private:
+ // prevent copy and assignment statements
+ StringTokenizer(const StringTokenizer&);
+ StringTokenizer& operator=(const StringTokenizer&);
+ }; // class StringTokenizer
+ } // namespace helpers;
+} // namespace log4cxx;
+
+#endif //_LOG4CXX_HELPERS_STRING_TOKENIZER_H
diff --git a/src/main/include/log4cxx/helpers/synchronized.h b/src/main/include/log4cxx/helpers/synchronized.h
new file mode 100755
index 0000000..05476db
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/synchronized.h
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_SYNCHRONIZED_H
+#define _LOG4CXX_HELPERS_SYNCHRONIZED_H
+#include <log4cxx/log4cxx.h>
+
+namespace log4cxx
+{
+ namespace helpers {
+ class Mutex;
+
+ /** utility class for objects multi-thread synchronization.*/
+ class LOG4CXX_EXPORT synchronized
+ {
+ public:
+ synchronized(const Mutex& mutex);
+ ~synchronized();
+
+
+ private:
+ void* mutex;
+ // prevent use of copy and assignment
+ synchronized(const synchronized&);
+ synchronized& operator=(const synchronized&);
+ };
+ }
+}
+
+#endif //_LOG4CXX_HELPERS_SYNCHRONIZED_H
diff --git a/src/main/include/log4cxx/helpers/syslogwriter.h b/src/main/include/log4cxx/helpers/syslogwriter.h
new file mode 100644
index 0000000..bc2378c
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/syslogwriter.h
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SYSLOG_WRITER_H
+#define _LOG4CXX_SYSLOG_WRITER_H
+
+
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/inetaddress.h>
+#include <log4cxx/helpers/datagramsocket.h>
+
+ namespace log4cxx
+{
+ namespace helpers
+ {
+ /**
+ SyslogWriter is a wrapper around the DatagramSocket class
+ it writes text to the specified host on the port 514 (UNIX syslog)
+ */
+ class LOG4CXX_EXPORT SyslogWriter
+ {
+ public:
+ SyslogWriter(const LogString& syslogHost);
+ void write(const LogString& string);
+
+ private:
+ LogString syslogHost;
+ InetAddressPtr address;
+ DatagramSocketPtr ds;
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif
diff --git a/src/main/include/log4cxx/helpers/system.h b/src/main/include/log4cxx/helpers/system.h
new file mode 100644
index 0000000..3885687
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/system.h
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_SYSTEM_H
+ #define _LOG4CXX_HELPERS_SYSTEM_H
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/exception.h>
+
+ namespace log4cxx
+ {
+ namespace helpers
+ {
+ class Properties;
+
+ /** The System class contains several useful class fields and methods.
+ It cannot be instantiated.
+ */
+ class LOG4CXX_EXPORT System
+ {
+ public:
+
+ /**
+ Gets the system property indicated by the specified key.
+
+ @param key the name of the system property.
+
+ @return the string value of the system property, or the default value if
+ there is no property with that key.
+
+ @throws IllegalArgumentException if key is empty.
+ */
+ static LogString getProperty(const LogString& key);
+
+ };
+ } // namespace helpers
+ } // namespace log4cxx
+
+ #endif //_LOG4CXX_HELPERS_SYSTEM_H
diff --git a/src/main/include/log4cxx/helpers/systemerrwriter.h b/src/main/include/log4cxx/helpers/systemerrwriter.h
new file mode 100644
index 0000000..7fda472
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/systemerrwriter.h
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_SYSTEMERRWRITER_H
+#define _LOG4CXX_HELPERS_SYSTEMERRWRITER_H
+
+#include <log4cxx/helpers/writer.h>
+
+namespace log4cxx
+{
+ namespace helpers {
+
+ /**
+ * Abstract class for writing to character streams.
+ */
+ class LOG4CXX_EXPORT SystemErrWriter : public Writer
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(SystemErrWriter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(SystemErrWriter)
+ LOG4CXX_CAST_ENTRY_CHAIN(Writer)
+ END_LOG4CXX_CAST_MAP()
+
+ SystemErrWriter();
+ virtual ~SystemErrWriter();
+
+ virtual void close(Pool& p);
+ virtual void flush(Pool& p);
+ virtual void write(const LogString& str, Pool& p);
+
+ static void write(const LogString& str);
+ static void flush();
+
+ private:
+ SystemErrWriter(const SystemErrWriter&);
+ SystemErrWriter& operator=(const SystemErrWriter&);
+ static bool isWide();
+ };
+
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_SYSTEMERRWRITER_H
diff --git a/src/main/include/log4cxx/helpers/systemoutwriter.h b/src/main/include/log4cxx/helpers/systemoutwriter.h
new file mode 100644
index 0000000..af7c55b
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/systemoutwriter.h
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_SYSTEMOUTWRITER_H
+#define _LOG4CXX_HELPERS_SYSTEMOUTWRITER_H
+
+#include <log4cxx/helpers/writer.h>
+
+namespace log4cxx
+{
+ namespace helpers {
+
+ /**
+ * Abstract class for writing to character streams.
+ */
+ class LOG4CXX_EXPORT SystemOutWriter : public Writer
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(SystemOutWriter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(SystemOutWriter)
+ LOG4CXX_CAST_ENTRY_CHAIN(Writer)
+ END_LOG4CXX_CAST_MAP()
+
+ SystemOutWriter();
+ ~SystemOutWriter();
+
+ virtual void close(Pool& p);
+ virtual void flush(Pool& p);
+ virtual void write(const LogString& str, Pool& p);
+
+ static void write(const LogString& str);
+ static void flush();
+ private:
+ SystemOutWriter(const SystemOutWriter&);
+ SystemOutWriter& operator=(const SystemOutWriter&);
+ static bool isWide();
+ };
+
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_SYSTEMOUTWRITER_H
diff --git a/src/main/include/log4cxx/helpers/tchar.h b/src/main/include/log4cxx/helpers/tchar.h
new file mode 100644
index 0000000..bf3412c
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/tchar.h
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_TCHAR_H
+#define _LOG4CXX_HELPERS_TCHAR_H
+
+#error log4cxx/helpers/tchar.h is obsolete, see details following this line.
+
+/**
+* A short history of log4cxx's tchar.h
+*
+* The previous log4cxx/helpers/tchar.h contained macros that
+* attempted to replicate macros and functions defined by
+* the Microsoft SDK's tchar.h and related header files
+* such as _T() and TCHAR.
+*
+* When building apps using both log4cxx and Microsoft SDK's tchar.h,
+* these definitions could conflict and, for example, the code generated
+* by _T("Foo") would depend on the include order of the two
+* tchar.h's.
+*
+* The motivation of tchar.h in the Microsoft SDK was to
+* support presenting either a wide-char or multi-byte char
+* facade to a C API depending on the presence of
+* the _UNICODE or _MBCS preprocessor macros. When _UNICODE
+* was set then tchar was typedef'd as wchar_t and, for example,
+* the CreateProcess macro was defined to be CreateProcessW, If
+* _MBCS was defined, then tchar was typedef'd as char
+* and CreateProcess macro was defined to be CreateProcessA.
+*
+* In either case, the setting of _UNICODE or _MBCS
+* didn't affect the implementation of the operating system.
+* If you were running the Windows NT family, all the multi-byte
+* methods delegated to a wide-char implementation.
+* In the Windows 9x family, most wide-char methods delegated
+* to a multi-byte implementation.
+*
+* In practice, most Microsoft Windows executables were either
+* wide-char or multi-byte centric. However, they did not
+* have to be exclusively so. An application built with
+* _UNICODE, could still call multi-byte API functions,
+* they would just need to explicitly call CreateProcessA
+* instead of using the facade macro. An executable could
+* also use both a multi-byte centric and wide-char centric
+* DLL's since all the calls eventually hit the same
+* underlying implementation be it a wide-char on in
+* Windows NT or multi-char in Windows 9x.
+*
+* The use of log4cxx/helpers/tchar.h in log4cxx 0.9.7 was
+* undesirable because it made log4cxx either exclusively
+* wide-char or exclusively multi-byte and had to be consistant
+* with the character model of the calling executable.
+* This would make it extremely difficult to use
+* log4cxx when DLL's with different character models
+* where called by the same application. Since log4cxx
+* was C++, not C, function overloading could be
+* used instead of the CreateProcess et al macros
+* used in the Windows headers.
+*
+* In the rework before the 0.9.8, the following changes
+* were made to log4cxx:
+*
+* 1. All inclusions of log4cxx/helpers/tchar.h
+* and use of TCHAR, log4cxx::String and _T
+* were removed from log4cxx.
+* 2. log4cxx/logstring.h was added to define the
+* implementation character model using the log4cxx::logchar
+* and log4cxx::LogString typedefs and LOG4CXX_STR macro.
+* 3. Methods commonly used by calling applications were defined
+* in both wide-char and multi-byte and both pointer and string
+* forms with conversion to the implementation character
+* model delayed as long as possible.
+* 4. Use of Standard Template Library streams within
+* log4cxx was substantially reduced (but not totally
+* elminated).
+* 5. The LOG4CXX_DEBUG and similar macros were simplified
+* and now only take arguments that evaluate to
+* character pointers or strings and no longer take
+* the right hand side of an insertion operation:
+*
+* // This used to work, but no longer
+* LOG4CXX_DEBUG(logger, "foo" << i);
+*
+* If you extensively used this idiom, please consider
+* migrating to stream-like API defined in log4cxx/stream.h.
+*
+* 6. The LOG4CXX_DEBUG and similar use the LOG4CXX_LOCATION
+* macro to define the log statement location instead of
+* using __FILE__ and __LINE__. Logger::debug and
+* similar now take const LocationInfo& instead of
+* separate const char* and int arguments. This allows
+* class and method names to appear in location info.
+* 7. log4cxx include files no longer include config.h
+* or related files. config.h and related files
+* may be used by log4cxx implementation, but have
+* no effect on the exposed API.
+*
+* It is expected that the default implementation character
+* model will be wchar_t. However this may vary by platform
+* and may be changed based on feedback.
+*
+* Developers using log4cxx should seldom be concerned
+* with the internal character model of log4cxx unless
+* writing custom appenders or layouts. An application
+* should not be using log4cxx::logchar, log4cxx::LogString
+* or LOG4CXX_STR unless dealing with something that is
+* clearly a log4cxx internal. If you find something
+* defined as using or returning LogString that you
+* don't consider a log4cxx internal, please file a
+* bug report or post a message to one of the mailing lists.
+*
+* wchar_t literals should be preferred in log requests since
+* since they eliminate potential encoding confusion
+* when the development and deployment encodings are different.
+*
+* Migration strategies:
+*
+* If you followed the examples in the previous log4cxx versions,
+* you may have _T() macros littered through your code
+* and inclusions of this file. If you are on the Microsoft
+* platform, the simplest solution is to just include
+* the Platform SDK's tchar.h which would result your log
+* statements matching the character model of your application.
+*
+* If you targetting another platform and your only use of
+* _T() in related to log4cxx, then I would recommend replacing
+* all _T() with another macro (say MYAPP_LOGSTR())
+* and defining that macro in a commonly included header file
+* or defining _T() in a commonly included header file.
+*
+* I would first try defining these macros as
+*
+* #define _T(str) L ## str
+*
+* If that results in too many compilation errors, then try:
+*
+* #define _T(str) str
+*
+* Using the first form will result in wchar_t literals which
+* will avoid potential encoding confusion and is expected
+* to result in slightly better performance when logging.
+*
+* Since the best choice for _T() depends on the application,
+* there is not a definition within log4cxx.
+*
+* Use encoding conversion macros A2T, W2T, et al should
+* not longer be necessary. If you are doing a lot of
+* work converting between encodings, you might consider
+* using the stream-like interface in log4cxx/stream.h
+* which defines insertion operators for multi-byte
+* strings in addition to exposing all the
+* insertion operations defined for
+* std::basic_ostream<wchar_t>.
+*
+*/
+
+#endif //_LOG4CXX_HELPERS_TCHAR_H
diff --git a/src/main/include/log4cxx/helpers/thread.h b/src/main/include/log4cxx/helpers/thread.h
new file mode 100644
index 0000000..09a47d6
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/thread.h
@@ -0,0 +1,184 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_THREAD_H
+#define _LOG4CXX_HELPERS_THREAD_H
+
+#include <log4cxx/log4cxx.h>
+#include <log4cxx/helpers/pool.h>
+
+#if !defined(LOG4CXX_THREAD_FUNC)
+#if defined(_WIN32)
+#define LOG4CXX_THREAD_FUNC __stdcall
+#else
+#define LOG4CXX_THREAD_FUNC
+#endif
+#endif
+
+extern "C" {
+ typedef struct apr_thread_t apr_thread_t;
+}
+
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class Pool;
+ class ThreadLocal;
+
+ typedef void* (LOG4CXX_THREAD_FUNC *Runnable)(apr_thread_t* thread, void* data);
+ /**
+ * This class implements an approximation of java.util.Thread.
+ */
+ class LOG4CXX_EXPORT Thread
+ {
+ public:
+ /**
+ * Create new instance.
+ */
+ Thread();
+ /**
+ * Destructor.
+ */
+ ~Thread();
+
+ /**
+ * Runs the specified method on a newly created thread.
+ */
+ void run(Runnable start, void* data);
+ void join();
+
+ inline bool isActive() { return thread != 0; }
+
+ /**
+ * Causes the currently executing thread to sleep for the
+ * specified number of milliseconds.
+ * @param millis milliseconds.
+ * @throws Interrupted Exception if the thread is interrupted.
+ */
+ static void sleep(int millis);
+ /**
+ * Sets interrupted status for current thread to true.
+ */
+ static void currentThreadInterrupt();
+ /**
+ * Sets interrupted status to true.
+ */
+ void interrupt();
+ /**
+ * Tests if the current thread has been interrupted and
+ * sets the interrupted status to false.
+ */
+ static bool interrupted();
+
+ bool isAlive();
+ bool isCurrentThread() const;
+ void ending();
+
+
+ private:
+ Pool p;
+ apr_thread_t* thread;
+ volatile unsigned int alive;
+ volatile unsigned int interruptedStatus;
+ Thread(const Thread&);
+ Thread& operator=(const Thread&);
+
+ /**
+ * This class is used to encapsulate the parameters to
+ * Thread::run when they are passed to Thread::launcher.
+ *
+ */
+ class LaunchPackage {
+ public:
+ /**
+ * Placement new to create LaunchPackage in specified pool.
+ * LaunchPackage needs to be dynamically allocated since
+ * since a stack allocated instance may go out of scope
+ * before thread is launched.
+ */
+ static void* operator new(size_t, Pool& p);
+ /**
+ * operator delete would be called if exception during construction.
+ */
+ static void operator delete(void*, Pool& p);
+ /**
+ * Create new instance.
+ */
+ LaunchPackage(Thread* thread, Runnable runnable, void* data);
+ /**
+ * Gets thread parameter.
+ * @return thread.
+ */
+ Thread* getThread() const;
+ /**
+ * Gets runnable parameter.
+ * @return runnable.
+ */
+ Runnable getRunnable() const;
+ /**
+ * gets data parameter.
+ * @return thread.
+ */
+ void* getData() const;
+ private:
+ LaunchPackage(const LaunchPackage&);
+ LaunchPackage& operator=(const LaunchPackage&);
+ Thread* thread;
+ Runnable runnable;
+ void* data;
+ };
+
+ /**
+ * This object atomically sets the specified memory location
+ * to non-zero on construction and to zero on destruction.
+ * Used to maintain Thread.alive.
+ */
+ class LaunchStatus {
+ public:
+ /*
+ * Construct new instance.
+ * @param p address of memory to set to non-zero on construction, zero on destruction.
+ */
+ LaunchStatus(volatile unsigned int* p);
+ /**
+ * Destructor.
+ */
+ ~LaunchStatus();
+ private:
+ LaunchStatus(const LaunchStatus&);
+ LaunchStatus& operator=(const LaunchStatus&);
+ volatile unsigned int* alive;
+ };
+
+ /**
+ * This method runs on the created thread and sets up thread-local storage
+ * used to keep the reference to the corresponding Thread object and
+ * is responsible for maintaining Thread.alive.
+ */
+ static void* LOG4CXX_THREAD_FUNC launcher(apr_thread_t* thread, void* data);
+ /**
+ * Get a key to the thread local storage used to hold the reference to
+ * the corresponding Thread object.
+ */
+ static ThreadLocal& getThreadLocal();
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_THREAD_H
diff --git a/src/main/include/log4cxx/helpers/threadlocal.h b/src/main/include/log4cxx/helpers/threadlocal.h
new file mode 100644
index 0000000..9275811
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/threadlocal.h
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_THREAD_LOCAL_H
+#define _LOG4CXX_HELPERS_THREAD_LOCAL_H
+
+#include <log4cxx/log4cxx.h>
+#include <log4cxx/helpers/pool.h>
+
+#if !defined(LOG4CXX_THREAD_FUNC)
+#if defined(_WIN32)
+#define LOG4CXX_THREAD_FUNC __stdcall
+#else
+#define LOG4CXX_THREAD_FUNC
+#endif
+#endif
+
+
+extern "C" {
+ struct apr_threadkey_t;
+}
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+
+ /**
+ * This class provides thread-local variables. This class is similar in function
+ * to java.lang.ThreadLocal.
+ */
+ class LOG4CXX_EXPORT ThreadLocal {
+ public:
+ /**
+ * Create new instance.
+ */
+ ThreadLocal();
+ /**
+ * Destructor.
+ */
+ ~ThreadLocal();
+ /**
+ * Sets the value in the current thread's copy of this thread-local variable.
+ * @param priv new value.
+ */
+ void set(void* priv);
+ /**
+ * Returns the value in the current thread's copy of this thread-local variable.
+ * @return value of thread-local variable for the current thread.
+ */
+ void* get();
+
+ private:
+ /**
+ * Prevent use of default copy constructor.
+ */
+ ThreadLocal(const ThreadLocal&);
+ /**
+ * Prevent use of default assignment operator.
+ */
+ ThreadLocal& operator=(const ThreadLocal&);
+
+ static apr_threadkey_t* create(Pool& p);
+
+ Pool p;
+ apr_threadkey_t* key;
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_THREAD_LOCAL_H
diff --git a/src/main/include/log4cxx/helpers/threadspecificdata.h b/src/main/include/log4cxx/helpers/threadspecificdata.h
new file mode 100644
index 0000000..b02cf51
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/threadspecificdata.h
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_THREAD_SPECIFIC_DATA_H
+#define _LOG4CXX_HELPERS_THREAD_SPECIFIC_DATA_H
+
+#include <log4cxx/ndc.h>
+#include <log4cxx/mdc.h>
+
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /**
+ * This class contains all the thread-specific
+ * data in use by log4cxx.
+ */
+ class LOG4CXX_EXPORT ThreadSpecificData
+ {
+ public:
+ ThreadSpecificData();
+ ~ThreadSpecificData();
+
+ /**
+ * Gets current thread specific data.
+ * @return thread specific data, may be null.
+ */
+ static ThreadSpecificData* getCurrentData();
+ /**
+ * Release this ThreadSpecficData if empty.
+ */
+ void recycle();
+
+ static void put(const LogString& key, const LogString& val);
+ static void push(const LogString& val);
+ static void inherit(const log4cxx::NDC::Stack& stack);
+
+ log4cxx::NDC::Stack& getStack();
+ log4cxx::MDC::Map& getMap();
+
+
+ private:
+ static ThreadSpecificData& getDataNoThreads();
+ static ThreadSpecificData* createCurrentData();
+ log4cxx::NDC::Stack ndcStack;
+ log4cxx::MDC::Map mdcMap;
+ };
+
+ } // namespace helpers
+} // namespace log4cxx
+
+#endif
diff --git a/src/main/include/log4cxx/helpers/timezone.h b/src/main/include/log4cxx/helpers/timezone.h
new file mode 100644
index 0000000..67c0626
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/timezone.h
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_TIMEZONE_H
+#define _LOG4CXX_HELPERS_TIMEZONE_H
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/helpers/objectptr.h>
+
+struct apr_time_exp_t;
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class TimeZone;
+ LOG4CXX_PTR_DEF(TimeZone);
+
+ class LOG4CXX_EXPORT TimeZone : public helpers::ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(TimeZone)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(TimeZone)
+ END_LOG4CXX_CAST_MAP()
+
+ static const TimeZonePtr& getDefault();
+ static const TimeZonePtr& getGMT();
+ static const TimeZonePtr getTimeZone(const LogString& ID);
+
+ const LogString getID() const {
+ return id;
+ }
+
+
+ /**
+ * Expand an APR time into the human readable
+ * components for this timezone.
+ */
+ virtual log4cxx_status_t explode(apr_time_exp_t* result,
+ log4cxx_time_t input) const = 0;
+
+
+ protected:
+ TimeZone(const LogString& ID);
+ virtual ~TimeZone();
+
+ const LogString id;
+ };
+
+
+ }
+}
+
+#endif //_LOG4CXX_HELPERS_TIMEZONE_H
diff --git a/src/main/include/log4cxx/helpers/transcoder.h b/src/main/include/log4cxx/helpers/transcoder.h
new file mode 100644
index 0000000..0559ba9
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/transcoder.h
@@ -0,0 +1,256 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_TRANSCODER_H
+#define _LOG4CXX_HELPERS_TRANSCODER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+
+
+namespace log4cxx {
+ namespace helpers {
+ class ByteBuffer;
+ class Pool;
+ /**
+ * Simple transcoder for converting between
+ * external char and wchar_t strings and
+ * internal strings.
+ *
+ */
+ class LOG4CXX_EXPORT Transcoder {
+ public:
+
+
+ /**
+ * Appends this specified string of UTF-8 characters to LogString.
+ */
+ static void decodeUTF8(const std::string& src, LogString& dst);
+ /**
+ * Converts the LogString to a UTF-8 string.
+ */
+ static void encodeUTF8(const LogString& src, std::string& dst);
+ /**
+ * Converts the LogString to a UTF-8 string.
+ */
+ static char* encodeUTF8(const LogString& src, log4cxx::helpers::Pool& p);
+ /**
+ * Append UCS-4 code point to a byte buffer as UTF-8.
+ */
+ static void encodeUTF8(unsigned int sv, ByteBuffer& dst);
+ /**
+ * Append UCS-4 code point to a byte buffer as UTF-16LE.
+ */
+ static void encodeUTF16LE(unsigned int sv, ByteBuffer& dst);
+ /**
+ * Append UCS-4 code point to a byte buffer as UTF-16BE.
+ */
+ static void encodeUTF16BE(unsigned int sv, ByteBuffer& dst);
+
+
+ /**
+ * Decodes next character from a UTF-8 string.
+ * @param in string from which the character is extracted.
+ * @param iter iterator addressing start of character, will be
+ * advanced to next character if successful.
+ * @return scalar value (UCS-4) or 0xFFFF if invalid sequence.
+ */
+ static unsigned int decode(const std::string& in,
+ std::string::const_iterator& iter);
+
+ /**
+ * Appends UCS-4 value to a UTF-8 string.
+ * @param ch UCS-4 value.
+ * @param dst destination.
+ */
+ static void encode(unsigned int ch, std::string& dst);
+
+ /**
+ * Appends string in the current code-page
+ * to a LogString.
+ */
+ static void decode(const std::string& src, LogString& dst);
+ /**
+ * Appends a LogString to a string in the current
+ * code-page. Unrepresentable characters may be
+ * replaced with loss characters.
+ */
+ static void encode(const LogString& src, std::string& dst);
+
+ /**
+ * Encodes the specified LogString to the current
+ * character set.
+ * @param src string to encode.
+ * @param p pool from which to allocate return value.
+ * @return pool allocated string.
+ */
+ static char* encode(const LogString& src, log4cxx::helpers::Pool& p);
+
+
+
+#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR_T || defined(WIN32) || defined(_WIN32)
+ static void decode(const std::wstring& src, LogString& dst);
+ static void encode(const LogString& src, std::wstring& dst);
+ static wchar_t* wencode(const LogString& src, log4cxx::helpers::Pool& p);
+
+ /**
+ * Decodes next character from a wstring.
+ * @param in string from which the character is extracted.
+ * @param iter iterator addressing start of character, will be
+ * advanced to next character if successful.
+ * @return scalar value (UCS-4) or 0xFFFF if invalid sequence.
+ */
+ static unsigned int decode(const std::wstring& in,
+ std::wstring::const_iterator& iter);
+
+ /**
+ * Appends UCS-4 value to a UTF-8 string.
+ * @param ch UCS-4 value.
+ * @param dst destination.
+ */
+ static void encode(unsigned int ch, std::wstring& dst);
+
+#endif
+
+
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API || LOG4CXX_LOGCHAR_IS_UNICHAR
+ static void decode(const std::basic_string<UniChar>& src, LogString& dst);
+ static void encode(const LogString& src, std::basic_string<UniChar>& dst);
+
+ /**
+ * Decodes next character from a UniChar string.
+ * @param in string from which the character is extracted.
+ * @param iter iterator addressing start of character, will be
+ * advanced to next character if successful.
+ * @return scalar value (UCS-4) or 0xFFFF if invalid sequence.
+ */
+ static unsigned int decode(const std::basic_string<UniChar>& in,
+ std::basic_string<UniChar>::const_iterator& iter);
+
+ /**
+ * Appends UCS-4 value to a UTF-8 string.
+ * @param ch UCS-4 value.
+ * @param dst destination.
+ */
+ static void encode(unsigned int ch, std::basic_string<UniChar>& dst);
+
+#endif
+
+#if LOG4CXX_CFSTRING_API
+ static void decode(const CFStringRef& src, LogString& dst);
+ static CFStringRef encode(const LogString& src);
+#endif
+
+ enum { LOSSCHAR = 0x3F };
+
+ /**
+ * Returns a logchar value given a character literal in the ASCII charset.
+ * Used to implement the LOG4CXX_STR macro for EBCDIC and UNICHAR.
+ */
+ static logchar decode(char v);
+ /**
+ * Returns a LogString given a string literal in the ASCII charset.
+ * Used to implement the LOG4CXX_STR macro for EBCDIC and UNICHAR.
+ */
+ static LogString decode(const char* v);
+
+ /**
+ * Encodes a charset name in the default encoding
+ * without using a CharsetEncoder (which could trigger recursion).
+ */
+ static std::string encodeCharsetName(const LogString& charsetName);
+
+ private:
+
+ private:
+ Transcoder();
+ Transcoder(const Transcoder&);
+ Transcoder& operator=(const Transcoder&);
+ enum { BUFSIZE = 256 };
+ static size_t encodeUTF8(unsigned int ch, char* dst);
+ static size_t encodeUTF16BE(unsigned int ch, char* dst);
+ static size_t encodeUTF16LE(unsigned int ch, char* dst);
+
+ };
+ }
+}
+
+#define LOG4CXX_ENCODE_CHAR(var, src) \
+std::string var; \
+log4cxx::helpers::Transcoder::encode(src, var)
+
+#define LOG4CXX_DECODE_CHAR(var, src) \
+log4cxx::LogString var; \
+log4cxx::helpers::Transcoder::decode(src, var)
+
+#define LOG4CXX_DECODE_CFSTRING(var, src) \
+log4cxx::LogString var; \
+log4cxx::helpers::Transcoder::decode(src, var)
+
+#define LOG4CXX_ENCODE_CFSTRING(var, src) \
+CFStringRef var = log4cxx::helpers::Transcoder::encode(src)
+
+
+#if LOG4CXX_LOGCHAR_IS_WCHAR
+
+#define LOG4CXX_ENCODE_WCHAR(var, src) \
+const std::wstring& var = src
+
+#define LOG4CXX_DECODE_WCHAR(var, src) \
+const log4cxx::LogString& var = src
+
+#else
+
+#define LOG4CXX_ENCODE_WCHAR(var, src) \
+std::wstring var; \
+log4cxx::helpers::Transcoder::encode(src, var)
+
+#define LOG4CXX_DECODE_WCHAR(var, src) \
+log4cxx::LogString var; \
+log4cxx::helpers::Transcoder::decode(src, var)
+
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_UNICHAR
+
+#define LOG4CXX_ENCODE_UNICHAR(var, src) \
+const std::basic_string<UniChar>& var = src
+
+#define LOG4CXX_DECODE_UNICHAR(var, src) \
+const log4cxx::LogString& var = src
+
+#else
+
+#define LOG4CXX_ENCODE_UNICHAR(var, src) \
+std::basic_string<UniChar> var; \
+log4cxx::helpers::Transcoder::encode(src, var)
+
+#define LOG4CXX_DECODE_UNICHAR(var, src) \
+log4cxx::LogString var; \
+log4cxx::helpers::Transcoder::decode(src, var)
+
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+#endif //_LOG4CXX_HELPERS_TRANSCODER_H
diff --git a/src/main/include/log4cxx/helpers/transform.h b/src/main/include/log4cxx/helpers/transform.h
new file mode 100644
index 0000000..08be797
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/transform.h
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_TRANSFORM_H
+#define _LOG4CXX_HELPERS_TRANSFORM_H
+
+#include <log4cxx/logstring.h>
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ /**
+ Utility class for transforming strings.
+ */
+ class LOG4CXX_EXPORT Transform
+ {
+ public:
+ /**
+ * This method takes a string which may contain HTML tags (ie,
+ * &lt;b&gt;, &lt;table&gt;, etc) and replaces any '<' and '>'
+ * characters with respective predefined entity references.
+ *
+ * @param buf output stream where to write the modified string.
+ * @param input The text to be converted.
+ * @return The input string with the characters '<' and '>' replaced with
+ * &amp;lt; and &amp;gt; respectively.
+ * */
+ static void appendEscapingTags(
+ LogString& buf, const LogString& input);
+
+ /**
+ * Ensures that embeded CDEnd strings (]]>) are handled properly
+ * within message, NDC and throwable tag text.
+ *
+ * @param buf output stream holding the XML data to this point. The
+ * initial CDStart (<![CDATA[) and final CDEnd (]]>) of the CDATA
+ * section are the responsibility of the calling method.
+ * @param input The String that is inserted into an existing CDATA
+ * Section within buf.
+ */
+ static void appendEscapingCDATA(
+ LogString& buf, const LogString& input);
+ }; // class Transform
+ } // namespace helpers
+} //namespace log4cxx
+
+#endif // _LOG4CXX_HELPERS_TRANSFORM_H
diff --git a/src/main/include/log4cxx/helpers/writer.h b/src/main/include/log4cxx/helpers/writer.h
new file mode 100644
index 0000000..debe834
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/writer.h
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_WRITER_H
+#define _LOG4CXX_HELPERS_WRITER_H
+
+#include <log4cxx/helpers/objectimpl.h>
+
+namespace log4cxx
+{
+
+ namespace helpers {
+
+ /**
+ * Abstract class for writing to character streams.
+ */
+ class LOG4CXX_EXPORT Writer : public ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(Writer)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(Writer)
+ END_LOG4CXX_CAST_MAP()
+
+ protected:
+ Writer();
+ virtual ~Writer();
+
+ public:
+ virtual void close(Pool& p) = 0;
+ virtual void flush(Pool& p) = 0;
+ virtual void write(const LogString& str, Pool& p) = 0;
+
+ private:
+ Writer(const Writer&);
+ Writer& operator=(const Writer&);
+ };
+
+ LOG4CXX_PTR_DEF(Writer);
+ } // namespace helpers
+
+} //namespace log4cxx
+
+#endif //_LOG4CXX_HELPERS_WRITER_H
diff --git a/src/main/include/log4cxx/helpers/xml.h b/src/main/include/log4cxx/helpers/xml.h
new file mode 100644
index 0000000..a6b212b
--- /dev/null
+++ b/src/main/include/log4cxx/helpers/xml.h
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_XML_H
+#define _LOG4CXX_HELPERS_XML_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/object.h>
+#include <log4cxx/helpers/exception.h>
+
+namespace log4cxx
+{
+ class File;
+ namespace helpers
+ {
+ class XMLDOMNode;
+ typedef helpers::ObjectPtrT<XMLDOMNode> XMLDOMNodePtr;
+
+ class XMLDOMDocument;
+ typedef helpers::ObjectPtrT<XMLDOMDocument> XMLDOMDocumentPtr;
+
+ class XMLDOMNodeList;
+ typedef helpers::ObjectPtrT<XMLDOMNodeList> XMLDOMNodeListPtr;
+
+ class LOG4CXX_EXPORT DOMException : public RuntimeException
+ {
+ public:
+ DOMException() : RuntimeException(LOG4CXX_STR("DOM exception")) {}
+ };
+
+
+ /**
+ The XMLDOMNode interface is the primary datatype for the entire Document
+ Object Model.
+ */
+ class LOG4CXX_EXPORT XMLDOMNode : virtual public Object
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(XMLDOMNode)
+ enum XMLDOMNodeType
+ {
+ NOT_IMPLEMENTED_NODE = 0,
+ ELEMENT_NODE = 1,
+ DOCUMENT_NODE = 9
+ };
+
+ virtual XMLDOMNodeListPtr getChildNodes() = 0;
+ virtual XMLDOMNodeType getNodeType() = 0;
+ virtual XMLDOMDocumentPtr getOwnerDocument() = 0;
+ };
+ LOG4CXX_PTR_DEF(XMLDOMNode);
+
+
+ /**
+ The XMLDOMElement interface represents an element in an XML document
+ */
+ class LOG4CXX_EXPORT XMLDOMElement : virtual public XMLDOMNode
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(XMLDOMElement)
+ virtual LogString getTagName() = 0;
+ virtual LogString getAttribute(const LogString& name) = 0;
+ };
+ LOG4CXX_PTR_DEF(XMLDOMElement);
+
+ /**
+ The XMLDOMDocument interface represents an entire XML document.
+
+ Conceptually, it is the root of the document tree, and provides the
+ primary access to the document's data.
+ */
+ class LOG4CXX_EXPORT XMLDOMDocument : virtual public XMLDOMNode
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(XMLDOMDocument)
+ virtual void load(const File& fileName) = 0;
+ virtual XMLDOMElementPtr getDocumentElement() = 0;
+ virtual XMLDOMElementPtr getElementById(const LogString& tagName,
+ const LogString& elementId) = 0;
+ };
+ LOG4CXX_PTR_DEF(XMLDOMDocument);
+
+ /**
+ The XMLDOMNodeList interface provides the abstraction of an ordered
+ collection of nodes, without defining or constraining how this
+ collection is implemented.
+
+ XMLDOMNodeList objects in the DOM are live.
+
+ The items in the XMLDOMNodeList are accessible via an integral index,
+ starting from 0.
+ */
+ class LOG4CXX_EXPORT XMLDOMNodeList : virtual public Object
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(XMLDOMNodeList)
+ virtual int getLength() = 0;
+ virtual XMLDOMNodePtr item(int index) = 0;
+ };
+ LOG4CXX_PTR_DEF(XMLDOMNodeList);
+ } // namespace helpers
+} // namespace log4cxx
+
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif // _LOG4CXX_HELPERS_XML_H
+
diff --git a/src/main/include/log4cxx/hierarchy.h b/src/main/include/log4cxx/hierarchy.h
new file mode 100644
index 0000000..ff6854d
--- /dev/null
+++ b/src/main/include/log4cxx/hierarchy.h
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HIERARCHY_H
+#define _LOG4CXX_HIERARCHY_H
+
+#if defined(_MSC_VER)
+#pragma warning (push)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/spi/loggerrepository.h>
+#include <log4cxx/spi/loggerfactory.h>
+#include <vector>
+#include <map>
+#include <log4cxx/provisionnode.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/spi/hierarchyeventlistener.h>
+#include <log4cxx/helpers/pool.h>
+
+namespace log4cxx
+{
+ /**
+ This class is specialized in retrieving loggers by name and also
+ maintaining the logger hierarchy.
+
+ <p><em>The casual user does not have to deal with this class
+ directly.</em>
+
+ <p>The structure of the logger hierarchy is maintained by the
+ #getLogger 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.
+
+ <p>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 LOG4CXX_EXPORT Hierarchy :
+ public virtual spi::LoggerRepository,
+ public virtual helpers::ObjectImpl
+ {
+ private:
+ log4cxx::helpers::Pool pool;
+ log4cxx::helpers::Mutex mutex;
+ bool configured;
+
+ spi::LoggerFactoryPtr defaultFactory;
+ spi::HierarchyEventListenerList listeners;
+
+ typedef std::map<LogString, LoggerPtr> LoggerMap;
+ LoggerMap* loggers;
+
+ typedef std::map<LogString, ProvisionNode> ProvisionNodeMap;
+ ProvisionNodeMap* provisionNodes;
+
+ LoggerPtr root;
+
+ int thresholdInt;
+ LevelPtr threshold;
+
+ bool emittedNoAppenderWarning;
+ bool emittedNoResourceBundleWarning;
+
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(Hierarchy)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(spi::LoggerRepository)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ Create a new logger hierarchy.
+ */
+ Hierarchy();
+
+ ~Hierarchy();
+
+ void addRef() const;
+ void releaseRef() const;
+
+ void addHierarchyEventListener(const spi::HierarchyEventListenerPtr& listener);
+
+ /**
+ This call will clear all logger definitions from the internal
+ hashtable. Invoking this method will irrevocably mess up the
+ logger hierarchy.
+
+ <p>You should <em>really</em> know what you are doing before
+ invoking this method.
+ */
+ void clear();
+
+ void emitNoAppenderWarning(const LoggerPtr& logger);
+
+ /**
+ Check if the named logger exists in the hierarchy. If so return
+ its reference, otherwise returns <code>null</code>.
+
+ @param name The name of the logger to search for.
+
+ */
+ LoggerPtr exists(const LogString& name);
+
+ /**
+ The string form of {@link #setThreshold(const LevelPtr&) setThreshold}.
+ */
+ void setThreshold(const LogString& levelStr);
+
+ /**
+ Enable logging for logging requests with level <code>l</code> or
+ higher. By default all levels are enabled.
+
+ @param l The minimum level for which logging requests are sent to
+ their appenders. */
+ void setThreshold(const LevelPtr& l);
+
+ void fireAddAppenderEvent(const LoggerPtr& logger, const AppenderPtr& appender);
+
+ void fireRemoveAppenderEvent(const LoggerPtr& logger,
+ const AppenderPtr& appender);
+
+ /**
+ Returns a Level representation of the <code>enable</code>
+ state.
+ */
+ const LevelPtr& getThreshold() const;
+
+ /**
+ Return a new logger instance named as the first parameter using
+ the default factory.
+
+ <p>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.
+
+ */
+ LoggerPtr getLogger(const LogString& name);
+
+ /**
+ Return a new logger instance named as the first parameter using
+ <code>factory</code>.
+
+ <p>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.
+
+ */
+ LoggerPtr getLogger(const LogString& name,
+ const spi::LoggerFactoryPtr& factory);
+
+ /**
+ Returns all the currently defined loggers in this hierarchy as
+ a LoggerList.
+
+ <p>The root logger is <em>not</em> included in the returned
+ LoggerList. */
+ LoggerList getCurrentLoggers() const;
+
+ /**
+ Get the root of this hierarchy.
+ */
+ LoggerPtr getRootLogger() const;
+
+ /**
+ This method will return <code>true</code> if this repository is
+ disabled for <code>level</code> object passed as parameter and
+ <code>false</code> otherwise. See also the
+ {@link #setThreshold(const LevelPtr&) setThreshold} method. */
+ bool isDisabled(int level) const;
+
+ /**
+ Reset all values contained in this hierarchy instance to their
+ default. This removes all appenders from all categories, sets
+ the level of all non-root categories to <code>null</code>,
+ sets their additivity flag to <code>true</code> and sets the level
+ of the root logger to DEBUG. Moreover,
+ message disabling is set its default "off" value.
+
+ <p>Existing categories are not removed. They are just reset.
+
+ <p>This method should be used sparingly and with care as it will
+ block all logging until it is completed.</p>
+ */
+ void resetConfiguration();
+
+ /**
+ Used by subclasses to add a renderer to the hierarchy passed as parameter.
+ */
+ /**
+ Shutting down a hierarchy will <em>safely</em> close and remove
+ all appenders in all categories including the root logger.
+
+ <p>Some appenders such as {@link net::SocketAppender SocketAppender}
+ and AsyncAppender need to be closed before the
+ application exists. Otherwise, pending logging events might be
+ lost.
+
+ <p>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.
+ */
+ void shutdown();
+
+
+ virtual bool isConfigured();
+ virtual void setConfigured(bool configured);
+
+
+ private:
+
+ /**
+ This method loops through all the *potential* parents of
+ 'cat'. There 3 possible cases:
+
+ 1) No entry for the potential parent of 'cat' exists
+
+ We create a ProvisionNode for this potential parent and insert
+ 'cat' in that provision node.
+
+ 2) There entry is of type Logger for the potential parent.
+
+ The entry is 'cat's nearest existing parent. We update cat'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 'cat' to the list of children for this potential parent.
+ */
+ void updateParents(LoggerPtr logger);
+
+ /**
+ We update the links for all the children that placed themselves
+ in the provision node 'pn'. The second argument 'cat' 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
+ 'cat' then there is no need to update 'c'.
+
+ Otherwise, we set cat's parent field to c's parent and set
+ c's parent field to cat.
+ */
+ Hierarchy(const Hierarchy&);
+ Hierarchy& operator=(const Hierarchy&);
+
+ void updateChildren(ProvisionNode& pn, LoggerPtr logger);
+ };
+
+} //namespace log4cxx
+
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+#endif //_LOG4CXX_HIERARCHY_H
diff --git a/src/main/include/log4cxx/htmllayout.h b/src/main/include/log4cxx/htmllayout.h
new file mode 100644
index 0000000..8c0c6a7
--- /dev/null
+++ b/src/main/include/log4cxx/htmllayout.h
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HTML_LAYOUT_H
+#define _LOG4CXX_HTML_LAYOUT_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/layout.h>
+#include <log4cxx/helpers/iso8601dateformat.h>
+
+
+
+namespace log4cxx
+{
+ /**
+ This layout outputs events in a HTML table.
+ */
+ class LOG4CXX_EXPORT HTMLLayout : public Layout
+ {
+ private:
+ // Print no location info by default
+ bool locationInfo; //= false
+
+ LogString title;
+
+ helpers::ISO8601DateFormat dateFormat;
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(HTMLLayout)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(HTMLLayout)
+ LOG4CXX_CAST_ENTRY_CHAIN(Layout)
+ END_LOG4CXX_CAST_MAP()
+
+ HTMLLayout();
+
+ /**
+ The <b>LocationInfo</b> option takes a boolean value. By
+ default, it is set to false which means there will be no location
+ information output by this layout. If the the option is set to
+ true, then the file name and line number of the statement
+ at the origin of the log statement will be output.
+
+ <p>If you are embedding this layout within an
+ {@link net::SMTPAppender SMTPAppender} then make sure
+ to set the <b>LocationInfo</b> option of that appender as well.
+ */
+ inline void setLocationInfo(bool locationInfoFlag)
+ { this->locationInfo = locationInfoFlag; }
+
+ /**
+ Returns the current value of the <b>LocationInfo</b> option.
+ */
+ inline bool getLocationInfo() const
+ { return locationInfo; }
+
+ /**
+ The <b>Title</b> option takes a String value. This option sets the
+ document title of the generated HTML document.
+ <p>Defaults to 'Log4cxx Log Messages'.
+ */
+ inline void setTitle(const LogString& title1)
+ { this->title.assign(title1); }
+
+ /**
+ Returns the current value of the <b>Title</b> option.
+ */
+ inline const LogString& getTitle() const
+ { return title; }
+
+ /**
+ Returns the content type output by this layout, i.e "text/html".
+ */
+ virtual LogString getContentType() const { return LOG4CXX_STR("text/html"); }
+
+ /**
+ No options to activate.
+ */
+ virtual void activateOptions(log4cxx::helpers::Pool& /* p */) {}
+
+ /**
+ Set options
+ */
+ virtual void setOption(const LogString& option, const LogString& value);
+
+ virtual void format(LogString& output,
+ const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool) const;
+
+ /**
+ Append appropriate HTML headers.
+ */
+ virtual void appendHeader(LogString& output, log4cxx::helpers::Pool& pool);
+
+ /**
+ Append the appropriate HTML footers.
+ */
+ virtual void appendFooter(LogString& output, log4cxx::helpers::Pool& pool);
+
+ /**
+ The HTML layout handles the throwable contained in logging
+ events. Hence, this method return <code>false</code>. */
+ virtual bool ignoresThrowable() const
+ { return false; }
+
+ }; // class HtmlLayout
+ LOG4CXX_PTR_DEF(HTMLLayout);
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+#endif // _LOG4CXX_HTML_LAYOUT_H
diff --git a/src/main/include/log4cxx/layout.h b/src/main/include/log4cxx/layout.h
new file mode 100644
index 0000000..b07d650
--- /dev/null
+++ b/src/main/include/log4cxx/layout.h
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_LAYOUT_H
+#define _LOG4CXX_LAYOUT_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/spi/optionhandler.h>
+#include <log4cxx/spi/loggingevent.h>
+
+
+namespace log4cxx
+{
+ /**
+ Extend this abstract class to create your own log layout format.
+ */
+ class LOG4CXX_EXPORT Layout :
+ public virtual spi::OptionHandler,
+ public virtual helpers::ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(Layout)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(Layout)
+ LOG4CXX_CAST_ENTRY(spi::OptionHandler)
+ END_LOG4CXX_CAST_MAP()
+
+ virtual ~Layout();
+ void addRef() const;
+ void releaseRef() const;
+
+
+ /**
+ Implement this method to create your own layout format.
+ */
+ virtual void format(LogString& output,
+ const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool) const = 0;
+
+ /**
+ Returns the content type output by this layout. The base class
+ returns "text/plain".
+ */
+ virtual LogString getContentType() const;
+
+ /**
+ Append the header for the layout format. The base class does
+ nothing.
+ */
+ virtual void appendHeader(LogString& output, log4cxx::helpers::Pool& p);
+
+ /**
+ Append the footer for the layout format. The base class does
+ nothing.
+ */
+ virtual void appendFooter(LogString& output, log4cxx::helpers::Pool& p);
+
+ /**
+ If the layout handles the throwable object contained within
+ {@link spi::LoggingEvent LoggingEvent}, then the layout should return
+ <code>false</code>. Otherwise, if the layout ignores throwable
+ object, then the layout should return <code>true</code>.
+
+ <p>The SimpleLayout, TTCCLayout,
+ PatternLayout all return <code>true</code>. The {@link
+ xml::XMLLayout XMLLayout} returns <code>false</code>.
+ */
+ virtual bool ignoresThrowable() const = 0;
+ };
+ LOG4CXX_PTR_DEF(Layout);
+}
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif // _LOG4CXX_LAYOUT_H
diff --git a/src/main/include/log4cxx/level.h b/src/main/include/log4cxx/level.h
new file mode 100644
index 0000000..e675e45
--- /dev/null
+++ b/src/main/include/log4cxx/level.h
@@ -0,0 +1,285 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_LEVEL_H
+#define _LOG4CXX_LEVEL_H
+
+
+#include <log4cxx/logstring.h>
+#include <limits.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/helpers/objectptr.h>
+
+
+namespace log4cxx
+{
+ class Level;
+ /** smart pointer to a Level instance */
+ LOG4CXX_PTR_DEF(Level);
+
+ /**
+ Defines the minimum set of levels recognized by the system, that is
+ <code>OFF</code>, <code>FATAL</code>, <code>ERROR</code>,
+ <code>WARN</code>, <code>INFO</code>, <code>DEBUG</code> and
+ <code>ALL</code>.
+ <p>The <code>Level</code> class may be subclassed to define a larger
+ level set.
+ */
+ class LOG4CXX_EXPORT Level : public helpers::ObjectImpl
+ {
+ public:
+ class LOG4CXX_EXPORT LevelClass : public helpers::Class
+ {
+ public:
+ LevelClass() : helpers::Class() {}
+
+ virtual LogString getName() const {
+ return LOG4CXX_STR("Level");
+ }
+
+ virtual LevelPtr toLevel(const LogString& sArg) const
+ { return Level::toLevelLS(sArg); }
+
+ virtual LevelPtr toLevel(int val) const
+ { return Level::toLevel(val); }
+ };
+
+ DECLARE_LOG4CXX_OBJECT_WITH_CUSTOM_CLASS(Level, LevelClass)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(Level)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ Instantiate a Level object.
+ */
+ Level(int level,
+ const LogString& name,
+ int syslogEquivalent);
+
+ /**
+ Convert the string passed as argument to a level. If the
+ conversion fails, then this method returns DEBUG.
+ * @param sArg level name.
+ */
+ static LevelPtr toLevel(const std::string& sArg);
+ /**
+ Convert the string passed as argument to a level. If the
+ conversion fails, then this method returns the value of
+ <code>defaultLevel</code>.
+ * @param sArg level name.
+ * @param defaultLevel level to return if no match.
+ * @return
+ */
+ static LevelPtr toLevel(const std::string& sArg,
+ const LevelPtr& defaultLevel);
+ /**
+ * Get the name of the level in the current encoding.
+ * @param name buffer to which name is appended.
+ */
+ void toString(std::string& name) const;
+
+#if LOG4CXX_WCHAR_T_API
+ /**
+ Convert the string passed as argument to a level. If the
+ conversion fails, then this method returns DEBUG.
+ * @param sArg level name.
+ */
+ static LevelPtr toLevel(const std::wstring& sArg);
+ /**
+ Convert the string passed as argument to a level. If the
+ conversion fails, then this method returns the value of
+ <code>defaultLevel</code>.
+ * @param sArg level name.
+ * @param defaultLevel level to return if no match.
+ * @return
+ */
+ static LevelPtr toLevel(const std::wstring& sArg,
+ const LevelPtr& defaultLevel);
+ /**
+ * Get the name of the level.
+ * @param name buffer to which name is appended.
+ */
+ void toString(std::wstring& name) const;
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ Convert the string passed as argument to a level. If the
+ conversion fails, then this method returns DEBUG.
+ * @param sArg level name.
+ */
+ static LevelPtr toLevel(const std::basic_string<UniChar>& sArg);
+ /**
+ Convert the string passed as argument to a level. If the
+ conversion fails, then this method returns the value of
+ <code>defaultLevel</code>.
+ * @param sArg level name.
+ * @param defaultLevel level to return if no match.
+ * @return
+ */
+ static LevelPtr toLevel(const std::basic_string<UniChar>& sArg,
+ const LevelPtr& defaultLevel);
+ /**
+ * Get the name of the level.
+ * @param name buffer to which name is appended.
+ */
+ void toString(std::basic_string<UniChar>& name) const;
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ Convert the string passed as argument to a level. If the
+ conversion fails, then this method returns DEBUG.
+ * @param sArg level name.
+ */
+ static LevelPtr toLevel(const CFStringRef& sArg);
+ /**
+ Convert the string passed as argument to a level. If the
+ conversion fails, then this method returns the value of
+ <code>defaultLevel</code>.
+ * @param sArg level name.
+ * @param defaultLevel level to return if no match.
+ * @return
+ */
+ static LevelPtr toLevel(const CFStringRef& sArg,
+ const LevelPtr& defaultLevel);
+ /**
+ * Get the name of the level.
+ * @param name buffer to which name is appended.
+ */
+ void toString(CFStringRef& name) const;
+#endif
+ /**
+ Convert the string passed as argument to a level. If the
+ conversion fails, then this method returns DEBUG.
+ * @param sArg level name.
+ */
+ static LevelPtr toLevelLS(const LogString& sArg);
+ /**
+ Convert the string passed as argument to a level. If the
+ conversion fails, then this method returns the value of
+ <code>defaultLevel</code>.
+ * @param sArg level name.
+ * @param defaultLevel level to return if no match.
+ * @return
+ */
+ static LevelPtr toLevelLS(const LogString& sArg,
+ const LevelPtr& defaultLevel);
+ /**
+ Returns the string representation of this level.
+ * @return level name.
+ */
+ LogString toString() const;
+
+ /**
+ Convert an integer passed as argument to a level. If the
+ conversion fails, then this method returns DEBUG.
+ */
+ static LevelPtr toLevel(int val);
+
+ /**
+ Convert an integer passed as argument to a level. If the
+ conversion fails, then this method returns the specified default.
+ */
+ static LevelPtr toLevel(int val, const LevelPtr& defaultLevel);
+
+ enum {
+ OFF_INT = INT_MAX,
+ FATAL_INT = 50000,
+ ERROR_INT = 40000,
+ WARN_INT = 30000,
+ INFO_INT = 20000,
+ DEBUG_INT = 10000,
+ TRACE_INT = 5000,
+ ALL_INT = INT_MIN
+ };
+
+
+ static LevelPtr getAll();
+ static LevelPtr getFatal();
+ static LevelPtr getError();
+ static LevelPtr getWarn();
+ static LevelPtr getInfo();
+ static LevelPtr getDebug();
+ static LevelPtr getTrace();
+ static LevelPtr getOff();
+
+
+ /**
+ Two levels are equal if their level fields are equal.
+ */
+ virtual bool equals(const LevelPtr& level) const;
+
+ inline bool operator==(const Level& level1) const
+ { return (this->level == level1.level); }
+
+ inline bool operator!=(const Level& level1) const
+ { return (this->level != level1.level); }
+
+ /**
+ Return the syslog equivalent of this level as an integer.
+ */
+ inline int getSyslogEquivalent() const {
+ return syslogEquivalent;
+ }
+
+
+ /**
+ Returns <code>true</code> if this level has a higher or equal
+ level than the level passed as argument, <code>false</code>
+ otherwise.
+
+ <p>You should think twice before overriding the default
+ implementation of <code>isGreaterOrEqual</code> method.
+
+ */
+ virtual bool isGreaterOrEqual(const LevelPtr& level) const;
+
+
+ /**
+ Returns the integer representation of this level.
+ */
+ inline int toInt() const {
+ return level;
+ }
+
+ private:
+ int level;
+ LogString name;
+ int syslogEquivalent;
+ Level(const Level&);
+ Level& operator=(const Level&);
+ };
+}
+
+#define DECLARE_LOG4CXX_LEVEL(level)\
+public:\
+ class Class##level : public Level::LevelClass\
+{\
+public:\
+ Class##level() : Level::LevelClass() {}\
+ virtual LogString getName() const { return LOG4CXX_STR(#level); } \
+ virtual LevelPtr toLevel(const LogString& sArg) const\
+ { return level::toLevelLS(sArg); }\
+ virtual LevelPtr toLevel(int val) const\
+ { return level::toLevel(val); }\
+};\
+DECLARE_LOG4CXX_OBJECT_WITH_CUSTOM_CLASS(level, Class##level)
+
+#define IMPLEMENT_LOG4CXX_LEVEL(level) \
+IMPLEMENT_LOG4CXX_OBJECT_WITH_CUSTOM_CLASS(level, Class##level)
+
+
+#endif //_LOG4CXX_LEVEL_H
diff --git a/src/main/include/log4cxx/log4cxx.h.in b/src/main/include/log4cxx/log4cxx.h.in
new file mode 100644
index 0000000..4260631
--- /dev/null
+++ b/src/main/include/log4cxx/log4cxx.h.in
@@ -0,0 +1,51 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 LOG4CXX_LOG4CXX_H
+#define LOG4CXX_LOG4CXX_H
+
+/* GENERATED FILE WARNING! DO NOT EDIT log4cxx.h
+ *
+ * Edit log4cxx.h.in instead
+ *
+ */
+
+
+#define LOG4CXX_LOGCHAR_IS_UNICHAR @LOGCHAR_IS_UNICHAR@
+#define LOG4CXX_LOGCHAR_IS_UTF8 @LOGCHAR_IS_UTF8@
+#define LOG4CXX_LOGCHAR_IS_WCHAR @LOGCHAR_IS_WCHAR@
+
+#define LOG4CXX_CHAR_API @CHAR_API@
+#define LOG4CXX_WCHAR_T_API @WCHAR_T_API@
+#define LOG4CXX_UNICHAR_API @UNICHAR_API@
+#define LOG4CXX_CFSTRING_API @CFSTRING_API@
+
+
+typedef long long log4cxx_int64_t;
+#define LOG4CXX_USE_GLOBAL_SCOPE_TEMPLATE 0
+#define LOG4CXX_LOGSTREAM_ADD_NOP 0
+typedef log4cxx_int64_t log4cxx_time_t;
+typedef int log4cxx_status_t;
+typedef unsigned int log4cxx_uint32_t;
+
+
+#define LOG4CXX_EXPORT
+#define LOG4CXX_PTR_DEF(T) typedef log4cxx::helpers::ObjectPtrT<T> T##Ptr
+#define LOG4CXX_LIST_DEF(N, T) typedef std::vector<T> N
+
+
+#endif
diff --git a/src/main/include/log4cxx/log4cxx.hw b/src/main/include/log4cxx/log4cxx.hw
new file mode 100644
index 0000000..670cd32
--- /dev/null
+++ b/src/main/include/log4cxx/log4cxx.hw
@@ -0,0 +1,99 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 LOG4CXX_LOG4CXX_H
+#define LOG4CXX_LOG4CXX_H
+
+/* GENERATED FILE WARNING! DO NOT EDIT log4cxx.h
+ *
+ * Edit log4cxx.hw instead
+ *
+ */
+
+#define LOG4CXX_LOGCHAR_IS_UTF8 0
+#if LOG4CXX_LOGCHAR_IS_UTF8
+#define LOG4CXX_LOGCHAR_IS_WCHAR 0
+#else
+#define LOG4CXX_LOGCHAR_IS_WCHAR 1
+#endif
+#define LOG4CXX_LOGCHAR_IS_UNICHAR 0
+
+#define LOG4CXX_CHAR_API 1
+#define LOG4CXX_WCHAR_T_API 1
+#define LOG4CXX_UNICHAR_API 0
+#define LOG4CXX_CFSTRING_API 0
+
+#if defined(_MSC_VER)
+typedef __int64 log4cxx_int64_t;
+#if _MSC_VER < 1300
+#define LOG4CXX_USE_GLOBAL_SCOPE_TEMPLATE 1
+#define LOG4CXX_LOGSTREAM_ADD_NOP 1
+#endif
+#elif defined(__BORLANDC__)
+typedef __int64 log4cxx_int64_t;
+#else
+typedef long long log4cxx_int64_t;
+#endif
+
+typedef log4cxx_int64_t log4cxx_time_t;
+typedef int log4cxx_status_t;
+typedef unsigned int log4cxx_uint32_t;
+
+// definitions used when using static library
+#if defined(LOG4CXX_STATIC)
+#define LOG4CXX_EXPORT
+// definitions used when building DLL
+#elif defined(LOG4CXX)
+#define LOG4CXX_EXPORT __declspec(dllexport)
+#else
+// definitions used when using DLL
+#define LOG4CXX_EXPORT __declspec(dllimport)
+#endif
+
+
+//
+// pointer and list definition macros when building DLL using VC
+//
+#if defined(_MSC_VER) && !defined(LOG4CXX_STATIC) && defined(LOG4CXX)
+#define LOG4CXX_PTR_DEF(T) \
+template class LOG4CXX_EXPORT log4cxx::helpers::ObjectPtrT<T>; \
+typedef log4cxx::helpers::ObjectPtrT<T> T##Ptr
+#define LOG4CXX_LIST_DEF(N, T) \
+template class LOG4CXX_EXPORT std::allocator<T>; \
+template class LOG4CXX_EXPORT std::vector<T>; \
+typedef std::vector<T> N
+//
+// pointer and list definition macros when linking with DLL using VC
+//
+#elif defined(_MSC_VER) && !defined(LOG4CXX_STATIC)
+#define LOG4CXX_PTR_DEF(T) \
+extern template class LOG4CXX_EXPORT log4cxx::helpers::ObjectPtrT<T>; \
+typedef log4cxx::helpers::ObjectPtrT<T> T##Ptr
+#define LOG4CXX_LIST_DEF(N, T) \
+extern template class LOG4CXX_EXPORT std::allocator<T>; \
+extern template class LOG4CXX_EXPORT std::vector<T>; \
+typedef std::vector<T> N
+//
+// pointer and list definition macros for all other cases
+//
+#else
+#define LOG4CXX_PTR_DEF(T) typedef log4cxx::helpers::ObjectPtrT<T> T##Ptr
+#define LOG4CXX_LIST_DEF(N, T) typedef std::vector<T> N
+#endif
+
+
+#endif
+
diff --git a/src/main/include/log4cxx/logger.h b/src/main/include/log4cxx/logger.h
new file mode 100644
index 0000000..d5b5007
--- /dev/null
+++ b/src/main/include/log4cxx/logger.h
@@ -0,0 +1,1911 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_LOGGER_H
+#define _LOG4CXX_LOGGER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/helpers/appenderattachableimpl.h>
+#include <log4cxx/level.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/mutex.h>
+#include <log4cxx/spi/location/locationinfo.h>
+#include <log4cxx/helpers/resourcebundle.h>
+#include <log4cxx/helpers/messagebuffer.h>
+
+
+namespace log4cxx
+{
+
+ namespace helpers {
+ class synchronized;
+ }
+
+ namespace spi {
+ class LoggerRepository;
+ LOG4CXX_PTR_DEF(LoggerRepository);
+ class LoggerFactory;
+ LOG4CXX_PTR_DEF(LoggerFactory);
+ }
+
+ class Logger;
+ /** smart pointer to a Logger class */
+ LOG4CXX_PTR_DEF(Logger);
+ LOG4CXX_LIST_DEF(LoggerList, LoggerPtr);
+
+
+ /**
+ This is the central class in the log4cxx package. Most logging
+ operations, except configuration, are done through this class.
+ */
+ class LOG4CXX_EXPORT Logger :
+ public virtual log4cxx::spi::AppenderAttachable,
+ public virtual helpers::ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(Logger)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(Logger)
+ LOG4CXX_CAST_ENTRY(spi::AppenderAttachable)
+ END_LOG4CXX_CAST_MAP()
+
+ private:
+ /**
+ * Reference to memory pool.
+ */
+ helpers::Pool* pool;
+
+ protected:
+ /**
+ The name of this logger.
+ */
+ LogString name;
+
+ /**
+ The assigned level of this logger. The
+ <code>level</code> variable need not be assigned a value in
+ which case it is inherited form the hierarchy. */
+ LevelPtr level;
+
+ /**
+ The parent of this logger. All loggers have at least one
+ ancestor which is the root logger. */
+ LoggerPtr parent;
+
+ /** The resourceBundle for localized messages.
+
+ @see setResourceBundle, getResourceBundle
+ */
+ helpers::ResourceBundlePtr resourceBundle;
+
+
+ // Loggers need to know what Hierarchy they are in
+ log4cxx::spi::LoggerRepository * repository;
+
+ helpers::AppenderAttachableImplPtr aai;
+
+ /** 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;
+
+ protected:
+ friend class DefaultLoggerFactory;
+
+ /**
+ This constructor created a new <code>logger</code> instance and
+ sets its name.
+
+ <p>It is intended to be used by sub-classes only. You should not
+ create categories directly.
+
+ @param pool lifetime of pool must be longer than logger.
+ @param name The name of the logger.
+ */
+ Logger(log4cxx::helpers::Pool& pool, const LogString& name);
+
+ public:
+ ~Logger();
+
+
+ void addRef() const;
+ void releaseRef() const;
+
+ /**
+ Add <code>newAppender</code> to the list of appenders of this
+ Logger instance.
+
+ <p>If <code>newAppender</code> is already in the list of
+ appenders, then it won't be added again.
+ */
+ virtual void addAppender(const AppenderPtr& newAppender);
+
+
+ /**
+ Call the appenders in the hierrachy starting at
+ <code>this</code>. If no appenders could be found, emit a
+ warning.
+
+ <p>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.
+ @param p memory pool for any allocations needed to process request.
+ */
+ void callAppenders(const log4cxx::spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) const;
+
+ /**
+ Close all attached appenders implementing the AppenderAttachable
+ interface.
+ */
+ void closeNestedAppenders();
+
+ /**
+ Log a message string with the DEBUG level.
+
+ <p>This method first checks if this logger is <code>DEBUG</code>
+ enabled by comparing the level of this logger with the
+ DEBUG level. If this logger is
+ <code>DEBUG</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void debug(const std::string& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the DEBUG level.
+
+ <p>This method first checks if this logger is <code>DEBUG</code>
+ enabled by comparing the level of this logger with the
+ DEBUG level. If this logger is
+ <code>DEBUG</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void debug(const std::string& msg) const;
+#if LOG4CXX_WCHAR_T_API
+ /**
+ Log a message string with the DEBUG level.
+
+ <p>This method first checks if this logger is <code>DEBUG</code>
+ enabled by comparing the level of this logger with the
+ DEBUG level. If this logger is
+ <code>DEBUG</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void debug(const std::wstring& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the DEBUG level.
+
+ <p>This method first checks if this logger is <code>DEBUG</code>
+ enabled by comparing the level of this logger with the
+ DEBUG level. If this logger is
+ <code>DEBUG</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void debug(const std::wstring& msg) const;
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ Log a message string with the DEBUG level.
+
+ <p>This method first checks if this logger is <code>DEBUG</code>
+ enabled by comparing the level of this logger with the
+ DEBUG level. If this logger is
+ <code>DEBUG</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void debug(const std::basic_string<UniChar>& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the DEBUG level.
+
+ <p>This method first checks if this logger is <code>DEBUG</code>
+ enabled by comparing the level of this logger with the
+ DEBUG level. If this logger is
+ <code>DEBUG</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void debug(const std::basic_string<UniChar>& msg) const;
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ Log a message string with the DEBUG level.
+
+ <p>This method first checks if this logger is <code>DEBUG</code>
+ enabled by comparing the level of this logger with the
+ DEBUG level. If this logger is
+ <code>DEBUG</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void debug(const CFStringRef& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the DEBUG level.
+
+ <p>This method first checks if this logger is <code>DEBUG</code>
+ enabled by comparing the level of this logger with the
+ DEBUG level. If this logger is
+ <code>DEBUG</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void debug(const CFStringRef& msg) const;
+#endif
+
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void error(const std::string& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void error(const std::string& msg) const;
+#if LOG4CXX_WCHAR_T_API
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void error(const std::wstring& msg) const;
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void error(const std::wstring& msg, const log4cxx::spi::LocationInfo& location) const;
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void error(const std::basic_string<UniChar>& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void error(const std::basic_string<UniChar>& msg) const;
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void error(const CFStringRef& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void error(const CFStringRef& msg) const;
+#endif
+
+ /**
+ Log a message string with the FATAL level.
+
+ <p>This method first checks if this logger is <code>FATAL</code>
+ enabled by comparing the level of this logger with the
+ FATAL level. If this logger is
+ <code>FATAL</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void fatal(const std::string& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void fatal(const std::string& msg) const;
+#if LOG4CXX_WCHAR_T_API
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void fatal(const std::wstring& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void fatal(const std::wstring& msg) const;
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void fatal(const std::basic_string<UniChar>& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void fatal(const std::basic_string<UniChar>& msg) const;
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void fatal(const CFStringRef& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the ERROR level.
+
+ <p>This method first checks if this logger is <code>ERROR</code>
+ enabled by comparing the level of this logger with the
+ ERROR level. If this logger is
+ <code>ERROR</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void fatal(const CFStringRef& msg) const;
+#endif
+
+ /**
+ This method creates a new logging event and logs the event
+ without further checks.
+ @param level the level to log.
+ @param message message.
+ @param location location of source of logging request.
+ */
+ void forcedLog(const LevelPtr& level, const std::string& message,
+ const log4cxx::spi::LocationInfo& location) const;
+ /**
+ This method creates a new logging event and logs the event
+ without further checks.
+ @param level the level to log.
+ @param message message.
+ */
+ void forcedLog(const LevelPtr& level, const std::string& message) const;
+
+#if LOG4CXX_WCHAR_T_API
+ /**
+ This method creates a new logging event and logs the event
+ without further checks.
+ @param level the level to log.
+ @param message message.
+ @param location location of source of logging request.
+ */
+ void forcedLog(const LevelPtr& level, const std::wstring& message,
+ const log4cxx::spi::LocationInfo& location) const;
+ /**
+ This method creates a new logging event and logs the event
+ without further checks.
+ @param level the level to log.
+ @param message message.
+ */
+ void forcedLog(const LevelPtr& level, const std::wstring& message) const;
+#endif
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+ /**
+ This method creates a new logging event and logs the event
+ without further checks.
+ @param level the level to log.
+ @param message message.
+ @param location location of source of logging request.
+ */
+ void forcedLog(const LevelPtr& level, const std::basic_string<UniChar>& message,
+ const log4cxx::spi::LocationInfo& location) const;
+ /**
+ This method creates a new logging event and logs the event
+ without further checks.
+ @param level the level to log.
+ @param message message.
+ */
+ void forcedLog(const LevelPtr& level, const std::basic_string<UniChar>& message) const;
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ This method creates a new logging event and logs the event
+ without further checks.
+ @param level the level to log.
+ @param message message.
+ @param location location of source of logging request.
+ */
+ void forcedLog(const LevelPtr& level, const CFStringRef& message,
+ const log4cxx::spi::LocationInfo& location) const;
+ /**
+ This method creates a new logging event and logs the event
+ without further checks.
+ @param level the level to log.
+ @param message message.
+ */
+ void forcedLog(const LevelPtr& level, const CFStringRef& message) const;
+#endif
+ /**
+ This method creates a new logging event and logs the event
+ without further checks.
+ @param level the level to log.
+ @param message the message string to log.
+ @param location location of the logging statement.
+ */
+ void forcedLogLS(const LevelPtr& level, const LogString& message,
+ const log4cxx::spi::LocationInfo& location) const;
+
+ /**
+ Get the additivity flag for this Logger instance.
+ */
+ bool getAdditivity() const;
+
+ /**
+ Get the appenders contained in this logger as an AppenderList.
+ If no appenders can be found, then an empty AppenderList
+ is returned.
+ @return AppenderList An collection of the appenders in this logger.*/
+ AppenderList getAllAppenders() const;
+
+ /**
+ Look for the appender named as <code>name</code>.
+ <p>Return the appender with that name if in the list. Return
+ <code>NULL</code> otherwise. */
+ AppenderPtr getAppender(const LogString& name) const;
+
+ /**
+ Starting from this logger, search the logger hierarchy for a
+ non-null level and return it.
+
+ <p>The Logger class is designed so that this method executes as
+ quickly as possible.
+
+ @throws RuntimeException if all levels are null in the hierarchy
+ */
+ virtual const LevelPtr& getEffectiveLevel() const;
+
+ /**
+ Return the the LoggerRepository where this
+ <code>Logger</code> is attached.
+ */
+ log4cxx::spi::LoggerRepositoryPtr getLoggerRepository() const;
+
+
+ /**
+ * Get the logger name.
+ * @return logger name as LogString.
+ */
+ const LogString getName() const { return name; }
+ /**
+ * Get logger name in current encoding.
+ * @param name buffer to which name is appended.
+ */
+ void getName(std::string& name) const;
+#if LOG4CXX_WCHAR_T_API
+ /**
+ * Get logger name.
+ * @param name buffer to which name is appended.
+ */
+ void getName(std::wstring& name) const;
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ * Get logger name.
+ * @param name buffer to which name is appended.
+ */
+ void getName(std::basic_string<UniChar>& name) const;
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ * Get logger name.
+ * @param name buffer to which name is appended.
+ */
+ void getName(CFStringRef& name) const;
+#endif
+
+ /**
+ Returns the parent of this logger. Note that the parent of a
+ given logger may change during the lifetime of the logger.
+
+ <p>The root logger will return <code>0</code>.
+ */
+ LoggerPtr getParent() const;
+
+
+ /**
+ Returns the assigned Level, if any, for this Logger.
+
+ @return Level - the assigned Level, can be null.
+ */
+ LevelPtr getLevel() const;
+
+ /**
+ * Retrieve a logger by name in current encoding.
+ * @param name logger name.
+ */
+ static LoggerPtr getLogger(const std::string& name);
+ /**
+ * Retrieve a logger by name in current encoding.
+ * @param name logger name.
+ */
+ static LoggerPtr getLogger(const char* const name);
+#if LOG4CXX_WCHAR_T_API
+ /**
+ * Retrieve a logger by name.
+ * @param name logger name.
+ */
+ static LoggerPtr getLogger(const std::wstring& name);
+ /**
+ * Retrieve a logger by name.
+ * @param name logger name.
+ */
+ static LoggerPtr getLogger(const wchar_t* const name);
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ * Retrieve a logger by name.
+ * @param name logger name.
+ */
+ static LoggerPtr getLogger(const std::basic_string<UniChar>& name);
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ * Retrieve a logger by name.
+ * @param name logger name.
+ */
+ static LoggerPtr getLogger(const CFStringRef& name);
+#endif
+ /**
+ * Retrieve a logger by name in Unicode.
+ * @param name logger name.
+ */
+ static LoggerPtr getLoggerLS(const LogString& name);
+
+ /**
+ Retrieve the root logger.
+ */
+ static LoggerPtr getRootLogger();
+
+ /**
+ Like #getLogger except that the type of logger
+ instantiated depends on the type returned by the
+ LoggerFactory#makeNewLoggerInstance method of the
+ <code>factory</code> parameter.
+
+ <p>This method is intended to be used by sub-classes.
+
+ @param name The name of the logger to retrieve.
+
+ @param factory A LoggerFactory implementation that will
+ actually create a new Instance.
+ */
+ static LoggerPtr getLoggerLS(const LogString& name,
+ const log4cxx::spi::LoggerFactoryPtr& factory);
+ /**
+ Like #getLogger except that the type of logger
+ instantiated depends on the type returned by the
+ LoggerFactory#makeNewLoggerInstance method of the
+ <code>factory</code> parameter.
+
+ <p>This method is intended to be used by sub-classes.
+
+ @param name The name of the logger to retrieve.
+
+ @param factory A LoggerFactory implementation that will
+ actually create a new Instance.
+ */
+ static LoggerPtr getLogger(const std::string& name,
+ const log4cxx::spi::LoggerFactoryPtr& factory);
+#if LOG4CXX_WCHAR_T_API
+ /**
+ Like #getLogger except that the type of logger
+ instantiated depends on the type returned by the
+ LoggerFactory#makeNewLoggerInstance method of the
+ <code>factory</code> parameter.
+
+ <p>This method is intended to be used by sub-classes.
+
+ @param name The name of the logger to retrieve.
+
+ @param factory A LoggerFactory implementation that will
+ actually create a new Instance.
+ */
+ static LoggerPtr getLogger(const std::wstring& name,
+ const log4cxx::spi::LoggerFactoryPtr& factory);
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ Like #getLogger except that the type of logger
+ instantiated depends on the type returned by the
+ LoggerFactory#makeNewLoggerInstance method of the
+ <code>factory</code> parameter.
+
+ <p>This method is intended to be used by sub-classes.
+
+ @param name The name of the logger to retrieve.
+
+ @param factory A LoggerFactory implementation that will
+ actually create a new Instance.
+ */
+ static LoggerPtr getLogger(const std::basic_string<UniChar>& name,
+ const log4cxx::spi::LoggerFactoryPtr& factory);
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ Like #getLogger except that the type of logger
+ instantiated depends on the type returned by the
+ LoggerFactory#makeNewLoggerInstance method of the
+ <code>factory</code> parameter.
+
+ <p>This method is intended to be used by sub-classes.
+
+ @param name The name of the logger to retrieve.
+
+ @param factory A LoggerFactory implementation that will
+ actually create a new Instance.
+ */
+ static LoggerPtr getLogger(const CFStringRef& name,
+ const log4cxx::spi::LoggerFactoryPtr& factory);
+#endif
+
+ /**
+ Return the <em>inherited</em> ResourceBundle for this logger.
+
+
+ This method walks the hierarchy to find the appropriate resource bundle.
+ It will return the resource bundle attached to the closest ancestor of
+ this logger, much like the way priorities are searched. In case there
+ is no bundle in the hierarchy then <code>NULL</code> is returned.
+ */
+ helpers::ResourceBundlePtr getResourceBundle() const;
+
+ protected:
+ /**
+ Returns the string resource coresponding to <code>key</code> in this
+ logger's inherited resource bundle.
+
+ If the resource cannot be found, then an {@link #error error} message
+ will be logged complaining about the missing resource.
+
+ @see #getResourceBundle.
+ */
+ LogString getResourceBundleString(const LogString& key) const;
+
+ public:
+ /**
+ Log a message string with the INFO level.
+
+ <p>This method first checks if this logger is <code>INFO</code>
+ enabled by comparing the level of this logger with the
+ INFO level. If this logger is
+ <code>INFO</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void info(const std::string& msg, const log4cxx::spi::LocationInfo& location) const;
+ void info(const std::string& msg) const;
+#if LOG4CXX_WCHAR_T_API
+ /**
+ Log a message string with the INFO level.
+
+ <p>This method first checks if this logger is <code>INFO</code>
+ enabled by comparing the level of this logger with the
+ INFO level. If this logger is
+ <code>INFO</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void info(const std::wstring& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the INFO level.
+
+ <p>This method first checks if this logger is <code>INFO</code>
+ enabled by comparing the level of this logger with the
+ INFO level. If this logger is
+ <code>INFO</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void info(const std::wstring& msg) const;
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ Log a message string with the INFO level.
+
+ <p>This method first checks if this logger is <code>INFO</code>
+ enabled by comparing the level of this logger with the
+ INFO level. If this logger is
+ <code>INFO</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void info(const std::basic_string<UniChar>& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the INFO level.
+
+ <p>This method first checks if this logger is <code>INFO</code>
+ enabled by comparing the level of this logger with the
+ INFO level. If this logger is
+ <code>INFO</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void info(const std::basic_string<UniChar>& msg) const;
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ Log a message string with the INFO level.
+
+ <p>This method first checks if this logger is <code>INFO</code>
+ enabled by comparing the level of this logger with the
+ INFO level. If this logger is
+ <code>INFO</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void info(const CFStringRef& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the INFO level.
+
+ <p>This method first checks if this logger is <code>INFO</code>
+ enabled by comparing the level of this logger with the
+ INFO level. If this logger is
+ <code>INFO</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void info(const CFStringRef& msg) const;
+#endif
+
+ /**
+ Is the appender passed as parameter attached to this logger?
+ */
+ bool isAttached(const AppenderPtr& appender) const;
+
+ /**
+ * Check whether this logger is enabled for the <code>DEBUG</code>
+ * Level.
+ *
+ * <p> This function is intended to lessen the computational cost of
+ * disabled log debug statements.
+ *
+ * <p> For some <code>logger</code> Logger object, when you write,
+ * <pre>
+ * logger->debug("debug message");
+ * </pre>
+ *
+ * <p>You incur the cost constructing the message, concatenation in
+ * this case, regardless of whether the message is logged or not.
+ *
+ * <p>If you are worried about speed, then you should write
+ * <pre>
+ * if(logger->isDebugEnabled()) {
+ * logger->debug("debug message");
+ * }
+ * </pre>
+ *
+ * <p>This way you will not incur the cost of parameter
+ * construction if debugging is disabled for <code>logger</code>. On
+ * the other hand, if the <code>logger</code> is debug enabled, you
+ * will incur the cost of evaluating whether the logger is debug
+ * enabled twice. Once in <code>isDebugEnabled</code> and once in
+ * the <code>debug</code>. This is an insignificant overhead
+ * since evaluating a logger takes about 1%% of the time it
+ * takes to actually log.
+ *
+ * @return bool - <code>true</code> if this logger is debug
+ * enabled, <code>false</code> otherwise.
+ * */
+ bool isDebugEnabled() const;
+
+ /**
+ Check whether this logger is enabled for a given
+ Level passed as parameter.
+
+ See also #isDebugEnabled.
+
+ @return bool True if this logger is enabled for <code>level</code>.
+ */
+ bool isEnabledFor(const LevelPtr& level) const;
+
+
+ /**
+ Check whether this logger is enabled for the info Level.
+ See also #isDebugEnabled.
+
+ @return bool - <code>true</code> if this logger is enabled
+ for level info, <code>false</code> otherwise.
+ */
+ bool isInfoEnabled() const;
+
+ /**
+ Check whether this logger is enabled for the warn Level.
+ See also #isDebugEnabled.
+
+ @return bool - <code>true</code> if this logger is enabled
+ for level warn, <code>false</code> otherwise.
+ */
+ bool isWarnEnabled() const;
+
+ /**
+ Check whether this logger is enabled for the error Level.
+ See also #isDebugEnabled.
+
+ @return bool - <code>true</code> if this logger is enabled
+ for level error, <code>false</code> otherwise.
+ */
+ bool isErrorEnabled() const;
+
+ /**
+ Check whether this logger is enabled for the fatal Level.
+ See also #isDebugEnabled.
+
+ @return bool - <code>true</code> if this logger is enabled
+ for level fatal, <code>false</code> otherwise.
+ */
+ bool isFatalEnabled() const;
+
+ /**
+ Check whether this logger is enabled for the trace level.
+ See also #isDebugEnabled.
+
+ @return bool - <code>true</code> if this logger is enabled
+ for level trace, <code>false</code> otherwise.
+ */
+ bool isTraceEnabled() const;
+
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+ @param values The values for the placeholders <code>{0}</code>,
+ <code>{1}</code> etc. within the pattern.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const LogString& key,
+ const log4cxx::spi::LocationInfo& locationInfo,
+ const std::vector<LogString>& values) const;
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const std::string& key,
+ const log4cxx::spi::LocationInfo& locationInfo) const;
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+ @param val1 The first value for the placeholders within the pattern.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const std::string& key,
+ const log4cxx::spi::LocationInfo& locationInfo,
+ const std::string& val1) const;
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+ @param val1 The first value for the placeholders within the pattern.
+ @param val2 The second value for the placeholders within the pattern.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const std::string& key,
+ const log4cxx::spi::LocationInfo& locationInfo,
+ const std::string& val1, const std::string& val2) const;
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+ @param val1 The value for the first placeholder within the pattern.
+ @param val2 The value for the second placeholder within the pattern.
+ @param val3 The value for the third placeholder within the pattern.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const std::string& key,
+ const log4cxx::spi::LocationInfo& locationInfo,
+ const std::string& val1, const std::string& val2, const std::string& val3) const;
+
+#if LOG4CXX_WCHAR_T_API
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const std::wstring& key,
+ const log4cxx::spi::LocationInfo& locationInfo) const;
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+ @param val1 The value for the first placeholder within the pattern.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const std::wstring& key,
+ const log4cxx::spi::LocationInfo& locationInfo,
+ const std::wstring& val1) const;
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+ @param val1 The value for the first placeholder within the pattern.
+ @param val2 The value for the second placeholder within the pattern.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const std::wstring& key,
+ const log4cxx::spi::LocationInfo& locationInfo,
+ const std::wstring& val1, const std::wstring& val2) const;
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+ @param val1 The value for the first placeholder within the pattern.
+ @param val2 The value for the second placeholder within the pattern.
+ @param val3 The value for the third placeholder within the pattern.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const std::wstring& key,
+ const log4cxx::spi::LocationInfo& locationInfo,
+ const std::wstring& val1, const std::wstring& val2, const std::wstring& val3) const;
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const std::basic_string<UniChar>& key,
+ const log4cxx::spi::LocationInfo& locationInfo) const;
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+ @param val1 The value for the first placeholder within the pattern.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const std::basic_string<UniChar>& key,
+ const log4cxx::spi::LocationInfo& locationInfo,
+ const std::basic_string<UniChar>& val1) const;
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+ @param val1 The value for the first placeholder within the pattern.
+ @param val2 The value for the second placeholder within the pattern.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const std::basic_string<UniChar>& key,
+ const log4cxx::spi::LocationInfo& locationInfo,
+ const std::basic_string<UniChar>& val1, const std::basic_string<UniChar>& val2) const;
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+ @param val1 The value for the first placeholder within the pattern.
+ @param val2 The value for the second placeholder within the pattern.
+ @param val3 The value for the third placeholder within the pattern.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const std::basic_string<UniChar>& key,
+ const log4cxx::spi::LocationInfo& locationInfo,
+ const std::basic_string<UniChar>& val1, const std::basic_string<UniChar>& val2,
+ const std::basic_string<UniChar>& val3) const;
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const CFStringRef& key,
+ const log4cxx::spi::LocationInfo& locationInfo) const;
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+ @param val1 The value for the first placeholder within the pattern.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const CFStringRef& key,
+ const log4cxx::spi::LocationInfo& locationInfo,
+ const CFStringRef& val1) const;
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+ @param val1 The value for the first placeholder within the pattern.
+ @param val2 The value for the second placeholder within the pattern.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const CFStringRef& key,
+ const log4cxx::spi::LocationInfo& locationInfo,
+ const CFStringRef& val1, const CFStringRef& val2) const;
+ /**
+ Log a localized and parameterized message.
+
+ First, the user supplied
+ <code>key</code> is searched in the resource bundle. Next, the resulting
+ pattern is formatted using helpers::StringHelper::format method with the user
+ supplied string array <code>params</code>.
+
+ @param level The level of the logging request.
+ @param key The key to be searched in the ResourceBundle.
+ @param locationInfo The location info of the logging request.
+ @param val1 The value for the first placeholder within the pattern.
+ @param val2 The value for the second placeholder within the pattern.
+ @param val3 The value for the third placeholder within the pattern.
+
+ @see #setResourceBundle
+ */
+ void l7dlog(const LevelPtr& level, const CFStringRef& key,
+ const log4cxx::spi::LocationInfo& locationInfo,
+ const CFStringRef& val1, const CFStringRef& val2,
+ const CFStringRef& val3) const;
+#endif
+
+ /**
+ This is the most generic printing method. It is intended to be
+ invoked by <b>wrapper</b> classes.
+
+ @param level The level of the logging request.
+ @param message The message of the logging request.
+ @param location The source file of the logging request, may be null. */
+ void log(const LevelPtr& level, const std::string& message,
+ const log4cxx::spi::LocationInfo& location) const;
+ /**
+ This is the most generic printing method. It is intended to be
+ invoked by <b>wrapper</b> classes.
+
+ @param level The level of the logging request.
+ @param message The message of the logging request.
+ */
+ void log(const LevelPtr& level, const std::string& message) const;
+#if LOG4CXX_WCHAR_T_API
+ /**
+ This is the most generic printing method. It is intended to be
+ invoked by <b>wrapper</b> classes.
+
+ @param level The level of the logging request.
+ @param message The message of the logging request.
+ @param location The source file of the logging request, may be null. */
+ void log(const LevelPtr& level, const std::wstring& message,
+ const log4cxx::spi::LocationInfo& location) const;
+ /**
+ This is the most generic printing method. It is intended to be
+ invoked by <b>wrapper</b> classes.
+
+ @param level The level of the logging request.
+ @param message The message of the logging request.
+ */
+ void log(const LevelPtr& level, const std::wstring& message) const;
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ This is the most generic printing method. It is intended to be
+ invoked by <b>wrapper</b> classes.
+
+ @param level The level of the logging request.
+ @param message The message of the logging request.
+ @param location The source file of the logging request, may be null. */
+ void log(const LevelPtr& level, const std::basic_string<UniChar>& message,
+ const log4cxx::spi::LocationInfo& location) const;
+ /**
+ This is the most generic printing method. It is intended to be
+ invoked by <b>wrapper</b> classes.
+
+ @param level The level of the logging request.
+ @param message The message of the logging request.
+ */
+ void log(const LevelPtr& level, const std::basic_string<UniChar>& message) const;
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ This is the most generic printing method. It is intended to be
+ invoked by <b>wrapper</b> classes.
+
+ @param level The level of the logging request.
+ @param message The message of the logging request.
+ @param location The source file of the logging request, may be null. */
+ void log(const LevelPtr& level, const CFStringRef& message,
+ const log4cxx::spi::LocationInfo& location) const;
+ /**
+ This is the most generic printing method. It is intended to be
+ invoked by <b>wrapper</b> classes.
+
+ @param level The level of the logging request.
+ @param message The message of the logging request.
+ */
+ void log(const LevelPtr& level, const CFStringRef& message) const;
+#endif
+ /**
+ This is the most generic printing method. It is intended to be
+ invoked by <b>wrapper</b> classes.
+
+ @param level The level of the logging request.
+ @param message The message of the logging request.
+ @param location The source file of the logging request, may be null. */
+ void logLS(const LevelPtr& level, const LogString& message,
+ const log4cxx::spi::LocationInfo& location) const;
+
+
+
+ /**
+ Remove all previously added appenders from this logger
+ instance.
+ <p>This is useful when re-reading configuration information.
+ */
+ void removeAllAppenders();
+
+ /**
+ Remove the appender passed as parameter form the list of appenders.
+ */
+ void removeAppender(const AppenderPtr& appender);
+
+ /**
+ Remove the appender with the name passed as parameter form the
+ list of appenders.
+ */
+ void removeAppender(const LogString& name);
+
+ /**
+ Set the additivity flag for this Logger instance.
+ */
+ void setAdditivity(bool additive);
+
+ protected:
+ friend class Hierarchy;
+ /**
+ Only the Hierarchy class can set the hierarchy of a logger.*/
+ void setHierarchy(spi::LoggerRepository * repository);
+
+ public:
+ /**
+ Set the level of this Logger.
+
+ <p>As in <pre> &nbsp;&nbsp;&nbsp;logger->setLevel(Level::getDebug()); </pre>
+
+ <p>Null values are admitted. */
+ virtual void setLevel(const LevelPtr& level);
+
+ /**
+ Set the resource bundle to be used with localized logging methods.
+ */
+ inline void setResourceBundle(const helpers::ResourceBundlePtr& bundle)
+ { resourceBundle = bundle; }
+
+#if LOG4CXX_WCHAR_T_API
+ /**
+ Log a message string with the WARN level.
+
+ <p>This method first checks if this logger is <code>WARN</code>
+ enabled by comparing the level of this logger with the
+ WARN level. If this logger is
+ <code>WARN</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void warn(const std::wstring& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the WARN level.
+
+ <p>This method first checks if this logger is <code>WARN</code>
+ enabled by comparing the level of this logger with the
+ WARN level. If this logger is
+ <code>WARN</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void warn(const std::wstring& msg) const;
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ Log a message string with the WARN level.
+
+ <p>This method first checks if this logger is <code>WARN</code>
+ enabled by comparing the level of this logger with the
+ WARN level. If this logger is
+ <code>WARN</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void warn(const std::basic_string<UniChar>& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the WARN level.
+
+ <p>This method first checks if this logger is <code>WARN</code>
+ enabled by comparing the level of this logger with the
+ WARN level. If this logger is
+ <code>WARN</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void warn(const std::basic_string<UniChar>& msg) const;
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ Log a message string with the WARN level.
+
+ <p>This method first checks if this logger is <code>WARN</code>
+ enabled by comparing the level of this logger with the
+ WARN level. If this logger is
+ <code>WARN</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void warn(const CFStringRef& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the WARN level.
+
+ <p>This method first checks if this logger is <code>WARN</code>
+ enabled by comparing the level of this logger with the
+ WARN level. If this logger is
+ <code>WARN</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void warn(const CFStringRef& msg) const;
+#endif
+ /**
+ Log a message string with the WARN level.
+
+ <p>This method first checks if this logger is <code>WARN</code>
+ enabled by comparing the level of this logger with the
+ WARN level. If this logger is
+ <code>WARN</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void warn(const std::string& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the WARN level.
+
+ <p>This method first checks if this logger is <code>WARN</code>
+ enabled by comparing the level of this logger with the
+ WARN level. If this logger is
+ <code>WARN</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void warn(const std::string& msg) const;
+
+#if LOG4CXX_WCHAR_T_API
+ /**
+ Log a message string with the TRACE level.
+
+ <p>This method first checks if this logger is <code>TRACE</code>
+ enabled by comparing the level of this logger with the
+ TRACE level. If this logger is
+ <code>TRACE</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void trace(const std::wstring& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the TRACE level.
+
+ <p>This method first checks if this logger is <code>TRACE</code>
+ enabled by comparing the level of this logger with the
+ TRACE level. If this logger is
+ <code>TRACE</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void trace(const std::wstring& msg) const;
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ Log a message string with the TRACE level.
+
+ <p>This method first checks if this logger is <code>TRACE</code>
+ enabled by comparing the level of this logger with the
+ TRACE level. If this logger is
+ <code>TRACE</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void trace(const std::basic_string<UniChar>& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the TRACE level.
+
+ <p>This method first checks if this logger is <code>TRACE</code>
+ enabled by comparing the level of this logger with the
+ TRACE level. If this logger is
+ <code>TRACE</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void trace(const std::basic_string<UniChar>& msg) const;
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ Log a message string with the TRACE level.
+
+ <p>This method first checks if this logger is <code>TRACE</code>
+ enabled by comparing the level of this logger with the
+ TRACE level. If this logger is
+ <code>TRACE</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void trace(const CFStringRef& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the TRACE level.
+
+ <p>This method first checks if this logger is <code>TRACE</code>
+ enabled by comparing the level of this logger with the
+ TRACE level. If this logger is
+ <code>TRACE</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void trace(const CFStringRef& msg) const;
+#endif
+ /**
+ Log a message string with the TRACE level.
+
+ <p>This method first checks if this logger is <code>TRACE</code>
+ enabled by comparing the level of this logger with the
+ TRACE level. If this logger is
+ <code>TRACE</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ @param location location of source of logging request.
+ */
+ void trace(const std::string& msg, const log4cxx::spi::LocationInfo& location) const;
+ /**
+ Log a message string with the TRACE level.
+
+ <p>This method first checks if this logger is <code>TRACE</code>
+ enabled by comparing the level of this logger with the
+ TRACE level. If this logger is
+ <code>TRACE</code> enabled, it proceeds to call all the
+ registered appenders in this logger and also higher in the
+ hierarchy depending on the value of the additivity flag.
+
+ @param msg the message string to log.
+ */
+ void trace(const std::string& msg) const;
+
+ inline const log4cxx::helpers::Mutex& getMutex() const { return mutex; }
+
+ private:
+ //
+ // prevent copy and assignment
+ Logger(const Logger&);
+ Logger& operator=(const Logger&);
+ log4cxx::helpers::Mutex mutex;
+ friend class log4cxx::helpers::synchronized;
+ };
+ LOG4CXX_LIST_DEF(LoggerList, LoggerPtr);
+
+}
+
+/** @addtogroup LoggingMacros Logging macros
+@{
+*/
+
+#if !defined(LOG4CXX_UNLIKELY)
+#if __GNUC__ >= 3
+/**
+Provides optimization hint to the compiler
+to optimize for the expression being false.
+@param expr boolean expression.
+@returns value of expression.
+*/
+#define LOG4CXX_UNLIKELY(expr) __builtin_expect(expr, 0)
+#else
+/**
+Provides optimization hint to the compiler
+to optimize for the expression being false.
+@param expr boolean expression.
+@returns value of expression.
+**/
+#define LOG4CXX_UNLIKELY(expr) expr
+#endif
+#endif
+
+
+/**
+Logs a message to a specified logger with a specified level.
+
+@param logger the logger to be used.
+@param level the level to log.
+@param message the message string to log.
+*/
+#define LOG4CXX_LOG(logger, level, message) { \
+ if (logger->isEnabledFor(level)) {\
+ ::log4cxx::helpers::MessageBuffer oss_; \
+ logger->forcedLog(level, oss_.str(oss_ << message), LOG4CXX_LOCATION); } }
+
+/**
+Logs a message to a specified logger with a specified level.
+
+@param logger the logger to be used.
+@param level the level to log.
+@param message the message string to log in the internal encoding.
+*/
+#define LOG4CXX_LOGLS(logger, level, message) { \
+ if (logger->isEnabledFor(level)) {\
+ ::log4cxx::helpers::LogCharMessageBuffer oss_; \
+ logger->forcedLog(level, oss_.str(oss_ << message), LOG4CXX_LOCATION); } }
+
+/**
+Logs a message to a specified logger with the DEBUG level.
+
+@param logger the logger to be used.
+@param message the message string to log.
+*/
+#define LOG4CXX_DEBUG(logger, message) { \
+ if (LOG4CXX_UNLIKELY(logger->isDebugEnabled())) {\
+ ::log4cxx::helpers::MessageBuffer oss_; \
+ logger->forcedLog(::log4cxx::Level::getDebug(), oss_.str(oss_ << message), LOG4CXX_LOCATION); }}
+
+/**
+Logs a message to a specified logger with the TRACE level.
+
+@param logger the logger to be used.
+@param message the message string to log.
+*/
+#define LOG4CXX_TRACE(logger, message) { \
+ if (LOG4CXX_UNLIKELY(logger->isTraceEnabled())) {\
+ ::log4cxx::helpers::MessageBuffer oss_; \
+ logger->forcedLog(::log4cxx::Level::getTrace(), oss_.str(oss_ << message), LOG4CXX_LOCATION); }}
+
+
+/**
+Logs a message to a specified logger with the INFO level.
+
+@param logger the logger to be used.
+@param message the message string to log.
+*/
+#define LOG4CXX_INFO(logger, message) { \
+ if (logger->isInfoEnabled()) {\
+ ::log4cxx::helpers::MessageBuffer oss_; \
+ logger->forcedLog(::log4cxx::Level::getInfo(), oss_.str(oss_ << message), LOG4CXX_LOCATION); }}
+
+/**
+Logs a message to a specified logger with the WARN level.
+
+@param logger the logger to be used.
+@param message the message string to log.
+*/
+#define LOG4CXX_WARN(logger, message) { \
+ if (logger->isWarnEnabled()) {\
+ ::log4cxx::helpers::MessageBuffer oss_; \
+ logger->forcedLog(::log4cxx::Level::getWarn(), oss_.str(oss_ << message), LOG4CXX_LOCATION); }}
+
+/**
+Logs a message to a specified logger with the ERROR level.
+
+@param logger the logger to be used.
+@param message the message string to log.
+*/
+#define LOG4CXX_ERROR(logger, message) { \
+ if (logger->isErrorEnabled()) {\
+ ::log4cxx::helpers::MessageBuffer oss_; \
+ logger->forcedLog(::log4cxx::Level::getError(), oss_.str(oss_ << message), LOG4CXX_LOCATION); }}
+
+/**
+Logs a error if the condition is not true.
+
+@param logger the logger to be used.
+@param condition condition
+@param message the message string to log.
+*/
+#define LOG4CXX_ASSERT(logger, condition, message) { \
+ if (!(condition) && logger->isErrorEnabled()) {\
+ ::log4cxx::helpers::MessageBuffer oss_; \
+ logger->forcedLog(::log4cxx::Level::getError(), oss_.str(oss_ << message), LOG4CXX_LOCATION); }}
+
+
+/**
+Logs a message to a specified logger with the FATAL level.
+
+@param logger the logger to be used.
+@param message the message string to log.
+*/
+#define LOG4CXX_FATAL(logger, message) { \
+ if (logger->isFatalEnabled()) {\
+ ::log4cxx::helpers::MessageBuffer oss_; \
+ logger->forcedLog(::log4cxx::Level::getFatal(), oss_.str(oss_ << message), LOG4CXX_LOCATION); }}
+
+/**
+Logs a localized message with no parameter.
+
+@param logger the logger to be used.
+@param level the level to log.
+@param key the key to be searched in the resourceBundle of the logger.
+*/
+#define LOG4CXX_L7DLOG(logger, level, key) { \
+ if (logger->isEnabledFor(level)) {\
+ logger->l7dlog(level, key, LOG4CXX_LOCATION); }}
+
+/**
+Logs a localized message with one parameter.
+
+@param logger the logger to be used.
+@param level the level to log.
+@param key the key to be searched in the resourceBundle of the logger.
+@param p1 the unique parameter.
+*/
+#define LOG4CXX_L7DLOG1(logger, level, key, p1) { \
+ if (logger->isEnabledFor(level)) {\
+ logger->l7dlog(level, key, LOG4CXX_LOCATION, p1); }}
+
+/**
+Logs a localized message with two parameters.
+
+@param logger the logger to be used.
+@param level the level to log.
+@param key the key to be searched in the resourceBundle of the logger.
+@param p1 the first parameter.
+@param p2 the second parameter.
+*/
+#define LOG4CXX_L7DLOG2(logger, level, key, p1, p2) { \
+ if (logger->isEnabledFor(level)) {\
+ logger->l7dlog(level, key, LOG4CXX_LOCATION, p1, p2); }}
+
+/**
+Logs a localized message with three parameters.
+
+@param logger the logger to be used.
+@param level the level to log.
+@param key the key to be searched in the resourceBundle of the logger.
+@param p1 the first parameter.
+@param p2 the second parameter.
+@param p3 the third parameter.
+*/
+#define LOG4CXX_L7DLOG3(logger, level, key, p1, p2, p3) { \
+ if (logger->isEnabledFor(level)) {\
+ logger->l7dlog(level, key, LOG4CXX_LOCATION, p1, p2, p3); }}
+
+/**@}*/
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#include <log4cxx/spi/loggerrepository.h>
+
+#endif //_LOG4CXX_LOGGER_H
diff --git a/src/main/include/log4cxx/logmanager.h b/src/main/include/log4cxx/logmanager.h
new file mode 100644
index 0000000..b9ec0b6
--- /dev/null
+++ b/src/main/include/log4cxx/logmanager.h
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_LOG_MANAGER_H
+#define _LOG4CXX_LOG_MANAGER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <vector>
+#include <log4cxx/spi/repositoryselector.h>
+
+namespace log4cxx
+{
+ class Logger;
+ typedef helpers::ObjectPtrT<Logger> LoggerPtr;
+ typedef std::vector<LoggerPtr> LoggerList;
+
+ namespace spi {
+ class LoggerFactory;
+ typedef helpers::ObjectPtrT<LoggerFactory> LoggerFactoryPtr;
+ }
+
+ /**
+ * Use the <code>LogManager</code> class to retreive Logger
+ * instances or to operate on the current
+ * {@link log4cxx::spi::LoggerRepository LoggerRepository}.
+ * When the <code>LogManager</code> class is loaded
+ * into memory the default initialization procedure is inititated.
+ */
+ class LOG4CXX_EXPORT LogManager
+ {
+ private:
+ static void * guard;
+ static spi::RepositorySelectorPtr& getRepositorySelector();
+
+ public:
+ /**
+ Sets <code>LoggerFactory</code> but only if the correct
+ <em>guard</em> is passed as parameter.
+
+ <p>Initally the guard is null. If the guard is
+ <code>null</code>, then invoking this method sets the logger
+ factory and the guard. Following invocations will throw a {@link
+ helpers::IllegalArgumentException IllegalArgumentException},
+ unless the previously set <code>guard</code> is passed as the second
+ parameter.
+
+ <p>This allows a high-level component to set the {@link
+ spi::RepositorySelector RepositorySelector} used by the
+ <code>LogManager</code>.
+ */
+
+ static void setRepositorySelector(spi::RepositorySelectorPtr selector,
+ void * guard);
+
+ static spi::LoggerRepositoryPtr& getLoggerRepository();
+
+ /**
+ Retrieve the appropriate root logger.
+ */
+ static LoggerPtr getRootLogger();
+
+ /**
+ Retrieve the appropriate Logger instance.
+ * @param name logger name in current encoding.
+ * @return logger.
+ */
+ static LoggerPtr getLogger(const std::string& name);
+ /**
+ Retrieve the appropriate Logger instance.
+ * @param name logger name in current encoding.
+ * @param factory logger factory.
+ * @return logger.
+ */
+ static LoggerPtr getLogger(const std::string& name,
+ const spi::LoggerFactoryPtr& factory);
+ /**
+ * Determines if logger name exists in the hierarchy.
+ * @param name logger name.
+ * @return true if logger exists.
+ */
+ static LoggerPtr exists(const std::string& name);
+#if LOG4CXX_WCHAR_T_API
+ /**
+ Retrieve the appropriate Logger instance.
+ * @param name logger name.
+ * @return logger.
+ */
+ static LoggerPtr getLogger(const std::wstring& name);
+ /**
+ Retrieve the appropriate Logger instance.
+ * @param name logger name.
+ * @param factory logger factory.
+ * @return logger.
+ */
+ static LoggerPtr getLogger(const std::wstring& name,
+ const spi::LoggerFactoryPtr& factory);
+ /**
+ * Determines if logger name exists in the hierarchy.
+ * @param name logger name.
+ * @return true if logger exists.
+ */
+ static LoggerPtr exists(const std::wstring& name);
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ Retrieve the appropriate Logger instance.
+ * @param name logger name.
+ * @return logger.
+ */
+ static LoggerPtr getLogger(const std::basic_string<UniChar>& name);
+ /**
+ Retrieve the appropriate Logger instance.
+ * @param name logger name.
+ * @param factory logger factory.
+ * @return logger.
+ */
+ static LoggerPtr getLogger(const std::basic_string<UniChar>& name,
+ const spi::LoggerFactoryPtr& factory);
+ /**
+ * Determines if logger name exists in the hierarchy.
+ * @param name logger name.
+ * @return true if logger exists.
+ */
+ static LoggerPtr exists(const std::basic_string<UniChar>& name);
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ Retrieve the appropriate Logger instance.
+ * @param name logger name.
+ * @return logger.
+ */
+ static LoggerPtr getLogger(const CFStringRef& name);
+ /**
+ Retrieve the appropriate Logger instance.
+ * @param name logger name.
+ * @param factory logger factory.
+ * @return logger.
+ */
+ static LoggerPtr getLogger(const CFStringRef& name,
+ const spi::LoggerFactoryPtr& factory);
+ /**
+ * Determines if logger name exists in the hierarchy.
+ * @param name logger name.
+ * @return true if logger exists.
+ */
+ static LoggerPtr exists(const CFStringRef& name);
+#endif
+
+
+ /**
+ Retrieve the appropriate Logger instance.
+ * @param name logger name.
+ * @return logger.
+ */
+ static LoggerPtr getLoggerLS(const LogString& name);
+ /**
+ Retrieve the appropriate Logger instance.
+ * @param name logger name.
+ * @param factory logger factory.
+ * @return logger.
+ */
+ static LoggerPtr getLoggerLS(const LogString& name,
+ const spi::LoggerFactoryPtr& factory);
+
+ /**
+ * Determines if logger name exists in the hierarchy.
+ * @param name logger name.
+ * @return true if logger exists.
+ */
+ static LoggerPtr existsLS(const LogString& name);
+
+ static LoggerList getCurrentLoggers();
+
+ /**
+ Safely close and remove all appenders in all loggers including
+ the root logger.
+ */
+ static void shutdown();
+
+ /**
+ Reset all values contained in this current {@link
+ spi::LoggerRepository LoggerRepository} to their default.
+ */
+ static void resetConfiguration();
+ }; // class LogManager
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+#endif //_LOG4CXX_LOG_MANAGER_H
diff --git a/src/main/include/log4cxx/logstring.h b/src/main/include/log4cxx/logstring.h
new file mode 100644
index 0000000..3bbcdf2
--- /dev/null
+++ b/src/main/include/log4cxx/logstring.h
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_STRING_H
+#define _LOG4CXX_STRING_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <string>
+#include <log4cxx/log4cxx.h>
+
+#if LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_LOGCHAR_IS_UTF8 && LOG4CXX_LOGCHAR_IS_UNICHAR
+#error only one of LOG4CXX_LOGCHAR_IS_WCHAR, LOG4CXX_LOGCHAR_IS_UTF8 or LOG4CXX_LOGCHAR_IS_UNICHAR may be true
+#endif
+
+#if LOG4CXX_CFSTRING_API
+extern "C" {
+typedef const struct __CFString* CFStringRef;
+}
+#endif
+
+
+
+namespace log4cxx {
+
+#if LOG4CXX_LOGCHAR_IS_UNICHAR || LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+typedef unsigned short UniChar;
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_WCHAR
+ typedef wchar_t logchar;
+#define LOG4CXX_STR(str) L ## str
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ typedef char logchar;
+#if LOG4CXX_CHARSET_EBCDIC
+#define LOG4CXX_STR(str) log4cxx::helpers::Transcoder::decode(str)
+#else
+#define LOG4CXX_STR(str) str
+#endif
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_UNICHAR
+ typedef UniChar logchar;
+#define LOG4CXX_STR(str) log4cxx::helpers::Transcoder::decode(str)
+#endif
+
+ typedef std::basic_string<logchar> LogString;
+
+
+}
+
+
+#if !defined(LOG4CXX_EOL)
+#if defined(_WIN32)
+#define LOG4CXX_EOL LOG4CXX_STR("\x0D\x0A")
+#else
+#define LOG4CXX_EOL LOG4CXX_STR("\x0A")
+#endif
+#endif
+
+
+#if LOG4CXX_LOGCHAR_IS_UNICHAR || (LOG4CXX_LOGCHAR_IS_UTF8 || LOG4CXX_CHARSET_EBCDIC)
+#include <log4cxx/helpers/transcoder.h>
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+#endif //_LOG4CXX_STRING_H
diff --git a/src/main/include/log4cxx/mdc.h b/src/main/include/log4cxx/mdc.h
new file mode 100644
index 0000000..f9cd875
--- /dev/null
+++ b/src/main/include/log4cxx/mdc.h
@@ -0,0 +1,240 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_MDC_H
+#define _LOG4CXX_MDC_H
+
+#if defined(_MSC_VER)
+#pragma warning (push)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/log4cxx.h>
+#include <log4cxx/logstring.h>
+#include <map>
+
+namespace log4cxx
+{
+ /**
+ The MDC class is similar to the {@link log4cxx::NDC NDC} class except that it is
+ based on a map instead of a stack. It provides <em>mapped
+ diagnostic contexts</em>. A <em>Mapped Diagnostic Context</em>, or
+ MDC in short, is an instrument for distinguishing interleaved log
+ output from different sources. Log output is typically interleaved
+ when a server handles multiple clients near-simultaneously.
+
+ <p><b><em>The MDC is managed on a per thread basis</em></b>. A
+ child thread automatically inherits a <em>copy</em> of the mapped
+ diagnostic context of its parent.
+
+ */
+ class LOG4CXX_EXPORT MDC
+ {
+ public:
+ /** String to string stl map.
+ */
+ typedef std::map<LogString, LogString> Map;
+
+ /**
+ * Places a key/value pair in the MDC for the current thread
+ * which will be removed during the corresponding destructor. Both
+ * construction and destruction are expected to be on the same thread.
+ * @param key key
+ * @param value value.
+ */
+ MDC(const std::string& key, const std::string& value);
+ ~MDC();
+
+ /**
+ * Put a context value (the <code>o</code> parameter) as identified
+ * with the <code>key</code> parameter into the current thread's
+ * context map.
+ *
+ * <p>If the current thread does not have a context map it is
+ * created as a side effect.
+ * @param key key
+ * @param value value.
+ */
+ static void put(const std::string& key, const std::string& value);
+ /**
+ * Put a context value (the <code>o</code> parameter) as identified
+ * with the <code>key</code> parameter into the current thread's
+ * context map.
+ *
+ * <p>If the current thread does not have a context map it is
+ * created as a side effect.
+ * */
+ static void putLS(const LogString& key, const LogString& value);
+
+ /**
+ * Get the context identified by the <code>key</code> parameter.
+ *
+ * <p>This method has no side effects.
+ * @param key key.
+ * @return value for key, empty if not set.
+ * */
+ static std::string get(const std::string& key);
+ /**
+ * Gets the context identified by the <code>key</code> parameter.
+ * @param key context key.
+ * @param dest destination to which value is appended.
+ * @return true if key has associated value.
+ */
+ static bool get(const LogString& key, LogString& dest);
+
+ /**
+ * Remove the the context identified by the <code>key</code>
+ * parameter.
+ * @param key key.
+ * @return value if key had been set, empty if not.
+ */
+ static std::string remove(const std::string& key);
+#if LOG4CXX_WCHAR_T_API
+ /**
+ * Places a key/value pair in the MDC for the current thread
+ * which will be removed during the corresponding destructor. Both
+ * construction and destruction are expected to be on the same thread.
+ * @param key key
+ * @param value value.
+ */
+ MDC(const std::wstring& key, const std::wstring& value);
+ /**
+ * Put a context value (the <code>o</code> parameter) as identified
+ * with the <code>key</code> parameter into the current thread's
+ * context map.
+ *
+ * <p>If the current thread does not have a context map it is
+ * created as a side effect.
+ * @param key key
+ * @param value value.
+ */
+ static void put(const std::wstring& key, const std::wstring& value);
+ /**
+ * Get the context identified by the <code>key</code> parameter.
+ *
+ * <p>This method has no side effects.
+ * @param key key.
+ * @return value for key, empty if not set.
+ * */
+ static std::wstring get(const std::wstring& key);
+ /**
+ * Remove the the context identified by the <code>key</code>
+ * parameter.
+ * @param key key.
+ * @return value if key had been set, empty if not.
+ */
+ static std::wstring remove(const std::wstring& key);
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ * Places a key/value pair in the MDC for the current thread
+ * which will be removed during the corresponding destructor. Both
+ * construction and destruction are expected to be on the same thread.
+ * @param key key
+ * @param value value.
+ */
+ MDC(const std::basic_string<UniChar>& key, const std::basic_string<UniChar>& value);
+ /**
+ * Put a context value (the <code>o</code> parameter) as identified
+ * with the <code>key</code> parameter into the current thread's
+ * context map.
+ *
+ * <p>If the current thread does not have a context map it is
+ * created as a side effect.
+ * @param key key
+ * @param value value.
+ */
+ static void put(const std::basic_string<UniChar>& key, const std::basic_string<UniChar>& value);
+ /**
+ * Get the context identified by the <code>key</code> parameter.
+ *
+ * <p>This method has no side effects.
+ * @param key key.
+ * @return value for key, empty if not set.
+ * */
+ static std::basic_string<UniChar> get(const std::basic_string<UniChar>& key);
+ /**
+ * Remove the the context identified by the <code>key</code>
+ * parameter.
+ * @param key key.
+ * @return value if key had been set, empty if not.
+ */
+ static std::basic_string<UniChar> remove(const std::basic_string<UniChar>& key);
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ * Places a key/value pair in the MDC for the current thread
+ * which will be removed during the corresponding destructor. Both
+ * construction and destruction are expected to be on the same thread.
+ * @param key key
+ * @param value value.
+ */
+ MDC(const CFStringRef& key, const CFStringRef& value);
+ /**
+ * Put a context value (the <code>o</code> parameter) as identified
+ * with the <code>key</code> parameter into the current thread's
+ * context map.
+ *
+ * <p>If the current thread does not have a context map it is
+ * created as a side effect.
+ * @param key key
+ * @param value value.
+ */
+ static void put(const CFStringRef& key, const CFStringRef& value);
+ /**
+ * Get the context identified by the <code>key</code> parameter.
+ *
+ * <p>This method has no side effects.
+ * @param key key.
+ * @return value for key, empty if not set.
+ * */
+ static CFStringRef get(const CFStringRef& key);
+ /**
+ * Remove the the context identified by the <code>key</code>
+ * parameter.
+ * @param key key.
+ * @return value if key had been set, empty if not.
+ */
+ static CFStringRef remove(const CFStringRef& key);
+#endif
+ /**
+ * Remove the the context identified by the <code>key</code>
+ * parameter.
+ * @param key key.
+ * @param prevValue buffer to which previous value is appended.
+ * @return true if key existed in MDC.
+ */
+ static bool remove(const LogString& key, LogString& prevValue);
+
+ /**
+ * Clear all entries in the MDC.
+ */
+ static void clear();
+
+ private:
+ MDC(const MDC&);
+ MDC& operator=(const MDC&);
+ LogString key;
+ }; // class MDC;
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+
+#endif // _LOG4CXX_MDC_H
diff --git a/src/main/include/log4cxx/ndc.h b/src/main/include/log4cxx/ndc.h
new file mode 100644
index 0000000..7cf7128
--- /dev/null
+++ b/src/main/include/log4cxx/ndc.h
@@ -0,0 +1,353 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_NDC_H
+#define _LOG4CXX_NDC_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/log4cxx.h>
+#include <log4cxx/logstring.h>
+#include <stack>
+
+namespace log4cxx
+{
+ /**
+ 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.
+
+ <p>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.
+
+ <p>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.
+
+ <p><em><b>note that ndcs are managed on a per thread
+ basis</b></em>. ndc operations such as #push,
+ #pop, #clear and #getDepth
+ affect the ndc of the <em>current</em> thread only. ndcs of other
+ threads remain unaffected.
+
+ <p>for example, a servlet 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 #push
+ operation. simply put,
+
+ <p><ul>
+ <li>contexts can be nested.
+
+ <p><li>when entering a context, call <code>ndc.push</code>. as a
+ side effect, if there is no nested diagnostic context for the
+ current thread, this method will create it.
+
+ <p><li>when leaving a context, call <code>ndc.pop</code>.
+
+ <p><li><b>when exiting a thread make sure to call #remove
+ </b>.
+ </ul>
+
+ <p>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.
+
+ <p>if configured to do so, PatternLayout and
+ TTCCLayout instances automatically retrieve the nested diagnostic
+ context for the current thread without any user intervention.
+ hence, even if a servlet 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.
+
+ <p>heavy duty systems should call the #remove method when
+ leaving the run method of a thread. this ensures that the memory
+ used by the thread can be freed by the java garbage
+ collector. there is a mechanism to lazily remove references to dead
+ threads. in practice, this means that you can be a little sloppy
+ and sometimes forget to call #remove before exiting a
+ thread.
+
+ */
+ class LOG4CXX_EXPORT NDC
+ {
+ public:
+ /**
+ * Pair of Message and FullMessage.
+ */
+ typedef std::pair<LogString, LogString> DiagnosticContext;
+ typedef std::stack<DiagnosticContext> Stack;
+
+ /**
+ Creates a nested diagnostic context.
+ Since java performs no automatic cleanup of objects when a
+ scope is left, in log4j push() and pop() must be used
+ to manage the NDC. For convenience, log4cxx provides
+ an NDC constructor and destructor which simply call the push() and
+ pop() methods, allowing for automatic cleanup when the current
+ scope ends.
+
+ @param message The new diagnostic context information.
+ @see The #push method.
+ */
+ NDC(const std::string& message);
+
+ /**
+ Removes the topmost element from the NDC stack.
+
+ @see The #pop method.
+ */
+ ~NDC();
+
+ /**
+ 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.
+ */
+ static void clear();
+
+ /**
+ Clone the diagnostic context for the current thread.
+ <p>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.
+ <p>The child thread uses the #inherit method to
+ inherit the parent's diagnostic context.
+ <p>If not passed to #inherit, returned stack should be deleted by caller.
+ @return Stack A clone of the current thread's diagnostic context, will not be null.
+ */
+ static Stack * cloneStack();
+
+ /**
+ Inherit the diagnostic context of another thread.
+ <p>The parent thread can obtain a reference to its diagnostic
+ context using the #cloneStack method. It should
+ communicate this information to its child so that it may inherit
+ the parent's diagnostic context.
+ <p>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,
+ will be deleted during call. If NULL, NDC will not be modified.
+ */
+ static void inherit(Stack * stack);
+
+ /**
+ * Get the current value of the NDC of the
+ * currrent thread.
+ * @param dest destination to which to append content of NDC.
+ * @return true if NDC is set.
+ */
+ static bool get(LogString& dest);
+
+ /**
+ Get the current nesting depth of this diagnostic context.
+ */
+ static int getDepth();
+
+
+ /**
+ * Tests if the NDC is empty.
+ */
+ static bool empty();
+
+ /**
+ Pop top value off stack.
+ @return top value.
+ */
+ static LogString pop();
+ /**
+ Pop top value off stack.
+ @param buf to which top value is appended.
+ @return true if NDC contained at least one value.
+ */
+ static bool pop(std::string& buf);
+
+ /**
+ Looks at the last diagnostic context at the top of this NDC
+ without removing it.
+ <p>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.
+ */
+ static LogString peek();
+ /**
+ Get top value without removing value.
+ @param buf to which top value is appended.
+ @return true if NDC contained at least one value.
+ */
+ static bool peek(std::string& buf);
+
+ /**
+ Push new diagnostic context information for the current thread.
+ <p>The contents of the <code>message</code> parameter is
+ determined solely by the client.
+ @param message The new diagnostic context information.
+ */
+ static void push(const std::string& message);
+ /**
+ Push new diagnostic context information for the current thread.
+ <p>The contents of the <code>message</code> parameter is
+ determined solely by the client.
+ @param message The new diagnostic context information.
+ */
+ static void pushLS(const LogString& message);
+
+ /**
+ Remove the diagnostic context for this thread.
+ <p>Each thread that created a diagnostic context by calling
+ #push should call this method before exiting. Otherwise,
+ the memory used by the <b>thread</b> cannot be reclaimed by the
+ VM.
+ <p>As this is such an important problem in heavy duty systems and
+ because it is difficult to always guarantee that the remove
+ method is called before exiting a thread, this method has been
+ augmented to lazily remove references to dead threads. In
+ practice, this means that you can be a little sloppy and
+ occasionally forget to call #remove before exiting a
+ thread. However, you must call <code>remove</code> sometime. If
+ you never call it, then your application is sure to run out of
+ memory.
+ */
+ static void remove();
+
+#if LOG4CXX_WCHAR_T_API
+ /**
+ Creates a nested diagnostic context.
+ Since java performs no automatic cleanup of objects when a
+ scope is left, in log4j push() and pop() must be used
+ to manage the NDC. For convenience, log4cxx provides
+ an NDC constructor and destructor which simply call the push() and
+ pop() methods, allowing for automatic cleanup when the current
+ scope ends.
+
+ @param message The new diagnostic context information.
+ @see The #push method.
+ */
+ NDC(const std::wstring& message);
+ /**
+ Push new diagnostic context information for the current thread.
+ <p>The contents of the <code>message</code> parameter is
+ determined solely by the client.
+ @param message The new diagnostic context information.
+ */
+ static void push(const std::wstring& message);
+ /**
+ * Appends the current NDC content to the provided string.
+ * @param dst destination.
+ * @return true if NDC value set.
+ */
+ static bool peek(std::wstring& dst);
+ /**
+ * Appends the current NDC content to the provided string and removes the value from the NDC.
+ * @param dst destination.
+ * @return true if NDC value set.
+ */
+ static bool pop(std::wstring& dst);
+#endif
+#if LOG4CXX_UNICHAR_API
+ /**
+ Creates a nested diagnostic context.
+ Since java performs no automatic cleanup of objects when a
+ scope is left, in log4j push() and pop() must be used
+ to manage the NDC. For convenience, log4cxx provides
+ an NDC constructor and destructor which simply call the push() and
+ pop() methods, allowing for automatic cleanup when the current
+ scope ends.
+
+ @param message The new diagnostic context information.
+ @see The #push method.
+ */
+ NDC(const std::basic_string<UniChar>& message);
+ /**
+ Push new diagnostic context information for the current thread.
+ <p>The contents of the <code>message</code> parameter is
+ determined solely by the client.
+ @param message The new diagnostic context information.
+ */
+ static void push(const std::basic_string<UniChar>& message);
+ /**
+ * Appends the current NDC content to the provided string.
+ * @param dst destination.
+ * @return true if NDC value set.
+ */
+ static bool peek(std::basic_string<UniChar>& dst);
+ /**
+ * Appends the current NDC content to the provided string and removes the value from the NDC.
+ * @param dst destination.
+ * @return true if NDC value set.
+ */
+ static bool pop(std::basic_string<UniChar>& dst);
+#endif
+#if LOG4CXX_CFSTRING_API
+ /**
+ Creates a nested diagnostic context.
+ Since java performs no automatic cleanup of objects when a
+ scope is left, in log4j push() and pop() must be used
+ to manage the NDC. For convenience, log4cxx provides
+ an NDC constructor and destructor which simply call the push() and
+ pop() methods, allowing for automatic cleanup when the current
+ scope ends.
+
+ @param message The new diagnostic context information.
+ @see The #push method.
+ */
+ NDC(const CFStringRef& message);
+ /**
+ Push new diagnostic context information for the current thread.
+ <p>The contents of the <code>message</code> parameter is
+ determined solely by the client.
+ @param message The new diagnostic context information.
+ */
+ static void push(const CFStringRef& message);
+ /**
+ * Gets the current NDC value.
+ * @param dst destination.
+ * @return true if NDC value set.
+ */
+ static bool peek(CFStringRef& dst);
+ /**
+ * Gets and removes the current NDC value.
+ * @param dst destination.
+ * @return true if NDC value set.
+ */
+ static bool pop(CFStringRef& dst);
+#endif
+
+ private:
+ NDC(const NDC&);
+ NDC& operator=(const NDC&);
+ static LogString& getMessage(DiagnosticContext& ctx);
+ static LogString& getFullMessage(DiagnosticContext& ctx);
+ }; // class NDC;
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+
+#endif // _LOG4CXX_NDC_H
diff --git a/src/main/include/log4cxx/net/Makefile.am b/src/main/include/log4cxx/net/Makefile.am
new file mode 100644
index 0000000..4a54041
--- /dev/null
+++ b/src/main/include/log4cxx/net/Makefile.am
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+netincdir = $(includedir)/log4cxx/net
+netinc_HEADERS= $(top_srcdir)/src/main/include/log4cxx/net/*.h
+
diff --git a/src/main/include/log4cxx/net/smtpappender.h b/src/main/include/log4cxx/net/smtpappender.h
new file mode 100644
index 0000000..eb1dbb5
--- /dev/null
+++ b/src/main/include/log4cxx/net/smtpappender.h
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_NET_SMTP_H
+#define _LOG4CXX_NET_SMTP_H
+
+
+#include <log4cxx/appenderskeleton.h>
+#include <log4cxx/helpers/cyclicbuffer.h>
+#include <log4cxx/spi/triggeringeventevaluator.h>
+
+namespace log4cxx
+{
+ namespace net
+ {
+ /**
+ Send an e-mail when a specific logging event occurs, typically on
+ errors or fatal errors.
+ <p>The number of logging events delivered in this e-mail depend on
+ the value of <b>BufferSize</b> option. The
+ <code>SMTPAppender</code> keeps only the last
+ <code>BufferSize</code> logging events in its cyclic buffer. This
+ keeps memory requirements at a reasonable level while still
+ delivering useful application context.
+ */
+ class LOG4CXX_EXPORT SMTPAppender : public AppenderSkeleton
+ {
+ private:
+
+ private:
+ SMTPAppender(const SMTPAppender&);
+ SMTPAppender& operator=(const SMTPAppender&);
+ static bool asciiCheck(const LogString& value, const LogString& label);
+ /**
+ This method determines if there is a sense in attempting to append.
+ <p>It checks whether there is a set output target and also if
+ there is a set layout. If these checks fail, then the boolean
+ value <code>false</code> is returned. */
+ bool checkEntryConditions();
+
+ LogString to;
+ LogString cc;
+ LogString bcc;
+ LogString from;
+ LogString subject;
+ LogString smtpHost;
+ LogString smtpUsername;
+ LogString smtpPassword;
+ int smtpPort;
+ int bufferSize; // 512
+ bool locationInfo;
+ helpers::CyclicBuffer cb;
+ spi::TriggeringEventEvaluatorPtr evaluator;
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(SMTPAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(SMTPAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+ END_LOG4CXX_CAST_MAP()
+
+ SMTPAppender();
+ /**
+ The default constructor will instantiate the appender with a
+ spi::TriggeringEventEvaluator that will trigger on events with
+ level ERROR or higher.*/
+ SMTPAppender(log4cxx::helpers::Pool& p);
+
+ /**
+ Use <code>evaluator</code> passed as parameter as the
+ spi::TriggeringEventEvaluator for this net::SMTPAppender.
+ */
+ SMTPAppender(spi::TriggeringEventEvaluatorPtr evaluator);
+
+ ~SMTPAppender();
+
+ /**
+ Set options
+ */
+ virtual void setOption(const LogString& option, const LogString& value);
+
+ /**
+ Activate the specified options, such as the smtp host, the
+ recipient, from, etc.
+ */
+ virtual void activateOptions(log4cxx::helpers::Pool& p);
+
+ /**
+ Perform SMTPAppender specific appending actions, mainly adding
+ the event to a cyclic buffer and checking if the event triggers
+ an e-mail to be sent. */
+ virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);
+
+
+ virtual void close();
+
+ /**
+ Returns value of the <b>To</b> option.
+ */
+ LogString getTo() const;
+
+ /**
+ Returns value of the <b>cc</b> option.
+ */
+ LogString getCc() const;
+
+ /**
+ Returns value of the <b>bcc</b> option.
+ */
+ LogString getBcc() const;
+
+
+ /**
+ The <code>SMTPAppender</code> requires a {@link
+ Layout layout}. */
+ virtual bool requiresLayout() const;
+
+ /**
+ Send the contents of the cyclic buffer as an e-mail message.
+ */
+ void sendBuffer(log4cxx::helpers::Pool& p);
+
+
+ /**
+ Returns value of the <b>EvaluatorClass</b> option.
+ */
+ LogString getEvaluatorClass();
+
+ /**
+ Returns value of the <b>From</b> option.
+ */
+ LogString getFrom() const;
+
+ /**
+ Returns value of the <b>Subject</b> option.
+ */
+ LogString getSubject() const;
+
+
+ /**
+ The <b>From</b> option takes a string value which should be a
+ e-mail address of the sender.
+ */
+ void setFrom(const LogString& from);
+
+ /**
+ The <b>Subject</b> option takes a string value which should be a
+ the subject of the e-mail message.
+ */
+ void setSubject(const LogString& subject);
+
+ /**
+ The <b>BufferSize</b> option takes a positive integer
+ representing the maximum number of logging events to collect in a
+ cyclic buffer. When the <code>BufferSize</code> is reached,
+ oldest events are deleted as new events are added to the
+ buffer. By default the size of the cyclic buffer is 512 events.
+ */
+ void setBufferSize(int bufferSize);
+
+ /**
+ The <b>SMTPHost</b> option takes a string value which should be a
+ the host name of the SMTP server that will send the e-mail message.
+ */
+ void setSMTPHost(const LogString& smtpHost);
+
+ /**
+ Returns value of the <b>SMTPHost</b> option.
+ */
+ LogString getSMTPHost() const;
+
+ /**
+ The <b>SMTPPort</b> option takes a string value which should be a
+ the port of the SMTP server that will send the e-mail message.
+ */
+ void setSMTPPort(int port);
+
+ /**
+ Returns value of the <b>SMTPHost</b> option.
+ */
+ int getSMTPPort() const;
+
+ /**
+ The <b>To</b> option takes a string value which should be a
+ comma separated list of e-mail address of the recipients.
+ */
+ void setTo(const LogString& to);
+
+ /**
+ The <b>Cc</b> option takes a string value which should be a
+ comma separated list of e-mail address of the cc'd recipients.
+ */
+ void setCc(const LogString& to);
+
+ /**
+ The <b>Bcc</b> option takes a string value which should be a
+ comma separated list of e-mail address of the bcc'd recipients.
+ */
+ void setBcc(const LogString& to);
+
+
+ /**
+ The <b>SMTPUsername</b> option takes a string value which should be a
+ the user name for the SMTP server.
+ */
+ void setSMTPUsername(const LogString& newVal);
+
+ /**
+ Returns value of the <b>SMTPUsername</b> option.
+ */
+ LogString getSMTPUsername() const;
+
+ /**
+ The <b>SMTPPassword</b> option takes a string value which should be a
+ the password for the SMTP server.
+ */
+ void setSMTPPassword(const LogString& newVal);
+
+ /**
+ Returns value of the <b>SMTPPassword</b> option.
+ */
+ LogString getSMTPPassword() const;
+
+ /**
+ Returns value of the <b>BufferSize</b> option.
+ */
+ inline int getBufferSize() const
+ { return bufferSize; }
+
+
+ /**
+ * Gets the current triggering evaluator.
+ * @return triggering evaluator.
+ */
+ log4cxx::spi::TriggeringEventEvaluatorPtr getEvaluator() const;
+
+ /**
+ * Sets the triggering evaluator.
+ * @param trigger triggering evaluator.
+ */
+ void setEvaluator(log4cxx::spi::TriggeringEventEvaluatorPtr& trigger);
+
+ /**
+ The <b>EvaluatorClass</b> option takes a string value
+ representing the name of the class implementing the
+ spi::TriggeringEventEvaluator interface. A corresponding object will
+ be instantiated and assigned as the triggering event evaluator
+ for the SMTPAppender.
+ */
+ void setEvaluatorClass(const LogString& value);
+
+ /**
+ The <b>LocationInfo</b> option is provided for compatibility with log4j
+ and has no effect in log4cxx.
+ */
+ void setLocationInfo(bool locationInfo);
+
+ /**
+ Returns value of the <b>LocationInfo</b> option.
+ */
+ bool getLocationInfo() const;
+ }; // class SMTPAppender
+
+ LOG4CXX_PTR_DEF(SMTPAppender);
+
+ } // namespace net
+} // namespace log4cxx
+
+#endif // _LOG4CXX_NET_SMTP_H
diff --git a/src/main/include/log4cxx/net/socketappender.h b/src/main/include/log4cxx/net/socketappender.h
new file mode 100644
index 0000000..b32ade6
--- /dev/null
+++ b/src/main/include/log4cxx/net/socketappender.h
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_NET_SOCKET_APPENDER_H
+#define _LOG4CXX_NET_SOCKET_APPENDER_H
+
+#include <log4cxx/net/socketappenderskeleton.h>
+#include <log4cxx/helpers/objectoutputstream.h>
+
+namespace log4cxx
+{
+ namespace net
+ {
+
+ /**
+ Sends {@link log4cxx::spi::LoggingEvent LoggingEvent} objects to a remote a log server,
+ usually Apache Chainsaw.
+
+ <p>The SocketAppender has the following properties:
+
+ - If sent to Apache Chainsaw, 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, {@link
+ NDC NDC}, location info as if it were logged locally by
+ the client.
+
+ - SocketAppenders do not use a layout. They ship a
+ serialized {@link log4cxx::spi::LoggingEvent LoggingEvent} object
+ to the server side.
+
+ - Remote logging uses the TCP protocol. Consequently, if
+ the server is reachable, then log events will eventually arrive
+ at the server.
+
+ - If the remote server is down, the logging requests are
+ simply dropped. However, if and when the server comes back up,
+ then event transmission is resumed transparently. This
+ transparent reconneciton is performed by a <em>connector</em>
+ thread which periodically attempts to connect to the server.
+
+ - 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.
+ @n @n 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.
+
+ - Even if a <code>SocketAppender</code> is no longer
+ attached to any logger, it will not be destroyed in
+ the presence of a connector thread. A connector thread exists
+ only if the connection to the server is down. To avoid this
+ destruction problem, you should #close the the
+ <code>SocketAppender</code> explicitly. See also next item.
+ @n @n Long lived applications which create/destroy many
+ <code>SocketAppender</code> instances should be aware of this
+ destruction problem. Most other applications can safely
+ ignore it.
+
+ - If the application hosting the <code>SocketAppender</code>
+ exits before the <code>SocketAppender</code> is closed either
+ explicitly or subsequent to destruction, then there might
+ be untransmitted data in the pipe which might be lost.
+ @n @n To avoid lost data, it is usually sufficient to
+ #close the <code>SocketAppender</code> either explicitly or by
+ calling the LogManager#shutdown method
+ before exiting the application.
+ */
+
+ class LOG4CXX_EXPORT SocketAppender : public SocketAppenderSkeleton
+ {
+ public:
+ /**
+ The default port number of remote logging server (4560).
+ */
+ static int DEFAULT_PORT;
+
+ /**
+ The default reconnection delay (30000 milliseconds or 30 seconds).
+ */
+ static int DEFAULT_RECONNECTION_DELAY;
+
+ DECLARE_LOG4CXX_OBJECT(SocketAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(SocketAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+ END_LOG4CXX_CAST_MAP()
+
+ SocketAppender();
+ ~SocketAppender();
+
+ /**
+ Connects to remote server at <code>address</code> and <code>port</code>.
+ */
+ SocketAppender(helpers::InetAddressPtr& address, int port);
+
+ /**
+ Connects to remote server at <code>host</code> and <code>port</code>.
+ */
+ SocketAppender(const LogString& host, int port);
+
+
+ protected:
+ virtual void setSocket(log4cxx::helpers::SocketPtr& socket, log4cxx::helpers::Pool& p);
+
+ virtual void cleanUp(log4cxx::helpers::Pool& p);
+
+ virtual int getDefaultDelay() const;
+
+ virtual int getDefaultPort() const;
+
+ void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool);
+
+ private:
+ log4cxx::helpers::ObjectOutputStreamPtr oos;
+
+ }; // class SocketAppender
+
+ LOG4CXX_PTR_DEF(SocketAppender);
+
+ } // namespace net
+} // namespace log4cxx
+
+#endif // _LOG4CXX_NET_SOCKET_APPENDER_H
+
diff --git a/src/main/include/log4cxx/net/socketappenderskeleton.h b/src/main/include/log4cxx/net/socketappenderskeleton.h
new file mode 100755
index 0000000..3dcb8a9
--- /dev/null
+++ b/src/main/include/log4cxx/net/socketappenderskeleton.h
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_NET_SOCKET_APPENDER_SKELETON_H
+#define _LOG4CXX_NET_SOCKET_APPENDER_SKELETON_H
+
+#include <log4cxx/appenderskeleton.h>
+#include <log4cxx/helpers/socket.h>
+#include <log4cxx/helpers/thread.h>
+#include <log4cxx/helpers/objectoutputstream.h>
+
+namespace log4cxx
+{
+
+ namespace net
+ {
+
+ /**
+ * Abstract base class for SocketAppender and XMLSocketAppender
+ */
+ class LOG4CXX_EXPORT SocketAppenderSkeleton : public AppenderSkeleton
+ {
+ private:
+ /**
+ host name
+ */
+ LogString remoteHost;
+
+ /**
+ IP address
+ */
+ helpers::InetAddressPtr address;
+
+ int port;
+ int reconnectionDelay;
+ bool locationInfo;
+
+ public:
+ SocketAppenderSkeleton(int defaultPort, int reconnectionDelay);
+ ~SocketAppenderSkeleton();
+
+ /**
+ Connects to remote server at <code>address</code> and <code>port</code>.
+ */
+ SocketAppenderSkeleton(helpers::InetAddressPtr address, int port, int reconnectionDelay);
+
+ /**
+ Connects to remote server at <code>host</code> and <code>port</code>.
+ */
+ SocketAppenderSkeleton(const LogString& host, int port, int reconnectionDelay);
+
+ /**
+ Connect to the specified <b>RemoteHost</b> and <b>Port</b>.
+ */
+ void activateOptions(log4cxx::helpers::Pool& p);
+
+ void close();
+
+
+ /**
+ * This appender does not use a layout. Hence, this method
+ * returns <code>false</code>.
+ *
+ */
+ bool requiresLayout() const
+ { return false; }
+
+ /**
+ * The <b>RemoteHost</b> option takes a string value which should be
+ * the host name of the server where a
+ * Apache Chainsaw or compatible is running.
+ * */
+ inline void setRemoteHost(const LogString& host)
+ { address = helpers::InetAddress::getByName(host);
+ remoteHost.assign(host); }
+
+ /**
+ Returns value of the <b>RemoteHost</b> option.
+ */
+ inline const LogString& getRemoteHost() const
+ { return remoteHost; }
+
+ /**
+ The <b>Port</b> option takes a positive integer representing
+ the port where the server is waiting for connections.
+ */
+ void setPort(int port1)
+ { this->port = port1; }
+
+ /**
+ Returns value of the <b>Port</b> option.
+ */
+ int getPort() const
+ { return port; }
+
+ /**
+ The <b>LocationInfo</b> option takes a boolean value. If true,
+ the information sent to the remote host will include location
+ information. By default no location information is sent to the server.
+ */
+ void setLocationInfo(bool locationInfo1)
+ { this->locationInfo = locationInfo1; }
+
+ /**
+ Returns value of the <b>LocationInfo</b> option.
+ */
+ bool getLocationInfo() const
+ { return locationInfo; }
+
+ /**
+ The <b>ReconnectionDelay</b> option takes a positive integer
+ representing the number of milliseconds to wait between each
+ failed connection attempt to the server. The default value of
+ this option is 30000 which corresponds to 30 seconds.
+
+ <p>Setting this option to zero turns off reconnection
+ capability.
+ */
+ void setReconnectionDelay(int reconnectionDelay1)
+ { this->reconnectionDelay = reconnectionDelay1; }
+
+ /**
+ Returns value of the <b>ReconnectionDelay</b> option.
+ */
+ int getReconnectionDelay() const
+ { return reconnectionDelay; }
+
+ void fireConnector();
+
+ void setOption(const LogString& option,
+ const LogString& value);
+
+ protected:
+
+ virtual void setSocket(log4cxx::helpers::SocketPtr& socket, log4cxx::helpers::Pool& p) = 0;
+
+ virtual void cleanUp(log4cxx::helpers::Pool& p) = 0;
+
+ virtual int getDefaultDelay() const = 0;
+
+ virtual int getDefaultPort() const = 0;
+
+ private:
+ void connect(log4cxx::helpers::Pool& p);
+ /**
+ The Connector will reconnect when the server becomes available
+ again. It does this by attempting to open a new connection every
+ <code>reconnectionDelay</code> milliseconds.
+
+ <p>It stops trying whenever a connection is established. It will
+ restart to try reconnect to the server when previpously open
+ connection is droppped.
+ */
+
+ helpers::Thread thread;
+ static void* LOG4CXX_THREAD_FUNC monitor(apr_thread_t* thread, void* data);
+ SocketAppenderSkeleton(const SocketAppenderSkeleton&);
+ SocketAppenderSkeleton& operator=(const SocketAppenderSkeleton&);
+
+ }; // class SocketAppenderSkeleton
+ } // namespace net
+} // namespace log4cxx
+
+#endif // _LOG4CXX_NET_SOCKET_APPENDER_SKELETON_H
+
diff --git a/src/main/include/log4cxx/net/sockethubappender.h b/src/main/include/log4cxx/net/sockethubappender.h
new file mode 100644
index 0000000..8994833
--- /dev/null
+++ b/src/main/include/log4cxx/net/sockethubappender.h
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_NET_SOCKET_HUB_APPENDER_H
+#define _LOG4CXX_NET_SOCKET_HUB_APPENDER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/appenderskeleton.h>
+#include <vector>
+#include <log4cxx/helpers/thread.h>
+#include <log4cxx/helpers/objectoutputstream.h>
+
+
+namespace log4cxx
+{
+ namespace helpers {
+ class ObjectOutputStream;
+ typedef ObjectPtrT<ObjectOutputStream> ObjectOutputStreamPtr;
+ }
+ namespace net
+ {
+ /**
+ Sends {@link log4cxx::spi::LoggingEvent LoggingEvent} objects to a set of remote log
+ servers, usually a SocketNode.
+
+ <p>Acts just like SocketAppender except that instead of
+ connecting to a given remote log server,
+ <code>SocketHubAppender</code> accepts connections from the remote
+ log servers as clients. It can accept more than one connection.
+ When a log event is received, the event is sent to the set of
+ currently connected remote log servers. Implemented this way it does
+ not require any update to the configuration file to send data to
+ another remote log server. The remote log server simply connects to
+ the host and port the <code>SocketHubAppender</code> is running on.
+
+ <p>The <code>SocketHubAppender</code> does not store events such
+ that the remote side will events that arrived after the
+ establishment of its connection. Once connected, events arrive in
+ order as guaranteed by the TCP protocol.
+
+ <p>This implementation borrows heavily from the SocketAppender.
+
+ <p>The SocketHubAppender has the following characteristics:
+
+ - If sent to a SocketNode, 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.
+
+ - <code>SocketHubAppender</code> does not use a layout. It
+ ships a serialized spi::LoggingEvent object to the remote side.
+
+ - <code>SocketHubAppender</code> relies on the TCP
+ protocol. Consequently, if the remote side is reachable, then log
+ events will eventually arrive at remote client.
+
+ - If no remote clients are attached, the logging requests are
+ simply dropped.
+
+ - Logging events are automatically <em>buffered</em> by the
+ native TCP implementation. This means that if the link to remote
+ client is slow but still faster than the rate of (log) event
+ production, the application will not be affected by the slow network
+ connection. However, if the network connection is slower then the
+ rate of event production, then the local application can only
+ progress at the network rate. In particular, if the network link to
+ the the remote client is down, the application will be blocked.
+ @n @n On the other hand, if the network link is up, but the remote
+ client is down, the client will not be blocked when making log
+ requests but the log events will be lost due to client
+ unavailability.
+ @n @n The single remote client case extends to multiple clients
+ connections. The rate of logging will be determined by the slowest
+ link.
+
+ - If the application hosting the <code>SocketHubAppender</code>
+ exits before the <code>SocketHubAppender</code> is closed either
+ explicitly or subsequent to garbage collection, then there might
+ be untransmitted data in the pipe which might be lost. This is a
+ common problem on Windows based systems.
+ @n @n To avoid lost data, it is usually sufficient to #close
+ the <code>SocketHubAppender</code> either explicitly or by calling
+ the LogManager#shutdown method before
+ exiting the application.
+ */
+
+ class LOG4CXX_EXPORT SocketHubAppender : public AppenderSkeleton
+ {
+ private:
+ /**
+ The default port number of the ServerSocket will be created on.
+ */
+ static int DEFAULT_PORT;
+
+ int port;
+ LOG4CXX_LIST_DEF(ObjectOutputStreamList, log4cxx::helpers::ObjectOutputStreamPtr);
+ ObjectOutputStreamList streams;
+ bool locationInfo;
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(SocketHubAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(SocketHubAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+ END_LOG4CXX_CAST_MAP()
+
+ SocketHubAppender();
+ ~SocketHubAppender();
+
+ /**
+ Connects to remote server at <code>address</code> and <code>port</code>.
+ */
+ SocketHubAppender(int port) ;
+
+ /**
+ Set up the socket server on the specified port.
+ */
+ virtual void activateOptions(log4cxx::helpers::Pool& p);
+
+ /**
+ Set options
+ */
+ virtual void setOption(const LogString& option, const LogString& value);
+
+ virtual void close();
+
+ /**
+ Append an event to all of current connections. */
+ virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);
+
+ /**
+ The SocketHubAppender does not use a layout. Hence, this method returns
+ <code>false</code>. */
+ virtual bool requiresLayout() const
+ { return false; }
+
+ /**
+ The <b>Port</b> option takes a positive integer representing
+ the port where the server is waiting for connections. */
+ inline void setPort(int port1)
+ { this->port = port1; }
+
+ /**
+ Returns value of the <b>Port</b> option. */
+ inline int getPort() const
+ { return port; }
+
+ /**
+ The <b>LocationInfo</b> option takes a boolean value. If true,
+ the information sent to the remote host will include location
+ information. By default no location information is sent to the server. */
+ inline void setLocationInfo(bool locationInfo1)
+ { this->locationInfo = locationInfo1; }
+
+ /**
+ Returns value of the <b>LocationInfo</b> option. */
+ inline bool getLocationInfo() const
+ { return locationInfo; }
+
+ /**
+ Start the ServerMonitor thread. */
+ private:
+ void startServer();
+
+ helpers::Thread thread;
+ static void* LOG4CXX_THREAD_FUNC monitor(apr_thread_t* thread, void* data);
+
+ }; // class SocketHubAppender
+ LOG4CXX_PTR_DEF(SocketHubAppender);
+ } // namespace net
+} // namespace log4cxx
+
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif // _LOG4CXX_NET_SOCKET_HUB_APPENDER_H
diff --git a/src/main/include/log4cxx/net/syslogappender.h b/src/main/include/log4cxx/net/syslogappender.h
new file mode 100644
index 0000000..27f737b
--- /dev/null
+++ b/src/main/include/log4cxx/net/syslogappender.h
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_NET_SYSLOG_APPENDER_H
+#define _LOG4CXX_NET_SYSLOG_APPENDER_H
+
+#include <log4cxx/appenderskeleton.h>
+#include <log4cxx/helpers/syslogwriter.h>
+
+namespace log4cxx
+{
+ namespace net
+ {
+ /** Use SyslogAppender to send log messages to a remote syslog daemon.*/
+ class LOG4CXX_EXPORT SyslogAppender : public AppenderSkeleton
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(SyslogAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(SyslogAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+ END_LOG4CXX_CAST_MAP()
+
+
+
+ SyslogAppender();
+ SyslogAppender(const LayoutPtr& layout, int syslogFacility);
+ SyslogAppender(const LayoutPtr& layout,
+ const LogString& syslogHost, int syslogFacility);
+ ~SyslogAppender();
+ /** Release any resources held by this SyslogAppender.*/
+ void close();
+
+ /**
+ Returns the specified syslog facility as a lower-case String,
+ e.g. "kern", "user", etc.
+ */
+ static LogString getFacilityString(int syslogFacility);
+
+ /**
+ Returns the integer value corresponding to the named syslog
+ facility, or -1 if it couldn't be recognized.
+ @param facilityName one of the strings KERN, USER, MAIL, DAEMON,
+ AUTH, SYSLOG, LPR, NEWS, UUCP, CRON, AUTHPRIV, FTP, LOCAL0,
+ LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+ The matching is case-insensitive.
+ */
+ static int getFacility(const LogString &facilityName);
+
+ void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);
+
+ /**
+ This method returns immediately as options are activated when they
+ are set.
+ */
+ void activateOptions(log4cxx::helpers::Pool& p);
+ void setOption(const LogString& option, const LogString& value);
+
+ /**
+ The SyslogAppender requires a layout. Hence, this method returns
+ <code>true</code>.
+ */
+ virtual bool requiresLayout() const
+ { return true; }
+
+ /**
+ The <b>SyslogHost</b> option is the name of the the syslog host
+ where log output should go.
+ <b>WARNING</b> If the SyslogHost is not set, then this appender
+ will fail.
+ */
+ void setSyslogHost(const LogString& syslogHost);
+
+ /**
+ Returns the value of the <b>SyslogHost</b> option.
+ */
+ inline const LogString& getSyslogHost() const
+ { return syslogHost; }
+
+ /**
+ Set the syslog facility. This is the <b>Facility</b> option.
+
+ <p>The <code>facilityName</code> parameter must be one of the
+ strings KERN, USER, MAIL, DAEMON, AUTH, SYSLOG, LPR, NEWS, UUCP,
+ CRON, AUTHPRIV, FTP, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4,
+ LOCAL5, LOCAL6, LOCAL7. Case is unimportant.
+ */
+ void setFacility(const LogString& facilityName);
+
+ /**
+ Returns the value of the <b>Facility</b> option.
+ */
+ inline LogString getFacility() const
+ { return getFacilityString(syslogFacility); }
+
+ /**
+ If the <b>FacilityPrinting</b> option is set to true, the printed
+ message will include the facility name of the application. It is
+ <em>false</em> by default.
+ */
+ inline void setFacilityPrinting(bool facilityPrinting1)
+ { this->facilityPrinting = facilityPrinting1; }
+
+ /**
+ Returns the value of the <b>FacilityPrinting</b> option.
+ */
+ inline bool getFacilityPrinting() const
+ { return facilityPrinting; }
+
+ protected:
+ void initSyslogFacilityStr();
+
+ int syslogFacility; // Have LOG_USER as default
+ LogString facilityStr;
+ bool facilityPrinting;
+ helpers::SyslogWriter * sw;
+ LogString syslogHost;
+ private:
+ SyslogAppender(const SyslogAppender&);
+ SyslogAppender& operator=(const SyslogAppender&);
+ }; // class SyslogAppender
+ LOG4CXX_PTR_DEF(SyslogAppender);
+ } // namespace net
+} // namespace log4cxx
+
+#endif // _LOG4CXX_NET_SYSLOG_APPENDER_H
+
diff --git a/src/main/include/log4cxx/net/telnetappender.h b/src/main/include/log4cxx/net/telnetappender.h
new file mode 100644
index 0000000..5cbe2b0
--- /dev/null
+++ b/src/main/include/log4cxx/net/telnetappender.h
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_NET_TELNET_APPENDER_H
+#define _LOG4CXX_NET_TELNET_APPENDER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+
+#include <log4cxx/appenderskeleton.h>
+#include <log4cxx/helpers/socket.h>
+#include <log4cxx/helpers/serversocket.h>
+#include <log4cxx/helpers/thread.h>
+#include <vector>
+#include <log4cxx/helpers/charsetencoder.h>
+
+namespace log4cxx
+{
+ namespace helpers {
+ class ByteBuffer;
+ }
+ namespace net
+ {
+/**
+<p>The TelnetAppender is a log4cxx appender that specializes in
+writing to a read-only socket. The output is provided in a
+telnet-friendly way so that a log can be monitored over TCP/IP.
+Clients using telnet connect to the socket and receive log data.
+This is handy for remote monitoring, especially when monitoring a
+servlet.
+
+<p>Here is a list of the available configuration options:
+
+<table border=1>
+<tr>
+<td align=center><b>Name</b></td>
+<td align=center><b>Requirement</b></td>
+<td align=center><b>Description</b></td>
+<td align=center><b>Sample Value</b></td>
+</tr>
+
+<tr>
+<td>Port</td>
+<td>optional</td>
+<td>This parameter determines the port to use for announcing log events. The default port is 23 (telnet).</td>
+<td>5875</td>
+</table>
+*/
+ class LOG4CXX_EXPORT TelnetAppender : public AppenderSkeleton
+ {
+ class SocketHandler;
+ friend class SocketHandler;
+ private:
+ static const int DEFAULT_PORT;
+ static const int MAX_CONNECTIONS;
+ int port;
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(TelnetAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(TelnetAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+ END_LOG4CXX_CAST_MAP()
+
+ TelnetAppender();
+ ~TelnetAppender();
+
+ /**
+ This appender requires a layout to format the text to the
+ attached client(s). */
+ virtual bool requiresLayout() const
+ { return true; }
+
+ LogString getEncoding() const;
+ void setEncoding(const LogString& value);
+
+
+ /** all of the options have been set, create the socket handler and
+ wait for connections. */
+ void activateOptions(log4cxx::helpers::Pool& p);
+
+ /**
+ Set options
+ */
+ virtual void setOption(const LogString& option, const LogString& value);
+
+ /**
+ Returns value of the <b>Port</b> option.
+ */
+ int getPort() const
+ { return port; }
+
+ /**
+ The <b>Port</b> option takes a positive integer representing
+ the port where the server is waiting for connections.
+ */
+ void setPort(int port1)
+ { this->port = port1; }
+
+
+ /** shuts down the appender. */
+ void close();
+
+ protected:
+ /** Handles a log event. For this appender, that means writing the
+ message to each connected client. */
+ virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) ;
+
+ //---------------------------------------------------------- SocketHandler:
+
+ private:
+ // prevent copy and assignment statements
+ TelnetAppender(const TelnetAppender&);
+ TelnetAppender& operator=(const TelnetAppender&);
+
+ typedef log4cxx::helpers::SocketPtr Connection;
+ LOG4CXX_LIST_DEF(ConnectionList, Connection);
+
+ void write(log4cxx::helpers::ByteBuffer&);
+ void writeStatus(const log4cxx::helpers::SocketPtr& socket, const LogString& msg, log4cxx::helpers::Pool& p);
+ ConnectionList connections;
+ LogString encoding;
+ log4cxx::helpers::CharsetEncoderPtr encoder;
+ helpers::ServerSocket* serverSocket;
+ helpers::Thread sh;
+ size_t activeConnections;
+ static void* LOG4CXX_THREAD_FUNC acceptConnections(apr_thread_t* thread, void* data);
+ }; // class TelnetAppender
+
+ LOG4CXX_PTR_DEF(TelnetAppender);
+ } // namespace net
+} // namespace log4cxx
+
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif // _LOG4CXX_NET_TELNET_APPENDER_H
+
diff --git a/src/main/include/log4cxx/net/xmlsocketappender.h b/src/main/include/log4cxx/net/xmlsocketappender.h
new file mode 100644
index 0000000..d99940f
--- /dev/null
+++ b/src/main/include/log4cxx/net/xmlsocketappender.h
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_NET_XML_SOCKET_APPENDER_H
+#define _LOG4CXX_NET_XML_SOCKET_APPENDER_H
+
+#include <log4cxx/net/socketappenderskeleton.h>
+#include <log4cxx/helpers/writer.h>
+
+namespace log4cxx
+{
+ namespace net
+ {
+
+ /**
+ Sends {@link log4cxx::spi::LoggingEvent LoggingEvent} objects in XML format
+ to a remote a log server, usually a XMLSocketNode.
+
+ <p>The XMLSocketAppender has the following properties:
+
+ - If sent to a XMLSocketNode, 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, {@link
+ NDC NDC}, location info as if it were logged locally by
+ the client.
+
+ - XMLSocketAppenders use exclusively an XMLLayout. They ship an
+ XML stream representing a {@link spi::LoggingEvent LoggingEvent} object
+ to the server side.
+
+ - Remote logging uses the TCP protocol. Consequently, if
+ the server is reachable, then log events will eventually arrive
+ at the server.
+
+ - If the remote server is down, the logging requests are
+ simply dropped. However, if and when the server comes back up,
+ then event transmission is resumed transparently. This
+ transparent reconneciton is performed by a <em>connector</em>
+ thread which periodically attempts to connect to the server.
+
+ - 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.
+ @n @n 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.
+
+ - Even if an <code>XMLSocketAppender</code> is no longer
+ attached to any logger, it will not be destroyed in
+ the presence of a connector thread. A connector thread exists
+ only if the connection to the server is down. To avoid this
+ destruction problem, you should #close the the
+ <code>XMLSocketAppender</code> explicitly. See also next item.
+ @n @n Long lived applications which create/destroy many
+ <code>XMLSocketAppender</code> instances should be aware of this
+ destruction problem. Most other applications can safely
+ ignore it.
+
+ - If the application hosting the <code>XMLSocketAppender</code>
+ exits before the <code>XMLSocketAppender</code> is closed either
+ explicitly or subsequent to destruction, then there might
+ be untransmitted data in the pipe which might be lost.
+ @n @n To avoid lost data, it is usually sufficient to
+ #close the <code>XMLSocketAppender</code> either explicitly or by
+ calling the LogManager#shutdown method
+ before exiting the application.
+ */
+
+ class LOG4CXX_EXPORT XMLSocketAppender : public SocketAppenderSkeleton
+ {
+ public:
+ /**
+ The default port number of remote logging server (4560).
+ */
+ static int DEFAULT_PORT;
+
+ /**
+ The default reconnection delay (30000 milliseconds or 30 seconds).
+ */
+ static int DEFAULT_RECONNECTION_DELAY;
+
+ /**
+ An event XML stream cannot exceed 1024 bytes.
+ */
+ static const int MAX_EVENT_LEN;
+
+ DECLARE_LOG4CXX_OBJECT(XMLSocketAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(XMLSocketAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+ END_LOG4CXX_CAST_MAP()
+
+ XMLSocketAppender();
+ ~XMLSocketAppender();
+
+ /**
+ Connects to remote server at <code>address</code> and <code>port</code>.
+ */
+ XMLSocketAppender(helpers::InetAddressPtr address, int port);
+
+ /**
+ Connects to remote server at <code>host</code> and <code>port</code>.
+ */
+ XMLSocketAppender(const LogString& host, int port);
+
+
+ protected:
+ virtual void setSocket(log4cxx::helpers::SocketPtr& socket, log4cxx::helpers::Pool& p);
+
+ virtual void cleanUp(log4cxx::helpers::Pool& p);
+
+ virtual int getDefaultDelay() const;
+
+ virtual int getDefaultPort() const;
+
+ void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool);
+
+ private:
+ log4cxx::helpers::WriterPtr writer;
+ // prevent copy and assignment statements
+ XMLSocketAppender(const XMLSocketAppender&);
+ XMLSocketAppender& operator=(const XMLSocketAppender&);
+ }; // class XMLSocketAppender
+
+ LOG4CXX_PTR_DEF(XMLSocketAppender);
+
+ } // namespace net
+} // namespace log4cxx
+
+#endif // _LOG4CXX_NET_XML_SOCKET_APPENDER_H
+
diff --git a/src/main/include/log4cxx/nt/EventLogCategories.mc b/src/main/include/log4cxx/nt/EventLogCategories.mc
new file mode 100644
index 0000000..e508746
--- /dev/null
+++ b/src/main/include/log4cxx/nt/EventLogCategories.mc
@@ -0,0 +1,42 @@
+;
+; Licensed to the Apache Software Foundation (ASF) under one
+; or more contributor license agreements. See the NOTICE file
+; distributed with this work for additional information
+; regarding copyright ownership. The ASF licenses this file
+; to you under the Apache License, Version 2.0 (the
+; "License"); you may not use this file except in compliance
+; with the License. You may obtain a copy of the License at
+;
+; http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing,
+; software distributed under the License is distributed on an
+; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+; KIND, either express or implied. See the License for the
+; specific language governing permissions and limitations
+; under the License.
+;
+MessageId=0x0001
+Language=English
+Fatal
+.
+MessageId=0x0002
+Language=English
+Error
+.
+MessageId=0x0003
+Language=English
+Warn
+.
+MessageId=0x0004
+Language=English
+Info
+.
+MessageId=0x0005
+Language=English
+Debug
+.
+MessageId=0x1000
+Language=English
+%1
+.
diff --git a/src/main/include/log4cxx/nt/Makefile.am b/src/main/include/log4cxx/nt/Makefile.am
new file mode 100644
index 0000000..c75bbbd
--- /dev/null
+++ b/src/main/include/log4cxx/nt/Makefile.am
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+ntincdir = $(includedir)/log4cxx/nt
+ntinc_HEADERS= $(top_srcdir)/src/main/include/log4cxx/nt/*.h
+
diff --git a/src/main/include/log4cxx/nt/nteventlogappender.h b/src/main/include/log4cxx/nt/nteventlogappender.h
new file mode 100644
index 0000000..4951bcc
--- /dev/null
+++ b/src/main/include/log4cxx/nt/nteventlogappender.h
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_NT_EVENT_LOG_APPENDER_HEADER_
+#define _LOG4CXX_NT_EVENT_LOG_APPENDER_HEADER_
+
+#include <log4cxx/appenderskeleton.h>
+
+
+namespace log4cxx
+{
+ namespace nt
+ {
+ /**
+ * Appends log events to NT EventLog.
+ */
+ class LOG4CXX_EXPORT NTEventLogAppender : public AppenderSkeleton
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(NTEventLogAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(NTEventLogAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+ END_LOG4CXX_CAST_MAP()
+
+ NTEventLogAppender();
+ NTEventLogAppender(const LogString& server, const LogString& log,
+ const LogString& source, const LayoutPtr& layout);
+
+ virtual ~NTEventLogAppender();
+
+ virtual void activateOptions(log4cxx::helpers::Pool& p);
+ virtual void close();
+ virtual void setOption(const LogString& option, const LogString& value);
+
+ /**
+ * The SocketAppender does not use a layout. Hence, this method
+ * returns <code>false</code>.
+ *
+ */
+ bool requiresLayout() const
+ { return true; }
+
+ void setSource(const LogString& source)
+ { this->source.assign(source); }
+
+ const LogString& getSource() const
+ { return source; }
+
+ void setLog(const LogString& log)
+ { this->log.assign(log); }
+
+ const LogString& getLog() const
+ { return log; }
+
+ void setServer(const LogString& server)
+ { this->server.assign(server); }
+
+ const LogString& getServer() const
+ { return server; }
+
+
+ protected:
+ //
+ // these typedef are proxies for the real Win32 definitions
+ // and need to be cast to the global definitions before
+ // use with a Win32 API call
+ typedef void SID;
+ typedef void* HANDLE;
+
+ virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);
+ static unsigned short getEventType(const spi::LoggingEventPtr& event);
+ static unsigned short getEventCategory(const spi::LoggingEventPtr& event);
+ /*
+ * Add this source with appropriate configuration keys to the registry.
+ */
+ void addRegistryInfo();
+
+ // Data
+ LogString server;
+ LogString log;
+ LogString source;
+ HANDLE hEventLog;
+ SID * pCurrentUserSID;
+ static LogString getErrorString(const LogString& function);
+
+ private:
+ NTEventLogAppender(const NTEventLogAppender&);
+ NTEventLogAppender& operator=(const NTEventLogAppender&);
+ }; // class NTEventLogAppender
+
+ LOG4CXX_PTR_DEF(NTEventLogAppender);
+
+ } // namespace nt
+} // namespace log4cxx
+
+#endif //_LOG4CXX_NT_EVENT_LOG_APPENDER_HEADER_
diff --git a/src/main/include/log4cxx/nt/outputdebugstringappender.h b/src/main/include/log4cxx/nt/outputdebugstringappender.h
new file mode 100644
index 0000000..b9cc7d9
--- /dev/null
+++ b/src/main/include/log4cxx/nt/outputdebugstringappender.h
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_NT_OUTPUTDEBUGSTRING_APPENDER_HEADER_
+#define _LOG4CXX_NT_OUTPUTDEBUGSTRING_APPENDER_HEADER_
+
+#include <log4cxx/appenderskeleton.h>
+
+namespace log4cxx
+{
+ namespace nt
+ {
+ class LOG4CXX_EXPORT OutputDebugStringAppender : public AppenderSkeleton
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(OutputDebugStringAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(OutputDebugStringAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+ END_LOG4CXX_CAST_MAP()
+
+ OutputDebugStringAppender();
+
+ bool requiresLayout() const
+ { return true; }
+
+ virtual void close() {}
+
+ virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);
+ };
+ }
+}
+
+#endif //_LOG4CXX_NT_OUTPUTDEBUGSTRING_APPENDER_HEADER_
diff --git a/src/main/include/log4cxx/pattern/Makefile.am b/src/main/include/log4cxx/pattern/Makefile.am
new file mode 100644
index 0000000..2170096
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/Makefile.am
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+patternincdir = $(includedir)/log4cxx/pattern
+patterninc_HEADERS= $(top_srcdir)/src/main/include/log4cxx/pattern/*.h
+
diff --git a/src/main/include/log4cxx/pattern/classnamepatternconverter.h b/src/main/include/log4cxx/pattern/classnamepatternconverter.h
new file mode 100644
index 0000000..dd750b8
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/classnamepatternconverter.h
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_CLASSNAME_PATTERN_CONVERTER_H
+#define _LOG4CXX_PATTERN_CLASSNAME_PATTERN_CONVERTER_H
+
+
+#include <log4cxx/pattern/namepatternconverter.h>
+
+namespace log4cxx {
+ namespace pattern {
+
+
+/**
+ * Formats the class name of the site of the logging request.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT ClassNamePatternConverter : public NamePatternConverter {
+ /**
+ * Private constructor.
+ * @param options options, may be null.
+ * @param logger logger for diagnostic messages, may be null.
+ */
+ ClassNamePatternConverter(
+ const std::vector<LogString>& options);
+
+public:
+ DECLARE_LOG4CXX_PATTERN(ClassNamePatternConverter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(ClassNamePatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(NamePatternConverter)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Gets an instance of ClassNamePatternConverter.
+ * @param options options, may be null.
+ * @return instance of pattern converter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ void format(const log4cxx::spi::LoggingEventPtr&event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+
+ }
+}
+#endif
diff --git a/src/main/include/log4cxx/pattern/datepatternconverter.h b/src/main/include/log4cxx/pattern/datepatternconverter.h
new file mode 100644
index 0000000..e556ef3
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/datepatternconverter.h
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_DATE_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_DATE_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+#include <log4cxx/helpers/cacheddateformat.h>
+#include <log4cxx/helpers/date.h>
+#include <vector>
+
+namespace log4cxx {
+ namespace pattern {
+
+
+/**
+ * Convert and format the event's date in a StringBuffer.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT DatePatternConverter : public LoggingEventPatternConverter {
+ /**
+ * Date format.
+ */
+ log4cxx::helpers::DateFormatPtr df;
+
+ /**
+ * Private constructor.
+ * @param options options, may be null.
+ * @param logger logger for diagnostic messages, may be null.
+ */
+ DatePatternConverter(const OptionsList& options);
+
+ /**
+ * Obtains an instance of pattern converter.
+ * @param options options, may be null.
+ * @return instance of pattern converter.
+ */
+ static log4cxx::helpers::DateFormatPtr getDateFormat(const OptionsList& options);
+ public:
+ DECLARE_LOG4CXX_PATTERN(DatePatternConverter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(DatePatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+ END_LOG4CXX_CAST_MAP()
+
+
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& output,
+ log4cxx::helpers::Pool& p) const;
+ void format(const log4cxx::helpers::ObjectPtr& obj,
+ LogString& output,
+ log4cxx::helpers::Pool& p) const;
+
+ void format(const log4cxx::helpers::DatePtr& date,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+
+LOG4CXX_PTR_DEF(DatePatternConverter);
+
+ }
+}
+#endif
+
diff --git a/src/main/include/log4cxx/pattern/filedatepatternconverter.h b/src/main/include/log4cxx/pattern/filedatepatternconverter.h
new file mode 100644
index 0000000..9e15239
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/filedatepatternconverter.h
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_FILE_DATE_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_FILE_DATE_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/patternconverter.h>
+
+namespace log4cxx { namespace pattern {
+
+
+/**
+ * Formats an date by delegating to DatePatternConverter. The default
+ * date pattern for a %d specifier in a file name is different than
+ * the %d pattern in pattern layout.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT FileDatePatternConverter {
+ /**
+ * Private constructor.
+ */
+ FileDatePatternConverter();
+
+public:
+ /**
+ * Obtains an instance of pattern converter.
+ * @param options options, may be null.
+ * @return instance of pattern converter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+};
+}
+}
+#endif
+
diff --git a/src/main/include/log4cxx/pattern/filelocationpatternconverter.h b/src/main/include/log4cxx/pattern/filelocationpatternconverter.h
new file mode 100644
index 0000000..9c053b3
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/filelocationpatternconverter.h
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_FILE_LOCATION_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_FILE_LOCATION_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx {
+ namespace pattern {
+
+
+/**
+ * Return the event's line location information in a StringBuffer.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT FileLocationPatternConverter
+ : public LoggingEventPatternConverter {
+ /**
+ * Private constructor.
+ */
+ FileLocationPatternConverter();
+
+public:
+ DECLARE_LOG4CXX_PATTERN(FileLocationPatternConverter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(FileLocationPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Obtains an instance of pattern converter.
+ * @param options options, may be null.
+ * @return instance of pattern converter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+
+ }
+}
+#endif
diff --git a/src/main/include/log4cxx/pattern/formattinginfo.h b/src/main/include/log4cxx/pattern/formattinginfo.h
new file mode 100644
index 0000000..c3eac5a
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/formattinginfo.h
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPER_FORMATTING_INFO_H
+#define _LOG4CXX_HELPER_FORMATTING_INFO_H
+
+
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/logstring.h>
+
+namespace log4cxx {
+ namespace pattern {
+
+
+class FormattingInfo;
+typedef helpers::ObjectPtrT<FormattingInfo> FormattingInfoPtr;
+
+
+/**
+ * Modifies the output of a pattern converter for a specified minimum
+ * and maximum width and alignment.
+ *
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT FormattingInfo : public virtual log4cxx::helpers::ObjectImpl {
+
+ /**
+ * Minimum length.
+ */
+ const int minLength;
+
+ /**
+ * Maximum length.
+ */
+ const int maxLength;
+
+ /**
+ * Alignment.
+ */
+ const bool leftAlign;
+
+public:
+DECLARE_ABSTRACT_LOG4CXX_OBJECT(FormattingInfo)
+BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(FormattingInfo)
+END_LOG4CXX_CAST_MAP()
+
+
+ /**
+ * Creates new instance.
+ * @param leftAlign left align if true.
+ * @param minLength minimum length.
+ * @param maxLength maximum length.
+ */
+FormattingInfo(
+ const bool leftAlign, const int minLength, const int maxLength);
+
+ /**
+ * Gets default instance.
+ * @return default instance.
+ */
+static FormattingInfoPtr getDefault();
+
+ /**
+ * Determine if left aligned.
+ * @return true if left aligned.
+ */
+inline bool isLeftAligned() const {
+ return leftAlign;
+}
+
+ /**
+ * Get minimum length.
+ * @return minimum length.
+ */
+inline int getMinLength() const {
+ return minLength;
+}
+
+ /**
+ * Get maximum length.
+ * @return maximum length.
+ */
+inline int getMaxLength() const {
+ return maxLength;
+}
+
+ /**
+ * Adjust the content of the buffer based on the specified lengths and alignment.
+ *
+ * @param fieldStart start of field in buffer.
+ * @param buffer buffer to be modified.
+ */
+void format(const int fieldStart, LogString& buffer) const;
+};
+LOG4CXX_PTR_DEF(FormattingInfo);
+ }
+}
+
+
+#endif
diff --git a/src/main/include/log4cxx/pattern/fulllocationpatternconverter.h b/src/main/include/log4cxx/pattern/fulllocationpatternconverter.h
new file mode 100644
index 0000000..bbd7c67
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/fulllocationpatternconverter.h
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_FULL_LOCATION_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_FULL_LOCATION_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx {
+namespace pattern {
+
+
+/**
+ * Format the event's line location information.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT FullLocationPatternConverter
+ : public LoggingEventPatternConverter {
+ /**
+ * Private constructor.
+ */
+ FullLocationPatternConverter();
+
+public:
+ DECLARE_LOG4CXX_PATTERN(FullLocationPatternConverter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(FullLocationPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Obtains an instance of pattern converter.
+ * @param options options, may be null.
+ * @return instance of pattern converter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+
+}
+}
+#endif
+
diff --git a/src/main/include/log4cxx/pattern/integerpatternconverter.h b/src/main/include/log4cxx/pattern/integerpatternconverter.h
new file mode 100644
index 0000000..0667809
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/integerpatternconverter.h
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_INTEGER_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_INTEGER_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/patternconverter.h>
+
+namespace log4cxx { namespace pattern {
+
+
+/**
+ * Formats an integer.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT IntegerPatternConverter : public PatternConverter {
+
+ /**
+ * Private constructor.
+ */
+ IntegerPatternConverter();
+
+public:
+ DECLARE_LOG4CXX_PATTERN(IntegerPatternConverter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(IntegerPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(PatternConverter)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Obtains an instance of pattern converter.
+ * @param options options, may be null.
+ * @return instance of pattern converter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ void format(const log4cxx::helpers::ObjectPtr& obj,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+
+LOG4CXX_PTR_DEF(IntegerPatternConverter);
+
+}
+}
+#endif
+
diff --git a/src/main/include/log4cxx/pattern/levelpatternconverter.h b/src/main/include/log4cxx/pattern/levelpatternconverter.h
new file mode 100644
index 0000000..f0f0039
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/levelpatternconverter.h
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_LEVEL_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_LEVEL_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx { namespace pattern {
+
+
+/**
+ * Return the event's level in a StringBuffer.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT LevelPatternConverter : public LoggingEventPatternConverter {
+ /**
+ * Private constructor.
+ */
+ LevelPatternConverter();
+
+public:
+ DECLARE_LOG4CXX_PATTERN(LevelPatternConverter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(LevelPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Obtains an instance of pattern converter.
+ * @param options options, may be null.
+ * @return instance of pattern converter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+
+ LogString getStyleClass(const log4cxx::helpers::ObjectPtr& e) const;
+};
+}
+}
+#endif
+
diff --git a/src/main/include/log4cxx/pattern/linelocationpatternconverter.h b/src/main/include/log4cxx/pattern/linelocationpatternconverter.h
new file mode 100644
index 0000000..b34d828
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/linelocationpatternconverter.h
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_LINE_LOCATION_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_LINE_LOCATION_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx {
+namespace pattern {
+
+
+/**
+ * Format the event's line location information.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT LineLocationPatternConverter
+ : public LoggingEventPatternConverter {
+ /**
+ * Private constructor.
+ */
+ LineLocationPatternConverter();
+
+public:
+ DECLARE_LOG4CXX_PATTERN(LineLocationPatternConverter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(LineLocationPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Obtains an instance of pattern converter.
+ * @param options options, may be null.
+ * @return instance of pattern converter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+
+}
+}
+#endif
diff --git a/src/main/include/log4cxx/pattern/lineseparatorpatternconverter.h b/src/main/include/log4cxx/pattern/lineseparatorpatternconverter.h
new file mode 100644
index 0000000..2d0a519
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/lineseparatorpatternconverter.h
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_LINE_SEPARATOR_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_LINE_SEPARATOR_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx {
+namespace pattern {
+
+
+/**
+ * Formats a line separator.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT LineSeparatorPatternConverter
+ : public LoggingEventPatternConverter {
+
+ /**
+ * Private constructor.
+ */
+ LineSeparatorPatternConverter();
+
+public:
+DECLARE_LOG4CXX_PATTERN(LineSeparatorPatternConverter)
+BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(LineSeparatorPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+END_LOG4CXX_CAST_MAP()
+
+
+ /**
+ * Obtains an instance of pattern converter.
+ * @param options options, may be null.
+ * @return instance of pattern converter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+
+ void format(const log4cxx::helpers::ObjectPtr& obj,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+
+}
+}
+#endif
+
diff --git a/src/main/include/log4cxx/pattern/literalpatternconverter.h b/src/main/include/log4cxx/pattern/literalpatternconverter.h
new file mode 100644
index 0000000..cbcba51
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/literalpatternconverter.h
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_LITERAL_PATTERN_CONVERTER_H
+#define _LOG4CXX_PATTERN_LITERAL_PATTERN_CONVERTER_H
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx {
+ namespace pattern {
+
+/**
+ * Formats a string literal.
+ *
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT LiteralPatternConverter : public LoggingEventPatternConverter {
+ /**
+ * String literal.
+ */
+ const LogString literal;
+
+ /**
+ * Create a new instance.
+ * @param literal string literal.
+ */
+ LiteralPatternConverter(const LogString& literal);
+
+
+public:
+ DECLARE_LOG4CXX_PATTERN(LiteralPatternConverter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(LiteralPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+ END_LOG4CXX_CAST_MAP()
+
+ static PatternConverterPtr newInstance(const LogString& literal);
+
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+
+ void format(const log4cxx::helpers::ObjectPtr& obj,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+
+ }
+}
+#endif
+
diff --git a/src/main/include/log4cxx/pattern/loggerpatternconverter.h b/src/main/include/log4cxx/pattern/loggerpatternconverter.h
new file mode 100644
index 0000000..a7d0093
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/loggerpatternconverter.h
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_LOGGER_PATTERN_CONVERTER_H
+ #define _LOG4CXX_PATTERN_LOGGER_PATTERN_CONVERTER_H
+
+
+#include <log4cxx/pattern/namepatternconverter.h>
+
+namespace log4cxx {
+ namespace pattern {
+
+
+/**
+ * Formats a logger name.
+ *
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT LoggerPatternConverter : public NamePatternConverter {
+
+ /**
+ * Private constructor.
+ * @param options options, may be null.
+ * @param logger logger for diagnostic messages, may be null.
+ */
+ LoggerPatternConverter(const std::vector<LogString>& options);
+
+public:
+ DECLARE_LOG4CXX_PATTERN(LoggerPatternConverter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(LoggerPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(NamePatternConverter)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Obtains an instance of pattern converter.
+ * @param options options, may be null.
+ * @return instance of pattern converter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+
+ }
+}
+
+#endif
+
diff --git a/src/main/include/log4cxx/pattern/loggingeventpatternconverter.h b/src/main/include/log4cxx/pattern/loggingeventpatternconverter.h
new file mode 100644
index 0000000..7118808
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/loggingeventpatternconverter.h
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_LOGGING_EVENT_PATTERN_CONVERTER_H
+#define _LOG4CXX_PATTERN_LOGGING_EVENT_PATTERN_CONVERTER_H
+
+#include <log4cxx/pattern/patternconverter.h>
+#include <log4cxx/spi/loggingevent.h>
+
+namespace log4cxx {
+
+ namespace pattern {
+ /**
+ * LoggingEventPatternConverter is a base class for pattern converters
+ * that can format information from instances of LoggingEvent.
+ *
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT LoggingEventPatternConverter : public PatternConverter {
+protected:
+ /**
+ * Constructs an instance of LoggingEventPatternConverter.
+ * @param name name of converter.
+ * @param style CSS style for output.
+ */
+ LoggingEventPatternConverter(
+ const LogString& name, const LogString& style);
+
+public:
+DECLARE_LOG4CXX_PATTERN(LoggingEventPatternConverter)
+BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(LoggingEventPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(PatternConverter)
+END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Formats an event into a string buffer.
+ * @param event event to format, may not be null.
+ * @param toAppendTo string buffer to which the formatted event will be appended. May not be null.
+ * @param p pool for memory allocations needing during format.
+ */
+ virtual void format(
+ const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const = 0;
+
+ void format(const log4cxx::helpers::ObjectPtr& obj,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+
+ /**
+ * Normally pattern converters are not meant to handle Exceptions although
+ * few pattern converters might.
+ *
+ * By examining the return values for this method, the containing layout will
+ * determine whether it handles throwables or not.
+
+ * @return true if this PatternConverter handles throwables
+ */
+ virtual bool handlesThrowable() const;
+};
+
+LOG4CXX_PTR_DEF(LoggingEventPatternConverter);
+
+ }
+}
+
+#endif
diff --git a/src/main/include/log4cxx/pattern/messagepatternconverter.h b/src/main/include/log4cxx/pattern/messagepatternconverter.h
new file mode 100644
index 0000000..04cd028
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/messagepatternconverter.h
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_MESSAGE_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_MESSAGE_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx { namespace pattern {
+
+
+/**
+ * Formats the message of an logging event.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT MessagePatternConverter : public LoggingEventPatternConverter {
+
+ /**
+ * Private constructor.
+ */
+ MessagePatternConverter();
+
+public:
+DECLARE_LOG4CXX_PATTERN(MessagePatternConverter)
+BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(MessagePatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Obtains an instance of pattern converter.
+ * @param options options, may be null.
+ * @return instance of pattern converter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+}
+}
+#endif
diff --git a/src/main/include/log4cxx/pattern/methodlocationpatternconverter.h b/src/main/include/log4cxx/pattern/methodlocationpatternconverter.h
new file mode 100644
index 0000000..da710c4
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/methodlocationpatternconverter.h
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_METHOD_LOCATION_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_METHOD_LOCATION_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx { namespace pattern {
+
+
+/**
+ * Return the event's line location information in a StringBuffer.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT MethodLocationPatternConverter
+ : public LoggingEventPatternConverter {
+
+ /**
+ * Private constructor.
+ */
+ MethodLocationPatternConverter();
+
+public:
+DECLARE_LOG4CXX_PATTERN(MethodLocationPatternConverter)
+BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(MethodLocationPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Obtains an instance of MethodLocationPatternConverter.
+ * @param options options, may be null.
+ * @return instance of MethodLocationPatternConverter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+}
+}
+#endif
diff --git a/src/main/include/log4cxx/pattern/nameabbreviator.h b/src/main/include/log4cxx/pattern/nameabbreviator.h
new file mode 100644
index 0000000..8eedaab
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/nameabbreviator.h
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_NAME_ABBREVIATOR
+#define _LOG4CXX_PATTERN_NAME_ABBREVIATOR
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/objectimpl.h>
+
+namespace log4cxx {
+ namespace pattern {
+
+ class NameAbbreviator;
+ LOG4CXX_PTR_DEF(NameAbbreviator);
+
+/**
+ * NameAbbreviator generates abbreviated logger and class names.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT NameAbbreviator : public log4cxx::helpers::ObjectImpl {
+public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(NameAbbreviator)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(NameAbbreviator)
+ END_LOG4CXX_CAST_MAP()
+
+protected:
+ NameAbbreviator();
+
+public:
+ virtual ~NameAbbreviator();
+
+ /**
+ * Gets an abbreviator.
+ *
+ * For example, "%logger{2}" will output only 2 elements of the logger name,
+ * "%logger{1.}" will output only the first character of the non-final elements in the name,
+ * "%logger(1~.2~} will output the first character of the first element, two characters of
+ * the second and subsequent elements and will use a tilde to indicate abbreviated characters.
+ *
+ * @param pattern abbreviation pattern.
+ * @return abbreviator, will not be null.
+ */
+ static NameAbbreviatorPtr getAbbreviator(const LogString& pattern);
+
+ /**
+ * Gets default abbreviator.
+ *
+ * @return default abbreviator.
+ */
+ static NameAbbreviatorPtr getDefaultAbbreviator();
+
+ /**
+ * Abbreviates a name in a StringBuffer.
+ *
+ * @param nameStart starting position of name in buf.
+ * @param buf buffer, may not be null.
+ */
+ virtual void abbreviate(LogString::size_type nameStart, LogString& buf) const = 0;
+
+};
+ }
+}
+#endif
diff --git a/src/main/include/log4cxx/pattern/namepatternconverter.h b/src/main/include/log4cxx/pattern/namepatternconverter.h
new file mode 100644
index 0000000..68c7e56
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/namepatternconverter.h
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_NAMED_PATTERN_CONVERTER_H
+#define _LOG4CXX_PATTERN_NAMED_PATTERN_CONVERTER_H
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+#include <log4cxx/pattern/nameabbreviator.h>
+
+#include <vector>
+
+namespace log4cxx {
+ namespace pattern {
+
+/**
+ *
+ * Base class for other pattern converters which can return only parts of their name.
+ *
+ */
+class LOG4CXX_EXPORT NamePatternConverter : public LoggingEventPatternConverter {
+ /**
+ * Abbreviator.
+ */
+ const NameAbbreviatorPtr abbreviator;
+
+public:
+DECLARE_LOG4CXX_PATTERN(NamePatternConverter)
+BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(NamePatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+END_LOG4CXX_CAST_MAP()
+
+
+protected:
+ /**
+ * Constructor.
+ * @param name name of converter.
+ * @param style style name for associated output.
+ * @param options options, may be null, first element will be interpreted as an abbreviation pattern.
+ */
+ NamePatternConverter(
+ const LogString& name,
+ const LogString& style,
+ const std::vector<LogString>& options);
+
+ /**
+ * Abbreviate name in string buffer.
+ * @param nameStart starting position of name to abbreviate.
+ * @param buf string buffer containing name.
+ */
+ void abbreviate(int nameStart, LogString& buf) const;
+
+private:
+ NameAbbreviatorPtr getAbbreviator(const std::vector<LogString>& options);
+};
+
+ }
+}
+
+#endif
diff --git a/src/main/include/log4cxx/pattern/ndcpatternconverter.h b/src/main/include/log4cxx/pattern/ndcpatternconverter.h
new file mode 100644
index 0000000..a380a62
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/ndcpatternconverter.h
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_NDC_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_NDC_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx { namespace pattern {
+
+
+/**
+ * Return the event's NDC in a StringBuffer.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT NDCPatternConverter : public LoggingEventPatternConverter {
+
+ /**
+ * Private constructor.
+ */
+ NDCPatternConverter();
+
+public:
+DECLARE_LOG4CXX_PATTERN(NDCPatternConverter)
+BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(NDCPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Obtains an instance of NDCPatternConverter.
+ * @param options options, may be null.
+ * @return instance of NDCPatternConverter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+}
+}
+#endif
diff --git a/src/main/include/log4cxx/pattern/patternconverter.h b/src/main/include/log4cxx/pattern/patternconverter.h
new file mode 100644
index 0000000..f5ad142
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/patternconverter.h
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_PATTERN_CONVERTER_H
+#define _LOG4CXX_PATTERN_PATTERN_CONVERTER_H
+
+
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/logstring.h>
+#include <vector>
+
+#ifdef _MSC_VER
+// disable identifier too wide for debugging warning
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#define DECLARE_LOG4CXX_PATTERN(cls) DECLARE_ABSTRACT_LOG4CXX_OBJECT(cls)
+
+namespace log4cxx {
+ namespace pattern {
+
+ typedef std::vector<LogString> OptionsList;
+
+/**
+
+ <p>PatternConverter is an abstract class that provides the
+ formatting functionality that derived classes need.
+
+ <p>Conversion specifiers in a conversion patterns are parsed to
+ individual PatternConverters. Each of which is responsible for
+ converting an object in a converter specific manner.
+
+ */
+class LOG4CXX_EXPORT PatternConverter : public virtual log4cxx::helpers::ObjectImpl {
+
+ /**
+ * Converter name.
+ */
+ const LogString name;
+
+ /**
+ * Converter style name.
+ */
+ const LogString style;
+
+
+protected:
+ /**
+ * Create a new pattern converter.
+ * @param name name for pattern converter.
+ * @param style CSS style for formatted output.
+ */
+ PatternConverter(const LogString& name,
+ const LogString& style);
+
+ virtual ~PatternConverter();
+
+public:
+ DECLARE_LOG4CXX_PATTERN(PatternConverter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(PatternConverter)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Formats an object into a string buffer.
+ * @param obj event to format, may not be null.
+ * @param toAppendTo string buffer to which the formatted event will be appended. May not be null.
+ * @param p pool for any allocations necessary during formatting.
+ */
+ virtual void format(const log4cxx::helpers::ObjectPtr& obj,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const = 0;
+
+ /**
+ * This method returns the name of the conversion pattern.
+ *
+ * The name can be useful to certain Layouts such as HTMLLayout.
+ *
+ * @return the name of the conversion pattern
+ */
+ LogString getName() const;
+
+ /**
+ * This method returns the CSS style class that should be applied to
+ * the LoggingEvent passed as parameter, which can be null.
+ *
+ * This information is currently used only by HTMLLayout.
+ *
+ * @param e null values are accepted
+ * @return the name of the conversion pattern
+ */
+ virtual LogString getStyleClass(const log4cxx::helpers::ObjectPtr& e) const;
+
+protected:
+/**
+* Appends content in the locale code page to a LogString.
+* @param toAppendTo string to which content is appended.
+* @param src content.
+*/
+ static void append(LogString& toAppendTo, const std::string& src);
+};
+
+
+LOG4CXX_PTR_DEF(PatternConverter);
+
+ }
+}
+
+
+#endif
diff --git a/src/main/include/log4cxx/pattern/patternparser.h b/src/main/include/log4cxx/pattern/patternparser.h
new file mode 100644
index 0000000..2a5113a
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/patternparser.h
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPER_PATTERN_CONVERTER_H
+#define _LOG4CXX_HELPER_PATTERN_CONVERTER_H
+
+#if defined(_MSC_VER)
+#pragma warning (push)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+
+#include <map>
+#include <vector>
+#include <log4cxx/helpers/class.h>
+#include <log4cxx/pattern/patternconverter.h>
+#include <log4cxx/pattern/formattinginfo.h>
+
+namespace log4cxx {
+ namespace pattern {
+
+typedef PatternConverterPtr (*PatternConstructor)(const std::vector<LogString>& options);
+typedef std::map<LogString, PatternConstructor> PatternMap;
+
+
+// Contributors: Nelson Minar <(nelson@monkey.org>
+// Igor E. Poteryaev <jah@mail.ru>
+// Reinhard Deschler <reinhard.deschler@web.de>
+
+/**
+ * Most of the work of the {@link log4cxx::PatternLayout PatternLayout} class
+ * is delegated to the PatternParser class.
+ * <p>It is this class that parses conversion patterns and creates
+ * a chained list of {@link PatternConverter PatternConverters}.
+ *
+ *
+*/
+class LOG4CXX_EXPORT PatternParser {
+ /**
+ * Escape character for format specifier.
+ */
+ static const logchar ESCAPE_CHAR;
+
+ enum {
+ LITERAL_STATE = 0,
+ CONVERTER_STATE = 1,
+ DOT_STATE = 3,
+ MIN_STATE = 4,
+ MAX_STATE = 5
+ };
+
+ /**
+ * Private constructor.
+ */
+ PatternParser();
+
+private:
+ /** Extract the converter identifier found at position i.
+ *
+ * After this function returns, the variable i will point to the
+ * first char after the end of the converter identifier.
+ *
+ * If i points to a char which is not a character acceptable at the
+ * start of a unicode identifier, the value null is returned.
+ *
+ * @param lastChar last processed character.
+ * @param pattern format string.
+ * @param i current index into pattern format.
+ * @param convBuf buffer to receive conversion specifier.
+ * @param currentLiteral literal to be output in case format specifier in unrecognized.
+ * @return position in pattern after converter.
+ */
+ static int extractConverter(
+ logchar lastChar, const LogString& pattern,
+ LogString::size_type i, LogString& convBuf,
+ LogString& currentLiteral);
+
+ /**
+ * Extract options.
+ * @param pattern conversion pattern.
+ * @param i start of options.
+ * @param options array to receive extracted options
+ * @return position in pattern after options.
+ */
+ static int extractOptions(const LogString& pattern, LogString::size_type i,
+ std::vector<LogString>& options);
+
+public:
+ /**
+ * Parse a format specifier.
+ * @param pattern pattern to parse.
+ * @param patternConverters list to receive pattern converters.
+ * @param formattingInfos list to receive field specifiers corresponding to pattern converters.
+ * @param rules map of stock pattern converters keyed by format specifier.
+ */
+ static void parse(
+ const LogString& pattern,
+ std::vector<PatternConverterPtr>& patternConverters,
+ std::vector<FormattingInfoPtr>& formattingInfos,
+ const PatternMap& rules);
+
+private:
+ /**
+ * Creates a new PatternConverter.
+ *
+ *
+ * @param converterId converterId.
+ * @param currentLiteral literal to be used if converter is unrecognized or following converter
+ * if converterId contains extra characters.
+ * @param rules map of stock pattern converters keyed by format specifier.
+ * @param options converter options.
+ * @return converter or null.
+ */
+ static PatternConverterPtr createConverter(
+ const LogString& converterId,
+ LogString& currentLiteral,
+ const PatternMap& rules,
+ std::vector<LogString>& options);
+
+ /**
+ * Processes a format specifier sequence.
+ *
+ * @param c initial character of format specifier.
+ * @param pattern conversion pattern
+ * @param i current position in conversion pattern.
+ * @param currentLiteral current literal.
+ * @param formattingInfo current field specifier.
+ * @param rules map of stock pattern converters keyed by format specifier.
+ * @param patternConverters list to receive parsed pattern converter.
+ * @param formattingInfos list to receive corresponding field specifier.
+ * @return position after format specifier sequence.
+ */
+ static int finalizeConverter(
+ logchar c, const LogString& pattern, int i,
+ LogString& currentLiteral, const FormattingInfoPtr& formattingInfo,
+ const PatternMap& rules,
+ std::vector<PatternConverterPtr>& patternConverters,
+ std::vector<FormattingInfoPtr>& formattingInfos);
+
+ static bool isUnicodeIdentifierStart(logchar c);
+ static bool isUnicodeIdentifierPart(logchar c);
+
+
+};
+
+}
+}
+
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+
+#endif
diff --git a/src/main/include/log4cxx/pattern/propertiespatternconverter.h b/src/main/include/log4cxx/pattern/propertiespatternconverter.h
new file mode 100644
index 0000000..bbe81c1
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/propertiespatternconverter.h
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_PROPERTIES_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_PROPERTIES_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx { namespace pattern {
+
+
+/**
+ * Able to handle the contents of the LoggingEvent's Property bundle and either
+ * output the entire contents of the properties in a similar format to the
+ * java.util.Hashtable.toString(), or to output the value of a specific key
+ * within the property bundle
+ * when this pattern converter has the option set.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT PropertiesPatternConverter
+ : public LoggingEventPatternConverter {
+ /**
+ * Name of property to output.
+ */
+ const LogString option;
+
+ /**
+ * Private constructor.
+ * @param options options, may be null.
+ * @param logger logger for diagnostic messages, may be null.
+ */
+ PropertiesPatternConverter(const LogString& name, const LogString& option);
+
+ public:
+ DECLARE_LOG4CXX_PATTERN(PropertiesPatternConverter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(PropertiesPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Obtains an instance of PropertiesPatternConverter.
+ * @param options options, may be null or first element contains name of property to format.
+ * @return instance of PropertiesPatternConverter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+}
+}
+#endif
+
diff --git a/src/main/include/log4cxx/pattern/relativetimepatternconverter.h b/src/main/include/log4cxx/pattern/relativetimepatternconverter.h
new file mode 100644
index 0000000..326b501
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/relativetimepatternconverter.h
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_RELATIVE_TIME_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_RELATIVE_TIME_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx { namespace pattern {
+
+
+/**
+ * Format the relative time in milliseconds.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT RelativeTimePatternConverter : public LoggingEventPatternConverter {
+public:
+DECLARE_LOG4CXX_PATTERN(RelativeTimePatternConverter)
+BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(RelativeTimePatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Private constructor.
+ */
+ RelativeTimePatternConverter();
+
+ /**
+ * Obtains an instance of RelativeTimePatternConverter.
+ * @param options options, currently ignored, may be null.
+ * @return instance of RelativeTimePatternConverter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+}
+}
+#endif
diff --git a/src/main/include/log4cxx/pattern/threadpatternconverter.h b/src/main/include/log4cxx/pattern/threadpatternconverter.h
new file mode 100644
index 0000000..f0baff9
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/threadpatternconverter.h
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_THREAD_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_THREAD_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx { namespace pattern {
+
+
+/**
+ * Formats the event thread name.
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT ThreadPatternConverter : public LoggingEventPatternConverter {
+ /**
+ * Private constructor.
+ */
+ ThreadPatternConverter();
+
+public:
+DECLARE_LOG4CXX_PATTERN(ThreadPatternConverter)
+BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(ThreadPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Obtains an instance of ThreadPatternConverter.
+ * @param options options, currently ignored, may be null.
+ * @return instance of ThreadPatternConverter.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+};
+}
+}
+#endif
+
diff --git a/src/main/include/log4cxx/pattern/throwableinformationpatternconverter.h b/src/main/include/log4cxx/pattern/throwableinformationpatternconverter.h
new file mode 100644
index 0000000..aa8e523
--- /dev/null
+++ b/src/main/include/log4cxx/pattern/throwableinformationpatternconverter.h
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_THROWABLE_INFORMATION_PATTERN_CONVERTER
+#define _LOG4CXX_PATTERN_THROWABLE_INFORMATION_PATTERN_CONVERTER
+
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+
+namespace log4cxx { namespace pattern {
+
+
+/**
+ * Outputs the ThrowableInformation portion of the LoggingiEvent as a full stacktrace
+ * unless this converter's option is 'short', where it just outputs the first line of the trace.
+ *
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT ThrowableInformationPatternConverter
+ : public LoggingEventPatternConverter {
+ /**
+ * If "short", only first line of throwable report will be formatted.
+ */
+ const bool shortReport;
+
+ /**
+ * Private constructor.
+ */
+ ThrowableInformationPatternConverter(bool shortReport);
+
+public:
+DECLARE_LOG4CXX_PATTERN(ThrowableInformationPatternConverter)
+BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(ThrowableInformationPatternConverter)
+ LOG4CXX_CAST_ENTRY_CHAIN(LoggingEventPatternConverter)
+END_LOG4CXX_CAST_MAP()
+
+
+ /**
+ * Gets an instance of the class.
+ * @param options pattern options, may be null. If first element is "short",
+ * only the first line of the throwable will be formatted.
+ * @return instance of class.
+ */
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+ void format(const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& p) const;
+
+ /**
+ * This converter obviously handles throwables.
+ * @return true.
+ */
+ bool handlesThrowable() const;
+};
+}
+}
+#endif
diff --git a/src/main/include/log4cxx/patternlayout.h b/src/main/include/log4cxx/patternlayout.h
new file mode 100644
index 0000000..55d6eb5
--- /dev/null
+++ b/src/main/include/log4cxx/patternlayout.h
@@ -0,0 +1,409 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PATTERN_LAYOUT_H
+#define _LOG4CXX_PATTERN_LAYOUT_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+
+#include <log4cxx/layout.h>
+#include <log4cxx/pattern/loggingeventpatternconverter.h>
+#include <log4cxx/pattern/formattinginfo.h>
+#include <log4cxx/pattern/patternparser.h>
+
+namespace log4cxx
+{
+
+ /**
+
+ A flexible layout configurable with pattern string.
+
+ <p>The goal of this class is to #format a {@link
+ spi::LoggingEvent LoggingEvent} and return the results as a string.
+ The results depend on the <em>conversion pattern</em>.
+
+ <p>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>.
+
+ <p><i>You are free to insert any literal text within the conversion
+ pattern.</i>
+
+ <p>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, level, date, thread name. The format
+ modifiers control such things as field width, padding, left and
+ right justification. The following is a simple example.
+
+ <p>Let the conversion pattern be <b>"\%-5p [\%t]: \%m\%n"</b> and assume
+ that the log4cxx environment was set to use a PatternLayout. Then the
+ statements
+ <pre>
+ LoggerPtr root = Logger::getRoot();
+ root->debug("Message 1");
+ root->warn("Message 2");
+ </pre>
+ would yield the output
+ <pre>
+ DEBUG [main]: Message 1
+ WARN [main]: Message 2
+ </pre>
+
+ <p>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 level of the logging event should be left
+ justified to a width of five characters.
+
+ The recognized conversion characters are
+
+ <p>
+ <table border="1" CELLPADDING="8">
+ <tr>
+ <td align=center><b>Conversion Character</b></td>
+ <td align=center><b>Effect</b></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.
+
+ <p>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.
+
+ <p>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. The date conversion specifier may be
+ followed by a set of braces containing a
+ date and time pattern string compatible with java.text.SimpleDateFormat,
+ <em>ABSOLUTE</em>, <em>DATE</em> or <em>ISO8601</em>.
+ For example, <b>%d{HH:mm:ss,SSS}</b>,
+ <b>%d{dd&nbsp;MMM&nbsp;yyyy&nbsp;HH:mm:ss,SSS}</b> or
+ <b>%d{DATE}</b>. If no date format specifier is given then
+ ISO8601 format is assumed.
+ </td>
+ </tr>
+
+ <tr>
+ <td align=center><b>F</b></td>
+
+ <td>Used to output the file name where the logging request was
+ issued.
+
+ </tr>
+
+ <tr>
+ <td align=center><b>l</b></td>
+
+ <td>Used to output location information of the caller which generated
+ the logging event.
+
+ </td>
+ </tr>
+
+ <tr>
+ <td align=center><b>L</b></td>
+
+ <td>Used to output the line number from where the logging request
+ was issued.
+ </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.
+
+ <p>This conversion character offers practically the same
+ performance as using non-portable line separator strings such as
+ "\n", or "\r\n". Thus, it is the preferred way of specifying a
+ line separator.
+
+
+ </tr>
+
+ <tr>
+ <td align=center><b>p</b></td>
+ <td>Used to output the level of the logging event.</td>
+ </tr>
+
+ <tr>
+
+ <td align=center><b>r</b></td>
+
+ <td>Used to output the number of milliseconds elapsed since the start
+ of the application until the creation 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>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>X</b></td>
+
+ <td>
+
+ <p>Used to output the MDC (mapped diagnostic context) associated
+ with the thread that generated the logging event. The <b>X</b>
+ conversion character <em>must</em> be followed by the key for the
+ map placed between braces, as in <b>\%X{clientNumber}</b> where
+ <code>clientNumber</code> is the key. The value in the MDC
+ corresponding to the key will be output.</p>
+
+ <p>See MDC class for more details.
+ </p>
+
+ </td>
+ </tr>
+
+ <tr>
+
+ <td align=center><b>\%</b></td>
+
+ <td>The sequence \%\% outputs a single percent sign.
+ </td>
+ </tr>
+
+ </table>
+
+ <p>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.
+
+ <p>The optional format modifier is placed between the percent sign
+ and the conversion character.
+
+ <p>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.
+
+ <p>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.
+
+ <p>Below are various format modifier examples for the logger
+ conversion specifier.
+
+ <p>
+ <TABLE BORDER=1 CELLPADDING=8>
+ <tr>
+ <td align=center><b>Format modifier</b></td>
+ <td align=center><b>left justify</b></td>
+ <td align=center><b>minimum width</b></td>
+ <td align=center><b>maximum width</b></td>
+ <td align=center><b>comment</b></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> <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>
+ <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>
+ <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>
+ <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.
+
+ </table>
+
+ <p>Below are some examples of conversion patterns.
+
+ <p><b>\%r [\%t] \%-5p \%c \%x - \%m\n</b>
+ <p>This is essentially the TTCC layout.
+
+ <p><b>\%-6r [\%15.15t] \%-5p \%30.30c \%x - \%m\n</b>
+
+ <p>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.
+
+ <p>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 LOG4CXX_EXPORT PatternLayout : public Layout
+ {
+ /**
+ * Conversion pattern.
+ */
+ LogString conversionPattern;
+
+ /**
+ * Pattern converters.
+ */
+ LOG4CXX_LIST_DEF(LoggingEventPatternConverterList, log4cxx::pattern::LoggingEventPatternConverterPtr);
+ LoggingEventPatternConverterList patternConverters;
+
+ /**
+ * Field widths and alignment corresponding to pattern converters.
+ */
+ LOG4CXX_LIST_DEF(FormattingInfoList, log4cxx::pattern::FormattingInfoPtr);
+ FormattingInfoList patternFields;
+
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(PatternLayout)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(PatternLayout)
+ LOG4CXX_CAST_ENTRY_CHAIN(Layout)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ Does nothing
+ */
+ PatternLayout();
+
+ /**
+ Constructs a PatternLayout using the supplied conversion pattern.
+ */
+ PatternLayout(const LogString& pattern);
+
+ /**
+ Set the <b>ConversionPattern</b> option. This is the string which
+ controls formatting and consists of a mix of literal content and
+ conversion specifiers.
+ */
+ void setConversionPattern(const LogString& conversionPattern);
+
+ /**
+ Returns the value of the <b>ConversionPattern</b> option.
+ */
+ inline LogString getConversionPattern() const
+ { return conversionPattern; }
+
+ /**
+ Call createPatternParser
+ */
+ virtual void activateOptions(log4cxx::helpers::Pool& p);
+
+ virtual void setOption(const LogString& option, const LogString& value);
+
+ /**
+ The PatternLayout does not handle the throwable contained within
+ {@link spi::LoggingEvent LoggingEvents}. Thus, it returns
+ <code>true</code>.
+ */
+ virtual bool ignoresThrowable() const
+ { return true; }
+
+ /**
+ Produces a formatted string as specified by the conversion pattern.
+ */
+ virtual void format(LogString& output,
+ const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool) const;
+
+ protected:
+ virtual log4cxx::pattern::PatternMap getFormatSpecifiers();
+ };
+ LOG4CXX_PTR_DEF(PatternLayout);
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+#endif //_LOG4CXX_PATTERN_LAYOUT_H
diff --git a/src/main/include/log4cxx/portability.h b/src/main/include/log4cxx/portability.h
new file mode 100644
index 0000000..ea24f5d
--- /dev/null
+++ b/src/main/include/log4cxx/portability.h
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PORTABILITY_H
+#define _LOG4CXX_PORTABILITY_H
+
+//
+// Obsolete file
+//
+
+#endif //_LOG4CXX_PORTABILITY_H
diff --git a/src/main/include/log4cxx/private/Makefile.am b/src/main/include/log4cxx/private/Makefile.am
new file mode 100644
index 0000000..3a896ea
--- /dev/null
+++ b/src/main/include/log4cxx/private/Makefile.am
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+privateincdir = $(includedir)/log4cxx/private
+privateinc_HEADERS= $(top_builddir)/src/main/include/log4cxx/private/*.h log4cxx_private.h
+DISTCLEANFILES = log4cxx_private.h
+EXTRA_DIST = log4cxx_private.hw
+
+dist-hook:
+ -rm -f $(distdir)/log4cxx_private.h
+
diff --git a/src/main/include/log4cxx/private/log4cxx_private.h.in b/src/main/include/log4cxx/private/log4cxx_private.h.in
new file mode 100644
index 0000000..e21f4d8
--- /dev/null
+++ b/src/main/include/log4cxx/private/log4cxx_private.h.in
@@ -0,0 +1,56 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 LOG4CXX_PRIVATE_LOG4CXX_H
+#define LOG4CXX_PRIVATE_LOG4CXX_H
+
+/* GENERATED FILE WARNING! DO NOT EDIT log4cxx_private.h
+ *
+ * You must modify log4cxx_private.h.in instead.
+ *
+ */
+
+#include <log4cxx/log4cxx.h>
+
+#if !defined(LOG4CXX) && !defined(LOG4CXX_TEST)
+#error "log4cxx/private/log4cxx_private.h should only be used within log4cxx implementation or tests"
+#endif
+
+#define LOG4CXX_RETURN_AFTER_THROW 0
+
+#define LOG4CXX_HAS_STD_LOCALE @HAS_STD_LOCALE@
+#define LOG4CXX_FORCE_WIDE_CONSOLE 0
+#define LOG4CXX_FORCE_BYTE_CONSOLE 0
+#define LOG4CXX_MEMSET_IOS_BASE 0
+#define LOG4CXX_HAVE_ODBC @HAS_ODBC@
+#define LOG4CXX_HAS_MBSRTOWCS @HAS_MBSRTOWCS@
+#define LOG4CXX_HAS_WCSTOMBS @HAS_WCSTOMBS@
+#define LOG4CXX_HAS_FWIDE @HAS_FWIDE@
+
+#define LOG4CXX_CHARSET_UTF8 @CHARSET_UTF8@
+#define LOG4CXX_CHARSET_ISO88591 @CHARSET_ISO88591@
+#define LOG4CXX_CHARSET_USASCII @CHARSET_USASCII@
+#define LOG4CXX_CHARSET_EBCDIC @CHARSET_EBCDIC@
+
+#define LOG4CXX_HAVE_LIBESMTP @HAS_LIBESMTP@
+#define LOG4CXX_HAVE_SYSLOG @HAS_SYSLOG@
+
+#define LOG4CXX_WIN32_THREAD_FMTSPEC "0x%.8x"
+#define LOG4CXX_APR_THREAD_FMTSPEC "0x%pt"
+
+
+#endif
diff --git a/src/main/include/log4cxx/private/log4cxx_private.hw b/src/main/include/log4cxx/private/log4cxx_private.hw
new file mode 100644
index 0000000..e7c8417
--- /dev/null
+++ b/src/main/include/log4cxx/private/log4cxx_private.hw
@@ -0,0 +1,84 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 LOG4CXX_PRIVATE_LOG4CXX_H
+#define LOG4CXX_PRIVATE_LOG4CXX_H
+
+
+/* GENERATED FILE WARNING! DO NOT EDIT log4cxx.h
+ *
+ * You must modify log4cxx.hw instead.
+ *
+ *
+ * This is the Win32 specific version of log4cxx.h.
+ */
+
+#include <log4cxx/log4cxx.h>
+
+#if !defined(LOG4CXX) && !defined(LOG4CXX_TEST)
+#error "log4cxx/private/log4cxx.h should only be used within log4cxx and tests implementation"
+#endif
+
+
+#if !defined(__BORLANDC__)
+#define LOG4CXX_RETURN_AFTER_THROW 1
+#else
+#define LOG4CXX_RETURN_AFTER_THROW 0
+#endif
+
+#if defined(_WIN32_WCE)
+#define LOG4CXX_HAS_STD_LOCALE 0
+#else
+#define LOG4CXX_HAS_STD_LOCALE 1
+#endif
+
+#define LOG4CXX_FORCE_WIDE_CONSOLE 1
+#define LOG4CXX_FORCE_BYTE_CONSOLE 0
+
+
+#if defined(_MSC_VER)
+#define LOG4CXX_MEMSET_IOS_BASE 1
+#endif
+
+#if !defined(_WIN32_WCE)
+#define LOG4CXX_HAVE_ODBC 1
+#if defined(__BORLANDC__)
+#define LOG4CXX_HAS_MBSRTOWCS 0
+#else
+#define LOG4CXX_HAS_MBSRTOWCS 1
+#endif
+#else
+#define LOG4CXX_HAVE_ODBC 0
+#define LOG4CXX_HAS_MBSRTOWCS 0
+#endif
+
+#define LOG4CXX_HAS_FWIDE 1
+#define LOG4CXX_HAS_WCSTOMBS 1
+
+#define LOG4CXX_CHARSET_UTF8 0
+#define LOG4CXX_CHARSET_ISO88591 0
+#define LOG4CXX_CHARSET_USASCII 0
+#define LOG4CXX_CHARSET_EBCDIC 0
+
+
+#define LOG4CXX_HAVE_LIBESMTP 0
+#define LOG4CXX_HAVE_SYSLOG 0
+
+#define LOG4CXX_WIN32_THREAD_FMTSPEC "0x%.8x"
+#define LOG4CXX_APR_THREAD_FMTSPEC "0x%pt"
+
+#endif
diff --git a/src/main/include/log4cxx/propertyconfigurator.h b/src/main/include/log4cxx/propertyconfigurator.h
new file mode 100644
index 0000000..0271e2d
--- /dev/null
+++ b/src/main/include/log4cxx/propertyconfigurator.h
@@ -0,0 +1,395 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PROPERTY_CONFIGURATOR_H
+#define _LOG4CXX_PROPERTY_CONFIGURATOR_H
+
+#if defined(_MSC_VER)
+#pragma warning (push)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/logstring.h>
+#include <log4cxx/spi/configurator.h>
+#include <map>
+
+#include <log4cxx/file.h>
+
+namespace log4cxx
+{
+ class Logger;
+ typedef helpers::ObjectPtrT<Logger> LoggerPtr;
+
+ class Appender;
+ typedef helpers::ObjectPtrT<Appender> AppenderPtr;
+
+ namespace helpers
+ {
+ class Properties;
+ }
+
+
+ namespace spi {
+ class LoggerFactory;
+ }
+
+/**
+Allows the configuration of log4cxx from an external file. See
+<b>{@link #doConfigure(const File&, log4cxx::spi::LoggerRepositoryPtr&)}</b>
+for the expected format.
+
+<p>It is sometimes useful to see how log4cxx is reading configuration
+files. You can enable log4cxx internal logging by defining the
+<b>log4j.debug</b> variable.
+
+<P>At class initialization time class,
+the file <b>log4j.properties</b> will be searched in the current directory.
+If the file can be found, then it will
+be fed to the
+{@link PropertyConfigurator#configure(const File& configFilename)}
+method.
+
+<p>The <code>PropertyConfigurator</code> does not handle the
+advanced configuration features supported by the {@link
+xml::DOMConfigurator DOMConfigurator} such as
+support for {@link spi::Filter Filters}, custom
+{@link spi::ErrorHandler ErrorHandlers}, nested
+appenders such as the {@link AsyncAppender
+AsyncAppender}, etc.
+
+<p>All option <em>values</em> admit variable substitution. 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. The value of
+the substituted variable can be defined as a system property or in
+the configuration file itself. The value of the key is first
+searched in the system properties, and if not found there, it is
+then searched in the configuration file being parsed. The
+corresponding value replaces the ${variableName} sequence. For
+example, if <code>java.home</code> system property is set to
+<code>/home/xyz</code>, then every occurrence of the sequence
+<code>${java.home}</code> will be interpreted as
+<code>/home/xyz</code>.
+*/
+ class LOG4CXX_EXPORT PropertyConfigurator :
+ virtual public spi::Configurator,
+ virtual public helpers::ObjectImpl
+ {
+ protected:
+
+ /**
+ Used internally to keep track of configured appenders.
+ */
+ std::map<LogString, AppenderPtr>* registry;
+
+ /**
+ Used to create new instances of logger
+ */
+ helpers::ObjectPtrT<spi::LoggerFactory> loggerFactory;
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(PropertyConfigurator)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(spi::Configurator)
+ END_LOG4CXX_CAST_MAP()
+
+ PropertyConfigurator();
+ virtual ~PropertyConfigurator();
+ void addRef() const;
+ void releaseRef() const;
+
+/**
+Read configuration from a file. <b>The existing configuration is
+not cleared nor reset.</b> If you require a different behavior,
+then call {@link LogManager#resetConfiguration
+resetConfiguration} method before calling
+<code>doConfigure</code>.
+
+<p>The configuration file consists of statements in the format
+<code>key=value</code>. The syntax of different configuration
+elements are discussed below.
+
+<h3>Repository-wide threshold</h3>
+
+<p>The repository-wide threshold filters logging requests by level
+regardless of logger. The syntax is:
+
+<pre>
+log4j.threshold=[level]
+</pre>
+
+<p>The level value can consist of the string values OFF, FATAL,
+ERROR, WARN, INFO, DEBUG, ALL or a <em>custom level</em> value. A
+custom level value can be specified in the form
+level#classname. By default the repository-wide threshold is set
+to the lowest possible value, namely the level <code>ALL</code>.
+</p>
+
+
+<h3>Appender configuration</h3>
+
+<p>Appender configuration syntax is:
+<pre>
+# For appender named <i>appenderName</i>, set its class.
+# Note: The appender name can contain dots.
+log4j.appender.appenderName=fully.qualified.name.of.appender.class
+
+# Set appender specific options.
+log4j.appender.appenderName.option1=value1
+...
+log4j.appender.appenderName.optionN=valueN
+</pre>
+
+For each named appender you can configure its {@link Layout Layout}. The
+syntax for configuring an appender's layout is:
+<pre>
+log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class
+log4j.appender.appenderName.layout.option1=value1
+....
+log4j.appender.appenderName.layout.optionN=valueN
+</pre>
+
+<h3>Configuring loggers</h3>
+
+<p>The syntax for configuring the root logger is:
+<pre>
+log4j.rootLogger=[level], appenderName, appenderName, ...
+</pre>
+
+<p>This syntax means that an optional <em>level</em> can be
+supplied followed by appender names separated by commas.
+
+<p>The level value can consist of the string values OFF, FATAL,
+ERROR, WARN, INFO, DEBUG, ALL or a <em>custom level</em> value. A
+custom level value can be specified in the form
+<code>level#classname</code>.
+
+<p>If a level value is specified, then the root level is set
+to the corresponding level. If no level value is specified,
+then the root level remains untouched.
+
+<p>The root logger can be assigned multiple appenders.
+
+<p>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.
+
+<p>For non-root categories the syntax is almost the same:
+<pre>
+log4j.logger.logger_name=[level|INHERITED|NULL], appenderName, appenderName,
+...
+</pre>
+
+<p>The meaning of the optional level 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 level from the logger hierarchy.
+
+<p>If no level value is supplied, then the level of the
+named logger remains untouched.
+
+<p>By default categories inherit their level from the
+hierarchy. However, if you set the level of a logger and later
+decide that that logger should inherit its level, then you should
+specify INHERITED as the value for the level value. NULL is a
+synonym for INHERITED.
+
+<p>Similar to the root logger syntax, each <i>appenderName</i>
+(separated by commas) will be attached to the named logger.
+
+<p>See the <a href="Introduction.html#additivity">appender
+additivity rule</a> in the user manual for the meaning of the
+<code>additivity</code> flag.
+
+<h3>Logger Factories</h3>
+
+The usage of custom logger factories is discouraged and no longer
+documented.
+
+<h3>Example</h3>
+
+<p>An example configuration is given below. Other configuration
+file examples are given in the <code>examples</code> folder.
+
+<pre>
+
+# Set options for appender named "A1".
+# Appender "A1" will be a SyslogAppender
+log4j.appender.A1=SyslogAppender
+
+# The syslog daemon resides on www.abc.net
+log4j.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 level 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 PatternLayout for further information
+# on the syntax of the ConversionPattern key.
+log4j.appender.A1.layout=PatternLayout
+log4j.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.
+log4j.appender.A2=RollingFileAppender
+log4j.appender.A2.MaxFileSize=10MB
+log4j.appender.A2.MaxBackupIndex=1
+log4j.appender.A2.layout=TTCCLayout
+log4j.appender.A2.layout.ContextPrinting=enabled
+log4j.appender.A2.layout.DateFormat=ISO8601
+
+# Root logger set to DEBUG using the A2 appender defined above.
+log4j.rootLogger=DEBUG, A2
+
+# Logger definitions:
+# The SECURITY logger inherits is level from root. However, it's output
+# will go to A1 appender defined above. It's additivity is non-cumulative.
+log4j.logger.SECURITY=INHERIT, A1
+log4j.additivity.SECURITY=false
+
+# Only warnings or above will be logged for the logger "SECURITY.access".
+# Output will go to A1.
+log4j.logger.SECURITY.access=WARN
+
+
+# The logger "class.of.the.day" inherits its level from the
+# logger hierarchy. Output will go to the appender's of the root
+# logger, A2 in this case.
+log4j.logger.class.of.the.day=INHERIT
+</pre>
+
+<p>Refer to the <b>setOption</b> method in each Appender and
+Layout for class specific options.
+
+<p>Use the <code>#</code> or <code>!</code> characters at the
+beginning of a line for comments.
+
+<p>
+@param configFileName The name of the configuration file where the
+configuration information is stored.
+@param hierarchy The hierarchy to operation upon.
+*/
+ void doConfigure(const File& configFileName,
+ spi::LoggerRepositoryPtr& hierarchy);
+
+ /**
+ Read configuration options from file <code>configFilename</code>.
+ */
+ static void configure(const File& configFilename);
+
+ /**
+ Like {@link #configureAndWatch(const File& configFilename, long delay)}
+ except that the
+ default delay as defined by helpers::FileWatchdog#DEFAULT_DELAY
+ is used.
+ @param configFilename A file in key=value format.
+ */
+ static void configureAndWatch(const File& configFilename);
+
+ /**
+ Read the configuration file <code>configFilename</code> if it
+ exists. Moreover, a thread will be created that will periodically
+ check if <code>configFilename</code> has been created or
+ modified. The period is determined by the <code>delay</code>
+ argument. If a change or file creation is detected, then
+ <code>configFilename</code> is read to configure log4j.
+
+ @param configFilename A file in key=value format.
+ @param delay The delay in milliseconds to wait between each check.
+ */
+ static void configureAndWatch(const File& configFilename,
+ long delay);
+
+ /**
+ Read configuration options from <code>properties</code>.
+ See #doConfigure(const File&, log4cxx::spi::LoggerRepositoryPtr&)
+ for the expected format.
+ */
+ static void configure(helpers::Properties& properties);
+
+ /**
+ Read configuration options from <code>properties</code>.
+ See #doConfigure(const File&, log4cxx::spi::LoggerRepositoryPtr&)
+ for the expected format.
+ */
+ void doConfigure(helpers::Properties& properties,
+ spi::LoggerRepositoryPtr& hierarchy);
+
+// --------------------------------------------------------------------------
+// Internal stuff
+// --------------------------------------------------------------------------
+protected:
+ /**
+ Check the provided <code>Properties</code> object for a
+ #loggerFactory
+ entry specified by LOGGER_FACTORY_KEY. If such an entry
+ exists, an attempt is made to create an instance using the default
+ constructor. This instance is used for subsequent Logger creations
+ within this configurator.
+ @see #parseCatsAndRenderers
+ */
+ void configureLoggerFactory(helpers::Properties& props);
+
+ void configureRootLogger(helpers::Properties& props,
+ spi::LoggerRepositoryPtr& hierarchy);
+
+ /**
+ Parse non-root elements, such non-root categories and renderers.
+ */
+ void parseCatsAndRenderers(helpers::Properties& props,
+ spi::LoggerRepositoryPtr& hierarchy);
+
+ /**
+ Parse the additivity option for a non-root logger.
+ */
+ void parseAdditivityForLogger(helpers::Properties& props,
+ LoggerPtr& cat, const LogString& loggerName);
+
+ /**
+ This method must work for the root logger as well.
+ */
+ void parseLogger(
+ helpers::Properties& props, LoggerPtr& logger,
+ const LogString& optionKey, const LogString& loggerName,
+ const LogString& value);
+
+ AppenderPtr parseAppender(
+ helpers::Properties& props, const LogString& appenderName);
+
+ void registryPut(const AppenderPtr& appender);
+ AppenderPtr registryGet(const LogString& name);
+
+private:
+ PropertyConfigurator(const PropertyConfigurator&);
+ PropertyConfigurator& operator=(const PropertyConfigurator&);
+ }; // class PropertyConfigurator
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+
+#endif //_LOG4CXX_PROPERTY_CONFIGURATOR_H
diff --git a/src/main/include/log4cxx/provisionnode.h b/src/main/include/log4cxx/provisionnode.h
new file mode 100644
index 0000000..5d1c31f
--- /dev/null
+++ b/src/main/include/log4cxx/provisionnode.h
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_PROVISION_NODE_H
+#define _LOG4CXX_PROVISION_NODE_H
+
+#include <vector>
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/logger.h>
+
+namespace log4cxx
+{
+ class Logger;
+ typedef helpers::ObjectPtrT<Logger> LoggerPtr;
+
+
+ typedef std::vector<LoggerPtr> ProvisionNode;
+
+} // namespace log4cxx
+
+#endif //_LOG4CXX_PROVISION_NODE_H
diff --git a/src/main/include/log4cxx/rolling/Makefile.am b/src/main/include/log4cxx/rolling/Makefile.am
new file mode 100755
index 0000000..8b10b18
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/Makefile.am
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+rollingincdir = $(includedir)/log4cxx/rolling
+rollinginc_HEADERS= $(top_srcdir)/src/main/include/log4cxx/rolling/*.h
+
diff --git a/src/main/include/log4cxx/rolling/action.h b/src/main/include/log4cxx/rolling/action.h
new file mode 100644
index 0000000..00595ff
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/action.h
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_ROLLING_ACTION_H)
+#define _LOG4CXX_ROLLING_ACTION_H
+
+#include <log4cxx/portability.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/helpers/mutex.h>
+#include <log4cxx/helpers/pool.h>
+
+namespace log4cxx {
+ namespace rolling {
+
+
+ /**
+ * A file system action performed as part of a rollover event.
+ */
+ class Action : public virtual log4cxx::helpers::ObjectImpl {
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(Action)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(Action)
+ END_LOG4CXX_CAST_MAP()
+ /**
+ * Is action complete.
+ */
+ bool complete;
+
+ /**
+ * Is action interrupted.
+ */
+ bool interrupted;
+
+ log4cxx::helpers::Pool pool;
+ log4cxx::helpers::Mutex mutex;
+
+
+ protected:
+ /**
+ * Constructor.
+ */
+ Action();
+ virtual ~Action();
+
+ public:
+ /**
+ * Perform action.
+ *
+ * @return true if successful.
+ */
+ virtual bool execute(log4cxx::helpers::Pool& pool) const = 0;
+
+ void run(log4cxx::helpers::Pool& pool);
+
+ void close();
+
+ /**
+ * Tests if the action is complete.
+ * @return true if action is complete.
+ */
+ bool isComplete() const;
+
+ void reportException(const std::exception&);
+
+
+ };
+
+ LOG4CXX_PTR_DEF(Action);
+
+ }
+}
+#endif
+
diff --git a/src/main/include/log4cxx/rolling/filerenameaction.h b/src/main/include/log4cxx/rolling/filerenameaction.h
new file mode 100644
index 0000000..46a284a
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/filerenameaction.h
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_ROLLING_FILE_RENAME_ACTION_H)
+#define _LOG4CXX_ROLLING_FILE_RENAME_ACTION_H
+
+#include <log4cxx/rolling/action.h>
+#include <log4cxx/file.h>
+
+namespace log4cxx {
+ namespace rolling {
+
+
+ class FileRenameAction : public Action {
+ const File source;
+ const File destination;
+ bool renameEmptyFile;
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(FileRenameAction)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(FileRenameAction)
+ LOG4CXX_CAST_ENTRY_CHAIN(Action)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Constructor.
+ */
+ FileRenameAction(const File& toRename,
+ const File& renameTo,
+ bool renameEmptyFile);
+
+ /**
+ * Perform action.
+ *
+ * @return true if successful.
+ */
+ virtual bool execute(log4cxx::helpers::Pool& pool) const;
+ };
+
+ LOG4CXX_PTR_DEF(FileRenameAction);
+
+ }
+}
+#endif
+
diff --git a/src/main/include/log4cxx/rolling/filterbasedtriggeringpolicy.h b/src/main/include/log4cxx/rolling/filterbasedtriggeringpolicy.h
new file mode 100644
index 0000000..efe5825
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/filterbasedtriggeringpolicy.h
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ #if !defined(_LOG4CXX_ROLLING_FILTER_BASED_TRIGGERING_POLICY_H)
+ #define _LOG4CXX_ROLLING_FILTER_BASED_TRIGGERING_POLICY_H
+
+#include <log4cxx/rolling/triggeringpolicy.h>
+#include <log4cxx/spi/filter.h>
+
+ namespace log4cxx {
+
+ class File;
+
+ namespace helpers {
+ class Pool;
+ }
+
+
+ namespace rolling {
+
+
+/**
+ * FilterBasedTriggeringPolicy determines if rolling should be triggered
+ * by evaluating the current message against a set of filters. Unless a
+ * filter rejects a message, a rolling event will be triggered.
+ *
+ *
+ *
+ *
+ */
+class LOG4CXX_EXPORT FilterBasedTriggeringPolicy : public TriggeringPolicy {
+
+ DECLARE_LOG4CXX_OBJECT(FilterBasedTriggeringPolicy)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(FilterBasedTriggeringPolicy)
+ LOG4CXX_CAST_ENTRY_CHAIN(TriggeringPolicy)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * The first filter in the filter chain. Set to <code>null</code> initially.
+ */
+ log4cxx::spi::FilterPtr headFilter;
+
+ /**
+ * The last filter in the filter chain.
+ */
+ log4cxx::spi::FilterPtr tailFilter;
+
+public:
+ /**
+ * Creates a new FilterBasedTriggeringPolicy.
+ */
+ FilterBasedTriggeringPolicy();
+ virtual ~FilterBasedTriggeringPolicy();
+
+/**
+ * Determines if a rollover may be appropriate at this time. If
+ * true is returned, RolloverPolicy.rollover will be called but it
+ * can determine that a rollover is not warranted.
+ *
+ * @param appender A reference to the appender.
+ * @param event A reference to the currently event.
+ * @param filename The filename for the currently active log file.
+ * @param fileLength Length of the file in bytes.
+ * @return true if a rollover should occur.
+ */
+virtual bool isTriggeringEvent(
+ Appender* appender,
+ const log4cxx::spi::LoggingEventPtr& event,
+ const LogString& filename,
+ size_t fileLength);
+
+ /**
+ * Add a filter to end of the filter list.
+ * @param newFilter filter to add to end of list.
+ */
+ void addFilter(const log4cxx::spi::FilterPtr& newFilter);
+
+ /**
+ * Clear the filters chain.
+ *
+ */
+ void clearFilters();
+
+ /**
+ * Returns the head Filter.
+ *
+ */
+ log4cxx::spi::FilterPtr& getFilter();
+
+ /**
+ * Prepares the instance for use.
+ */
+ void activateOptions(log4cxx::helpers::Pool&);
+
+ void setOption(const LogString& option, const LogString& value);
+ };
+
+ LOG4CXX_PTR_DEF(FilterBasedTriggeringPolicy);
+
+}
+ }
+
+#endif
diff --git a/src/main/include/log4cxx/rolling/fixedwindowrollingpolicy.h b/src/main/include/log4cxx/rolling/fixedwindowrollingpolicy.h
new file mode 100755
index 0000000..1cb6b48
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/fixedwindowrollingpolicy.h
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_ROLLING_FIXED_WINDOW_ROLLING_POLICY_H)
+#define _LOG4CXX_ROLLING_FIXED_WINDOW_ROLLING_POLICY_H
+
+#include <log4cxx/rolling/rollingpolicybase.h>
+
+
+
+
+namespace log4cxx {
+
+ namespace helpers {
+ class Pool;
+ }
+
+ namespace rolling {
+
+
+/**
+ * When rolling over, <code>FixedWindowRollingPolicy</code> renames files
+ * according to a fixed window algorithm as described below.
+ *
+ * <p>The <b>ActiveFileName</b> property, which is required, represents the name
+ * of the file where current logging output will be written.
+ * The <b>FileNamePattern</b> option represents the file name pattern for the
+ * archived (rolled over) log files. If present, the <b>FileNamePattern</b>
+ * option must include an integer token, that is the string "%i" somwhere
+ * within the pattern.
+ *
+ * <p>Let <em>max</em> and <em>min</em> represent the values of respectively
+ * the <b>MaxIndex</b> and <b>MinIndex</b> options. Let "foo.log" be the value
+ * of the <b>ActiveFile</b> option and "foo.%i.log" the value of
+ * <b>FileNamePattern</b>. Then, when rolling over, the file
+ * <code>foo.<em>max</em>.log</code> will be deleted, the file
+ * <code>foo.<em>max-1</em>.log</code> will be renamed as
+ * <code>foo.<em>max</em>.log</code>, the file <code>foo.<em>max-2</em>.log</code>
+ * renamed as <code>foo.<em>max-1</em>.log</code>, and so on,
+ * the file <code>foo.<em>min+1</em>.log</code> renamed as
+ * <code>foo.<em>min+2</em>.log</code>. Lastly, the active file <code>foo.log</code>
+ * will be renamed as <code>foo.<em>min</em>.log</code> and a new active file name
+ * <code>foo.log</code> will be created.
+ *
+ * <p>Given that this rollover algorithm requires as many file renaming
+ * operations as the window size, large window sizes are discouraged. The
+ * current implementation will automatically reduce the window size to 12 when
+ * larger values are specified by the user.
+ *
+ *
+ *
+ *
+ * */
+ class LOG4CXX_EXPORT FixedWindowRollingPolicy : public RollingPolicyBase {
+ DECLARE_LOG4CXX_OBJECT(FixedWindowRollingPolicy)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(FixedWindowRollingPolicy)
+ LOG4CXX_CAST_ENTRY_CHAIN(RollingPolicyBase)
+ END_LOG4CXX_CAST_MAP()
+
+ int minIndex;
+ int maxIndex;
+ bool explicitActiveFile;
+
+ /**
+ * It's almost always a bad idea to have a large window size, say over 12.
+ */
+ enum { MAX_WINDOW_SIZE = 12 };
+
+ bool purge(int purgeStart, int maxIndex, log4cxx::helpers::Pool& p) const;
+
+ public:
+
+ FixedWindowRollingPolicy();
+
+ void activateOptions(log4cxx::helpers::Pool& p);
+ void setOption(const LogString& option,
+ const LogString& value);
+
+ void rollover();
+
+ int getMaxIndex() const;
+
+ int getMinIndex() const;
+
+ void setMaxIndex(int newVal);
+ void setMinIndex(int newVal);
+
+
+/**
+* Initialize the policy and return any initial actions for rolling file appender.
+*
+* @param file current value of RollingFileAppender::getFile().
+* @param append current value of RollingFileAppender::getAppend().
+* @param p pool used for any required memory allocations.
+* @return Description of the initialization, may be null to indicate
+* no initialization needed.
+* @throws SecurityException if denied access to log files.
+*/
+virtual RolloverDescriptionPtr initialize(
+const LogString& file, const bool append, log4cxx::helpers::Pool& p);
+
+/**
+* Prepare for a rollover. This method is called prior to
+* closing the active log file, performs any necessary
+* preliminary actions and describes actions needed
+* after close of current log file.
+*
+* @param activeFile file name for current active log file.
+* @param p pool used for any required memory allocations.
+* @return Description of pending rollover, may be null to indicate no rollover
+* at this time.
+* @throws SecurityException if denied access to log files.
+*/
+virtual RolloverDescriptionPtr rollover(const LogString& activeFile, log4cxx::helpers::Pool& p);
+
+protected:
+ log4cxx::pattern::PatternMap getFormatSpecifiers() const;
+
+ };
+
+ LOG4CXX_PTR_DEF(FixedWindowRollingPolicy);
+
+ }
+}
+
+#endif
diff --git a/src/main/include/log4cxx/rolling/gzcompressaction.h b/src/main/include/log4cxx/rolling/gzcompressaction.h
new file mode 100644
index 0000000..d94d4e8
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/gzcompressaction.h
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_ROLLING_GZ_COMPRESS_ACTION_H)
+#define _LOG4CXX_ROLLING_GZ_COMPRESS_ACTION_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/rolling/action.h>
+#include <log4cxx/file.h>
+
+namespace log4cxx {
+ namespace rolling {
+
+
+ class GZCompressAction : public Action {
+ const File source;
+ const File destination;
+ bool deleteSource;
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(GZCompressAction)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(GZCompressAction)
+ LOG4CXX_CAST_ENTRY_CHAIN(Action)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Constructor.
+ */
+ GZCompressAction(const File& source,
+ const File& destination,
+ bool deleteSource);
+
+ /**
+ * Perform action.
+ *
+ * @return true if successful.
+ */
+ virtual bool execute(log4cxx::helpers::Pool& pool) const;
+
+ private:
+ GZCompressAction(const GZCompressAction&);
+ GZCompressAction& operator=(const GZCompressAction&);
+ };
+
+ LOG4CXX_PTR_DEF(GZCompressAction);
+
+ }
+}
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif
+
diff --git a/src/main/include/log4cxx/rolling/manualtriggeringpolicy.h b/src/main/include/log4cxx/rolling/manualtriggeringpolicy.h
new file mode 100644
index 0000000..5461183
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/manualtriggeringpolicy.h
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_ROLLING_MANUAL_TRIGGERING_POLICY_H)
+#define _LOG4CXX_ROLLING_MANUAL_TRIGGERING_POLICY_H
+
+#include <log4cxx/rolling/triggeringpolicy.h>
+
+namespace log4cxx {
+
+ class File;
+
+ namespace helpers {
+ class Pool;
+ }
+
+ namespace rolling {
+
+ /**
+ * ManualTriggeringPolicy only rolls over on explicit calls to
+ * RollingFileAppender.rollover().
+ *
+ *
+ *
+ */
+ class LOG4CXX_EXPORT ManualTriggeringPolicy : public TriggeringPolicy {
+ DECLARE_LOG4CXX_OBJECT(ManualTriggeringPolicy)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(ManualTriggeringPolicy)
+ LOG4CXX_CAST_ENTRY_CHAIN(TriggeringPolicy)
+ END_LOG4CXX_CAST_MAP()
+
+ public:
+ ManualTriggeringPolicy();
+ /**
+ * Determines if a rollover may be appropriate at this time. If
+ * true is returned, RolloverPolicy.rollover will be called but it
+ * can determine that a rollover is not warranted.
+ *
+ * @param appender A reference to the appender.
+ * @param event A reference to the currently event.
+ * @param filename The filename for the currently active log file.
+ * @param fileLength Length of the file in bytes.
+ * @return true if a rollover should occur.
+ */
+ virtual bool isTriggeringEvent(
+ Appender* appender,
+ const log4cxx::spi::LoggingEventPtr& event,
+ const LogString& filename,
+ size_t fileLength);
+
+ void activateOptions(log4cxx::helpers::Pool&);
+ void setOption(const LogString& option, const LogString& value);
+ };
+ }
+}
+#endif
+
diff --git a/src/main/include/log4cxx/rolling/rollingfileappender.h b/src/main/include/log4cxx/rolling/rollingfileappender.h
new file mode 100755
index 0000000..ec044fb
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/rollingfileappender.h
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_ROLLING_ROLLING_FILE_APPENDER_H)
+#define _LOG4CXX_ROLLING_ROLLING_FILE_APPENDER_H
+
+#include <log4cxx/rolling/rollingfileappenderskeleton.h>
+
+
+namespace log4cxx {
+ namespace rolling {
+
+
+ /**
+ * <code>RollingFileAppender</code> extends {@link log4cxx::FileAppender} to backup the log files
+ * depending on {@link log4cxx::rolling::RollingPolicy RollingPolicy} and {@link log4cxx::rolling::TriggeringPolicy TriggeringPolicy}.
+ * <p>
+ * To be of any use, a <code>RollingFileAppender</code> instance must have both
+ * a <code>RollingPolicy</code> and a <code>TriggeringPolicy</code> set up.
+ * However, if its <code>RollingPolicy</code> also implements the
+ * <code>TriggeringPolicy</code> interface, then only the former needs to be
+ * set up. For example, {@link log4cxx::rolling::TimeBasedRollingPolicy TimeBasedRollingPolicy} acts both as a
+ * <code>RollingPolicy</code> and a <code>TriggeringPolicy</code>.
+ *
+ * <p><code>RollingFileAppender</code> can be configured programattically or
+ * using {@link log4cxx::xml::DOMConfigurator}. Here is a sample
+ * configration file:
+
+ <pre>&lt;?xml version="1.0" encoding="UTF-8" ?>
+ &lt;!DOCTYPE log4j:configuration>
+
+ &lt;log4j:configuration debug="true">
+
+ &lt;appender name="ROLL" class="org.apache.log4j.rolling.RollingFileAppender">
+ <b>&lt;rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
+ &lt;param name="FileNamePattern" value="/wombat/foo.%d{yyyy-MM}.gz"/>
+ &lt;/rollingPolicy></b>
+
+ &lt;layout class="org.apache.log4j.PatternLayout">
+ &lt;param name="ConversionPattern" value="%c{1} - %m%n"/>
+ &lt;/layout>
+ &lt;/appender>
+
+ &lt;root">
+ &lt;appender-ref ref="ROLL"/>
+ &lt;/root>
+
+ &lt;/log4j:configuration>
+ </pre>
+
+ *<p>This configuration file specifies a monthly rollover schedule including
+ * automatic compression of the archived files. See
+ * {@link TimeBasedRollingPolicy} for more details.
+ *
+ *
+ *
+ *
+ * */
+ class LOG4CXX_EXPORT RollingFileAppender : public RollingFileAppenderSkeleton {
+ DECLARE_LOG4CXX_OBJECT(RollingFileAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(RollingFileAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(RollingFileAppenderSkeleton)
+ END_LOG4CXX_CAST_MAP()
+
+ public:
+ RollingFileAppender();
+
+ using RollingFileAppenderSkeleton::getRollingPolicy;
+
+ using RollingFileAppenderSkeleton::getTriggeringPolicy;
+
+ /**
+ * Sets the rolling policy. In case the 'policy' argument also implements
+ * {@link TriggeringPolicy}, then the triggering policy for this appender
+ * is automatically set to be the policy argument.
+ * @param policy
+ */
+ using RollingFileAppenderSkeleton::setRollingPolicy;
+
+ using RollingFileAppenderSkeleton::setTriggeringPolicy;
+
+ };
+
+ LOG4CXX_PTR_DEF(RollingFileAppender);
+
+ }
+}
+
+#endif
+
diff --git a/src/main/include/log4cxx/rolling/rollingfileappenderskeleton.h b/src/main/include/log4cxx/rolling/rollingfileappenderskeleton.h
new file mode 100644
index 0000000..f1b73b4
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/rollingfileappenderskeleton.h
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_ROLLING_ROLLING_FILE_APPENDER_SKELETON_H)
+#define _LOG4CXX_ROLLING_ROLLING_FILE_APPENDER_SKELETON_H
+
+#include <log4cxx/portability.h>
+#include <log4cxx/spi/optionhandler.h>
+#include <log4cxx/fileappender.h>
+#include <log4cxx/rolling/triggeringpolicy.h>
+#include <log4cxx/rolling/rollingpolicy.h>
+#include <log4cxx/rolling/action.h>
+
+namespace log4cxx {
+ namespace rolling {
+
+
+ /**
+ * Base class for log4cxx::rolling::RollingFileAppender and log4cxx::RollingFileAppender
+ * (analogues of org.apache.log4j.rolling.RFA from extras companion and
+ * org.apache.log4j.RFA from log4j 1.2, respectively).
+ *
+ * */
+ class LOG4CXX_EXPORT RollingFileAppenderSkeleton : public FileAppender {
+ DECLARE_LOG4CXX_OBJECT(RollingFileAppenderSkeleton)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(RollingFileAppenderSkeleton)
+ LOG4CXX_CAST_ENTRY_CHAIN(FileAppender)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Triggering policy.
+ */
+ TriggeringPolicyPtr triggeringPolicy;
+
+ /**
+ * Rolling policy.
+ */
+ RollingPolicyPtr rollingPolicy;
+
+ /**
+ * Length of current active log file.
+ */
+ size_t fileLength;
+
+ public:
+ /**
+ * The default constructor simply calls its {@link
+ * FileAppender#FileAppender parents constructor}.
+ * */
+ RollingFileAppenderSkeleton();
+
+ void activateOptions(log4cxx::helpers::Pool&);
+
+
+ /**
+ Implements the usual roll over behaviour.
+
+ <p>If <code>MaxBackupIndex</code> is positive, then files
+ {<code>File.1</code>, ..., <code>File.MaxBackupIndex -1</code>}
+ are renamed to {<code>File.2</code>, ...,
+ <code>File.MaxBackupIndex</code>}. Moreover, <code>File</code> is
+ renamed <code>File.1</code> and closed. A new <code>File</code> is
+ created to receive further log output.
+
+ <p>If <code>MaxBackupIndex</code> is equal to zero, then the
+ <code>File</code> is truncated with no backup files created.
+
+ */
+ bool rollover(log4cxx::helpers::Pool& p);
+
+ protected:
+
+ /**
+ Actual writing occurs here.
+ */
+ virtual void subAppend(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);
+
+ protected:
+
+ RollingPolicyPtr getRollingPolicy() const;
+
+ TriggeringPolicyPtr getTriggeringPolicy() const;
+
+ /**
+ * Sets the rolling policy. In case the 'policy' argument also implements
+ * {@link TriggeringPolicy}, then the triggering policy for this appender
+ * is automatically set to be the policy argument.
+ * @param policy
+ */
+ void setRollingPolicy(const RollingPolicyPtr& policy);
+
+ void setTriggeringPolicy(const TriggeringPolicyPtr& policy);
+
+ public:
+ /**
+ * Close appender. Waits for any asynchronous file compression actions to be completed.
+ */
+ void close();
+
+ protected:
+ /**
+ Returns an OutputStreamWriter when passed an OutputStream. The
+ encoding used will depend on the value of the
+ <code>encoding</code> property. If the encoding value is
+ specified incorrectly the writer will be opened using the default
+ system encoding (an error message will be printed to the loglog.
+ @param os output stream, may not be null.
+ @return new writer.
+ */
+ log4cxx::helpers::WriterPtr createWriter(log4cxx::helpers::OutputStreamPtr& os);
+
+ public:
+
+
+
+ /**
+ * Get byte length of current active log file.
+ * @return byte length of current active log file.
+ */
+ size_t getFileLength() const;
+
+ /**
+ * Increments estimated byte length of current active log file.
+ * @param increment additional bytes written to log file.
+ */
+ void incrementFileLength(size_t increment);
+
+ };
+
+
+ LOG4CXX_PTR_DEF(RollingFileAppenderSkeleton);
+
+ }
+}
+
+#endif
+
diff --git a/src/main/include/log4cxx/rolling/rollingpolicy.h b/src/main/include/log4cxx/rolling/rollingpolicy.h
new file mode 100755
index 0000000..4598d94
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/rollingpolicy.h
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_ROLLING_ROLLING_POLICY_H)
+#define _LOG4CXX_ROLLING_ROLLING_POLICY_H
+
+#include <log4cxx/portability.h>
+#include <log4cxx/spi/optionhandler.h>
+#include <log4cxx/rolling/rolloverdescription.h>
+#include <log4cxx/file.h>
+
+namespace log4cxx {
+ namespace rolling {
+
+
+ /**
+ * A <code>RollingPolicy</code> is responsible for performing the
+ * rolling over of the active log file. The <code>RollingPolicy</code>
+ * is also responsible for providing the <em>active log file</em>,
+ * that is the live file where logging output will be directed.
+ *
+ *
+ *
+ *
+ */
+ class LOG4CXX_EXPORT RollingPolicy :
+ public virtual spi::OptionHandler {
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(RollingPolicy)
+
+ public:
+ virtual ~RollingPolicy() {}
+ /**
+ * Initialize the policy and return any initial actions for rolling file appender.
+ *
+ * @param file current value of RollingFileAppender.getFile().
+ * @param append current value of RollingFileAppender.getAppend().
+ * @param p pool for memory allocations during call.
+ * @return Description of the initialization, may be null to indicate
+ * no initialization needed.
+ * @throws SecurityException if denied access to log files.
+ */
+ virtual RolloverDescriptionPtr initialize(
+ const LogString& file,
+ const bool append,
+ log4cxx::helpers::Pool& p) = 0;
+
+ /**
+ * Prepare for a rollover. This method is called prior to
+ * closing the active log file, performs any necessary
+ * preliminary actions and describes actions needed
+ * after close of current log file.
+ *
+ * @param activeFile file name for current active log file.
+ * @param p pool for memory allocations during call.
+ * @return Description of pending rollover, may be null to indicate no rollover
+ * at this time.
+ * @throws SecurityException if denied access to log files.
+ */
+ virtual RolloverDescriptionPtr rollover(const LogString& activeFile,
+ log4cxx::helpers::Pool& p) = 0;
+ };
+
+ LOG4CXX_PTR_DEF(RollingPolicy);
+
+ }
+}
+#endif
+
diff --git a/src/main/include/log4cxx/rolling/rollingpolicybase.h b/src/main/include/log4cxx/rolling/rollingpolicybase.h
new file mode 100755
index 0000000..154b17d
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/rollingpolicybase.h
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_ROLLING_ROLLING_POLICY_BASE_H)
+#define _LOG4CXX_ROLLING_ROLLING_POLICY_BASE_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/helpers/object.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/rolling/rollingpolicy.h>
+#include <log4cxx/pattern/patternconverter.h>
+#include <log4cxx/pattern/formattinginfo.h>
+#include <log4cxx/pattern/patternparser.h>
+
+namespace log4cxx {
+ namespace rolling {
+
+ /**
+ * Implements methods common to most, it not all, rolling
+ * policies.
+ *
+ *
+ *
+ */
+ class LOG4CXX_EXPORT RollingPolicyBase :
+ public virtual RollingPolicy,
+ public virtual helpers::ObjectImpl {
+ protected:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(RollingPolicyBase)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(RollingPolicy)
+ LOG4CXX_CAST_ENTRY(spi::OptionHandler)
+ END_LOG4CXX_CAST_MAP()
+
+
+ private:
+ /**
+ * File name pattern converters.
+ */
+ LOG4CXX_LIST_DEF(PatternConverterList, log4cxx::pattern::PatternConverterPtr);
+ PatternConverterList patternConverters;
+
+ /**
+ * File name field specifiers.
+ */
+ LOG4CXX_LIST_DEF(FormattingInfoList, log4cxx::pattern::FormattingInfoPtr);
+ FormattingInfoList patternFields;
+
+ /**
+ * File name pattern.
+ */
+ LogString fileNamePatternStr;
+
+
+ public:
+ RollingPolicyBase();
+ virtual ~RollingPolicyBase();
+ void addRef() const;
+ void releaseRef() const;
+ virtual void activateOptions(log4cxx::helpers::Pool& p) = 0;
+ virtual log4cxx::pattern::PatternMap getFormatSpecifiers() const = 0;
+
+ virtual void setOption(const LogString& option,
+ const LogString& value);
+
+ /**
+ * Set file name pattern.
+ * @param fnp file name pattern.
+ */
+ void setFileNamePattern(const LogString& fnp);
+
+ /**
+ * Get file name pattern.
+ * @return file name pattern.
+ */
+ LogString getFileNamePattern() const;
+
+
+ protected:
+ /**
+ * Parse file name pattern.
+ */
+ void parseFileNamePattern();
+
+ /**
+ * Format file name.
+ *
+ * @param obj object to be evaluted in formatting, may not be null.
+ * @param buf string buffer to which formatted file name is appended, may not be null.
+ * @param p memory pool.
+ */
+ void formatFileName(log4cxx::helpers::ObjectPtr& obj,
+ LogString& buf, log4cxx::helpers::Pool& p) const;
+
+ log4cxx::pattern::PatternConverterPtr getIntegerPatternConverter() const;
+ log4cxx::pattern::PatternConverterPtr getDatePatternConverter() const;
+
+
+ };
+ }
+}
+
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif
diff --git a/src/main/include/log4cxx/rolling/rolloverdescription.h b/src/main/include/log4cxx/rolling/rolloverdescription.h
new file mode 100644
index 0000000..4e01fca
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/rolloverdescription.h
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_ROLLING_ROLLOVER_DESCRIPTION_H)
+#define _LOG4CXX_ROLLING_ROLLOVER_DESCRIPTION_H
+
+#include <log4cxx/portability.h>
+#include <log4cxx/rolling/action.h>
+
+namespace log4cxx {
+ namespace rolling {
+
+
+ class RolloverDescription : public log4cxx::helpers::ObjectImpl {
+ DECLARE_LOG4CXX_OBJECT(RolloverDescription)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(RolloverDescription)
+ END_LOG4CXX_CAST_MAP()
+ /**
+ * Active log file name after rollover.
+ */
+ LogString activeFileName;
+
+ /**
+ * Should active file be opened for appending.
+ */
+ bool append;
+
+ /**
+ * Action to be completed after close of current active log file
+ * before returning control to caller.
+ */
+ ActionPtr synchronous;
+
+ /**
+ * Action to be completed after close of current active log file
+ * and before next rollover attempt, may be executed asynchronously.
+ */
+ ActionPtr asynchronous;
+
+ public:
+ RolloverDescription();
+ /**
+ * Create new instance.
+ * @param activeFileName active log file name after rollover, may not be null.
+ * @param append true if active log file after rollover should be opened for appending.
+ * @param synchronous action to be completed after close of current active log file, may be null.
+ * @param asynchronous action to be completed after close of current active log file and
+ * before next rollover attempt.
+ */
+ RolloverDescription(
+ const LogString& activeFileName,
+ const bool append,
+ const ActionPtr& synchronous,
+ const ActionPtr& asynchronous);
+
+ /**
+ * Active log file name after rollover.
+ * @return active log file name after rollover.
+ */
+ LogString getActiveFileName() const;
+
+ bool getAppend() const;
+
+ /**
+ * Action to be completed after close of current active log file
+ * before returning control to caller.
+ *
+ * @return action, may be null.
+ */
+ ActionPtr getSynchronous() const;
+
+ /**
+ * Action to be completed after close of current active log file
+ * and before next rollover attempt, may be executed asynchronously.
+ *
+ * @return action, may be null.
+ */
+ ActionPtr getAsynchronous() const;
+ };
+
+ LOG4CXX_PTR_DEF(RolloverDescription);
+
+ }
+}
+#endif
+
diff --git a/src/main/include/log4cxx/rolling/sizebasedtriggeringpolicy.h b/src/main/include/log4cxx/rolling/sizebasedtriggeringpolicy.h
new file mode 100755
index 0000000..87ddffb
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/sizebasedtriggeringpolicy.h
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_ROLLING_SIZE_BASED_TRIGGERING_POLICY_H)
+#define _LOG4CXX_ROLLING_SIZE_BASED_TRIGGERING_POLICY_H
+
+#include <log4cxx/rolling/triggeringpolicy.h>
+
+namespace log4cxx {
+
+ class File;
+
+ namespace helpers {
+ class Pool;
+ }
+
+ namespace rolling {
+
+ /**
+ * SizeBasedTriggeringPolicy looks at size of the file being
+ * currently written to.
+ *
+ *
+ *
+ */
+ class LOG4CXX_EXPORT SizeBasedTriggeringPolicy : public TriggeringPolicy {
+ DECLARE_LOG4CXX_OBJECT(SizeBasedTriggeringPolicy)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(SizeBasedTriggeringPolicy)
+ LOG4CXX_CAST_ENTRY_CHAIN(TriggeringPolicy)
+ END_LOG4CXX_CAST_MAP()
+
+ protected:
+ size_t maxFileSize;
+
+ public:
+ SizeBasedTriggeringPolicy();
+ /**
+ * Determines if a rollover may be appropriate at this time. If
+ * true is returned, RolloverPolicy.rollover will be called but it
+ * can determine that a rollover is not warranted.
+ *
+ * @param appender A reference to the appender.
+ * @param event A reference to the currently event.
+ * @param filename The filename for the currently active log file.
+ * @param fileLength Length of the file in bytes.
+ * @return true if a rollover should occur.
+ */
+ virtual bool isTriggeringEvent(
+ Appender* appender,
+ const log4cxx::spi::LoggingEventPtr& event,
+ const LogString& filename,
+ size_t fileLength);
+
+ size_t getMaxFileSize();
+
+ void setMaxFileSize(size_t l);
+
+ void activateOptions(log4cxx::helpers::Pool&);
+ void setOption(const LogString& option, const LogString& value);
+ };
+
+ LOG4CXX_PTR_DEF(SizeBasedTriggeringPolicy);
+
+ }
+}
+#endif
+
diff --git a/src/main/include/log4cxx/rolling/timebasedrollingpolicy.h b/src/main/include/log4cxx/rolling/timebasedrollingpolicy.h
new file mode 100755
index 0000000..d20745e
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/timebasedrollingpolicy.h
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#if !defined(_LOG4CXX_ROLLING_TIME_BASED_ROLLING_POLICY_H)
+#define _LOG4CXX_ROLLING_TIME_BASED_ROLLING_POLICY_H
+
+#include <log4cxx/portability.h>
+#include <log4cxx/rolling/rollingpolicybase.h>
+#include <log4cxx/rolling/triggeringpolicy.h>
+
+namespace log4cxx {
+
+ namespace rolling {
+
+
+
+ /**
+ * <code>TimeBasedRollingPolicy</code> is both easy to configure and quite
+ * powerful.
+ *
+ * <p>In order to use <code>TimeBasedRollingPolicy</code>, the
+ * <b>FileNamePattern</b> option must be set. It basically specifies the name of the
+ * rolled log files. The value <code>FileNamePattern</code> should consist of
+ * the name of the file, plus a suitably placed <code>%d</code> conversion
+ * specifier. The <code>%d</code> conversion specifier may contain a date and
+ * time pattern as specified by the {@link log4cxx::helpers::SimpleDateFormat} class. If
+ * the date and time pattern is ommitted, then the default pattern of
+ * "yyyy-MM-dd" is assumed. The following examples should clarify the point.
+ *
+ * <p>
+ * <table cellspacing="5px" border="1">
+ * <tr>
+ * <th><code>FileNamePattern</code> value</th>
+ * <th>Rollover schedule</th>
+ * <th>Example</th>
+ * </tr>
+ * <tr>
+ * <td nowrap="true"><code>/wombat/folder/foo.%d</code></td>
+ * <td>Daily rollover (at midnight). Due to the omission of the optional
+ * time and date pattern for the %d token specifier, the default pattern
+ * of "yyyy-MM-dd" is assumed, which corresponds to daily rollover.
+ * </td>
+ * <td>During November 23rd, 2004, logging output will go to
+ * the file <code>/wombat/foo.2004-11-23</code>. At midnight and for
+ * the rest of the 24th, logging output will be directed to
+ * <code>/wombat/foo.2004-11-24</code>.
+ * </td>
+ * </tr>
+ * <tr>
+ * <td nowrap="true"><code>/wombat/foo.%d{yyyy-MM}.log</code></td>
+ * <td>Rollover at the beginning of each month.</td>
+ * <td>During the month of October 2004, logging output will go to
+ * <code>/wombat/foo.2004-10.log</code>. After midnight of October 31st
+ * and for the rest of November, logging output will be directed to
+ * <code>/wombat/foo.2004-11.log</code>.
+ * </td>
+ * </tr>
+ * </table>
+ * <h2>Automatic file compression</h2>
+ * <code>TimeBasedRollingPolicy</code> supports automatic file compression.
+ * This feature is enabled if the value of the <b>FileNamePattern</b> option
+ * ends with <code>.gz</code> or <code>.zip</code>.
+ * <p>
+ * <table cellspacing="5px" border="1">
+ * <tr>
+ * <th><code>FileNamePattern</code> value</th>
+ * <th>Rollover schedule</th>
+ * <th>Example</th>
+ * </tr>
+ * <tr>
+ * <td nowrap="true"><code>/wombat/foo.%d.gz</code></td>
+ * <td>Daily rollover (at midnight) with automatic GZIP compression of the
+ * arcived files.</td>
+ * <td>During November 23rd, 2004, logging output will go to
+ * the file <code>/wombat/foo.2004-11-23</code>. However, at midnight that
+ * file will be compressed to become <code>/wombat/foo.2004-11-23.gz</code>.
+ * For the 24th of November, logging output will be directed to
+ * <code>/wombat/folder/foo.2004-11-24</code> until its rolled over at the
+ * beginning of the next day.
+ * </td>
+ * </tr>
+ * </table>
+ *
+ * <h2>Decoupling the location of the active log file and the archived log files</h2>
+ * <p>The <em>active file</em> is defined as the log file for the current period
+ * whereas <em>archived files</em> are thos files which have been rolled over
+ * in previous periods.
+ *
+ * <p>By setting the <b>ActiveFileName</b> option you can decouple the location
+ * of the active log file and the location of the archived log files.
+ * <p>
+ * <table cellspacing="5px" border="1">
+ * <tr>
+ * <th><code>FileNamePattern</code> value</th>
+ * <th>ActiveFileName</th>
+ * <th>Rollover schedule</th>
+ * <th>Example</th>
+ * </tr>
+ * <tr>
+ * <td nowrap="true"><code>/wombat/foo.log.%d</code></td>
+ * <td nowrap="true"><code>/wombat/foo.log</code></td>
+ * <td>Daily rollover.</td>
+ *
+ * <td>During November 23rd, 2004, logging output will go to
+ * the file <code>/wombat/foo.log</code>. However, at midnight that file
+ * will archived as <code>/wombat/foo.log.2004-11-23</code>. For the 24th
+ * of November, logging output will be directed to
+ * <code>/wombat/folder/foo.log</code> until its archived as
+ * <code>/wombat/foo.log.2004-11-24</code> at the beginning of the next
+ * day.
+ * </td>
+ * </tr>
+ * </table>
+ * <p>
+ * If configuring programatically, do not forget to call {@link #activateOptions}
+ * method before using this policy. Moreover, {@link #activateOptions} of
+ * <code> TimeBasedRollingPolicy</code> must be called <em>before</em> calling
+ * the {@link #activateOptions} method of the owning
+ * <code>RollingFileAppender</code>.
+ *
+ *
+ *
+ */
+ class LOG4CXX_EXPORT TimeBasedRollingPolicy : public RollingPolicyBase,
+ public TriggeringPolicy {
+ DECLARE_LOG4CXX_OBJECT(TimeBasedRollingPolicy)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(TimeBasedRollingPolicy)
+ LOG4CXX_CAST_ENTRY_CHAIN(RollingPolicyBase)
+ LOG4CXX_CAST_ENTRY_CHAIN(TriggeringPolicy)
+ END_LOG4CXX_CAST_MAP()
+
+ private:
+ /**
+ * Time for next determination if time for rollover.
+ */
+ log4cxx_time_t nextCheck;
+
+ /**
+ * File name at last rollover.
+ */
+ LogString lastFileName;
+
+ /**
+ * Length of any file type suffix (.gz, .zip).
+ */
+ int suffixLength;
+
+ public:
+ TimeBasedRollingPolicy();
+ void addRef() const;
+ void releaseRef() const;
+ void activateOptions(log4cxx::helpers::Pool& );
+ /**
+ * Initialize the policy and return any initial actions for rolling file appender.
+ *
+ * @param file current value of RollingFileAppender.getFile().
+ * @param append current value of RollingFileAppender.getAppend().
+ * @param pool pool for any required allocations.
+ * @return Description of the initialization, may be null to indicate
+ * no initialization needed.
+ * @throws SecurityException if denied access to log files.
+ */
+ RolloverDescriptionPtr initialize(
+ const LogString& file,
+ const bool append,
+ log4cxx::helpers::Pool& pool);
+
+ /**
+ * Prepare for a rollover. This method is called prior to
+ * closing the active log file, performs any necessary
+ * preliminary actions and describes actions needed
+ * after close of current log file.
+ *
+ * @param activeFile file name for current active log file.
+ * @param pool pool for any required allocations.
+ * @return Description of pending rollover, may be null to indicate no rollover
+ * at this time.
+ * @throws SecurityException if denied access to log files.
+ */
+ RolloverDescriptionPtr rollover(const LogString& activeFile,
+ log4cxx::helpers::Pool& pool);
+
+/**
+ * Determines if a rollover may be appropriate at this time. If
+ * true is returned, RolloverPolicy.rollover will be called but it
+ * can determine that a rollover is not warranted.
+ *
+ * @param appender A reference to the appender.
+ * @param event A reference to the currently event.
+ * @param filename The filename for the currently active log file.
+ * @param fileLength Length of the file in bytes.
+ * @return true if a rollover should occur.
+ */
+virtual bool isTriggeringEvent(
+ Appender* appender,
+ const log4cxx::spi::LoggingEventPtr& event,
+ const LogString& filename,
+ size_t fileLength);
+
+ protected:
+ log4cxx::pattern::PatternMap getFormatSpecifiers() const;
+
+ };
+
+ LOG4CXX_PTR_DEF(TimeBasedRollingPolicy);
+
+ }
+}
+
+#endif
+
diff --git a/src/main/include/log4cxx/rolling/triggeringpolicy.h b/src/main/include/log4cxx/rolling/triggeringpolicy.h
new file mode 100755
index 0000000..6a71632
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/triggeringpolicy.h
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#if !defined(_LOG4CXX_ROLLING_TRIGGER_POLICY_H)
+#define _LOG4CXX_ROLLING_TRIGGER_POLICY_H
+
+
+#include <log4cxx/spi/optionhandler.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/appender.h>
+
+namespace log4cxx {
+ class File;
+
+ namespace rolling {
+
+ /**
+ * A <code>TriggeringPolicy</code> controls the conditions under which rollover
+ * occurs. Such conditions include time of day, file size, an
+ * external event or a combination thereof.
+ *
+ *
+ *
+ * */
+
+ class LOG4CXX_EXPORT TriggeringPolicy :
+ public virtual spi::OptionHandler,
+ public virtual helpers::ObjectImpl {
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(TriggeringPolicy)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(TriggeringPolicy)
+ LOG4CXX_CAST_ENTRY(spi::OptionHandler)
+ END_LOG4CXX_CAST_MAP()
+ public:
+ virtual ~TriggeringPolicy();
+ void addRef() const;
+ void releaseRef() const;
+
+ /**
+ * Determines if a rollover may be appropriate at this time. If
+ * true is returned, RolloverPolicy.rollover will be called but it
+ * can determine that a rollover is not warranted.
+ *
+ * @param appender A reference to the appender.
+ * @param event A reference to the currently event.
+ * @param filename The filename for the currently active log file.
+ * @param fileLength Length of the file in bytes.
+ * @return true if a rollover should occur.
+ */
+ virtual bool isTriggeringEvent(
+ Appender* appender,
+ const log4cxx::spi::LoggingEventPtr& event,
+ const LogString& filename,
+ size_t fileLength) = 0;
+
+ };
+
+ LOG4CXX_PTR_DEF(TriggeringPolicy);
+
+
+ }
+}
+
+#endif
diff --git a/src/main/include/log4cxx/rolling/zipcompressaction.h b/src/main/include/log4cxx/rolling/zipcompressaction.h
new file mode 100644
index 0000000..66a19c6
--- /dev/null
+++ b/src/main/include/log4cxx/rolling/zipcompressaction.h
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_ROLLING_ZIP_COMPRESS_ACTION_H)
+#define _LOG4CXX_ROLLING_ZIP_COMPRESS_ACTION_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/rolling/action.h>
+#include <log4cxx/file.h>
+
+namespace log4cxx {
+ namespace rolling {
+
+
+ class ZipCompressAction : public Action {
+ const File source;
+ const File destination;
+ bool deleteSource;
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(ZipCompressAction)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(ZipCompressAction)
+ LOG4CXX_CAST_ENTRY_CHAIN(Action)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ * Constructor.
+ */
+ ZipCompressAction(const File& source,
+ const File& destination,
+ bool deleteSource);
+
+ /**
+ * Perform action.
+ *
+ * @return true if successful.
+ */
+ virtual bool execute(log4cxx::helpers::Pool& pool) const;
+
+ private:
+ ZipCompressAction(const ZipCompressAction&);
+ ZipCompressAction& operator=(const ZipCompressAction&);
+ };
+
+ LOG4CXX_PTR_DEF(ZipCompressAction);
+
+ }
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+}
+#endif
+
diff --git a/src/main/include/log4cxx/rollingfileappender.h b/src/main/include/log4cxx/rollingfileappender.h
new file mode 100644
index 0000000..f8d519f
--- /dev/null
+++ b/src/main/include/log4cxx/rollingfileappender.h
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_ROLLING_FILE_APPENDER_H
+#define _LOG4CXX_ROLLING_FILE_APPENDER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/rolling/rollingfileappenderskeleton.h>
+
+namespace log4cxx
+{
+
+ /** RollingFileAppender extends FileAppender to backup the log files when they reach a certain size. */
+ class LOG4CXX_EXPORT RollingFileAppender : public log4cxx::rolling::RollingFileAppenderSkeleton
+ {
+ private:
+ /** The default maximum file size is 10MB. */
+ long maxFileSize;
+
+ /** There is one backup file by default. */
+ int maxBackupIndex;
+
+ public:
+ //
+ // Use custom class to use non-default name to avoid
+ // conflict with log4cxx::rolling::RollingFileAppender
+ DECLARE_LOG4CXX_OBJECT_WITH_CUSTOM_CLASS( RollingFileAppender, ClassRollingFileAppender )
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY( RollingFileAppender )
+ LOG4CXX_CAST_ENTRY_CHAIN( FileAppender )
+ END_LOG4CXX_CAST_MAP()
+ /** The default constructor simply calls its {@link FileAppender#FileAppender parents constructor}. */
+ RollingFileAppender();
+
+ /**
+ Instantiate a RollingFileAppender and open the file designated by
+ <code>filename</code>. The opened filename will become the ouput destination for this appender.
+
+ <p>If the <code>append</code> parameter is true, the file will be appended to. Otherwise, the file desginated by
+ <code>filename</code> will be truncated before being opened.
+ */
+ RollingFileAppender( const LayoutPtr & layout, const LogString & fileName, bool append );
+
+ /**
+ Instantiate a FileAppender and open the file designated by
+ <code>filename</code>. The opened filename will become the output destination for this appender.
+ <p>The file will be appended to.
+ */
+ RollingFileAppender( const LayoutPtr & layout, const LogString & fileName );
+
+ virtual ~RollingFileAppender();
+
+ /** Returns the value of the <b>MaxBackupIndex</b> option. */
+ int getMaxBackupIndex() const;
+
+ /** Get the maximum size that the output file is allowed to reach before being rolled over to backup files. */
+ long getMaximumFileSize() const;
+
+
+ /**
+ Set the maximum number of backup files to keep around.
+
+ <p>The <b>MaxBackupIndex</b> option determines how many backup
+ files are kept before the oldest is erased. This option takes
+ a positive integer value. If set to zero, then there will be no
+ backup files and the log file will be truncated when it reaches <code>MaxFileSize</code>.
+ */
+ void setMaxBackupIndex( int maxBackupIndex );
+
+ /**
+ Set the maximum size that the output file is allowed to reach before being rolled over to backup files.
+
+ <p>In configuration files, the <b>MaxFileSize</b> option takes an
+ long integer in the range 0 - 2^63. You can specify the value with the suffixes "KB", "MB" or "GB" so that the integer is
+ interpreted being expressed respectively in kilobytes, megabytes
+ or gigabytes. For example, the value "10KB" will be interpreted as 10240.
+ */
+ void setMaxFileSize( const LogString & value );
+
+ void setMaximumFileSize( int value );
+
+
+ virtual void setOption( const LogString & option, const LogString & value );
+
+ /** Prepares RollingFileAppender for use. */
+ void activateOptions( log4cxx::helpers::Pool & pool );
+
+
+ }; // class RollingFileAppender
+ LOG4CXX_PTR_DEF(RollingFileAppender);
+
+ } // namespace log4cxx
+
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif //_LOG4CXX_ROLLING_FILE_APPENDER_H
diff --git a/src/main/include/log4cxx/simplelayout.h b/src/main/include/log4cxx/simplelayout.h
new file mode 100644
index 0000000..2dae784
--- /dev/null
+++ b/src/main/include/log4cxx/simplelayout.h
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SIMPLE_LAYOUT_H
+#define _LOG4CXX_SIMPLE_LAYOUT_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/layout.h>
+
+namespace log4cxx
+{
+ /**
+ SimpleLayout consists of the level of the log statement,
+ followed by " - " and then the log message itself. For example,
+
+ <pre>
+ DEBUG - Hello world
+ </pre>
+
+ <p>
+
+ <p>PatternLayout offers a much more powerful alternative.
+ */
+ class LOG4CXX_EXPORT SimpleLayout : public Layout
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(SimpleLayout)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(SimpleLayout)
+ LOG4CXX_CAST_ENTRY_CHAIN(Layout)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ Returns the log statement in a format consisting of the
+ <code>level</code>, followed by " - " and then the
+ <code>message</code>. For example, <pre> INFO - "A message"
+ </pre>
+
+ @return A byte array in SimpleLayout format.
+ */
+ virtual void format(LogString& output,
+ const spi::LoggingEventPtr& event,
+ log4cxx::helpers::Pool& pool) const;
+
+ /**
+ The SimpleLayout does not handle the throwable contained within
+ {@link spi::LoggingEvent LoggingEvents}. Thus, it returns
+ <code>true</code>.
+ */
+ bool ignoresThrowable() const { return true; }
+
+ virtual void activateOptions(log4cxx::helpers::Pool& /* p */) {}
+ virtual void setOption(const LogString& /* option */,
+ const LogString& /* value */) {}
+ };
+ LOG4CXX_PTR_DEF(SimpleLayout);
+} // namespace log4cxx
+
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif //_LOG4CXX_SIMPLE_LAYOUT_H
diff --git a/src/main/include/log4cxx/spi/Makefile.am b/src/main/include/log4cxx/spi/Makefile.am
new file mode 100644
index 0000000..4e547ca
--- /dev/null
+++ b/src/main/include/log4cxx/spi/Makefile.am
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+SUBDIRS = location
+spiincdir = $(includedir)/log4cxx/spi
+spiinc_HEADERS= $(top_srcdir)/src/main/include/log4cxx/spi/*.h
+
diff --git a/src/main/include/log4cxx/spi/appenderattachable.h b/src/main/include/log4cxx/spi/appenderattachable.h
new file mode 100644
index 0000000..7fa06fa
--- /dev/null
+++ b/src/main/include/log4cxx/spi/appenderattachable.h
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_APPENDER_ATTACHABLE_H_
+#define _LOG4CXX_SPI_APPENDER_ATTACHABLE_H_
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include <vector>
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/object.h>
+#include <log4cxx/appender.h>
+
+namespace log4cxx
+{
+
+ namespace spi
+ {
+
+ /**
+ * This Interface is for attaching Appenders to objects.
+ */
+ class LOG4CXX_EXPORT AppenderAttachable : public virtual helpers::Object
+ {
+ public:
+ // Methods
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(AppenderAttachable)
+ /**
+ * Add an appender.
+ */
+ virtual void addAppender(const AppenderPtr& newAppender) = 0;
+
+ /**
+ * Get all previously added appenders as an AppenderList.
+ */
+ virtual AppenderList getAllAppenders() const = 0;
+
+ /**
+ * Get an appender by name.
+ */
+ virtual AppenderPtr getAppender(const LogString& name) const = 0;
+
+ /**
+ Returns <code>true</code> if the specified appender is in list of
+ attached attached, <code>false</code> otherwise.
+ */
+ virtual bool isAttached(const AppenderPtr& appender) const = 0;
+
+ /**
+ * Remove all previously added appenders.
+ */
+ virtual void removeAllAppenders() = 0;
+
+ /**
+ * Remove the appender passed as parameter from the list of appenders.
+ */
+ virtual void removeAppender(const AppenderPtr& appender) = 0;
+
+ /**
+ * Remove the appender with the name passed as parameter from the
+ * list of appenders.
+ */
+ virtual void removeAppender(const LogString& name) = 0;
+
+ // Dtor
+ virtual ~AppenderAttachable(){}
+ };
+
+
+ LOG4CXX_PTR_DEF(AppenderAttachable);
+
+ }
+}
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+#endif //_LOG4CXX_SPI_APPENDER_ATTACHABLE_H_
diff --git a/src/main/include/log4cxx/spi/configurator.h b/src/main/include/log4cxx/spi/configurator.h
new file mode 100644
index 0000000..7ded840
--- /dev/null
+++ b/src/main/include/log4cxx/spi/configurator.h
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_CONFIGURATOR_H
+#define _LOG4CXX_SPI_CONFIGURATOR_H
+
+#include <log4cxx/spi/loggerrepository.h>
+
+namespace log4cxx
+{
+ class File;
+
+ namespace spi
+ {
+ /**
+ Implemented by classes capable of configuring log4j using a URL.
+ */
+ class LOG4CXX_EXPORT Configurator : virtual public helpers::Object
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(Configurator)
+ Configurator();
+
+ /**
+ Interpret a resource pointed by a URL and set up log4j accordingly.
+
+ The configuration is done relative to the <code>hierarchy</code>
+ parameter.
+
+ @param configFileName The file to parse
+ @param repository The hierarchy to operation upon.
+ */
+ virtual void doConfigure(const File& configFileName,
+ spi::LoggerRepositoryPtr& repository) = 0;
+
+
+ private:
+ Configurator(const Configurator&);
+ Configurator& operator=(const Configurator&);
+ bool initialized;
+ };
+
+ LOG4CXX_PTR_DEF(Configurator);
+ }
+}
+
+#endif // _LOG4CXX_SPI_CONFIGURATOR_H
diff --git a/src/main/include/log4cxx/spi/defaultrepositoryselector.h b/src/main/include/log4cxx/spi/defaultrepositoryselector.h
new file mode 100644
index 0000000..9f09908
--- /dev/null
+++ b/src/main/include/log4cxx/spi/defaultrepositoryselector.h
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_DEFAULT_REPOSITORY_SELECTOR_H
+#define _LOG4CXX_SPI_DEFAULT_REPOSITORY_SELECTOR_H
+
+#include <log4cxx/spi/repositoryselector.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/spi/loggerrepository.h>
+
+namespace log4cxx
+{
+ namespace spi
+ {
+ class LOG4CXX_EXPORT DefaultRepositorySelector :
+ public virtual RepositorySelector,
+ public virtual helpers::ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(DefaultRepositorySelector)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(RepositorySelector)
+ END_LOG4CXX_CAST_MAP()
+
+ DefaultRepositorySelector(const LoggerRepositoryPtr& repository1);
+ void addRef() const;
+ void releaseRef() const;
+ virtual LoggerRepositoryPtr& getLoggerRepository();
+
+ private:
+ LoggerRepositoryPtr repository;
+ };
+ } // namespace spi
+} // namespace log4cxx
+
+#endif //_LOG4CXX_SPI_DEFAULT_REPOSITORY_SELECTOR_H
diff --git a/src/main/include/log4cxx/spi/errorhandler.h b/src/main/include/log4cxx/spi/errorhandler.h
new file mode 100644
index 0000000..54e8262
--- /dev/null
+++ b/src/main/include/log4cxx/spi/errorhandler.h
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_ERROR_HANDLER_H
+#define _LOG4CXX_SPI_ERROR_HANDLER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/spi/optionhandler.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/appender.h>
+#include <log4cxx/spi/loggingevent.h>
+
+namespace log4cxx
+{
+ namespace spi
+ {
+ class ErrorCode
+ {
+ public:
+ enum
+ {
+ GENERIC_FAILURE = 0,
+ WRITE_FAILURE = 1,
+ FLUSH_FAILURE = 2,
+ CLOSE_FAILURE = 3,
+ FILE_OPEN_FAILURE = 4,
+ MISSING_LAYOUT = 5,
+ ADDRESS_PARSE_FAILURE = 6
+ };
+ };
+
+
+ /**
+ Appenders may delegate their error handling to
+ <code>ErrorHandlers</code>.
+
+ <p>Error handling is a particularly tedious to get right because by
+ definition errors are hard to predict and to reproduce.
+
+
+ <p>Please take the time to contact the author in case you discover
+ that errors are not properly handled. You are most welcome to
+ suggest new error handling policies or criticize existing policies.
+ */
+ class LOG4CXX_EXPORT ErrorHandler : public virtual OptionHandler
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(ErrorHandler)
+ virtual ~ErrorHandler() {}
+
+ /**
+ Add a reference to a logger to which the failing appender might
+ be attached to. The failing appender will be searched and
+ replaced only in the loggers you add through this method.
+
+ @param logger One of the loggers that will be searched for the failing
+ appender in view of replacement.
+ */
+ virtual void setLogger(const LoggerPtr& logger) = 0;
+
+
+ /**
+ Equivalent to the error(const String&, helpers::Exception&, int,
+ spi::LoggingEvent&) with the the event parameteter set to
+ null.
+ */
+ virtual void error(const LogString& message, const std::exception& e,
+ int errorCode) const = 0;
+
+ /**
+ This method is normally used to just print the error message
+ passed as a parameter.
+ */
+ virtual void error(const LogString& message) const = 0;
+
+ /**
+ This method is invoked to handle the error.
+
+ @param message The message assoicated with the error.
+ @param e The Exption that was thrown when the error occured.
+ @param errorCode The error code associated with the error.
+ @param event The logging event that the failing appender is asked
+ to log.
+ */
+ virtual void error(const LogString& message, const std::exception& e,
+ int errorCode, const LoggingEventPtr& event) const = 0;
+
+ /**
+ Set the appender for which errors are handled. This method is
+ usually called when the error handler is configured.
+ */
+ virtual void setAppender(const AppenderPtr& appender) = 0;
+
+ /**
+ Set the appender to fallback upon in case of failure.
+ */
+ virtual void setBackupAppender(const AppenderPtr& appender) = 0;
+ };
+
+ LOG4CXX_PTR_DEF(ErrorHandler);
+ } //namespace spi
+} //namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif //_LOG4CXX_SPI_ERROR_HANDLER_H
diff --git a/src/main/include/log4cxx/spi/filter.h b/src/main/include/log4cxx/spi/filter.h
new file mode 100644
index 0000000..83c5dc7
--- /dev/null
+++ b/src/main/include/log4cxx/spi/filter.h
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_FILTER_H
+#define _LOG4CXX_SPI_FILTER_H
+
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/spi/optionhandler.h>
+#include <log4cxx/spi/loggingevent.h>
+
+namespace log4cxx
+{
+ namespace spi
+ {
+ class Filter;
+ LOG4CXX_PTR_DEF(Filter);
+
+
+ /**
+ Users should extend this class to implement customized logging
+ event filtering. Note that Logger and
+ AppenderSkeleton, the parent class of all standard
+ appenders, 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.
+
+ <p>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.
+
+ <p>The {@link #decide decide(LoggingEvent)} method must return one
+ of the integer constants #DENY, #NEUTRAL or
+ #ACCEPT.
+
+ <p>If the value #DENY is returned, then the log event is
+ dropped immediately without consulting with the remaining
+ filters.
+
+ <p>If the value #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.
+
+ <p>If the value #ACCEPT is returned, then the log
+ event is logged without consulting the remaining filters.
+
+ <p>The philosophy of log4cxx filters is largely inspired from the
+ Linux ipchains.
+
+ <p>Note that filtering is only supported by the {@link
+ xml::DOMConfigurator DOMConfigurator}.
+ */
+ class LOG4CXX_EXPORT Filter : public virtual OptionHandler,
+ public virtual helpers::ObjectImpl
+ {
+ /**
+ Points to the next filter in the filter chain.
+ */
+ FilterPtr next;
+ public:
+ Filter();
+
+ void addRef() const;
+ void releaseRef() const;
+
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(Filter)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(Filter)
+ LOG4CXX_CAST_ENTRY(spi::OptionHandler)
+ END_LOG4CXX_CAST_MAP()
+
+ log4cxx::spi::FilterPtr getNext() const;
+ void setNext(const log4cxx::spi::FilterPtr& newNext);
+
+ enum FilterDecision
+ {
+ /**
+ The log event must be dropped immediately without consulting
+ with the remaining filters, if any, in the chain. */
+ DENY = -1,
+ /**
+ This filter is neutral with respect to the log event. The
+ remaining filters, if any, should be consulted for a final decision.
+ */
+ NEUTRAL = 0,
+ /**
+ The log event must be logged immediately without consulting with
+ the remaining filters, if any, in the chain.
+ */
+ ACCEPT = 1
+
+ };
+
+
+ /**
+ Usually filters options become active when set. We provide a
+
+ default do-nothing implementation for convenience.
+ */
+ void activateOptions(log4cxx::helpers::Pool& p);
+ void setOption(const LogString& option, const LogString& value);
+
+ /**
+ <p>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 FilterDecision decide(const LoggingEventPtr& event) const = 0;
+ };
+ }
+}
+
+#endif //_LOG4CXX_SPI_FILTER_H
diff --git a/src/main/include/log4cxx/spi/hierarchyeventlistener.h b/src/main/include/log4cxx/spi/hierarchyeventlistener.h
new file mode 100644
index 0000000..7112397
--- /dev/null
+++ b/src/main/include/log4cxx/spi/hierarchyeventlistener.h
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_HIERARCHY_EVENT_LISTENER_H
+#define _LOG4CXX_SPI_HIERARCHY_EVENT_LISTENER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/helpers/object.h>
+#include <log4cxx/helpers/objectptr.h>
+#include <vector>
+
+namespace log4cxx
+{
+ class Logger;
+ class Appender;
+
+
+ namespace spi
+ {
+
+ /** Listen to events occuring within a Hierarchy.*/
+ class LOG4CXX_EXPORT HierarchyEventListener :
+ public virtual log4cxx::helpers::Object
+ {
+ public:
+ virtual ~HierarchyEventListener() {}
+
+ virtual void addAppenderEvent(
+ const log4cxx::helpers::ObjectPtrT<Logger>& logger,
+ const log4cxx::helpers::ObjectPtrT<Appender>& appender) = 0;
+
+ virtual void removeAppenderEvent(
+ const log4cxx::helpers::ObjectPtrT<Logger>& logger,
+ const log4cxx::helpers::ObjectPtrT<Appender>& appender) = 0;
+ };
+ LOG4CXX_PTR_DEF(HierarchyEventListener);
+ LOG4CXX_LIST_DEF(HierarchyEventListenerList, HierarchyEventListenerPtr);
+
+ } // namespace spi
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif //_LOG4CXX_SPI_HIERARCHY_EVENT_LISTENER_H
diff --git a/src/main/include/log4cxx/spi/location/Makefile.am b/src/main/include/log4cxx/spi/location/Makefile.am
new file mode 100644
index 0000000..6b780ae
--- /dev/null
+++ b/src/main/include/log4cxx/spi/location/Makefile.am
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+spiincdir = $(includedir)/log4cxx/spi/location
+spiinc_HEADERS= $(top_srcdir)/src/main/include/log4cxx/spi/location/*.h
+
diff --git a/src/main/include/log4cxx/spi/location/locationinfo.h b/src/main/include/log4cxx/spi/location/locationinfo.h
new file mode 100644
index 0000000..c49f606
--- /dev/null
+++ b/src/main/include/log4cxx/spi/location/locationinfo.h
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_LOCATION_LOCATIONINFO_H
+#define _LOG4CXX_SPI_LOCATION_LOCATIONINFO_H
+
+#include <log4cxx/log4cxx.h>
+#include <string>
+#include <log4cxx/helpers/objectoutputstream.h>
+
+namespace log4cxx
+{
+ namespace spi
+ {
+ /**
+ * This class represents the location of a logging statement.
+ *
+ */
+ class LOG4CXX_EXPORT LocationInfo
+ {
+ public:
+
+
+
+ /**
+ * When location information is not available the constant
+ * <code>NA</code> is returned. Current value of this string constant is <b>?</b>.
+ */
+ static const char * const NA;
+ static const char * const NA_METHOD;
+
+ static const LocationInfo& getLocationUnavailable();
+
+
+
+ /**
+ * Constructor.
+ * @remarks Used by LOG4CXX_LOCATION to generate
+ * location info for current code site
+ */
+ LocationInfo( const char * const fileName,
+ const char * const functionName,
+ int lineNumber);
+
+ /**
+ * Default constructor.
+ */
+ LocationInfo();
+
+ /**
+ * Copy constructor.
+ * @param src source location
+ */
+ LocationInfo( const LocationInfo & src );
+
+ /**
+ * Assignment operator.
+ * @param src source location
+ */
+ LocationInfo & operator = ( const LocationInfo & src );
+
+ /**
+ * Resets location info to default state.
+ */
+ void clear();
+
+
+ /** Return the class name of the call site. */
+ const std::string getClassName() const;
+
+ /**
+ * Return the file name of the caller.
+ * @returns file name, may be null.
+ */
+ const char * getFileName() const;
+
+ /**
+ * Returns the line number of the caller.
+ * @returns line number, -1 if not available.
+ */
+ int getLineNumber() const;
+
+ /** Returns the method name of the caller. */
+ const std::string getMethodName() const;
+
+ void write(log4cxx::helpers::ObjectOutputStream& os, log4cxx::helpers::Pool& p) const;
+
+
+ private:
+ /** Caller's line number. */
+ int lineNumber;
+
+ /** Caller's file name. */
+ const char * fileName;
+
+ /** Caller's method name. */
+ const char * methodName;
+
+
+ };
+ }
+}
+
+ #if !defined(LOG4CXX_LOCATION)
+#if defined(_MSC_VER)
+#if _MSC_VER >= 1300
+ #define __LOG4CXX_FUNC__ __FUNCSIG__
+#endif
+#else
+#if defined(__GNUC__)
+ #define __LOG4CXX_FUNC__ __PRETTY_FUNCTION__
+#endif
+#endif
+#if !defined(__LOG4CXX_FUNC__)
+#define __LOG4CXX_FUNC__ ""
+#endif
+ #define LOG4CXX_LOCATION ::log4cxx::spi::LocationInfo(__FILE__, \
+ __LOG4CXX_FUNC__, \
+ __LINE__)
+ #endif
+
+#endif //_LOG4CXX_SPI_LOCATION_LOCATIONINFO_H
diff --git a/src/main/include/log4cxx/spi/loggerfactory.h b/src/main/include/log4cxx/spi/loggerfactory.h
new file mode 100644
index 0000000..07f8be9
--- /dev/null
+++ b/src/main/include/log4cxx/spi/loggerfactory.h
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_LOGGERFACTORY_H
+#define _LOG4CXX_SPI_LOGGERFACTORY_H
+
+#include <log4cxx/logger.h>
+
+namespace log4cxx
+{
+
+ namespace spi
+ {
+ /**
+ Implement this interface to create new instances of Logger or
+ a sub-class of Logger.
+ */
+ class LOG4CXX_EXPORT LoggerFactory : public virtual helpers::Object
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(LoggerFactory)
+ virtual ~LoggerFactory() {}
+ virtual LoggerPtr makeNewLoggerInstance(
+ log4cxx::helpers::Pool& pool,
+ const LogString& name) const = 0;
+ };
+
+
+ } // namespace spi
+} // namesapce log4cxx
+
+#endif //_LOG4CXX_SPI_LOGGERFACTORY_H
diff --git a/src/main/include/log4cxx/spi/loggerrepository.h b/src/main/include/log4cxx/spi/loggerrepository.h
new file mode 100644
index 0000000..4fe7957
--- /dev/null
+++ b/src/main/include/log4cxx/spi/loggerrepository.h
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_LOG_REPOSITORY_H
+#define _LOG4CXX_SPI_LOG_REPOSITORY_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#include <log4cxx/appender.h>
+#include <log4cxx/spi/loggerfactory.h>
+#include <log4cxx/level.h>
+#include <log4cxx/spi/hierarchyeventlistener.h>
+
+namespace log4cxx
+{
+ namespace spi
+ {
+
+ /**
+ A <code>LoggerRepository</code> is used to create and retrieve
+ <code>Loggers</code>. The relation between loggers in a repository
+ depends on the repository but typically loggers are arranged in a
+ named hierarchy.
+
+ <p>In addition to the creational methods, a
+ <code>LoggerRepository</code> can be queried for existing loggers,
+ can act as a point of registry for events related to loggers.
+ */
+ class LOG4CXX_EXPORT LoggerRepository : public virtual helpers::Object
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(LoggerRepository)
+ virtual ~LoggerRepository() {}
+
+ /**
+ Add a {@link spi::HierarchyEventListener HierarchyEventListener}
+ event to the repository.
+ */
+ virtual void addHierarchyEventListener(const HierarchyEventListenerPtr&
+ listener) = 0;
+ /**
+ Is the repository disabled for a given level? The answer depends
+ on the repository threshold and the <code>level</code>
+ parameter. See also #setThreshold method. */
+ virtual bool isDisabled(int level) const = 0;
+
+ /**
+ Set the repository-wide threshold. All logging requests below the
+ threshold are immediately dropped. By default, the threshold is
+ set to <code>Level::getAll()</code> which has the lowest possible rank. */
+ virtual void setThreshold(const LevelPtr& level) = 0;
+
+ /**
+ Another form of {@link #setThreshold(const LevelPtr&)
+ setThreshold} accepting a string
+ parameter instead of a <code>Level</code>. */
+ virtual void setThreshold(const LogString& val) = 0;
+
+ virtual void emitNoAppenderWarning(const LoggerPtr& logger) = 0;
+
+ /**
+ Get the repository-wide threshold. See {@link
+ #setThreshold(const LevelPtr&) setThreshold}
+ for an explanation. */
+ virtual const LevelPtr& getThreshold() const = 0;
+
+ virtual LoggerPtr getLogger(const LogString& name) = 0;
+
+ virtual LoggerPtr getLogger(const LogString& name,
+ const spi::LoggerFactoryPtr& factory) = 0;
+
+ virtual LoggerPtr getRootLogger() const = 0;
+
+ virtual LoggerPtr exists(const LogString& name) = 0;
+
+ virtual void shutdown() = 0;
+
+ virtual LoggerList getCurrentLoggers() const = 0;
+
+ virtual void fireAddAppenderEvent(const LoggerPtr& logger,
+ const AppenderPtr& appender) = 0;
+
+ virtual void resetConfiguration() = 0;
+
+ virtual bool isConfigured() = 0;
+ virtual void setConfigured(bool configured) = 0;
+
+ }; // class LoggerRepository
+
+ } // namespace spi
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+
+#endif //_LOG4CXX_SPI_LOG_REPOSITORY_H
diff --git a/src/main/include/log4cxx/spi/loggingevent.h b/src/main/include/log4cxx/spi/loggingevent.h
new file mode 100644
index 0000000..25f5c0d
--- /dev/null
+++ b/src/main/include/log4cxx/spi/loggingevent.h
@@ -0,0 +1,263 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_LOGGING_EVENT_H
+#define _LOG4CXX_SPI_LOGGING_EVENT_H
+
+#if defined(_MSC_VER)
+#pragma warning (push)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/logstring.h>
+#include <time.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/mdc.h>
+#include <log4cxx/spi/location/locationinfo.h>
+#include <vector>
+
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class ObjectOutputStream;
+ }
+
+ namespace spi
+ {
+
+ /**
+ The internal representation of logging events. When an affirmative
+ decision is made to log then a <code>LoggingEvent</code> instance
+ is created. This instance is passed around to the different log4cxx
+ components.
+
+ <p>This class is of concern to those wishing to extend log4cxx.
+ */
+ class LOG4CXX_EXPORT LoggingEvent :
+ public virtual helpers::ObjectImpl
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(LoggingEvent)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(LoggingEvent)
+ END_LOG4CXX_CAST_MAP()
+
+ /** For serialization only
+ */
+ LoggingEvent();
+
+ /**
+ Instantiate a LoggingEvent from the supplied parameters.
+
+ <p>Except timeStamp all the other fields of
+ <code>LoggingEvent</code> are filled when actually needed.
+ <p>
+ @param logger The logger of this event.
+ @param level The level of this event.
+ @param message The message of this event.
+ @param location location of logging request.
+ */
+ LoggingEvent(const LogString& logger,
+ const LevelPtr& level, const LogString& message,
+ const log4cxx::spi::LocationInfo& location);
+
+ ~LoggingEvent();
+
+ /** Return the level of this event. */
+ inline const LevelPtr& getLevel() const
+ { return level; }
+
+ /** Return the name of the logger. */
+ inline const LogString& getLoggerName() const {
+ return logger;
+ }
+
+ /** Return the message for this logging event. */
+ inline const LogString& getMessage() const
+ { return message; }
+
+ /** Return the message for this logging event. */
+ inline const LogString& getRenderedMessage() const
+ { return message; }
+
+ /**Returns the time when the application started,
+ in seconds elapsed since 01.01.1970.
+ */
+ static log4cxx_time_t getStartTime();
+
+ /** Return the threadName of this event. */
+ inline const LogString& getThreadName() const {
+ return threadName;
+ }
+
+ /** Return the timeStamp of this event. */
+ inline log4cxx_time_t getTimeStamp() const
+ { return timeStamp; }
+
+ /* Return the file where this log statement was written. */
+ inline const log4cxx::spi::LocationInfo& getLocationInformation() const
+ { return locationInfo; }
+
+ /**
+ * This method appends the NDC for this event to passed string. It will return the
+ * correct content even if the event was generated in a different
+ * thread or even on a different machine. The NDC#get method
+ * should <em>never</em> be called directly.
+ *
+ * @param dest destination for NDC, unchanged if NDC is not set.
+ * @return true if NDC is set.
+ */
+ bool getNDC(LogString& dest) const;
+
+ /**
+ * Writes the content of the LoggingEvent
+ * in a format compatible with log4j's serialized form.
+ */
+ void write(helpers::ObjectOutputStream& os, helpers::Pool& p) const;
+
+ /**
+ * Appends the the context corresponding to the <code>key</code> parameter.
+ * If there is a local MDC copy, possibly because we are in a logging
+ * server or running inside AsyncAppender, then we search for the key in
+ * MDC copy, if a value is found it is returned. Otherwise, if the search
+ * in MDC copy returns an empty result, then the current thread's
+ * <code>MDC</code> is used.
+ *
+ * <p>
+ * Note that <em>both</em> the local MDC copy and the current thread's MDC
+ * are searched.
+ * </p>
+ * @param key key.
+ * @param dest string to which value, if any, is appended.
+ * @return true if key had a corresponding value.
+ */
+ bool getMDC(const LogString& key, LogString& dest) const;
+
+ LOG4CXX_LIST_DEF(KeySet, LogString);
+ /**
+ * Returns the set of of the key values in the MDC for the event.
+ * The returned set is unmodifiable by the caller.
+ *
+ * @return Set an unmodifiable set of the MDC keys.
+ *
+ */
+ KeySet getMDCKeySet() const;
+
+ /**
+ Obtain a copy of this thread's MDC prior to serialization
+ or asynchronous logging.
+ */
+ void getMDCCopy() const;
+
+ /**
+ * Return a previously set property.
+ * @param key key.
+ * @param dest string to which value, if any, is appended.
+ * @return true if key had a corresponding value.
+ */
+ bool getProperty(const LogString& key, LogString& dest) const;
+ /**
+ * Returns the set of of the key values in the properties
+ * for the event. The returned set is unmodifiable by the caller.
+ *
+ * @return Set an unmodifiable set of the property keys.
+ */
+ KeySet getPropertyKeySet() const;
+
+ /**
+ * Set a string property using a key and a string value. since 1.3
+ */
+ void setProperty(const LogString& key, const LogString& value);
+
+ private:
+ /**
+ * The logger of the logging event.
+ **/
+ LogString logger;
+
+ /** level of logging event. */
+ LevelPtr level;
+
+ /** The nested diagnostic context (NDC) of logging event. */
+ mutable LogString* ndc;
+
+ /** The mapped diagnostic context (MDC) of logging event. */
+ mutable MDC::Map* mdcCopy;
+
+ /**
+ * A map of String keys and String values.
+ */
+ std::map<LogString, LogString> * properties;
+
+ /** Have we tried to do an NDC lookup? If we did, there is no need
+ * to do it again. Note that its value is always false when
+ * serialized. Thus, a receiving SocketNode will never use it's own
+ * (incorrect) NDC. See also writeObject method.
+ */
+ mutable bool ndcLookupRequired;
+
+ /**
+ * Have we tried to do an MDC lookup? If we did, there is no need to do it
+ * again. Note that its value is always false when serialized. See also
+ * the getMDC and getMDCCopy methods.
+ */
+ mutable bool mdcCopyLookupRequired;
+
+ /** The application supplied message of logging event. */
+ LogString message;
+
+
+ /** The number of milliseconds elapsed from 1/1/1970 until logging event
+ was created. */
+ log4cxx_time_t timeStamp;
+
+ /** The is the location where this log statement was written. */
+ const log4cxx::spi::LocationInfo locationInfo;
+
+
+ /** The identifier of thread in which this logging event
+ was generated.
+ */
+ const LogString threadName;
+
+ //
+ // prevent copy and assignment
+ //
+ LoggingEvent(const LoggingEvent&);
+ LoggingEvent& operator=(const LoggingEvent&);
+ static const LogString getCurrentThreadName();
+
+ static void writeProlog(log4cxx::helpers::ObjectOutputStream& os, log4cxx::helpers::Pool& p);
+
+ };
+
+ LOG4CXX_PTR_DEF(LoggingEvent);
+ LOG4CXX_LIST_DEF(LoggingEventList, LoggingEventPtr);
+ }
+}
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+
+#endif //_LOG4CXX_SPI_LOGGING_EVENT_H
diff --git a/src/main/include/log4cxx/spi/optionhandler.h b/src/main/include/log4cxx/spi/optionhandler.h
new file mode 100644
index 0000000..88cd954
--- /dev/null
+++ b/src/main/include/log4cxx/spi/optionhandler.h
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_OPTION_HANDLER_H
+#define _LOG4CXX_SPI_OPTION_HANDLER_H
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/object.h>
+#include <log4cxx/helpers/objectptr.h>
+
+namespace log4cxx
+{
+ namespace spi
+ {
+ class OptionHandler;
+ typedef helpers::ObjectPtrT<OptionHandler> OptionHandlerPtr;
+
+ /**
+ A string based interface to configure package components.
+ */
+ class LOG4CXX_EXPORT OptionHandler : public virtual helpers::Object
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(OptionHandler)
+ virtual ~OptionHandler() {}
+
+ /**
+ Activate the options that were previously set with calls to option
+ setters.
+
+ <p>This allows to defer activiation of the options until all
+ options have been set. This is required for components which have
+ related options that remain ambigous until all are set.
+
+ <p>For example, the FileAppender has the {@link
+ FileAppender#setFile File} and {@link
+ FileAppender#setAppend Append} options both of
+ which are ambigous until the other is also set. */
+ virtual void activateOptions(log4cxx::helpers::Pool& p) = 0;
+
+
+ /**
+ Set <code>option</code> to <code>value</code>.
+
+ <p>The handling of each option depends on the OptionHandler
+ instance. Some options may become active immediately whereas
+ other may be activated only when #activateOptions is
+ called.
+ */
+ virtual void setOption(const LogString& option,
+ const LogString& value) = 0;
+
+ }; // class OptionConverter
+ } // namespace spi
+} // namespace log4cxx
+
+
+#endif //_LOG4CXX_SPI_OPTION_HANDLER_H
diff --git a/src/main/include/log4cxx/spi/repositoryselector.h b/src/main/include/log4cxx/spi/repositoryselector.h
new file mode 100644
index 0000000..1d1bf0c
--- /dev/null
+++ b/src/main/include/log4cxx/spi/repositoryselector.h
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_REPOSITORY_SELECTOR_H
+#define _LOG4CXX_SPI_REPOSITORY_SELECTOR_H
+
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/helpers/object.h>
+
+namespace log4cxx
+{
+ namespace spi
+ {
+ class LoggerRepository;
+ typedef helpers::ObjectPtrT<LoggerRepository> LoggerRepositoryPtr;
+
+ /**
+ The <code>LogManager</code> uses one (and only one)
+ <code>RepositorySelector</code> implementation to select the
+ {@link log4cxx::spi::LoggerRepository LoggerRepository}
+ for a particular application context.
+
+ <p>It is the responsability of the <code>RepositorySelector</code>
+ implementation to track the application context. log4cxx makes no
+ assumptions about the application context or on its management.
+
+ <p>See also LogManager.
+ */
+ class LOG4CXX_EXPORT RepositorySelector : public virtual helpers::Object
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(RepositorySelector)
+ virtual ~RepositorySelector() {}
+ virtual LoggerRepositoryPtr& getLoggerRepository() = 0;
+ };
+ LOG4CXX_PTR_DEF(RepositorySelector);
+ } //namespace spi
+} //namespace log4cxx
+
+#endif //_LOG4CXX_SPI_REPOSITORY_SELECTOR_H
diff --git a/src/main/include/log4cxx/spi/rootlogger.h b/src/main/include/log4cxx/spi/rootlogger.h
new file mode 100644
index 0000000..5027385
--- /dev/null
+++ b/src/main/include/log4cxx/spi/rootlogger.h
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_ROOT_LOGGER_H
+#define _LOG4CXX_SPI_ROOT_LOGGER_H
+
+#include <log4cxx/logger.h>
+
+namespace log4cxx
+{
+ namespace spi
+ {
+ /**
+ RootLogger sits at the top of the logger hierachy. It is a
+ regular logger except that it provides several guarantees.
+
+ <p>First, it cannot be assigned a null
+ level. Second, since root logger cannot have a parent, the
+ #getEffectiveLevel method always returns the value of the
+ level field without walking the hierarchy.
+ */
+ class LOG4CXX_EXPORT RootLogger : public Logger
+ {
+ public:
+ /**
+ The root logger names itself as "root". However, the root
+ logger cannot be retrieved by name.
+ */
+ RootLogger(log4cxx::helpers::Pool& pool, const LevelPtr& level);
+
+ /**
+ Return the assigned level value without walking the logger
+ hierarchy.
+ */
+ virtual const LevelPtr& getEffectiveLevel() const;
+
+ /**
+ Setting a null value to the level of the root logger may have catastrophic
+ results. We prevent this here.
+ */
+ void setLevel(const LevelPtr& level);
+ };
+ } // namespace spi
+} // namespace log4cxx
+
+#endif //_LOG4CXX_SPI_ROOT_LOGGER_H
diff --git a/src/main/include/log4cxx/spi/triggeringeventevaluator.h b/src/main/include/log4cxx/spi/triggeringeventevaluator.h
new file mode 100644
index 0000000..3c6b054
--- /dev/null
+++ b/src/main/include/log4cxx/spi/triggeringeventevaluator.h
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_SPI_TRIGGERING_EVENT_EVALUATOR_H
+#define _LOG4CXX_SPI_TRIGGERING_EVENT_EVALUATOR_H
+
+#include <log4cxx/spi/loggingevent.h>
+
+namespace log4cxx
+{
+ namespace spi
+ {
+ /**
+ Implementions of this interface allow certain appenders to decide
+ when to perform an appender specific action.
+
+ <p>For example the {@link net::SMTPAppender SMTPAppender} sends
+ an email when the #isTriggeringEvent method returns
+ <code>true</code> and adds the event to an internal buffer when the
+ returned result is <code>false</code>.
+
+ */
+ class LOG4CXX_EXPORT TriggeringEventEvaluator : public virtual helpers::Object
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(TriggeringEventEvaluator)
+ /**
+ Is this the triggering event?
+ */
+ virtual bool isTriggeringEvent(const spi::LoggingEventPtr& event) = 0;
+ };
+ LOG4CXX_PTR_DEF(TriggeringEventEvaluator);
+ }
+}
+
+#endif // _LOG4CXX_SPI_TRIGGERING_EVENT_EVALUATOR_H
diff --git a/src/main/include/log4cxx/stream.h b/src/main/include/log4cxx/stream.h
new file mode 100644
index 0000000..8edec0d
--- /dev/null
+++ b/src/main/include/log4cxx/stream.h
@@ -0,0 +1,566 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_STREAM_H
+#define _LOG4CXX_STREAM_H
+
+#include <log4cxx/logger.h>
+#include <sstream>
+#include <log4cxx/spi/location/locationinfo.h>
+
+namespace log4cxx
+{
+
+ /**
+ * Base class for the basic_logstream template which attempts
+ * to emulate std::basic_ostream but attempts to short-circuit
+ * unnecessary operations.
+ *
+ * The logstream has a logger and level that are used for logging
+ * requests. The level of the stream is compared against the
+ * current level of the logger to determine if the request should be processed.
+ */
+ class LOG4CXX_EXPORT logstream_base {
+ public:
+ /**
+ * Create new instance.
+ * @param logger logger logger used in log requests.
+ * @param level indicates level that will be used in log requests. Can
+ * be modified later by inserting a level or calling setLevel.
+ */
+ logstream_base(const log4cxx::LoggerPtr& logger,
+ const log4cxx::LevelPtr& level);
+ /**
+ * Destructor.
+ */
+ virtual ~logstream_base();
+ /**
+ * Insertion operator for std::fixed and similar manipulators.
+ */
+ void insert(std::ios_base& (*manip)(std::ios_base&));
+
+ /**
+ * get precision.
+ */
+ int precision();
+ /**
+ * get width.
+ */
+ int width();
+ /**
+ * set precision. This should be used in preference to inserting an std::setprecision(n)
+ * since the other requires construction of an STL stream which may be expensive.
+ */
+ int precision(int newval);
+ /**
+ * set width. This should be used in preference to inserting an std::setw(n)
+ * since the other requires construction of an STL stream which may be expensive.
+ */
+ int width(int newval);
+ /**
+ * Get fill character.
+ */
+ int fill();
+ /**
+ * Set fill character.
+ */
+ int fill(int newval);
+
+ /**
+ * Set flags. see std::ios_base.
+ */
+ std::ios_base::fmtflags flags(std::ios_base::fmtflags newflags);
+ /**
+ * Set flags. see std::ios_base.
+ */
+ std::ios_base::fmtflags setf(std::ios_base::fmtflags newflags, std::ios_base::fmtflags mask);
+ /**
+ * Set flags. see std::ios_base.
+ */
+ std::ios_base::fmtflags setf(std::ios_base::fmtflags newflags);
+
+
+ /**
+ * end of message manipulator, triggers logging.
+ */
+ static logstream_base& endmsg(logstream_base&);
+
+ /**
+ * no-operation manipulator, Used to avoid ambiguity with VC6.
+ */
+ static logstream_base& nop(logstream_base&);
+
+ /**
+ * end of message action.
+ */
+ void end_message();
+
+
+
+ /**
+ * Set the level.
+ * @param level level
+ */
+ void setLevel(const LevelPtr& level);
+ /**
+ * Returns true if the current level is the same or high as the
+ * level of logger at time of construction or last setLevel.
+ */
+ inline bool isEnabled() const {
+ return enabled;
+ }
+
+ /**
+ * Returns if logger is currently enabled for the specified level.
+ */
+ bool isEnabledFor(const LevelPtr& level) const;
+
+ /**
+ * Sets the location for subsequent log requests.
+ */
+ void setLocation(const log4cxx::spi::LocationInfo& location);
+
+ /**
+ * Sets the state of the embedded stream (if any)
+ * to the state of the formatting info.
+ * @param os stream to receive formatting info.
+ * @param fillchar receives fill charater.
+ * @return true if fill character was specified.
+ */
+ bool set_stream_state(std::ios_base& os, int& fillchar);
+
+ protected:
+ /**
+ * Dispatches the pending log request.
+ */
+ virtual void log(LoggerPtr& logger,
+ const LevelPtr& level,
+ const log4cxx::spi::LocationInfo& location) = 0;
+ /**
+ * Erase any content in the message construction buffer.
+ */
+ virtual void erase() = 0;
+ /**
+ * Copy state of embedded stream (if any)
+ * to value and mask instances of std::ios_base
+ * and return fill character value.
+ */
+ virtual void get_stream_state(std::ios_base& base,
+ std::ios_base& mask,
+ int& fill,
+ bool& fillSet) const = 0;
+ virtual void refresh_stream_state() = 0;
+
+ private:
+ /**
+ * prevent copy constructor.
+ */
+ logstream_base(logstream_base&);
+ /**
+ * prevent copy operatpr.
+ */
+ logstream_base& operator=(logstream_base&);
+ /**
+ * Minimal extension of std::ios_base to allow creation
+ * of embedded IO states.
+ */
+ class LOG4CXX_EXPORT logstream_ios_base : public std::ios_base {
+ public:
+ logstream_ios_base(std::ios_base::fmtflags initval,
+ int initsize);
+ } initset, initclear;
+ /**
+ * fill character.
+ */
+ int fillchar;
+ /**
+ * true if fill character is set.
+ */
+ bool fillset;
+ /**
+ * true if assigned level was same or higher than level of associated logger.
+ */
+ bool enabled;
+ /**
+ * associated logger.
+ */
+ log4cxx::LoggerPtr logger;
+ /**
+ * associated level.
+ */
+ log4cxx::LevelPtr level;
+ /**
+ * associated level.
+ */
+ log4cxx::spi::LocationInfo location;
+ };
+
+ typedef logstream_base& (*logstream_manipulator)(logstream_base&);
+
+ /**
+ * An STL-like stream API for log4cxx using char as the character type.
+ *. Instances of log4cxx::logstream
+ * are not designedfor use by multiple threads and in general should be short-lived
+ * function scoped objects. Using log4cxx::basic_logstream as a class member or
+ * static instance should be avoided in the same manner as you would avoid placing a std::ostringstream
+ * in those locations. Insertion operations are generally short-circuited if the
+ * level for the stream is not the same of higher that the level of the associated logger.
+ */
+ class LOG4CXX_EXPORT logstream : public logstream_base {
+ typedef char Ch;
+ public:
+ /**
+ * Constructor.
+ */
+ logstream(const log4cxx::LoggerPtr& logger,
+ const log4cxx::LevelPtr& level);
+
+ /**
+ * Constructor.
+ */
+ logstream(const Ch* loggerName,
+ const log4cxx::LevelPtr& level);
+
+ /**
+ * Constructor.
+ */
+ logstream(const std::basic_string<Ch>& loggerName,
+ const log4cxx::LevelPtr& level);
+
+ ~logstream();
+
+ /**
+ * Insertion operator for std::fixed and similar manipulators.
+ */
+ logstream& operator<<(std::ios_base& (*manip)(std::ios_base&));
+
+ /**
+ * Insertion operator for logstream_base::endmsg.
+ */
+ logstream& operator<<(logstream_manipulator manip);
+
+ /**
+ * Insertion operator for level.
+ */
+ logstream& operator<<(const log4cxx::LevelPtr& level);
+ /**
+ * Insertion operator for location.
+ */
+ logstream& operator<<(const log4cxx::spi::LocationInfo& location);
+
+ /**
+ * Alias for insertion operator for location. Kludge to avoid
+ * inappropriate compiler ambiguity.
+ */
+ logstream& operator>>(const log4cxx::spi::LocationInfo& location);
+
+ /**
+ * Cast operator to provide access to embedded std::basic_ostream.
+ */
+ operator std::basic_ostream<Ch>&();
+
+#if !(LOG4CXX_USE_GLOBAL_SCOPE_TEMPLATE)
+ /**
+ * Template to allow any class with an std::basic_ostream inserter
+ * to be applied to this class.
+ */
+ template <class V>
+ inline log4cxx::logstream& operator<<(const V& val) {
+ if (LOG4CXX_UNLIKELY(isEnabled())) {
+ ((std::basic_ostream<char>&) *this) << val;
+ }
+ return *this;
+ }
+#endif
+
+
+ protected:
+ virtual void log(LoggerPtr& logger,
+ const LevelPtr& level,
+ const log4cxx::spi::LocationInfo& location);
+
+ virtual void erase();
+
+ virtual void get_stream_state(std::ios_base& base,
+ std::ios_base& mask,
+ int& fill,
+ bool& fillSet) const;
+ virtual void refresh_stream_state();
+
+
+ private:
+ logstream(const logstream&);
+ logstream& operator=(const logstream&);
+ std::basic_stringstream<Ch>* stream;
+
+ };
+
+#if LOG4CXX_WCHAR_T_API
+ /**
+ * An STL-like stream API for log4cxx using wchar_t as the character type.
+ *. Instances of log4cxx::logstream
+ * are not designedfor use by multiple threads and in general should be short-lived
+ * function scoped objects. Using log4cxx::basic_logstream as a class member or
+ * static instance should be avoided in the same manner as you would avoid placing a std::ostringstream
+ * in those locations. Insertion operations are generally short-circuited if the
+ * level for the stream is not the same of higher that the level of the associated logger.
+ */
+ class LOG4CXX_EXPORT wlogstream : public logstream_base {
+ typedef wchar_t Ch;
+ public:
+ /**
+ * Constructor.
+ */
+ wlogstream(const log4cxx::LoggerPtr& logger,
+ const log4cxx::LevelPtr& level);
+
+ /**
+ * Constructor.
+ */
+ wlogstream(const Ch* loggerName,
+ const log4cxx::LevelPtr& level);
+
+ /**
+ * Constructor.
+ */
+ wlogstream(const std::basic_string<Ch>& loggerName,
+ const log4cxx::LevelPtr& level);
+
+ ~wlogstream();
+
+ /**
+ * Insertion operator for std::fixed and similar manipulators.
+ */
+ wlogstream& operator<<(std::ios_base& (*manip)(std::ios_base&));
+
+ /**
+ * Insertion operator for logstream_base::endmsg.
+ */
+ wlogstream& operator<<(logstream_manipulator manip);
+
+ /**
+ * Insertion operator for level.
+ */
+ wlogstream& operator<<(const log4cxx::LevelPtr& level);
+ /**
+ * Insertion operator for location.
+ */
+ wlogstream& operator<<(const log4cxx::spi::LocationInfo& location);
+
+ /**
+ * Alias for insertion operator for location. Kludge to avoid
+ * inappropriate compiler ambiguity.
+ */
+ wlogstream& operator>>(const log4cxx::spi::LocationInfo& location);
+
+
+ /**
+ * Cast operator to provide access to embedded std::basic_ostream.
+ */
+ operator std::basic_ostream<Ch>&();
+
+#if !(LOG4CXX_USE_GLOBAL_SCOPE_TEMPLATE)
+ /**
+ * Template to allow any class with an std::basic_ostream inserter
+ * to be applied to this class.
+ */
+ template <class V>
+ inline log4cxx::wlogstream& operator<<(const V& val) {
+ if (LOG4CXX_UNLIKELY(isEnabled())) {
+ ((std::basic_ostream<wchar_t>&) *this) << val;
+ }
+ return *this;
+ }
+#endif
+
+ protected:
+ virtual void log(LoggerPtr& logger,
+ const LevelPtr& level,
+ const log4cxx::spi::LocationInfo& location);
+
+ virtual void erase();
+
+ virtual void get_stream_state(std::ios_base& base,
+ std::ios_base& mask,
+ int& fill,
+ bool& fillSet) const;
+ virtual void refresh_stream_state();
+
+
+ private:
+ wlogstream(const wlogstream&);
+ wlogstream& operator=(const wlogstream&);
+ std::basic_stringstream<Ch>* stream;
+
+ };
+#endif
+
+#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+ /**
+ * An STL-like stream API for log4cxx using UniChar as the character type.
+ *. Instances of log4cxx::logstream
+ * are not designedfor use by multiple threads and in general should be short-lived
+ * function scoped objects. Using log4cxx::basic_logstream as a class member or
+ * static instance should be avoided in the same manner as you would avoid placing a std::ostringstream
+ * in those locations. Insertion operations are generally short-circuited if the
+ * level for the stream is not the same of higher that the level of the associated logger.
+ */
+ class LOG4CXX_EXPORT ulogstream : public logstream_base {
+ typedef UniChar Ch;
+ public:
+ /**
+ * Constructor.
+ */
+ ulogstream(const log4cxx::LoggerPtr& logger,
+ const log4cxx::LevelPtr& level);
+
+#if LOG4CXX_UNICHAR_API
+ /**
+ * Constructor.
+ */
+ ulogstream(const Ch* loggerName,
+ const log4cxx::LevelPtr& level);
+
+ /**
+ * Constructor.
+ */
+ ulogstream(const std::basic_string<Ch>& loggerName,
+ const log4cxx::LevelPtr& level);
+#endif
+
+#if LOG4CXX_CFSTRING_API
+ ulogstream(const CFStringRef& loggerName,
+ const log4cxx::LevelPtr& level);
+#endif
+
+ ~ulogstream();
+
+ /**
+ * Insertion operator for std::fixed and similar manipulators.
+ */
+ ulogstream& operator<<(std::ios_base& (*manip)(std::ios_base&));
+
+ /**
+ * Insertion operator for logstream_base::endmsg.
+ */
+ ulogstream& operator<<(logstream_manipulator manip);
+
+ /**
+ * Insertion operator for level.
+ */
+ ulogstream& operator<<(const log4cxx::LevelPtr& level);
+ /**
+ * Insertion operator for location.
+ */
+ ulogstream& operator<<(const log4cxx::spi::LocationInfo& location);
+
+ /**
+ * Alias for insertion operator for location. Kludge to avoid
+ * inappropriate compiler ambiguity.
+ */
+ ulogstream& operator>>(const log4cxx::spi::LocationInfo& location);
+
+
+ /**
+ * Cast operator to provide access to embedded std::basic_ostream.
+ */
+ operator std::basic_ostream<Ch>&();
+
+#if !(LOG4CXX_USE_GLOBAL_SCOPE_TEMPLATE)
+ /**
+ * Template to allow any class with an std::basic_ostream inserter
+ * to be applied to this class.
+ */
+ template <class V>
+ inline ulogstream& operator<<(const V& val) {
+ if (LOG4CXX_UNLIKELY(isEnabled())) {
+ ((std::basic_ostream<Ch>&) *this) << val;
+ }
+ return *this;
+ }
+#endif
+
+ protected:
+ virtual void log(LoggerPtr& logger,
+ const LevelPtr& level,
+ const log4cxx::spi::LocationInfo& location);
+
+ virtual void erase();
+
+ virtual void get_stream_state(std::ios_base& base,
+ std::ios_base& mask,
+ int& fill,
+ bool& fillSet) const;
+ virtual void refresh_stream_state();
+
+
+ private:
+ ulogstream(const ulogstream&);
+ ulogstream& operator=(const ulogstream&);
+ std::basic_stringstream<Ch>* stream;
+
+ };
+#endif
+
+
+} // namespace log4cxx
+
+
+#if LOG4CXX_USE_GLOBAL_SCOPE_TEMPLATE
+//
+// VC6 will fail to compile if class-scope templates
+// are used to handle arbitrary insertion operations.
+// However, using global namespace insertion operations
+// run into LOGCXX-150.
+
+/**
+ * Template to allow any class with an std::basic_ostream inserter
+ * to be applied to this class.
+ */
+template <class V>
+inline log4cxx::logstream& operator<<(log4cxx::logstream& os, const V& val) {
+ if (LOG4CXX_UNLIKELY(os.isEnabled())) {
+ ((std::basic_ostream<char>&) os) << val;
+ }
+ return os;
+}
+
+#if LOG4CXX_WCHAR_T_API
+/**
+ * Template to allow any class with an std::basic_ostream inserter
+ * to be applied to this class.
+ */
+template <class V>
+inline log4cxx::wlogstream& operator<<(log4cxx::wlogstream& os, const V& val) {
+ if (LOG4CXX_UNLIKELY(os.isEnabled())) {
+ ((std::basic_ostream<wchar_t>&) os) << val;
+ }
+ return os;
+}
+#endif
+#endif
+
+#if !defined(LOG4CXX_ENDMSG)
+#if LOG4CXX_LOGSTREAM_ADD_NOP
+#define LOG4CXX_ENDMSG (log4cxx::logstream_manipulator) log4cxx::logstream_base::nop >> LOG4CXX_LOCATION << (log4cxx::logstream_manipulator) log4cxx::logstream_base::endmsg
+#else
+#define LOG4CXX_ENDMSG LOG4CXX_LOCATION << (log4cxx::logstream_manipulator) log4cxx::logstream_base::endmsg
+#endif
+#endif
+
+
+#endif //_LOG4CXX_STREAM_H
diff --git a/src/main/include/log4cxx/ttcclayout.h b/src/main/include/log4cxx/ttcclayout.h
new file mode 100644
index 0000000..8c14d65
--- /dev/null
+++ b/src/main/include/log4cxx/ttcclayout.h
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TTCC_LAYOUT_H
+#define _LOG4CXX_TTCC_LAYOUT_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/helpers/datelayout.h>
+
+namespace log4cxx
+{
+
+ /**
+ TTCC layout format consists of time, thread, logger name and nested
+ diagnostic context information, hence the name.
+
+ <p>Each of the four fields can be individually enabled or
+ disabled. The time format depends on the <code>DateFormat</code>
+ used.
+
+ <p>Here is an example TTCCLayout output with the
+ {@link helpers::RelativeTimeDateFormat RelativeTimeDateFormat}.
+
+ <pre>
+ 176 [main] INFO examples.Sort - Populating an array of 2 elements in reverse order.
+ 225 [main] INFO examples.SortAlgo - Entered the sort method.
+ 262 [main] DEBUG examples.SortAlgo.OUTER i=1 - Outer loop.
+ 276 [main] DEBUG examples.SortAlgo.SWAP i=1 j=0 - Swapping intArray[0] = 1 and intArray[1] = 0
+ 290 [main] DEBUG examples.SortAlgo.OUTER i=0 - Outer loop.
+ 304 [main] INFO examples.SortAlgo.DUMP - Dump of interger array:
+ 317 [main] INFO examples.SortAlgo.DUMP - Element [0] = 0
+ 331 [main] INFO examples.SortAlgo.DUMP - Element [1] = 1
+ 343 [main] INFO examples.Sort - The next log statement should be an error message.
+ 346 [main] ERROR examples.SortAlgo.DUMP - Tried to dump an uninitialized array.
+ 467 [main] INFO examples.Sort - Exiting main method.
+ </pre>
+
+ <p>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 level, the fourth field is
+ the logger to which the statement belongs.
+
+ <p>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.
+
+ <p><b>WARNING</b> Do not use the same TTCCLayout instance from
+ within different appenders. The TTCCLayout is not thread safe when
+ used in his way. However, it is perfectly safe to use a TTCCLayout
+ instance from just one appender.
+
+ <p>PatternLayout offers a much more flexible alternative.
+ */
+ class LOG4CXX_EXPORT TTCCLayout : public helpers::DateLayout
+ {
+ private:
+ // Internal representation of options
+ bool threadPrinting;
+ bool categoryPrefixing;
+ bool contextPrinting;
+ bool filePrinting;
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(TTCCLayout)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(TTCCLayout)
+ LOG4CXX_CAST_ENTRY_CHAIN(Layout)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ Instantiate a TTCCLayout object with {@link
+ helpers::RelativeTimeDateFormat RelativeTimeDateFormat} as the date
+ formatter in the local time zone.
+ */
+ TTCCLayout();
+
+ /**
+ Instantiate a TTCCLayout object using the local time zone. The
+ DateFormat used will depend on the <code>dateFormatType</code>.
+ <p>This constructor just calls the {@link
+ helpers::DateLayout#setDateFormat DateLayout::setDateFormat} method.
+ */
+ TTCCLayout(const LogString& dateFormatType);
+
+ /**
+ The <b>ThreadPrinting</b> option specifies whether the name of the
+ current thread is part of log output or not. This is true by default.
+ */
+ inline void setThreadPrinting(bool threadPrinting1)
+ { this->threadPrinting = threadPrinting1; }
+
+ /**
+ Returns value of the <b>ThreadPrinting</b> option.
+ */
+ inline bool getThreadPrinting() const
+ { return threadPrinting; }
+
+ /**
+ The <b>CategoryPrefixing</b> option specifies whether Logger
+ name is part of log output or not. This is true by default.
+ */
+ inline void setCategoryPrefixing(bool categoryPrefixing1)
+ { this->categoryPrefixing = categoryPrefixing1; }
+
+ /**
+ Returns value of the <b>CategoryPrefixing</b> option.
+ */
+ inline bool getCategoryPrefixing() const
+ { return categoryPrefixing; }
+
+ /**
+ The <b>ContextPrinting</b> option specifies log output will include
+ the nested context information belonging to the current thread.
+ This is true by default.
+ */
+ inline void setContextPrinting(bool contextPrinting1)
+ { this->contextPrinting = contextPrinting1; }
+
+ /**
+ Returns value of the <b>ContextPrinting</b> option.
+ */
+ inline bool getContextPrinting() const
+ { return contextPrinting; }
+
+ /**
+ The <b>FilePrinting</b> option specifies log output will include
+ the file and the line where the log statement was written.
+ */
+ inline void setFilePrinting(bool filePrinting1)
+ { this->filePrinting = filePrinting1; }
+
+ /**
+ Returns value of the <b>ContextPrinting</b> option.
+ */
+ inline bool getFilePrinting() const
+ { return filePrinting; }
+
+ /**
+ In addition to the level of the statement and message, this function
+ writes to the ouput stream time, thread, logger and NDC
+ information.
+
+ <p>Time, thread, logger and diagnostic context are printed
+ depending on options.
+
+ @param output destination to receive formatted output.
+ @param event event to format.
+ @param pool pool used to allocate memory needed during formatting.
+ */
+ virtual void format(LogString& output,
+ const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool) const;
+
+ /**
+ The TTCCLayout does not handle the throwable contained within
+ {@link spi::LoggingEvent LoggingEvents}. Thus, it returns
+ <code>true</code>.
+ */
+ virtual bool ignoresThrowable() const { return true; }
+ };
+ LOG4CXX_PTR_DEF(TTCCLayout);
+}
+
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif
diff --git a/src/main/include/log4cxx/varia/Makefile.am b/src/main/include/log4cxx/varia/Makefile.am
new file mode 100644
index 0000000..de87f54
--- /dev/null
+++ b/src/main/include/log4cxx/varia/Makefile.am
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+variaincdir = $(includedir)/log4cxx/varia
+variainc_HEADERS= $(top_srcdir)/src/main/include/log4cxx/varia/*.h
+
diff --git a/src/main/include/log4cxx/varia/fallbackerrorhandler.h b/src/main/include/log4cxx/varia/fallbackerrorhandler.h
new file mode 100644
index 0000000..63b6fc8
--- /dev/null
+++ b/src/main/include/log4cxx/varia/fallbackerrorhandler.h
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_VARIA_FALLBACK_ERROR_HANDLER_H
+#define _LOG4CXX_VARIA_FALLBACK_ERROR_HANDLER_H
+
+#include <log4cxx/spi/errorhandler.h>
+#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/appender.h>
+#include <log4cxx/logger.h>
+#include <vector>
+
+namespace log4cxx
+{
+ namespace varia
+ {
+ /**
+ The <code>FallbackErrorHandler</code> implements the ErrorHandler
+ interface such that a secondary appender may be specified. This
+ secondary appender takes over if the primary appender fails for
+ whatever reason.
+
+ <p>The error message is printed on <code>System.err</code>, and
+ logged in the new secondary appender.
+ */
+ class LOG4CXX_EXPORT FallbackErrorHandler :
+ public virtual spi::ErrorHandler,
+ public virtual helpers::ObjectImpl
+ {
+ private:
+ AppenderPtr backup;
+ AppenderPtr primary;
+ std::vector<LoggerPtr> loggers;
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(FallbackErrorHandler)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(spi::OptionHandler)
+ LOG4CXX_CAST_ENTRY(spi::ErrorHandler)
+ END_LOG4CXX_CAST_MAP()
+
+ FallbackErrorHandler();
+ void addRef() const;
+ void releaseRef() const;
+
+
+ /**
+ <em>Adds</em> the logger passed as parameter to the list of
+ loggers that we need to search for in case of appender failure.
+ */
+ void setLogger(const LoggerPtr& logger);
+
+
+ /**
+ No options to activate.
+ */
+ void activateOptions(log4cxx::helpers::Pool& p);
+ void setOption(const LogString& option, const LogString& value);
+
+
+ /**
+ Prints the message and the stack trace of the exception on
+ <code>System.err</code>.
+ */
+ void error(const LogString& message, const std::exception& e,
+ int errorCode) const;
+
+ /**
+ Prints the message and the stack trace of the exception on
+ <code>System.err</code>.
+ */
+ void error(const LogString& message, const std::exception& e,
+ int errorCode, const spi::LoggingEventPtr& event) const;
+
+
+ /**
+ Print a the error message passed as parameter on
+ <code>System.err</code>.
+ */
+ void error(const LogString& /* message */) const {}
+
+ /**
+ Return the backup appender.
+ */
+ const AppenderPtr& getBackupAppender() const
+ { return backup; }
+
+ /**
+ The appender to which this error handler is attached.
+ */
+ void setAppender(const AppenderPtr& primary);
+
+ /**
+ Set the backup appender.
+ */
+ void setBackupAppender(const AppenderPtr& backup);
+ };
+ } // namespace varia
+} // namespace log4cxx
+
+#endif //_LOG4CXX_VARIA_FALLBACK_ERROR_HANDLER_H
+
diff --git a/src/main/include/log4cxx/writerappender.h b/src/main/include/log4cxx/writerappender.h
new file mode 100644
index 0000000..37db9b1
--- /dev/null
+++ b/src/main/include/log4cxx/writerappender.h
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_WRITER_APPENDER_H
+#define _LOG4CXX_WRITER_APPENDER_H
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/appenderskeleton.h>
+#include <log4cxx/helpers/outputstreamwriter.h>
+
+namespace log4cxx
+{
+
+ namespace helpers {
+ class Transcoder;
+ }
+
+ /**
+ WriterAppender appends log events to a standard output stream
+ */
+ class LOG4CXX_EXPORT WriterAppender : public AppenderSkeleton
+ {
+ private:
+ /**
+ 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.
+
+ <p>The <code>immediateFlush</code> variable is set to
+ <code>true</code> by default.
+
+ */
+ bool immediateFlush;
+
+ /**
+ The encoding to use when opening an input stream.
+ <p>The <code>encoding</code> variable is set to <code>""</code> by
+ default which results in the utilization of the system's default
+ encoding. */
+ LogString encoding;
+
+ /**
+ * This is the {@link Writer Writer} where we will write to.
+ */
+ log4cxx::helpers::WriterPtr writer;
+
+
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(WriterAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(WriterAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ This default constructor does nothing.*/
+ WriterAppender();
+ protected:
+ WriterAppender(const LayoutPtr& layout,
+ log4cxx::helpers::WriterPtr& writer);
+ WriterAppender(const LayoutPtr& layout);
+
+ public:
+ ~WriterAppender();
+
+ /**
+ Derived appenders should override this method if option structure
+ requires it.
+ */
+ virtual void activateOptions(log4cxx::helpers::Pool& pool);
+
+ /**
+ If the <b>ImmediateFlush</b> option is set to
+ <code>true</code>, the appender will flush at the end of each
+ write. This is the default behavior. If the option is set to
+ <code>false</code>, then the underlying stream can defer writing
+ to physical medium to a later time.
+
+ <p>Avoiding the flush operation at the end of each append results in
+ a performance gain of 10 to 20 percent. However, there is safety
+ tradeoff involved in skipping flushing. Indeed, when flushing is
+ skipped, then it is likely that the last few log events will not
+ be recorded on disk when the application exits. This is a high
+ price to pay even for a 20% performance gain.
+ */
+ void setImmediateFlush(bool value);
+ /**
+ Returns value of the <b>ImmediateFlush</b> option.
+ */
+ bool getImmediateFlush() const { return immediateFlush; }
+
+ /**
+ This method is called by the AppenderSkeleton#doAppend
+ method.
+
+ <p>If the output stream exists and is writable then write a log
+ statement to the output stream. Otherwise, write a single warning
+ message to <code>stderr</code>.
+
+ <p>The format of the output will depend on this appender's
+ layout.
+
+ */
+ virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);
+
+
+ protected:
+ /**
+ This method determines if there is a sense in attempting to append.
+
+ <p>It checks whether there is a set output target and also if
+ there is a set layout. If these checks fail, then the boolean
+ value <code>false</code> is returned. */
+ virtual bool checkEntryConditions() const;
+
+
+ public:
+ /**
+ Close this appender instance. The underlying stream or writer is
+ also closed.
+
+ <p>Closed appenders cannot be reused.
+ */
+ virtual void close();
+
+ protected:
+ /**
+ * Close the underlying {@link log4cxx::helpers::Writer}.
+ * */
+ void closeWriter();
+
+ /**
+ Returns an OutputStreamWriter when passed an OutputStream. The
+ encoding used will depend on the value of the
+ <code>encoding</code> property. If the encoding value is
+ specified incorrectly the writer will be opened using the default
+ system encoding (an error message will be printed to the loglog. */
+ virtual log4cxx::helpers::WriterPtr createWriter(
+ log4cxx::helpers::OutputStreamPtr& os);
+
+ public:
+ LogString getEncoding() const;
+ void setEncoding(const LogString& value);
+ void setOption(const LogString& option,
+ const LogString& value);
+
+ /**
+ <p>Sets the Writer where the log output will go. The
+ specified Writer must be opened by the user and be
+ writable.
+
+ <p>The <code>java.io.Writer</code> will be closed when the
+ appender instance is closed.
+
+
+ <p><b>WARNING:</b> Logging to an unopened Writer will fail.
+ <p>
+ @param writer An already opened Writer. */
+ void setWriter(const log4cxx::helpers::WriterPtr& writer);
+
+ virtual bool requiresLayout() const;
+
+ protected:
+ /**
+ Actual writing occurs here.
+ */
+ virtual void subAppend(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);
+
+
+ /**
+ Write a footer as produced by the embedded layout's
+ Layout#appendFooter method. */
+ virtual void writeFooter(log4cxx::helpers::Pool& p);
+
+ /**
+ Write a header as produced by the embedded layout's
+ Layout#appendHeader method. */
+ virtual void writeHeader(log4cxx::helpers::Pool& p);
+
+ private:
+ //
+ // prevent copy and assignment
+ WriterAppender(const WriterAppender&);
+ WriterAppender& operator=(const WriterAppender&);
+ };
+
+ LOG4CXX_PTR_DEF(WriterAppender);
+
+} //namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+
+#endif //_LOG4CXX_WRITER_APPENDER_H
diff --git a/src/main/include/log4cxx/xml/Makefile.am b/src/main/include/log4cxx/xml/Makefile.am
new file mode 100644
index 0000000..b28bb8e
--- /dev/null
+++ b/src/main/include/log4cxx/xml/Makefile.am
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+xmlincdir = $(includedir)/log4cxx/xml
+xmlinc_HEADERS= $(top_srcdir)/src/main/include/log4cxx/xml/*.h
+
diff --git a/src/main/include/log4cxx/xml/domconfigurator.h b/src/main/include/log4cxx/xml/domconfigurator.h
new file mode 100644
index 0000000..6799d54
--- /dev/null
+++ b/src/main/include/log4cxx/xml/domconfigurator.h
@@ -0,0 +1,316 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_XML_DOM_CONFIGURATOR_H
+#define _LOG4CXX_XML_DOM_CONFIGURATOR_H
+
+#if defined(_MSC_VER)
+#pragma warning (push)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+
+#include <log4cxx/logstring.h>
+#include <map>
+#include <log4cxx/appender.h>
+#include <log4cxx/layout.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/helpers/properties.h>
+#include <log4cxx/spi/configurator.h>
+#include <log4cxx/helpers/charsetdecoder.h>
+#include <log4cxx/spi/filter.h>
+#include <log4cxx/rolling/triggeringpolicy.h>
+#include <log4cxx/rolling/rollingpolicy.h>
+#include <log4cxx/file.h>
+#include <log4cxx/config/propertysetter.h>
+
+extern "C" {
+ struct apr_xml_doc;
+ struct apr_xml_elem;
+}
+
+namespace log4cxx
+{
+
+ namespace xml
+ {
+
+ /**
+ Use this class to initialize the log4cxx environment using a DOM tree.
+
+ <p>Sometimes it is useful to see how log4cxx is reading configuration
+ files. You can enable log4cxx internal logging by setting the
+ <code>debug</code> attribute in the
+ <code>log4cxx</code> element. As in
+ <pre>
+ &lt;log4j:configuration <b>debug="true"</b> xmlns:log4j="http://jakarta.apache.org/log4j/">
+ ...
+ &lt;/log4j:configuration>
+ </pre>
+
+ <p>There are sample XML files included in the package.
+ */
+ class LOG4CXX_EXPORT DOMConfigurator :
+ virtual public spi::Configurator,
+ virtual public helpers::ObjectImpl
+ {
+ protected:
+ typedef std::map<LogString, AppenderPtr> AppenderMap;
+ /**
+ Used internally to parse appenders by IDREF name.
+ */
+ AppenderPtr findAppenderByName(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* elem,
+ apr_xml_doc* doc,
+ const LogString& appenderName,
+ AppenderMap& appenders);
+
+ /**
+ Used internally to parse appenders by IDREF element.
+ */
+ AppenderPtr findAppenderByReference(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* appenderRef,
+ apr_xml_doc* doc,
+ AppenderMap& appenders);
+
+ /**
+ Used internally to parse an appender element.
+ */
+ AppenderPtr parseAppender(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* appenderElement,
+ apr_xml_doc* doc,
+ AppenderMap& appenders);
+
+ /**
+ Used internally to parse an {@link spi::ErrorHandler ErrorHandler } element.
+ */
+ void parseErrorHandler(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ AppenderPtr& appender,
+ apr_xml_doc* doc,
+ AppenderMap& appenders);
+
+ /**
+ Used internally to parse a filter element.
+ */
+ void parseFilters(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ std::vector<log4cxx::spi::FilterPtr>& filters);
+
+ /**
+ Used internally to parse a logger element.
+ */
+ void parseLogger(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* loggerElement,
+ apr_xml_doc* doc,
+ AppenderMap& appenders);
+
+ /**
+ Used internally to parse the logger factory element.
+ */
+ void parseLoggerFactory(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* factoryElement);
+
+ /**
+ Used internally to parse the logger factory element.
+ */
+ log4cxx::helpers::ObjectPtr parseTriggeringPolicy(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* factoryElement);
+
+ /**
+ Used internally to parse the logger factory element.
+ */
+ log4cxx::rolling::RollingPolicyPtr parseRollingPolicy(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* factoryElement);
+
+ /**
+ Used internally to parse the root logger element.
+ */
+ void parseRoot(log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* rootElement, apr_xml_doc* doc, AppenderMap& appenders);
+
+ /**
+ Used internally to parse the children of a logger element.
+ */
+ void parseChildrenOfLoggerElement(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* catElement,
+ LoggerPtr logger, bool isRoot,
+ apr_xml_doc* doc,
+ AppenderMap& appenders);
+
+ /**
+ Used internally to parse a layout element.
+ */
+ LayoutPtr parseLayout(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* layout_element);
+
+ /**
+ Used internally to parse a level element.
+ */
+ void parseLevel(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ LoggerPtr logger, bool isRoot);
+
+ void setParameter(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* elem,
+ log4cxx::config::PropertySetter& propSetter);
+
+ /**
+ Used internally to configure the log4cxx framework from
+ an in-memory representation of an XML document.
+ */
+ void parse(
+ log4cxx::helpers::Pool& p,
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ apr_xml_doc* doc,
+ AppenderMap& appenders);
+
+ public:
+ DOMConfigurator();
+
+ DECLARE_LOG4CXX_OBJECT(DOMConfigurator)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(spi::Configurator)
+ END_LOG4CXX_CAST_MAP()
+
+ DOMConfigurator(log4cxx::helpers::Pool& p);
+
+ void addRef() const;
+ void releaseRef() const;
+
+ /**
+ A static version of #doConfigure.
+ */
+ static void configure(const std::string& filename);
+#if LOG4CXX_WCHAR_T_API
+ static void configure(const std::wstring& filename);
+#endif
+#if LOG4CXX_UNICHAR_API
+ static void configure(const std::basic_string<UniChar>& filename);
+#endif
+#if LOG4CXX_CFSTRING_API
+ static void configure(const CFStringRef& filename);
+#endif
+ /**
+ Like #configureAndWatch(const std::string& configFilename, long delay)
+ except that the default delay as defined by
+ log4cxx::helpers::FileWatchdog#DEFAULT_DELAY is used.
+ @param configFilename A log4j configuration file in XML format.
+ */
+ static void configureAndWatch(const std::string& configFilename);
+#if LOG4CXX_WCHAR_T_API
+ static void configureAndWatch(const std::wstring& configFilename);
+#endif
+#if LOG4CXX_UNICHAR_API
+ static void configureAndWatch(const std::basic_string<UniChar>& configFilename);
+#endif
+#if LOG4CXX_CFSTRING_API
+ static void configureAndWatch(const CFStringRef& configFilename);
+#endif
+ /**
+ Read the configuration file <code>configFilename</code> if it
+ exists. Moreover, a thread will be created that will periodically
+ check if <code>configFilename</code> has been created or
+ modified. The period is determined by the <code>delay</code>
+ argument. If a change or file creation is detected, then
+ <code>configFilename</code> is read to configure log4cxx.
+
+ @param configFilename A log4j configuration file in XML format.
+ @param delay The delay in milliseconds to wait between each check.
+ */
+ static void configureAndWatch(const std::string& configFilename,
+ long delay);
+#if LOG4CXX_WCHAR_T_API
+ static void configureAndWatch(const std::wstring& configFilename,
+ long delay);
+#endif
+#if LOG4CXX_UNICHAR_API
+ static void configureAndWatch(const std::basic_string<UniChar>& configFilename,
+ long delay);
+#endif
+#if LOG4CXX_CFSTRING_API
+ static void configureAndWatch(const CFStringRef& configFilename,
+ long delay);
+#endif
+
+ /**
+ Interpret the XML file pointed by <code>filename</code> and set up
+ log4cxx accordingly.
+ <p>The configuration is done relative to the hierarchy parameter.
+ @param filename The file to parse.
+ @param repository The hierarchy to operation upon.
+ */
+ void doConfigure(const File& filename,
+ spi::LoggerRepositoryPtr& repository);
+
+ protected:
+ static LogString getAttribute(
+ log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem*,
+ const std::string& attrName);
+
+ LogString subst(const LogString& value);
+
+ protected:
+ helpers::Properties props;
+ spi::LoggerRepositoryPtr repository;
+ spi::LoggerFactoryPtr loggerFactory;
+
+ private:
+ // prevent assignment or copy statements
+ DOMConfigurator(const DOMConfigurator&);
+ DOMConfigurator& operator=(const DOMConfigurator&);
+
+ };
+ LOG4CXX_PTR_DEF(DOMConfigurator);
+ } // namespace xml
+} // namespace log4cxx
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+#endif // _LOG4CXX_XML_DOM_CONFIGURATOR_H
diff --git a/src/main/include/log4cxx/xml/xmllayout.h b/src/main/include/log4cxx/xml/xmllayout.h
new file mode 100644
index 0000000..a0094ac
--- /dev/null
+++ b/src/main/include/log4cxx/xml/xmllayout.h
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_XML_LAYOUT_H
+#define _LOG4CXX_XML_LAYOUT_H
+
+#include <log4cxx/layout.h>
+
+namespace log4cxx
+{
+ namespace xml
+ {
+
+ /**
+ The output of the XMLLayout consists of a series of log4j:event
+ elements. It does not output a
+ complete well-formed XML file. The output is designed to be
+ included as an <em>external entity</em> in a separate file to form
+ a correct XML file.
+
+ <p>For example, if <code>abc</code> is the name of the file where
+ the XMLLayout ouput goes, then a well-formed XML file would be:
+
+ <code>
+ <?xml version="1.0" ?>
+
+ <!DOCTYPE log4j:eventSet [<!ENTITY data SYSTEM "abc">]>
+
+ <log4j:eventSet version="1.2" xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+ @&data;
+
+ </log4j:eventSet>
+ </code>
+
+ <p>This approach enforces the independence of the XMLLayout and the
+ appender where it is embedded.
+ */
+ class LOG4CXX_EXPORT XMLLayout : public Layout
+ {
+ private:
+
+ // Print no location info by default
+ bool locationInfo; //= false
+ bool properties; // = false
+
+ public:
+ DECLARE_LOG4CXX_OBJECT(XMLLayout)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(XMLLayout)
+ LOG4CXX_CAST_ENTRY_CHAIN(Layout)
+ END_LOG4CXX_CAST_MAP()
+
+ XMLLayout();
+
+ /**
+ The <b>LocationInfo</b> option takes a boolean value. By
+ default, it is set to false which means there will be no location
+ information output by this layout. If the the option is set to
+ true, then the file name and line number of the statement
+ at the origin of the log statement will be output.
+
+ <p>If you are embedding this layout within a SMTPAppender
+ then make sure to set the
+ <b>LocationInfo</b> option of that appender as well.
+ */
+ inline void setLocationInfo(bool locationInfo1)
+ { this->locationInfo = locationInfo1; }
+
+ /**
+ Returns the current value of the <b>LocationInfo</b> option.
+ */
+ inline bool getLocationInfo() const
+ { return locationInfo; }
+
+ /**
+ * Sets whether MDC key-value pairs should be output, default false.
+ * @param flag new value.
+ *
+ */
+ inline void setProperties(bool flag) {
+ properties = flag;
+ }
+
+ /**
+ * Gets whether MDC key-value pairs should be output.
+ * @return true if MDC key-value pairs are output.
+ *
+ */
+ inline bool getProperties() {
+ return properties;
+ }
+
+
+ /** No options to activate. */
+ void activateOptions(log4cxx::helpers::Pool& /* p */) { }
+
+ /**
+ Set options
+ */
+ virtual void setOption(const LogString& option,
+ const LogString& value);
+
+ /**
+ * Formats a {@link spi::LoggingEvent LoggingEvent}
+ * in conformance with the log4cxx.dtd.
+ **/
+ virtual void format(LogString& output,
+ const spi::LoggingEventPtr& event,
+ log4cxx::helpers::Pool& p) const;
+
+ /**
+ The XMLLayout prints and does not ignore exceptions. Hence the
+ return value <code>false</code>.
+ */
+ virtual bool ignoresThrowable() const
+ { return false; }
+
+ }; // class XMLLayout
+ LOG4CXX_PTR_DEF(XMLLayout);
+ } // namespace xml
+} // namespace log4cxx
+
+#endif // _LOG4CXX_XML_LAYOUT_H
diff --git a/src/main/resources/EventLogCategories.mc b/src/main/resources/EventLogCategories.mc
new file mode 100644
index 0000000..f017900
--- /dev/null
+++ b/src/main/resources/EventLogCategories.mc
@@ -0,0 +1,46 @@
+;
+; Licensed to the Apache Software Foundation (ASF) under one
+; or more contributor license agreements. See the NOTICE file
+; distributed with this work for additional information
+; regarding copyright ownership. The ASF licenses this file
+; to you under the Apache License, Version 2.0 (the
+; "License"); you may not use this file except in compliance
+; with the License. You may obtain a copy of the License at
+;
+; http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing,
+; software distributed under the License is distributed on an
+; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+; KIND, either express or implied. See the License for the
+; specific language governing permissions and limitations
+; under the License.
+;
+MessageId=1
+Language=English
+Trace
+.
+MessageId=2
+Language=English
+Debug
+.
+MessageId=3
+Language=English
+Info
+.
+MessageId=4
+Language=English
+Warn
+.
+MessageId=5
+Language=English
+Error
+.
+MessageId=6
+Language=English
+Fatal
+.
+MessageId=0x1000
+Language=English
+%1
+.
diff --git a/src/main/resources/MSG00001.bin b/src/main/resources/MSG00001.bin
new file mode 100644
index 0000000..b6a1996
--- /dev/null
+++ b/src/main/resources/MSG00001.bin
Binary files differ
diff --git a/src/main/resources/log4cxx.rc b/src/main/resources/log4cxx.rc
new file mode 100755
index 0000000..bd5f323
--- /dev/null
+++ b/src/main/resources/log4cxx.rc
@@ -0,0 +1,125 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+//
+// Message file include
+//
+LANGUAGE 0x9,0x1
+1 11 MSG00001.bin
+// Microsoft Visual C++ generated resource script.
+//
+#include "windows.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+//#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0, 10, 0, 1
+ PRODUCTVERSION 0, 10, 0, 1
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Apache Software Foundation"
+ VALUE "FileDescription", "Apache log4cxx"
+ VALUE "FileVersion", "0,10, 0, 1"
+ VALUE "InternalName", "log4cxx"
+ VALUE "LegalCopyright", "Licensed to the Apache Software Foundation (ASF) under one or more\ncontributor license agreements. See the NOTICE file distributed with\nthis work for additional information regarding copyright ownership.\nThe ASF licenses this file to You under the Apache License, Version 2.0\n(the ""License""); you may not use this file except in compliance with\nthe License. You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an ""AS IS"" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
+ VALUE "OriginalFilename", "log4cxx.dll"
+ VALUE "ProductName", "Apache log4cxx"
+ VALUE "ProductVersion", "0, 10, 0, 1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/site/Makefile.am b/src/site/Makefile.am
new file mode 100644
index 0000000..d48a135
--- /dev/null
+++ b/src/site/Makefile.am
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+SUBDIRS = doxy
diff --git a/src/site/apt/Makefile.am b/src/site/apt/Makefile.am
new file mode 100644
index 0000000..8e6be87
--- /dev/null
+++ b/src/site/apt/Makefile.am
@@ -0,0 +1,15 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
diff --git a/src/site/apt/building/ant.apt b/src/site/apt/building/ant.apt
new file mode 100644
index 0000000..07c543d
--- /dev/null
+++ b/src/site/apt/building/ant.apt
@@ -0,0 +1,235 @@
+~~ Licensed to the Apache Software Foundation (ASF) under one or more
+~~ contributor license agreements. See the NOTICE file distributed with
+~~ this work for additional information regarding copyright ownership.
+~~ The ASF licenses this file to You under the Apache License, Version 2.0
+~~ (the "License"); you may not use this file except in compliance with
+~~ the License. You may obtain a copy of the License at
+~~
+~~ http://www.apache.org/licenses/LICENSE-2.0
+~~
+~~ Unless required by applicable law or agreed to in writing, software
+~~ distributed under the License is distributed on an "AS IS" BASIS,
+~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~~ See the License for the specific language governing permissions and
+~~ limitations under the License.
+ ------
+ Building Apache log4cxx with Apache Ant
+ ------
+ ------
+ ------
+
+
+Building Apache log4cxx with Apache Ant
+
+ {{{http://ant.apache.org}Apache Ant}} with cpptasks from the
+ {{{http://ant-contrib.sourceforge.net}Ant-Contrib}} project can be used to build log4cxx
+ with supported compilers and is also used to generate the IDE project files included
+ in the releases. The Apache Maven build which is used to generate the site documentation
+ and release packaging delegates to this build. The Ant build can build APR and APR-Util
+ if source is available.
+
+* Quick start:
+
+ *Install {{{http://ant.apache.org}Apache Ant}} 1.6.5 or later.
+
+ *Install cpptasks 1.0b5 or later from the {{{http://ant-contrib.sourceforge.net}Ant-Contrib Project}}.
+ ant-contribs 1.0b3 or later is needed for some less frequent build targets.
+
+ *Install APR and APR-Util or place source in apr and apr-util directories as a
+ sibling to the log4cxx directory.
+
+ *Install gzip and zip (used for compression by RollingFileAppender) and
+ sed (used to normalize output files for comparison in unit tests).
+
+ * Install log4j 1.2. Used in testing of SocketAppender.
+
+ Building and testing log4cxx on a Unix platform with packaged APR and APR-Util.
+
++----+
+$ export CLASSPATH=~/cpptasks/cpptasks-1.0b5.jar
+$ cd apache-log4cxx-0.10.0
+$ ant
++----+
+
+ Building and testing log4cxx on a Unix platform with APR and APR-Util built from source.
+
++----+
+$ export CLASSPATH=~/cpptasks/cpptasks-1.0b5.jar
+$ tar -xvzf apr-1.2.12.tar.gz
+$ mv apr-1.2.12 apr
+$ tar -xvzf apr-util-1.2.12.tar.gz
+$ mv apr-util-1.2.12 apr-util
+$ cd apache-log4cxx-0.10.0
+$ ant
++----+
+
+ Building and testing log4cxx on a Microsoft Windows with APR and APR-Util built from source.
+
++----+
+set PATH=\apache-ant-1.7.0\bin;%PATH%
+set CLASSPATH=\cpptasks\cpptasks-1.0b5.jar
+tar -xvzf apr-1.2.12.tar.gz
+rename apr-1.2.12 apr
+tar -xvzf apr-util-1.2.12.tar.gz
+rename apr-util-1.2.12 apr-util
+cd apache-log4cxx-0.10.0
+ant -Dfind=false
++----+
+
+
+
+
+
+* Common ant targets
+
+*-----------------------+---------------------------------------------------------------------------------------------+
+| build | build log4cxx library. |
+*-----------------------+---------------------------------------------------------------------------------------------+
+| check | build logcxx library and build and run unit tests and examples. |
+*-----------------------+---------------------------------------------------------------------------------------------+
+| clean | Delete all generated files. |
+*-----------------------+---------------------------------------------------------------------------------------------+
+| build-unittest | build log4cxx library and unit test. |
+*-----------------------+---------------------------------------------------------------------------------------------+
+| run-socketserver | Tests SocketAppender with Java-based receiver. |
+*-----------------------+---------------------------------------------------------------------------------------------+
+| build-projects-vc6 | Build Microsoft Visual Studio 6 project files. |
+*-----------------------+---------------------------------------------------------------------------------------------+
+| build-projects-vc7 | Build Microsoft Visual Studio .NET project files. |
+*-----------------------+---------------------------------------------------------------------------------------------+
+| build-projects-vc8 | Build Microsoft Visual Studio 2005 project files. |
+*-----------------------+---------------------------------------------------------------------------------------------+
+| build-projects-vc9 | Build Microsoft Visual Studio 2008 project files. |
+*-----------------------+---------------------------------------------------------------------------------------------+
+| build-projects-xcode | Build Apple Xcode project files. |
+*-----------------------+---------------------------------------------------------------------------------------------+
+
+ All build products will be placed in the target subdirectory.
+
+ Project files should be generated after successfully building the library, however it is possible
+ to generate Microsoft Visual Studio project files on other platforms. The project
+ files will typically be missing references to the Platform SDK libraries.
+ The Maven project modifies the generated project files for release preparation. Generation
+ of Xcode projects from Microsoft Windows is not supported.
+
+
+* ant options
+
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Dcompiler | Compiler, see cpptasks documentation for full list. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Ddebug | Build for debugging, yes (default), no. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Dfind | Attempt to locate compiled APR and APR-Util, yes (default), no. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Dwith-apr | path to non-default location for APR. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Dwith-apr-util | path to non-default location for APR-Util. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Denable-wchar_t | Enable wchar_t API methods, choice of yes (default), no. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Denable-unichar | Enable UniChar API methods, choice of yes, no (default). |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Denable-cfstring | Enable CFString API methods, requires Mac OS/X CoreFoundation, choice of yes, no (default). |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Dwith-logchar | Interal character representation, choice of utf-8 (default), wchar_t , unichar. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Dwith-charset | Exteral character encoding, choice of utf-8, iso-8859-1, usascii, ebcdic, auto (default). |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Dwith-SMTP | SMTP implementation for SMTPAppender, choice of libesmtp, no (default). |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Dwith-ODBC | OBDC implementation for ODBCAppender, choice of unixODBC, iODBC, Microsoft, no (default). |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Dlog4j.jar | Path to log4j.jar for run-socketserver. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Dprojects.dir | Location for generated IDE projects. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Dlib.type | Library type to create, choice of shared (default), static. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Druntime | Type of C runtime library to use, choice of dynamic (default), static. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -Doptimization | Optimization: none (default), size, minimal, speed, full, aggressive, extreme, unsafe. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -p | Display available targets and quit. |
+*-------------------+---------------------------------------------------------------------------------------------+
+
+ SMTP and ODBC options can depend on libraries that
+ that have different licenses.
+ You should review the corresponding licenses and understand
+ the implications before redistribution.
+
+ Combining -Dlib.type=shared and -Druntime=static is unsafe.
+
+ Properties may also be placed in a build.properties file in the log4cxx directory.
+
+* Platform specific notes:
+
+ ** Microsoft Windows
+
+ {{{http://gnuwin32.sourceforge.net}GnuWin32}}
+ provides binary versions of sed, gzip and zip. Alternative,
+ the bin directory of {{{http://www.cygwin.com}Cygwin}} may be placed on the path.
+
+ If -Dwith-SMTP=libesmtp is specified, the build will attempt to build
+ libesmtp from source, unfortunately libesmtp depends on poll.h and will not build.
+
+ APR 1.2.12 has a known issue that will prevent
+ compilation with Visual Studio 6 unless a later Platform SDK is installed.
+ See APR bug {{{http://issues.apache.org/bugzilla/show_bug.cgi?44327}44327}}.
+ APR 1.2.11 and the corresponding APR-Util 1.2.10 will compile with Visual Studio 6.
+
+
+ *** Cygwin:
+
+ gcc 3.x does not provide wchar_t support which needs to be explicitly disabled.
+ The Win32 path to the APR libraries need to be provided (CYGWIN_HOME/lib) if compiling against an installed APR and APR-Util.
+
++-----+
+$ cd apache-log4cxx-0.10.0
+$ ant -Dos.family=cygwin \
+ -Dwith-apr=/cygwin/lib \
+ -Dwith-apr-util=/cygwin/lib \
+ -Denable-wchar_t=0
++-----+
+
+
+ *** MinGW:
+
++----+
+$ cd apache-log4cxx-0.10.0
+$ path c:\mingw\bin;%PATH%
+$ ant -Dcompiler=gcc -Dfind=false build-all
+$ cd src\test\resources
+$ set TOTO=wonderful
+$ set key1=value1
+$ set key2=value2
+$ ..\..\..\target\debug\shared\testsuite -v
+$ ..\..\..\target\debug\shared\trivial
+$ ..\..\..\target\debug\shared\stream
++----+
+
+ Running "ant check" was observed to fail with unexpected exceptions
+ in streamtestcase and datetimedateformattestcase.
+ See {{{http://issues.apache.org/jira/browse/LOGCXX-244}LOGCXX-244}}.
+
+ ** Debian:
+
+ Apache APR, APR-Util, Ant and log4j and zip may be installed using:
+
++----+
+$ sudo apt-get install libapr1.0-dev libaprutil1.0-dev \
+ ant ant-optional liblog4j1.2-java zip
++----+
+
+
+ ** Mac OS/X:
+
+ APR and APR-Util are provided by the platform in Mac OS/X 10.5 and iODBC in 10.4.
+
+ Site generation requires "doxygen" command on path which can be provided
+ by installing Doxygen.app and then setting the path like:
+
++---+
+$ setenv PATH /Applications/Doxygen.app/Contents/Resources:$PATH
++---+
+
diff --git a/src/site/apt/building/autotools.apt b/src/site/apt/building/autotools.apt
new file mode 100644
index 0000000..7dd2373
--- /dev/null
+++ b/src/site/apt/building/autotools.apt
@@ -0,0 +1,136 @@
+~~ Licensed to the Apache Software Foundation (ASF) under one or more
+~~ contributor license agreements. See the NOTICE file distributed with
+~~ this work for additional information regarding copyright ownership.
+~~ The ASF licenses this file to You under the Apache License, Version 2.0
+~~ (the "License"); you may not use this file except in compliance with
+~~ the License. You may obtain a copy of the License at
+~~
+~~ http://www.apache.org/licenses/LICENSE-2.0
+~~
+~~ Unless required by applicable law or agreed to in writing, software
+~~ distributed under the License is distributed on an "AS IS" BASIS,
+~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~~ See the License for the specific language governing permissions and
+~~ limitations under the License.
+ ------
+ Building Apache log4cxx with autotools
+ ------
+ ------
+ ------
+
+Building Apache log4cxx with autotools
+
+* Quick start:
+
+ Install or build apr 1.x, apr-util 1.x, gzip and zip.
+
++------------+
+$ cd apache-log4cxx-0.10.0
+$ ./configure
+$ make
+$ make check
+$ sudo make install
++------------+
+
+
+* configure options
+
+*-------------------+---------------------------------------------------------------------------------------------+
+| --with-apr | path to non-default location for APR. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| --with-apr-util | path to non-default location for APR-Util. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| --enable-wchar_t | Enable wchar_t API methods, choice of yes (default), no. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| --enable-unichar | Enable UniChar API methods, choice of yes, no (default). |
+*-------------------+---------------------------------------------------------------------------------------------+
+| --enable-cfstring | Enable CFString API methods, requires Mac OS/X CoreFoundation, choice of yes, no (default). |
+*-------------------+---------------------------------------------------------------------------------------------+
+| --with-logchar | Interal character representation, choice of utf-8 (default), wchar_t , unichar. |
+*-------------------+---------------------------------------------------------------------------------------------+
+| --with-charset | Exteral character encoding, choice of utf-8, iso-8859-1, usascii, ebcdic, auto (default). |
+*-------------------+---------------------------------------------------------------------------------------------+
+| --with-SMTP | SMTP implementation for SMTPAppender, choice of libesmtp, no (default). |
+*-------------------+---------------------------------------------------------------------------------------------+
+| --with-ODBC | OBDC implementation for ODBCAppender, choice of unixODBC, iODBC, Microsoft, no (default). |
+*-------------------+---------------------------------------------------------------------------------------------+
+| -help | Display help showing all options and exit. |
+*-------------------+---------------------------------------------------------------------------------------------+
+
+
+ SMTP and ODBC options can depend on libraries that
+ that have different licenses.
+ You should review the corresponding licenses and understand
+ the implications before redistribution.
+
+* Platform specific notes:
+
+** Mac OS/X:
+
+ APR and APR-Util are provided by the platform in Mac OS/X 10.5 and iODBC in 10.4.
+
+** Debian:
+
+ APR, APR-Util and zip may be installed by:
+
++----+
+$ sudo apt-get install libapr1.0-dev libaprutil1.0-dev zip
++----+
+
+** FreeBSD:
+
+ APR, APR-Util and zip may be installed from the ports collection by:
+
++----+
+# cd /usr/ports/archivers/zip
+# make
+# make install
+# cd /usr/ports/devel/apr
+# make
+# make install
++----+
+
+** Cygwin:
+
+ Install zip (used by RollingFileAppender) and sed (used to normalize
+ output files for comparison in the unit tests). The prepackaged
+ APR currently available from Cygwin has APR_HAS_THREADS == 0.
+ Some appenders will not be available and some may operate
+ with reduced functionality. There have been reports of
+ building APR on Cygwin with threads enabled.
+
+
+** MinGW:
+
+ Recent APR 1.2.x releases fail ./configure with a error
+ of "decision on anonymous shared memory failed". That issue
+ has been fixed in the current APR SVN HEAD. The follow
+ sequence worked with MSYS (with Python on Path):
+
++----+
+$ cd expat-2.0.1
+$ ./configure
+$ make install
+$ cd ..
+$ svn co https://svn.apache.org/repos/asf/apr/apr/trunk apr
+$ cd apr
+$ ./buildconf.sh
+$ ./configure
+$ make install
+$ cd ..
+$ svn co \
+ https://svn.apache.org/repos/asf/apr/apr-util/trunk \
+ apr-util
+$ cd apr-util
+$ ./buildconf.sh
+$ ./configure --with-apr=/usr/local --with-expat=/usr/local
+$ make install
+$ cd ../apache-log4cxx-0.10.0
+$ ./configure --with-apr=/usr/local \
+ --with-apr-util=/usr/local --with-logchar=wchar_t
+$ make install
++----+
+
+ Running "make check" was observed to fail with unexpected exceptions
+ in streamtestcase and datetimedateformattestcase.
+ See {{{http://issues.apache.org/jira/browse/LOGCXX-244}LOGCXX-244}}.
diff --git a/src/site/apt/building/maven.apt b/src/site/apt/building/maven.apt
new file mode 100644
index 0000000..a40e313
--- /dev/null
+++ b/src/site/apt/building/maven.apt
@@ -0,0 +1,95 @@
+~~ Licensed to the Apache Software Foundation (ASF) under one or more
+~~ contributor license agreements. See the NOTICE file distributed with
+~~ this work for additional information regarding copyright ownership.
+~~ The ASF licenses this file to You under the Apache License, Version 2.0
+~~ (the "License"); you may not use this file except in compliance with
+~~ the License. You may obtain a copy of the License at
+~~
+~~ http://www.apache.org/licenses/LICENSE-2.0
+~~
+~~ Unless required by applicable law or agreed to in writing, software
+~~ distributed under the License is distributed on an "AS IS" BASIS,
+~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~~ See the License for the specific language governing permissions and
+~~ limitations under the License.
+ ------
+ Building Apache log4cxx with Apache Maven 2
+ ------
+ ------
+ ------
+
+
+Building Apache log4cxx with Apache Maven 2
+
+ {{{http://maven.apache.org}Apache Maven 2}} is used to generate the release assemblies and generate
+ product documentation. It delegates to the {{{ant.html}Apache Ant build}} to build
+ and test log4cxx and can be used as an alternate front end to the Ant
+ build process since it can automatically download and use ant-contrib,
+ cpptasks and log4j.
+ The Maven build, like the Ant build, can build APR and APR-Util from source.
+
+* Quick start:
+
+ *Install {{{http://maven.apache.org}Apache Maven}} 2.0.8 or later.
+
+ *Install APR and APR-Util or place source in apr and apr-util directories in same parent directory
+ as log4cxx directory.
+
+
+ Building and testing log4cxx on a Unix platform with packaged APR and APR-Util.
+
++----+
+ sudo apt-get install libapr1.0-dev libaprutil1.0-dev doxygen
+ cd apache-log4cxx-0.10.0
+ export PATH=/home/myself/maven-2.0.8/bin:$PATH
+ mvn package
++----+
+
+
+ Building and testing log4cxx on a Microsoft Windows with APR and APR-Util built from source.
+
++----+
+ set PATH=\maven-2.0.8\bin;%PATH%
+ tar -xvzf apr-1.2.12.tar.gz
+ rename apr-1.2.12 apr
+ tar -xvzf apr-util-1.2.12.tar.gz
+ rename apr-util-1.2.12 apr-util
+ cd apache-log4cxx-0.10.0
+ mvn package
++----+
+
+
+
+
+
+* Common Maven targets
+
+*--------------------------+---------------------------------------------------------------------------------------------+
+| compile | build log4cxx library. |
+*--------------------------+---------------------------------------------------------------------------------------------+
+| package | build logcxx library and build and run unit tests and examples. |
+*--------------------------+---------------------------------------------------------------------------------------------+
+| site | Generate documentation and IDE project files, requires doxygen. |
+*--------------------------+---------------------------------------------------------------------------------------------+
+| site assembly:assembly | Generate snapshot tarball and zip file. |
+*--------------------------+---------------------------------------------------------------------------------------------+
+| site-deploy | Publish website to staging area on ASF subversion repository (requires credentials). |
+*--------------------------+---------------------------------------------------------------------------------------------+
+| clean | Delete all generated files. |
+*--------------------------+---------------------------------------------------------------------------------------------+
+
+ All build products will be placed in the target subdirectory.
+
+ It is not possible to directly pass options to the Ant build, however the ant build will read
+ any build.properties file in the log4cxx directory.
+
+ SMTP and ODBC options can depend on libraries that
+ that have different licenses.
+ You should review the corresponding licenses and understand
+ the implications before redistribution.
+
+* Platform specific notes:
+
+ See the {{{ant.html}Apache Ant build}} for platform specific notes.
+
+
diff --git a/src/site/apt/building/vstudio.apt b/src/site/apt/building/vstudio.apt
new file mode 100644
index 0000000..1577b11
--- /dev/null
+++ b/src/site/apt/building/vstudio.apt
@@ -0,0 +1,86 @@
+~~ Licensed to the Apache Software Foundation (ASF) under one or more
+~~ contributor license agreements. See the NOTICE file distributed with
+~~ this work for additional information regarding copyright ownership.
+~~ The ASF licenses this file to You under the Apache License, Version 2.0
+~~ (the "License"); you may not use this file except in compliance with
+~~ the License. You may obtain a copy of the License at
+~~
+~~ http://www.apache.org/licenses/LICENSE-2.0
+~~
+~~ Unless required by applicable law or agreed to in writing, software
+~~ distributed under the License is distributed on an "AS IS" BASIS,
+~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~~ See the License for the specific language governing permissions and
+~~ limitations under the License.
+ ------
+ Building Apache log4cxx with Microsoft Visual Studio
+ ------
+ ------
+ ------
+
+Building Apache log4cxx with Microsoft Visual Studio
+
+*Preparation
+
++----+
+unzip apr-1.2.11-win32-src.zip
+rename apr-1.2.11 apr
+unzip apr-util-1.2.10-win32-src.zip
+rename apr-util-1.2.10 apr-util
+cd apache-log4cxx-0.10.0
+configure
+configure-aprutil
++----+
+
+ configure.bat copies the prefabricated log4cxx.hw and private/log4cxx_private.hw over
+ to log4cxx.h and private/log4cxx_private.h.
+
+ configure-aprutil.bat uses "sed" to modify apu.hw and apr_ldap.hw to disable APR-Iconv
+ and LDAP which are not necessary for log4cxx and problematic to build.
+ If "sed" is not available, the modifications would be trivial to do in any text editor.
+
+ Use the Win32 source zips for APR and APR-Util to preserve the required line endings
+ for the project files. Directories need to be renamed to "apr" and "apr-util" respectively.
+
+
+
+*Building log4cxx.dll
+
+ Open projects/log4cxx.dsw with Microsoft
+ Visual Studio 6 or later at which time you may be prompted to
+ upgrade the projects to the format used by your version
+ of Microsoft Visual Studio.
+
+ Select log4cxx as active project and build.
+
+
+*Running unit tests
+
+ To pass the unit tests, gzip, zip and sed must be on the path.
+ Also three
+ environment variables need to be defined: TOTO=wonderful,
+ key1=value1 and key2=value2. These must be done outside
+ of Microsoft Visual Studio, either in the Control Panel or
+ in a Command Prompt uses to launch Microsoft Visual Studio.
+
+ Open projects/testsuite.dsw or projects/testsuite-standalone.dsw
+ (test suite and implementation in one project) in Microsoft Visual
+ Studio, select active project and build.
+
+ On the Debug Tab of the Project/Settings dialog,
+ set the Working Directory to "../src/test/resources".
+ Individual tests can be specified in Program Arguments
+ and "-v" can be specified to output verbose test results.
+
+
+*Known Issues
+
+ *APR 1.2.12 has a known issue that will prevent
+ compilation with Visual Studio 6 unless a later Platform SDK is installed.
+ See APR bug {{{http://issues.apache.org/bugzilla/show_bug.cgi?44327}44327}}.
+ APR 1.2.11 and the corresponding APR-Util 1.2.10 will compile with Visual Studio 6.
+
+ *APR-Util requires later LDAP headers than provided with Visual Studio 6
+ and will fail to compile. log4cxx does not use LDAP, it can be disabled in apr_ldap.hw.
+
+ *APR-Iconv is problematic and not used by log4cxx, it can be disabled in apu.hw.
diff --git a/src/site/apt/building/xcode.apt b/src/site/apt/building/xcode.apt
new file mode 100644
index 0000000..a0a10d5
--- /dev/null
+++ b/src/site/apt/building/xcode.apt
@@ -0,0 +1,65 @@
+~~ Licensed to the Apache Software Foundation (ASF) under one or more
+~~ contributor license agreements. See the NOTICE file distributed with
+~~ this work for additional information regarding copyright ownership.
+~~ The ASF licenses this file to You under the Apache License, Version 2.0
+~~ (the "License"); you may not use this file except in compliance with
+~~ the License. You may obtain a copy of the License at
+~~
+~~ http://www.apache.org/licenses/LICENSE-2.0
+~~
+~~ Unless required by applicable law or agreed to in writing, software
+~~ distributed under the License is distributed on an "AS IS" BASIS,
+~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~~ See the License for the specific language governing permissions and
+~~ limitations under the License.
+ ------
+ Building Apache log4cxx with Apple Xcode
+ ------
+ ------
+ ------
+
+Building Apache log4cxx with Apple Xcode
+
+*Building log4cxx.dylib
+
+ Run configure to generate log4cxx.h and log4cxx_private.h
+ then launch Xcode.
+
++----+
+cd apache-log4cxx-0.10.0
+./configure
+open projects/log4cxx.xcodeproj
++----+
+
+
+*Running unit tests
+
+ Run configure then open projects/testsuite.xcodeproj
+ or projects/testsuite-standalone.xcodeproj
+ (test suite and implementation in one project) in Xcode.
+
+ The unit tests require the working directory and several environment variables
+ to be set. To set these, elect the executable in Groups & Files and press Info and:
+
+ * In the General pane, set Working Directory to Custom with path "../src/test/resources".
+
+ * In the Arguments pane, add following key value pairs to "Variables to be set in the environment":
+ TOTO=wonderful, key1=value1 and key2=value2.
+
+ * In the Arguments pane, add "-v" for verbose output, or individual test names in "Arguments to be passed on launch".
+
+*Issues
+
+ The project file generation does does not
+ properly create an entry in the "Link Binary with Libraries"
+ build phase for projects (such as the examples and unit tests) that depend
+ on log4cxx. To work around the problem, open the project in Xcode and
+ in the Groups & Files pane, drag log4cxx.dylib
+ and drop on the "Link Binary with Libraries" folder
+ under Targets.
+
+ See issue {{{http://issues.apache.org/jira/browse/LOGCXX-245}LOGCXX-245}} for further information.
+
+ The projects provided in the release target Mac OS/X 10.5 which provides
+ preinstalled APR and APR-Util libraries. To generate XCode projects to target Mac OS/X 10.4,
+ set up the ant build and then "ant build-projects-xcode -Dfind=false".
diff --git a/src/site/apt/download.apt b/src/site/apt/download.apt
new file mode 100644
index 0000000..f56c556
--- /dev/null
+++ b/src/site/apt/download.apt
@@ -0,0 +1,44 @@
+~~ Licensed to the Apache Software Foundation (ASF) under one or more
+~~ contributor license agreements. See the NOTICE file distributed with
+~~ this work for additional information regarding copyright ownership.
+~~ The ASF licenses this file to You under the Apache License, Version 2.0
+~~ (the "License"); you may not use this file except in compliance with
+~~ the License. You may obtain a copy of the License at
+~~
+~~ http://www.apache.org/licenses/LICENSE-2.0
+~~
+~~ Unless required by applicable law or agreed to in writing, software
+~~ distributed under the License is distributed on an "AS IS" BASIS,
+~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~~ See the License for the specific language governing permissions and
+~~ limitations under the License.
+ ------
+Download Apache log4cxx 0.10.0
+ ------
+ ------
+ ------
+
+Download Apache log4cxx 0.10.0
+
+ Apache log4cxx 0.10.0 is distributed under the {{{http://www.apache.org/licenses/LICENSE-2.0.html} Apache License, version 2.0}}.
+
+ The link in the Mirrors column should display a list of available mirrors with a
+ default selection based on your inferred location. If you do not see that page,
+ try a different browser. The checksum and signature are links to
+ the originals on the main distribution server.
+
+*-------------------------+---------+----------+-----------+
+| | Mirrors | Checksum | Signature |
+*-------------------------+---------+----------+-----------+
+| Apache log4cxx 0.10.0 (tar.gz) | {{{http://www.apache.org/dyn/closer.cgi/logging/log4cxx/0.10.0/apache-log4cxx-0.10.0.tar.gz} apache-log4cxx-0.10.0.tar.gz}} | {{{http://www.apache.org/dist/logging/log4cxx/0.10.0/apache-log4cxx-0.10.0.tar.gz.md5} apache-log4cxx-0.10.0.tar.gz.md5}} | {{{http://www.apache.org/dist/logging/log4cxx/0.10.0/apache-log4cxx-0.10.0.tar.gz.asc} apache-log4cxx-0.10.0.tar.gz.asc}} |
+*-------------------------+---------+----------+-----------+
+| Apache log4cxx 0.10.0 (zip) | {{{http://www.apache.org/dyn/closer.cgi/logging/log4cxx/0.10.0/apache-log4cxx-0.10.0.zip} apache-log4cxx-0.10.0.zip}} | {{{http://www.apache.org/dist/logging/log4cxx/0.10.0/apache-log4cxx-0.10.0.zip.md5} apache-log4cxx-0.10.0.zip.md5}} | {{{http://www.apache.org/dist/logging/log4cxx/0.10.0/apache-log4cxx-0.10.0.zip.asc} apache-log4cxx-0.10.0.zip.asc}} |
+*-------------------------+---------+----------+-----------+
+
+ Please read {{{http://httpd.apache.org/dev/verification.html}Verifying Apache HTTP Server Releases}}
+ for more information on why you should verify our releases.
+
+
+* Previous Releases
+
+ All previous releases of Apache log4cxx can be found in the {{{http://archive.apache.org/dist/logging/log4cxx}archive repository}}.
diff --git a/src/site/doxy/Doxyfile.in b/src/site/doxy/Doxyfile.in
new file mode 100644
index 0000000..f39ae74
--- /dev/null
+++ b/src/site/doxy/Doxyfile.in
@@ -0,0 +1,1306 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Doxyfile 1.5.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file that
+# follow. The default is UTF-8 which is also the encoding used for all text before
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
+# possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = "Apache log4cxx"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = "Version @VERSION@"
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = .
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be extracted
+# and appear in the documentation as a namespace called 'anonymous_namespace{file}',
+# where file will be replaced with the base name of the file that contains the anonymous
+# namespace. By default anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= NO
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = NO
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text "
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = \
+ @base_dir@/src/main/include \
+ @base_dir@/src/site/doxy/mainpage.dox
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS = *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH
+# then you must also enable this option. If you don't then doxygen will produce
+# a warning and turn it on anyway
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 2
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = @manual_dest@
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = @base_dir@/src/site/doxy/license_notice_footer.txt
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = YES
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = LOG4CXX_WCHAR_T_API \
+ LOG4CXX_UNICHAR_API \
+ LOG4CXX_CFSTRING_API
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = NO
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the number
+# of direct children of the root node in a graph is already larger than
+# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/src/site/doxy/Makefile.am b/src/site/doxy/Makefile.am
new file mode 100644
index 0000000..0c7293d
--- /dev/null
+++ b/src/site/doxy/Makefile.am
@@ -0,0 +1,86 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+EXTRA_DIST = Doxyfile mainpage.dox license_notice_footer.txt
+
+# DOC is defined if installer requests doc generation.
+
+
+if DOC
+
+htmldest = $(pkgdatadir)/html
+
+install-data-hook:
+ $(mkinstalldirs) $(DESTDIR)$(htmldest)
+ cp -dpR @manual_dest@/* $(DESTDIR)$(htmldest)
+
+# Automake's "distcheck" is sensitive to having files left over
+# after "make uninstall", so we have to clean up the install hook.
+uninstall-local:
+ rm -rf $(DESTDIR)$(htmldest)
+
+dox: @manual_dest@/index.html
+
+if LATEX_DOC
+
+pdf: @PACKAGE@.pdf
+@PACKAGE@.pdf:
+ $(MAKE) -C ./latex pdf
+ ln -s ./latex/refman.ps @PACKAGE@.ps
+ ln -s ./latex/refman.pdf @PACKAGE@.pdf
+
+endif
+
+else
+
+# We repeat the three targets in both the "if" and "else" clauses
+# of the conditional, because the generated makefile will contain
+# references to the targets (target "install" depends on target
+# "install-datahook", for example), and some make programs get upset
+# if no target exists.
+
+install-data-hook:
+uninstall-local:
+dox:
+
+endif
+
+
+all-local: dox
+
+
+@manual_dest@/index.html: Doxyfile mainpage.dox
+ "@DOXYGEN@"
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)
+
+# Make tarfile to distribute the HTML documentation.
+doc-dist: dox
+ rm -rf $(distdir)
+ mkdir $(distdir)
+ mkdir $(distdir)/docs
+ mkdir $(distdir)/docs/html
+ cp @manual_dest@/* $(distdir)/docs/html
+ tar -czf $(top_builddir)/$(PACKAGE)-docs-$(VERSION).tar.gz -C $(distdir) docs
+ rm -rf $(distdir)
+
+
+clean-local:
+ $(RM) -r latex
+ $(RM) -r @manual_dest@ man @PACKAGE@.ps @PACKAGE@.pdf
+
+dist-hook:
+ -rm -f $(distdir)/Doxyfile
+
diff --git a/src/site/doxy/license_notice_footer.txt b/src/site/doxy/license_notice_footer.txt
new file mode 100644
index 0000000..53eb256
--- /dev/null
+++ b/src/site/doxy/license_notice_footer.txt
@@ -0,0 +1 @@
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> </BODY> </HTML> \ No newline at end of file
diff --git a/src/site/doxy/mainpage.dox b/src/site/doxy/mainpage.dox
new file mode 100755
index 0000000..b87d2c8
--- /dev/null
+++ b/src/site/doxy/mainpage.dox
@@ -0,0 +1,22 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*/
+/** @mainpage
+
+\ref Introduction
+<p>
+\ref LoggingMacros
diff --git a/src/site/fml/Makefile.am b/src/site/fml/Makefile.am
new file mode 100644
index 0000000..8e6be87
--- /dev/null
+++ b/src/site/fml/Makefile.am
@@ -0,0 +1,15 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
diff --git a/src/site/fml/faq.fml b/src/site/fml/faq.fml
new file mode 100644
index 0000000..dcc3521
--- /dev/null
+++ b/src/site/fml/faq.fml
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<faqs title="Frequently Asked Technical Questions">
+ <part id="faq">
+
+ <faq id="custom_levels"><question>How do I add a custom level to Apache log4cxx?</question>
+ <answer>
+ <p>This is a common topic for all the Apache logging frameworks and
+ typically motivated to try to categorize events by functionality or
+ audience. An common request is to add an AUDIT level so that the
+ user can configure AUDIT level messages to go to a specific appender.
+ However, the logger name was designed explicitly to support
+ routing of messages by topic or audience. The common
+ pattern of using classnames for logger names obscures the more
+ general capability of logger name to represent the topic or audience
+ of the logging request. The easiest approach to solve the underlying issue
+ is to use a logger names like "AUDIT.com.example.MyPackage.MyClass"
+ that allow all AUDIT messages to be routed to a particular appender.
+ If you attempted to use a level for that then you would lose
+ the ability to distinguish between different significances within
+ the audit messages.
+ </p></answer></faq>
+
+
+ <faq id="msvc_crash"><question>My application on Windows crashes on shutdown?</question>
+ <answer>
+ <p>Apache log4cxx API calls use C++ Standard Template Library string
+ parameters. If the caller is using a different instance or type of the
+ C Runtime Library that log4cxx, then it is very likely that some memory
+ that was originally allocated by log4cxx would be freed by the caller.
+ If log4cxx and the caller are using different C RTL's, the program
+ will likely crash at the point. Use "Multithread DLL" with release
+ builds of log4cxx and "Multithread DLL Debug" with debug builds.
+ </p></answer></faq>
+
+ <faq id="unicode"><question>Does Apache log4cxx support Unicode?</question>
+ <answer>
+ <p>Yes. Apache log4cxx exposes API methods in multiple string flavors
+ const char*, std::string, wchar_t*, std::wstring, CFStringRef et al.
+ const char* and std::string are interpreted according to the
+ current locale settings. Applications should call setlocale(LC_ALL, "")
+ on startup or the C RTL will assume US-ASCII.
+ Before being processed internally, all these are converted to the
+ LogString type which is one of several supported Unicode representations
+ selected by the --with-logchar option. When using methods that take LogString arguments,
+ the LOG4CXX_STR() macro can be used to convert ASCII literals to
+ the current LogString type. FileAppenders support an encoding
+ property which should be explicitly specified to "UTF-8" or "UTF-16"
+ for XML files.
+ </p></answer></faq>
+
+
+ </part>
+</faqs>
diff --git a/src/site/resources/.htaccess b/src/site/resources/.htaccess
new file mode 100644
index 0000000..fd861ac
--- /dev/null
+++ b/src/site/resources/.htaccess
@@ -0,0 +1,33 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+<IfModule mod_rewrite.c>
+ RewriteEngine on
+ #
+ # rewrite site requests to equivalent new URLs
+ #
+ RewriteRule ^contributing\.html$ http://logging.apache.org/log4cxx/issue-tracking.html [R=permanent,L]
+ RewriteRule ^roadmap\.html$ http://logging.apache.org/log4cxx/issue-tracking.html [R=permanent,L]
+ RewriteRule ^support\.html$ http://logging.apache.org/log4cxx/index.html [R=permanent,L]
+ RewriteRule ^team\.html$ http://logging.apache.org/team-list.html [R=permanent,L]
+ RewriteRule ^performance\.html$ http://logging.apache.org/log4cxx/index.html [R=permanent,L]
+ RewriteRule ^ChangeLog$ http://logging.apache.org/log4cxx/changes-report.html [R=permanent,L]
+ RewriteRule ^news$ http://logging.apache.org/log4cxx/changes-report.html [R=permanent,L]
+ RewriteRule ^manual\.html$ http://logging.apache.org/log4cxx/index.html [R=permanent,L]
+ RewriteRule ^manual/index\.html$ http://logging.apache.org/log4cxx/manual.html [R=permanent,L]
+ RewriteRule ^manual/(.*)$ http://logging.apache.org/log4cxx/apidocs/$1 [R=permanent,L]
+ RewriteRule ^manual\.html/index\.html$ http://logging.apache.org/log4cxx/manual.html [R=permanent,L]
+ RewriteRule ^manual\.html/(.*)$ http://logging.apache.org/log4cxx/apidocs/$1 [R=permanent,L]
+</IfModule>
diff --git a/src/site/resources/css/site.css b/src/site/resources/css/site.css
new file mode 100644
index 0000000..1e70f6c
--- /dev/null
+++ b/src/site/resources/css/site.css
@@ -0,0 +1,17 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
diff --git a/src/site/resources/images/ls-logo.jpg b/src/site/resources/images/ls-logo.jpg
new file mode 100755
index 0000000..611c5c3
--- /dev/null
+++ b/src/site/resources/images/ls-logo.jpg
Binary files differ
diff --git a/src/site/resources/images/od.gif b/src/site/resources/images/od.gif
new file mode 100644
index 0000000..3f2326c
--- /dev/null
+++ b/src/site/resources/images/od.gif
Binary files differ
diff --git a/src/site/site.xml b/src/site/site.xml
new file mode 100644
index 0000000..55f3d77
--- /dev/null
+++ b/src/site/site.xml
@@ -0,0 +1,69 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project name="log4cxx">
+ <bannerLeft>
+ <name>Logging Services</name>
+ <src>images/ls-logo.jpg</src>
+ <href>http://logging.apache.org/</href>
+ </bannerLeft>
+ <body>
+ <breadcrumbs>
+ <item name="Apache" href="http://www.apache.org/"/>
+ <item name="Logging Services" href="http://logging.apache.org/"/>
+ <item name="log4cxx" href="http://logging.apache.org:80/log4cxx/"/>
+ </breadcrumbs>
+
+ <menu name="Get log4cxx">
+ <item name="Download" href="/download.html"/>
+ <item name="Changes" href="/changes-report.html"/>
+ <item name="License" href="/license.html"/>
+ </menu>
+
+ <menu name="About log4cxx">
+ <item name="What is log4cxx?" href="/index.html"/>
+ <item name="API Documentation" href="/apidocs/index.html"/>
+ <item name="FAQ" href="/faq.html"/>
+ </menu>
+
+ <menu name="Community">
+ <item name="Mailing Lists" href="/mail-lists.html"/>
+ <item name="Issue Tracking" href="/issue-tracking.html"/>
+ <item name="Wiki" href="http://wiki.apache.org/logging-log4cxx"/>
+ </menu>
+
+ <menu name="Development">
+ <item name="Repository" href="/source-repository.html"/>
+
+ <item name="Building">
+ <item name="autotools" href="/building/autotools.html"/>
+ <item name="Apache Ant" href="/building/ant.html"/>
+ <item name="Apache Maven 2" href="/building/maven.html"/>
+ <item name="Microsoft Visual Studio" href="/building/vstudio.html"/>
+ <item name="Apple Xcode" href="/building/xcode.html"/>
+ </item>
+ </menu>
+
+ <menu name="Apache">
+ <item name="Home" href="http://www.apache.org"/>
+ <item name="Sponsorship" href="http://www.apache.org/foundation/sponsorship.html"/>
+ <item name="Thanks" href="http://www.apache.org/foundation/thanks.html"/>
+ <item name="Conferences" href="http://www.apachecon.com"/>
+ </menu>
+
+ </body>
+</project>
diff --git a/src/site/xdoc/Makefile.am b/src/site/xdoc/Makefile.am
new file mode 100644
index 0000000..8e6be87
--- /dev/null
+++ b/src/site/xdoc/Makefile.am
@@ -0,0 +1,15 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml
new file mode 100644
index 0000000..929cd96
--- /dev/null
+++ b/src/site/xdoc/index.xml
@@ -0,0 +1,936 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<document>
+
+ <properties>
+ <title>Short introduction to Apache log4cxx</title>
+ </properties>
+ <body>
+<section name="Short introduction to Apache log4cxx">
+
+<h2>Introduction</h2>
+
+Apache log4cxx is a logging framework for C++ patterned after
+<a href="http://logging.apache.org/log4j">Apache log4j</a>.
+Apache log4cxx uses <a href="http://apr.apache.org">Apache Portable Runtime</a>
+for most platform-specific code and should be usable on any
+platform supported by APR. Apache log4cxx is licensed under the
+<a href="http://www.apache.org/licenses/">Apache License</a>,
+an open source license certified by the
+<a href="http://www.opensource.org/">Open Source Initiative</a>.
+
+<p>Almost every large application includes its own logging or tracing
+API. Inserting log statements into code is a low-tech method for
+debugging it. It may also be the only way because debuggers are not
+always available or applicable. This is usually the case for
+multithreaded applications and distributed applications at large.</p>
+
+<p>Experience indicates that logging is an important component of the
+development cycle. It offeres several advantages. It provides precise
+<em>context</em> about a run of the application. Once inserted into
+the code, the generation of logging output requires no human
+intervention. Moreover, log output can be saved in persistent medium
+to be studied at a later time. In addition to its use in the
+development cycle, a sufficiently rich logging package can also be
+viewed as an auditing tool.</p>
+
+<p>Logging does have its drawbacks. It can slow down an
+application. If too verbose, it can cause scrolling blindness. To
+alleviate these concerns, log4cxx is designed to be reliable, fast and
+extensible. Since logging is rarely the main focus of an application,
+the log4cxx API strives to be simple to understand and to use.</p>
+
+<h2>Loggers, Appenders and Layouts</h2>
+
+<p>Log4cxx has three main components: <em>loggers</em>,
+<em>appenders</em> and <em>layouts</em>. These three types of
+components work together to enable developers to log messages according
+to message type and level, and to control at runtime how these
+messages are formatted and where they are reported.</p>
+
+<h3>Logger hierarchy</h3>
+
+<p>The first and foremost advantage of any logging API over plain
+<code>std::cout</code> resides in its ability to disable
+certain log statements while allowing others to print unhindered. This
+capability assumes that the logging space, that is, the space of all
+possible logging statements, is categorized according to some
+developer-chosen criteria.</p>
+
+<p>Loggers are named entities. Logger names are case-sensitive and
+they follow the hierarchical naming rule:</p>
+
+<p>
+<table bgcolor="#EEEE99">
+ <tr>
+ <td>
+ <dl>
+ <dt><b>Named Hierarchy</b></dt>
+
+ <dd>A logger is said to be an <em>ancestor</em> of another
+ logger if its name followed by a dot is a prefix of the
+ <em>descendant</em> logger name. A logger is said to be a
+ <em>parent</em> of a <em>child</em> logger if there are no
+ ancestors between itself and the descendant logger.</dd>
+
+
+ </dl>
+</td></tr></table></p>
+
+
+<p>For example, the logger named <code>"com.foo"</code> is a parent
+of the logger named <code>"com.foo.Bar"</code>. Similarly,
+<code>"java"</code> is a parent of <code>"java.util"</code> and an
+ancestor of <code>"java.util.Vector"</code>. This naming scheme
+should be familiar to most developers.</p>
+
+<p>The root logger resides at the top of the logger hierarchy. It
+is exceptional in two ways:
+
+<ol>
+<li> it always exists,</li>
+<li> it cannot be retrieved by name.</li>
+</ol></p>
+<p>Invoking the class static <a
+href="apidocs/classlog4cxx_1_1Logger.html#e3">log4cxx::Logger::getRootLogger</a>
+method retrieves it. All other loggers are instantiated and
+retrieved with the class static <a
+href="apidocs/classlog4cxx_1_1Logger.html#e0">log4cxx::Logger::getLogger</a>
+method. This method takes the name of the desired logger as a
+parameter. Some of the basic methods in the Logger class are listed
+below.</p>
+
+<p><table>
+<tr bgcolor="CCCCCC">
+<td>
+<pre>
+ namespace log4cxx {
+
+ class <b>Logger</b> {
+ public:
+ // Creation &amp; retrieval methods:
+ static LoggerPtr getRootLogger();
+ static LoggerPtr getLogger(const std::string&amp; name);
+ static LoggerPtr getLogger(const std::wstring&amp; name);
+
+ }
+ }
+//
+// Use these macros instead of calling Logger methods directly.
+// Macros will handle char or wchar_t pointers or strings
+// or most right-hand side expressions of an
+// std::basic_string::operator&lt;&lt;.
+//
+#define LOG4CXX_TRACE(logger, expression) ...
+#define LOG4CXX_DEBUG(logger, expression) ...
+#define LOG4CXX_INFO(logger, expression) ...
+#define LOG4CXX_WARN(logger, expression) ...
+#define LOG4CXX_ERROR(logger, expression) ...
+#define LOG4CXX_FATAL(logger, expression) ...
+</pre>
+</td>
+</tr>
+</table></p>
+
+<p>Loggers <em>may</em> be assigned levels. The pre-defined
+levels: TRACE, DEBUG, INFO, WARN, ERROR and FATAL are defined in the <code><a
+href="apidocs/classlog4cxx_1_1Level.html">log4cxx::Level</a></code>
+class which provides accessor functions.</p>
+
+<p>If a given logger is not assigned a level, then it inherits
+one from its closest ancestor with an assigned level. More
+formally:</p>
+
+
+<p>
+<table bgcolor="#EEEE99">
+ <tr>
+ <td>
+ <dl>
+ <dt><b>Level Inheritance</b></dt>
+
+ <dd><p>The <em>inherited level</em> for a given logger
+<i>C</i>, is equal to the first non-null level in the logger
+hierarchy, starting at <i>C</i> and proceeding upwards in the
+hierarchy towards the <code>root</code> logger.</p></dd>
+
+ </dl>
+ </td>
+ </tr>
+</table></p>
+
+<p>To ensure that all loggers can eventually inherit a level,
+the root logger always has an assigned level.</p>
+
+<p>Below are four tables with various assigned level values and the
+resulting inherited levels according to the above rule.</p>
+
+<p>
+<table border="1" >
+ <tr><th>Logger<br/>name</th><th>Assigned<br/>level</th>
+ <th>Inherited<br/>level</th></tr>
+ <tr align="left"><td>root</td> <td>Proot</td> <td>Proot</td></tr>
+ <tr align="left"><td>X </td> <td>none</td> <td>Proot</td></tr>
+ <tr align="left"><td>X.Y </td> <td>none</td> <td>Proot</td></tr>
+ <tr align="left"><td>X.Y.Z</td> <td>none</td> <td>Proot</td></tr>
+ <caption align="bottom">Example 1</caption>
+</table></p>
+
+<p>In example 1 above, only the root logger is assigned a
+level. This level value, <code>Proot</code>, is inherited by the
+other loggers <code>X</code>, <code>X.Y</code> and
+<code>X.Y.Z</code>.</p>
+
+
+<p>
+<table border="1">
+ <tr><th>Logger<br/>name</th><th>Assigned<br/>level</th>
+ <th>Inherited<br/>level</th></tr>
+ <tr align="left"><td>root</td> <td>Proot</td> <td>Proot</td></tr>
+ <tr align="left"><td>X </td> <td>Px</td> <td>Px</td></tr>
+ <tr align="left"><td>X.Y </td> <td>Pxy</td> <td>Pxy</td></tr>
+ <tr align="left"><td>X.Y.Z</td> <td>Pxyz</td> <td>Pxyz</td></tr>
+ <caption align="bottom">Example 2</caption>
+ </table></p>
+
+<p>In example 2, all loggers have an assigned level value. There
+is no need for level inheritence.</p>
+
+<p><table border="1">
+ <tr><th>Logger<br/>name</th><th>Assigned<br/>level</th>
+ <th>Inherited<br/>level</th></tr>
+ <tr align="left"><td>root</td> <td>Proot</td> <td>Proot</td></tr>
+ <tr align="left"><td>X </td> <td>Px</td> <td>Px</td></tr>
+ <tr align="left"><td>X.Y </td> <td>none</td> <td>Px</td></tr>
+ <tr align="left"><td>X.Y.Z</td> <td>Pxyz</td> <td>Pxyz</td></tr>
+ <caption align="bottom">Example 3</caption>
+</table></p>
+
+<p>In example 3, the loggers <code>root</code>, <code>X</code> and
+<code>X.Y.Z</code> are assigned the levels <code>Proot</code>,
+<code>Px</code> and <code>Pxyz</code> respectively. The logger
+<code>X.Y</code> inherits its level value from its parent
+<code>X</code>.</p>
+
+<table border="1">
+ <tr><th>Logger<br/>name</th><th>Assigned<br/>level</th>
+ <th>Inherited<br/>level</th></tr>
+ <tr align="left"><td>root</td> <td>Proot</td> <td>Proot</td></tr>
+ <tr align="left"><td>X </td> <td>Px</td> <td>Px</td></tr>
+ <tr align="left"><td>X.Y </td> <td>none</td> <td>Px</td></tr>
+ <tr align="left"><td>X.Y.Z</td> <td>none</td> <td>Px</td></tr>
+ <caption align="bottom">Example 4</caption>
+</table>
+
+<p>In example 4, the loggers <code>root</code> and <code>X</code>
+and are assigned the levels <code>Proot</code> and <code>Px</code>
+respectively. The loggers <code>X.Y</code> and <code>X.Y.Z</code>
+inherits their level value from their nearest parent <code>X</code>
+having an assigned level.</p>
+
+
+<p>Logging requests are made by invoking a method of
+a logger instance, preferrably through the use of LOG4CXX_INFO or similar
+macros which support short-circuiting if the threshold is not satisfied
+and use of the insertion operator (&lt;&lt;) in the message parameter.</p>
+
+<p><table bgcolor="CCCCCC"><tr><td><pre>
+ log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(<strong>"com.foo"</strong>));
+ const char* region = "World";
+ LOG4CXX_INFO(logger, "Simple message text.");
+ LOG4CXX_INFO(logger, "Hello, " &lt;&lt; region);
+ LOG4CXX_DEBUG(logger, L"Iteration " &lt;&lt; i);
+ LOG4CXX_DEBUG(logger, "e^10 = " &lt;&lt; std::scientific &lt;&lt; exp(10.0));
+ //
+ // Use a wchar_t first operand to force use of wchar_t based stream.
+ //
+ LOG4CXX_WARN(logger, L"" &lt;&lt; i &lt;&lt; L" is the number of the iteration.");
+</pre></td></tr></table></p>
+
+<p>A logging request is said to be <em>enabled</em> if its level is
+higher than or equal to the level of its logger. Otherwise, the
+request is said to be <em>disabled</em>. A logger without an
+assigned level will inherit one from the hierarchy. This rule is
+summarized below.</p>
+
+
+<p>
+<a name="selectionRule"/><table bgcolor="#EEEE99">
+ <tr>
+ <td>
+ <dl>
+ <dt><b>Basic Selection Rule</b></dt>
+
+ <dd><p>A log request of level <i>p</i> in a logger with
+ (either assigned or inherited, whichever is appropriate) level <i>q</i>, is enabled if <i> p &gt;=
+ q</i>.</p></dd>
+ </dl>
+</td></tr></table></p>
+
+<p>This rule is at the heart of log4cxx. It assumes that levels are
+ordered. For the standard levels, we have <code>TRACE &lt; DEBUG &lt; INFO
+&lt; WARN &lt; ERROR &lt; FATAL</code>.</p>
+
+<p>Here is an example of this rule.</p>
+
+<p><table bgcolor="CCCCCC">
+<tr><td>
+<pre>
+
+ // get a logger instance named "com.foo"
+ log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(<strong>"com.foo"</strong>));
+
+ // Now set its level. Normally you do not need to set the
+ // level of a logger programmatically. This is usually done
+ // in configuration files.
+ <strong>logger</strong>->setLevel(<font
+ color="0000AA"><strong>log4cxx::Level::getInfo()</strong></font>);
+
+ log4cxx::LoggerPtr barlogger(log4cxx::Logger::getLogger(<strong>"com.foo.Bar"</strong>);
+
+ // This request is enabled, because <font color="00AA00"><strong>WARN</strong></font> &gt;= <font color="0000AA"><strong>INFO</strong></font>.
+ LOG4CXX_WARN(logger, "Low fuel level.");
+
+ // This request is disabled, because <font color="00AA00"><strong>DEBUG</strong></font> &lt; <font color="0000AA"><strong>INFO</strong></font>.
+ LOG4CXX_DEBUG(logger, "Starting search for nearest gas station.");
+
+ // The logger instance barlogger, named "com.foo.Bar",
+ // will inherit its level from the logger named
+ // "com.foo" Thus, the following request is enabled
+ // because <font color="00AA00"><strong>INFO</strong></font> &gt;= <font color="0000AA"><strong>INFO</strong></font>.
+ LOG4CXX_INFO(barlogger. "Located nearest gas station.");
+
+ // This request is disabled, because <font color="00AA00"><strong>DEBUG</strong></font> &lt; <font color="0000AA"><strong>INFO</strong></font>.
+ LOG4CXX_DEBUG(barlogger, "Exiting gas station search");
+</pre>
+</td></tr>
+</table></p>
+
+<p>Calling the <code>getLogger</code> method with the same name will
+always return a reference to the exact same logger object.</p>
+
+<p>For example, in
+
+<table bgcolor="CCCCCC">
+<tr><td>
+<pre>
+ log4cxx::LoggerPtr x = log4cxx::Logger::getLogger("wombat");
+ log4cxx::LoggerPtr y = log4cxx::Logger::getLogger("wombat");</pre>
+</td></tr>
+</table>
+<code>x</code> and <code>y</code> refer to <em>exactly</em> the same
+logger object.</p>
+
+<p>Thus, it is possible to configure a logger and then to retrieve
+the same instance somewhere else in the code without passing around
+references. In fundamental contradiction to biological parenthood,
+where parents always preceed their children, log4cxx loggers can be
+created and configured in any order. In particular, a "parent"
+logger will find and link to its descendants even if it is
+instantiated after them.</p>
+
+<p>Configuration of the log4cxx environment is typically done at
+application initialization. The preferred way is by reading a
+configuration file. This approach will be discussed shortly.</p>
+
+<p>Log4cxx makes it easy to name loggers by <em>software
+component</em>. This can be accomplished by statically instantiating
+a logger in each class, with the logger name equal to the fully
+qualified name of the class. This is a useful and straightforward
+method of defining loggers. As the log output bears the name of the
+generating logger, this naming strategy makes it easy to identify
+the origin of a log message. However, this is only one possible,
+albeit common, strategy for naming loggers. Log4cxx does not restrict
+the possible set of loggers. The developer is free to name the
+loggers as desired.</p>
+
+<p>Nevertheless, naming loggers after the class where they are
+located seems to be the best strategy known so far.</p>
+
+<h2>Appenders and Layouts</h2>
+
+<p>The ability to selectively enable or disable logging requests based
+on their logger is only part of the picture. Log4cxx allows logging
+requests to print to multiple destinations. In log4cxx speak, an output
+destination is called an <em>appender</em>. Currently, appenders exist
+for the <a href="apidocs/classlog4cxx_1_1ConsoleAppender.html">console</a>, <a
+href="apidocs/classlog4cxx_1_1FileAppender.html">files</a>, GUI
+components, <a
+href="apidocs/classlog4cxx_1_1net_1_1SocketAppender.html">remote socket</a>
+servers, <a href="apidocs/classlog4cxx_1_1nt_1_1NTEventLogAppender.html"> NT
+Event Loggers</a>, and remote UNIX <a
+href="apidocs/classlog4cxx_1_1net_1_1SyslogAppender.html">Syslog</a>
+daemons. It is also possible to log <a href="apidocs/classlog4cxx_1_1AsyncAppender.html">asynchronously</a>.</p>
+
+<p>More than one appender can be attached to a logger.</p>
+
+<p>The <a
+href="apidocs/classlog4cxx_1_1Logger.html#a3">addAppender</a>
+method adds an appender to a given logger.
+
+<b>Each enabled logging
+request for a given logger will be forwarded to all the appenders in
+that logger as well as the appenders higher in the hierarchy.</b> In
+other words, appenders are inherited additively from the logger
+hierarchy. For example, if a console appender is added to the root
+logger, then all enabled logging requests will at least print on the
+console. If in addition a file appender is added to a logger, say
+<em>C</em>, then enabled logging requests for <em>C</em> and
+<em>C</em>'s children will print on a file <em>and</em> on the
+console. It is possible to override this default behavior so that
+appender accumulation is no longer additive by <a
+href="apidocs/classlog4cxx_1_1Logger.html#a46">setting
+the additivity flag</a> to <code>false</code>.</p>
+
+<p>The rules governing appender additivity are summarized below.</p>
+
+<p>
+<a name="additivity"/><table bgcolor="#EEEE99">
+ <tr>
+ <td>
+ <dl>
+ <dt><b>Appender Additivity</b></dt>
+
+ <dd><p>The output of a log statement of logger <i>C</i> will
+ go to all the appenders in <i>C</i> and its ancestors. This is
+ the meaning of the term "appender additivity".</p>
+
+ <p>However, if an ancestor of logger <i>C</i>, say <i>P</i>,
+ has the additivity flag set to <code>false</code>, then
+ <i>C</i>'s output will be directed to all the appenders in
+ <i>C</i> and it's ancestors upto and including <i>P</i> but
+ not the appenders in any of the ancestors of <i>P</i>.</p>
+
+ <p>Loggers have their additivity flag set to
+ <code>true</code> by default.</p></dd>
+ </dl></td></tr>
+</table></p>
+
+
+<p>The table below shows an example:</p>
+
+<p><table align="center" border="3" cellpadding="10">
+ <tr rowspan="2">
+ <th>Logger<br/>Name </th><th>Added<br/>Appenders</th> <th>Additivity<br/>Flag</th> <th>Output Targets</th> <th>Comment</th>
+ </tr>
+<tr><td>root </td><td>A1 </td><td>not applicable </td><td>A1</td>
+
+ <td>The root logger is anonymous but can be accessed with the
+ log4cxx::Logger::getRootLogger() method. There is no default appender
+ attached to root.</td></tr>
+
+<tr><td>x </td><td>A-x1, A-x2 </td><td>true </td><td>A1, A-x1, A-x2</td>
+ <td>Appenders of "x" and root.</td></tr>
+
+<tr><td>x.y </td><td>none </td><td>true </td><td>A1, A-x1, A-x2</td>
+ <td>Appenders of "x" and root.</td></tr>
+
+<tr><td>x.y.z </td><td>A-xyz1 </td><td>true </td><td>A1, A-x1, A-x2, A-xyz1</td>
+ <td>Appenders in "x.y.z", "x" and root.</td></tr>
+
+<tr><td>security </td><td>A-sec </td><td><font color="blue">false</font></td>
+ <td>A-sec</td>
+
+ <td>No appender accumulation since the additivity flag is set to
+ <code>false</code>.</td></tr>
+
+<tr><td>security.access </td><td>none </td><td> true </td><td> A-sec </td><td>Only
+ appenders of "security" because the additivity flag in "security" is
+ set to <code>false</code>.</td></tr>
+
+</table>
+
+
+<p>More often than not, users wish to customize not only the output
+destination but also the output format. This is accomplished by
+associating a <em>layout</em> with an appender. The layout is
+responsible for formatting the logging request according to the user's
+wishes, whereas an appender takes care of sending the formatted output
+to its destination.</p>
+
+The <a
+href="apidocs/classlog4cxx_1_1PatternLayout.html">PatternLayout</a>, part
+of the standard log4cxx distribution, lets the user specify the output
+format according to conversion patterns similar to the C language
+<code>printf</code> function.</p>
+
+<p>For example, the PatternLayout with the conversion pattern "%r [%t]
+%-5p %c - %m%n" will output something akin to:<br/>
+
+<pre>
+176 [main] INFO org.foo.Bar - Located nearest gas station.
+</pre></p>
+
+<p>The first field is the number of milliseconds elapsed since the
+start of the program. The second field is the thread making the log
+request. The third field is the level of the log statement. The
+fourth field is the name of the logger associated with the log
+request. The text after the '-' is the message of the statement.</p>
+
+
+<h2>Configuration</h2>
+
+<p>Inserting log requests into the application code requires a fair
+amount of planning and effort. Observation shows that approximately 4
+percent of code is dedicated to logging. Consequently, even moderately
+sized applications will have thousands of logging statements embedded
+within their code. Given their number, it becomes imperative to
+manage these log statements without the need to modify them manually.</p>
+
+<p>The log4cxx environment is fully configurable programmatically.
+However, it is far more flexible to configure log4cxx using
+configuration files. Currently, configuration files can be written in
+XML or in Java properties (key=value) format.</p>
+
+<p>Let us give a taste of how this is done with the help of an
+imaginary application <code>MyApp</code> that uses log4cxx.</p>
+
+<p><table bgcolor="CCCCCC"><tr><td>
+<pre>
+#include "com/foo/bar.h"
+using namespace com::foo;
+
+// include log4cxx header files.
+#include "log4cxx/logger.h"
+#include "log4cxx/basicconfigurator.h"
+#include "log4cxx/helpers/exception.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+LoggerPtr logger(Logger::getLogger("MyApp"));
+
+int main(int argc, char **argv)
+{
+ int result = EXIT_SUCCESS;
+ try
+ {
+ // Set up a simple configuration that logs on the console.
+ BasicConfigurator::configure();
+
+ LOG4CXX_INFO(logger, "Entering application.");
+ Bar bar;
+ bar.doIt();
+ LOG4CXX_INFO(logger, "Exiting application.");
+ }
+ catch(Exception&amp;)
+ {
+ result = EXIT_FAILURE;
+ }
+
+ return result;
+}
+</pre>
+</td></tr>
+</table></p>
+
+<p><code>MyApp</code> begins by including log4cxx headers. It
+then defines a static logger variable with the name
+<code>MyApp</code> which happens to be the fully qualified name of the
+class.</p>
+
+<p><code>MyApp</code> uses the <code>Bar</code> class defined in header
+file <code>com/foo/bar.h</code>.</p>
+
+<p><table bgcolor="CCCCCC"><tr><td>
+<pre>
+// file com/foo/bar.h
+#include "log4cxx/logger.h"
+
+namespace com {
+ namespace foo {
+ class Bar {
+ static log4cxx::LoggerPtr logger;
+
+ public:
+ void doIt();
+ }
+ }
+}
+</pre>
+
+<pre>
+// file bar.cpp
+#include "com/foo/bar.h"
+
+using namespace com::foo;
+using namespace log4cxx;
+
+LoggerPtr Bar::logger(Logger::getLogger("com.foo.bar"));
+
+void Bar::doIt() {
+ LOG4CXX_DEBUG(logger, "Did it again!");
+}
+</pre>
+</td></tr>
+</table></p>
+
+<p>The invocation of the <a
+href="apidocs/classlog4cxx_1_1BasicConfigurator.html#e0">BasicConfigurator::configure</a>
+method creates a rather simple log4cxx setup. This method is hardwired
+to add to the root logger a <a
+href="apidocs/classlog4cxx_1_1ConsoleAppender.html">
+ConsoleAppender</a>. The output will be formatted using a <a
+href="apidocs/classlog4cxx_1_1PatternLayout.html">PatternLayout</a> set
+to the pattern "%-4r [%t] %-5p %c %x - %m%n".</p>
+
+<p>Note that by default, the root logger is assigned to
+<code>Level::getDebug()</code>.</p>
+
+<p>The output of MyApp is:
+<pre>
+0 [12345] INFO MyApp - Entering application.
+36 [12345] DEBUG com.foo.Bar - Did it again!
+51 [12345] INFO MyApp - Exiting application.
+</pre></p>
+
+<p>The previous example always outputs the same log information.
+Fortunately, it is easy to modify <code>MyApp</code> so that the log
+output can be controlled at run-time. Here is a slightly modified
+version.</p>
+
+<p><table bgcolor="CCCCCC"><tr><td>
+<pre>
+// file MyApp2.cpp
+
+#include "com/foo/bar.h"
+using namespace com::foo;
+
+// include log4cxx header files.
+#include "log4cxx/logger.h"
+#include "log4cxx/basicconfigurator.h"
+#include "log4cxx/propertyconfigurator.h"
+#include "log4cxx/helpers/exception.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+// Define a static logger variable so that it references the
+// Logger instance named "MyApp".
+LoggerPtr logger(Logger::getLogger("MyApp"));
+
+int main(int argc, char **argv)
+{
+ int result = EXIT_SUCCESS;
+ try
+ {
+ if (argc > 1)
+ {
+ // BasicConfigurator replaced with PropertyConfigurator.
+ PropertyConfigurator::configure(argv[1]);
+ }
+ else
+ {
+ BasicConfigurator::configure();
+ }
+
+ LOG4CXX_INFO(logger, "Entering application.");
+ Bar bar
+ bar.doIt();
+ LOG4CXX_INFO(logger, "Exiting application.");
+ }
+ catch(Exception&amp;)
+ {
+ result = EXIT_FAILURE;
+ }
+
+ return result;
+}
+</pre>
+</td></tr>
+</table>
+
+<p>This version of <code>MyApp</code> instructs
+<code>PropertyConfigurator</code> to parse a configuration file and
+set up logging accordingly.</p>
+
+<p>Here is a sample configuration file that results in exactly same
+output as the previous <code>BasicConfigurator</code> based example.</p>
+
+<p><table bgcolor="CCAAAA"><tr><td>
+<pre>
+# Set root logger level to DEBUG and its only appender to A1.
+log4j.rootLogger=DEBUG, A1
+
+# A1 is set to be a ConsoleAppender.
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+# A1 uses PatternLayout.
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+</pre>
+</td></tr></table></p>
+
+<p>It can be noticed that the PropertyConfigurator file format is the same as log4j.</p>
+
+<p>Suppose we are no longer interested in seeing the output of any
+component belonging to the <code>com::foo</code> package. The following
+configuration file shows one possible way of achieving this.</p>
+
+<p><table bgcolor="CCAAAA"><tr><td>
+<pre>
+log4j.rootLogger=DEBUG, A1
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+
+# <strong>Print the date in ISO 8601 format</strong>
+log4j.appender.A1.layout.ConversionPattern=<strong>%d</strong> [%t] %-5p %c - %m%n
+
+# Print only messages of level WARN or above in the package com.foo.
+<strong>log4j.logger.com.foo=WARN</strong>
+</pre>
+</td></tr></table></p>
+
+<p>The output of <code>MyApp</code> configured with this file is shown below.</p>
+
+<pre>
+<strong>2000-09-07 14:07:41,508</strong> [12345] INFO MyApp - Entering application.
+<strong>2000-09-07 14:07:41,529</strong> [12345] INFO MyApp - Exiting application.
+</pre>
+
+<p>As the logger <code>com.foo.Bar</code> does not have an assigned
+level, it inherits its level from <code>com.foo</code>, which
+was set to WARN in the configuration file. The log statement from the
+<code>Bar::doIt</code> method has the level DEBUG, lower than the
+logger level WARN. Consequently, <code>doIt()</code> method's log
+request is suppressed.</p>
+
+<p>Here is another configuration file that uses multiple appenders.</p>
+
+<p><table bgcolor="CCAAAA"><tr><td>
+<pre>
+log4j.rootLogger=debug, <strong>stdout, R</strong>
+
+log4j.appender.<strong>stdout</strong>=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+
+# Pattern to output the caller's file name and line number.
+log4j.appender.stdout.layout.ConversionPattern=%5p [%t] <strong>(%F:%L)</strong> - %m%n
+
+log4j.appender.<strong>R</strong>=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=example.log
+
+log4j.appender.R.MaxFileSize=<strong>100KB</strong>
+# Keep one backup file
+log4j.appender.R.MaxBackupIndex=1
+
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
+</pre>
+</td></tr></table></p>
+
+<p>Calling the enhanced MyApp with the this configuration file will
+output the following on the console.</p>
+
+<pre>
+ INFO [12345] <strong>(MyApp2.cpp:31)</strong> - Entering application.
+DEBUG [12345] (Bar.h:16) - Doing it again!
+ INFO [12345] (MyApp2.cpp:34) - Exiting application.
+</pre></p>
+
+<p>In addition, as the root logger has been allocated a second
+appender, output will also be directed to the <code>example.log</code>
+file. This file will be rolled over when it reaches 100KB. When
+roll-over occurs, the old version of <code>example.log</code> is
+automatically moved to <code>example.log.1</code>.</p>
+
+<p>Note that to obtain these different logging behaviors we did not
+need to recompile code. We could just as easily have logged to a UNIX
+Syslog daemon, redirected all <code>com.foo</code> output to an NT
+Event logger, or forwarded logging events to a remote log4cxx server,
+which would log according to local server policy, for example by
+forwarding the log event to a second log4cxx server.</p>
+
+<a name="defaultInit"/><h2>Default Initialization Procedure</h2>
+
+<p>The log4cxx library does not make any assumptions about its
+environment. In particular, there are no default log4cxx
+appenders. Under certain well-defined circumstances however, the
+static inializer of the <code>Logger</code> class will attempt to
+automatically configure log4cxx.</p>
+
+<p>The exact default initialization algorithm is defined as follows:</p>
+
+<ol>
+
+ <li><p>Set the configurationOptionStr string variable to the value of the
+ <b>LOG4CXX_CONFIGURATION</b> environment variable if set, otherwise
+ the value of the <b>log4j.configuration</b> or <b>LOG4CXX_CONFIGURATION</b>
+ environment variable if set,
+ otherwise the first of the following file names which exist in the
+ current working directory, "log4cxx.xml", "log4cxx.properties",
+ "log4j.xml" and "log4j.properties".
+ If configurationOptionStr has not been set, then disable logging.</p></li>
+
+ <li><p>Unless a custom configurator is specified using the
+ <b>LOG4CXX_CONFIGURATOR_CLASS</b> or <b>log4j.configuratorClass</b>
+ environment variable, the PropertyConfigurator will be used to configure
+ log4cxx unless the file name ends with the ".xml" extension,
+ in which case the DOMConfigurator will be used.
+ If a custom configurator is specified, the environment variable
+ should contain a fully qualified class name of a class that
+ implements the Configurator interface.</p>
+ </li>
+
+</ol>
+
+
+<h2> Nested Diagnostic Contexts</h2>
+
+<p>Most real-world systems have to deal with multiple clients
+simultaneously. In a typical multithreaded implementation of such a
+system, different threads will handle different clients. Logging is
+especially well suited to trace and debug complex distributed
+applications. A common approach to differentiate the logging output of
+one client from another is to instantiate a new separate logger for
+each client. This promotes the proliferation of loggers and
+increases the management overhead of logging.</p>
+
+<p>A lighter technique is to uniquely stamp each log request initiated
+from the same client interaction. Neil Harrison described this method
+in the book "Patterns for Logging Diagnostic Messages," in <em>Pattern
+Languages of Program Design 3</em>, edited by R. Martin, D. Riehle,
+and F. Buschmann (Addison-Wesley, 1997).</p>
+
+
+
+<p> To uniquely stamp each request, the
+user pushes contextual information into the NDC, the abbreviation of
+<em>Nested Diagnostic Context</em>. The NDC class is shown below.
+
+<pre>
+namespace log4cxx {
+ class NDC {
+ public:
+ // pushes the value on construction and pops on destruction.
+ NDC(const std::string&amp; value);
+ NDC(const std::wstring&amp; value);
+
+ // Remove the top of the context from the NDC.
+ <strong>static</strong> LogString pop();
+
+ // Add diagnostic context for the current thread.
+ <strong>static</strong> void push(const std::string&amp; message);
+ <strong>static</strong> void push(const std::wstring&amp; message);
+ }
+</pre></p>
+
+<p>The NDC is managed per thread as a <em>stack</em> of contextual
+information. Note that all methods of the <code>log4cxx::NDC</code>
+class are static. Assuming that NDC printing is turned on, every time
+a log request is made, the appropriate log4cxx component will include
+the <em>entire</em> NDC stack for the current thread in the log
+output. This is done without the intervention of the user, who is
+responsible only for placing the correct information in the NDC by
+using the <code>push</code> and <code>pop</code> methods at a few
+well-defined points in the code. In contrast, the per-client logger
+approach commands extensive changes in the code.</p>
+
+<p>To illustrate this point, let us take the example of a servlet
+delivering content to numerous clients. The servlet can build the NDC
+at the very beginning of the request before executing other code. The
+contextual information can be the client's host name and other
+information inherent to the request, typically information contained
+in cookies. Hence, even if the servlet is serving multiple clients
+simultaneously, the logs initiated by the same code, i.e. belonging to
+the same logger, can still be distinguished because each client
+request will have a different NDC stack. Contrast this with the
+complexity of passing a freshly instantiated logger to all code
+exercised during the client's request.</p>
+
+<p>Nevertheless, some sophisticated applications, such as virtual
+hosting web servers, must log differently depending on the virtual
+host context and also depending on the software component issuing the
+request. Recent log4cxx releases support multiple hierarchy trees. This
+enhancement allows each virtual host to possess its own copy of the
+logger hierarchy.</p>
+
+
+<a name="performance"/><h2>Performance</h2>
+
+<p>One of the often-cited arguments against logging is its
+computational cost. This is a legitimate concern as even moderately
+sized applications can generate thousands of log requests. Much
+effort was spent measuring and tweaking logging performance. Log4cxx
+claims to be fast and flexible: speed first, flexibility second.</p>
+
+<p>The user should be aware of the following performance issues.</p>
+
+<ol>
+ <li><b>Logging performance when logging is turned off.</b><br/>
+
+ <p>When logging is turned
+ off entirely or just for a set
+ of levels, the cost of a log request consists of a method
+ invocation plus an integer comparison. The LOG4CXX_DEBUG and similar
+ macros suppress unnecessary expression evaluation if the
+ request is not enabled.</p></li>
+
+ <li><b>The performance of deciding whether to log or not to log when
+ logging is turned on.</b><br/>
+
+ <p>This is essentially the performance of walking the logger
+ hierarchy. When logging is turned on, log4cxx still needs to compare
+ the level of the log request with the level of the request
+ logger. However, loggers may not have an assigned
+ level; they can inherit them from the logger hierarchy. Thus,
+ before inheriting a level, the logger may need to search its
+ ancestors.</p>
+
+ <p>There has been a serious effort to make this hierarchy walk to
+be as fast as possible. For example, child loggers link only to
+their existing ancestors. In the <code>BasicConfigurator</code>
+example shown earlier, the logger named <code>com.foo.Bar</code> is
+linked directly to the root logger, thereby circumventing the
+nonexistent <code>com</code> or <code>com.foo</code> loggers. This
+significantly improves the speed of the walk, especially in "sparse"
+hierarchies.</p>
+
+ <p>The cost of walking the hierarchy is typically 3
+ times slower than when logging is turned off entirely.</p></li>
+
+ <li><b>Actually outputting log messages</b><br/>
+
+ <p>This is the cost of formatting the log output and sending it to
+ its target destination. Here again, a serious effort was made to
+ make layouts (formatters) perform as quickly as possible. The same
+ is true for appenders.</p>
+
+ </li>
+
+</ol>
+
+
+<h2>Conclusions</h2>
+
+<p>Apache Log4cxx is a popular logging package written in C++. One of its
+distinctive features is the notion of inheritance in loggers. Using
+a logger hierarchy it is possible to control which log statements
+are output at arbitrary granularity. This helps reduce the volume of
+logged output and minimize the cost of logging.</p>
+
+<p>One of the advantages of the log4cxx API is its manageability. Once
+the log statements have been inserted into the code, they can be
+controlled with configuration files. They can be selectively enabled
+or disabled, and sent to different and multiple output targets in
+user-chosen formats. The log4cxx package is designed so that log
+statements can remain in shipped code without incurring a heavy
+performance cost.</p>
+
+</section>
+</body>
+</document> \ No newline at end of file
diff --git a/src/site/xdoc/stylesheets/project.xml b/src/site/xdoc/stylesheets/project.xml
new file mode 100755
index 0000000..29d68e8
--- /dev/null
+++ b/src/site/xdoc/stylesheets/project.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project name="Logging Services"
+ href="http://logging.apache.org/">
+
+ <title>log4cxx</title>
+ <!-- <logo href="images/logo.jpg">Apache Logging Services</logo> -->
+ <copyright year="2004-2006" />
+
+ <body>
+
+ <menu name="Apache">
+ <item name="Apache Home" href="http://www.apache.org" />
+ <item name="Logging Services" href="http://logging.apache.org/" />
+ </menu>
+
+ <menu name="log4cxx project">
+ <item name="Introduction" href="/index.html"/>
+ <item name="Download" href="/download.html"/>
+ <item name="Documentation" href="/manual/Introduction.html"/>
+ <item name="SVN Repositories" href="http://logging.apache.org/site/cvs-repositories.html"/>
+ <item name="Mailing Lists" href="http://logging.apache.org/site/mailing-lists.html"/>
+ <item name="Bug Reporting" href="http://logging.apache.org/site/bugreport.html"/>
+ </menu>
+
+ </body>
+</project>
diff --git a/src/site/xdoc/stylesheets/site.css b/src/site/xdoc/stylesheets/site.css
new file mode 100644
index 0000000..73cd1bb
--- /dev/null
+++ b/src/site/xdoc/stylesheets/site.css
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+H1, H2, H3 {
+ color: #101099;
+}
+
+A:link, A:visited {
+ text-decoration: none;
+ color: #006699;
+}
+
+A:link:hover {
+ text-decoration: underline;
+}
+
+.centercol {
+ margin-top: 120px;
+ margin-left: 210px;
+ margin-right:210px;
+ max-width: 800px;
+}
+
+.leftcol {
+ position: absolute;
+ left: 10px;
+ top: 130px;
+ width: 190px;
+}
+
+.banner {
+ position: absolute;
+ left: 10px;
+ top: 10px;
+ height: 130px;
+ width: 1000px;
+}
+
+.menu_header, .menu_item {
+/* width: 190px; */
+ font-family: "trebuchet MS", Arial, Helvetica, sans-serif;
+ font-size: smaller;
+}
+
+.menu_header {
+ border:1px solid #AAAAAA;
+ background: #CCCCCC;
+ padding-left: 1ex;
+}
+
+.menu_item:hover {
+ background: #DDD;
+}
+
+.menu_item {
+ background: #EEEEEE;
+ padding-left: 2ex;
+ border-top: 0px solid #AAAAAA;
+ border-right: 1px solid #AAAAAA;
+ border-bottom:1px solid #AAAAAA;
+ border-left: 1px solid #AAAAAA;
+}
+
+.source {
+ border-top: 1px solid #DDDDDD;
+ border-bottom: 1px solid #DDDDDD;
+ background:#eee;
+ font-family: Courier, "MS Courier New", Prestige, Everson Monocourrier, monospace;
+ font-size: smaller;
+ padding-bottom: 0.5ex;
+ padding-top: 0.5ex;
+ padding-left: 2ex;
+}
+
+table.ls {
+ background: #FFFFFF;
+}
+table.ls td {
+ background: #f4f4f4;
+ vertical-align: top;
+ padding-bottom: 1ex;
+}
+
+table.ls th {
+ background: #E4E4E4;
+}
+
+.index-faqSection {
+ font-size: larger;
+ padding-left: 0em;
+ font-weight: bolder;
+}
+.index-question {
+ padding-left: 1em;
+}
+
+.faqSection {
+ font-size: larger;
+ font-weight: bolder;
+}
+
+.question {
+ font-weight: bolder;
+}
+
+/* this class is used for screen output placed in <pre></pre> tags */
+.screen_output {
+ padding-left: 1em;
+ padding-right: 1em;
+ border-top: 1px solid #AAAAAA;
+ border-right: 1px solid #AAAAAA;
+ border-bottom:1px solid #AAAAAA;
+ border-left: 1px solid #AAAAAA;
+}
+
+
+.big {
+ font-size: larger;
+ font-weight: bold;
+}
+
+.small {
+ font-size: smaller;
+}
+
+.red {
+ color: #AA0000;
+}
+
+.msg_title {
+ padding-left: 1ex;
+ padding-right: 1ex;
+ font-family: Courier, "MS Courier New", Prestige, Everson Monocourrier, monospace;
+ border: 1px solid #AAAAAA;
+ background: #DDDDFF;
+
+}
+
+.msg_meaning {
+ padding-left: 1em;
+ padding-right: 1em;
+}
diff --git a/src/site/xdoc/stylesheets/site.vsl b/src/site/xdoc/stylesheets/site.vsl
new file mode 100755
index 0000000..04cf801
--- /dev/null
+++ b/src/site/xdoc/stylesheets/site.vsl
@@ -0,0 +1,357 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<!-- Content Stylesheet for Site -->
+
+ ## Defined variables
+ #set ($bodybg = "#ffffff")
+ #set ($bodyfg = "#000000")
+ #set ($bodylink = "#525D76")
+
+ #set ($titlebg = "#FFFFFF")
+ #set ($titlefg = "#2222AA")
+
+## #set ($bannerbg = "#525D76")
+ #set ($bannerbg = "#FFFFFF")
+ #set ($bannerfg = "#2222AA")
+
+ #set ($subbannerbg = "#828DA6")
+ #set ($subbannerfg = "#ffffff")
+ #set ($tablethbg = "#039acc")
+ #set ($tabletdbg = "#a0ddf0")
+
+<!-- start the processing -->
+#document()
+<!-- end the processing -->
+
+## This is where the macro's live
+
+#macro ( table $table)
+<table>
+ #foreach ( $items in $table.getChildren() )
+ #if ($items.getName().equals("tr"))
+ #tr ($items)
+ #end
+ #end
+</table>
+#end
+
+#macro ( tr $tr)
+<tr>
+ #foreach ( $items in $tr.getChildren() )
+ #if ($items.getName().equals("td"))
+ #td ($items)
+ #elseif ($items.getName().equals("th"))
+ #th ($items)
+ #end
+ #end
+</tr>
+#end
+
+#macro ( td $value)
+#if ($value.getAttributeValue("colspan"))
+#set ($colspan = $value.getAttributeValue("colspan"))
+#end
+#if ($value.getAttributeValue("rowspan"))
+#set ($rowspan = $value.getAttributeValue("rowspan"))
+#end
+<td bgcolor="$tabletdbg" colspan="$!colspan" rowspan="$!rowspan" valign="top" align="left">
+ <font color="#000000" size="-1" face="arial,helvetica,sanserif">
+ #if ($value.getText().length() != 0 || $value.hasChildren())
+ $value.getContent()
+ #else
+ &nbsp;
+ #end
+ </font>
+</td>
+#end
+
+#macro ( th $value)
+#if ($value.getAttributeValue("colspan"))
+#set ($colspan = $value.getAttributeValue("colspan"))
+#end
+#if ($value.getAttributeValue("rowspan"))
+#set ($rowspan = $value.getAttributeValue("rowspan"))
+#end
+<th bgcolor="$tablethbg" colspan="$!colspan" rowspan="$!rowspan" valign="top" align="left">
+ <font color="#000000" size="-1" face="arial,helvetica,sanserif">
+ #if ($value.getText().length() != 0 || $value.hasChildren())
+ $value.getContent()
+ #else
+ &nbsp;
+ #end
+ </font>
+</th>
+#end
+
+#macro ( projectanchor $name $value )
+#if ($value.startsWith("http://"))
+ <a href="$value">$name</a>
+## #elseif ($value.startsWith("/site"))
+## <a href="http://logging.apache.org/site/$value">$name</a>
+#else
+ <a href="$relativePath$value">$name</a>
+#end
+#end
+
+#macro ( metaauthor $author $email )
+ <meta name="author" value="$author">
+ <meta name="email" value="$email">
+#end
+
+#macro ( image $value )
+#if ($value.getAttributeValue("width"))
+#set ($width=$value.getAttributeValue("width"))
+#end
+#if ($value.getAttributeValue("height"))
+#set ($height=$value.getAttributeValue("height"))
+#end
+#if ($value.getAttributeValue("align"))
+#set ($align=$value.getAttributeValue("align"))
+#end
+<img src="$relativePath$value.getAttributeValue("src")" width="$!width" height="$!height" align="$!align">
+#end
+
+#macro ( source $value)
+ <div align="left">
+ <table cellspacing="4" cellpadding="0" border="0">
+ <tr>
+ <td bgcolor="#023264" width="1" height="1"><img src="/images/void.gif" width="1" height="1" vspace="0" hspace="0" border="0"/></td>
+ <td bgcolor="#023264" height="1"><img src="/images/void.gif" width="1" height="1" vspace="0" hspace="0" border="0"/></td>
+ <td bgcolor="#023264" width="1" height="1"><img src="/images/void.gif" width="1" height="1" vspace="0" hspace="0" border="0"/></td>
+ </tr>
+ <tr>
+ <td bgcolor="#023264" width="1"><img src="/images/void.gif" width="1" height="1" vspace="0" hspace="0" border="0"/></td>
+ <td bgcolor="#ffffff"><pre>$escape.getText($value.getText())</pre></td>
+ <td bgcolor="#023264" width="1"><img src="/images/void.gif" width="1" height="1" vspace="0" hspace="0" border="0"/></td>
+ </tr>
+ <tr>
+ <td bgcolor="#023264" width="1" height="1"><img src="/images/void.gif" width="1" height="1" vspace="0" hspace="0" border="0"/></td>
+ <td bgcolor="#023264" height="1"><img src="/images/void.gif" width="1" height="1" vspace="0" hspace="0" border="0"/></td>
+ <td bgcolor="#023264" width="1" height="1"><img src="/images/void.gif" width="1" height="1" vspace="0" hspace="0" border="0"/></td>
+ </tr>
+ </table>
+ </div>
+#end
+
+## ============================================
+## subsection macro
+## ============================================
+#macro ( subsection $subsection)
+ <h3>$subsection.getAttributeValue("name")</strong></h3>
+ #foreach ( $items in $subsection.getChildren() )
+ #if ($items.getName().equals("img"))
+ #image ($items)
+ #elseif ($items.getName().equals("source"))
+ #source ($items)
+ #elseif ($items.getName().equals("table"))
+ #table ($items)
+ #else
+ $items
+ #end
+ #end
+#end
+
+## ===================================
+## titleSection macro
+## ===================================
+#macro ( titleSection $titleSection)
+ <font size="+2" color="$titlefg"><b>$titleSection.getAttributeValue("name")</b></font>
+#end
+
+## ================================
+## section macro
+## ================================
+#macro ( section $section)
+ <h1>$section.getAttributeValue("name")</strong></h1>
+ #foreach ( $items in $section.getChildren() )
+ #if ($items.getName().equals("img"))
+ #image ($items)
+ #elseif ($items.getName().equals("source"))
+ #source ($items)
+ #elseif ($items.getName().equals("table"))
+ #table ($items)
+ #elseif ($items.getName().equals("subsection"))
+ #subsection ($items)
+ #else
+ $items
+ #end
+ #end
+#end
+
+## ===================================
+## make navigation bar
+## ===================================
+
+#macro ( makeNavigationBar )
+ <!-- ============================================================ -->
+ <table id="navbar" border="0" cellspacing="0" cellpadding="0">
+ #set ($menus = $project.getChild("body").getChildren("menu"))
+ #foreach ( $menu in $menus )
+ #if ( $velocityCount != 1 )
+## <tr bgcolor="#999999">
+## <td><html:img page="/images/space2.gif" height="1"></html:img></td>
+## </tr>
+ #end
+ <tr >
+ <td class="navbarHeader" nowrap="true">
+ <strong>$menu.getAttributeValue("name")</strong>
+ </td>
+ </tr>
+ #foreach ( $item in $menu.getChildren() )
+ #set ($name = $item.getAttributeValue("name"))
+ <tr><td class="navbarItem"><small>#projectanchor($name $item.getAttributeValue("href"))</small></td></tr>
+ #end
+ #end
+ </table>
+
+#end
+
+## ====================================
+## getProjectImage
+## ====================================
+#macro (getProjectImage)
+ #if ($project.getChild("logo"))
+ <td align="left">
+ <a href="http://logging.apache.org">
+ <img src="http://logging.apache.org/images/ls-logo.jpg" border="0"/></a>
+ </td>
+ <td align="right">
+ #set ( $logoString = $project.getChild("logo").getAttributeValue("href") )
+ #if ( $logoString.startsWith("/") )
+ <a href="$project.getAttributeValue("href")">
+ <img src="$relativePath$logoString"
+ alt="$project.getChild("logo").getText()" border="0"/>
+ </a>
+ #else
+ <a href="$project.getAttributeValue("href")">
+ <img src="$relativePath/$logoString" alt="$project.getChild("logo").getText()" border="0"/>
+ </a>
+ #end
+ </td>
+
+ #else
+ <td colspan="2">
+ <a href="http://logging.apache.org">
+ <img src="http://logging.apache.org/images/ls-logo.jpg" align="left" border="0"/>
+ </a>
+ </td>
+ #end
+
+#end
+
+#macro (printMeta $metaElement)
+<meta #set ($attribs = $metaElement.getAttributes())
+#foreach ($a in $attribs) $a.getName()="$a.getValue()" #end />
+#end
+
+#macro (document)
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+ <!-- ====================================================================== -->
+ <!-- GENERATED FILE, DO NOT EDIT, EDIT THE XML FILE IN xdocs INSTEAD! -->
+ <!-- Main Page Section -->
+ <!-- ====================================================================== -->
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
+
+ #set ($authors = $root.getChild("properties").getChildren("author"))
+ #foreach ( $au in $authors )
+ #metaauthor ( $au.getText() $au.getAttributeValue("email") )
+ #end
+
+ #set ($metas = $root.getChildren("meta"))
+
+ ## Parse meta directives such as
+ ## <meta name="keyword" content="jakarta, java"/>
+ #foreach ($meta in $metas) #printMeta($meta) #end
+
+ ## Support for <base> tags.
+ #if ($root.getChild("properties").getChild("base"))
+ #set ($url = $root.getChild("properties").getChild("base").getAttributeValue("href"))
+ <base href="$url"/>
+ #end
+
+ <link href="$relativePath/css/site.css" rel="stylesheet" type="text/css"/>
+
+ <title>$project.getChild("title").getText() - $root.getChild("properties").getChild("title").getText()</title>
+ </head>
+
+ <body bgcolor="$bodybg" text="$bodyfg" link="$bodylink">
+ <!-- START Header table -->
+ <table border="0" cellspacing="0" width="90%">
+ <!-- TOP IMAGE -->
+ <tr>
+ #getProjectImage()
+ </tr>
+ </table>
+ <!-- END Header table -->
+
+ <!-- START main table -->
+ <table id="main" border="0" width="90%" cellspacing="2" cellpadding="0">
+ <tr><td colspan="2">
+ <hr noshade="" size="1"/>
+ </td></tr>
+
+ <tr>
+ <!-- LEFT SIDE NAVIGATION -->
+ <td id="navbar" valign="top">
+ #makeNavigationBar()
+ </td>
+ <td id="mainContents" align="left" valign="top">
+ #foreach ( $item in $root.getChild("body").getChildren() )
+ #if ($item.getName().equals("img"))
+ #image ($item)
+ #elseif ($item.getName().equals("section"))
+ #section ($item)
+ #elseif ($item.getName().equals("source"))
+ #source ($item)
+ #elseif ($item.getName().equals("table"))
+ #table ($item)
+ #elseif ($item.getName().equals("subsection"))
+ #subsection ($item)
+ #else
+ $item
+ #end
+ #end
+
+## #if ($root.getChild("body").getChild("titleSection"))
+## #set ($titleSection = $root.getChild("body").getChild("titleSection"))
+## #titleSection($titleSection)
+## #end
+##
+## #set ($allSections = $root.getChild("body").getChildren("section"))
+## #foreach ( $section in $allSections )
+## #section ($section)
+## #end
+ </td>
+ </tr>
+
+ <!-- FOOTER -->
+ <tr><td colspan="2">
+ <hr noshade="" size="1"/>
+ </td></tr>
+ </table>
+ <!-- END main table -->
+ </body>
+ </html>
+#end
+
+
+
+
+
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
new file mode 100644
index 0000000..528d1b8
--- /dev/null
+++ b/src/test/Makefile.am
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+SUBDIRS = cpp resources
diff --git a/src/test/cpp/Makefile.am b/src/test/cpp/Makefile.am
new file mode 100644
index 0000000..626a7f7
--- /dev/null
+++ b/src/test/cpp/Makefile.am
@@ -0,0 +1,160 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+noinst_HEADERS = \
+ $(top_srcdir)/src/test/cpp/customlogger/*.h \
+ $(top_srcdir)/src/test/cpp/helpers/*.h \
+ $(top_srcdir)/src/test/cpp/net/*.h \
+ $(top_srcdir)/src/test/cpp/pattern/*.h \
+ $(top_srcdir)/src/test/cpp/util/*.h \
+ $(top_srcdir)/src/test/cpp/xml/*.h \
+ $(top_srcdir)/src/test/cpp/*.h
+
+INCLUDES = -I$(top_srcdir)/src/main/include -I$(top_builddir)/src/main/include
+
+noinst_PROGRAMS = testsuite
+
+customlogger_tests = \
+ customlogger/xlogger.cpp\
+ customlogger/xloggertestcase.cpp
+
+defaultinit_tests = \
+ defaultinit/testcase1.cpp\
+ defaultinit/testcase2.cpp\
+ defaultinit/testcase3.cpp\
+ defaultinit/testcase4.cpp
+
+helpers = \
+ helpers/absolutetimedateformattestcase.cpp \
+ helpers/cacheddateformattestcase.cpp \
+ helpers/charsetdecodertestcase.cpp \
+ helpers/charsetencodertestcase.cpp \
+ helpers/cyclicbuffertestcase.cpp\
+ helpers/datetimedateformattestcase.cpp \
+ helpers/inetaddresstestcase.cpp \
+ helpers/iso8601dateformattestcase.cpp \
+ helpers/localechanger.cpp\
+ helpers/messagebuffertest.cpp \
+ helpers/optionconvertertestcase.cpp \
+ helpers/propertiestestcase.cpp \
+ helpers/relativetimedateformattestcase.cpp \
+ helpers/stringtokenizertestcase.cpp \
+ helpers/stringhelpertestcase.cpp \
+ helpers/syslogwritertest.cpp \
+ helpers/timezonetestcase.cpp \
+ helpers/transcodertestcase.cpp
+
+net_tests = \
+ net/smtpappendertestcase.cpp \
+ net/socketappendertestcase.cpp \
+ net/sockethubappendertestcase.cpp \
+ net/socketservertestcase.cpp \
+ net/syslogappendertestcase.cpp \
+ net/telnetappendertestcase.cpp \
+ net/xmlsocketappendertestcase.cpp
+
+pattern_tests = \
+ pattern/num343patternconverter.cpp \
+ pattern/patternparsertestcase.cpp
+
+rolling_tests = \
+ rolling/filenamepatterntestcase.cpp \
+ rolling/filterbasedrollingtest.cpp \
+ rolling/manualrollingtest.cpp \
+ rolling/obsoletedailyrollingfileappendertest.cpp \
+ rolling/obsoleterollingfileappendertest.cpp \
+ rolling/sizebasedrollingtest.cpp \
+ rolling/timebasedrollingtest.cpp
+
+util = \
+ util/absolutetimefilter.cpp\
+ util/absolutedateandtimefilter.cpp\
+ util/binarycompare.cpp\
+ util/compare.cpp\
+ util/controlfilter.cpp\
+ util/filenamefilter.cpp \
+ util/utilfilter.cpp\
+ util/iso8601filter.cpp\
+ util/linenumberfilter.cpp\
+ util/relativetimefilter.cpp\
+ util/serializationtesthelper.cpp \
+ util/threadfilter.cpp\
+ util/transformer.cpp\
+ util/xmlfilenamefilter.cpp \
+ util/xmllineattributefilter.cpp\
+ util/xmltimestampfilter.cpp \
+ util/xmlthreadfilter.cpp
+
+varia_tests = \
+ varia/errorhandlertestcase.cpp \
+ varia/levelmatchfiltertestcase.cpp \
+ varia/levelrangefiltertestcase.cpp
+
+db_tests = \
+ db/odbcappendertestcase.cpp
+
+xml_tests = \
+ xml/customleveltestcase.cpp \
+ xml/domtestcase.cpp \
+ xml/xlevel.cpp \
+ xml/xmllayouttestcase.cpp \
+ xml/xmllayouttest.cpp
+
+nt_tests = \
+ nt/nteventlogappendertestcase.cpp
+
+testsuite_SOURCES = \
+ $(customlogger_tests) \
+ $(defaultinit_tests) \
+ $(helpers) \
+ $(net_tests) \
+ $(pattern_tests) \
+ $(rolling_tests) \
+ $(util) \
+ $(varia_tests) \
+ $(db_tests) \
+ $(xml_tests) \
+ $(nt_tests) \
+ abts.cpp \
+ asyncappendertestcase.cpp\
+ encodingtest.cpp\
+ filetestcase.cpp \
+ hierarchytest.cpp\
+ hierarchythresholdtestcase.cpp\
+ l7dtestcase.cpp\
+ leveltestcase.cpp \
+ logunit.cpp \
+ loggertestcase.cpp\
+ minimumtestcase.cpp\
+ patternlayouttest.cpp\
+ vectorappender.cpp\
+ appenderskeletontestcase.cpp\
+ consoleappendertestcase.cpp\
+ fileappendertestcase.cpp\
+ rollingfileappendertestcase.cpp\
+ streamtestcase.cpp\
+ writerappendertestcase.cpp \
+ ndctestcase.cpp \
+ propertyconfiguratortest.cpp
+
+testsuite_LDADD = \
+ $(top_builddir)/src/main/cpp/liblog4cxx.la
+
+
+testsuite_DEPENDENCIES = \
+ $(top_builddir)/src/main/cpp/liblog4cxx.la
+
+check: testsuite
+
diff --git a/src/test/cpp/abts.cpp b/src/test/cpp/abts.cpp
new file mode 100644
index 0000000..489e5dc
--- /dev/null
+++ b/src/test/cpp/abts.cpp
@@ -0,0 +1,451 @@
+/* Copyright 2000-2004 Ryan Bloom
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Portions of this file were taken from testall.c in the APR test suite,
+ * written by members of the Apache Software Foundation.
+ */
+
+#include "abts.h"
+#include "abts_tests.h"
+#include "testutil.h"
+
+
+
+#define ABTS_STAT_SIZE 6
+static char status[ABTS_STAT_SIZE] = {'|', '/', '-', '|', '\\', '-'};
+static int curr_char;
+static int verbose = 0;
+static int exclude = 0;
+static int quiet = 0;
+static int list_tests = 0;
+
+const char **testlist = NULL;
+// defined in logunit.cpp
+abts_suite* abts_run_suites(abts_suite*);
+
+static int find_test_name(const char *testname) {
+ int i;
+ for (i = 0; testlist[i] != NULL; i++) {
+ if (!strcmp(testlist[i], testname)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Determine if the test should be run at all */
+static int should_test_run(const char *testname) {
+ int found = 0;
+ if (list_tests == 1) {
+ return 0;
+ }
+ if (testlist == NULL) {
+ return 1;
+ }
+ found = find_test_name(testname);
+ if ((found && !exclude) || (!found && exclude)) {
+ return 1;
+ }
+ return 0;
+}
+
+static void reset_status(void)
+{
+ curr_char = 0;
+}
+
+static void update_status(void)
+{
+ if (!quiet) {
+ curr_char = (curr_char + 1) % ABTS_STAT_SIZE;
+ fprintf(stdout, "\b%c", status[curr_char]);
+ fflush(stdout);
+ }
+}
+
+static void end_suite(abts_suite *suite)
+{
+ if (suite != NULL) {
+ sub_suite *last = suite->tail;
+ if (!quiet) {
+ fprintf(stdout, "\b");
+ fflush(stdout);
+ }
+ if (last->failed == 0) {
+ fprintf(stdout, "SUCCESS\n");
+ fflush(stdout);
+ }
+ else {
+ fprintf(stdout, "FAILED %d of %d\n", last->failed, last->num_test);
+ fflush(stdout);
+ }
+ }
+}
+
+abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name_full)
+{
+ sub_suite *subsuite;
+ const char *p;
+ const char *suite_name;
+ curr_char = 0;
+
+ /* Only end the suite if we actually ran it */
+ if (suite && suite->tail &&!suite->tail->not_run) {
+ end_suite(suite);
+ }
+
+ subsuite = (sub_suite*) malloc(sizeof(*subsuite));
+ subsuite->num_test = 0;
+ subsuite->failed = 0;
+ subsuite->next = NULL;
+ /* suite_name_full may be an absolute path depending on __FILE__
+ * expansion */
+ suite_name = strrchr(suite_name_full, '/');
+ if (suite_name) {
+ suite_name++;
+ } else {
+ suite_name = suite_name_full;
+ }
+ p = strrchr(suite_name, '.');
+ if (p) {
+ subsuite->name = (const char*) memcpy(calloc(p - suite_name + 1, 1),
+ suite_name, p - suite_name);
+ }
+ else {
+ subsuite->name = suite_name;
+ }
+
+ if (list_tests) {
+ fprintf(stdout, "%s\n", subsuite->name);
+ }
+
+ subsuite->not_run = 0;
+
+ if (suite == NULL) {
+ suite = (abts_suite*) malloc(sizeof(*suite));
+ suite->head = subsuite;
+ suite->tail = subsuite;
+ }
+ else {
+ suite->tail->next = subsuite;
+ suite->tail = subsuite;
+ }
+
+ if (!should_test_run(subsuite->name)) {
+ subsuite->not_run = 1;
+ return suite;
+ }
+
+ reset_status();
+ fprintf(stdout, "%-20s: ", subsuite->name);
+ update_status();
+ fflush(stdout);
+
+ return suite;
+}
+
+void abts_run_test(abts_suite *ts, test_func f, void *value)
+{
+ abts_case tc;
+ sub_suite *ss;
+
+ if (!should_test_run(ts->tail->name)) {
+ return;
+ }
+ ss = ts->tail;
+
+ tc.failed = 0;
+ tc.suite = ss;
+
+ ss->num_test++;
+ update_status();
+
+ f(&tc, value);
+
+ if (tc.failed) {
+ ss->failed++;
+ }
+}
+
+static int report(abts_suite *suite)
+{
+ int count = 0;
+ sub_suite *dptr;
+
+ if (suite && suite->tail &&!suite->tail->not_run) {
+ end_suite(suite);
+ }
+
+ for (dptr = suite->head; dptr; dptr = dptr->next) {
+ count += dptr->failed;
+ }
+
+ if (list_tests) {
+ return 0;
+ }
+
+ if (count == 0) {
+ printf("All tests passed.\n");
+ return 0;
+ }
+
+ dptr = suite->head;
+ fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests");
+ fprintf(stdout, "===================================================\n");
+ while (dptr != NULL) {
+ if (dptr->failed != 0) {
+ float percent = ((float)dptr->failed / (float)dptr->num_test);
+ fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name,
+ dptr->num_test, dptr->failed, percent * 100);
+ }
+ dptr = dptr->next;
+ }
+ return 1;
+}
+
+void abts_log_message(const char *fmt, ...)
+{
+ va_list args;
+ update_status();
+
+ if (verbose) {
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+}
+
+void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (expected == actual) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual);
+ fflush(stderr);
+ }
+}
+
+void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (expected != actual) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual);
+ fflush(stderr);
+ }
+}
+
+void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (expected == actual) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ /* Note that the comparison is type-exact, reporting must be a best-fit */
+ fprintf(stderr, "Line %d: expected %lu, but saw %lu\n", lineno,
+ (unsigned long)expected, (unsigned long)actual);
+ fflush(stderr);
+ }
+}
+
+void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (!expected && !actual) return;
+ if (expected && actual)
+ if (!strcmp(expected, actual)) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual);
+ fflush(stderr);
+ }
+}
+
+void abts_str_nequal(abts_case *tc, const char *expected, const char *actual,
+ size_t n, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (!strncmp(expected, actual, n)) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual);
+ fflush(stderr);
+ }
+}
+
+void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (ptr != NULL) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: Expected NULL, but saw <%p>\n", lineno, ptr);
+ fflush(stderr);
+ }
+}
+
+void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (expected == actual) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: expected <%p>, but saw <%p>\n", lineno, expected, actual);
+ fflush(stderr);
+ }
+}
+
+void abts_fail(abts_case *tc, const char *message, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: %s\n", lineno, message);
+ fflush(stderr);
+ }
+}
+
+void abts_assert(abts_case *tc, const char *message, int condition, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (condition) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: %s\n", lineno, message);
+ fflush(stderr);
+ }
+}
+
+void abts_true(abts_case *tc, int condition, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (condition) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: Condition is false, but expected true\n", lineno);
+ fflush(stderr);
+ }
+}
+
+void abts_not_impl(abts_case *tc, const char *message, int lineno)
+{
+ update_status();
+
+ tc->suite->not_impl++;
+ if (verbose) {
+ fprintf(stderr, "Line %d: %s\n", lineno, message);
+ fflush(stderr);
+ }
+}
+
+int main(int argc, const char *const argv[]) {
+ int i;
+ int rv;
+ int list_provided = 0;
+ abts_suite *suite = NULL;
+
+ initialize();
+
+#if defined(_MSC_VER)
+ quiet = 1;
+#else
+ quiet = !isatty(STDOUT_FILENO);
+#endif
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-v")) {
+ verbose = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-x")) {
+ exclude = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-l")) {
+ list_tests = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-q")) {
+ quiet = 1;
+ continue;
+ }
+ if (argv[i][0] == '-') {
+ fprintf(stderr, "Invalid option: `%s'\n", argv[i]);
+ exit(1);
+ }
+ list_provided = 1;
+ }
+
+ if (list_provided) {
+ /* Waste a little space here, because it is easier than counting the
+ * number of tests listed. Besides it is at most three char *.
+ */
+ testlist = (const char**) calloc(argc + 1, sizeof(char *));
+ for (i = 1; i < argc; i++) {
+ testlist[i - 1] = argv[i];
+ }
+ }
+
+ suite = abts_run_suites(suite);
+
+ if (suite == 0) {
+ fputs("No tests selected\n", stderr);
+ } else {
+ rv = report(suite);
+ //
+ // clean up suite
+ //
+ sub_suite* next;
+ for(sub_suite* head = suite->head; head != NULL; head = next) {
+ next = head->next;
+ free((void*) head->name);
+ free(head);
+ }
+ free(suite);
+ }
+ return rv;
+}
diff --git a/src/test/cpp/abts.h b/src/test/cpp/abts.h
new file mode 100644
index 0000000..4d6470a
--- /dev/null
+++ b/src/test/cpp/abts.h
@@ -0,0 +1,107 @@
+/* Copyright 2000-2004 Ryan Bloom
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#ifndef ABTS_H
+#define ABTS_H
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+struct sub_suite {
+ const char *name;
+ int num_test;
+ int failed;
+ int not_run;
+ int not_impl;
+ struct sub_suite *next;
+};
+typedef struct sub_suite sub_suite;
+
+struct abts_suite {
+ sub_suite *head;
+ sub_suite *tail;
+};
+typedef struct abts_suite abts_suite;
+
+struct abts_case {
+ int failed;
+ sub_suite *suite;
+};
+typedef struct abts_case abts_case;
+
+typedef void (*test_func)(abts_case *tc, void *data);
+
+#define ADD_SUITE(suite) abts_add_suite(suite, __FILE__);
+
+abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name);
+void abts_run_test(abts_suite *ts, test_func f, void *value);
+void abts_log_message(const char *fmt, ...);
+
+void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno);
+void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno);
+void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno);
+void abts_str_nequal(abts_case *tc, const char *expected, const char *actual,
+ size_t n, int lineno);
+void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno);
+void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno);
+void abts_true(abts_case *tc, int condition, int lineno);
+void abts_fail(abts_case *tc, const char *message, int lineno);
+void abts_not_impl(abts_case *tc, const char *message, int lineno);
+void abts_assert(abts_case *tc, const char *message, int condition, int lineno);
+void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno);
+
+/* Convenience macros. Ryan hates these! */
+#define ABTS_INT_EQUAL(a, b, c) abts_int_equal(a, b, c, __LINE__)
+#define ABTS_INT_NEQUAL(a, b, c) abts_int_nequal(a, b, c, __LINE__)
+#define ABTS_STR_EQUAL(a, b, c) abts_str_equal(a, b, c, __LINE__)
+#define ABTS_STR_NEQUAL(a, b, c, d) abts_str_nequal(a, b, c, d, __LINE__)
+#define ABTS_PTR_NOTNULL(a, b) abts_ptr_notnull(a, b, __LINE__)
+#define ABTS_PTR_EQUAL(a, b, c) abts_ptr_equal(a, b, c, __LINE__)
+#define ABTS_TRUE(a, b) abts_true(a, b, __LINE__);
+#define ABTS_FAIL(a, b) abts_fail(a, b, __LINE__);
+#define ABTS_NOT_IMPL(a, b) abts_not_impl(a, b, __LINE__);
+#define ABTS_ASSERT(a, b, c) abts_assert(a, b, c, __LINE__);
+
+#define ABTS_SIZE_EQUAL(a, b, c) abts_size_equal(a, b, c, __LINE__)
+
+
+abts_suite *run_tests(abts_suite *suite);
+abts_suite *run_tests1(abts_suite *suite);
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/test/cpp/abts_tests.h b/src/test/cpp/abts_tests.h
new file mode 100644
index 0000000..f84ee58
--- /dev/null
+++ b/src/test/cpp/abts_tests.h
@@ -0,0 +1,23 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 APR_TEST_INCLUDES
+#define APR_TEST_INCLUDES
+
+#include "abts.h"
+#include "testutil.h"
+
+#endif /* APR_TEST_INCLUDES */
diff --git a/src/test/cpp/appenderskeletontestcase.cpp b/src/test/cpp/appenderskeletontestcase.cpp
new file mode 100644
index 0000000..6406c42
--- /dev/null
+++ b/src/test/cpp/appenderskeletontestcase.cpp
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "appenderskeletontestcase.h"
+#include "logunit.h"
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/appenderskeleton.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+void AppenderSkeletonTestCase::testDefaultThreshold() {
+ ObjectPtrT<AppenderSkeleton> appender(createAppenderSkeleton());
+ LevelPtr threshold(appender->getThreshold());
+ LOGUNIT_ASSERT_EQUAL(Level::getAll()->toInt(), threshold->toInt());
+}
+
+void AppenderSkeletonTestCase::testSetOptionThreshold() {
+ ObjectPtrT<AppenderSkeleton> appender(createAppenderSkeleton());
+ appender->setOption(LOG4CXX_STR("threshold"), LOG4CXX_STR("debug"));
+ LevelPtr threshold(appender->getThreshold());
+ LOGUNIT_ASSERT_EQUAL(Level::getDebug()->toInt(), threshold->toInt());
+}
diff --git a/src/test/cpp/appenderskeletontestcase.h b/src/test/cpp/appenderskeletontestcase.h
new file mode 100644
index 0000000..23b8b46
--- /dev/null
+++ b/src/test/cpp/appenderskeletontestcase.h
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/appenderskeleton.h>
+#include "logunit.h"
+
+/**
+ An abstract set of tests for inclusion in concrete
+ appender test case
+ */
+LOGUNIT_CLASS(AppenderSkeletonTestCase)
+{
+
+public:
+ virtual log4cxx::AppenderSkeleton* createAppenderSkeleton() const = 0;
+
+ void testDefaultThreshold();
+
+ void testSetOptionThreshold();
+};
diff --git a/src/test/cpp/asyncappendertestcase.cpp b/src/test/cpp/asyncappendertestcase.cpp
new file mode 100644
index 0000000..06e58e9
--- /dev/null
+++ b/src/test/cpp/asyncappendertestcase.cpp
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "logunit.h"
+
+#include <log4cxx/logger.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/simplelayout.h>
+#include "vectorappender.h"
+#include <log4cxx/asyncappender.h>
+#include "appenderskeletontestcase.h"
+#include <log4cxx/helpers/pool.h>
+#include <apr_strings.h>
+#include "testchar.h"
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <log4cxx/spi/location/locationinfo.h>
+#include <log4cxx/xml/domconfigurator.h>
+#include <log4cxx/file.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+class NullPointerAppender : public AppenderSkeleton {
+public:
+ NullPointerAppender() {
+ }
+
+
+ /**
+ * @{inheritDoc}
+ */
+ void append(const spi::LoggingEventPtr&, log4cxx::helpers::Pool&) {
+ throw NullPointerException(LOG4CXX_STR("Intentional NullPointerException"));
+ }
+
+ void close() {
+ }
+
+ bool requiresLayout() const {
+ return false;
+ }
+};
+
+ /**
+ * Vector appender that can be explicitly blocked.
+ */
+class BlockableVectorAppender : public VectorAppender {
+private:
+ Mutex blocker;
+public:
+ /**
+ * Create new instance.
+ */
+ BlockableVectorAppender() : blocker(pool) {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) {
+ synchronized sync(blocker);
+ VectorAppender::append(event, p);
+ //
+ // if fatal, echo messages for testLoggingInDispatcher
+ //
+ if (event->getLevel() == Level::getInfo()) {
+ LoggerPtr logger = Logger::getLoggerLS(event->getLoggerName());
+ LOG4CXX_LOGLS(logger, Level::getError(), event->getMessage());
+ LOG4CXX_LOGLS(logger, Level::getWarn(), event->getMessage());
+ LOG4CXX_LOGLS(logger, Level::getInfo(), event->getMessage());
+ LOG4CXX_LOGLS(logger, Level::getDebug(), event->getMessage());
+ }
+ }
+
+ Mutex& getBlocker() {
+ return blocker;
+ }
+
+ };
+
+typedef helpers::ObjectPtrT<BlockableVectorAppender> BlockableVectorAppenderPtr;
+
+#if APR_HAS_THREADS
+/**
+ * Tests of AsyncAppender.
+ */
+class AsyncAppenderTestCase : public AppenderSkeletonTestCase
+{
+ LOGUNIT_TEST_SUITE(AsyncAppenderTestCase);
+ //
+ // tests inherited from AppenderSkeletonTestCase
+ //
+ LOGUNIT_TEST(testDefaultThreshold);
+ LOGUNIT_TEST(testSetOptionThreshold);
+
+ LOGUNIT_TEST(closeTest);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST(test3);
+ //
+ // TODO: test fails on Linux.
+ //LOGUNIT_TEST(testBadAppender);
+ LOGUNIT_TEST(testLocationInfoTrue);
+ LOGUNIT_TEST(testConfiguration);
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+ void setUp() {
+ AppenderSkeletonTestCase::setUp();
+ }
+
+ void tearDown()
+ {
+ LogManager::shutdown();
+ AppenderSkeletonTestCase::tearDown();
+ }
+
+ AppenderSkeleton* createAppenderSkeleton() const {
+ return new AsyncAppender();
+ }
+
+ // this test checks whether it is possible to write to a closed AsyncAppender
+ void closeTest()
+ {
+ LoggerPtr root = Logger::getRootLogger();
+ LayoutPtr layout = new SimpleLayout();
+ VectorAppenderPtr vectorAppender = new VectorAppender();
+ AsyncAppenderPtr asyncAppender = new AsyncAppender();
+ asyncAppender->setName(LOG4CXX_STR("async-CloseTest"));
+ asyncAppender->addAppender(vectorAppender);
+ root->addAppender(asyncAppender);
+
+ root->debug(LOG4CXX_TEST_STR("m1"));
+ asyncAppender->close();
+ root->debug(LOG4CXX_TEST_STR("m2"));
+
+ const std::vector<spi::LoggingEventPtr>& v = vectorAppender->getVector();
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, v.size());
+ }
+
+ // this test checks whether appenders embedded within an AsyncAppender are also
+ // closed
+ void test2()
+ {
+ LoggerPtr root = Logger::getRootLogger();
+ LayoutPtr layout = new SimpleLayout();
+ VectorAppenderPtr vectorAppender = new VectorAppender();
+ AsyncAppenderPtr asyncAppender = new AsyncAppender();
+ asyncAppender->setName(LOG4CXX_STR("async-test2"));
+ asyncAppender->addAppender(vectorAppender);
+ root->addAppender(asyncAppender);
+
+ root->debug(LOG4CXX_TEST_STR("m1"));
+ asyncAppender->close();
+ root->debug(LOG4CXX_TEST_STR("m2"));
+
+ const std::vector<spi::LoggingEventPtr>& v = vectorAppender->getVector();
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, v.size());
+ LOGUNIT_ASSERT(vectorAppender->isClosed());
+ }
+
+ // this test checks whether appenders embedded within an AsyncAppender are also
+ // closed
+ void test3()
+ {
+ size_t LEN = 200;
+ LoggerPtr root = Logger::getRootLogger();
+ VectorAppenderPtr vectorAppender = new VectorAppender();
+ AsyncAppenderPtr asyncAppender = new AsyncAppender();
+ asyncAppender->setName(LOG4CXX_STR("async-test3"));
+ asyncAppender->addAppender(vectorAppender);
+ root->addAppender(asyncAppender);
+
+ for (size_t i = 0; i < LEN; i++) {
+ LOG4CXX_DEBUG(root, "message" << i);
+ }
+
+ asyncAppender->close();
+ root->debug(LOG4CXX_TEST_STR("m2"));
+
+ const std::vector<spi::LoggingEventPtr>& v = vectorAppender->getVector();
+ LOGUNIT_ASSERT_EQUAL(LEN, v.size());
+ LOGUNIT_ASSERT_EQUAL(true, vectorAppender->isClosed());
+ }
+
+ /**
+ * Tests that a bad appender will switch async back to sync.
+ */
+ void testBadAppender() {
+ AppenderPtr nullPointerAppender = new NullPointerAppender();
+ AsyncAppenderPtr asyncAppender = new AsyncAppender();
+ asyncAppender->addAppender(nullPointerAppender);
+ asyncAppender->setBufferSize(5);
+ Pool p;
+ asyncAppender->activateOptions(p);
+ LoggerPtr root = Logger::getRootLogger();
+ root->addAppender(asyncAppender);
+ LOG4CXX_INFO(root, "Message");
+ Thread::sleep(10);
+ try {
+ LOG4CXX_INFO(root, "Message");
+ LOGUNIT_FAIL("Should have thrown exception");
+ } catch(NullPointerException& ex) {
+ }
+ }
+
+ /**
+ * Tests non-blocking behavior.
+ */
+ void testLocationInfoTrue() {
+ BlockableVectorAppenderPtr blockableAppender = new BlockableVectorAppender();
+ AsyncAppenderPtr async = new AsyncAppender();
+ async->addAppender(blockableAppender);
+ async->setBufferSize(5);
+ async->setLocationInfo(true);
+ async->setBlocking(false);
+ Pool p;
+ async->activateOptions(p);
+ LoggerPtr rootLogger = Logger::getRootLogger();
+ rootLogger->addAppender(async);
+ {
+ synchronized sync(blockableAppender->getBlocker());
+ for (int i = 0; i < 100; i++) {
+ LOG4CXX_INFO(rootLogger, "Hello, World");
+ Thread::sleep(1);
+ }
+ LOG4CXX_ERROR(rootLogger, "That's all folks.");
+ }
+ async->close();
+ const std::vector<spi::LoggingEventPtr>& events = blockableAppender->getVector();
+ LOGUNIT_ASSERT(events.size() > 0);
+ LoggingEventPtr initialEvent = events[0];
+ LoggingEventPtr discardEvent = events[events.size() - 1];
+ LOGUNIT_ASSERT(initialEvent->getMessage() == LOG4CXX_STR("Hello, World"));
+ LOGUNIT_ASSERT(discardEvent->getMessage().substr(0,10) == LOG4CXX_STR("Discarded "));
+ LOGUNIT_ASSERT_EQUAL(log4cxx::spi::LocationInfo::getLocationUnavailable().getClassName(),
+ discardEvent->getLocationInformation().getClassName());
+ }
+
+ void testConfiguration() {
+ log4cxx::xml::DOMConfigurator::configure("input/xml/asyncAppender1.xml");
+ AsyncAppenderPtr asyncAppender(Logger::getRootLogger()->getAppender(LOG4CXX_STR("ASYNC")));
+ LOGUNIT_ASSERT(!(asyncAppender == 0));
+ LOGUNIT_ASSERT_EQUAL(100, asyncAppender->getBufferSize());
+ LOGUNIT_ASSERT_EQUAL(false, asyncAppender->getBlocking());
+ LOGUNIT_ASSERT_EQUAL(true, asyncAppender->getLocationInfo());
+ AppenderList nestedAppenders(asyncAppender->getAllAppenders());
+ // TODO:
+ // test seems to work okay, but have not found a working way to
+ // get a reference to the nested vector appender
+ //
+// LOGUNIT_ASSERT_EQUAL((size_t) 1, nestedAppenders.size());
+// VectorAppenderPtr vectorAppender(nestedAppenders[0]);
+// LOGUNIT_ASSERT(0 != vectorAppender);
+ LoggerPtr root(Logger::getRootLogger());
+
+ size_t LEN = 20;
+ for (size_t i = 0; i < LEN; i++) {
+ LOG4CXX_DEBUG(root, "message" << i);
+ }
+
+ asyncAppender->close();
+// const std::vector<spi::LoggingEventPtr>& v = vectorAppender->getVector();
+// LOGUNIT_ASSERT_EQUAL(LEN, v.size());
+// LOGUNIT_ASSERT_EQUAL(true, vectorAppender->isClosed());
+ }
+
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(AsyncAppenderTestCase);
+#endif
diff --git a/src/test/cpp/consoleappendertestcase.cpp b/src/test/cpp/consoleappendertestcase.cpp
new file mode 100644
index 0000000..230bbca
--- /dev/null
+++ b/src/test/cpp/consoleappendertestcase.cpp
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/consoleappender.h>
+#include "logunit.h"
+#include "writerappendertestcase.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+/**
+ Unit tests of log4cxx::nt::NTEventLogAppender
+ */
+class ConsoleAppenderTestCase : public WriterAppenderTestCase
+{
+ LOGUNIT_TEST_SUITE(ConsoleAppenderTestCase);
+ //
+ // tests inherited from AppenderSkeletonTestCase
+ //
+ LOGUNIT_TEST(testDefaultThreshold);
+ LOGUNIT_TEST(testSetOptionThreshold);
+
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+
+ WriterAppender* createWriterAppender() const {
+ return new log4cxx::ConsoleAppender();
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(ConsoleAppenderTestCase);
diff --git a/src/test/cpp/customlogger/xlogger.cpp b/src/test/cpp/customlogger/xlogger.cpp
new file mode 100644
index 0000000..a837509
--- /dev/null
+++ b/src/test/cpp/customlogger/xlogger.cpp
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include "xlogger.h"
+#include <log4cxx/level.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/spi/location/locationinfo.h>
+#include <log4cxx/spi/loggerrepository.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+
+IMPLEMENT_LOG4CXX_OBJECT(XLogger)
+IMPLEMENT_LOG4CXX_OBJECT(XFactory)
+
+XFactoryPtr XLogger::factory = new XFactory();
+
+void XLogger::lethal(const LogString& message, const LocationInfo& locationInfo)
+{
+ if (repository->isDisabled(XLevel::LETHAL_INT))
+ {
+ return;
+ }
+
+ if (XLevel::getLethal()->isGreaterOrEqual(this->getEffectiveLevel()))
+ {
+ forcedLog(XLevel::getLethal(), message, locationInfo);
+ }
+}
+
+void XLogger::lethal(const LogString& message)
+{
+ if (repository->isDisabled(XLevel::LETHAL_INT))
+ {
+ return;
+ }
+
+ if (XLevel::getLethal()->isGreaterOrEqual(this->getEffectiveLevel()))
+ {
+ forcedLog(XLevel::getLethal(), message, LocationInfo::getLocationUnavailable());
+ }
+}
+
+LoggerPtr XLogger::getLogger(const LogString& name)
+{
+ return LogManager::getLogger(name, factory);
+}
+
+LoggerPtr XLogger::getLogger(const helpers::Class& clazz)
+{
+ return XLogger::getLogger(clazz.getName());
+}
+
+void XLogger::trace(const LogString& message, const LocationInfo& locationInfo)
+{
+ if (repository->isDisabled(XLevel::TRACE_INT))
+ {
+ return;
+ }
+
+ if (XLevel::getTrace()->isGreaterOrEqual(this->getEffectiveLevel()))
+ {
+ forcedLog(XLevel::getTrace(), message, locationInfo);
+ }
+}
+
+void XLogger::trace(const LogString& message)
+{
+ if (repository->isDisabled(XLevel::TRACE_INT))
+ {
+ return;
+ }
+
+ if (XLevel::getTrace()->isGreaterOrEqual(this->getEffectiveLevel()))
+ {
+ forcedLog(XLevel::getTrace(), message, LocationInfo::getLocationUnavailable());
+ }
+}
+
+XFactory::XFactory()
+{
+}
+
+LoggerPtr XFactory::makeNewLoggerInstance(log4cxx::helpers::Pool& pool,
+ const LogString& name) const
+{
+ return new XLogger(pool, name);
+}
diff --git a/src/test/cpp/customlogger/xlogger.h b/src/test/cpp/customlogger/xlogger.h
new file mode 100644
index 0000000..0080f48
--- /dev/null
+++ b/src/test/cpp/customlogger/xlogger.h
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logger.h>
+#include "../xml/xlevel.h"
+#include <log4cxx/spi/loggerfactory.h>
+
+
+namespace log4cxx
+{
+ namespace spi {
+ namespace location {
+ class LocationInfo;
+ }
+ }
+ // Any sub-class of Logger must also have its own implementation of
+ // LoggerFactory.
+ class XFactory :
+ public virtual spi::LoggerFactory,
+ public virtual helpers::ObjectImpl
+ {
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(XFactory)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(XFactory)
+ LOG4CXX_CAST_ENTRY(spi::LoggerFactory)
+ END_LOG4CXX_CAST_MAP()
+
+ XFactory();
+ virtual LoggerPtr makeNewLoggerInstance(
+ log4cxx::helpers::Pool& pool,
+ const LogString& name) const;
+ };
+
+ typedef helpers::ObjectPtrT<XFactory> XFactoryPtr;
+
+ /**
+ A simple example showing Logger sub-classing. It shows the
+ minimum steps necessary to implement one's {@link LoggerFactory}.
+ Note that sub-classes follow the hierarchy even if its loggers
+ belong to different classes.
+ */
+ class XLogger : public Logger
+ {
+ // It's enough to instantiate a factory once and for all.
+ static XFactoryPtr factory;
+ LogString suffix;
+
+ public:
+ DECLARE_ABSTRACT_LOG4CXX_OBJECT(XLogger)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(XLogger)
+ LOG4CXX_CAST_ENTRY_CHAIN(Logger)
+ END_LOG4CXX_CAST_MAP()
+
+ /**
+ Just calls the parent constuctor.
+ */
+ XLogger(log4cxx::helpers::Pool& pool,
+ const LogString& name1) : Logger(pool, name1) {}
+
+ /**
+ Nothing to activate.
+ */
+ void activateOptions() {}
+
+
+ /**
+ We introduce a new printing method in order to support {@link
+ XLevel#LETHAL}. */
+ void lethal(const LogString& message, const log4cxx::spi::LocationInfo& location);
+
+ /**
+ We introduce a new printing method in order to support {@link
+ XLevel#LETHAL}. */
+ void lethal(const LogString& message);
+
+ static LoggerPtr getLogger(const LogString& name);
+
+ static LoggerPtr getLogger(const helpers::Class& clazz);
+
+ LogString getSuffix() const
+ { return suffix; }
+
+ void setSuffix(const LogString& suffix1)
+ { this->suffix = suffix1; }
+
+ /**
+ We introduce a new printing method that takes the TRACE level.
+ */
+ void trace(const LogString& message, const log4cxx::spi::LocationInfo& location);
+
+ /**
+ We introduce a new printing method that takes the TRACE level.
+ */
+ void trace(const LogString& message);
+ };
+
+ typedef helpers::ObjectPtrT<XLogger> XLoggerPtr;
+}
+
diff --git a/src/test/cpp/customlogger/xloggertestcase.cpp b/src/test/cpp/customlogger/xloggertestcase.cpp
new file mode 100644
index 0000000..15c3bcf
--- /dev/null
+++ b/src/test/cpp/customlogger/xloggertestcase.cpp
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG4CXX_TEST 1
+#include <log4cxx/private/log4cxx_private.h>
+
+#include "../logunit.h"
+#include "xlogger.h"
+#include <log4cxx/xml/domconfigurator.h>
+#include "../util/transformer.h"
+#include "../util/compare.h"
+#include <log4cxx/file.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::xml;
+
+#define LOG4CXX_TEST_STR(x) L##x
+
+/**
+ Tests handling of custom loggers.
+*/
+LOGUNIT_CLASS(XLoggerTestCase)
+{
+ LOGUNIT_TEST_SUITE(XLoggerTestCase);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST_SUITE_END();
+
+ XLoggerPtr logger;
+
+public:
+ void setUp()
+ {
+ logger = XLogger::getLogger(
+ LOG4CXX_STR("org.apache.log4j.customLogger.XLoggerTestCase"));
+ }
+
+ void tearDown()
+ {
+ logger->getLoggerRepository()->resetConfiguration();
+ }
+
+ void test1() { common("1"); }
+ void test2() { common("2"); }
+
+ void common(const char* number)
+ {
+ std::string fn("input/xml/customLogger");
+ fn.append(number);
+ fn.append(".xml");
+ DOMConfigurator::configure(fn);
+
+ int i = 0;
+ LOG4CXX_LOG(logger, log4cxx::XLevel::getTrace(), "Message " << i);
+
+ i++;
+ LOG4CXX_DEBUG(logger, "Message " << i);
+ i++;
+ LOG4CXX_WARN(logger, "Message " << i);
+ i++;
+ LOG4CXX_ERROR(logger, "Message " << i);
+ i++;
+ LOG4CXX_FATAL(logger, "Message " << i);
+ i++;
+ LOG4CXX_DEBUG(logger, "Message " << i);
+
+ const File OUTPUT("output/temp");
+ std::string witness("witness/customLogger.");
+ witness.append(number);
+ const File WITNESS(witness);
+ LOGUNIT_ASSERT(Compare::compare(OUTPUT, WITNESS));
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(XLoggerTestCase);
+
diff --git a/src/test/cpp/db/odbcappendertestcase.cpp b/src/test/cpp/db/odbcappendertestcase.cpp
new file mode 100644
index 0000000..d0bef0a
--- /dev/null
+++ b/src/test/cpp/db/odbcappendertestcase.cpp
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/db/odbcappender.h>
+#include "../appenderskeletontestcase.h"
+#include "../logunit.h"
+
+#define LOG4CXX_TEST 1
+#include <log4cxx/private/log4cxx_private.h>
+
+#ifdef LOG4CXX_HAVE_ODBC
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+/**
+ Unit tests of log4cxx::SocketAppender
+ */
+class ODBCAppenderTestCase : public AppenderSkeletonTestCase
+{
+ LOGUNIT_TEST_SUITE(ODBCAppenderTestCase);
+ //
+ // tests inherited from AppenderSkeletonTestCase
+ //
+ LOGUNIT_TEST(testDefaultThreshold);
+ LOGUNIT_TEST(testSetOptionThreshold);
+
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+
+ AppenderSkeleton* createAppenderSkeleton() const {
+ return new log4cxx::db::ODBCAppender();
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(ODBCAppenderTestCase);
+
+#endif
diff --git a/src/test/cpp/defaultinit/testcase1.cpp b/src/test/cpp/defaultinit/testcase1.cpp
new file mode 100644
index 0000000..9d60bb5
--- /dev/null
+++ b/src/test/cpp/defaultinit/testcase1.cpp
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "../logunit.h"
+
+#include <log4cxx/logmanager.h>
+#include <log4cxx/logger.h>
+
+using namespace log4cxx;
+
+LOGUNIT_CLASS(TestCase1)
+{
+ LOGUNIT_TEST_SUITE(TestCase1);
+ LOGUNIT_TEST(noneTest);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ LogManager::shutdown();
+ }
+
+ void noneTest()
+ {
+ LoggerPtr root = Logger::getRootLogger();
+ LOG4CXX_DEBUG(root, "Hello, world");
+ bool rootIsConfigured = !root->getAllAppenders().empty();
+ LOGUNIT_ASSERT(!rootIsConfigured);
+ }
+};
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION_DISABLED(TestCase1)
+
diff --git a/src/test/cpp/defaultinit/testcase2.cpp b/src/test/cpp/defaultinit/testcase2.cpp
new file mode 100644
index 0000000..13c755d
--- /dev/null
+++ b/src/test/cpp/defaultinit/testcase2.cpp
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG4CXX_TEST 1
+#include <log4cxx/private/log4cxx_private.h>
+
+
+#include <log4cxx/logmanager.h>
+#include <log4cxx/logger.h>
+#include "../insertwide.h"
+#include "../logunit.h"
+
+using namespace log4cxx;
+
+LOGUNIT_CLASS(TestCase2)
+{
+ LOGUNIT_TEST_SUITE(TestCase2);
+ LOGUNIT_TEST(xmlTest);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ LogManager::shutdown();
+ }
+
+ void xmlTest()
+ {
+ LoggerPtr root = Logger::getRootLogger();
+ LOG4CXX_DEBUG(root, "Hello, world");
+ bool rootIsConfigured = !root->getAllAppenders().empty();
+ LOGUNIT_ASSERT(rootIsConfigured);
+
+ AppenderList list = root->getAllAppenders();
+ AppenderPtr appender = list.front();
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("D1"), appender->getName());
+ }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION_DISABLED(TestCase2)
+
+
diff --git a/src/test/cpp/defaultinit/testcase3.cpp b/src/test/cpp/defaultinit/testcase3.cpp
new file mode 100644
index 0000000..37e0761
--- /dev/null
+++ b/src/test/cpp/defaultinit/testcase3.cpp
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logmanager.h>
+#include <log4cxx/logger.h>
+#include "../insertwide.h"
+#include "../logunit.h"
+
+using namespace log4cxx;
+
+LOGUNIT_CLASS(TestCase3)
+{
+ LOGUNIT_TEST_SUITE(TestCase3);
+ LOGUNIT_TEST(testProperties);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ LogManager::shutdown();
+ }
+
+ void testProperties()
+ {
+ LoggerPtr root = Logger::getRootLogger();
+ LOG4CXX_DEBUG(root, "Hello, world");
+ bool rootIsConfigured = !root->getAllAppenders().empty();
+ LOGUNIT_ASSERT(rootIsConfigured);
+
+ AppenderList list = root->getAllAppenders();
+ AppenderPtr appender = list.front();
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("D3"), appender->getName());
+ }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION_DISABLED(TestCase3)
diff --git a/src/test/cpp/defaultinit/testcase4.cpp b/src/test/cpp/defaultinit/testcase4.cpp
new file mode 100644
index 0000000..64bc06e
--- /dev/null
+++ b/src/test/cpp/defaultinit/testcase4.cpp
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG4CXX_TEST 1
+#include <log4cxx/private/log4cxx_private.h>
+
+
+#include <log4cxx/logmanager.h>
+#include <log4cxx/logger.h>
+#include "../insertwide.h"
+#include "../logunit.h"
+
+using namespace log4cxx;
+
+LOGUNIT_CLASS(TestCase4)
+{
+ LOGUNIT_TEST_SUITE(TestCase4);
+ LOGUNIT_TEST(combinedTest);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ LogManager::shutdown();
+ }
+
+ void combinedTest()
+ {
+ LoggerPtr root = Logger::getRootLogger();
+ LOG4CXX_DEBUG(root, "Hello, world");
+ bool rootIsConfigured = !root->getAllAppenders().empty();
+ LOGUNIT_ASSERT(rootIsConfigured);
+
+ AppenderList list = root->getAllAppenders();
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, list.size());
+ AppenderPtr appender = list.front();
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("D1"), appender->getName());
+ }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION_DISABLED(TestCase4)
+
diff --git a/src/test/cpp/encodingtest.cpp b/src/test/cpp/encodingtest.cpp
new file mode 100644
index 0000000..ce0ab54
--- /dev/null
+++ b/src/test/cpp/encodingtest.cpp
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logger.h>
+#include "logunit.h"
+//
+// If there is no support for wchar_t logging then
+// there is not a consistent way to get the test characters logged
+//
+#if LOG4CXX_WCHAR_T_API
+
+
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/fileappender.h>
+#include <log4cxx/level.h>
+
+#include "util/binarycompare.h"
+#include <log4cxx/file.h>
+#include <log4cxx/helpers/pool.h>
+
+using namespace log4cxx;
+using namespace log4cxx::util;
+using namespace log4cxx::helpers;
+
+/**
+ * Tests support for encoding specification.
+ *
+ *
+ */
+LOGUNIT_CLASS(EncodingTest) {
+ LOGUNIT_TEST_SUITE(EncodingTest);
+ LOGUNIT_TEST(testASCII);
+ LOGUNIT_TEST(testLatin1);
+ LOGUNIT_TEST(testUtf8);
+ LOGUNIT_TEST(testUtf16);
+ LOGUNIT_TEST(testUtf16LE);
+ LOGUNIT_TEST(testUtf16BE);
+ LOGUNIT_TEST_SUITE_END();
+public:
+ /**
+ * Resets configuration after each test.
+ */
+ void tearDown() {
+ Logger::getRootLogger()->getLoggerRepository()->resetConfiguration();
+ }
+
+
+ /**
+ * Test us-ascii encoding.
+ */
+ void testASCII() {
+ LoggerPtr root(Logger::getRootLogger());
+ configure(root, LOG4CXX_STR("output/ascii.log"), LOG4CXX_STR("US-ASCII"));
+ common(root);
+ BinaryCompare::compare("output/ascii.log", "witness/encoding/ascii.log");
+ }
+
+ /**
+ * Test iso-8859-1 encoding.
+ */
+ void testLatin1() {
+ LoggerPtr root(Logger::getRootLogger());
+ configure(root, LOG4CXX_STR("output/latin1.log"), LOG4CXX_STR("iso-8859-1"));
+ common(root);
+ BinaryCompare::compare("output/latin1.log", "witness/encoding/latin1.log");
+ }
+
+ /**
+ * Test utf-8 encoding.
+ */
+ void testUtf8() {
+ LoggerPtr root(Logger::getRootLogger());
+ configure(root, LOG4CXX_STR("output/UTF-8.log"), LOG4CXX_STR("UTF-8"));
+ common(root);
+ BinaryCompare::compare("output/UTF-8.log", "witness/encoding/UTF-8.log");
+ }
+
+ /**
+ * Test utf-16 encoding.
+ */
+ void testUtf16() {
+ LoggerPtr root(Logger::getRootLogger());
+ configure(root, LOG4CXX_STR("output/UTF-16.log"), LOG4CXX_STR("UTF-16"));
+ common(root);
+ BinaryCompare::compare("output/UTF-16.log", "witness/encoding/UTF-16.log");
+ }
+
+ /**
+ * Test utf-16be encoding.
+ */
+ void testUtf16BE() {
+ LoggerPtr root(Logger::getRootLogger());
+ configure(root, LOG4CXX_STR("output/UTF-16BE.log"), LOG4CXX_STR("UTF-16BE"));
+ common(root);
+ BinaryCompare::compare("output/UTF-16BE.log", "witness/encoding/UTF-16BE.log");
+ }
+
+ /**
+ * Test utf16-le encoding.
+ */
+ void testUtf16LE() {
+ LoggerPtr root(Logger::getRootLogger());
+ configure(root, LOG4CXX_STR("output/UTF-16LE.log"), LOG4CXX_STR("UTF-16LE"));
+ common(root);
+ BinaryCompare::compare("output/UTF-16LE.log", "witness/encoding/UTF-16LE.log");
+ }
+
+ /**
+ * Configure logging.
+ * @param logger logger
+ * @param filename logging file name
+ * @param encoding encoding
+ */
+ private:
+ void configure(LoggerPtr& logger,
+ const LogString& filename, const LogString& encoding) {
+ PatternLayoutPtr layout(new PatternLayout());
+ layout->setConversionPattern(LOG4CXX_STR("%p - %m\n"));
+ Pool p;
+ layout->activateOptions(p);
+ FileAppenderPtr appender(new FileAppender());
+ appender->setFile(filename);
+ appender->setEncoding(encoding);
+ appender->setAppend(false);
+ appender->setLayout(layout);
+ appender->activateOptions(p);
+ logger->addAppender(appender);
+ logger->setLevel(Level::getInfo());
+ }
+
+ /**
+ * Common logging requests.
+ * @param logger logger
+ */
+ void common(LoggerPtr& logger) {
+ logger->info("Hello, World");
+ // pi can be encoded in iso-8859-1
+ const wchar_t pi[] = { 0x00B9, 0 };
+ logger->info(pi);
+ // arbitrary, hopefully meaningless, characters from
+ // Latin, Arabic, Armenian, Bengali, CJK and Cyrillic
+ const wchar_t greeting[] = { L'A', 0x0605, 0x0530, 0x986, 0x4E03, 0x400, 0 };
+ logger->info(greeting);
+
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(EncodingTest);
+
+#endif
+
diff --git a/src/test/cpp/fileappendertest.cpp b/src/test/cpp/fileappendertest.cpp
new file mode 100644
index 0000000..e16355a
--- /dev/null
+++ b/src/test/cpp/fileappendertest.cpp
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/pool.h>
+#include <log4cxx/fileappender.h>
+#include <log4cxx/patternlayout.h>
+#include "logunit.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+/**
+ *
+ * FileAppender tests.
+ */
+LOGUNIT_CLASS(FileAppenderTest) {
+ LOGUNIT_TEST_SUITE(FileAppenderTest);
+ LOGUNIT_TEST(testDirectoryCreation);
+ LOGUNIT_TEST(testgetSetThreshold);
+ LOGUNIT_TEST(testIsAsSevereAsThreshold);
+ LOGUNIT_TEST_SUITE_END();
+public:
+ /**
+ * Tests that any necessary directories are attempted to
+ * be created if they don't exist. See bug 9150.
+ *
+ */
+ void testDirectoryCreation() {
+ File newFile(LOG4CXX_STR("output/newdir/temp.log"));
+ Pool p;
+ newFile.deleteFile(p);
+
+ File newDir(LOG4CXX_STR("output/newdir"));
+ newDir.deleteFile(p);
+
+ FileAppenderPtr wa(new FileAppender());
+ wa->setFile(LOG4CXX_STR("output/newdir/temp.log"));
+ wa->setLayout(new PatternLayout(LOG4CXX_STR("%m%n")));
+ wa->activateOptions(p);
+
+ LOGUNIT_ASSERT(File(LOG4CXX_STR("output/newdir/temp.log")).exists(p));
+ }
+
+ /**
+ * Tests getThreshold and setThreshold.
+ */
+ void testgetSetThreshold() {
+ FileAppenderPtr appender = new FileAppender();
+ LevelPtr debug = Level::getDebug();
+ //
+ // different from log4j where threshold is null.
+ //
+ LOGUNIT_ASSERT_EQUAL(Level::getAll(), appender->getThreshold());
+ appender->setThreshold(debug);
+ LOGUNIT_ASSERT_EQUAL(debug, appender->getThreshold());
+ }
+
+ /**
+ * Tests isAsSevereAsThreshold.
+ */
+ void testIsAsSevereAsThreshold() {
+ FileAppenderPtr appender = new FileAppender();
+ LevelPtr debug = Level::getDebug();
+ LOGUNIT_ASSERT(appender->isAsSevereAsThreshold(debug));
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(FileAppenderTest);
+
diff --git a/src/test/cpp/fileappendertestcase.cpp b/src/test/cpp/fileappendertestcase.cpp
new file mode 100644
index 0000000..dadf034
--- /dev/null
+++ b/src/test/cpp/fileappendertestcase.cpp
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "fileappendertestcase.h"
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/fileappender.h>
+#include "insertwide.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+WriterAppender* FileAppenderAbstractTestCase::createWriterAppender() const {
+ return createFileAppender();
+}
+
+
+/**
+ Unit tests of log4cxx::FileAppender
+ */
+class FileAppenderTestCase : public FileAppenderAbstractTestCase
+{
+ LOGUNIT_TEST_SUITE(FileAppenderTestCase);
+ //
+ // tests inherited from AppenderSkeletonTestCase
+ //
+ LOGUNIT_TEST(testDefaultThreshold);
+ LOGUNIT_TEST(testSetOptionThreshold);
+
+ // tests defined here
+ LOGUNIT_TEST(testSetDoubleBackslashes);
+ LOGUNIT_TEST(testStripDuplicateBackslashes);
+
+ LOGUNIT_TEST_SUITE_END();
+
+
+
+
+public:
+
+ FileAppender* createFileAppender() const {
+ return new log4cxx::FileAppender();
+ }
+
+ void testSetDoubleBackslashes() {
+ FileAppender appender;
+ appender.setOption(LOG4CXX_STR("FILE"), LOG4CXX_STR("output\\\\temp"));
+ const File& file = appender.getFile();
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("output\\temp"), file.getPath());
+ }
+
+ /**
+ * Tests that double backslashes in filespecs are stripped
+ * on calls to setOption.
+ *
+ */
+ void testStripDoubleBackslashes() {
+
+ FileAppender appender;
+ appender.setOption(LOG4CXX_STR("FILE"), LOG4CXX_STR("output\\\\temp"));
+ const File& file = appender.getFile();
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("output\\temp"), file.getPath());
+ }
+
+ /**
+ * Tests stripDuplicateBackslashes
+ *
+ *
+ */
+ void testStripDuplicateBackslashes() {
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("\\foo\\bar\\foo"),
+ FileAppender::stripDuplicateBackslashes(LOG4CXX_STR("\\foo\\bar\\foo")));
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("\\foo\\bar\\foo\\"),
+ FileAppender::stripDuplicateBackslashes(LOG4CXX_STR("\\\\foo\\\\bar\\\\foo\\\\")));
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("\\foo\\bar\\foo\\"),
+ FileAppender::stripDuplicateBackslashes(LOG4CXX_STR("\\foo\\bar\\foo\\")));
+ //
+ // UNC's should either start with two backslashes and contain additional singles
+ // or four back slashes and addition doubles
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("\\\\foo\\bar\\foo"),
+ FileAppender::stripDuplicateBackslashes(LOG4CXX_STR("\\\\\\\\foo\\\\bar\\\\foo")));
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("\\\\foo\\bar\\foo"),
+ FileAppender::stripDuplicateBackslashes(LOG4CXX_STR("\\\\foo\\bar\\foo")));
+ //
+ // it it starts with doubles but has no other path component
+ // then it is a file path
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("\\foo.log"),
+ FileAppender::stripDuplicateBackslashes(LOG4CXX_STR("\\\\foo.log")));
+ //
+ // it it starts with quads but has no other path component
+ // then it is a UNC
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("\\\\foo.log"),
+ FileAppender::stripDuplicateBackslashes(LOG4CXX_STR("\\\\\\\\foo.log")));
+ }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(FileAppenderTestCase);
diff --git a/src/test/cpp/fileappendertestcase.h b/src/test/cpp/fileappendertestcase.h
new file mode 100644
index 0000000..4eabed3
--- /dev/null
+++ b/src/test/cpp/fileappendertestcase.h
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/fileappender.h>
+#include "writerappendertestcase.h"
+
+
+/**
+ An abstract set of tests for inclusion in concrete
+ appender test case
+ */
+class FileAppenderAbstractTestCase : public WriterAppenderTestCase
+{
+
+public:
+ log4cxx::WriterAppender* createWriterAppender() const;
+
+ virtual log4cxx::FileAppender* createFileAppender() const = 0;
+
+};
diff --git a/src/test/cpp/filetestcase.cpp b/src/test/cpp/filetestcase.cpp
new file mode 100755
index 0000000..06efce2
--- /dev/null
+++ b/src/test/cpp/filetestcase.cpp
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/file.h>
+#include "logunit.h"
+#include "insertwide.h"
+#include <log4cxx/helpers/pool.h>
+#include <apr_errno.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/fileinputstream.h>
+
+#include <log4cxx/helpers/outputstreamwriter.h>
+#include <log4cxx/helpers/fileoutputstream.h>
+#include <log4cxx/helpers/inputstreamreader.h>
+#include <log4cxx/helpers/fileinputstream.h>
+
+#if LOG4CXX_CFSTRING_API
+#include <CoreFoundation/CFString.h>
+#endif
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+LOGUNIT_CLASS(FileTestCase)
+{
+ LOGUNIT_TEST_SUITE(FileTestCase);
+ LOGUNIT_TEST(defaultConstructor);
+ LOGUNIT_TEST(defaultExists);
+ LOGUNIT_TEST(defaultRead);
+ LOGUNIT_TEST(propertyRead);
+ LOGUNIT_TEST(propertyExists);
+ LOGUNIT_TEST(fileWrite1);
+#if LOG4CXX_WCHAR_T_API
+ LOGUNIT_TEST(wcharConstructor);
+#endif
+#if LOG4CXX_UNICHAR_API
+ LOGUNIT_TEST(unicharConstructor);
+#endif
+#if LOG4CXX_CFSTRING_API
+ LOGUNIT_TEST(cfstringConstructor);
+#endif
+ LOGUNIT_TEST(copyConstructor);
+ LOGUNIT_TEST(assignment);
+ LOGUNIT_TEST(deleteBackslashedFileName);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ void defaultConstructor() {
+ File defFile;
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR(""), defFile.getPath());
+ }
+
+
+
+ void defaultExists() {
+ File defFile;
+ Pool pool;
+ bool exists = defFile.exists(pool);
+ LOGUNIT_ASSERT_EQUAL(false, exists);
+ }
+
+ // check default constructor. read() throws an exception
+ // if no file name was given.
+ void defaultRead() {
+ File defFile;
+ Pool pool;
+ try {
+ InputStreamPtr defInput = new FileInputStream(defFile);
+ InputStreamReaderPtr inputReader = new InputStreamReader(defInput);
+ LogString contents(inputReader->read(pool));
+ LOGUNIT_ASSERT(false);
+ } catch(IOException &ex) {
+ }
+ }
+
+
+#if LOG4CXX_WCHAR_T_API
+ void wcharConstructor() {
+ File propFile(L"input/patternLayout1.properties");
+ Pool pool;
+ bool exists = propFile.exists(pool);
+ LOGUNIT_ASSERT_EQUAL(true, exists);
+ }
+#endif
+
+#if LOG4CXX_UNICHAR_API
+ void unicharConstructor() {
+ const log4cxx::UniChar filename[] = { 'i', 'n', 'p', 'u', 't', '/',
+ 'p', 'a', 't', 't', 'e', 'r', 'n', 'L', 'a', 'y', 'o', 'u', 't', '1', '.',
+ 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's', 0 };
+ File propFile(filename);
+ Pool pool;
+ bool exists = propFile.exists(pool);
+ LOGUNIT_ASSERT_EQUAL(true, exists);
+ }
+#endif
+
+#if LOG4CXX_CFSTRING_API
+ void cfstringConstructor() {
+ File propFile(CFSTR("input/patternLayout.properties"));
+ Pool pool;
+ bool exists = propFile.exists(pool);
+ LOGUNIT_ASSERT_EQUAL(true, exists);
+ }
+#endif
+
+ void copyConstructor() {
+ File propFile("input/patternLayout1.properties");
+ File copy(propFile);
+ Pool pool;
+ bool exists = copy.exists(pool);
+ LOGUNIT_ASSERT_EQUAL(true, exists);
+ }
+
+ void assignment() {
+ File propFile("input/patternLayout1.properties");
+ File copy = propFile;
+ Pool pool;
+ bool exists = copy.exists(pool);
+ LOGUNIT_ASSERT_EQUAL(true, exists);
+ }
+
+ void propertyRead() {
+ File propFile("input/patternLayout1.properties");
+ Pool pool;
+ InputStreamPtr propStream = new FileInputStream(propFile);
+ InputStreamReaderPtr propReader = new InputStreamReader(propStream);
+ LogString props(propReader->read(pool));
+ LogString line1(LOG4CXX_STR("# Licensed to the Apache Software Foundation (ASF) under one or more"));
+ LOGUNIT_ASSERT_EQUAL(line1, props.substr(0, line1.length()));
+ }
+
+ void propertyExists() {
+ File propFile("input/patternLayout1.properties");
+ Pool pool;
+ bool exists = propFile.exists(pool);
+ LOGUNIT_ASSERT_EQUAL(true, exists);
+ }
+
+ void fileWrite1() {
+ OutputStreamPtr fos =
+ new FileOutputStream(LOG4CXX_STR("output/fileWrite1.txt"));
+ OutputStreamWriterPtr osw = new OutputStreamWriter(fos);
+
+ Pool pool;
+ LogString greeting(LOG4CXX_STR("Hello, World"));
+ greeting.append(LOG4CXX_EOL);
+ osw->write(greeting, pool);
+
+ InputStreamPtr is =
+ new FileInputStream(LOG4CXX_STR("output/fileWrite1.txt"));
+ InputStreamReaderPtr isr = new InputStreamReader(is);
+ LogString reply = isr->read(pool);
+
+ LOGUNIT_ASSERT_EQUAL(greeting, reply);
+ }
+
+ /**
+ * Tests conversion of backslash containing file names.
+ * Would cause infinite loop due to bug LOGCXX-105.
+ */
+ void deleteBackslashedFileName() {
+ File file("output\\bogus.txt");
+ Pool pool;
+ /*bool deleted = */file.deleteFile(pool);
+ }
+};
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(FileTestCase);
diff --git a/src/test/cpp/helpers/absolutetimedateformattestcase.cpp b/src/test/cpp/helpers/absolutetimedateformattestcase.cpp
new file mode 100644
index 0000000..8f19117
--- /dev/null
+++ b/src/test/cpp/helpers/absolutetimedateformattestcase.cpp
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "../logunit.h"
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/absolutetimedateformat.h>
+#include "../insertwide.h"
+#include <apr.h>
+#include <apr_time.h>
+#include <log4cxx/helpers/pool.h>
+
+//Define INT64_C for compilers that don't have it
+#if (!defined(INT64_C))
+#define INT64_C(value) value ## LL
+#endif
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+
+/**
+ Unit test {@link AbsoluteTimeDateFormat}.
+
+ */
+LOGUNIT_CLASS(AbsoluteTimeDateFormatTestCase) {
+ LOGUNIT_TEST_SUITE(AbsoluteTimeDateFormatTestCase);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST(test3);
+ LOGUNIT_TEST(test4);
+ LOGUNIT_TEST(test5);
+ LOGUNIT_TEST(test6);
+ LOGUNIT_TEST(test7);
+ LOGUNIT_TEST(test8);
+ LOGUNIT_TEST_SUITE_END();
+
+ public:
+
+ /**
+ * Asserts that formatting the provided date results
+ * in the expected string.
+ *
+ * @param date Date date
+ * @param timeZone TimeZone timezone for conversion
+ * @param expected String expected string
+ */
+ private:
+ void assertFormattedTime(apr_time_t date,
+ const TimeZonePtr& timeZone,
+ const LogString& expected) {
+ AbsoluteTimeDateFormat formatter;
+ formatter.setTimeZone(timeZone);
+ LogString actual;
+ Pool p;
+ formatter.format(actual, date, p);
+ LOGUNIT_ASSERT_EQUAL(expected, actual);
+ }
+
+#define MICROSECONDS_PER_DAY APR_INT64_C(86400000000)
+
+ public:
+ /**
+ * Convert 02 Jan 2004 00:00:00 GMT for GMT.
+ */
+ void test1() {
+ //
+ // 02 Jan 2004 00:00 GMT
+ //
+ apr_time_t jan2 = MICROSECONDS_PER_DAY * 12419;
+ assertFormattedTime(jan2, TimeZone::getGMT(), LOG4CXX_STR("00:00:00,000"));
+ }
+
+ /**
+ * Convert 03 Jan 2004 00:00:00 GMT for America/Chicago.
+ */
+ void test2() {
+ //
+ // 03 Jan 2004 00:00 GMT
+ // (asking for the same time at a different timezone
+ // will ignore the change of timezone)
+ apr_time_t jan2 = MICROSECONDS_PER_DAY * 12420;
+ assertFormattedTime(jan2, TimeZone::getTimeZone(LOG4CXX_STR("GMT-6")), LOG4CXX_STR("18:00:00,000"));
+ }
+
+ /**
+ * Convert 29 Jun 2004 00:00:00 GMT for GMT.
+ */
+ void test3() {
+ apr_time_t jun29 = MICROSECONDS_PER_DAY * 12599;
+ assertFormattedTime(jun29, TimeZone::getGMT(), LOG4CXX_STR("00:00:00,000"));
+ }
+
+ /**
+ * Convert 29 Jun 2004 00:00:00 GMT for Chicago, daylight savings in effect.
+ */
+ void test4() {
+ apr_time_t jun30 = MICROSECONDS_PER_DAY * 12600;
+ //
+ // log4cxx doesn't support non-fixed timezones at this time
+ // passing the fixed equivalent to Chicago's Daylight Savings Time
+ //
+ assertFormattedTime(jun30, TimeZone::getTimeZone(LOG4CXX_STR("GMT-5")), LOG4CXX_STR("19:00:00,000"));
+ }
+
+ /**
+ * Test multiple calls in close intervals.
+ */
+ void test5() {
+ // subsequent calls within one minute
+ // are optimized to reuse previous formatted value
+ // make a couple of nearly spaced calls
+ apr_time_t ticks = MICROSECONDS_PER_DAY * 12601;
+ assertFormattedTime(ticks, TimeZone::getGMT(), LOG4CXX_STR("00:00:00,000"));
+ assertFormattedTime(ticks + 8000, TimeZone::getGMT(), LOG4CXX_STR("00:00:00,008"));
+ assertFormattedTime(ticks + 17000, TimeZone::getGMT(), LOG4CXX_STR("00:00:00,017"));
+ assertFormattedTime(ticks + 237000, TimeZone::getGMT(), LOG4CXX_STR("00:00:00,237"));
+ assertFormattedTime(ticks + 1415000, TimeZone::getGMT(), LOG4CXX_STR("00:00:01,415"));
+ }
+
+ /**
+ * Check that caching does not disregard timezone.
+ * This test would fail for revision 1.4 of AbsoluteTimeDateFormat.java.
+ */
+ void test6() {
+ apr_time_t jul2 = MICROSECONDS_PER_DAY * 12602;
+ assertFormattedTime(jul2, TimeZone::getGMT(), LOG4CXX_STR("00:00:00,000"));
+ assertFormattedTime(jul2, TimeZone::getTimeZone(LOG4CXX_STR("GMT-5")), LOG4CXX_STR("19:00:00,000"));
+ }
+
+ /**
+ * Test multiple calls in close intervals predating 1 Jan 1970.
+ */
+ void test7() {
+ // subsequent calls within one minute
+ // are optimized to reuse previous formatted value
+ // make a couple of nearly spaced calls
+ apr_time_t ticks = MICROSECONDS_PER_DAY * -7;
+ assertFormattedTime(ticks, TimeZone::getGMT(), LOG4CXX_STR("00:00:00,000"));
+#if defined(_WIN32)
+ //
+ // These tests fail on Unix due to bug in APR's explode_time
+ //
+// assertFormattedTime(ticks + 8000, TimeZone::getGMT(), LOG4CXX_STR("00:00:00,008"));
+// assertFormattedTime(ticks + 17000, TimeZone::getGMT(), LOG4CXX_STR("00:00:00,017"));
+// assertFormattedTime(ticks + 237000, TimeZone::getGMT(), LOG4CXX_STR("00:00:00,237"));
+// assertFormattedTime(ticks + 1415000, TimeZone::getGMT(), LOG4CXX_STR("00:00:01,415"));
+#endif
+ }
+
+ /**
+ * Checks that numberFormat works as expected.
+ */
+ void test8() {
+ Pool p;
+ LogString numb;
+ AbsoluteTimeDateFormat formatter;
+ formatter.numberFormat(numb, 87, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("87"), numb);
+ }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(AbsoluteTimeDateFormatTestCase);
+
diff --git a/src/test/cpp/helpers/cacheddateformattestcase.cpp b/src/test/cpp/helpers/cacheddateformattestcase.cpp
new file mode 100644
index 0000000..4f68924
--- /dev/null
+++ b/src/test/cpp/helpers/cacheddateformattestcase.cpp
@@ -0,0 +1,613 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/cacheddateformat.h>
+#include "../logunit.h"
+#include <log4cxx/helpers/absolutetimedateformat.h>
+#include <log4cxx/helpers/relativetimedateformat.h>
+#include <log4cxx/helpers/pool.h>
+#include <locale>
+#include "../insertwide.h"
+#include <apr.h>
+#include <apr_time.h>
+#include "localechanger.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::pattern;
+
+#define LOCALE_US "C"
+#if defined(_WIN32)
+#define LOCALE_JP "Japanese_japan"
+#else
+#define LOCALE_JP "ja_JP"
+#endif
+
+
+//Define INT64_C for compilers that don't have it
+#if (!defined(INT64_C))
+#define INT64_C(value) value ##LL
+#endif
+
+#define LOG4CXX_TEST 1
+#include <log4cxx/private/log4cxx_private.h>
+
+
+/**
+ Unit test {@link CachedDateFormat}.
+
+ */
+LOGUNIT_CLASS(CachedDateFormatTestCase)
+ {
+ LOGUNIT_TEST_SUITE( CachedDateFormatTestCase );
+ LOGUNIT_TEST( test1 );
+ LOGUNIT_TEST( test2 );
+ LOGUNIT_TEST( test3 );
+ LOGUNIT_TEST( test4 );
+#if LOG4CXX_HAS_STD_LOCALE
+ LOGUNIT_TEST( test5 );
+#endif
+ LOGUNIT_TEST( test6 );
+ LOGUNIT_TEST( test8 );
+// Gump doesn't like this test
+// LOGUNIT_TEST( test9 );
+ LOGUNIT_TEST( test10 );
+ LOGUNIT_TEST( test11);
+ LOGUNIT_TEST( test12 );
+ LOGUNIT_TEST( test13 );
+ LOGUNIT_TEST( test14 );
+ LOGUNIT_TEST( test15 );
+ LOGUNIT_TEST( test16 );
+ LOGUNIT_TEST( test17);
+ LOGUNIT_TEST( test18);
+ LOGUNIT_TEST( test19);
+ LOGUNIT_TEST( test20);
+ LOGUNIT_TEST( test21);
+ LOGUNIT_TEST_SUITE_END();
+
+
+#define MICROSECONDS_PER_DAY APR_INT64_C(86400000000)
+
+ public:
+
+ /**
+ * Test multiple calls in close intervals.
+ */
+ void test1() {
+ // subsequent calls within one minute
+ // are optimized to reuse previous formatted value
+ // make a couple of nearly spaced calls
+ DateFormatPtr baseFormatter(new AbsoluteTimeDateFormat());
+ CachedDateFormat gmtFormat(baseFormatter, 1000000);
+ gmtFormat.setTimeZone(TimeZone::getGMT());
+
+ apr_time_t jul1 = MICROSECONDS_PER_DAY * 12601L;
+ Pool p;
+
+ LogString actual;
+
+ gmtFormat.format(actual, jul1, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:00,000"), actual);
+ actual.erase(actual.begin(), actual.end());
+
+ gmtFormat.format(actual, jul1 + 8000, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:00,008"), actual);
+ actual.erase(actual.begin(), actual.end());
+
+ gmtFormat.format(actual, jul1 + 17000, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:00,017"), actual);
+ actual.erase(actual.begin(), actual.end());
+
+ gmtFormat.format(actual, jul1 + 237000, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:00,237"), actual);
+ actual.erase(actual.begin(), actual.end());
+
+ gmtFormat.format(actual, jul1 + 1415000, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:01,415"), actual);
+ actual.erase(actual.begin(), actual.end());
+
+ }
+
+ /**
+ * Check for interaction between caches.
+ */
+
+ void test2() {
+ apr_time_t jul2 = MICROSECONDS_PER_DAY * 12602;
+ DateFormatPtr baseFormatter(new AbsoluteTimeDateFormat());
+ CachedDateFormat gmtFormat(baseFormatter, 1000000);
+ gmtFormat.setTimeZone(TimeZone::getGMT());
+
+ DateFormatPtr chicagoBase(new AbsoluteTimeDateFormat());
+ CachedDateFormat chicagoFormat(chicagoBase, 1000000);
+ chicagoFormat.setTimeZone(TimeZone::getTimeZone(LOG4CXX_STR("GMT-5")));
+
+ Pool p;
+ LogString actual;
+ gmtFormat.format(actual, jul2, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:00,000"), actual);
+
+ actual.erase(actual.begin(), actual.end());
+ chicagoFormat.format(actual, jul2, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("19:00:00,000"), actual);
+
+ actual.erase(actual.begin(), actual.end());
+ gmtFormat.format(actual, jul2, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:00,000"), actual);
+ }
+
+ /**
+ * Test multiple calls in close intervals prior to 1 Jan 1970.
+ */
+ void test3() {
+ // subsequent calls within one minute
+ // are optimized to reuse previous formatted value
+ // make a couple of nearly spaced calls
+ DateFormatPtr baseFormatter(new AbsoluteTimeDateFormat());
+ CachedDateFormat gmtFormat(baseFormatter, 1000000);
+ gmtFormat.setTimeZone(TimeZone::getGMT());
+
+ apr_time_t ticks = MICROSECONDS_PER_DAY * -7;
+
+ Pool p;
+
+ LogString actual;
+
+
+ gmtFormat.format(actual, ticks, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:00,000"), actual);
+ actual.erase(actual.begin(), actual.end());
+
+ //
+ // APR's explode_time method does not properly calculate tm_usec
+ // prior to 1 Jan 1970 on Unix
+ gmtFormat.format(actual, ticks + 8000, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:00,008"), actual);
+ actual.erase(actual.begin(), actual.end());
+
+ gmtFormat.format(actual, ticks + 17000, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:00,017"), actual);
+ actual.erase(actual.begin(), actual.end());
+
+ gmtFormat.format(actual, ticks + 237000, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:00,237"), actual);
+ actual.erase(actual.begin(), actual.end());
+
+ gmtFormat.format(actual, ticks + 1423000, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:01,423"), actual);
+ }
+
+ void assertFormattedEquals(
+ const DateFormatPtr& baseFormat,
+ const CachedDateFormat& cachedFormat,
+ apr_time_t date,
+ Pool& p) {
+ LogString expected;
+ LogString actual;
+
+ baseFormat->format(expected, date, p);
+ cachedFormat.format(actual, date, p);
+
+
+ LOGUNIT_ASSERT_EQUAL(expected, actual);
+ }
+
+ void test4() {
+ // subsequent calls within one minute
+ // are optimized to reuse previous formatted value
+ // make a couple of nearly spaced calls
+#if LOG4CXX_HAS_STD_LOCALE
+ std::locale loco(LOCALE_US);
+ std::locale* localeEN = &loco;
+#else
+ std::locale* localeEN = NULL;
+#endif
+ DateFormatPtr baseFormat(
+ new SimpleDateFormat(LOG4CXX_STR("EEE, MMM dd, HH:mm:ss.SSS Z"), localeEN));
+ CachedDateFormat cachedFormat(baseFormat, 1000000);
+ //
+ // use a date in 2000 to attempt to confuse the millisecond locator
+ apr_time_t ticks = MICROSECONDS_PER_DAY * 11141;
+
+ Pool p;
+
+ assertFormattedEquals(baseFormat, cachedFormat, ticks, p);
+ assertFormattedEquals(baseFormat, cachedFormat, ticks + 8000, p);
+ assertFormattedEquals(baseFormat, cachedFormat, ticks + 17000, p);
+ assertFormattedEquals(baseFormat, cachedFormat, ticks + 237000, p);
+ assertFormattedEquals(baseFormat, cachedFormat, ticks + 1415000, p);
+ }
+
+
+#if LOG4CXX_HAS_STD_LOCALE
+ void test5() {
+ // subsequent calls within one minute
+ // are optimized to reuse previous formatted value
+ // make a couple of nearly spaced calls
+ LocaleChanger localeChange(LOCALE_JP);
+ if (localeChange.isEffective()) {
+ DateFormatPtr baseFormat(new SimpleDateFormat(
+ LOG4CXX_STR("EEE, MMM dd, HH:mm:ss.SSS Z")));
+ CachedDateFormat cachedFormat(baseFormat, 1000000);
+ //
+ // use a date in 2000 to attempt to confuse the millisecond locator
+ apr_time_t ticks = MICROSECONDS_PER_DAY * 11141;
+
+ Pool p;
+
+ assertFormattedEquals(baseFormat, cachedFormat, ticks, p);
+ assertFormattedEquals(baseFormat, cachedFormat, ticks + 8000, p);
+ assertFormattedEquals(baseFormat, cachedFormat, ticks + 17000, p);
+ assertFormattedEquals(baseFormat, cachedFormat, ticks + 237000, p);
+ assertFormattedEquals(baseFormat, cachedFormat, ticks + 1415000, p);
+ }
+ }
+#endif
+
+ /**
+ * Checks that numberFormat works as expected.
+ */
+ void test6() {
+ LogString numb;
+ Pool p;
+ AbsoluteTimeDateFormat formatter;
+ formatter.numberFormat(numb, 87, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("87"), numb);
+ }
+
+
+ /**
+ * Set time zone on cached and check that it is effective.
+ */
+ void test8() {
+ DateFormatPtr baseFormat(new SimpleDateFormat(LOG4CXX_STR("yyyy-MM-dd HH:mm:ss,SSS")));
+ baseFormat->setTimeZone(TimeZone::getGMT());
+ CachedDateFormat cachedFormat(baseFormat, 1000000);
+ apr_time_t jul4 = MICROSECONDS_PER_DAY * 12603;
+
+ Pool p;
+
+ LogString actual;
+ cachedFormat.format(actual, jul4, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("2004-07-04 00:00:00,000"), actual);
+
+ cachedFormat.setTimeZone(TimeZone::getTimeZone(LOG4CXX_STR("GMT-6")));
+ actual.erase(actual.begin(), actual.end());
+ cachedFormat.format(actual, jul4, p);
+
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("2004-07-03 18:00:00,000"), actual);
+ }
+
+
+/**
+ * Test of caching when less than three millisecond digits are specified.
+ */
+void test9() {
+ std::locale localeUS(LOCALE_US);
+
+ DateFormatPtr baseFormat = new SimpleDateFormat(
+ LOG4CXX_STR("yyyy-MMMM-dd HH:mm:ss,SS Z"), &localeUS);
+ DateFormatPtr cachedFormat = new CachedDateFormat(baseFormat, 1000000);
+ TimeZonePtr cet = TimeZone::getTimeZone(LOG4CXX_STR("GMT+1"));
+ cachedFormat->setTimeZone(cet);
+
+
+ apr_time_exp_t c;
+ memset(&c, 0, sizeof(c));
+ c.tm_year = 104;
+ c.tm_mon = 11;
+ c.tm_mday = 12;
+ c.tm_hour = 19;
+ c.tm_sec = 37;
+ c.tm_usec = 23000;
+
+ apr_time_t dec12;
+ apr_status_t stat = apr_time_exp_gmt_get(&dec12, &c);
+ const apr_status_t statOK = 0;
+ LOGUNIT_ASSERT_EQUAL(statOK, stat);
+
+ Pool p;
+
+ LogString s;
+ cachedFormat->format(s, dec12, p);
+
+ LOGUNIT_ASSERT_EQUAL(
+ (LogString) LOG4CXX_STR("2004-December-12 20:00:37,23 +0100"), s);
+
+ memset(&c, 0, sizeof(c));
+ c.tm_year = 104;
+ c.tm_mon = 11;
+ c.tm_mday = 31;
+ c.tm_hour = 23;
+ c.tm_sec = 13;
+ c.tm_usec = 905000;
+
+ apr_time_t jan1;
+ stat = apr_time_exp_gmt_get(&jan1, &c);
+ LOGUNIT_ASSERT_EQUAL(statOK, stat);
+
+ s.erase(s.begin(), s.end());
+ cachedFormat->format(s, jan1, p);
+
+ LOGUNIT_ASSERT_EQUAL(
+ (LogString) LOG4CXX_STR("2005-January-01 00:00:13,905 +0100"), s);
+}
+
+
+/**
+ * Test when millisecond position moves but length remains constant.
+ */
+void test10() {
+#if LOG4CXX_HAS_STD_LOCALE
+ std::locale loco("C");
+ std::locale* localeUS = &loco;
+#else
+ std::locale* localeUS = NULL;
+#endif
+ DateFormatPtr baseFormat = new SimpleDateFormat(
+ LOG4CXX_STR("MMMM SSS EEEEEE"), localeUS);
+ DateFormatPtr cachedFormat = new CachedDateFormat(baseFormat, 1000000);
+ TimeZonePtr cet = TimeZone::getTimeZone(LOG4CXX_STR("GMT+1"));
+ cachedFormat->setTimeZone(cet);
+
+ apr_time_exp_t c;
+ memset(&c, 0, sizeof(c));
+ c.tm_year = 104;
+ c.tm_mon = 9;
+ c.tm_mday = 5;
+ c.tm_hour = 21;
+ c.tm_sec = 37;
+ c.tm_usec = 23000;
+
+ apr_time_t oct5;
+ apr_status_t stat = apr_time_exp_gmt_get(&oct5, &c);
+ const apr_status_t statOK = 0;
+ LOGUNIT_ASSERT_EQUAL(statOK, stat);
+
+ Pool p;
+
+ LogString s;
+ cachedFormat->format(s, oct5, p);
+
+ LOGUNIT_ASSERT_EQUAL(
+ (LogString) LOG4CXX_STR("October 023 Tuesday"), s);
+
+ memset(&c, 0, sizeof(c));
+ c.tm_year = 104;
+ c.tm_mon = 10;
+ c.tm_mday = 1;
+ c.tm_usec = 23000;
+
+ apr_time_t nov1;
+ stat = apr_time_exp_gmt_get(&nov1, &c);
+ LOGUNIT_ASSERT_EQUAL(statOK, stat);
+
+ s.erase(s.begin(), s.end());
+ cachedFormat->format(s, nov1, p);
+
+ LOGUNIT_ASSERT_EQUAL(
+ (LogString) LOG4CXX_STR("November 023 Monday"), s);
+
+ nov1 += 961000;
+ s.erase(s.begin(), s.end());
+ cachedFormat->format(s, nov1, p);
+
+ LOGUNIT_ASSERT_EQUAL(
+ (LogString) LOG4CXX_STR("November 984 Monday"), s);
+}
+
+/**
+ * Test that tests if caching is skipped if only "SS"
+ * is specified.
+ */
+void test11() {
+ //
+ // Earlier versions could be tricked by "SS0" patterns.
+ //
+ LogString badPattern(LOG4CXX_STR("ss,SS0"));
+ DateFormatPtr simpleFormat = new SimpleDateFormat(badPattern);
+ DateFormatPtr gmtFormat = new CachedDateFormat(simpleFormat, 1000000);
+ gmtFormat->setTimeZone(TimeZone::getGMT());
+
+ //
+ // The first request has to 100 ms after an ordinal second
+ // to push the literal zero out of the pattern check
+ apr_time_t ticks = MICROSECONDS_PER_DAY * 11142L;
+ apr_time_t jul2 = ticks + 120000;
+
+ Pool p;
+
+ LogString s;
+ gmtFormat->format(s, jul2, p);
+
+ LOGUNIT_ASSERT_EQUAL(
+ (LogString) LOG4CXX_STR("00,1200"), s);
+
+ jul2 = ticks + 87000;
+
+ s.erase(s.begin(), s.end());
+ gmtFormat->format(s, jul2, p);
+
+ LOGUNIT_ASSERT_EQUAL(
+ (LogString) LOG4CXX_STR("00,870"), s);
+}
+
+/**
+ * Check pattern location for ISO8601
+ */
+void test12() {
+ DateFormatPtr df = new SimpleDateFormat(LOG4CXX_STR("yyyy-MM-dd HH:mm:ss,SSS"));
+ apr_time_t ticks = 11142L * MICROSECONDS_PER_DAY;
+
+ Pool p;
+
+ LogString formatted;
+ df->format(formatted, ticks, p);
+
+ int millisecondStart = CachedDateFormat::findMillisecondStart(ticks,
+ formatted, df, p);
+ LOGUNIT_ASSERT_EQUAL(20, millisecondStart);
+}
+
+/**
+ * Check pattern location for DATE
+ */
+void test13() {
+ DateFormatPtr df = new SimpleDateFormat(LOG4CXX_STR("yyyy-MM-dd"));
+ apr_time_t ticks = 11142L * MICROSECONDS_PER_DAY;
+
+ Pool p;
+
+ LogString formatted;
+ df->format(formatted, ticks, p);
+
+ int millisecondStart = CachedDateFormat::findMillisecondStart(ticks,
+ formatted, df, p);
+ LOGUNIT_ASSERT_EQUAL((int) CachedDateFormat::NO_MILLISECONDS, millisecondStart);
+}
+
+/**
+ * Check pattern location for ABSOLUTE
+ */
+void test14() {
+ DateFormatPtr df = new SimpleDateFormat(LOG4CXX_STR("HH:mm:ss,SSS"));
+ apr_time_t ticks = 11142L * MICROSECONDS_PER_DAY;
+
+ Pool p;
+ LogString formatted;
+ df->format(formatted, ticks, p);
+
+ int millisecondStart = CachedDateFormat::findMillisecondStart(ticks,
+ formatted, df, p);
+ LOGUNIT_ASSERT_EQUAL(9, millisecondStart);
+}
+
+/**
+ * Check pattern location for single S
+ */
+void test15() {
+ DateFormatPtr df = new SimpleDateFormat(LOG4CXX_STR("HH:mm:ss,S"));
+ apr_time_t ticks = 11142L * MICROSECONDS_PER_DAY;
+
+ Pool p;
+ LogString formatted;
+ df->format(formatted, ticks, p);
+
+ int millisecondStart = CachedDateFormat::findMillisecondStart(ticks,
+ formatted, df, p);
+ LOGUNIT_ASSERT_EQUAL((int) CachedDateFormat::UNRECOGNIZED_MILLISECONDS, millisecondStart);
+}
+
+/**
+ * Check pattern location for single SS
+ */
+void test16() {
+ DateFormatPtr df = new SimpleDateFormat(LOG4CXX_STR("HH:mm:ss,SS"));
+ apr_time_t ticks = 11142L * MICROSECONDS_PER_DAY;
+
+ Pool p;
+ LogString formatted;
+ df->format(formatted, ticks, p);
+
+ int millisecondStart =
+ CachedDateFormat::findMillisecondStart(ticks, formatted, df, p);
+ LOGUNIT_ASSERT_EQUAL((int) CachedDateFormat::UNRECOGNIZED_MILLISECONDS, millisecondStart);
+}
+
+
+/**
+ * Check caching when multiple SSS appear in pattern
+ */
+void test17() {
+ apr_time_t jul2 = 12602L * MICROSECONDS_PER_DAY;
+ LogString badPattern(LOG4CXX_STR("HH:mm:ss,SSS HH:mm:ss,SSS"));
+ DateFormatPtr simpleFormat = new SimpleDateFormat(badPattern);
+ simpleFormat->setTimeZone(TimeZone::getGMT());
+ DateFormatPtr cachedFormat = new CachedDateFormat(simpleFormat, 1000000);
+
+ Pool p;
+ LogString s;
+ cachedFormat->format(s, jul2, p);
+
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:00,000 00:00:00,000"), s);
+ jul2 += 120000;
+
+ s.erase(s.begin(), s.end());
+ simpleFormat->format(s, jul2, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:00,120 00:00:00,120"), s);
+
+ s.erase(s.begin(), s.end());
+ cachedFormat->format(s, jul2, p);
+
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("00:00:00,120 00:00:00,120"), s) ;
+
+ int maxValid = CachedDateFormat::getMaximumCacheValidity(badPattern);
+ LOGUNIT_ASSERT_EQUAL(1000, maxValid);
+}
+
+/**
+ * Check that patterns not containing microseconds
+ * are reported as being able to be cached for a full second.
+ */
+void test18() {
+
+ int maxValid =
+ CachedDateFormat::getMaximumCacheValidity(
+ LOG4CXX_STR("yyyy-MM-dd"));
+ LOGUNIT_ASSERT_EQUAL(1000000, maxValid);
+}
+
+/**
+ * Check that patterns not containing 3 microseconds
+ * are reported as being able to be cached for a full second.
+ */
+void test19() {
+
+ int maxValid =
+ CachedDateFormat::getMaximumCacheValidity(
+ LOG4CXX_STR("yyyy-MM-dd SSS"));
+ LOGUNIT_ASSERT_EQUAL(1000000, maxValid);
+}
+
+/**
+ * Check that patterns not containing 2 S's
+ * are reported as being able to be cached for only a millisecond.
+ */
+void test20() {
+
+ int maxValid =
+ CachedDateFormat::getMaximumCacheValidity(
+ LOG4CXX_STR("yyyy-MM-dd SS"));
+ LOGUNIT_ASSERT_EQUAL(1000, maxValid);
+}
+
+/**
+ * Check that patterns not containing multi S groups
+ * are reported as being able to be cached for only a millisecond.
+ */
+void test21() {
+
+ int maxValid =
+ CachedDateFormat::getMaximumCacheValidity(
+ LOG4CXX_STR("yyyy-MM-dd SSS SSS"));
+ LOGUNIT_ASSERT_EQUAL(1000, maxValid);
+}
+
+};
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(CachedDateFormatTestCase);
diff --git a/src/test/cpp/helpers/charsetdecodertestcase.cpp b/src/test/cpp/helpers/charsetdecodertestcase.cpp
new file mode 100644
index 0000000..22a485f
--- /dev/null
+++ b/src/test/cpp/helpers/charsetdecodertestcase.cpp
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/charsetdecoder.h>
+#include "../logunit.h"
+#include "../insertwide.h"
+#include <log4cxx/helpers/bytebuffer.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+#define APR_SUCCESS ((log4cxx_status_t) 0)
+
+
+
+LOGUNIT_CLASS(CharsetDecoderTestCase)
+{
+ LOGUNIT_TEST_SUITE(CharsetDecoderTestCase);
+ LOGUNIT_TEST(decode1);
+ LOGUNIT_TEST(decode2);
+ LOGUNIT_TEST(decode8);
+ LOGUNIT_TEST_SUITE_END();
+
+ enum { BUFSIZE = 256 };
+
+public:
+
+
+ void decode1() {
+ char buf[] = "Hello, World";
+ ByteBuffer src(buf, strlen(buf));
+
+ CharsetDecoderPtr dec(CharsetDecoder::getDefaultDecoder());
+ LogString greeting;
+ log4cxx_status_t stat = dec->decode(src, greeting);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+
+ stat = dec->decode(src, greeting);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT_EQUAL((size_t) 12, src.position());
+
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("Hello, World"), greeting);
+ }
+
+ void decode2() {
+ char buf[BUFSIZE + 6];
+ memset(buf, 'A', BUFSIZE);
+ buf[BUFSIZE - 3] = 0;
+#if defined(__STDC_LIB_EXT1__) || defined(__STDC_SECURE_LIB__)
+ strcat_s(buf, sizeof buf, "Hello");
+#else
+ strcat(buf, "Hello");
+#endif
+ ByteBuffer src(buf, strlen(buf));
+
+ CharsetDecoderPtr dec(CharsetDecoder::getDefaultDecoder());
+
+ LogString greeting;
+ log4cxx_status_t stat = dec->decode(src, greeting);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT_EQUAL((size_t) 0, src.remaining());
+
+
+ stat = dec->decode(src, greeting);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+
+ LogString manyAs(BUFSIZE - 3, LOG4CXX_STR('A'));
+ LOGUNIT_ASSERT_EQUAL(manyAs, greeting.substr(0, BUFSIZE - 3));
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("Hello")), greeting.substr(BUFSIZE - 3));
+ }
+
+
+
+ void decode8() {
+ char buf[] = { 'H', 'e', 'l', 'l', 'o', ',', 0, 'W', 'o', 'r', 'l', 'd'};
+ ByteBuffer src(buf, 12);
+
+ CharsetDecoderPtr dec(CharsetDecoder::getDefaultDecoder());
+ LogString greeting;
+ log4cxx_status_t stat = dec->decode(src, greeting);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+
+ stat = dec->decode(src, greeting);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT_EQUAL((size_t) 12, src.position());
+
+ const logchar expected[] = { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x00, 0x57, 0x6F, 0x72, 0x6C, 0x64 };
+ LOGUNIT_ASSERT_EQUAL(LogString(expected, 12), greeting);
+ }
+
+
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(CharsetDecoderTestCase);
diff --git a/src/test/cpp/helpers/charsetencodertestcase.cpp b/src/test/cpp/helpers/charsetencodertestcase.cpp
new file mode 100644
index 0000000..74af926
--- /dev/null
+++ b/src/test/cpp/helpers/charsetencodertestcase.cpp
@@ -0,0 +1,302 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/charsetencoder.h>
+#include "../logunit.h"
+#include "../insertwide.h"
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/thread.h>
+#include <log4cxx/helpers/mutex.h>
+#include <log4cxx/helpers/condition.h>
+#include <log4cxx/helpers/synchronized.h>
+#include <apr.h>
+#include <apr_atomic.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+LOGUNIT_CLASS(CharsetEncoderTestCase)
+{
+ LOGUNIT_TEST_SUITE(CharsetEncoderTestCase);
+ LOGUNIT_TEST(encode1);
+ LOGUNIT_TEST(encode2);
+ LOGUNIT_TEST(encode3);
+ LOGUNIT_TEST(encode4);
+#if APR_HAS_THREADS
+ LOGUNIT_TEST(thread1);
+#endif
+ LOGUNIT_TEST_SUITE_END();
+
+ enum { BUFSIZE = 256 };
+
+public:
+
+
+ void encode1() {
+ const LogString greeting(LOG4CXX_STR("Hello, World"));
+ CharsetEncoderPtr enc(CharsetEncoder::getEncoder(LOG4CXX_STR("US-ASCII")));
+ char buf[BUFSIZE];
+ ByteBuffer out(buf, BUFSIZE);
+ LogString::const_iterator iter = greeting.begin();
+ log4cxx_status_t stat = enc->encode(greeting, iter, out);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT(iter == greeting.end());
+
+ stat = enc->encode(greeting, iter, out);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT_EQUAL((size_t) 12, out.position());
+
+ out.flip();
+ std::string encoded((const char*) out.data(), out.limit());
+ LOGUNIT_ASSERT_EQUAL((std::string) "Hello, World", encoded);
+ LOGUNIT_ASSERT(iter == greeting.end());
+ }
+
+ void encode2() {
+ LogString greeting(BUFSIZE - 3, LOG4CXX_STR('A'));
+ greeting.append(LOG4CXX_STR("Hello"));
+
+ CharsetEncoderPtr enc(CharsetEncoder::getEncoder(LOG4CXX_STR("US-ASCII")));
+
+ char buf[BUFSIZE];
+ ByteBuffer out(buf, BUFSIZE);
+ LogString::const_iterator iter = greeting.begin();
+ log4cxx_status_t stat = enc->encode(greeting, iter, out);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT_EQUAL((size_t) 0, out.remaining());
+ LOGUNIT_ASSERT_EQUAL(LOG4CXX_STR('o'), *(iter+1));
+
+ out.flip();
+ std::string encoded((char*) out.data(), out.limit());
+ out.clear();
+
+ stat = enc->encode(greeting, iter, out);
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT_EQUAL((size_t) 2, out.position());
+ LOGUNIT_ASSERT(iter == greeting.end());
+
+ stat = enc->encode(greeting, iter, out);
+ out.flip();
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ encoded.append(out.data(), out.limit());
+
+ std::string manyAs(BUFSIZE - 3, 'A');
+ LOGUNIT_ASSERT_EQUAL(manyAs, encoded.substr(0, BUFSIZE - 3));
+ LOGUNIT_ASSERT_EQUAL(std::string("Hello"), encoded.substr(BUFSIZE - 3));
+ }
+
+
+ void encode3() {
+#if LOG4CXX_LOGCHAR_IS_WCHAR || LOG4CXX_LOGCHAR_IS_UNICHAR
+ // arbitrary, hopefully meaningless, characters from
+ // Latin, Arabic, Armenian, Bengali, CJK and Cyrillic
+ const logchar greet[] = { L'A', 0x0605, 0x0530, 0x986, 0x4E03, 0x400, 0 };
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ const char greet[] = { 'A',
+ (char) 0xD8, (char) 0x85,
+ (char) 0xD4, (char) 0xB0,
+ (char) 0xE0, (char) 0xA6, (char) 0x86,
+ (char) 0xE4, (char) 0xB8, (char) 0x83,
+ (char) 0xD0, (char) 0x80,
+ 0 };
+#endif
+ LogString greeting(greet);
+
+ CharsetEncoderPtr enc(CharsetEncoder::getEncoder(LOG4CXX_STR("US-ASCII")));
+
+ char buf[BUFSIZE];
+ ByteBuffer out(buf, BUFSIZE);
+
+ LogString::const_iterator iter = greeting.begin();
+ log4cxx_status_t stat = enc->encode(greeting, iter, out);
+ out.flip();
+ LOGUNIT_ASSERT_EQUAL(true, CharsetEncoder::isError(stat));
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, out.limit());
+ LOGUNIT_ASSERT_EQUAL(greet[1], *iter);
+ LOGUNIT_ASSERT_EQUAL('A', out.data()[0]);
+ }
+
+
+ void encode4() {
+ const char utf8_greet[] = { 'A',
+ (char) 0xD8, (char) 0x85,
+ (char) 0xD4, (char) 0xB0,
+ (char) 0xE0, (char) 0xA6, (char) 0x86,
+ (char) 0xE4, (char) 0xB8, (char) 0x83,
+ (char) 0xD0, (char) 0x80,
+ 0 };
+#if LOG4CXX_LOGCHAR_IS_WCHAR || LOG4CXX_LOGCHAR_IS_UNICHAR
+ // arbitrary, hopefully meaningless, characters from
+ // Latin, Arabic, Armenian, Bengali, CJK and Cyrillic
+ const logchar greet[] = { L'A', 0x0605, 0x0530, 0x986, 0x4E03, 0x400, 0 };
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ const logchar *greet = utf8_greet;
+#endif
+ LogString greeting(greet);
+
+ CharsetEncoderPtr enc(CharsetEncoder::getEncoder(LOG4CXX_STR("UTF-8")));
+
+ char buf[BUFSIZE];
+ ByteBuffer out(buf, BUFSIZE);
+ LogString::const_iterator iter = greeting.begin();
+ log4cxx_status_t stat = enc->encode(greeting, iter, out);
+ LOGUNIT_ASSERT_EQUAL(false, CharsetEncoder::isError(stat));
+ stat = enc->encode(greeting, iter, out);
+ LOGUNIT_ASSERT_EQUAL(false, CharsetEncoder::isError(stat));
+
+ out.flip();
+ LOGUNIT_ASSERT_EQUAL((size_t) 13, out.limit());
+ for(size_t i = 0; i < out.limit(); i++) {
+ LOGUNIT_ASSERT_EQUAL((int) utf8_greet[i], (int) out.data()[i]);
+ }
+ LOGUNIT_ASSERT(iter == greeting.end());
+ }
+
+#if APR_HAS_THREADS
+ class ThreadPackage {
+ public:
+ ThreadPackage(CharsetEncoderPtr& enc, int repetitions) :
+ p(), lock(p), condition(p), passCount(0), failCount(0), enc(enc), repetitions(repetitions) {
+ }
+
+ void await() {
+ synchronized sync(lock);
+ condition.await(lock);
+ }
+
+ void signalAll() {
+ synchronized sync(lock);
+ condition.signalAll();
+ }
+
+ void fail() {
+ apr_atomic_inc32(&failCount);
+ }
+
+ void pass() {
+ apr_atomic_inc32(&passCount);
+ }
+
+ apr_uint32_t getFail() {
+ return apr_atomic_read32(&failCount);
+ }
+
+ apr_uint32_t getPass() {
+ return apr_atomic_read32(&passCount);
+ }
+
+ int getRepetitions() {
+ return repetitions;
+ }
+
+ CharsetEncoderPtr& getEncoder() {
+ return enc;
+ }
+
+ private:
+ ThreadPackage(const ThreadPackage&);
+ ThreadPackage& operator=(ThreadPackage&);
+ Pool p;
+ Mutex lock;
+ Condition condition;
+ volatile apr_uint32_t passCount;
+ volatile apr_uint32_t failCount;
+ CharsetEncoderPtr enc;
+ int repetitions;
+ };
+
+ static void* LOG4CXX_THREAD_FUNC thread1Action(apr_thread_t* /* thread */, void* data) {
+ ThreadPackage* package = (ThreadPackage*) data;
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ const logchar greet[] = { 'H', 'e', 'l', 'l', 'o', ' ',
+ (char) 0xC2, (char) 0xA2, // cent sign
+ (char) 0xC2, (char) 0xA9, // copyright
+ (char) 0xc3, (char) 0xb4, // latin small letter o with circumflex
+ 0 };
+#endif
+#if LOG4CXX_LOGCHAR_IS_WCHAR || LOG4CXX_LOGCHAR_IS_UNICHAR
+ // arbitrary, hopefully meaningless, characters from
+ // Latin, Arabic, Armenian, Bengali, CJK and Cyrillic
+ const logchar greet[] = { L'H', L'e', L'l', L'l', L'o', L' ',
+ 0x00A2, 0x00A9, 0x00F4 , 0 };
+#endif
+
+ const char expected[] = { 'H', 'e', 'l', 'l', 'o', ' ',
+ (char) 0x00A2, (char) 0x00A9, (char) 0x00F4 };
+
+ LogString greeting(greet);
+
+ package->await();
+ for(int i = 0; i < package->getRepetitions(); i++) {
+ bool pass = true;
+ char buf[BUFSIZE];
+ ByteBuffer out(buf, BUFSIZE);
+ LogString::const_iterator iter = greeting.begin();
+ log4cxx_status_t stat = package->getEncoder()->encode(greeting, iter, out);
+ pass = (false == CharsetEncoder::isError(stat));
+ if (pass) {
+ stat = package->getEncoder()->encode(greeting, iter, out);
+ pass = (false == CharsetEncoder::isError(stat));
+ if (pass) {
+ out.flip();
+ pass = (sizeof(expected) == out.limit());
+ for(size_t i = 0; i < out.limit() && pass; i++) {
+ pass = (expected[i] == out.data()[i]);
+ }
+ pass = pass && (iter == greeting.end());
+ }
+ }
+ if (pass) {
+ package->pass();
+ } else {
+ package->fail();
+ }
+ }
+ return 0;
+ }
+
+ void thread1() {
+ enum { THREAD_COUNT = 10, THREAD_REPS = 10000 };
+ Thread threads[THREAD_COUNT];
+ CharsetEncoderPtr enc(CharsetEncoder::getEncoder(LOG4CXX_STR("ISO-8859-1")));
+ ThreadPackage* package = new ThreadPackage(enc, THREAD_REPS);
+ { for(int i = 0; i < THREAD_COUNT; i++) {
+ threads[i].run(thread1Action, package);
+ } }
+ //
+ // give time for all threads to be launched so
+ // we don't signal before everybody is waiting.
+ Thread::sleep(100);
+ package->signalAll();
+ for(int i = 0; i < THREAD_COUNT; i++) {
+ threads[i].join();
+ }
+ LOGUNIT_ASSERT_EQUAL((apr_uint32_t) 0, package->getFail());
+ LOGUNIT_ASSERT_EQUAL((apr_uint32_t) THREAD_COUNT * THREAD_REPS, package->getPass());
+ delete package;
+ }
+#endif
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(CharsetEncoderTestCase);
diff --git a/src/test/cpp/helpers/cyclicbuffertestcase.cpp b/src/test/cpp/helpers/cyclicbuffertestcase.cpp
new file mode 100644
index 0000000..05e9065
--- /dev/null
+++ b/src/test/cpp/helpers/cyclicbuffertestcase.cpp
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/cyclicbuffer.h>
+#include "../logunit.h"
+
+#include <log4cxx/logmanager.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/spi/location/locationinfo.h>
+#include "../testchar.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+#define MAX 1000
+
+LOGUNIT_CLASS(CyclicBufferTestCase)
+{
+ LOGUNIT_TEST_SUITE(CyclicBufferTestCase);
+ LOGUNIT_TEST(test0);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(testResize);
+ LOGUNIT_TEST_SUITE_END();
+
+ LoggerPtr logger;
+ std::vector<LoggingEventPtr> e;
+
+public:
+ void setUp()
+ {
+ e.reserve(1000);
+ LoggingEventPtr event;
+ for (int i = 0; i < MAX; i++)
+ {
+ event = new LoggingEvent(LOG4CXX_STR("x"), Level::getDebug(), LOG4CXX_STR("e"),
+ log4cxx::spi::LocationInfo::getLocationUnavailable());
+ e.push_back(event);
+ }
+ }
+
+ void tearDown()
+ {
+ LogManager::shutdown();
+ }
+
+ void test0()
+ {
+ int size = 2;
+
+ CyclicBuffer cb(size);
+ LOGUNIT_ASSERT_EQUAL(size, cb.getMaxSize());
+
+ cb.add(e[0]);
+ LOGUNIT_ASSERT_EQUAL(1, cb.length());
+ LOGUNIT_ASSERT_EQUAL(e[0], cb.get());
+ LOGUNIT_ASSERT_EQUAL(0, cb.length());
+ LOGUNIT_ASSERT(cb.get() == 0);
+ LOGUNIT_ASSERT_EQUAL(0, cb.length());
+
+ CyclicBuffer cb2(size);
+ cb2.add(e[0]);
+ cb2.add(e[1]);
+ LOGUNIT_ASSERT_EQUAL(2, cb2.length());
+ LOGUNIT_ASSERT_EQUAL(e[0], cb2.get());
+ LOGUNIT_ASSERT_EQUAL(1, cb2.length());
+ LOGUNIT_ASSERT_EQUAL(e[1], cb2.get());
+ LOGUNIT_ASSERT_EQUAL(0, cb2.length());
+ LOGUNIT_ASSERT(cb2.get() == 0);
+ LOGUNIT_ASSERT_EQUAL(0, cb2.length());
+ }
+
+ void test1()
+ {
+ for (int bufSize = 1; bufSize <= 128; bufSize *= 2)
+ doTest1(bufSize);
+ }
+
+ void doTest1(int size)
+ {
+ //System.out.println("Doing test with size = "+size);
+ CyclicBuffer cb(size);
+
+ LOGUNIT_ASSERT_EQUAL(size, cb.getMaxSize());
+
+ int i;
+
+ for (i = -(size + 10); i < (size + 10); i++)
+ {
+ LOGUNIT_ASSERT(cb.get(i) == 0);
+ }
+
+ for (i = 0; i < MAX; i++)
+ {
+ cb.add(e[i]);
+
+ int limit = (i < (size - 1)) ? i : (size - 1);
+
+ //System.out.println("\nLimit is " + limit + ", i="+i);
+ for (int j = limit; j >= 0; j--)
+ {
+ //System.out.println("i= "+i+", j="+j);
+ LOGUNIT_ASSERT_EQUAL(e[i - (limit - j)], cb.get(j));
+ }
+
+ LOGUNIT_ASSERT(cb.get(-1) == 0);
+ LOGUNIT_ASSERT(cb.get(limit + 1) == 0);
+ }
+ }
+
+ void testResize()
+ {
+ for (int isize = 1; isize <= 128; isize *= 2)
+ {
+ doTestResize(isize, (isize / 2) + 1, (isize / 2) + 1);
+ doTestResize(isize, (isize / 2) + 1, isize + 10);
+ doTestResize(isize, isize + 10, (isize / 2) + 1);
+ doTestResize(isize, isize + 10, isize + 10);
+ }
+
+ }
+
+ void doTestResize(int initialSize, int numberOfAdds, int newSize)
+ {
+ //System.out.println("initialSize = "+initialSize+", numberOfAdds="
+ // +numberOfAdds+", newSize="+newSize);
+ CyclicBuffer cb(initialSize);
+
+ for (int i = 0; i < numberOfAdds; i++)
+ {
+ cb.add(e[i]);
+ }
+
+ cb.resize(newSize);
+
+ int offset = numberOfAdds - initialSize;
+
+ if (offset < 0)
+ {
+ offset = 0;
+ }
+
+ int len = (newSize < numberOfAdds) ? newSize : numberOfAdds;
+ len = (len < initialSize) ? len : initialSize;
+
+ //System.out.println("Len = "+len+", offset="+offset);
+ for (int j = 0; j < len; j++)
+ {
+ LOGUNIT_ASSERT_EQUAL(e[offset + j], cb.get(j));
+ }
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(CyclicBufferTestCase);
diff --git a/src/test/cpp/helpers/datetimedateformattestcase.cpp b/src/test/cpp/helpers/datetimedateformattestcase.cpp
new file mode 100644
index 0000000..e1183d5
--- /dev/null
+++ b/src/test/cpp/helpers/datetimedateformattestcase.cpp
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define __STDC_CONSTANT_MACROS
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/datetimedateformat.h>
+#include "../logunit.h"
+#include <log4cxx/helpers/pool.h>
+#include "../insertwide.h"
+#include <apr.h>
+#include <apr_time.h>
+#include <sstream>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace std;
+
+#define LOCALE_US "C"
+#if defined(_WIN32)
+#define LOCALE_FR "French_france"
+#else
+#define LOCALE_FR "fr_FR"
+#endif
+
+#define LOG4CXX_TEST 1
+#include <log4cxx/private/log4cxx_private.h>
+
+
+#if LOG4CXX_HAS_STD_LOCALE
+#include <locale>
+#include "localechanger.h"
+#define MAKE_LOCALE(ptr, id) \
+std::locale loco(id); \
+std::locale* ptr = &loco;
+#else
+#define MAKE_LOCALE(ptr, id) \
+std::locale* ptr = NULL;
+#endif
+
+
+/**
+ Unit test {@link DateTimeDateFormat}.
+
+
+*/
+LOGUNIT_CLASS(DateTimeDateFormatTestCase)
+{
+ LOGUNIT_TEST_SUITE( DateTimeDateFormatTestCase );
+ LOGUNIT_TEST( test1 );
+ LOGUNIT_TEST( test2 );
+ LOGUNIT_TEST( test3 );
+ LOGUNIT_TEST( test4 );
+ LOGUNIT_TEST( test5 );
+ LOGUNIT_TEST( test6 );
+#if LOG4CXX_HAS_STD_LOCALE
+ LOGUNIT_TEST( test7 );
+ LOGUNIT_TEST( test8 );
+#endif
+ LOGUNIT_TEST_SUITE_END();
+
+
+
+private:
+
+#define MICROSECONDS_PER_DAY APR_INT64_C(86400000000)
+
+
+ /**
+ Asserts that formatting the provided date results in the expected string.
+
+ @param date Date date
+ @param timeZone TimeZone timezone for conversion
+ @param expected String expected string
+ */
+ void assertFormattedTime( apr_time_t date, const std::locale* locale,
+ const TimeZonePtr& timeZone, const LogString& expected )
+ {
+ DateTimeDateFormat formatter(locale);
+ formatter.setTimeZone(timeZone);
+ LogString actual;
+ Pool p;
+ formatter.format(actual, date, p);
+ LOGUNIT_ASSERT_EQUAL( expected, actual );
+ }
+public:
+
+ /** Convert 02 Jan 2004 00:00:00 GMT for GMT. */
+ void test1()
+ {
+ //
+ // 02 Jan 2004 00:00 GMT
+ //
+ apr_time_t jan2 = MICROSECONDS_PER_DAY * 12419;
+ MAKE_LOCALE(localeUS, LOCALE_US);
+ assertFormattedTime( jan2, localeUS, TimeZone::getGMT(), LOG4CXX_STR("02 Jan 2004 00:00:00,000"));
+ }
+
+ /** Convert 03 Jan 2004 00:00:00 GMT for America/Chicago. */
+ void test2()
+ {
+ //
+ // 03 Jan 2004 00:00 GMT
+ apr_time_t jan3 = MICROSECONDS_PER_DAY * 12420;
+ MAKE_LOCALE(localeUS, LOCALE_US);
+ assertFormattedTime( jan3, localeUS,
+ TimeZone::getTimeZone(LOG4CXX_STR("GMT-6")),
+ LOG4CXX_STR("02 Jan 2004 18:00:00,000"));
+ }
+
+
+ /** Convert 30 Jun 2004 00:00:00 GMT for GMT. */
+ void test3()
+ {
+ apr_time_t jun30 = MICROSECONDS_PER_DAY * 12599;
+ MAKE_LOCALE(localeUS, LOCALE_US);
+ assertFormattedTime( jun30, localeUS, TimeZone::getGMT(),
+ LOG4CXX_STR("30 Jun 2004 00:00:00,000"));
+ }
+
+ /** Convert 29 Jun 2004 00:00:00 GMT for Chicago, daylight savings in effect. */
+ void test4()
+ {
+ apr_time_t jul1 = MICROSECONDS_PER_DAY * 12600;
+ MAKE_LOCALE(localeUS, LOCALE_US);
+ assertFormattedTime( jul1, localeUS,
+ TimeZone::getTimeZone(LOG4CXX_STR("GMT-5")),
+ LOG4CXX_STR("30 Jun 2004 19:00:00,000"));
+ }
+
+ /** Test multiple calls in close intervals. */
+ void test5()
+ {
+ // subsequent calls within one minute
+ // are optimized to reuse previous formatted value
+ // make a couple of nearly spaced calls
+ apr_time_t ticks = MICROSECONDS_PER_DAY * 12601;
+ MAKE_LOCALE(localeUS, LOCALE_US);
+ assertFormattedTime( ticks, localeUS, TimeZone::getGMT(),
+ LOG4CXX_STR("02 Jul 2004 00:00:00,000"));
+ assertFormattedTime( ticks + 8000, localeUS, TimeZone::getGMT(),
+ LOG4CXX_STR("02 Jul 2004 00:00:00,008"));
+ assertFormattedTime( ticks + 17000, localeUS, TimeZone::getGMT(),
+ LOG4CXX_STR("02 Jul 2004 00:00:00,017"));
+ assertFormattedTime( ticks + 237000, localeUS, TimeZone::getGMT(),
+ LOG4CXX_STR("02 Jul 2004 00:00:00,237"));
+ assertFormattedTime( ticks + 1415000, localeUS, TimeZone::getGMT(),
+ LOG4CXX_STR("02 Jul 2004 00:00:01,415"));
+ }
+
+ /** Check that caching does not disregard timezone. This test would fail for revision 1.4 of DateTimeDateFormat.java. */
+ void test6()
+ {
+ apr_time_t jul3 = MICROSECONDS_PER_DAY * 12602;
+ MAKE_LOCALE(localeUS, LOCALE_US);
+ assertFormattedTime( jul3, localeUS, TimeZone::getGMT(),
+ LOG4CXX_STR("03 Jul 2004 00:00:00,000"));
+ assertFormattedTime( jul3, localeUS,
+ TimeZone::getTimeZone(LOG4CXX_STR("GMT-5")),
+ LOG4CXX_STR("02 Jul 2004 19:00:00,000"));
+ assertFormattedTime( jul3, localeUS, TimeZone::getGMT(),
+ LOG4CXX_STR("03 Jul 2004 00:00:00,000"));
+ }
+
+#if LOG4CXX_HAS_STD_LOCALE
+ LogString formatDate(const std::locale& locale, const tm& date, const LogString& fmt) {
+ //
+ // output the using STL
+ //
+ std::basic_ostringstream<logchar> buffer;
+#if defined(_USEFAC)
+ _USEFAC(locale, std::time_put<logchar>)
+ .put(buffer, buffer, &date, fmt.c_str(), fmt.c_str() + fmt.length());
+#else
+#if defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE)
+ const std::time_put<logchar>& facet = std::use_facet(locale, (std::time_put<logchar>*) 0);
+#else
+ const std::time_put<logchar>& facet = std::use_facet<std::time_put<logchar> >(locale);
+#endif
+ facet.put(buffer, buffer, buffer.fill(), &date, fmt.c_str(), fmt.c_str() + fmt.length());
+#endif
+ return buffer.str();
+ }
+
+ /** Check that format is locale sensitive. */
+ void test7()
+ {
+ apr_time_t avr11 = MICROSECONDS_PER_DAY * 12519;
+ LocaleChanger localeChange(LOCALE_FR);
+ if (localeChange.isEffective()) {
+ LogString formatted;
+ Pool p;
+ SimpleDateFormat formatter(LOG4CXX_STR("MMM"));
+ formatter.format(formatted, avr11, p);
+
+ std::locale localeFR(LOCALE_FR);
+ struct tm avr11tm = { 0, 0, 0, 11, 03, 104 };
+ LogString expected(formatDate(localeFR, avr11tm, LOG4CXX_STR("%b")));
+
+ LOGUNIT_ASSERT_EQUAL(expected, formatted);
+ }
+ }
+
+ /** Check that format is locale sensitive. */
+ void test8()
+ {
+ apr_time_t apr11 = MICROSECONDS_PER_DAY * 12519;
+ LocaleChanger localeChange(LOCALE_US);
+ if (localeChange.isEffective()) {
+ LogString formatted;
+ Pool p;
+ SimpleDateFormat formatter(LOG4CXX_STR("MMM"));
+ formatter.setTimeZone(TimeZone::getGMT());
+ formatter.format(formatted, apr11, p);
+
+ std::locale localeUS(LOCALE_US);
+ struct tm apr11tm = { 0, 0, 0, 11, 03, 104 };
+ LogString expected(formatDate(localeUS, apr11tm, LOG4CXX_STR("%b")));
+
+ LOGUNIT_ASSERT_EQUAL(expected, formatted);
+ }
+ }
+#endif
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(DateTimeDateFormatTestCase);
+
diff --git a/src/test/cpp/helpers/inetaddresstestcase.cpp b/src/test/cpp/helpers/inetaddresstestcase.cpp
new file mode 100644
index 0000000..9077752
--- /dev/null
+++ b/src/test/cpp/helpers/inetaddresstestcase.cpp
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/inetaddress.h>
+#include "../logunit.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+LOGUNIT_CLASS(InetAddressTestCase)
+{
+ LOGUNIT_TEST_SUITE(InetAddressTestCase);
+ LOGUNIT_TEST(testGetLocalHost);
+ LOGUNIT_TEST(testByNameLocal);
+ LOGUNIT_TEST(testAllByNameLocal);
+ LOGUNIT_TEST(testUnreachable);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ /**
+ * Tests the InetAddress::getLocalHost() method.
+ */
+ void testGetLocalHost() {
+ InetAddressPtr addr = InetAddress::getLocalHost();
+
+ LOGUNIT_ASSERT(addr->getHostAddress() == LOG4CXX_STR("127.0.0.1"));
+ LOGUNIT_ASSERT(!addr->getHostName().empty());
+ }
+
+ /**
+ * Tests the InetAddress::getByName() method with the
+ * "localhost" host name.
+ */
+ void testByNameLocal() {
+ InetAddressPtr addr = InetAddress::getByName(LOG4CXX_STR("localhost"));
+
+ LOGUNIT_ASSERT(addr->getHostAddress() == LOG4CXX_STR("127.0.0.1"));
+ LOGUNIT_ASSERT(!addr->getHostName().empty());
+ }
+
+ /**
+ * Tests the InetAddress::getAllByName() method with the
+ * "localhost" host name.
+ */
+ void testAllByNameLocal() {
+ std::vector<InetAddressPtr> addr = InetAddress::getAllByName(LOG4CXX_STR("localhost"));
+
+ LOGUNIT_ASSERT(addr.size() > 0);
+ }
+
+ /**
+ * Tests the UnknownHostException.
+ */
+ void testUnknownHost() {
+ InetAddressPtr addr = InetAddress::getByName(LOG4CXX_STR("unknown.invalid"));
+ }
+
+ /**
+ * Tests an (likely) unreachable address.
+ */
+ void testUnreachable() {
+ InetAddressPtr addr(InetAddress::getByName(LOG4CXX_STR("192.168.10.254")));
+ LogString addrStr(addr->toString());
+ LOGUNIT_ASSERT_EQUAL(addrStr.size() - 15, addrStr.find(LOG4CXX_STR("/192.168.10.254")));
+ }
+
+};
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(InetAddressTestCase);
+
diff --git a/src/test/cpp/helpers/iso8601dateformattestcase.cpp b/src/test/cpp/helpers/iso8601dateformattestcase.cpp
new file mode 100644
index 0000000..7aa7247
--- /dev/null
+++ b/src/test/cpp/helpers/iso8601dateformattestcase.cpp
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/iso8601dateformat.h>
+#include "../logunit.h"
+#define LOG4CXX_TEST
+#include <log4cxx/private/log4cxx_private.h>
+#if LOG4CXX_HAS_STD_LOCALE
+#include <locale>
+#endif
+#include "../insertwide.h"
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/date.h>
+
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+/**
+ Unit test {@link ISO8601DateFormat}.
+
+ */
+LOGUNIT_CLASS(ISO8601DateFormatTestCase) {
+ LOGUNIT_TEST_SUITE( ISO8601DateFormatTestCase );
+ LOGUNIT_TEST( test1 );
+ LOGUNIT_TEST( test2 );
+ LOGUNIT_TEST( test3 );
+ LOGUNIT_TEST( test4 );
+ LOGUNIT_TEST( test5 );
+ LOGUNIT_TEST( test6 );
+ LOGUNIT_TEST( test7 );
+ LOGUNIT_TEST_SUITE_END();
+
+ /**
+ * Asserts that formatting the provided date results
+ * in the expected string.
+ *
+ * @param date Date date
+ * @param timeZone TimeZone timezone for conversion
+ * @param expected String expected string
+ */
+ void assertFormattedTime(log4cxx_time_t date,
+ const TimeZonePtr& timeZone,
+ const LogString& expected) {
+ ISO8601DateFormat formatter;
+ formatter.setTimeZone(timeZone);
+ LogString actual;
+ Pool p;
+ formatter.format(actual, date, p);
+ LOGUNIT_ASSERT_EQUAL(expected, actual);
+ }
+
+
+public:
+ /**
+ * Convert 02 Jan 2004 00:00:00 GMT for GMT.
+ */
+ void test1() {
+ log4cxx_time_t jan2 = Date::getMicrosecondsPerDay() * 12419;
+ assertFormattedTime(jan2, TimeZone::getGMT(),
+ LOG4CXX_STR("2004-01-02 00:00:00,000"));
+ }
+
+ /**
+ * Convert 03 Jan 2004 00:00:00 GMT for America/Chicago.
+ */
+ void test2() {
+ //
+ // 03 Jan 2004 00:00 GMT
+ // (asking for the same time at a different timezone
+ // will ignore the change of timezone)
+ log4cxx_time_t jan3 = Date::getMicrosecondsPerDay() * 12420;
+ assertFormattedTime(jan3, TimeZone::getTimeZone(LOG4CXX_STR("GMT-6")),
+ LOG4CXX_STR("2004-01-02 18:00:00,000"));
+ }
+
+
+ /**
+ * Convert 30 Jun 2004 00:00:00 GMT for GMT.
+ */
+ void test3() {
+ log4cxx_time_t jun30 = Date::getMicrosecondsPerDay() * 12599;
+ assertFormattedTime(jun30, TimeZone::getGMT(),
+ LOG4CXX_STR("2004-06-30 00:00:00,000"));
+ }
+
+ /**
+ * Convert 1 Jul 2004 00:00:00 GMT for Chicago, daylight savings in effect.
+ */
+ void test4() {
+ log4cxx_time_t jul1 = Date::getMicrosecondsPerDay() * 12600;
+ assertFormattedTime(jul1, TimeZone::getTimeZone(LOG4CXX_STR("GMT-5")),
+ LOG4CXX_STR("2004-06-30 19:00:00,000"));
+ }
+
+ /**
+ * Test multiple calls in close intervals.
+ */
+ void test5() {
+ // subsequent calls within one minute
+ // are optimized to reuse previous formatted value
+ // make a couple of nearly spaced calls
+ log4cxx_time_t ticks = Date::getMicrosecondsPerDay() * 12601;
+ assertFormattedTime(ticks, TimeZone::getGMT(),
+ LOG4CXX_STR("2004-07-02 00:00:00,000"));
+ assertFormattedTime(ticks + 8000, TimeZone::getGMT(),
+ LOG4CXX_STR("2004-07-02 00:00:00,008"));
+ assertFormattedTime(ticks + 17000, TimeZone::getGMT(),
+ LOG4CXX_STR("2004-07-02 00:00:00,017"));
+ assertFormattedTime(ticks + 237000, TimeZone::getGMT(),
+ LOG4CXX_STR("2004-07-02 00:00:00,237"));
+ assertFormattedTime(ticks + 1415000, TimeZone::getGMT(),
+ LOG4CXX_STR("2004-07-02 00:00:01,415"));
+ }
+
+ /**
+ * Check that caching does not disregard timezone.
+ * This test would fail for revision 1.4 of DateTimeDateFormat.java.
+ */
+ void test6() {
+ log4cxx_time_t jul3 = Date::getMicrosecondsPerDay() * 12602;
+ assertFormattedTime(jul3, TimeZone::getGMT(),
+ LOG4CXX_STR("2004-07-03 00:00:00,000"));
+ assertFormattedTime(jul3, TimeZone::getTimeZone(LOG4CXX_STR("GMT-5")),
+ LOG4CXX_STR("2004-07-02 19:00:00,000"));
+ assertFormattedTime(jul3, TimeZone::getGMT(),
+ LOG4CXX_STR("2004-07-03 00:00:00,000"));
+ }
+
+ /**
+ * Checks that numberFormat is implemented.
+ */
+ void test7() {
+ LogString number;
+ ISO8601DateFormat formatter;
+ Pool p;
+ formatter.numberFormat(number, 87, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("87"), number);
+ }
+
+
+
+};
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(ISO8601DateFormatTestCase);
diff --git a/src/test/cpp/helpers/localechanger.cpp b/src/test/cpp/helpers/localechanger.cpp
new file mode 100644
index 0000000..9c9b00b
--- /dev/null
+++ b/src/test/cpp/helpers/localechanger.cpp
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG4CXX_TEST
+#include <log4cxx/private/log4cxx_private.h>
+#if LOG4CXX_HAS_STD_LOCALE
+
+#include "localechanger.h"
+#include <stdexcept>
+
+using namespace log4cxx::helpers;
+
+/**
+* Construction attemtps to change default locale.
+* @param locale locale.
+*/
+LocaleChanger::LocaleChanger(const char* locale) {
+ effective = false;
+ try {
+ std::locale newLocale(locale);
+ initial = std::locale::global(newLocale);
+ effective = true;
+ } catch(std::runtime_error&) {
+ } catch(std::exception&) {
+ }
+ }
+
+/**
+* Restores previous locale.
+*/
+LocaleChanger::~LocaleChanger() {
+ if (effective) {
+ std::locale::global(initial);
+ }
+ }
+
+#endif
diff --git a/src/test/cpp/helpers/localechanger.h b/src/test/cpp/helpers/localechanger.h
new file mode 100644
index 0000000..ef902b9
--- /dev/null
+++ b/src/test/cpp/helpers/localechanger.h
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_HELPERS_LOCALE_CHANGER_H
+#define _LOG4CXX_HELPERS_LOCALE_CHANGER_H
+
+#include <locale>
+
+namespace log4cxx {
+ namespace helpers {
+ /**
+ * Utility class to change the locale for the duration of a test.
+ *
+ *
+ *
+ *
+ */
+ class LocaleChanger {
+ public:
+ /**
+ * Construction attemtps to change default locale.
+ * @param locale locale.
+ */
+ LocaleChanger(const char* locale);
+
+ /**
+ * Restores previous locale.
+ */
+ ~LocaleChanger();
+
+ /**
+ * Determines whether locale change was effective.
+ * @return true if effective.
+ */
+ inline bool isEffective() { return effective; }
+
+ private:
+ LocaleChanger(LocaleChanger&);
+ LocaleChanger& operator=(LocaleChanger&);
+ std::locale initial;
+ bool effective;
+ };
+ }
+}
+#endif
diff --git a/src/test/cpp/helpers/messagebuffertest.cpp b/src/test/cpp/helpers/messagebuffertest.cpp
new file mode 100644
index 0000000..ea2ed34
--- /dev/null
+++ b/src/test/cpp/helpers/messagebuffertest.cpp
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/messagebuffer.h>
+#include <iomanip>
+#include "../insertwide.h"
+#include "../logunit.h"
+#include <log4cxx/logstring.h>
+
+#if LOG4CXX_CFSTRING_API
+#include <CoreFoundation/CFString.h>
+#endif
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+/**
+ * Test MessageBuffer.
+ */
+LOGUNIT_CLASS(MessageBufferTest)
+{
+ LOGUNIT_TEST_SUITE(MessageBufferTest);
+ LOGUNIT_TEST(testInsertChar);
+ LOGUNIT_TEST(testInsertConstStr);
+ LOGUNIT_TEST(testInsertStr);
+ LOGUNIT_TEST(testInsertString);
+ LOGUNIT_TEST(testInsertNull);
+ LOGUNIT_TEST(testInsertInt);
+ LOGUNIT_TEST(testInsertManipulator);
+#if LOG4CXX_WCHAR_T_API
+ LOGUNIT_TEST(testInsertConstWStr);
+ LOGUNIT_TEST(testInsertWString);
+ LOGUNIT_TEST(testInsertWStr);
+#endif
+#if LOG4CXX_UNICHAR_API
+ LOGUNIT_TEST(testInsertConstUStr);
+ LOGUNIT_TEST(testInsertUString);
+#endif
+#if LOG4CXX_CFSTRING_API
+ LOGUNIT_TEST(testInsertCFString);
+#endif
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+ void testInsertChar() {
+ MessageBuffer buf;
+ std::string greeting("Hello, World");
+ CharMessageBuffer& retval = buf << "Hello, Worl" << 'd';
+ LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
+ LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
+ }
+
+ void testInsertConstStr() {
+ MessageBuffer buf;
+ std::string greeting("Hello, World");
+ CharMessageBuffer& retval = buf << "Hello" << ", World";
+ LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
+ LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
+ }
+
+ void testInsertStr() {
+ MessageBuffer buf;
+ std::string greeting("Hello, World");
+ char* part1 = (char*) malloc(10*sizeof(wchar_t));
+ strcpy(part1, "Hello");
+ char* part2 = (char*) malloc(10*sizeof(wchar_t));
+ strcpy(part2, ", World");
+ CharMessageBuffer& retval = buf << part1 << part2;
+ free(part1);
+ free(part2);
+ LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
+ LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
+ }
+
+ void testInsertString() {
+ MessageBuffer buf;
+ std::string greeting("Hello, World");
+ CharMessageBuffer& retval = buf << std::string("Hello") << std::string(", World");
+ LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
+ LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
+ }
+
+ void testInsertNull() {
+ MessageBuffer buf;
+ std::string greeting("Hello, null");
+ CharMessageBuffer& retval = buf << "Hello, " << (const char*) 0;
+ LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
+ LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
+ }
+
+ void testInsertInt() {
+ MessageBuffer buf;
+ std::string greeting("Hello, 5");
+ std::ostream& retval = buf << "Hello, " << 5;
+ LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
+ LOGUNIT_ASSERT_EQUAL(true, buf.hasStream());
+ }
+
+ void testInsertManipulator() {
+ MessageBuffer buf;
+ std::string greeting("pi=3.142");
+ std::ostream& retval = buf << "pi=" << std::setprecision(4) << 3.1415926;
+ LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
+ LOGUNIT_ASSERT_EQUAL(true, buf.hasStream());
+ }
+
+#if LOG4CXX_WCHAR_T_API
+ void testInsertConstWStr() {
+ MessageBuffer buf;
+ std::wstring greeting(L"Hello, World");
+ WideMessageBuffer& retval = buf << L"Hello" << L", World";
+ LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
+ LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
+ }
+
+ void testInsertWString() {
+ MessageBuffer buf;
+ std::wstring greeting(L"Hello, World");
+ WideMessageBuffer& retval = buf << std::wstring(L"Hello") << std::wstring(L", World");
+ LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
+ LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
+ }
+
+ void testInsertWStr() {
+ MessageBuffer buf;
+ std::wstring greeting(L"Hello, World");
+ wchar_t* part1 = (wchar_t*) malloc(10*sizeof(wchar_t));
+ wcscpy(part1, L"Hello");
+ wchar_t* part2 = (wchar_t*) malloc(10*sizeof(wchar_t));
+ wcscpy(part2, L", World");
+ WideMessageBuffer& retval = buf << part1 << part2;
+ free(part1);
+ free(part2);
+ LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
+ LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
+ }
+#endif
+
+#if LOG4CXX_UNICHAR_API
+ void testInsertConstUStr() {
+ MessageBuffer buf;
+ const log4cxx::UniChar hello[] = { 'H', 'e', 'l', 'l', 'o', 0 };
+ const log4cxx::UniChar world[] = { ',', ' ', 'W', 'o', 'r', 'l', 'd', 0 };
+ const log4cxx::UniChar greeting[] = { 'H', 'e', 'l', 'l', 'o',
+ ',', ' ', 'W', 'o', 'r', 'l', 'd', 0 };
+ UniCharMessageBuffer& retval = buf << hello << world;
+ LOGUNIT_ASSERT_EQUAL(std::basic_string<log4cxx::UniChar>(greeting), buf.str(retval));
+ LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
+ }
+
+ void testInsertUString() {
+ MessageBuffer buf;
+ const log4cxx::UniChar hello[] = { 'H', 'e', 'l', 'l', 'o', 0 };
+ const log4cxx::UniChar world[] = { ',', ' ', 'W', 'o', 'r', 'l', 'd', 0 };
+ const log4cxx::UniChar greeting[] = { 'H', 'e', 'l', 'l', 'o',
+ ',', ' ', 'W', 'o', 'r', 'l', 'd', 0 };
+ UniCharMessageBuffer& retval = buf << std::basic_string<log4cxx::UniChar>(hello)
+ << std::basic_string<log4cxx::UniChar>(world);
+ LOGUNIT_ASSERT_EQUAL(std::basic_string<log4cxx::UniChar>(greeting), buf.str(retval));
+ LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
+ }
+
+#endif
+
+#if LOG4CXX_CFSTRING_API
+ void testInsertCFString() {
+ MessageBuffer buf;
+ const log4cxx::UniChar greeting[] = { 'H', 'e', 'l', 'l', 'o',
+ ',', ' ', 'W', 'o', 'r', 'l', 'd', 0 };
+ UniCharMessageBuffer& retval = buf << CFSTR("Hello")
+ << CFSTR(", World");
+ LOGUNIT_ASSERT_EQUAL(std::basic_string<log4cxx::UniChar>(greeting), buf.str(retval));
+ LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
+ }
+
+#endif
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(MessageBufferTest);
+
diff --git a/src/test/cpp/helpers/optionconvertertestcase.cpp b/src/test/cpp/helpers/optionconvertertestcase.cpp
new file mode 100644
index 0000000..1cc3a82
--- /dev/null
+++ b/src/test/cpp/helpers/optionconvertertestcase.cpp
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/helpers/properties.h>
+#include <log4cxx/helpers/system.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/pool.h>
+#include "../testchar.h"
+#include "../insertwide.h"
+#include "../logunit.h"
+#include <stdlib.h>
+#include <apr_pools.h>
+#include <apr_file_io.h>
+#include <apr_user.h>
+#include <apr_env.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+#define MAX 1000
+
+LOGUNIT_CLASS(OptionConverterTestCase)
+{
+ LOGUNIT_TEST_SUITE(OptionConverterTestCase);
+ LOGUNIT_TEST(varSubstTest1);
+ LOGUNIT_TEST(varSubstTest2);
+ LOGUNIT_TEST(varSubstTest3);
+ LOGUNIT_TEST(varSubstTest4);
+ LOGUNIT_TEST(varSubstTest5);
+ LOGUNIT_TEST(testTmpDir);
+#if APR_HAS_USER
+ LOGUNIT_TEST(testUserHome);
+ LOGUNIT_TEST(testUserName);
+#endif
+ LOGUNIT_TEST(testUserDir);
+ LOGUNIT_TEST_SUITE_END();
+
+ Properties props;
+ Properties nullProperties;
+
+public:
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ /**
+ * Checks that environment variables were properly set
+ * before invoking tests. ::putenv not reliable.
+ */
+ void envCheck() {
+ Pool p;
+ char* toto;
+ apr_status_t stat = apr_env_get(&toto, "TOTO",
+ p.getAPRPool());
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT_EQUAL("wonderful", toto);
+ char* key1;
+ stat = apr_env_get(&key1, "key1",
+ p.getAPRPool());
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT_EQUAL("value1", key1);
+ char* key2;
+ stat = apr_env_get(&key2, "key2",
+ p.getAPRPool());
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LOGUNIT_ASSERT_EQUAL("value2", key2);
+ }
+
+ void varSubstTest1()
+ {
+ envCheck();
+ LogString r(OptionConverter::substVars(LOG4CXX_STR("hello world."), nullProperties));
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("hello world."), r);
+
+ r = OptionConverter::substVars(LOG4CXX_STR("hello ${TOTO} world."), nullProperties);
+
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("hello wonderful world."), r);
+ }
+
+
+ void varSubstTest2()
+ {
+ envCheck();
+ LogString r(OptionConverter::substVars(LOG4CXX_STR("Test2 ${key1} mid ${key2} end."),
+ nullProperties));
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("Test2 value1 mid value2 end."), r);
+ }
+
+
+ void varSubstTest3()
+ {
+ envCheck();
+ LogString r(OptionConverter::substVars(
+ LOG4CXX_STR("Test3 ${unset} mid ${key1} end."), nullProperties));
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("Test3 mid value1 end."), r);
+ }
+
+
+ void varSubstTest4()
+ {
+ LogString res;
+ LogString val(LOG4CXX_STR("Test4 ${incomplete "));
+ try
+ {
+ res = OptionConverter::substVars(val, nullProperties);
+ }
+ catch(IllegalArgumentException& e)
+ {
+ std::string witness("\"Test4 ${incomplete \" has no closing brace. Opening brace at position 6.");
+ LOGUNIT_ASSERT_EQUAL(witness, (std::string) e.what());
+ }
+ }
+
+
+ void varSubstTest5()
+ {
+ Properties props1;
+ props1.setProperty(LOG4CXX_STR("p1"), LOG4CXX_STR("x1"));
+ props1.setProperty(LOG4CXX_STR("p2"), LOG4CXX_STR("${p1}"));
+ LogString res = OptionConverter::substVars(LOG4CXX_STR("${p2}"), props1);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("x1"), res);
+ }
+
+ void testTmpDir()
+ {
+ LogString actual(OptionConverter::substVars(
+ LOG4CXX_STR("${java.io.tmpdir}"), nullProperties));
+ Pool p;
+ const char* tmpdir = NULL;
+ apr_status_t stat = apr_temp_dir_get(&tmpdir, p.getAPRPool());
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+ LogString expected;
+ Transcoder::decode(tmpdir, expected);
+
+ LOGUNIT_ASSERT_EQUAL(expected, actual);
+ }
+
+#if APR_HAS_USER
+ void testUserHome() {
+ LogString actual(OptionConverter::substVars(
+ LOG4CXX_STR("${user.home}"), nullProperties));
+ Pool p;
+
+ apr_uid_t userid;
+ apr_gid_t groupid;
+ apr_status_t stat = apr_uid_current(&userid, &groupid, p.getAPRPool());
+ if (stat == APR_SUCCESS) {
+ char* username = NULL;
+ stat = apr_uid_name_get(&username, userid, p.getAPRPool());
+ if (stat == APR_SUCCESS) {
+ char* dirname = NULL;
+ stat = apr_uid_homepath_get(&dirname, username, p.getAPRPool());
+ if (stat == APR_SUCCESS) {
+ LogString expected;
+ Transcoder::decode(dirname, expected);
+ LOGUNIT_ASSERT_EQUAL(expected, actual);
+ }
+ }
+ }
+
+ }
+
+ void testUserName() {
+ LogString actual(OptionConverter::substVars(
+ LOG4CXX_STR("${user.name}"), nullProperties));
+ Pool p;
+ apr_uid_t userid;
+ apr_gid_t groupid;
+ apr_status_t stat = apr_uid_current(&userid, &groupid, p.getAPRPool());
+ if (stat == APR_SUCCESS) {
+ char* username = NULL;
+ stat = apr_uid_name_get(&username, userid, p.getAPRPool());
+ if (stat == APR_SUCCESS) {
+ LogString expected;
+ Transcoder::decode(username, expected);
+ LOGUNIT_ASSERT_EQUAL(expected, actual);
+ }
+ }
+ }
+#endif
+
+ void testUserDir() {
+ LogString actual(OptionConverter::substVars(
+ LOG4CXX_STR("${user.dir}"), nullProperties));
+ Pool p;
+
+ char* dirname = NULL;
+ apr_status_t stat = apr_filepath_get(&dirname, APR_FILEPATH_NATIVE, p.getAPRPool());
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+
+ LogString expected;
+ Transcoder::decode(dirname, expected);
+
+ LOGUNIT_ASSERT_EQUAL(expected, actual);
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(OptionConverterTestCase);
diff --git a/src/test/cpp/helpers/propertiestestcase.cpp b/src/test/cpp/helpers/propertiestestcase.cpp
new file mode 100644
index 0000000..7a288d3
--- /dev/null
+++ b/src/test/cpp/helpers/propertiestestcase.cpp
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/properties.h>
+#include <log4cxx/helpers/fileinputstream.h>
+#include "../insertwide.h"
+#include "../logunit.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+LOGUNIT_CLASS(PropertiesTestCase)
+{
+ LOGUNIT_TEST_SUITE(PropertiesTestCase);
+ LOGUNIT_TEST(testLoad1);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ void testLoad1() {
+ //
+ // read patternLayout1.properties
+ FileInputStreamPtr propFile =
+ new FileInputStream(LOG4CXX_STR("input/patternLayout1.properties"));
+ Properties properties;
+ properties.load(propFile);
+ LogString pattern(properties.getProperty(LOG4CXX_STR("log4j.appender.testAppender.layout.ConversionPattern")));
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("%-5p - %m%n"), pattern);
+ }
+};
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(PropertiesTestCase);
diff --git a/src/test/cpp/helpers/relativetimedateformattestcase.cpp b/src/test/cpp/helpers/relativetimedateformattestcase.cpp
new file mode 100644
index 0000000..88d4351
--- /dev/null
+++ b/src/test/cpp/helpers/relativetimedateformattestcase.cpp
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/relativetimedateformat.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include "../insertwide.h"
+#include "../logunit.h"
+#include <log4cxx/helpers/date.h>
+
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+
+/**
+ Unit test {@link RelativeTimeDateFormat} class.
+
+ */
+LOGUNIT_CLASS(RelativeTimeDateFormatTestCase) {
+ LOGUNIT_TEST_SUITE(RelativeTimeDateFormatTestCase);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST(test3);
+ LOGUNIT_TEST_SUITE_END();
+
+
+ public:
+
+ /**
+ * Convert 2 Jan 2004
+ */
+ void test1() {
+ log4cxx_time_t jan2 = Date::getMicrosecondsPerDay() * 12419;
+ log4cxx_time_t preStartTime = LoggingEvent::getStartTime();
+
+ RelativeTimeDateFormat formatter;
+
+ Pool p;
+
+ LogString actual;
+
+ formatter.format(actual, jan2, p);
+
+ log4cxx_time_t elapsed = log4cxx::helpers::StringHelper::toInt64(actual);
+
+
+ LOGUNIT_ASSERT(preStartTime + elapsed*1000 > jan2 - 2000);
+ LOGUNIT_ASSERT(preStartTime + elapsed*1000 < jan2 + 2000);
+ }
+
+
+ /**
+ * Checks that numberFormat works as expected.
+ */
+ void test2() {
+ LogString numb;
+ Pool p;
+ RelativeTimeDateFormat formatter;
+ formatter.numberFormat(numb, 87, p);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("87"), numb);
+ }
+
+
+ /**
+ * Checks that setting timezone doesn't throw an exception.
+ */
+ void test3() {
+ RelativeTimeDateFormat formatter;
+ formatter.setTimeZone(TimeZone::getGMT());
+ }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(RelativeTimeDateFormatTestCase);
+
diff --git a/src/test/cpp/helpers/stringhelpertestcase.cpp b/src/test/cpp/helpers/stringhelpertestcase.cpp
new file mode 100644
index 0000000..1085265
--- /dev/null
+++ b/src/test/cpp/helpers/stringhelpertestcase.cpp
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include "../insertwide.h"
+#include "../logunit.h"
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+/**
+ Unit test for StringHelper.
+
+
+*/
+LOGUNIT_CLASS(StringHelperTestCase)
+ {
+ LOGUNIT_TEST_SUITE( StringHelperTestCase );
+ LOGUNIT_TEST( testStartsWith1 );
+ LOGUNIT_TEST( testStartsWith2 );
+ LOGUNIT_TEST( testStartsWith3 );
+ LOGUNIT_TEST( testStartsWith4 );
+ LOGUNIT_TEST( testStartsWith5 );
+ LOGUNIT_TEST( testEndsWith1 );
+ LOGUNIT_TEST( testEndsWith2 );
+ LOGUNIT_TEST( testEndsWith3 );
+ LOGUNIT_TEST( testEndsWith4 );
+ LOGUNIT_TEST( testEndsWith5 );
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+
+ /**
+ * Check that startsWith("foobar", "foo") returns true.
+ */
+ void testStartsWith1() {
+ LOGUNIT_ASSERT_EQUAL(true, StringHelper::startsWith(LOG4CXX_STR("foobar"), LOG4CXX_STR("foo")));
+ }
+
+ /**
+ * Check that startsWith("bar", "foobar") returns false.
+ */
+ void testStartsWith2() {
+ LOGUNIT_ASSERT_EQUAL(false, StringHelper::startsWith(LOG4CXX_STR("foo"), LOG4CXX_STR("foobar")));
+ }
+
+ /**
+ * Check that startsWith("foobar", "foobar") returns true.
+ */
+ void testStartsWith3() {
+ LOGUNIT_ASSERT_EQUAL(true, StringHelper::startsWith(LOG4CXX_STR("foobar"), LOG4CXX_STR("foobar")));
+ }
+
+ /**
+ * Check that startsWith("foobar", "") returns true.
+ */
+ void testStartsWith4() {
+ LOGUNIT_ASSERT_EQUAL(true, StringHelper::startsWith(LOG4CXX_STR("foobar"), LOG4CXX_STR("")));
+ }
+
+ /**
+ * Check that startsWith("foobar", "abc") returns false.
+ */
+ void testStartsWith5() {
+ LOGUNIT_ASSERT_EQUAL(false, StringHelper::startsWith(LOG4CXX_STR("foobar"), LOG4CXX_STR("abc")));
+ }
+
+
+
+ /**
+ * Check that endsWith("foobar", "bar") returns true.
+ */
+ void testEndsWith1() {
+ LOGUNIT_ASSERT_EQUAL(true, StringHelper::endsWith(LOG4CXX_STR("foobar"), LOG4CXX_STR("bar")));
+ }
+
+ /**
+ * Check that endsWith("bar", "foobar") returns false.
+ */
+ void testEndsWith2() {
+ LOGUNIT_ASSERT_EQUAL(false, StringHelper::endsWith(LOG4CXX_STR("bar"), LOG4CXX_STR("foobar")));
+ }
+
+ /**
+ * Check that endsWith("foobar", "foobar") returns true.
+ */
+ void testEndsWith3() {
+ LOGUNIT_ASSERT_EQUAL(true, StringHelper::endsWith(LOG4CXX_STR("foobar"), LOG4CXX_STR("foobar")));
+ }
+
+ /**
+ * Check that endsWith("foobar", "") returns true.
+ */
+ void testEndsWith4() {
+ LOGUNIT_ASSERT_EQUAL(true, StringHelper::endsWith(LOG4CXX_STR("foobar"), LOG4CXX_STR("")));
+ }
+
+ /**
+ * Check that endsWith("foobar", "abc") returns false.
+ */
+ void testEndsWith5() {
+ LOGUNIT_ASSERT_EQUAL(false, StringHelper::startsWith(LOG4CXX_STR("foobar"), LOG4CXX_STR("abc")));
+ }
+
+
+};
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(StringHelperTestCase);
diff --git a/src/test/cpp/helpers/stringtokenizertestcase.cpp b/src/test/cpp/helpers/stringtokenizertestcase.cpp
new file mode 100644
index 0000000..85043e5
--- /dev/null
+++ b/src/test/cpp/helpers/stringtokenizertestcase.cpp
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/stringtokenizer.h>
+#include "../logunit.h"
+#include "../insertwide.h"
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+LOGUNIT_CLASS(StringTokenizerTestCase)
+{
+ LOGUNIT_TEST_SUITE(StringTokenizerTestCase);
+ LOGUNIT_TEST(testNextTokenEmptyString);
+ LOGUNIT_TEST(testHasMoreTokensEmptyString);
+ LOGUNIT_TEST(testNextTokenAllDelim);
+ LOGUNIT_TEST(testHasMoreTokensAllDelim);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST(test3);
+ LOGUNIT_TEST(test4);
+ LOGUNIT_TEST(test5);
+ LOGUNIT_TEST(test6);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ void testNextTokenEmptyString() {
+ LogString src;
+ LogString delim(LOG4CXX_STR(" "));
+ StringTokenizer tokenizer(src, delim);
+ try {
+ LogString token(tokenizer.nextToken());
+ } catch (NoSuchElementException &ex) {
+ return;
+ }
+ LOGUNIT_ASSERT(false);
+ }
+
+ void testHasMoreTokensEmptyString() {
+ LogString src;
+ LogString delim(LOG4CXX_STR(" "));
+ StringTokenizer tokenizer(src, delim);
+ LOGUNIT_ASSERT_EQUAL(false, tokenizer.hasMoreTokens());
+ }
+
+ void testNextTokenAllDelim() {
+ LogString src(LOG4CXX_STR("==="));
+ LogString delim(LOG4CXX_STR("="));
+ StringTokenizer tokenizer(src, delim);
+ try {
+ LogString token(tokenizer.nextToken());
+ } catch (NoSuchElementException &ex) {
+ return;
+ }
+ LOGUNIT_ASSERT(false);
+ }
+
+ void testHasMoreTokensAllDelim() {
+ LogString src(LOG4CXX_STR("==="));
+ LogString delim(LOG4CXX_STR("="));
+ StringTokenizer tokenizer(src, delim);
+ LOGUNIT_ASSERT_EQUAL(false, tokenizer.hasMoreTokens());
+ }
+
+ void testBody(const LogString& src, const LogString& delim) {
+ StringTokenizer tokenizer(src, delim);
+ LOGUNIT_ASSERT_EQUAL(true, tokenizer.hasMoreTokens());
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("log4j"), tokenizer.nextToken());
+ LOGUNIT_ASSERT_EQUAL(true, tokenizer.hasMoreTokens());
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("properties"), tokenizer.nextToken());
+ LOGUNIT_ASSERT_EQUAL(true, tokenizer.hasMoreTokens());
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("txt"), tokenizer.nextToken());
+ LOGUNIT_ASSERT_EQUAL(false, tokenizer.hasMoreTokens());
+ try {
+ LogString token(tokenizer.nextToken());
+ } catch (NoSuchElementException& ex) {
+ return;
+ }
+ LOGUNIT_ASSERT(false);
+ }
+
+ void test1() {
+ LogString src(LOG4CXX_STR("log4j.properties.txt"));
+ LogString delim(LOG4CXX_STR("."));
+ testBody(src, delim);
+ }
+
+ void test2() {
+ LogString src(LOG4CXX_STR(".log4j.properties.txt"));
+ LogString delim(LOG4CXX_STR("."));
+ testBody(src, delim);
+ }
+
+ void test3() {
+ LogString src(LOG4CXX_STR("log4j.properties.txt."));
+ LogString delim(LOG4CXX_STR("."));
+ testBody(src, delim);
+ }
+
+ void test4() {
+ LogString src(LOG4CXX_STR("log4j..properties....txt"));
+ LogString delim(LOG4CXX_STR("."));
+ testBody(src, delim);
+ }
+
+ void test5() {
+ LogString src(LOG4CXX_STR("log4j properties,txt"));
+ LogString delim(LOG4CXX_STR(" ,"));
+ testBody(src, delim);
+ }
+
+ void test6() {
+ LogString src(LOG4CXX_STR(" log4j properties,txt "));
+ LogString delim(LOG4CXX_STR(" ,"));
+ testBody(src, delim);
+ }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(StringTokenizerTestCase);
diff --git a/src/test/cpp/helpers/syslogwritertest.cpp b/src/test/cpp/helpers/syslogwritertest.cpp
new file mode 100644
index 0000000..b5961f9
--- /dev/null
+++ b/src/test/cpp/helpers/syslogwritertest.cpp
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "../logunit.h"
+#include <log4cxx/helpers/syslogwriter.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+LOGUNIT_CLASS(SyslogWriterTest)
+{
+ LOGUNIT_TEST_SUITE(SyslogWriterTest);
+ LOGUNIT_TEST(testUnknownHost);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ /**
+ * Tests writing to an unknown host.
+ */
+ void testUnknownHost() {
+ SyslogWriter writer(LOG4CXX_STR("unknown.invalid"));
+ writer.write(LOG4CXX_STR("Hello, Unknown World."));
+ }
+
+};
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(SyslogWriterTest);
+
diff --git a/src/test/cpp/helpers/timezonetestcase.cpp b/src/test/cpp/helpers/timezonetestcase.cpp
new file mode 100644
index 0000000..4883c27
--- /dev/null
+++ b/src/test/cpp/helpers/timezonetestcase.cpp
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+#include <log4cxx/helpers/timezone.h>
+#include "../insertwide.h"
+#include "../logunit.h"
+#include <apr_time.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+//Define INT64_C for compilers that don't have it
+#if (!defined(INT64_C))
+#define INT64_C(value) value ## LL
+#endif
+
+
+/**
+ Unit test {@link TimeZone}.
+
+ */
+LOGUNIT_CLASS(TimeZoneTestCase) {
+ LOGUNIT_TEST_SUITE(TimeZoneTestCase);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+#if !defined(__BORLANDC__)
+ LOGUNIT_TEST(test3);
+#endif
+ LOGUNIT_TEST(test4);
+ LOGUNIT_TEST(test5);
+ LOGUNIT_TEST(test6);
+ LOGUNIT_TEST_SUITE_END();
+
+#define MICROSECONDS_PER_DAY APR_INT64_C(86400000000)
+
+
+ public:
+ /**
+ * Checks the GMT timezone
+ */
+ void test1() {
+ TimeZonePtr tz(TimeZone::getGMT());
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("GMT"), tz->getID());
+ }
+
+ /**
+ * Get "GMT-6" time zone
+ */
+ void test2() {
+ TimeZonePtr tz(TimeZone::getTimeZone(LOG4CXX_STR("GMT-6")));
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("GMT-06:00"), tz->getID());
+
+ apr_time_t jan2 = MICROSECONDS_PER_DAY * 12420;
+ apr_time_exp_t exploded;
+ tz->explode(&exploded, jan2);
+ LOGUNIT_ASSERT_EQUAL(-6 * 3600, exploded.tm_gmtoff);
+ LOGUNIT_ASSERT_EQUAL(18, exploded.tm_hour);
+ }
+
+ /**
+ * Get the default timezone name
+ */
+ void test3() {
+ TimeZonePtr tz(TimeZone::getDefault());
+ LogString tzName(tz->getID());
+ LOGUNIT_ASSERT(tzName.length() > 0);
+ }
+
+
+/**
+ * Get "GMT+0010" time zone
+ */
+void test4() {
+ TimeZonePtr tz(TimeZone::getTimeZone(LOG4CXX_STR("GMT+0010")));
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("GMT+00:10"), tz->getID());
+
+ apr_time_t jan2 = MICROSECONDS_PER_DAY * 12420;
+ apr_time_exp_t exploded;
+ tz->explode(&exploded, jan2);
+ LOGUNIT_ASSERT_EQUAL(600, exploded.tm_gmtoff);
+ LOGUNIT_ASSERT_EQUAL(0, exploded.tm_hour);
+ LOGUNIT_ASSERT_EQUAL(10, exploded.tm_min);
+}
+
+
+/**
+ * Get "GMT+6" time zone
+ */
+void test5() {
+ TimeZonePtr tz(TimeZone::getTimeZone(LOG4CXX_STR("GMT+6")));
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("GMT+06:00"), tz->getID());
+
+ apr_time_t jan2 = MICROSECONDS_PER_DAY * 12420;
+ apr_time_exp_t exploded;
+ tz->explode(&exploded, jan2);
+ LOGUNIT_ASSERT_EQUAL(6 * 3600, exploded.tm_gmtoff);
+ LOGUNIT_ASSERT_EQUAL(6, exploded.tm_hour);
+}
+
+/**
+ * Checks the GMT timezone
+ */
+void test6() {
+ TimeZonePtr tz(TimeZone::getTimeZone(LOG4CXX_STR("GMT")));
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("GMT"), tz->getID());
+}
+
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(TimeZoneTestCase);
+
diff --git a/src/test/cpp/helpers/transcodertestcase.cpp b/src/test/cpp/helpers/transcodertestcase.cpp
new file mode 100644
index 0000000..9711317
--- /dev/null
+++ b/src/test/cpp/helpers/transcodertestcase.cpp
@@ -0,0 +1,309 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/transcoder.h>
+#include "../insertwide.h"
+#include "../logunit.h"
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+LOGUNIT_CLASS(TranscoderTestCase)
+{
+ LOGUNIT_TEST_SUITE(TranscoderTestCase);
+ LOGUNIT_TEST(decode1);
+#if LOG4CXX_WCHAR_T_API
+ LOGUNIT_TEST(decode2);
+#endif
+ LOGUNIT_TEST(decode3);
+#if LOG4CXX_WCHAR_T_API
+ LOGUNIT_TEST(decode4);
+#endif
+ LOGUNIT_TEST(decode7);
+ LOGUNIT_TEST(decode8);
+#if LOG4CXX_WCHAR_T_API
+ LOGUNIT_TEST(encode1);
+#endif
+ LOGUNIT_TEST(encode2);
+#if LOG4CXX_WCHAR_T_API
+ LOGUNIT_TEST(encode3);
+#endif
+ LOGUNIT_TEST(encode4);
+#if LOG4CXX_WCHAR_T_API
+ LOGUNIT_TEST(encode5);
+#endif
+ LOGUNIT_TEST(encode6);
+ LOGUNIT_TEST(testDecodeUTF8_1);
+ LOGUNIT_TEST(testDecodeUTF8_2);
+ LOGUNIT_TEST(testDecodeUTF8_3);
+ LOGUNIT_TEST(testDecodeUTF8_4);
+#if LOG4CXX_UNICHAR_API
+ LOGUNIT_TEST(udecode2);
+ LOGUNIT_TEST(udecode4);
+ LOGUNIT_TEST(uencode1);
+ LOGUNIT_TEST(uencode3);
+ LOGUNIT_TEST(uencode5);
+#endif
+
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+ void decode1() {
+ const char* greeting = "Hello, World";
+ LogString decoded(LOG4CXX_STR("foo\n"));
+ Transcoder::decode(greeting, decoded);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("foo\nHello, World"), decoded);
+ }
+
+#if LOG4CXX_WCHAR_T_API
+ void decode2() {
+ const wchar_t* greeting = L"Hello, World";
+ LogString decoded(LOG4CXX_STR("foo\n"));
+ Transcoder::decode(greeting, decoded);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("foo\nHello, World"), decoded);
+ }
+#endif
+
+ void decode3() {
+ const char* nothing = "";
+ LogString decoded(LOG4CXX_STR("foo\n"));
+ Transcoder::decode(nothing, decoded);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("foo\n"), decoded);
+ }
+
+#if LOG4CXX_WCHAR_T_API
+ void decode4() {
+ const wchar_t* nothing = L"";
+ LogString decoded(LOG4CXX_STR("foo\n"));
+ Transcoder::decode(nothing, decoded);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("foo\n"), decoded);
+ }
+#endif
+
+
+ enum { BUFSIZE = 255 };
+
+ void decode7() {
+ //
+ // normal characters striding over a buffer boundary
+ //
+ std::string longMsg(BUFSIZE - 2, 'A');
+ longMsg.append("Hello");
+ LogString decoded;
+ Transcoder::decode(longMsg, decoded);
+ LOGUNIT_ASSERT_EQUAL((size_t) BUFSIZE + 3, decoded.length());
+ LOGUNIT_ASSERT_EQUAL(LogString(BUFSIZE -2, LOG4CXX_STR('A')),
+ decoded.substr(0, BUFSIZE - 2));
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("Hello"),
+ decoded.substr(BUFSIZE -2 ));
+ }
+
+ void decode8() {
+ std::string msg("Hello, World.");
+ LogString actual;
+ Transcoder::decode(msg, actual);
+ LogString expected(LOG4CXX_STR("Hello, World."));
+ LOGUNIT_ASSERT_EQUAL(expected, actual);
+ }
+
+
+#if LOG4CXX_WCHAR_T_API
+ void encode1() {
+ const LogString greeting(LOG4CXX_STR("Hello, World"));
+ std::wstring encoded;
+ Transcoder::encode(greeting, encoded);
+ LOGUNIT_ASSERT_EQUAL((std::wstring) L"Hello, World", encoded);
+ }
+#endif
+
+ void encode2() {
+ const LogString greeting(LOG4CXX_STR("Hello, World"));
+ std::string encoded;
+ Transcoder::encode(greeting, encoded);
+ LOGUNIT_ASSERT_EQUAL((std::string) "Hello, World", encoded);
+ }
+
+#if LOG4CXX_WCHAR_T_API
+ void encode3() {
+ LogString greeting(BUFSIZE - 3, LOG4CXX_STR('A'));
+ greeting.append(LOG4CXX_STR("Hello"));
+ std::wstring encoded;
+ Transcoder::encode(greeting, encoded);
+ std::wstring manyAs(BUFSIZE - 3, L'A');
+ LOGUNIT_ASSERT_EQUAL(manyAs, encoded.substr(0, BUFSIZE - 3));
+ LOGUNIT_ASSERT_EQUAL(std::wstring(L"Hello"), encoded.substr(BUFSIZE - 3));
+ }
+#endif
+
+ void encode4() {
+ LogString greeting(BUFSIZE - 3, LOG4CXX_STR('A'));
+ greeting.append(LOG4CXX_STR("Hello"));
+ std::string encoded;
+ Transcoder::encode(greeting, encoded);
+ std::string manyAs(BUFSIZE - 3, 'A');
+ LOGUNIT_ASSERT_EQUAL(manyAs, encoded.substr(0, BUFSIZE - 3));
+ LOGUNIT_ASSERT_EQUAL(std::string("Hello"), encoded.substr(BUFSIZE - 3));
+ }
+
+#if LOG4CXX_WCHAR_T_API
+ void encode5() {
+ // arbitrary, hopefully meaningless, characters from
+ // Latin, Arabic, Armenian, Bengali, CJK and Cyrillic
+ const wchar_t greeting[] = { L'A', 0x0605, 0x0530, 0x984, 0x40E3, 0x400, 0 };
+ //
+ // decode to LogString (UTF-16 or UTF-8)
+ //
+ LogString decoded;
+ Transcoder::decode(greeting, decoded);
+ //
+ // decode to wstring
+ //
+ std::wstring encoded;
+ Transcoder::encode(decoded, encoded);
+ //
+ // should be lossless
+ //
+ LOGUNIT_ASSERT_EQUAL((std::wstring) greeting, encoded);
+ }
+#endif
+
+ void encode6() {
+#if LOG4CXX_LOGCHAR_IS_WCHAR || LOG4CXX_LOGCHAR_IS_UNICHAR
+ // arbitrary, hopefully meaningless, characters from
+ // Latin, Arabic, Armenian, Bengali, CJK and Cyrillic
+ const logchar greeting[] = { L'A', 0x0605, 0x0530, 0x984, 0x40E3, 0x400, 0 };
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ const char greeting[] = { 'A',
+ (char) 0xD8, (char) 0x85,
+ (char) 0xD4, (char) 0xB0,
+ (char) 0xE0, (char) 0xCC, (char) 0x84,
+ (char) 0xE8, (char) 0x87, (char) 0x83,
+ (char) 0xD0, (char) 0x80,
+ 0 };
+#endif
+
+ //
+ // decode to LogString (UTF-16 or UTF-8)
+ //
+ LogString decoded;
+ Transcoder::decode(greeting, decoded);
+ //
+ // decode to wstring
+ //
+ std::string encoded;
+ //
+ // likely 'A\u0605\u0530\u0984\u40E3\u0400'
+ //
+ Transcoder::encode(decoded, encoded);
+ }
+
+ void testDecodeUTF8_1() {
+ std::string src("a");
+ LogString out;
+ Transcoder::decodeUTF8(src, out);
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("a")), out);
+ }
+
+ void testDecodeUTF8_2() {
+ std::string src(1, 0x80);
+ LogString out;
+ Transcoder::decodeUTF8(src, out);
+ LOGUNIT_ASSERT_EQUAL(LogString(1, Transcoder::LOSSCHAR), out);
+ }
+
+ void testDecodeUTF8_3() {
+ std::string src("\xC2");
+ LogString out;
+ Transcoder::decodeUTF8(src, out);
+ LOGUNIT_ASSERT_EQUAL(LogString(1, Transcoder::LOSSCHAR), out);
+ }
+
+ void testDecodeUTF8_4() {
+ std::string src("\xC2\xA9");
+ LogString out;
+ Transcoder::decodeUTF8(src, out);
+ LogString::const_iterator iter = out.begin();
+ unsigned int sv = Transcoder::decode(out, iter);
+ LOGUNIT_ASSERT_EQUAL((unsigned int) 0xA9, sv);
+ LOGUNIT_ASSERT_EQUAL(true, iter == out.end());
+ }
+
+
+#if LOG4CXX_UNICHAR_API
+ void udecode2() {
+ const UniChar greeting[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', 0 };
+ LogString decoded(LOG4CXX_STR("foo\n"));
+ Transcoder::decode(greeting, decoded);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("foo\nHello, World"), decoded);
+ }
+
+ void udecode4() {
+ const UniChar nothing[] = { 0 };
+ LogString decoded(LOG4CXX_STR("foo\n"));
+ Transcoder::decode(nothing, decoded);
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("foo\n"), decoded);
+ }
+
+ void uencode1() {
+ const LogString greeting(LOG4CXX_STR("Hello, World"));
+ std::basic_string<UniChar> encoded;
+ Transcoder::encode(greeting, encoded);
+ const UniChar expected[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', 0 };
+ LOGUNIT_ASSERT_EQUAL(std::basic_string<UniChar>(expected), encoded);
+ }
+
+ void uencode3() {
+ LogString greeting(BUFSIZE - 3, LOG4CXX_STR('A'));
+ greeting.append(LOG4CXX_STR("Hello"));
+ std::basic_string<UniChar> encoded;
+ Transcoder::encode(greeting, encoded);
+ std::basic_string<UniChar> manyAs(BUFSIZE - 3, 'A');
+ LOGUNIT_ASSERT_EQUAL(manyAs, encoded.substr(0, BUFSIZE - 3));
+ const UniChar hello[] = { 'H', 'e', 'l', 'l', 'o', 0 };
+ LOGUNIT_ASSERT_EQUAL(std::basic_string<UniChar>(hello), encoded.substr(BUFSIZE - 3));
+ }
+
+ void uencode5() {
+ // arbitrary, hopefully meaningless, characters from
+ // Latin, Arabic, Armenian, Bengali, CJK and Cyrillic
+ const UniChar greeting[] = { L'A', 0x0605, 0x0530, 0x984, 0x40E3, 0x400, 0 };
+ //
+ // decode to LogString (UTF-16 or UTF-8)
+ //
+ LogString decoded;
+ Transcoder::decode(greeting, decoded);
+ //
+ // decode to basic_string<UniChar>
+ //
+ std::basic_string<UniChar> encoded;
+ Transcoder::encode(decoded, encoded);
+ //
+ // should be lossless
+ //
+ LOGUNIT_ASSERT_EQUAL(std::basic_string<UniChar>(greeting), encoded);
+ }
+#endif
+
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(TranscoderTestCase);
diff --git a/src/test/cpp/hierarchytest.cpp b/src/test/cpp/hierarchytest.cpp
new file mode 100755
index 0000000..1475ca1
--- /dev/null
+++ b/src/test/cpp/hierarchytest.cpp
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logger.h>
+#include <log4cxx/hierarchy.h>
+#include "logunit.h"
+#include "insertwide.h"
+
+using namespace log4cxx;
+
+/**
+ * Tests hierarchy.
+ *
+ */
+LOGUNIT_CLASS(HierarchyTest) {
+ LOGUNIT_TEST_SUITE(HierarchyTest);
+ LOGUNIT_TEST(testGetParent);
+ LOGUNIT_TEST_SUITE_END();
+public:
+
+ /**
+ * Tests getParent.
+ */
+ void testGetParent() {
+ //
+ // Note: test inspired by LOGCXX-118.
+ //
+ LoggerPtr logger1(Logger::getLogger("HierarchyTest_testGetParent.logger1"));
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("root")), logger1->getParent()->getName());
+ LoggerPtr logger2(Logger::getLogger("HierarchyTest_testGetParent.logger2"));
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("root")), logger1->getParent()->getName());
+ LoggerPtr logger3(Logger::getLogger("HierarchyTest_testGetParent"));
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("HierarchyTest_testGetParent")),
+ logger1->getParent()->getName());
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("HierarchyTest_testGetParent")),
+ logger2->getParent()->getName());
+ }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(HierarchyTest);
+
diff --git a/src/test/cpp/hierarchythresholdtestcase.cpp b/src/test/cpp/hierarchythresholdtestcase.cpp
new file mode 100644
index 0000000..89db0e6
--- /dev/null
+++ b/src/test/cpp/hierarchythresholdtestcase.cpp
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logger.h>
+#include <log4cxx/propertyconfigurator.h>
+#include "util/compare.h"
+#include "xml/xlevel.h"
+#include "logunit.h"
+#include "testchar.h"
+#include <log4cxx/spi/loggerrepository.h>
+
+using namespace log4cxx;
+
+/**
+Test the configuration of the hierarchy-wide threshold.
+*/
+LOGUNIT_CLASS(HierarchyThresholdTestCase)
+{
+ LOGUNIT_TEST_SUITE(HierarchyThresholdTestCase);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST(test3);
+ LOGUNIT_TEST(test4);
+ LOGUNIT_TEST(test5);
+ LOGUNIT_TEST(test6);
+ LOGUNIT_TEST(test7);
+ LOGUNIT_TEST(test8);
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ logger->getLoggerRepository()->resetConfiguration();
+ }
+
+ void test1()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold1.properties"));
+ common();
+ LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.1")));
+ }
+
+ void test2()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold2.properties"));
+ common();
+ LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.2")));
+ }
+
+ void test3()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold3.properties"));
+ common();
+ LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.3")));
+ }
+
+ void test4()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold4.properties"));
+ common();
+ LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.4")));
+ }
+
+ void test5()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold5.properties"));
+ common();
+ LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.5")));
+ }
+
+ void test6()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold6.properties"));
+ common();
+ LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.6")));
+ }
+
+ void test7()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold7.properties"));
+ common();
+ LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.7")));
+ }
+
+ void test8()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold8.properties"));
+ common();
+ LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.8")));
+ }
+
+ static void common()
+ {
+ logger->log(XLevel::getTrace(), LOG4CXX_TEST_STR("m0"));
+ logger->debug(LOG4CXX_TEST_STR("m1"));
+ logger->info(LOG4CXX_TEST_STR("m2"));
+ logger->warn(LOG4CXX_TEST_STR("m3"));
+ logger->error(LOG4CXX_TEST_STR("m4"));
+ logger->fatal(LOG4CXX_TEST_STR("m5"));
+ }
+
+private:
+ static File TEMP;
+ static LoggerPtr logger;
+};
+
+File HierarchyThresholdTestCase::TEMP(LOG4CXX_FILE("output/temp"));
+
+LoggerPtr HierarchyThresholdTestCase::logger =
+ Logger::getLogger(LOG4CXX_TEST_STR("HierarchyThresholdTestCase"));
+
+LOGUNIT_TEST_SUITE_REGISTRATION(HierarchyThresholdTestCase);
diff --git a/src/test/cpp/insertwide.h b/src/test/cpp/insertwide.h
new file mode 100644
index 0000000..3bcc802
--- /dev/null
+++ b/src/test/cpp/insertwide.h
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(LOG4CXX_TEST_INSERT_WIDE)
+#define LOG4CXX_TEST_INSERT_WIDE 1
+
+#include <ostream>
+#include <string>
+
+#if LOG4CXX_WCHAR_T_API
+std::ostream& operator<<(std::ostream& os,
+ const std::wstring& str);
+#endif
+
+#if LOG4CXX_LOGCHAR_IS_UNICHAR || LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+std::ostream& operator<<(std::ostream& os,
+ const std::basic_string<log4cxx::UniChar>& str);
+#endif
+
+#endif
diff --git a/src/test/cpp/l7dtestcase.cpp b/src/test/cpp/l7dtestcase.cpp
new file mode 100644
index 0000000..680def2
--- /dev/null
+++ b/src/test/cpp/l7dtestcase.cpp
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logger.h>
+#include <log4cxx/propertyconfigurator.h>
+#include <log4cxx/helpers/propertyresourcebundle.h>
+#include <log4cxx/helpers/locale.h>
+
+#include "util/compare.h"
+
+#include <vector>
+#include <sstream>
+
+#include "testchar.h"
+#include "logunit.h"
+#include <log4cxx/spi/loggerrepository.h>
+
+
+typedef std::basic_ostringstream<testchar> StringBuffer;
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+LOGUNIT_CLASS(L7dTestCase)
+{
+ LOGUNIT_TEST_SUITE(L7dTestCase);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST_SUITE_END();
+
+ LoggerPtr root;
+ ResourceBundlePtr bundles[3];
+
+public:
+ void setUp()
+ {
+ Locale localeUS(LOG4CXX_STR("en"), LOG4CXX_STR("US"));
+ bundles[0] =
+ ResourceBundle::getBundle(LOG4CXX_STR("L7D"), localeUS);
+ LOGUNIT_ASSERT(bundles[0] != 0);
+
+ Locale localeFR(LOG4CXX_STR("fr"), LOG4CXX_STR("FR"));
+ bundles[1] =
+ ResourceBundle::getBundle(LOG4CXX_STR("L7D"), localeFR);
+ LOGUNIT_ASSERT(bundles[1] != 0);
+
+ Locale localeCH(LOG4CXX_STR("fr"), LOG4CXX_STR("CH"));
+ bundles[2] =
+ ResourceBundle::getBundle(LOG4CXX_STR("L7D"), localeCH);
+ LOGUNIT_ASSERT(bundles[2] != 0);
+
+ root = Logger::getRootLogger();
+ }
+
+ void tearDown()
+ {
+ root->getLoggerRepository()->resetConfiguration();
+ }
+
+ void test1()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/l7d1.properties"));
+
+ log4cxx::helpers::Pool pool;
+
+ for (int i = 0; i < 3; i++)
+ {
+ root->setResourceBundle(bundles[i]);
+
+ LOG4CXX_L7DLOG(root, Level::getDebug(), LOG4CXX_TEST_STR("bogus1"));
+ LOG4CXX_L7DLOG(root, Level::getInfo(), LOG4CXX_TEST_STR("test"));
+ LOG4CXX_L7DLOG(root, Level::getWarn(), LOG4CXX_TEST_STR("hello_world"));
+
+
+ StringBuffer os;
+ os << (i + 1);
+ LOG4CXX_L7DLOG2(root, Level::getDebug(), LOG4CXX_TEST_STR("msg1"), os.str().c_str(),
+ LOG4CXX_TEST_STR("log4j"));
+ LOG4CXX_L7DLOG2(root, Level::getError(), LOG4CXX_TEST_STR("bogusMsg"), os.str().c_str(),
+ LOG4CXX_TEST_STR("log4j"));
+ LOG4CXX_L7DLOG2(root, Level::getError(), LOG4CXX_TEST_STR("msg1"), os.str().c_str(),
+ LOG4CXX_TEST_STR("log4j"));
+ LOG4CXX_L7DLOG(root, Level::getInfo(), LOG4CXX_TEST_STR("bogus2"));
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(LOG4CXX_FILE("output/temp"),
+ LOG4CXX_FILE("witness/l7d.1")));
+ }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(L7dTestCase);
diff --git a/src/test/cpp/leveltestcase.cpp b/src/test/cpp/leveltestcase.cpp
new file mode 100644
index 0000000..15893ae
--- /dev/null
+++ b/src/test/cpp/leveltestcase.cpp
@@ -0,0 +1,121 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/level.h>
+#include "testchar.h"
+#include "logunit.h"
+
+#if LOG4CXX_CFSTRING_API
+#include <CoreFoundation/CFString.h>
+#endif
+
+using namespace log4cxx;
+
+LOGUNIT_CLASS(LevelTestCase)
+{
+ LOGUNIT_TEST_SUITE(LevelTestCase);
+ LOGUNIT_TEST(testToLevelFatal);
+ LOGUNIT_TEST(testTraceInt);
+ LOGUNIT_TEST(testTrace);
+ LOGUNIT_TEST(testIntToTrace);
+ LOGUNIT_TEST(testStringToTrace);
+#if LOG4CXX_WCHAR_T_API
+ LOGUNIT_TEST(testWideStringToTrace);
+#endif
+#if LOG4CXX_UNICHAR_API
+ LOGUNIT_TEST(testUniCharStringToTrace);
+#endif
+#if LOG4CXX_CFSTRING_API
+ LOGUNIT_TEST(testCFStringToTrace);
+#endif
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ void testToLevelFatal()
+ {
+ LevelPtr level(Level::toLevel(LOG4CXX_TEST_STR("fATal")));
+ LOGUNIT_ASSERT_EQUAL((int) Level::FATAL_INT, level->toInt());
+ }
+
+ /**
+ * Tests Level::TRACE_INT.
+ */
+ void testTraceInt() {
+ LOGUNIT_ASSERT_EQUAL(5000, (int) Level::TRACE_INT);
+ }
+
+ /**
+ * Tests Level.TRACE.
+ */
+ void testTrace() {
+ LOGUNIT_ASSERT(Level::getTrace()->toString() == LOG4CXX_STR("TRACE"));
+ LOGUNIT_ASSERT_EQUAL(5000, Level::getTrace()->toInt());
+ LOGUNIT_ASSERT_EQUAL(7, Level::getTrace()->getSyslogEquivalent());
+ }
+
+ /**
+ * Tests Level.toLevel(Level.TRACE_INT).
+ */
+ void testIntToTrace() {
+ LevelPtr trace(Level::toLevel(5000));
+ LOGUNIT_ASSERT(trace->toString() == LOG4CXX_STR("TRACE"));
+ }
+
+ /**
+ * Tests Level.toLevel("TRACE");
+ */
+ void testStringToTrace() {
+ LevelPtr trace(Level::toLevel("TRACE"));
+ LOGUNIT_ASSERT(trace->toString() == LOG4CXX_STR("TRACE"));
+ }
+
+#if LOG4CXX_WCHAR_T_API
+ /**
+ * Tests Level.toLevel(L"TRACE");
+ */
+ void testWideStringToTrace() {
+ LevelPtr trace(Level::toLevel(L"TRACE"));
+ LOGUNIT_ASSERT(trace->toString() == LOG4CXX_STR("TRACE"));
+ }
+#endif
+
+#if LOG4CXX_UNICHAR_API
+ /**
+ * Tests Level.toLevel("TRACE");
+ */
+ void testUniCharStringToTrace() {
+ const log4cxx::UniChar name[] = { 'T', 'R', 'A', 'C', 'E', 0 };
+ LevelPtr trace(Level::toLevel(name));
+ LOGUNIT_ASSERT(trace->toString() == LOG4CXX_STR("TRACE"));
+ }
+#endif
+
+#if LOG4CXX_CFSTRING_API
+ /**
+ * Tests Level.toLevel(CFSTR("TRACE"));
+ */
+ void testCFStringToTrace() {
+ LevelPtr trace(Level::toLevel(CFSTR("TRACE")));
+ LOGUNIT_ASSERT(trace->toString() == LOG4CXX_STR("TRACE"));
+ }
+#endif
+
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(LevelTestCase);
diff --git a/src/test/cpp/loggertestcase.cpp b/src/test/cpp/loggertestcase.cpp
new file mode 100644
index 0000000..399d697
--- /dev/null
+++ b/src/test/cpp/loggertestcase.cpp
@@ -0,0 +1,465 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logger.h>
+#include <log4cxx/fileappender.h>
+#include <log4cxx/appenderskeleton.h>
+#include <log4cxx/basicconfigurator.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/level.h>
+#include <log4cxx/hierarchy.h>
+#include <log4cxx/spi/rootlogger.h>
+#include <log4cxx/helpers/propertyresourcebundle.h>
+#include "insertwide.h"
+#include "testchar.h"
+#include "logunit.h"
+#include <log4cxx/helpers/locale.h>
+#include "vectorappender.h"
+
+using namespace log4cxx;
+using namespace log4cxx::spi;
+using namespace log4cxx::helpers;
+
+class CountingAppender;
+typedef helpers::ObjectPtrT<CountingAppender> CountingAppenderPtr;
+
+class CountingAppender : public AppenderSkeleton
+{
+public:
+ int counter;
+
+ CountingAppender() : counter(0)
+ {}
+
+ void close()
+ {}
+
+ void append(const spi::LoggingEventPtr& /*event*/, Pool& /*p*/)
+ { counter++; }
+
+ bool requiresLayout() const
+ { return true; }
+};
+
+LOGUNIT_CLASS(LoggerTestCase)
+{
+ LOGUNIT_TEST_SUITE(LoggerTestCase);
+ LOGUNIT_TEST(testAppender1);
+ LOGUNIT_TEST(testAppender2);
+ LOGUNIT_TEST(testAdditivity1);
+ LOGUNIT_TEST(testAdditivity2);
+ LOGUNIT_TEST(testAdditivity3);
+ LOGUNIT_TEST(testDisable1);
+// LOGUNIT_TEST(testRB1);
+// LOGUNIT_TEST(testRB2); //TODO restore
+// LOGUNIT_TEST(testRB3);
+ LOGUNIT_TEST(testExists);
+ LOGUNIT_TEST(testHierarchy1);
+ LOGUNIT_TEST(testTrace);
+ LOGUNIT_TEST(testIsTraceEnabled);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ BasicConfigurator::resetConfiguration();
+ a1 = 0;
+ a2 = 0;
+ logger = 0;
+ }
+
+ /**
+ Add an appender and see if it can be retrieved.
+ */
+ void testAppender1()
+ {
+ logger = Logger::getLogger(LOG4CXX_TEST_STR("test"));
+ a1 = new FileAppender();
+ a1->setName(LOG4CXX_STR("testAppender1"));
+ logger->addAppender(a1);
+
+ AppenderList list = logger->getAllAppenders();
+ AppenderPtr aHat = list.front();
+ LOGUNIT_ASSERT_EQUAL(a1, aHat);
+ }
+
+ /**
+ Add an appender X, Y, remove X and check if Y is the only
+ remaining appender.
+ */
+ void testAppender2()
+ {
+ a1 = new FileAppender();
+ a1->setName(LOG4CXX_STR("testAppender2.1"));
+ a2 = new FileAppender();
+ a2->setName(LOG4CXX_STR("testAppender2.2"));
+
+ logger = Logger::getLogger(LOG4CXX_TEST_STR("test"));
+ logger->addAppender(a1);
+ logger->addAppender(a2);
+ logger->removeAppender((LogString) LOG4CXX_STR("testAppender2.1"));
+
+ AppenderList list = logger->getAllAppenders();
+ AppenderPtr aHat = list.front();
+ LOGUNIT_ASSERT_EQUAL(a2, aHat);
+ LOGUNIT_ASSERT(list.size() == 1);
+ }
+
+ /**
+ Test if LoggerPtr a.b inherits its appender from a.
+ */
+ void testAdditivity1()
+ {
+ LoggerPtr a = Logger::getLogger(LOG4CXX_TEST_STR("a"));
+ LoggerPtr ab = Logger::getLogger(LOG4CXX_TEST_STR("a.b"));
+ CountingAppenderPtr ca = new CountingAppender();
+ a->addAppender(ca);
+
+ LOGUNIT_ASSERT_EQUAL(ca->counter, 0);
+ ab->debug(MSG);
+ LOGUNIT_ASSERT_EQUAL(ca->counter, 1);
+ ab->info(MSG);
+ LOGUNIT_ASSERT_EQUAL(ca->counter, 2);
+ ab->warn(MSG);
+ LOGUNIT_ASSERT_EQUAL(ca->counter, 3);
+ ab->error(MSG);
+ LOGUNIT_ASSERT_EQUAL(ca->counter, 4);
+ }
+
+ /**
+ Test multiple additivity.
+ */
+ void testAdditivity2()
+ {
+ LoggerPtr a = Logger::getLogger(LOG4CXX_TEST_STR("a"));
+ LoggerPtr ab = Logger::getLogger(LOG4CXX_TEST_STR("a.b"));
+ LoggerPtr abc = Logger::getLogger(LOG4CXX_TEST_STR("a.b.c"));
+ LoggerPtr x = Logger::getLogger(LOG4CXX_TEST_STR("x"));
+
+ CountingAppenderPtr ca1 = new CountingAppender();
+ CountingAppenderPtr ca2 = new CountingAppender();
+
+ a->addAppender(ca1);
+ abc->addAppender(ca2);
+
+ LOGUNIT_ASSERT_EQUAL(ca1->counter, 0);
+ LOGUNIT_ASSERT_EQUAL(ca2->counter, 0);
+
+ ab->debug(MSG);
+ LOGUNIT_ASSERT_EQUAL(ca1->counter, 1);
+ LOGUNIT_ASSERT_EQUAL(ca2->counter, 0);
+
+ abc->debug(MSG);
+ LOGUNIT_ASSERT_EQUAL(ca1->counter, 2);
+ LOGUNIT_ASSERT_EQUAL(ca2->counter, 1);
+
+ x->debug(MSG);
+ LOGUNIT_ASSERT_EQUAL(ca1->counter, 2);
+ LOGUNIT_ASSERT_EQUAL(ca2->counter, 1);
+ }
+
+ /**
+ Test additivity flag.
+ */
+ void testAdditivity3()
+ {
+ LoggerPtr root = Logger::getRootLogger();
+ LoggerPtr a = Logger::getLogger(LOG4CXX_TEST_STR("a"));
+ LoggerPtr ab = Logger::getLogger(LOG4CXX_TEST_STR("a.b"));
+ LoggerPtr abc = Logger::getLogger(LOG4CXX_TEST_STR("a.b.c"));
+ LoggerPtr x = Logger::getLogger(LOG4CXX_TEST_STR("x"));
+
+ CountingAppenderPtr caRoot = new CountingAppender();
+ CountingAppenderPtr caA = new CountingAppender();
+ CountingAppenderPtr caABC = new CountingAppender();
+
+ root->addAppender(caRoot);
+ a->addAppender(caA);
+ abc->addAppender(caABC);
+
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 0);
+ LOGUNIT_ASSERT_EQUAL(caA->counter, 0);
+ LOGUNIT_ASSERT_EQUAL(caABC->counter, 0);
+
+ ab->setAdditivity(false);
+
+ a->debug(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 1);
+ LOGUNIT_ASSERT_EQUAL(caA->counter, 1);
+ LOGUNIT_ASSERT_EQUAL(caABC->counter, 0);
+
+ ab->debug(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 1);
+ LOGUNIT_ASSERT_EQUAL(caA->counter, 1);
+ LOGUNIT_ASSERT_EQUAL(caABC->counter, 0);
+
+ abc->debug(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 1);
+ LOGUNIT_ASSERT_EQUAL(caA->counter, 1);
+ LOGUNIT_ASSERT_EQUAL(caABC->counter, 1);
+ }
+
+ void testDisable1()
+ {
+ CountingAppenderPtr caRoot = new CountingAppender();
+ LoggerPtr root = Logger::getRootLogger();
+ root->addAppender(caRoot);
+
+ LoggerRepositoryPtr h = LogManager::getLoggerRepository();
+
+ //h.disableDebug();
+ h->setThreshold(Level::getInfo());
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 0);
+
+ root->debug(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 0);
+ root->info(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 1);
+ root->log(Level::getWarn(), MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 2);
+ root->warn(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 3);
+
+ //h.disableInfo();
+ h->setThreshold(Level::getWarn());
+ root->debug(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 3);
+ root->info(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 3);
+ root->log(Level::getWarn(), MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 4);
+ root->error(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 5);
+ root->log(Level::getError(), MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 6);
+
+ //h.disableAll();
+ h->setThreshold(Level::getOff());
+ root->debug(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 6);
+ root->info(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 6);
+ root->log(Level::getWarn(), MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 6);
+ root->error(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 6);
+ root->log(Level::getFatal(), MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 6);
+ root->log(Level::getFatal(), MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 6);
+
+ //h.disable(Level::getFatalLevel());
+ h->setThreshold(Level::getOff());
+ root->debug(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 6);
+ root->info(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 6);
+ root->log(Level::getWarn(), MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 6);
+ root->error(MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 6);
+ root->log(Level::getWarn(), MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 6);
+ root->log(Level::getFatal(), MSG);
+ LOGUNIT_ASSERT_EQUAL(caRoot->counter, 6);
+ }
+
+
+ ResourceBundlePtr getBundle(const LogString& lang, const LogString& region)
+ {
+ Locale l(lang, region);
+ ResourceBundlePtr bundle(
+ PropertyResourceBundle::getBundle(LOG4CXX_STR("L7D"),l));
+ LOGUNIT_ASSERT(bundle != 0);
+ return bundle;
+ }
+
+ void testRB1()
+ {
+ ResourceBundlePtr rbUS(getBundle(LOG4CXX_STR("en"), LOG4CXX_STR("US")));
+ ResourceBundlePtr rbFR(getBundle(LOG4CXX_STR("fr"), LOG4CXX_STR("FR")));
+ ResourceBundlePtr rbCH(getBundle(LOG4CXX_STR("fr"), LOG4CXX_STR("CH")));
+
+ LoggerPtr root = Logger::getRootLogger();
+ root->setResourceBundle(rbUS);
+
+ ResourceBundlePtr t = root->getResourceBundle();
+ LOGUNIT_ASSERT(t == rbUS);
+
+ LoggerPtr x = Logger::getLogger(LOG4CXX_TEST_STR("x"));
+ LoggerPtr x_y = Logger::getLogger(LOG4CXX_TEST_STR("x.y"));
+ LoggerPtr x_y_z = Logger::getLogger(LOG4CXX_TEST_STR("x.y.z"));
+
+ t = x->getResourceBundle();
+ LOGUNIT_ASSERT(t == rbUS);
+ t = x_y->getResourceBundle();
+ LOGUNIT_ASSERT(t == rbUS);
+ t = x_y_z->getResourceBundle();
+ LOGUNIT_ASSERT(t == rbUS);
+ }
+
+ void testRB2()
+ {
+ LoggerPtr root = Logger::getRootLogger();
+ ResourceBundlePtr rbUS(getBundle(LOG4CXX_STR("en"), LOG4CXX_STR("US")));
+ ResourceBundlePtr rbFR(getBundle(LOG4CXX_STR("fr"), LOG4CXX_STR("FR")));
+ ResourceBundlePtr rbCH(getBundle(LOG4CXX_STR("fr"), LOG4CXX_STR("CH")));
+
+ root->setResourceBundle(rbUS);
+
+ ResourceBundlePtr t = root->getResourceBundle();
+ LOGUNIT_ASSERT(t == rbUS);
+
+ LoggerPtr x = Logger::getLogger(LOG4CXX_TEST_STR("x"));
+ LoggerPtr x_y = Logger::getLogger(LOG4CXX_TEST_STR("x.y"));
+ LoggerPtr x_y_z = Logger::getLogger(LOG4CXX_TEST_STR("x.y.z"));
+
+ x_y->setResourceBundle(rbFR);
+ t = x->getResourceBundle();
+ LOGUNIT_ASSERT(t == rbUS);
+ t = x_y->getResourceBundle();
+ LOGUNIT_ASSERT(t == rbFR);
+ t = x_y_z->getResourceBundle();
+ LOGUNIT_ASSERT(t == rbFR);
+ }
+
+ void testRB3()
+ {
+ ResourceBundlePtr rbUS(getBundle(LOG4CXX_STR("en"), LOG4CXX_STR("US")));
+ ResourceBundlePtr rbFR(getBundle(LOG4CXX_STR("fr"), LOG4CXX_STR("FR")));
+ ResourceBundlePtr rbCH(getBundle(LOG4CXX_STR("fr"), LOG4CXX_STR("CH")));
+
+ LoggerPtr root = Logger::getRootLogger();
+ root->setResourceBundle(rbUS);
+
+ ResourceBundlePtr t = root->getResourceBundle();
+ LOGUNIT_ASSERT(t == rbUS);
+
+ LoggerPtr x = Logger::getLogger(LOG4CXX_TEST_STR("x"));
+ LoggerPtr x_y = Logger::getLogger(LOG4CXX_TEST_STR("x.y"));
+ LoggerPtr x_y_z = Logger::getLogger(LOG4CXX_TEST_STR("x.y.z"));
+
+ x_y->setResourceBundle(rbFR);
+ x_y_z->setResourceBundle(rbCH);
+ t = x->getResourceBundle();
+ LOGUNIT_ASSERT(t == rbUS);
+ t = x_y->getResourceBundle();
+ LOGUNIT_ASSERT(t == rbFR);
+ t = x_y_z->getResourceBundle();
+ LOGUNIT_ASSERT(t == rbCH);
+ }
+
+ void testExists()
+ {
+ LoggerPtr a = Logger::getLogger(LOG4CXX_TEST_STR("a"));
+ LoggerPtr a_b = Logger::getLogger(LOG4CXX_TEST_STR("a.b"));
+ LoggerPtr a_b_c = Logger::getLogger(LOG4CXX_TEST_STR("a.b.c"));
+
+ LoggerPtr t;
+ t = LogManager::exists(LOG4CXX_TEST_STR("xx"));
+ LOGUNIT_ASSERT(t == 0);
+ t = LogManager::exists(LOG4CXX_TEST_STR("a"));
+ LOGUNIT_ASSERT_EQUAL(a, t);
+ t = LogManager::exists(LOG4CXX_TEST_STR("a.b"));
+ LOGUNIT_ASSERT_EQUAL(a_b, t);
+ t = LogManager::exists(LOG4CXX_TEST_STR("a.b.c"));
+ LOGUNIT_ASSERT_EQUAL(a_b_c, t);
+ }
+
+ void testHierarchy1()
+ {
+ LoggerRepositoryPtr h = new Hierarchy();
+ LoggerPtr root(h->getRootLogger());
+ root->setLevel(Level::getError());
+ LoggerPtr a0 = h->getLogger(LOG4CXX_STR("a"));
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("a"), a0->getName());
+ LOGUNIT_ASSERT(a0->getLevel() == 0);
+ LOGUNIT_ASSERT(Level::getError() == a0->getEffectiveLevel());
+
+ LoggerPtr a11 = h->getLogger(LOG4CXX_STR("a"));
+ LOGUNIT_ASSERT_EQUAL(a0, a11);
+ }
+
+ void compileTestForLOGCXX202() const {
+ //
+ // prior to fix, these line would compile.
+ //
+ (*logger).info("Hello, World.");
+ ((Logger*) logger)->info("Hello, World.");
+ //
+ // this one would not.
+ //
+ logger->info("Hello, World.");
+ }
+
+
+ /**
+ * Tests logger.trace(Object).
+ *
+ */
+ void testTrace() {
+ VectorAppenderPtr appender = new VectorAppender();
+ LoggerPtr root = Logger::getRootLogger();
+ root->addAppender(appender);
+ root->setLevel(Level::getInfo());
+
+ LoggerPtr tracer = Logger::getLogger("com.example.Tracer");
+ tracer->setLevel(Level::getTrace());
+
+ LOG4CXX_TRACE(tracer, "Message 1");
+ LOG4CXX_TRACE(root, "Discarded Message");
+ LOG4CXX_TRACE(root, "Discarded Message");
+
+ std::vector<LoggingEventPtr> msgs(appender->vector);
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, msgs.size());
+ LoggingEventPtr event = msgs[0];
+ LOGUNIT_ASSERT_EQUAL((int) Level::TRACE_INT, event->getLevel()->toInt());
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("Message 1")), event->getMessage());
+ }
+
+ /**
+ * Tests isTraceEnabled.
+ *
+ */
+ void testIsTraceEnabled() {
+ VectorAppenderPtr appender = new VectorAppender();
+ LoggerPtr root = Logger::getRootLogger();
+ root->addAppender(appender);
+ root->setLevel(Level::getInfo());
+
+ LoggerPtr tracer = Logger::getLogger("com.example.Tracer");
+ tracer->setLevel(Level::getTrace());
+
+ LOGUNIT_ASSERT_EQUAL(true, tracer->isTraceEnabled());
+ LOGUNIT_ASSERT_EQUAL(false, root->isTraceEnabled());
+ }
+
+protected:
+ static LogString MSG;
+ LoggerPtr logger;
+ AppenderPtr a1;
+ AppenderPtr a2;
+};
+
+LogString LoggerTestCase::MSG(LOG4CXX_STR("M"));
+
+LOGUNIT_TEST_SUITE_REGISTRATION(LoggerTestCase);
diff --git a/src/test/cpp/logunit.cpp b/src/test/cpp/logunit.cpp
new file mode 100644
index 0000000..d5c52cc
--- /dev/null
+++ b/src/test/cpp/logunit.cpp
@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include "logunit.h"
+
+#include <apr_general.h>
+#include <algorithm>
+#include <stdlib.h>
+#include <locale.h>
+
+void initialize() {
+ setlocale(LC_CTYPE, "");
+ const char* ctype = setlocale(LC_CTYPE, 0);
+ if (ctype == 0) {
+ puts("LC_CTYPE: NULL");
+ } else {
+ printf("LC_CTYPE: %s\n", ctype);
+ }
+ apr_initialize();
+}
+
+extern const char** testlist;
+
+static bool suite_sort(const LogUnit::SuiteList::value_type& lhs, const LogUnit::SuiteList::value_type& rhs) {
+ return lhs.first < rhs.first;
+}
+
+abts_suite* abts_run_suites(abts_suite* suite) {
+ LogUnit::SuiteList sorted(LogUnit::getAllSuites());
+
+#if !defined(_MSC_VER)
+ std::sort(sorted.begin(), sorted.end(), suite_sort);
+#endif
+
+ for(LogUnit::SuiteList::const_iterator iter = sorted.begin();
+ iter != sorted.end();
+ iter++) {
+ //
+ // if there is an explicit testlist or if the suite is not by default disabled
+ // pump suite through filter
+ if(testlist || !iter->second->isDisabled()) {
+ suite = iter->second->run(suite);
+ }
+ }
+ apr_terminate();
+ return suite;
+}
+
+using namespace LogUnit;
+using namespace std;
+
+TestException::TestException() {}
+TestException::TestException(const TestException& src) : std::exception(src) {
+}
+
+TestException& TestException::operator=(const TestException& src) {
+ exception::operator=(src);
+ return *this;
+}
+
+
+AssertException::AssertException(std::string message, int line) : msg(message), lineno(line) {}
+
+AssertException::AssertException(bool expected, const char* actualExpr, int line) : msg(actualExpr), lineno(line) {
+ if (expected) {
+ msg.append(" was expected to be true, was false.");
+ } else {
+ msg.append(" was expected to be true, was false.");
+ }
+}
+
+AssertException::AssertException(const AssertException& src)
+ : std::exception(src),
+ msg(src.msg),
+ lineno(src.lineno) {
+}
+
+AssertException::~AssertException() throw() {
+}
+
+AssertException& AssertException::operator=(const AssertException& src) {
+ exception::operator=(src);
+ msg = src.msg;
+ lineno = src.lineno;
+ return *this;
+}
+
+std::string AssertException::getMessage() const {
+ return msg;
+}
+
+int AssertException::getLine() const {
+ return lineno;
+}
+
+
+
+
+TestFixture::TestFixture() : tc(0) {}
+TestFixture::~TestFixture() {}
+void TestFixture::setCase(abts_case* tc) {
+ this->tc = tc;
+}
+void TestFixture::setUp() {}
+void TestFixture::tearDown() {}
+
+void TestFixture::assertEquals(const char* expected,
+ const char* actual,
+ const char* expectedExpr,
+ const char* actualExpr,
+ int lineno) {
+ abts_str_equal(tc, expected, actual, lineno);
+ if ((expected == 0 || actual != 0) ||
+ (expected != 0 || actual == 0) ||
+ (expected != 0 && strcmp(expected, actual) != 0)) {
+ throw TestException();
+ }
+}
+
+void TestFixture::assertEquals(const std::string expected,
+ const std::string actual,
+ const char* expectedExpr,
+ const char* actualExpr,
+ int lineno) {
+ abts_str_equal(tc, expected.c_str(), actual.c_str(), lineno);
+ if (expected != actual) {
+ throw TestException();
+ }
+}
+
+template<class S>
+static void transcode(std::string& dst, const S& src) {
+ for(typename S::const_iterator iter = src.begin();
+ iter != src.end();
+ iter++) {
+ if (*iter <= 0x7F) {
+ dst.append(1, (char) *iter);
+ } else {
+ dst.append(1, '?');
+ }
+ }
+}
+
+#if LOG4CXX_LOGCHAR_IS_WCHAR || LOG4CXX_WCHAR_T_API
+void TestFixture::assertEquals(const std::wstring expected,
+ const std::wstring actual,
+ const char* expectedExpr,
+ const char* actualExpr,
+ int lineno) {
+ if (expected != actual) {
+ std::string exp, act;
+ transcode(exp, expected);
+ transcode(act, actual);
+ abts_str_equal(tc, exp.c_str(), act.c_str(), lineno);
+ throw TestException();
+ }
+}
+#endif
+#if LOG4CXX_LOGCHAR_IS_UNICHAR || LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+void TestFixture::assertEquals(const std::basic_string<log4cxx::UniChar> expected,
+ const std::basic_string<log4cxx::UniChar> actual,
+ const char* expectedExpr,
+ const char* actualExpr,
+int lineno) {
+ if (expected != actual) {
+ std::string exp, act;
+ transcode(exp, expected);
+ transcode(act, actual);
+ abts_str_equal(tc, exp.c_str(), act.c_str(), lineno);
+ throw TestException();
+ }
+}
+#endif
+
+
+void TestFixture::assertEquals(const int expected, const int actual, int lineno) {
+ abts_int_equal(tc, expected, actual, lineno);
+ if (expected != actual) {
+ throw TestException();
+ }
+}
+
+
+LogUnit::TestSuite::TestSuite(const char* fname) : filename(fname), disabled(false) {
+#if defined(_WIN32)
+ for(size_t i = filename.find('\\');
+ i != std::string::npos;
+ i = filename.find('\\', i+1)) {
+ filename.replace(i, 1, 1, '/');
+ }
+#endif
+}
+
+void LogUnit::TestSuite::addTest(const char*, test_func func) {
+ test_funcs.push_back(func);
+}
+
+std::string LogUnit::TestSuite::getName() const {
+ return filename;
+}
+
+void LogUnit::TestSuite::setDisabled(bool newVal) {
+ disabled = newVal;
+}
+
+bool LogUnit::TestSuite::isDisabled() const {
+ return disabled;
+}
+
+abts_suite* TestSuite::run(abts_suite* suite) const {
+ suite = abts_add_suite(suite, filename.c_str());
+ for(TestList::const_iterator iter = test_funcs.begin();
+ iter != test_funcs.end();
+ iter++) {
+ abts_run_test(suite, *iter, NULL);
+ }
+ return suite;
+}
+
+
+LogUnit::SuiteList& LogUnit::getAllSuites() {
+ static LogUnit::SuiteList allSuites;
+ return allSuites;
+}
+
diff --git a/src/test/cpp/logunit.h b/src/test/cpp/logunit.h
new file mode 100644
index 0000000..179e268
--- /dev/null
+++ b/src/test/cpp/logunit.h
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_LOGUNIT_H)
+#define _LOG4CXX_LOGUNIT_H
+
+
+#if defined(_MSC_VER)
+#pragma warning (push)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include "abts.h"
+#include <exception>
+#include <map>
+#include <string>
+#include <vector>
+
+#include <log4cxx/logstring.h>
+
+namespace LogUnit {
+ class TestException : public std::exception {
+ public:
+ TestException();
+ TestException(const TestException&);
+ TestException& operator=(const TestException&);
+ };
+ class AssertException : public std::exception {
+ public:
+ AssertException(std::string msg, int lineno);
+ AssertException(bool expected, const char* actualExpr, int lineno);
+ AssertException(const AssertException&);
+ AssertException& operator=(const AssertException&);
+ virtual ~AssertException() throw();
+ std::string getMessage() const;
+ int getLine() const;
+ private:
+ std::string msg;
+ int lineno;
+ };
+ class TestFixture {
+ public:
+ TestFixture();
+ virtual ~TestFixture();
+ void setCase(abts_case* tc);
+ virtual void setUp();
+ virtual void tearDown();
+
+ void assertEquals(const int expected, const int actual, int lineno);
+ void assertEquals(const std::string expected,
+ const std::string actual,
+ const char* expectedExpr,
+ const char* actualExpr,
+ int lineno);
+ void assertEquals(const char* expected,
+ const char* actual,
+ const char* expectedExpr,
+ const char* actualExpr,
+ int lineno);
+#if LOG4CXX_LOGCHAR_IS_WCHAR || LOG4CXX_WCHAR_T_API
+ void assertEquals(const std::wstring expected,
+ const std::wstring actual,
+ const char* expectedExpr,
+ const char* actualExpr,
+ int lineno);
+#endif
+#if LOG4CXX_LOGCHAR_IS_UNICHAR || LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
+ void assertEquals(const std::basic_string<log4cxx::UniChar> expected,
+ const std::basic_string<log4cxx::UniChar> actual,
+ const char* expectedExpr,
+ const char* actualExpr, int lineno);
+#endif
+ template<class T>
+ void assertEquals(const T& expected,
+ const T& actual,
+ const char* expectedExpr,
+ const char* actualExpr,
+ int lineno) {
+ if (expected != actual) {
+ std::string msg(expectedExpr);
+ msg.append(" != ");
+ msg.append(actualExpr);
+ abts_fail(tc, msg.c_str(), lineno);
+ }
+ }
+ private:
+ TestFixture(const TestFixture&);
+ TestFixture& operator=(const TestFixture&);
+ abts_case* tc;
+ };
+ template<class T>
+ void runTest(abts_case* tc, void (T::*func)()) {
+ T ti;
+ ti.setCase(tc);
+ ti.setUp();
+ try {
+ (ti.*func)();
+ } catch(TestException&) {
+ } catch(AssertException& fx) {
+ abts_fail(tc, fx.getMessage().c_str(), fx.getLine());
+ } catch(...) {
+ abts_fail(tc, "Unexpected exception", -1);
+ }
+ ti.tearDown();
+ }
+ template<class T, class X>
+ void runTestWithException(abts_case* tc, void (T::*func)()) {
+ T ti;
+ ti.setCase(tc);
+ ti.setUp();
+ try {
+ (ti.*func)();
+ } catch(TestException&) {
+ } catch(AssertException& fx) {
+ abts_fail(tc, fx.getMessage().c_str(), fx.getLine());
+ } catch(X&) {
+ } catch(...) {
+ abts_fail(tc, "Unexpected exception", -1);
+ }
+ ti.tearDown();
+ }
+ class TestSuite {
+ public:
+ TestSuite(const char* filename);
+ void addTest(const char* testName, test_func func);
+ abts_suite* run(abts_suite* suite) const;
+ std::string getName() const;
+ void setDisabled(bool newVal);
+ bool isDisabled() const;
+ private:
+ TestSuite(const TestSuite&);
+ TestSuite& operator=(const TestSuite&);
+ typedef std::vector<test_func> TestList;
+ TestList test_funcs;
+ std::string filename;
+ bool disabled;
+ };
+ typedef std::vector< std::pair<std::string, const TestSuite*> > SuiteList;
+ SuiteList& getAllSuites();
+ template<class T>
+ class RegisterSuite {
+ public:
+ RegisterSuite() {
+ T::populateSuite();
+ TestSuite* suite = T::getSuite();
+ LogUnit::getAllSuites().push_back(SuiteList::value_type(suite->getName(), suite));
+ }
+ };
+ template<class T>
+ class RegisterDisabledSuite {
+ public:
+ RegisterDisabledSuite() {
+ T::populateSuite();
+ TestSuite* suite = T::getSuite();
+ suite->setDisabled(true);
+ LogUnit::getAllSuites().push_back(SuiteList::value_type(suite->getName(), suite));
+ }
+ };
+}
+
+#define LOGUNIT_CLASS(x) class x : public LogUnit::TestFixture
+
+
+#define LOGUNIT_TEST_SUITE(TF) \
+public: \
+ static LogUnit::TestSuite* getSuite() { \
+ static LogUnit::TestSuite suite(__FILE__); \
+ return &suite; \
+ } \
+ private: \
+ class RegisterSuite { \
+ public: \
+ typedef TF ThisFixture;
+
+#define LOGUNIT_TEST(testName) \
+ class testName ## Registration { \
+ public: \
+ testName ## Registration() { \
+ ThisFixture::getSuite()->addTest(#testName, &testName ## Registration :: run); \
+ } \
+ static void run(abts_case* tc, void*) { \
+ LogUnit::runTest<ThisFixture>(tc, &ThisFixture::testName); \
+ } \
+ } register ## testName;
+
+#define LOGUNIT_TEST_EXCEPTION(testName, Exception) \
+ class testName ## Registration { \
+ public: \
+ testName ## Registration() { \
+ ThisFixture::getSuite()->addTest(#testName, &testName ## Registration :: run); \
+ } \
+ static void run(abts_case* tc, void*) { \
+ LogUnit::runTestWithException<ThisFixture, Exception>(tc, &ThisFixture::testName); \
+ } \
+ } register ## testName;
+
+
+#define LOGUNIT_TEST_SUITE_END() \
+ }; \
+ public: \
+ static void populateSuite() { \
+ static RegisterSuite registration; \
+ }
+
+
+#define LOGUNIT_TEST_SUITE_REGISTRATION(TF) \
+static LogUnit::RegisterSuite<TF> registration;
+
+#define LOGUNIT_TEST_SUITE_REGISTRATION_DISABLED(TF) \
+static LogUnit::RegisterDisabledSuite<TF> registration;
+
+
+#define LOGUNIT_ASSERT(x) { if (!(x)) throw LogUnit::AssertException(true, #x, __LINE__); }
+#define LOGUNIT_ASSERT_EQUAL(expected, actual) assertEquals(expected, actual, #expected, #actual, __LINE__)
+#define LOGUNIT_FAIL(msg) throw LogUnit::AssertException(msg, __LINE__)
+
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+#endif
+
diff --git a/src/test/cpp/minimumtestcase.cpp b/src/test/cpp/minimumtestcase.cpp
new file mode 100644
index 0000000..2d08cc4
--- /dev/null
+++ b/src/test/cpp/minimumtestcase.cpp
@@ -0,0 +1,248 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "logunit.h"
+#include <log4cxx/logger.h>
+#include <log4cxx/simplelayout.h>
+#include <log4cxx/ttcclayout.h>
+#include <log4cxx/fileappender.h>
+#include <log4cxx/helpers/absolutetimedateformat.h>
+
+#include "util/compare.h"
+#include "util/transformer.h"
+#include "util/linenumberfilter.h"
+#include "util/controlfilter.h"
+#include "util/absolutedateandtimefilter.h"
+#include "util/threadfilter.h"
+#include <log4cxx/file.h>
+#include <iostream>
+#include <log4cxx/helpers/pool.h>
+#include <apr_strings.h>
+#include "testchar.h"
+#include <log4cxx/spi/loggerrepository.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <apr_strings.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+#define TTCC_PAT \
+ ABSOLUTE_DATE_AND_TIME_PAT \
+ " \\[0x[0-9A-F]*]\\ (DEBUG|INFO|WARN|ERROR|FATAL) .* - Message [0-9]\\{1,2\\}"
+
+#define TTCC2_PAT \
+ ABSOLUTE_DATE_AND_TIME_PAT \
+ " \\[0x[0-9A-F]*]\\ (DEBUG|INFO|WARN|ERROR|FATAL) .* - " \
+ "Messages should bear numbers 0 through 23\\."
+
+
+LOGUNIT_CLASS(MinimumTestCase)
+{
+ LOGUNIT_TEST_SUITE(MinimumTestCase);
+ LOGUNIT_TEST(simple);
+ LOGUNIT_TEST(ttcc);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ void setUp()
+ {
+ root = Logger::getRootLogger();
+ root->removeAllAppenders();
+ }
+
+ void tearDown()
+ {
+ root->getLoggerRepository()->resetConfiguration();
+ }
+
+ void simple()
+ {
+ LayoutPtr layout = new SimpleLayout();
+ AppenderPtr appender = new FileAppender(layout, LOG4CXX_STR("output/simple"), false);
+ root->addAppender(appender);
+ common();
+
+ LOGUNIT_ASSERT(Compare::compare(LOG4CXX_FILE("output/simple"), LOG4CXX_FILE("witness/simple")));
+ }
+
+ void ttcc()
+ {
+ LayoutPtr layout =
+ new TTCCLayout(LOG4CXX_STR("DATE"));
+ AppenderPtr appender = new FileAppender(layout, LOG4CXX_STR("output/ttcc"), false);
+ root->addAppender(appender);
+ common();
+
+ ControlFilter filter1;
+ filter1 << TTCC_PAT << TTCC2_PAT;
+ AbsoluteDateAndTimeFilter filter2;
+ ThreadFilter filter3;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&filter1);
+ filters.push_back(&filter2);
+ filters.push_back(&filter3);
+
+ try
+ {
+ const File output("output/ttcc");
+ Transformer::transform(output, FILTERED, filters);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ const File witness("witness/ttcc");
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, witness));
+ }
+
+ std::string createMessage(int i, Pool& pool) {
+ std::string msg("Message ");
+ msg.append(pool.itoa(i));
+ return msg;
+ }
+
+ void common()
+ {
+ int i = 0;
+
+ // In the lines below, the logger names are chosen as an aid in
+ // remembering their level values. In general, the logger names
+ // have no bearing to level values.
+ LoggerPtr ERRlogger = Logger::getLogger(LOG4CXX_TEST_STR("ERR"));
+ ERRlogger->setLevel(Level::getError());
+
+ LoggerPtr INF = Logger::getLogger(LOG4CXX_TEST_STR("INF"));
+ INF->setLevel(Level::getInfo());
+
+ LoggerPtr INF_ERR = Logger::getLogger(LOG4CXX_TEST_STR("INF.ERR"));
+ INF_ERR->setLevel(Level::getError());
+
+ LoggerPtr DEB = Logger::getLogger(LOG4CXX_TEST_STR("DEB"));
+ DEB->setLevel(Level::getDebug());
+
+ // Note: categories with undefined level
+ LoggerPtr INF_UNDEF = Logger::getLogger(LOG4CXX_TEST_STR("INF.UNDEF"));
+ LoggerPtr INF_ERR_UNDEF = Logger::getLogger(LOG4CXX_TEST_STR("INF.ERR.UNDEF"));
+ LoggerPtr UNDEF = Logger::getLogger(LOG4CXX_TEST_STR("UNDEF"));
+
+ std::string msg("Message ");
+
+ Pool pool;
+
+ // These should all log.----------------------------
+ LOG4CXX_FATAL(ERRlogger, createMessage(i, pool));
+ i++; //0
+ LOG4CXX_ERROR(ERRlogger, createMessage(i, pool));
+ i++;
+
+ LOG4CXX_FATAL(INF, createMessage(i, pool));
+ i++; // 2
+ LOG4CXX_ERROR(INF, createMessage(i, pool));
+ i++;
+ LOG4CXX_WARN(INF, createMessage(i, pool));
+ i++;
+ LOG4CXX_INFO(INF, createMessage(i, pool));
+ i++;
+
+ LOG4CXX_FATAL(INF_UNDEF, createMessage(i, pool));
+ i++; //6
+ LOG4CXX_ERROR(INF_UNDEF, createMessage(i, pool));
+ i++;
+ LOG4CXX_WARN(INF_UNDEF, createMessage(i, pool));
+ i++;
+ LOG4CXX_INFO(INF_UNDEF, createMessage(i, pool));
+ i++;
+
+ LOG4CXX_FATAL(INF_ERR, createMessage(i, pool));
+ i++; // 10
+ LOG4CXX_ERROR(INF_ERR, createMessage(i, pool));
+ i++;
+
+ LOG4CXX_FATAL(INF_ERR_UNDEF, createMessage(i, pool));
+ i++;
+ LOG4CXX_ERROR(INF_ERR_UNDEF, createMessage(i, pool));
+ i++;
+
+ LOG4CXX_FATAL(DEB, createMessage(i, pool));
+ i++; //14
+ LOG4CXX_ERROR(DEB, createMessage(i, pool));
+ i++;
+ LOG4CXX_WARN(DEB, createMessage(i, pool));
+ i++;
+ LOG4CXX_INFO(DEB, createMessage(i, pool));
+ i++;
+ LOG4CXX_DEBUG(DEB, createMessage(i, pool));
+ i++;
+
+ // defaultLevel=DEBUG
+ LOG4CXX_FATAL(UNDEF, createMessage(i, pool));
+ i++; // 19
+ LOG4CXX_ERROR(UNDEF, createMessage(i, pool));
+ i++;
+ LOG4CXX_WARN(UNDEF, createMessage(i, pool));
+ i++;
+ LOG4CXX_INFO(UNDEF, createMessage(i, pool));
+ i++;
+ LOG4CXX_DEBUG(UNDEF, createMessage(i, pool));
+ i++;
+
+ // -------------------------------------------------
+ // The following should not log
+ LOG4CXX_WARN(ERRlogger, createMessage(i, pool));
+ i++;
+ LOG4CXX_INFO(ERRlogger, createMessage(i, pool));
+ i++;
+ LOG4CXX_DEBUG(ERRlogger, createMessage(i, pool));
+ i++;
+
+ LOG4CXX_DEBUG(INF, createMessage(i, pool));
+ i++;
+ LOG4CXX_DEBUG(INF_UNDEF, createMessage(i, pool));
+ i++;
+
+ LOG4CXX_WARN(INF_ERR, createMessage(i, pool));
+ i++;
+ LOG4CXX_INFO(INF_ERR, createMessage(i, pool));
+ i++;
+ LOG4CXX_DEBUG(INF_ERR, createMessage(i, pool));
+ i++;
+ LOG4CXX_WARN(INF_ERR_UNDEF, createMessage(i, pool));
+ i++;
+ LOG4CXX_INFO(INF_ERR_UNDEF, createMessage(i, pool));
+ i++;
+ LOG4CXX_DEBUG(INF_ERR_UNDEF, createMessage(i, pool));
+ i++;
+
+ // -------------------------------------------------
+ LOG4CXX_INFO(INF, LOG4CXX_TEST_STR("Messages should bear numbers 0 through 23."));
+ }
+
+ LoggerPtr root;
+ LoggerPtr logger;
+
+private:
+ static const File FILTERED;
+};
+
+
+const File MinimumTestCase::FILTERED("output/filtered");
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(MinimumTestCase);
diff --git a/src/test/cpp/ndctestcase.cpp b/src/test/cpp/ndctestcase.cpp
new file mode 100755
index 0000000..fd55942
--- /dev/null
+++ b/src/test/cpp/ndctestcase.cpp
@@ -0,0 +1,110 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/ndc.h>
+#include <log4cxx/file.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/propertyconfigurator.h>
+#include "insertwide.h"
+#include "logunit.h"
+#include "util/compare.h"
+
+
+
+using namespace log4cxx;
+
+LOGUNIT_CLASS(NDCTestCase)
+{
+ static File TEMP;
+ static LoggerPtr logger;
+
+ LOGUNIT_TEST_SUITE(NDCTestCase);
+ LOGUNIT_TEST(testPushPop);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(testInherit);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+
+ void setUp() {
+ }
+
+ void tearDown() {
+ logger->getLoggerRepository()->resetConfiguration();
+ }
+
+ /**
+ * Push and pop a value from the NDC
+ */
+ void testPushPop()
+ {
+ NDC::push("trivial context");
+ LogString actual(NDC::pop());
+ LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR("trivial context"), actual);
+ }
+
+
+ void test1() {
+ PropertyConfigurator::configure(File("input/ndc/NDC1.properties"));
+ common();
+ LOGUNIT_ASSERT(Compare::compare(TEMP, File("witness/ndc/NDC.1")));
+ }
+
+ static void common() {
+ commonLog();
+ NDC::push("n1");
+ commonLog();
+ NDC::push("n2");
+ NDC::push("n3");
+ commonLog();
+ NDC::pop();
+ commonLog();
+ NDC::clear();
+ commonLog();
+ }
+
+ static void commonLog() {
+ LOG4CXX_DEBUG(logger, "m1");
+ LOG4CXX_INFO(logger, "m2");
+ LOG4CXX_WARN(logger, "m3");
+ LOG4CXX_ERROR(logger, "m4");
+ LOG4CXX_FATAL(logger, "m5");
+ }
+
+ void testInherit() {
+ NDC::push("hello");
+ NDC::push("world");
+ NDC::Stack* clone = NDC::cloneStack();
+ NDC::clear();
+ NDC::push("discard");
+ NDC::inherit(clone);
+ LogString expected1(LOG4CXX_STR("world"));
+ LOGUNIT_ASSERT_EQUAL(expected1, NDC::pop());
+ LogString expected2(LOG4CXX_STR("hello"));
+ LOGUNIT_ASSERT_EQUAL(expected2, NDC::pop());
+ LogString expected3;
+ LOGUNIT_ASSERT_EQUAL(expected3, NDC::pop());
+ }
+
+};
+
+
+File NDCTestCase::TEMP("output/temp");
+LoggerPtr NDCTestCase::logger(Logger::getLogger("org.apache.log4j.NDCTestCase"));
+
+LOGUNIT_TEST_SUITE_REGISTRATION(NDCTestCase);
diff --git a/src/test/cpp/net/smtpappendertestcase.cpp b/src/test/cpp/net/smtpappendertestcase.cpp
new file mode 100644
index 0000000..240011f
--- /dev/null
+++ b/src/test/cpp/net/smtpappendertestcase.cpp
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG4CXX_TEST 1
+#include <log4cxx/private/log4cxx_private.h>
+
+#if LOG4CXX_HAVE_SMTP
+
+#include <log4cxx/net/smtpappender.h>
+#include "../appenderskeletontestcase.h"
+#include <log4cxx/xml/domconfigurator.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/ttcclayout.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::net;
+using namespace log4cxx::xml;
+using namespace log4cxx::spi;
+
+namespace log4cxx {
+ namespace net {
+
+ class MockTriggeringEventEvaluator :
+ public virtual spi::TriggeringEventEvaluator,
+ public virtual helpers::ObjectImpl
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(MockTriggeringEventEvaluator)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(MockTriggeringEventEvaluator)
+ LOG4CXX_CAST_ENTRY(spi::TriggeringEventEvaluator)
+ END_LOG4CXX_CAST_MAP()
+
+ MockTriggeringEventEvaluator() {
+ }
+
+ virtual bool isTriggeringEvent(const spi::LoggingEventPtr& event) {
+ return true;
+ }
+ private:
+ MockTriggeringEventEvaluator(const MockTriggeringEventEvaluator&);
+ MockTriggeringEventEvaluator& operator=(const MockTriggeringEventEvaluator&);
+ };
+ }
+}
+
+IMPLEMENT_LOG4CXX_OBJECT(MockTriggeringEventEvaluator)
+
+
+/**
+ Unit tests of log4cxx::SocketAppender
+ */
+class SMTPAppenderTestCase : public AppenderSkeletonTestCase
+{
+ LOGUNIT_TEST_SUITE(SMTPAppenderTestCase);
+ //
+ // tests inherited from AppenderSkeletonTestCase
+ //
+ LOGUNIT_TEST(testDefaultThreshold);
+ LOGUNIT_TEST(testSetOptionThreshold);
+ LOGUNIT_TEST(testTrigger);
+ LOGUNIT_TEST(testInvalid);
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+
+ AppenderSkeleton* createAppenderSkeleton() const {
+ return new log4cxx::net::SMTPAppender();
+ }
+
+ void setUp() {
+ }
+
+ void tearDown() {
+ LogManager::resetConfiguration();
+ }
+
+ /**
+ * Tests that triggeringPolicy element will set evaluator.
+ */
+ void testTrigger() {
+ DOMConfigurator::configure("input/xml/smtpAppender1.xml");
+ SMTPAppenderPtr appender(Logger::getRootLogger()->getAppender(LOG4CXX_STR("A1")));
+ TriggeringEventEvaluatorPtr evaluator(appender->getEvaluator());
+ LOGUNIT_ASSERT_EQUAL(true, evaluator->instanceof(MockTriggeringEventEvaluator::getStaticClass()));
+ }
+
+ void testInvalid() {
+ SMTPAppenderPtr appender(new SMTPAppender());
+ appender->setSMTPHost(LOG4CXX_STR("smtp.invalid"));
+ appender->setTo(LOG4CXX_STR("you@example.invalid"));
+ appender->setFrom(LOG4CXX_STR("me@example.invalid"));
+ appender->setLayout(new TTCCLayout());
+ Pool p;
+ appender->activateOptions(p);
+ LoggerPtr root(Logger::getRootLogger());
+ root->addAppender(appender);
+ LOG4CXX_INFO(root, "Hello, World.");
+ LOG4CXX_ERROR(root, "Sending Message");
+ }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(SMTPAppenderTestCase);
+
+#endif
diff --git a/src/test/cpp/net/socketappendertestcase.cpp b/src/test/cpp/net/socketappendertestcase.cpp
new file mode 100644
index 0000000..b77cc05
--- /dev/null
+++ b/src/test/cpp/net/socketappendertestcase.cpp
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/net/socketappender.h>
+#include "../appenderskeletontestcase.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+#if APR_HAS_THREADS
+/**
+ Unit tests of log4cxx::SocketAppender
+ */
+class SocketAppenderTestCase : public AppenderSkeletonTestCase
+{
+ LOGUNIT_TEST_SUITE(SocketAppenderTestCase);
+ //
+ // tests inherited from AppenderSkeletonTestCase
+ //
+ LOGUNIT_TEST(testDefaultThreshold);
+ LOGUNIT_TEST(testSetOptionThreshold);
+
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+
+ AppenderSkeleton* createAppenderSkeleton() const {
+ return new log4cxx::net::SocketAppender();
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(SocketAppenderTestCase);
+#endif
diff --git a/src/test/cpp/net/sockethubappendertestcase.cpp b/src/test/cpp/net/sockethubappendertestcase.cpp
new file mode 100644
index 0000000..d7b86f7
--- /dev/null
+++ b/src/test/cpp/net/sockethubappendertestcase.cpp
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/net/sockethubappender.h>
+#include "../appenderskeletontestcase.h"
+#include <log4cxx/helpers/thread.h>
+#include <apr.h>
+
+using namespace log4cxx;
+using namespace log4cxx::net;
+using namespace log4cxx::helpers;
+
+#if APR_HAS_THREADS
+/**
+ Unit tests of log4cxx::SocketHubAppender
+ */
+class SocketHubAppenderTestCase : public AppenderSkeletonTestCase
+{
+ LOGUNIT_TEST_SUITE(SocketHubAppenderTestCase);
+ //
+ // tests inherited from AppenderSkeletonTestCase
+ //
+ LOGUNIT_TEST(testDefaultThreshold);
+ LOGUNIT_TEST(testSetOptionThreshold);
+ LOGUNIT_TEST(testActivateClose);
+ LOGUNIT_TEST(testActivateSleepClose);
+ LOGUNIT_TEST(testActivateWriteClose);
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+
+ AppenderSkeleton* createAppenderSkeleton() const {
+ return new log4cxx::net::SocketHubAppender();
+ }
+
+ void testActivateClose() {
+ SocketHubAppenderPtr hubAppender(new SocketHubAppender());
+ Pool p;
+ hubAppender->activateOptions(p);
+ hubAppender->close();
+ }
+
+ void testActivateSleepClose() {
+ SocketHubAppenderPtr hubAppender(new SocketHubAppender());
+ Pool p;
+ hubAppender->activateOptions(p);
+ Thread::sleep(1000);
+ hubAppender->close();
+ }
+
+
+ void testActivateWriteClose() {
+ SocketHubAppenderPtr hubAppender(new SocketHubAppender());
+ Pool p;
+ hubAppender->activateOptions(p);
+ LoggerPtr root(Logger::getRootLogger());
+ root->addAppender(hubAppender);
+ for(int i = 0; i < 50; i++) {
+ LOG4CXX_INFO(root, "Hello, World " << i);
+ }
+ hubAppender->close();
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(SocketHubAppenderTestCase);
+#endif
diff --git a/src/test/cpp/net/socketservertestcase.cpp b/src/test/cpp/net/socketservertestcase.cpp
new file mode 100644
index 0000000..ce4444f
--- /dev/null
+++ b/src/test/cpp/net/socketservertestcase.cpp
@@ -0,0 +1,481 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logger.h>
+#include <log4cxx/net/socketappender.h>
+#include <log4cxx/ndc.h>
+#include <log4cxx/mdc.h>
+#include <log4cxx/asyncappender.h>
+
+#include "socketservertestcase.h"
+#include "../util/compare.h"
+#include "../util/transformer.h"
+#include "../util/controlfilter.h"
+#include "../util/absolutedateandtimefilter.h"
+#include "../util/threadfilter.h"
+#include "../util/filenamefilter.h"
+#include <apr_time.h>
+#include <log4cxx/file.h>
+#include <iostream>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include "../testchar.h"
+#include "../logunit.h"
+#include <log4cxx/spi/loggerrepository.h>
+
+
+//Define INT64_C for compilers that don't have it
+#if (!defined(INT64_C))
+#define INT64_C(value) value ## LL
+#endif
+
+#if defined(WIN32) || defined(_WIN32)
+#include <windows.h>
+#endif
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::net;
+
+#define REGEX_STR(x) x
+// %5p %x [%t] %c %m%n
+// DEBUG T1 [thread] org.apache.log4j.net.SocketAppenderTestCase Message 1
+#define PAT1 \
+ REGEX_STR("^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) T1 \\[0x[0-9A-F]*]\\ ") \
+ REGEX_STR(".* Message [0-9]\\{1,2\\}")
+
+// DEBUG T2 [thread] patternlayouttest.cpp(?) Message 1
+#define PAT2 \
+ REGEX_STR("^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) T2 \\[0x[0-9A-F]*]\\ ") \
+ REGEX_STR(".*socketservertestcase.cpp\\([0-9]\\{1,4\\}\\) Message [0-9]\\{1,2\\}")
+
+// DEBUG T3 [thread] patternlayouttest.cpp(?) Message 1
+#define PAT3 \
+ REGEX_STR("^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) T3 \\[0x[0-9A-F]*]\\ ") \
+ REGEX_STR(".*socketservertestcase.cpp\\([0-9]\\{1,4\\}\\) Message [0-9]\\{1,2\\}")
+
+// DEBUG some T4 MDC-TEST4 [thread] SocketAppenderTestCase - Message 1
+// DEBUG some T4 MDC-TEST4 [thread] SocketAppenderTestCase - Message 1
+#define PAT4 \
+ REGEX_STR("^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some T4 MDC-TEST4 \\[0x[0-9A-F]*]\\") \
+ REGEX_STR(" (root|SocketServerTestCase) - Message [0-9]\\{1,2\\}")
+#define PAT5 \
+ REGEX_STR("^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some5 T5 MDC-TEST5 \\[0x[0-9A-F]*]\\") \
+ REGEX_STR(" (root|SocketServerTestCase) - Message [0-9]\\{1,2\\}")
+#define PAT6 \
+ REGEX_STR("^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some6 T6 client-test6 MDC-TEST6") \
+ REGEX_STR(" \\[0x[0-9A-F]*]\\ (root|SocketServerTestCase) - Message [0-9]\\{1,2\\}")
+#define PAT7 \
+ REGEX_STR("^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some7 T7 client-test7 MDC-TEST7") \
+ REGEX_STR(" \\[0x[0-9A-F]*]\\ (root|SocketServerTestCase) - Message [0-9]\\{1,2\\}")
+
+// DEBUG some8 T8 shortSocketServer MDC-TEST7 [thread] SocketServerTestCase - Message 1
+#define PAT8 \
+ REGEX_STR("^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some8 T8 shortSocketServer") \
+ REGEX_STR(" MDC-TEST8 \\[0x[0-9A-F]*]\\ (root|SocketServerTestCase) - Message [0-9]\\{1,2\\}")
+
+
+
+/**
+ * This test checks receipt of SocketAppender messages by the ShortSocketServer
+ * class from log4j. That class must be started externally to this class
+ * for this test to succeed.
+ */
+LOGUNIT_CLASS(SocketServerTestCase)
+{
+ LOGUNIT_TEST_SUITE(SocketServerTestCase);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST(test3);
+ LOGUNIT_TEST(test4);
+ LOGUNIT_TEST(test5);
+ LOGUNIT_TEST(test6);
+ LOGUNIT_TEST(test7);
+ LOGUNIT_TEST(test8);
+ LOGUNIT_TEST_SUITE_END();
+
+ SocketAppenderPtr socketAppender;
+ LoggerPtr logger;
+ LoggerPtr root;
+
+ class LineNumberFilter : public Filter {
+ public:
+ LineNumberFilter() {
+ patterns.push_back(PatternReplacement("cpp:[0-9]*", "cpp:XXX"));
+ }
+ };
+
+public:
+ void setUp()
+ {
+ logger = Logger::getLogger(LOG4CXX_STR("org.apache.log4j.net.SocketServerTestCase"));
+ root = Logger::getRootLogger();
+ }
+
+ void tearDown()
+ {
+ socketAppender = 0;
+ root->getLoggerRepository()->resetConfiguration();
+ logger = 0;
+ root = 0;
+ }
+
+ /**
+ The pattern on the server side: %5p %x [%t] %c %m%n.
+
+ We are testing NDC functionality across the wire.
+ */
+ void test1()
+ {
+ SocketAppenderPtr socketAppender1 =
+ new SocketAppender(LOG4CXX_STR("localhost"), PORT);
+ root->addAppender(socketAppender1);
+ common("test1", LOG4CXX_STR("T1"), LOG4CXX_STR("key1"), LOG4CXX_STR("MDC-TEST1"));
+ delay(1);
+
+ ControlFilter cf;
+ cf << PAT1;
+
+ ThreadFilter threadFilter;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&cf);
+ filters.push_back(&threadFilter);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/socketServer.1")));
+ }
+
+ void test2()
+ {
+ SocketAppenderPtr socketAppender1 =
+ new SocketAppender(LOG4CXX_STR("localhost"), PORT);
+ root->addAppender(socketAppender1);
+ common("test2", LOG4CXX_STR("T2"), LOG4CXX_STR("key2"), LOG4CXX_STR("MDC-TEST2"));
+ delay(1);
+
+ ControlFilter cf;
+ cf << PAT2;
+
+ ThreadFilter threadFilter;
+ LineNumberFilter lineNumberFilter;
+ LogString thisFile;
+ FilenameFilter filenameFilter(__FILE__, "socketservertestcase.cpp");
+
+ std::vector<Filter *> filters;
+ filters.push_back(&filenameFilter);
+ filters.push_back(&cf);
+ filters.push_back(&threadFilter);
+ filters.push_back(&lineNumberFilter);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/socketServer.2")));
+ }
+
+ void test3()
+ {
+ SocketAppenderPtr socketAppender1 =
+ new SocketAppender(LOG4CXX_STR("localhost"), PORT);
+ root->addAppender(socketAppender1);
+ common("test3", LOG4CXX_STR("T3"), LOG4CXX_STR("key3"), LOG4CXX_STR("MDC-TEST3"));
+ delay(1);
+
+ ControlFilter cf;
+ cf << PAT3;
+
+ ThreadFilter threadFilter;
+ LineNumberFilter lineNumberFilter;
+ LogString thisFile;
+ FilenameFilter filenameFilter(__FILE__, "socketservertestcase.cpp");
+
+ std::vector<Filter *> filters;
+ filters.push_back(&filenameFilter);
+ filters.push_back(&cf);
+ filters.push_back(&threadFilter);
+ filters.push_back(&lineNumberFilter);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/socketServer.3")));
+ }
+
+ void test4()
+ {
+ SocketAppenderPtr socketAppender1 =
+ new SocketAppender(LOG4CXX_STR("localhost"), PORT);
+ root->addAppender(socketAppender1);
+ NDC::push(LOG4CXX_TEST_STR("some"));
+ common("test4", LOG4CXX_STR("T4"), LOG4CXX_STR("key4"), LOG4CXX_STR("MDC-TEST4"));
+ NDC::pop();
+ delay(1);
+
+ ControlFilter cf;
+ cf << PAT4;
+
+ ThreadFilter threadFilter;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&cf);
+ filters.push_back(&threadFilter);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/socketServer.4")));
+ }
+
+ void test5()
+ {
+ SocketAppenderPtr socketAppender1 =
+ new SocketAppender(LOG4CXX_STR("localhost"), PORT);
+ AsyncAppenderPtr asyncAppender = new AsyncAppender();
+
+ root->addAppender(socketAppender1);
+ root->addAppender(asyncAppender);
+
+ NDC::push(LOG4CXX_TEST_STR("some5"));
+ common("test5", LOG4CXX_STR("T5"), LOG4CXX_STR("key5"), LOG4CXX_STR("MDC-TEST5"));
+ NDC::pop();
+ delay(2);
+
+ ControlFilter cf;
+ cf << PAT5;
+
+ ThreadFilter threadFilter;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&cf);
+ filters.push_back(&threadFilter);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/socketServer.5")));
+ }
+
+ void test6()
+ {
+ SocketAppenderPtr socketAppender1 =
+ new SocketAppender(LOG4CXX_STR("localhost"), PORT);
+ AsyncAppenderPtr asyncAppender = new AsyncAppender();
+
+ root->addAppender(socketAppender1);
+ root->addAppender(asyncAppender);
+
+ NDC::push(LOG4CXX_TEST_STR("some6"));
+ MDC::put(LOG4CXX_TEST_STR("hostID"), LOG4CXX_TEST_STR("client-test6"));
+ common("test6", LOG4CXX_STR("T6"), LOG4CXX_STR("key6"), LOG4CXX_STR("MDC-TEST6"));
+ NDC::pop();
+ MDC::remove(LOG4CXX_TEST_STR("hostID"));
+ delay(2);
+
+ ControlFilter cf;
+ cf << PAT6;
+
+ ThreadFilter threadFilter;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&cf);
+ filters.push_back(&threadFilter);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/socketServer.6")));
+ }
+
+ void test7()
+ {
+ SocketAppenderPtr socketAppender1 =
+ new SocketAppender(LOG4CXX_STR("localhost"), PORT);
+ AsyncAppenderPtr asyncAppender = new AsyncAppender();
+
+ root->addAppender(socketAppender1);
+ root->addAppender(asyncAppender);
+
+ NDC::push(LOG4CXX_TEST_STR("some7"));
+ MDC::put(LOG4CXX_TEST_STR("hostID"), LOG4CXX_TEST_STR("client-test7"));
+ common("test7", LOG4CXX_STR("T7"), LOG4CXX_STR("key7"), LOG4CXX_STR("MDC-TEST7"));
+ NDC::pop();
+ MDC::remove(LOG4CXX_TEST_STR("hostID"));
+ delay(2);
+
+ ControlFilter cf;
+ cf << PAT7;
+
+ ThreadFilter threadFilter;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&cf);
+ filters.push_back(&threadFilter);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/socketServer.7")));
+ }
+
+ void test8()
+ {
+ SocketAppenderPtr socketAppender1 =
+ new SocketAppender(LOG4CXX_STR("localhost"), PORT);
+
+ root->addAppender(socketAppender1);
+
+ NDC::push(LOG4CXX_TEST_STR("some8"));
+ common("test8", LOG4CXX_STR("T8"), LOG4CXX_STR("key8"), LOG4CXX_STR("MDC-TEST8"));
+ NDC::pop();
+ delay(2);
+
+ ControlFilter cf;
+ cf << PAT8;
+
+ ThreadFilter threadFilter;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&cf);
+ filters.push_back(&threadFilter);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/socketServer.8")));
+ }
+
+ void common(const std::string& testName, const LogString& dc, const LogString& key, const LogString& val)
+ {
+ int i = -1;
+ NDC::push(dc);
+ MDC::put(key, val);
+
+ logger->setLevel(Level::getDebug());
+ root->setLevel(Level::getDebug());
+
+ LOG4CXX_TRACE(logger, "Message " << i);
+ i++;
+
+ logger->setLevel(Level::getTrace());
+ root->setLevel(Level::getTrace());
+
+ LOG4CXX_TRACE(logger, "Message " << ++i);
+ LOG4CXX_TRACE(root, "Message " << ++i);
+
+ LOG4CXX_DEBUG(logger, "Message " << ++i);
+ LOG4CXX_DEBUG(root, "Message " << ++i);
+
+ LOG4CXX_INFO(logger, "Message " << ++i);
+ LOG4CXX_WARN(logger, "Message " << ++i);
+ LOG4CXX_FATAL(logger, "Message " << ++i); //5
+
+ std::string exceptionMsg("\njava.lang.Exception: Just testing\n"
+ "\tat org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)\n"
+ "\tat org.apache.log4j.net.SocketServerTestCase.");
+ exceptionMsg.append(testName);
+ exceptionMsg.append("(SocketServerTestCase.java:XXX)\n"
+ "\tat junit.framework.TestCase.runTest(TestCase.java:XXX)\n"
+ "\tat junit.framework.TestCase.runBare(TestCase.java:XXX)\n"
+ "\tat junit.framework.TestResult$1.protect(TestResult.java:XXX)\n"
+ "\tat junit.framework.TestResult.runProtected(TestResult.java:XXX)\n"
+ "\tat junit.framework.TestResult.run(TestResult.java:XXX)\n"
+ "\tat junit.framework.TestCase.run(TestCase.java:XXX)\n"
+ "\tat junit.framework.TestSuite.runTest(TestSuite.java:XXX)\n"
+ "\tat junit.framework.TestSuite.run(TestSuite.java:XXX)");
+
+
+ LOG4CXX_DEBUG(logger, "Message " << ++i << exceptionMsg);
+ LOG4CXX_ERROR(root, "Message " << ++i << exceptionMsg);
+
+ NDC::pop();
+ MDC::remove(key);
+ }
+
+ void delay(int secs)
+ {
+ apr_sleep(APR_USEC_PER_SEC * secs);
+ }
+
+ private:
+ static const File TEMP;
+ static const File FILTERED;
+};
+
+const File SocketServerTestCase::TEMP("output/temp");
+const File SocketServerTestCase::FILTERED("output/filtered");
+
+LOGUNIT_TEST_SUITE_REGISTRATION_DISABLED(SocketServerTestCase)
diff --git a/src/test/cpp/net/socketservertestcase.h b/src/test/cpp/net/socketservertestcase.h
new file mode 100644
index 0000000..ae285d9
--- /dev/null
+++ b/src/test/cpp/net/socketservertestcase.h
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_NET_SOCKETSERVER_TESTCASE_H
+#define _LOG4CXX_NET_SOCKETSERVER_TESTCASE_H
+
+#define PORT 12345
+
+#endif //_LOG4CXX_NET_SOCKETSERVER_TESTCASE_H
diff --git a/src/test/cpp/net/syslogappendertestcase.cpp b/src/test/cpp/net/syslogappendertestcase.cpp
new file mode 100644
index 0000000..b2b723c
--- /dev/null
+++ b/src/test/cpp/net/syslogappendertestcase.cpp
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/datagramsocket.h>
+#include <log4cxx/net/syslogappender.h>
+#include "../appenderskeletontestcase.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+/**
+ Unit tests of log4cxx::SyslogAppender
+ */
+class SyslogAppenderTestCase : public AppenderSkeletonTestCase
+{
+ LOGUNIT_TEST_SUITE(SyslogAppenderTestCase);
+ //
+ // tests inherited from AppenderSkeletonTestCase
+ //
+ LOGUNIT_TEST(testDefaultThreshold);
+ LOGUNIT_TEST(testSetOptionThreshold);
+
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+
+ AppenderSkeleton* createAppenderSkeleton() const {
+ return new log4cxx::net::SyslogAppender();
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(SyslogAppenderTestCase);
diff --git a/src/test/cpp/net/telnetappendertestcase.cpp b/src/test/cpp/net/telnetappendertestcase.cpp
new file mode 100644
index 0000000..394571b
--- /dev/null
+++ b/src/test/cpp/net/telnetappendertestcase.cpp
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/net/telnetappender.h>
+#include <log4cxx/ttcclayout.h>
+#include "../appenderskeletontestcase.h"
+#include <apr_thread_proc.h>
+#include <apr_time.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::net;
+
+#if APR_HAS_THREADS
+/**
+ Unit tests of log4cxx::TelnetAppender
+ */
+class TelnetAppenderTestCase : public AppenderSkeletonTestCase
+{
+ LOGUNIT_TEST_SUITE(TelnetAppenderTestCase);
+ //
+ // tests inherited from AppenderSkeletonTestCase
+ //
+ LOGUNIT_TEST(testDefaultThreshold);
+ LOGUNIT_TEST(testSetOptionThreshold);
+ LOGUNIT_TEST(testActivateClose);
+ LOGUNIT_TEST(testActivateSleepClose);
+ LOGUNIT_TEST(testActivateWriteClose);
+
+ LOGUNIT_TEST_SUITE_END();
+
+ enum { TEST_PORT = 1723 };
+
+public:
+
+ AppenderSkeleton* createAppenderSkeleton() const {
+ return new log4cxx::net::TelnetAppender();
+ }
+
+ void testActivateClose() {
+ TelnetAppenderPtr appender(new TelnetAppender());
+ appender->setLayout(new TTCCLayout());
+ appender->setPort(TEST_PORT);
+ Pool p;
+ appender->activateOptions(p);
+ appender->close();
+ }
+
+ void testActivateSleepClose() {
+ TelnetAppenderPtr appender(new TelnetAppender());
+ appender->setLayout(new TTCCLayout());
+ appender->setPort(TEST_PORT);
+ Pool p;
+ appender->activateOptions(p);
+ Thread::sleep(1000);
+ appender->close();
+ }
+
+ void testActivateWriteClose() {
+ TelnetAppenderPtr appender(new TelnetAppender());
+ appender->setLayout(new TTCCLayout());
+ appender->setPort(TEST_PORT);
+ Pool p;
+ appender->activateOptions(p);
+ LoggerPtr root(Logger::getRootLogger());
+ root->addAppender(appender);
+ for (int i = 0; i < 50; i++) {
+ LOG4CXX_INFO(root, "Hello, World " << i);
+ }
+ appender->close();
+ }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(TelnetAppenderTestCase);
+#endif
diff --git a/src/test/cpp/net/xmlsocketappendertestcase.cpp b/src/test/cpp/net/xmlsocketappendertestcase.cpp
new file mode 100644
index 0000000..caf0008
--- /dev/null
+++ b/src/test/cpp/net/xmlsocketappendertestcase.cpp
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/net/xmlsocketappender.h>
+#include "../appenderskeletontestcase.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+#if APR_HAS_THREADS
+/**
+ Unit tests of log4cxx::net::XMLSocketAppender
+ */
+class XMLSocketAppenderTestCase : public AppenderSkeletonTestCase
+{
+ LOGUNIT_TEST_SUITE(XMLSocketAppenderTestCase);
+ //
+ // tests inherited from AppenderSkeletonTestCase
+ //
+ LOGUNIT_TEST(testDefaultThreshold);
+ LOGUNIT_TEST(testSetOptionThreshold);
+
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+
+ AppenderSkeleton* createAppenderSkeleton() const {
+ return new log4cxx::net::XMLSocketAppender();
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(XMLSocketAppenderTestCase);
+#endif
diff --git a/src/test/cpp/nt/nteventlogappendertestcase.cpp b/src/test/cpp/nt/nteventlogappendertestcase.cpp
new file mode 100644
index 0000000..5e8c6ff
--- /dev/null
+++ b/src/test/cpp/nt/nteventlogappendertestcase.cpp
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(_WIN32) && !defined(_WIN32_WCE)
+#include <log4cxx/nt/nteventlogappender.h>
+#include "../appenderskeletontestcase.h"
+#include "windows.h"
+#include <log4cxx/logger.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/patternlayout.h>
+#include "../insertwide.h"
+#include "../logunit.h"
+#include <log4cxx/helpers/date.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::nt;
+using namespace log4cxx::spi;
+
+/**
+ Unit tests of log4cxx::nt::NTEventLogAppender
+ */
+class NTEventLogAppenderTestCase : public AppenderSkeletonTestCase
+{
+ LOGUNIT_TEST_SUITE(NTEventLogAppenderTestCase);
+ //
+ // tests inherited from AppenderSkeletonTestCase
+ //
+ LOGUNIT_TEST(testDefaultThreshold);
+ LOGUNIT_TEST(testSetOptionThreshold);
+ LOGUNIT_TEST(testHelloWorld);
+
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+
+ AppenderSkeleton* createAppenderSkeleton() const {
+ return new log4cxx::nt::NTEventLogAppender();
+ }
+
+ void testHelloWorld() {
+ DWORD expectedId = 1;
+ HANDLE hEventLog = ::OpenEventLogW(NULL, L"log4cxx_test");
+ if (hEventLog != NULL) {
+ BOOL stat = GetNumberOfEventLogRecords(hEventLog, &expectedId);
+ DWORD oldest;
+ if(stat) stat = GetOldestEventLogRecord(hEventLog, &oldest);
+ CloseEventLog(hEventLog);
+ LOGUNIT_ASSERT(stat);
+ expectedId += oldest;
+ }
+
+
+ Pool p;
+ Date now;
+ DWORD expectedTime = now.getTime() / Date::getMicrosecondsPerSecond();
+ {
+ NTEventLogAppenderPtr appender(new NTEventLogAppender());
+ appender->setSource(LOG4CXX_STR("log4cxx_test"));
+ LayoutPtr layout(new PatternLayout(LOG4CXX_STR("%c - %m%n")));
+ appender->setLayout(layout);
+ appender->activateOptions(p);
+
+ LoggingEventPtr event(new LoggingEvent(
+ LOG4CXX_STR("org.foobar"), Level::getInfo(), LOG4CXX_STR("Hello, World"), LOG4CXX_LOCATION));
+ appender->doAppend(event, p);
+ }
+ hEventLog = ::OpenEventLogW(NULL, L"log4cxx_test");
+ LOGUNIT_ASSERT(hEventLog != NULL);
+ DWORD actualId;
+ BOOL stat = GetNumberOfEventLogRecords(hEventLog, &actualId);
+ DWORD oldest;
+ if (stat) stat = GetOldestEventLogRecord(hEventLog, &oldest);
+ actualId += oldest;
+ actualId--;
+ CloseEventLog(hEventLog);
+ LOGUNIT_ASSERT(stat);
+ LOGUNIT_ASSERT_EQUAL(expectedId, actualId);
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(NTEventLogAppenderTestCase);
+#endif
diff --git a/src/test/cpp/pattern/num343patternconverter.cpp b/src/test/cpp/pattern/num343patternconverter.cpp
new file mode 100644
index 0000000..fa756c5
--- /dev/null
+++ b/src/test/cpp/pattern/num343patternconverter.cpp
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <log4cxx/logstring.h>
+#include "num343patternconverter.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::pattern;
+
+IMPLEMENT_LOG4CXX_OBJECT(Num343PatternConverter)
+
+
+Num343PatternConverter::Num343PatternConverter() :
+ LoggingEventPatternConverter(LOG4CXX_STR("Num343"), LOG4CXX_STR("num343")) {
+}
+
+PatternConverterPtr Num343PatternConverter::newInstance(
+ const std::vector<LogString>&) {
+ return new Num343PatternConverter();
+}
+
+
+void Num343PatternConverter::format(
+ const spi::LoggingEventPtr&,
+ LogString& sbuf,
+ Pool&) const
+{
+ sbuf.append(LOG4CXX_STR("343"));
+}
+
diff --git a/src/test/cpp/pattern/num343patternconverter.h b/src/test/cpp/pattern/num343patternconverter.h
new file mode 100644
index 0000000..0e2f75b
--- /dev/null
+++ b/src/test/cpp/pattern/num343patternconverter.h
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/pattern/loggingeventpatternconverter.h>
+#include <vector>
+
+namespace log4cxx
+{
+ namespace pattern {
+ class Num343PatternConverter : public LoggingEventPatternConverter
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(Num343PatternConverter)
+
+ Num343PatternConverter();
+ static PatternConverterPtr newInstance(
+ const std::vector<LogString>& options);
+
+ protected:
+ void format(
+ const log4cxx::spi::LoggingEventPtr& event,
+ LogString& toAppendTo,
+ log4cxx::helpers::Pool& pool) const;
+ };
+ }
+}
diff --git a/src/test/cpp/pattern/patternparsertestcase.cpp b/src/test/cpp/pattern/patternparsertestcase.cpp
new file mode 100644
index 0000000..f304252
--- /dev/null
+++ b/src/test/cpp/pattern/patternparsertestcase.cpp
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logger.h>
+#include <log4cxx/spi/loggingevent.h>
+#include <log4cxx/helpers/system.h>
+#include <log4cxx/level.h>
+
+#include "num343patternconverter.h"
+#include "../testchar.h"
+#include "../insertwide.h"
+#include "../logunit.h"
+#include <log4cxx/spi/loggerrepository.h>
+#include <log4cxx/pattern/patternparser.h>
+#include <log4cxx/pattern/patternconverter.h>
+#include <log4cxx/helpers/relativetimedateformat.h>
+#include <log4cxx/helpers/simpledateformat.h>
+
+
+#include <log4cxx/pattern/loggerpatternconverter.h>
+#include <log4cxx/pattern/literalpatternconverter.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/pattern/classnamepatternconverter.h>
+#include <log4cxx/pattern/datepatternconverter.h>
+#include <log4cxx/pattern/filedatepatternconverter.h>
+#include <log4cxx/pattern/filelocationpatternconverter.h>
+#include <log4cxx/pattern/fulllocationpatternconverter.h>
+#include <log4cxx/pattern/integerpatternconverter.h>
+#include <log4cxx/pattern/linelocationpatternconverter.h>
+#include <log4cxx/pattern/messagepatternconverter.h>
+#include <log4cxx/pattern/lineseparatorpatternconverter.h>
+#include <log4cxx/pattern/methodlocationpatternconverter.h>
+#include <log4cxx/pattern/levelpatternconverter.h>
+#include <log4cxx/pattern/relativetimepatternconverter.h>
+#include <log4cxx/pattern/threadpatternconverter.h>
+#include <log4cxx/pattern/ndcpatternconverter.h>
+#include <log4cxx/pattern/propertiespatternconverter.h>
+#include <log4cxx/pattern/throwableinformationpatternconverter.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+using namespace log4cxx::pattern;
+
+#define RULES_PUT(spec, cls) \
+map.insert(PatternMap::value_type(LOG4CXX_STR(spec), (PatternConstructor) cls ::newInstance))
+
+
+LOGUNIT_CLASS(PatternParserTestCase)
+{
+ LOGUNIT_TEST_SUITE(PatternParserTestCase);
+ LOGUNIT_TEST(testNewWord);
+ LOGUNIT_TEST(testNewWord2);
+ LOGUNIT_TEST(testBogusWord1);
+ LOGUNIT_TEST(testBogusWord2);
+ LOGUNIT_TEST(testBasic1);
+ LOGUNIT_TEST(testBasic2);
+ LOGUNIT_TEST(testMultiOption);
+ LOGUNIT_TEST_SUITE_END();
+
+ LoggingEventPtr event;
+
+public:
+ void setUp()
+ {
+ event = new LoggingEvent(
+ LOG4CXX_STR("org.foobar"), Level::getInfo(), LOG4CXX_STR("msg 1"), LOG4CXX_LOCATION);
+ }
+
+ void tearDown()
+ {
+ }
+
+
+ PatternMap getFormatSpecifiers() {
+ PatternMap map;
+ RULES_PUT("c", LoggerPatternConverter);
+ RULES_PUT("logger", LoggerPatternConverter);
+
+ RULES_PUT("C", ClassNamePatternConverter);
+ RULES_PUT("class", ClassNamePatternConverter);
+
+ RULES_PUT("d", DatePatternConverter);
+ RULES_PUT("date", DatePatternConverter);
+
+ RULES_PUT("F", FileLocationPatternConverter);
+ RULES_PUT("file", FileLocationPatternConverter);
+
+ RULES_PUT("l", FullLocationPatternConverter);
+
+ RULES_PUT("L", LineLocationPatternConverter);
+ RULES_PUT("line", LineLocationPatternConverter);
+
+ RULES_PUT("m", MessagePatternConverter);
+ RULES_PUT("message", MessagePatternConverter);
+
+ RULES_PUT("n", LineSeparatorPatternConverter);
+
+ RULES_PUT("M", MethodLocationPatternConverter);
+ RULES_PUT("method", MethodLocationPatternConverter);
+
+ RULES_PUT("p", LevelPatternConverter);
+ RULES_PUT("level", LevelPatternConverter);
+
+ RULES_PUT("r", RelativeTimePatternConverter);
+ RULES_PUT("relative", RelativeTimePatternConverter);
+
+ RULES_PUT("t", ThreadPatternConverter);
+ RULES_PUT("thread", ThreadPatternConverter);
+
+ RULES_PUT("x", NDCPatternConverter);
+ RULES_PUT("ndc", NDCPatternConverter);
+
+ RULES_PUT("X", PropertiesPatternConverter);
+ RULES_PUT("properties", PropertiesPatternConverter);
+
+ RULES_PUT("throwable", ThrowableInformationPatternConverter);
+
+ return map;
+
+ }
+
+ void assertFormattedEquals(const LogString& pattern,
+ const PatternMap& patternMap,
+ const LogString& expected) {
+ std::vector<PatternConverterPtr> converters;
+ std::vector<FormattingInfoPtr> fields;
+ PatternParser::parse(pattern, converters, fields, patternMap);
+ Pool p;
+ LogString actual;
+ std::vector<FormattingInfoPtr>::const_iterator fieldIter = fields.begin();
+ for(std::vector<PatternConverterPtr>::const_iterator converterIter = converters.begin();
+ converterIter != converters.end();
+ converterIter++, fieldIter++) {
+ int fieldStart = actual.length();
+ (*converterIter)->format(event, actual, p);
+ (*fieldIter)->format(fieldStart, actual);
+ }
+ LOGUNIT_ASSERT_EQUAL(expected, actual);
+ }
+
+
+ void testNewWord() {
+ PatternMap testRules(getFormatSpecifiers());
+ testRules.insert(
+ PatternMap::value_type(LOG4CXX_STR("z343"),
+ (PatternConstructor) Num343PatternConverter::newInstance));
+ assertFormattedEquals(LOG4CXX_STR("%z343"), testRules, LOG4CXX_STR("343"));
+ }
+
+
+ /* Test whether words starting with the letter 'n' are treated differently,
+ * which was previously the case by mistake.
+ */
+ void testNewWord2() {
+ PatternMap testRules(getFormatSpecifiers());
+ testRules.insert(
+ PatternMap::value_type(LOG4CXX_STR("n343"),
+ (PatternConstructor) Num343PatternConverter::newInstance));
+ assertFormattedEquals(LOG4CXX_STR("%n343"), testRules, LOG4CXX_STR("343"));
+ }
+
+ void testBogusWord1() {
+ assertFormattedEquals(LOG4CXX_STR("%, foobar"),
+ getFormatSpecifiers(),
+ LOG4CXX_STR("%, foobar"));
+ }
+
+ void testBogusWord2() {
+ assertFormattedEquals(LOG4CXX_STR("xyz %, foobar"),
+ getFormatSpecifiers(),
+ LOG4CXX_STR("xyz %, foobar"));
+ }
+
+ void testBasic1() {
+ assertFormattedEquals(LOG4CXX_STR("hello %-5level - %m%n"),
+ getFormatSpecifiers(),
+ LogString(LOG4CXX_STR("hello INFO - msg 1")) + LOG4CXX_EOL);
+ }
+
+ void testBasic2() {
+ Pool pool;
+ RelativeTimeDateFormat relativeFormat;
+ LogString expected;
+ relativeFormat.format(expected, event->getTimeStamp(), pool);
+
+ expected.append(LOG4CXX_STR(" INFO ["));
+ expected.append(event->getThreadName());
+ expected.append(LOG4CXX_STR("] org.foobar - msg 1"));
+ expected.append(LOG4CXX_EOL);
+
+ assertFormattedEquals(LOG4CXX_STR("%relative %-5level [%thread] %logger - %m%n"),
+ getFormatSpecifiers(),
+ expected);
+ }
+
+ void testMultiOption() {
+ Pool pool;
+
+ SimpleDateFormat dateFormat(LOG4CXX_STR("HH:mm:ss"));
+ LogString localTime;
+ dateFormat.format(localTime, event->getTimeStamp(), pool);
+
+ dateFormat.setTimeZone(TimeZone::getGMT());
+ LogString utcTime;
+ dateFormat.format(utcTime, event->getTimeStamp(), pool);
+
+ LogString expected(utcTime);
+ expected.append(1, LOG4CXX_STR(' '));
+ expected.append(localTime);
+ expected.append(LOG4CXX_STR(" org.foobar - msg 1"));
+
+
+ assertFormattedEquals(LOG4CXX_STR("%d{HH:mm:ss}{GMT} %d{HH:mm:ss} %c - %m"),
+ getFormatSpecifiers(),
+ expected);
+ }
+
+};
+
+//
+// See bug LOGCXX-204
+//
+#if !defined(_MSC_VER) || _MSC_VER > 1200
+LOGUNIT_TEST_SUITE_REGISTRATION(PatternParserTestCase);
+#endif
diff --git a/src/test/cpp/patternlayouttest.cpp b/src/test/cpp/patternlayouttest.cpp
new file mode 100644
index 0000000..9c3818f
--- /dev/null
+++ b/src/test/cpp/patternlayouttest.cpp
@@ -0,0 +1,547 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logger.h>
+#include <log4cxx/propertyconfigurator.h>
+#include <log4cxx/mdc.h>
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/fileappender.h>
+
+#include "util/compare.h"
+#include "util/transformer.h"
+#include "util/absolutedateandtimefilter.h"
+#include "util/iso8601filter.h"
+#include "util/absolutetimefilter.h"
+#include "util/relativetimefilter.h"
+#include "util/controlfilter.h"
+#include "util/threadfilter.h"
+#include "util/linenumberfilter.h"
+#include "util/filenamefilter.h"
+#include <iostream>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/pool.h>
+#include <apr_strings.h>
+#include <log4cxx/helpers/pool.h>
+#include "testchar.h"
+#include "logunit.h"
+#include <log4cxx/spi/loggerrepository.h>
+#include <log4cxx/helpers/stringhelper.h>
+
+
+#define REGEX_STR(x) x
+#define PAT0 REGEX_STR("\\[[0-9A-FXx]*]\\ (DEBUG|INFO|WARN|ERROR|FATAL) .* - Message [0-9]\\{1,2\\}")
+#define PAT1 ISO8601_PAT REGEX_STR(" ") PAT0
+#define PAT2 ABSOLUTE_DATE_AND_TIME_PAT REGEX_STR(" ") PAT0
+#define PAT3 ABSOLUTE_TIME_PAT REGEX_STR(" ") PAT0
+#define PAT4 RELATIVE_TIME_PAT REGEX_STR(" ") PAT0
+#define PAT5 REGEX_STR("\\[[0-9A-FXx]*]\\ (DEBUG|INFO|WARN|ERROR|FATAL) .* : Message [0-9]\\{1,2\\}")
+#define PAT6 REGEX_STR("\\[[0-9A-FXx]*]\\ (DEBUG|INFO |WARN |ERROR|FATAL) .*patternlayouttest.cpp\\([0-9]\\{1,4\\}\\): Message [0-9]\\{1,3\\}")
+#define PAT11a REGEX_STR("^(DEBUG|INFO |WARN |ERROR|FATAL) \\[[0-9A-FXx]*]\\ log4j.PatternLayoutTest: Message [0-9]\\{1,2\\}")
+#define PAT11b REGEX_STR("^(DEBUG|INFO |WARN |ERROR|FATAL) \\[[0-9A-FXx]*]\\ root: Message [0-9]\\{1,2\\}")
+#define PAT12 REGEX_STR("^\\[[0-9A-FXx]*]\\ (DEBUG|INFO |WARN |ERROR|FATAL) ")\
+ REGEX_STR(".*patternlayouttest.cpp([0-9]\\{1,4\\}): ")\
+ REGEX_STR("Message [0-9]\\{1,2\\}")
+#define PAT_MDC_1 REGEX_STR("")
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+LOGUNIT_CLASS(PatternLayoutTest)
+{
+ LOGUNIT_TEST_SUITE(PatternLayoutTest);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST(test3);
+ LOGUNIT_TEST(test4);
+ LOGUNIT_TEST(test5);
+ LOGUNIT_TEST(test6);
+ LOGUNIT_TEST(test7);
+ LOGUNIT_TEST(test8);
+ LOGUNIT_TEST(test9);
+ LOGUNIT_TEST(test10);
+ LOGUNIT_TEST(test11);
+ LOGUNIT_TEST(test12);
+ LOGUNIT_TEST(testMDC1);
+ LOGUNIT_TEST(testMDC2);
+ LOGUNIT_TEST_SUITE_END();
+
+ LoggerPtr root;
+ LoggerPtr logger;
+
+public:
+ void setUp()
+ {
+ root = Logger::getRootLogger();
+ MDC::clear();
+ logger = Logger::getLogger(LOG4CXX_TEST_STR("java.org.apache.log4j.PatternLayoutTest"));
+ }
+
+ void tearDown()
+ {
+ MDC::clear();
+ root->getLoggerRepository()->resetConfiguration();
+ }
+
+ void test1()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout1.properties"));
+ common();
+ LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/patternLayout.1")));
+ }
+
+ void test2()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout2.properties"));
+ common();
+
+ ControlFilter filter1;
+ filter1 << PAT1;
+ ISO8601Filter filter2;
+ ThreadFilter filter3;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&filter1);
+ filters.push_back(&filter2);
+ filters.push_back(&filter3);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/patternLayout.2")));
+ }
+
+ void test3()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout3.properties"));
+ common();
+
+ ControlFilter filter1;
+ filter1 << PAT1;
+ ISO8601Filter filter2;
+ ThreadFilter filter3;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&filter1);
+ filters.push_back(&filter2);
+ filters.push_back(&filter3);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/patternLayout.3")));
+ }
+
+ // Output format:
+ // 06 avr. 2002 18:30:58,937 [12345] DEBUG atternLayoutTest - Message 0
+ void test4()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout4.properties"));
+ common();
+
+ ControlFilter filter1;
+ filter1 << PAT2;
+ AbsoluteDateAndTimeFilter filter2;
+ ThreadFilter filter3;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&filter1);
+ filters.push_back(&filter2);
+ filters.push_back(&filter3);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/patternLayout.4")));
+ }
+
+ void test5()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout5.properties"));
+ common();
+
+ ControlFilter filter1;
+ filter1 << PAT2;
+ AbsoluteDateAndTimeFilter filter2;
+ ThreadFilter filter3;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&filter1);
+ filters.push_back(&filter2);
+ filters.push_back(&filter3);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/patternLayout.5")));
+ }
+
+ void test6()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout6.properties"));
+ common();
+
+ ControlFilter filter1;
+ filter1 << PAT3;
+ AbsoluteTimeFilter filter2;
+ ThreadFilter filter3;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&filter1);
+ filters.push_back(&filter2);
+ filters.push_back(&filter3);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/patternLayout.6")));
+ }
+
+ void test7()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout7.properties"));
+ common();
+
+ ControlFilter filter1;
+ filter1 << PAT3;
+ AbsoluteTimeFilter filter2;
+ ThreadFilter filter3;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&filter1);
+ filters.push_back(&filter2);
+ filters.push_back(&filter3);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/patternLayout.7")));
+ }
+
+ void test8()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout8.properties"));
+ common();
+
+
+ ControlFilter filter1;
+ filter1 << PAT4;
+ //
+ // combo of relative time and thread identifier
+ // (the \\\\1 preserve a leading space)
+ Filter filter2(".*]", "[main]");
+
+ std::vector<Filter *> filters;
+
+ filters.push_back(&filter1);
+ filters.push_back(&filter2);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/patternLayout.8")));
+ }
+
+ void test9()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout9.properties"));
+ common();
+
+ ControlFilter filter1;
+ filter1 << PAT5;
+ ThreadFilter filter2;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&filter1);
+ filters.push_back(&filter2);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/patternLayout.9")));
+ }
+
+ void test10()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout10.properties"));
+ common();
+
+ ControlFilter filter1;
+ filter1 << PAT6;
+ ThreadFilter filter2;
+ LineNumberFilter filter3;
+ FilenameFilter filenameFilter(__FILE__, "patternlayouttest.cpp");
+
+
+ std::vector<Filter *> filters;
+ filters.push_back(&filenameFilter);
+ filters.push_back(&filter1);
+ filters.push_back(&filter2);
+ filters.push_back(&filter3);
+
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/patternLayout.10")));
+ }
+
+ void test11()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout11.properties"));
+ common();
+
+ ControlFilter filter1;
+ filter1 << PAT11a << PAT11b;
+ ThreadFilter filter2;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&filter1);
+ filters.push_back(&filter2);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/patternLayout.11")));
+ }
+
+ void test12()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout12.properties"));
+ common();
+
+ ControlFilter filter1;
+ filter1 << PAT12;
+ ThreadFilter filter2;
+ LineNumberFilter filter3;
+ FilenameFilter filenameFilter(__FILE__, "patternlayouttest.cpp");
+
+ std::vector<Filter *> filters;
+ filters.push_back(&filenameFilter);
+ filters.push_back(&filter1);
+ filters.push_back(&filter2);
+ filters.push_back(&filter3);
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, LOG4CXX_FILE("witness/patternLayout.12")));
+ }
+
+ void testMDC1()
+ {
+ PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout.mdc.1.properties"));
+ MDC::put(LOG4CXX_TEST_STR("key1"), LOG4CXX_TEST_STR("va11"));
+ MDC::put(LOG4CXX_TEST_STR("key2"), LOG4CXX_TEST_STR("va12"));
+ logger->debug(LOG4CXX_TEST_STR("Hello World"));
+ MDC::clear();
+
+ LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/patternLayout.mdc.1")));
+ }
+
+ void testMDC2()
+ {
+ LogString OUTPUT_FILE = LOG4CXX_STR("output/patternLayout.mdc.2");
+ File WITNESS_FILE = LOG4CXX_FILE("witness/patternLayout.mdc.2");
+
+ LogString mdcMsgPattern1 = LOG4CXX_STR("%m : %X%n");
+ LogString mdcMsgPattern2 = LOG4CXX_STR("%m : %X{key1}%n");
+ LogString mdcMsgPattern3 = LOG4CXX_STR("%m : %X{key2}%n");
+ LogString mdcMsgPattern4 = LOG4CXX_STR("%m : %X{key3}%n");
+ LogString mdcMsgPattern5 = LOG4CXX_STR("%m : %X{key1},%X{key2},%X{key3}%n");
+
+ // set up appender
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%m%n"));
+ AppenderPtr appender = new FileAppender(layout, OUTPUT_FILE, false);
+
+ // set appender on root and set level to debug
+ root->addAppender(appender);
+ root->setLevel(Level::getDebug());
+
+ // output starting message
+ root->debug(LOG4CXX_TEST_STR("starting mdc pattern test"));
+
+ layout->setConversionPattern(mdcMsgPattern1);
+ log4cxx::helpers::Pool pool;
+ layout->activateOptions(pool);
+ root->debug(LOG4CXX_TEST_STR("empty mdc, no key specified in pattern"));
+
+ layout->setConversionPattern(mdcMsgPattern2);
+ layout->activateOptions(pool);
+ root->debug(LOG4CXX_TEST_STR("empty mdc, key1 in pattern"));
+
+ layout->setConversionPattern(mdcMsgPattern3);
+ layout->activateOptions(pool);
+ root->debug(LOG4CXX_TEST_STR("empty mdc, key2 in pattern"));
+
+ layout->setConversionPattern(mdcMsgPattern4);
+ layout->activateOptions(pool);
+ root->debug(LOG4CXX_TEST_STR("empty mdc, key3 in pattern"));
+
+ layout->setConversionPattern(mdcMsgPattern5);
+ layout->activateOptions(pool);
+ root->debug(LOG4CXX_TEST_STR("empty mdc, key1, key2, and key3 in pattern"));
+
+ MDC::put(LOG4CXX_TEST_STR("key1"), LOG4CXX_TEST_STR("value1"));
+ MDC::put(LOG4CXX_TEST_STR("key2"), LOG4CXX_TEST_STR("value2"));
+
+ layout->setConversionPattern(mdcMsgPattern1);
+ layout->activateOptions(pool);
+ root->debug(LOG4CXX_TEST_STR("filled mdc, no key specified in pattern"));
+
+ layout->setConversionPattern(mdcMsgPattern2);
+ layout->activateOptions(pool);
+ root->debug(LOG4CXX_TEST_STR("filled mdc, key1 in pattern"));
+
+ layout->setConversionPattern(mdcMsgPattern3);
+ layout->activateOptions(pool);
+ root->debug(LOG4CXX_TEST_STR("filled mdc, key2 in pattern"));
+
+ layout->setConversionPattern(mdcMsgPattern4);
+ layout->activateOptions(pool);
+ root->debug(LOG4CXX_TEST_STR("filled mdc, key3 in pattern"));
+
+ layout->setConversionPattern(mdcMsgPattern5);
+ layout->activateOptions(pool);
+ root->debug(LOG4CXX_TEST_STR("filled mdc, key1, key2, and key3 in pattern"));
+
+ MDC::remove(LOG4CXX_TEST_STR("key1"));
+ MDC::remove(LOG4CXX_TEST_STR("key2"));
+
+ layout->setConversionPattern(LOG4CXX_STR("%m%n"));
+ layout->activateOptions(pool);
+ root->debug(LOG4CXX_TEST_STR("finished mdc pattern test"));
+
+ LOGUNIT_ASSERT(Compare::compare(OUTPUT_FILE, WITNESS_FILE));
+ }
+
+ std::string createMessage(Pool& pool, int i) {
+ std::string msg("Message ");
+ msg.append(pool.itoa(i));
+ return msg;
+ }
+
+ void common()
+ {
+ int i = -1;
+
+ Pool pool;
+
+
+ LOG4CXX_DEBUG(logger, createMessage(pool, ++i));
+ LOG4CXX_DEBUG(root, createMessage(pool, i));
+
+ LOG4CXX_INFO(logger, createMessage(pool, ++i));
+ LOG4CXX_INFO(root, createMessage(pool, i));
+
+ LOG4CXX_WARN(logger, createMessage(pool, ++i));
+ LOG4CXX_WARN(root, createMessage(pool, i));
+
+ LOG4CXX_ERROR(logger, createMessage(pool, ++i));
+ LOG4CXX_ERROR(root, createMessage(pool, i));
+
+ LOG4CXX_FATAL(logger, createMessage(pool, ++i));
+ LOG4CXX_FATAL(root, createMessage(pool, i));
+ }
+
+private:
+ static const LogString FILTERED;
+ static const LogString TEMP;
+
+};
+
+const LogString PatternLayoutTest::TEMP(LOG4CXX_STR("output/temp"));
+const LogString PatternLayoutTest::FILTERED(LOG4CXX_STR("output/filtered"));
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(PatternLayoutTest);
diff --git a/src/test/cpp/propertyconfiguratortest.cpp b/src/test/cpp/propertyconfiguratortest.cpp
new file mode 100644
index 0000000..c93c363
--- /dev/null
+++ b/src/test/cpp/propertyconfiguratortest.cpp
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/helpers/properties.h>
+#include <log4cxx/propertyconfigurator.h>
+#include <log4cxx/logmanager.h>
+#include "vectorappender.h"
+#include "logunit.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+LOGUNIT_CLASS(PropertyConfiguratorTest)
+{
+ LOGUNIT_TEST_SUITE(PropertyConfiguratorTest);
+ LOGUNIT_TEST(testInherited);
+ LOGUNIT_TEST(testNull);
+ LOGUNIT_TEST(testAppenderThreshold);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ void testInherited() {
+ Properties props;
+ props.put(LOG4CXX_STR("log4j.rootLogger"),LOG4CXX_STR("DEBUG,VECTOR1"));
+ props.put(LOG4CXX_STR("log4j.logger.org.apache.log4j.PropertyConfiguratorTest"), LOG4CXX_STR("inherited,VECTOR2"));
+ props.put(LOG4CXX_STR("log4j.appender.VECTOR1"), LOG4CXX_STR("org.apache.log4j.VectorAppender"));
+ props.put(LOG4CXX_STR("log4j.appender.VECTOR2"), LOG4CXX_STR("org.apache.log4j.VectorAppender"));
+ PropertyConfigurator::configure(props);
+ LoggerPtr logger = Logger::getLogger("org.apache.log4j.PropertyConfiguratorTest");
+ LOGUNIT_ASSERT_EQUAL((int) Level::DEBUG_INT,
+ logger->getEffectiveLevel()->toInt());
+ Logger::getRootLogger()->setLevel(Level::getError());
+ LOGUNIT_ASSERT_EQUAL((int) Level::ERROR_INT,
+ logger->getEffectiveLevel()->toInt());
+ LogManager::resetConfiguration();
+ }
+
+ void testNull() {
+ Properties props;
+ props.put(LOG4CXX_STR("log4j.rootLogger"),LOG4CXX_STR("DEBUG,VECTOR1"));
+ props.put(LOG4CXX_STR("log4j.logger.org.apache.log4j.PropertyConfiguratorTest"), LOG4CXX_STR("NuLL,VECTOR2"));
+ props.put(LOG4CXX_STR("log4j.appender.VECTOR1"), LOG4CXX_STR("org.apache.log4j.VectorAppender"));
+ props.put(LOG4CXX_STR("log4j.appender.VECTOR2"), LOG4CXX_STR("org.apache.log4j.VectorAppender"));
+ PropertyConfigurator::configure(props);
+ LoggerPtr logger = Logger::getLogger("org.apache.log4j.PropertyConfiguratorTest");
+ LOGUNIT_ASSERT_EQUAL((int) Level::DEBUG_INT,
+ logger->getEffectiveLevel()->toInt());
+ Logger::getRootLogger()->setLevel(Level::getError());
+ LOGUNIT_ASSERT_EQUAL((int) Level::ERROR_INT,
+ logger->getEffectiveLevel()->toInt());
+ LogManager::resetConfiguration();
+ }
+
+ void testAppenderThreshold() {
+ Properties props;
+ props.put(LOG4CXX_STR("log4j.rootLogger"), LOG4CXX_STR("ALL,VECTOR1"));
+ props.put(LOG4CXX_STR("log4j.appender.VECTOR1"), LOG4CXX_STR("org.apache.log4j.VectorAppender"));
+ props.put(LOG4CXX_STR("log4j.appender.VECTOR1.threshold"), LOG4CXX_STR("WARN"));
+ PropertyConfigurator::configure(props);
+ LoggerPtr root(Logger::getRootLogger());
+ VectorAppenderPtr appender(root->getAppender(LOG4CXX_STR("VECTOR1")));
+ LOGUNIT_ASSERT_EQUAL((int) Level::WARN_INT, appender->getThreshold()->toInt());
+ LOG4CXX_INFO(root, "Info message");
+ LOG4CXX_WARN(root, "Warn message");
+ LOG4CXX_WARN(root, "Error message");
+ LOGUNIT_ASSERT_EQUAL((size_t) 2, appender->vector.size());
+ LogManager::resetConfiguration();
+ }
+
+};
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(PropertyConfiguratorTest);
diff --git a/src/test/cpp/rolling/filenamepatterntestcase.cpp b/src/test/cpp/rolling/filenamepatterntestcase.cpp
new file mode 100644
index 0000000..de6b655
--- /dev/null
+++ b/src/test/cpp/rolling/filenamepatterntestcase.cpp
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/pattern/filedatepatternconverter.h>
+#include <log4cxx/pattern/integerpatternconverter.h>
+#include <log4cxx/pattern/patternparser.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/date.h>
+#include <log4cxx/helpers/integer.h>
+#include "../util/compare.h"
+#include "../logunit.h"
+#include "../insertwide.h"
+#include <apr_time.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::pattern;
+
+
+/**
+ * Tests for FileNamePattern.
+ *
+ *
+ *
+ *
+ */
+LOGUNIT_CLASS(FileNamePatternTestCase) {
+ LOGUNIT_TEST_SUITE(FileNamePatternTestCase);
+ LOGUNIT_TEST(testFormatInteger1);
+ LOGUNIT_TEST(testFormatInteger2);
+ LOGUNIT_TEST(testFormatInteger3);
+ LOGUNIT_TEST(testFormatInteger4);
+ LOGUNIT_TEST(testFormatInteger5);
+ LOGUNIT_TEST(testFormatInteger6);
+ LOGUNIT_TEST(testFormatInteger7);
+ LOGUNIT_TEST(testFormatInteger8);
+ LOGUNIT_TEST(testFormatInteger9);
+ LOGUNIT_TEST(testFormatInteger10);
+ LOGUNIT_TEST(testFormatInteger11);
+ LOGUNIT_TEST(testFormatDate1);
+//
+// TODO: Problem with timezone offset
+// LOGUNIT_TEST(testFormatDate2);
+// LOGUNIT_TEST(testFormatDate3);
+ LOGUNIT_TEST(testFormatDate4);
+ LOGUNIT_TEST(testFormatDate5);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ LogString format(const LogString& pattern,
+ const ObjectPtr& obj) {
+ std::vector<PatternConverterPtr> converters;
+ std::vector<FormattingInfoPtr> fields;
+ PatternMap rules;
+ rules.insert(PatternMap::value_type(LOG4CXX_STR("d"), (PatternConstructor) FileDatePatternConverter::newInstance));
+ rules.insert(PatternMap::value_type(LOG4CXX_STR("i"), (PatternConstructor) IntegerPatternConverter::newInstance));
+ PatternParser::parse(pattern, converters, fields, rules);
+ LogString result;
+ Pool pool;
+ std::vector<FormattingInfoPtr>::const_iterator fieldIter = fields.begin();
+ for(std::vector<PatternConverterPtr>::const_iterator converterIter = converters.begin();
+ converterIter != converters.end();
+ converterIter++, fieldIter++) {
+ LogString::size_type i = result.length();
+ (*converterIter)->format(obj, result, pool);
+ (*fieldIter)->format(i, result);
+ }
+ return result;
+ }
+
+
+
+ void assertDatePattern(const LogString& pattern,
+ int year,
+ int month,
+ int day, int hour,
+ int min,
+ const LogString& expected) {
+ apr_time_exp_t tm;
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_min = min;
+ tm.tm_hour = hour;
+ tm.tm_mday = day;
+ tm.tm_mon = month;
+ tm.tm_year = year - 1900;
+ apr_time_t n;
+ /*apr_status_t stat = */apr_time_exp_get(&n, &tm);
+ ObjectPtr obj(new Date(n));
+ LOGUNIT_ASSERT_EQUAL(expected, format(pattern, obj));
+ }
+
+ void assertIntegerPattern(const LogString& pattern, int value,
+ const LogString& expected) {
+ ObjectPtr obj(new Integer(value));
+ LOGUNIT_ASSERT_EQUAL(expected, format(pattern, obj));
+ }
+
+ void testFormatInteger1() {
+ assertIntegerPattern(LOG4CXX_STR("t"), 3, LOG4CXX_STR("t"));
+ }
+
+ void testFormatInteger2() {
+ assertIntegerPattern(LOG4CXX_STR("foo"), 3, LOG4CXX_STR("foo"));
+ }
+
+ void testFormatInteger3() {
+ assertIntegerPattern(LOG4CXX_STR("foo%"), 3, LOG4CXX_STR("foo%"));
+ }
+
+ void testFormatInteger4() {
+ assertIntegerPattern(LOG4CXX_STR("%ifoo"), 3, LOG4CXX_STR("3foo"));
+ }
+
+ void testFormatInteger5() {
+ assertIntegerPattern(LOG4CXX_STR("foo%ixixo"), 3, LOG4CXX_STR("foo3xixo"));
+ }
+
+ void testFormatInteger6() {
+ assertIntegerPattern(LOG4CXX_STR("foo%i.log"), 3, LOG4CXX_STR("foo3.log"));
+ }
+
+ void testFormatInteger7() {
+ assertIntegerPattern(LOG4CXX_STR("foo.%i.log"), 3, LOG4CXX_STR("foo.3.log"));
+ }
+
+ void testFormatInteger8() {
+ assertIntegerPattern(LOG4CXX_STR("%ifoo%"), 3, LOG4CXX_STR("3foo%"));
+ }
+
+ void testFormatInteger9() {
+ assertIntegerPattern(LOG4CXX_STR("%ifoo%%"), 3, LOG4CXX_STR("3foo%"));
+ }
+
+ void testFormatInteger10() {
+ assertIntegerPattern(LOG4CXX_STR("%%foo"), 3, LOG4CXX_STR("%foo"));
+ }
+
+ void testFormatInteger11() {
+ assertIntegerPattern(LOG4CXX_STR("foo%ibar%i"), 3, LOG4CXX_STR("foo3bar3"));
+ }
+
+ void testFormatDate1() {
+ assertDatePattern(LOG4CXX_STR("foo%d{yyyy.MM.dd}"), 2003, 4, 20, 17, 55,
+ LOG4CXX_STR("foo2003.05.20"));
+ }
+
+ void testFormatDate2() {
+ assertDatePattern(LOG4CXX_STR("foo%d{yyyy.MM.dd HH:mm}"), 2003, 4, 20, 17, 55,
+ LOG4CXX_STR("foo2003.05.20 17:55"));
+ }
+
+ void testFormatDate3() {
+ assertDatePattern(LOG4CXX_STR("%d{yyyy.MM.dd HH:mm} foo"), 2003, 4, 20, 17, 55,
+ LOG4CXX_STR("2003.05.20 17:55 foo"));
+ }
+
+ void testFormatDate4() {
+ assertDatePattern(LOG4CXX_STR("foo%dyyyy.MM.dd}"), 2003, 4, 20, 17, 55,
+ LOG4CXX_STR("foo2003-05-20yyyy.MM.dd}"));
+ }
+
+ void testFormatDate5() {
+ assertDatePattern(LOG4CXX_STR("foo%d{yyyy.MM.dd"), 2003, 4, 20, 17, 55,
+ LOG4CXX_STR("foo2003-05-20{yyyy.MM.dd"));
+ }
+
+};
+
+//
+// See bug LOGCXX-204
+//
+#if !defined(_MSC_VER) || _MSC_VER > 1200
+LOGUNIT_TEST_SUITE_REGISTRATION(FileNamePatternTestCase);
+#endif
diff --git a/src/test/cpp/rolling/filterbasedrollingtest.cpp b/src/test/cpp/rolling/filterbasedrollingtest.cpp
new file mode 100644
index 0000000..c1e238a
--- /dev/null
+++ b/src/test/cpp/rolling/filterbasedrollingtest.cpp
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "../util/compare.h"
+#include "../logunit.h"
+#include "../insertwide.h"
+#include <log4cxx/logmanager.h>
+#include <log4cxx/xml/domconfigurator.h>
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/rolling/rollingfileappender.h>
+#include <log4cxx/rolling/fixedwindowrollingpolicy.h>
+#include <log4cxx/rolling/filterbasedtriggeringpolicy.h>
+#include <log4cxx/filter/levelrangefilter.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/logger.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::xml;
+using namespace log4cxx::filter;
+using namespace log4cxx::helpers;
+
+/**
+ *
+ * Tests of rolling file appender with a filter based triggering policy.
+ *
+ *
+ *
+ *
+ */
+LOGUNIT_CLASS(FilterBasedRollingTest) {
+ LOGUNIT_TEST_SUITE(FilterBasedRollingTest);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ void tearDown() {
+ LogManager::getLoggerRepository()->resetConfiguration();
+ }
+
+ /**
+ * Test basic rolling functionality using configuration file.
+ */
+ void test1() {
+ DOMConfigurator::configure(
+ "./input/rolling/filter1.xml" /*, LogManager::getLoggerRepository() */);
+
+ common(LOG4CXX_STR("output/filterBased-test1"));
+ }
+
+ /**
+ * Test basic rolling functionality using explicit configuration.
+ * @remarks Test fails when run immediately after test1.
+ */
+ void test2() {
+ LayoutPtr layout(new PatternLayout(LOG4CXX_STR("%m\n")));
+ RollingFileAppenderPtr rfa(new RollingFileAppender());
+ rfa->setName(LOG4CXX_STR("ROLLING"));
+ rfa->setLayout(layout);
+
+ FixedWindowRollingPolicyPtr swrp(new FixedWindowRollingPolicy());
+ FilterBasedTriggeringPolicyPtr fbtp(new FilterBasedTriggeringPolicy());
+
+ LevelRangeFilterPtr rf(new LevelRangeFilter());
+ rf->setLevelMin(Level::getInfo());
+ fbtp->addFilter(rf);
+
+ Pool p;
+ fbtp->activateOptions(p);
+
+ swrp->setMinIndex(0);
+ rfa->setFile(LOG4CXX_STR("output/filterBased-test2.log"));
+ rfa->setAppend(false);
+
+ swrp->setFileNamePattern(LOG4CXX_STR("output/filterBased-test2.%i"));
+ swrp->activateOptions(p);
+
+ rfa->setRollingPolicy(swrp);
+ rfa->setTriggeringPolicy(fbtp);
+ rfa->activateOptions(p);
+ Logger::getRootLogger()->addAppender(rfa);
+ Logger::getRootLogger()->setLevel(Level::getDebug());
+
+ common(LOG4CXX_STR("output/filterBased-test2"));
+ }
+
+private:
+ /**
+ * Common aspects of test1 and test2
+ */
+ void common(const LogString& baseName) {
+ LoggerPtr logger(Logger::getLogger("org.apache.log4j.rolling.FilterBasedRollingTest"));
+
+ // Write exactly 10 bytes with each log
+ for (int i = 0; i < 25; i++) {
+ char msg[10];
+#if defined(__STDC_LIB_EXT1__) || defined(__STDC_SECURE_LIB__)
+ strcpy_s(msg, sizeof msg, "Hello---?");
+#else
+ strcpy(msg, "Hello---?");
+#endif
+ if (i < 10) {
+ msg[8] = (char) ('0' + i);
+ LOG4CXX_DEBUG(logger, msg);
+ } else if (i < 100) {
+ msg[7] = (char) ('0' + (i / 10));
+ msg[8] = (char) ('0' + (i % 10));
+ if ((i % 10) == 0) {
+ LOG4CXX_WARN(logger, msg);
+ } else {
+ LOG4CXX_DEBUG(logger, msg);
+ }
+ }
+ }
+
+ //
+ // test was constructed to mimic SizeBasedRollingTest.test2
+ //
+ LOGUNIT_ASSERT_EQUAL(true,
+ Compare::compare(baseName + LOG4CXX_STR(".log"), LogString(LOG4CXX_STR("witness/rolling/sbr-test2.log"))));
+ LOGUNIT_ASSERT_EQUAL(true,
+ Compare::compare(baseName + LOG4CXX_STR(".0"), LogString(LOG4CXX_STR("witness/rolling/sbr-test2.0"))));
+ LOGUNIT_ASSERT_EQUAL(true,
+ Compare::compare(baseName + LOG4CXX_STR(".1"), LogString(LOG4CXX_STR("witness/rolling/sbr-test2.1"))));
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(FilterBasedRollingTest);
+
diff --git a/src/test/cpp/rolling/manualrollingtest.cpp b/src/test/cpp/rolling/manualrollingtest.cpp
new file mode 100644
index 0000000..4e479ac
--- /dev/null
+++ b/src/test/cpp/rolling/manualrollingtest.cpp
@@ -0,0 +1,296 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "../util/compare.h"
+#include "../insertwide.h"
+#include "../logunit.h"
+#include <apr_time.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/xml/domconfigurator.h>
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/rolling/fixedwindowrollingpolicy.h>
+#include <log4cxx/rolling/sizebasedtriggeringpolicy.h>
+#include <log4cxx/filter/levelrangefilter.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/propertyconfigurator.h>
+#include <log4cxx/rolling/rollingfileappender.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/consoleappender.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/fileoutputstream.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::xml;
+using namespace log4cxx::filter;
+using namespace log4cxx::helpers;
+using namespace log4cxx::rolling;
+
+/**
+ * Tests of explicit manual rolling of RollingFileAppenders.
+ *
+ *
+ *
+ */
+LOGUNIT_CLASS(ManualRollingTest) {
+ LOGUNIT_TEST_SUITE(ManualRollingTest);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+// TODO: Compression not yet implemented
+// LOGUNIT_TEST(test3);
+ LOGUNIT_TEST(test4);
+ LOGUNIT_TEST(test5);
+ LOGUNIT_TEST_SUITE_END();
+
+ LoggerPtr root;
+ LoggerPtr logger;
+
+ public:
+ void setUp() {
+ logger = Logger::getLogger("org.apache.log4j.rolling.ManualRollingTest");
+ root = Logger::getRootLogger();
+ }
+
+ void tearDown() {
+ LogManager::shutdown();
+ }
+
+ void common(RollingFileAppenderPtr& rfa,
+ Pool& pool,
+ LoggerPtr& logger1) {
+ char msg[] = { 'H', 'e', 'l', 'l', 'o', '-', '-', '-', 'N', 0 };
+
+ // Write exactly 10 bytes with each log
+ for (int i = 0; i < 25; i++) {
+ if (i < 10) {
+ msg[8] = '0' + i;
+ } else if (i < 100) {
+ int digit = i % 10;
+ if (digit == 0) {
+ rfa->rollover(pool);
+ }
+ msg[7] = '0' + i / 10;
+ msg[8] = '0' + digit;
+ }
+ LOG4CXX_DEBUG(logger1, msg);
+ }
+ }
+
+
+ /**
+ * Tests that the lack of an explicit active file will use the
+ * low index as the active file.
+ *
+ */
+ void test1() {
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%m\n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setName(LOG4CXX_STR("ROLLING"));
+ rfa->setAppend(false);
+ rfa->setLayout(layout);
+
+ FixedWindowRollingPolicyPtr swrp = new FixedWindowRollingPolicy();
+ swrp->setMinIndex(0);
+
+ swrp->setFileNamePattern(LOG4CXX_STR("output/manual-test1.%i"));
+ Pool p;
+ swrp->activateOptions(p);
+
+ rfa->setRollingPolicy(swrp);
+ rfa->activateOptions(p);
+ root->addAppender(rfa);
+
+
+ common(rfa, p, logger);
+
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test1.0").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test1.1").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test1.2").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/manual-test1.0"),
+ File("witness/rolling/sbr-test2.log")));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/manual-test1.1"),
+ File("witness/rolling/sbr-test2.0")));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/manual-test1.2"),
+ File("witness/rolling/sbr-test2.1")));
+ }
+
+ /**
+ * Test basic rolling functionality with explicit setting of FileAppender.file.
+ */
+ void test2() {
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%m\n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setName(LOG4CXX_STR("ROLLING"));
+ rfa->setAppend(false);
+ rfa->setLayout(layout);
+ rfa->setFile(LOG4CXX_STR("output/manual-test2.log"));
+
+ Pool p;
+ rfa->activateOptions(p);
+ root->addAppender(rfa);
+
+ common(rfa, p, logger);
+
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test2.log").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test2.log.1").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test2.log.2").exists(p));
+
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/manual-test2.log"),
+ File("witness/rolling/sbr-test2.log")));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/manual-test2.log.1"),
+ File("witness/rolling/sbr-test2.0")));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/manual-test2.log.2"),
+ File("witness/rolling/sbr-test2.1")));
+ }
+
+ /**
+ * Same as testBasic but also with GZ compression.
+ */
+ void test3() {
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%m\n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setAppend(false);
+ rfa->setLayout(layout);
+
+ FixedWindowRollingPolicyPtr fwrp = new FixedWindowRollingPolicy();
+
+ fwrp->setMinIndex(0);
+ rfa->setFile(LOG4CXX_STR("output/manual-test3.log"));
+ fwrp->setFileNamePattern(LOG4CXX_STR("output/sbr-test3.%i.gz"));
+ Pool p;
+ fwrp->activateOptions(p);
+ rfa->setRollingPolicy(fwrp);
+ rfa->activateOptions(p);
+ root->addAppender(rfa);
+
+ common(rfa, p, logger);
+
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test3.log").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test3.0.gz").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test3.1.gz").exists(p));
+
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/manual-test3.log"), File("witness/rolling/sbr-test3.log")));
+ LOGUNIT_ASSERT_EQUAL(File("witness/rolling/sbr-test3.0.gz").length(p), File("output/manual-test3.0.gz").length(p));
+ LOGUNIT_ASSERT_EQUAL(File("witness/rolling/sbr-test3.1.gz").length(p), File("output/manual-test3.1.gz").length(p));
+ }
+
+ /**
+ * Test basic rolling functionality with bogus path in file name pattern.
+ */
+ void test4() {
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%m\n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setName(LOG4CXX_STR("ROLLING"));
+ rfa->setAppend(false);
+ rfa->setLayout(layout);
+ rfa->setFile(LOG4CXX_STR("output/manual-test4.log"));
+
+ FixedWindowRollingPolicyPtr swrp = new FixedWindowRollingPolicy();
+
+ swrp->setMinIndex(0);
+
+ //
+ // test4 directory should not exists. Should cause all rollover attempts to fail.
+ //
+ swrp->setFileNamePattern(LOG4CXX_STR("output/test4/manual-test4.%i"));
+ Pool p;
+ swrp->activateOptions(p);
+
+ rfa->setRollingPolicy(swrp);
+ rfa->activateOptions(p);
+ root->addAppender(rfa);
+
+ common(rfa, p, logger);
+
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test4.log").exists(p));
+
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/manual-test4.log"),
+ File("witness/rolling/sbr-test4.log")));
+ }
+
+ /**
+ * Checking handling of rename failures due to other access
+ * to the indexed files.
+ */
+ void test5() {
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%m\n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setName(LOG4CXX_STR("ROLLING"));
+ rfa->setAppend(false);
+ rfa->setLayout(layout);
+ rfa->setFile(LOG4CXX_STR("output/manual-test5.log"));
+
+ FixedWindowRollingPolicyPtr swrp = new FixedWindowRollingPolicy();
+
+ swrp->setMinIndex(0);
+
+ swrp->setFileNamePattern(LOG4CXX_STR("output/manual-test5.%i"));
+ Pool p;
+ swrp->activateOptions(p);
+
+ rfa->setRollingPolicy(swrp);
+ rfa->activateOptions(p);
+ root->addAppender(rfa);
+
+ //
+ // put stray file about locked file
+ FileOutputStream os1(LOG4CXX_STR("output/manual-test5.1"), false);
+ os1.close(p);
+
+
+ FileOutputStream os0(LOG4CXX_STR("output/manual-test5.0"), false);
+
+ common(rfa, p, logger);
+
+ os0.close(p);
+
+ if (File("output/manual-test5.3").exists(p)) {
+ //
+ // looks like platform where open files can be renamed
+ //
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test5.log").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test5.0").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test5.1").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test5.2").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test5.3").exists(p));
+
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/manual-test5.log"),
+ File("witness/rolling/sbr-test2.log")));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/manual-test5.0"),
+ File("witness/rolling/sbr-test2.0")));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/manual-test5.1"),
+ File("witness/rolling/sbr-test2.1")));
+
+ } else {
+ //
+ // rollover attempts should all fail
+ // so initial log file should have all log content
+ // open file should be unaffected
+ // stray file should have only been moved one slot.
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test5.log").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test5.0").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/manual-test5.2").exists(p));
+
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/manual-test5.log"),
+ File("witness/rolling/sbr-test4.log")));
+ }
+ }
+
+};
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(ManualRollingTest);
diff --git a/src/test/cpp/rolling/obsoletedailyrollingfileappendertest.cpp b/src/test/cpp/rolling/obsoletedailyrollingfileappendertest.cpp
new file mode 100644
index 0000000..7e18e87
--- /dev/null
+++ b/src/test/cpp/rolling/obsoletedailyrollingfileappendertest.cpp
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "../util/compare.h"
+#include "../insertwide.h"
+#include "../logunit.h"
+#include <apr_time.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/xml/domconfigurator.h>
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/rolling/rollingfileappender.h>
+#include <log4cxx/rolling/fixedwindowrollingpolicy.h>
+#include <log4cxx/rolling/filterbasedtriggeringpolicy.h>
+#include <log4cxx/filter/levelrangefilter.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/propertyconfigurator.h>
+#include <log4cxx/dailyrollingfileappender.h>
+#include <log4cxx/helpers/stringhelper.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::xml;
+using namespace log4cxx::filter;
+using namespace log4cxx::helpers;
+
+
+/**
+ * Tests the emulation of org.apache.log4j.DailyRollingFileAppender
+ *
+ *
+ *
+ */
+LOGUNIT_CLASS(ObsoleteDailyRollingFileAppenderTest) {
+ LOGUNIT_TEST_SUITE(ObsoleteDailyRollingFileAppenderTest);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+
+ void tearDown() {
+ LogManager::shutdown();
+ }
+
+ /**
+ * Test basic rolling functionality.
+ */
+ void test1() {
+ PropertyConfigurator::configure(File("input/rolling/obsoleteDRFA1.properties"));
+
+ int preCount = getFileCount("output", LOG4CXX_STR("obsoleteDRFA-test1.log."));
+ LoggerPtr logger(Logger::getLogger("org.apache.log4j.ObsoleteDailyRollingFileAppenderTest"));
+
+ char msg[11];
+ strcpy(msg, "Hello---??");
+
+ for (int i = 0; i < 25; i++) {
+ apr_sleep(100000);
+ msg[8] = (char) ('0' + (i / 10));
+ msg[9] = (char) ('0' + (i % 10));
+ LOG4CXX_DEBUG(logger, msg);
+ }
+
+ int postCount = getFileCount("output", LOG4CXX_STR("obsoleteDRFA-test1.log."));
+ LOGUNIT_ASSERT_EQUAL(true, postCount > preCount);
+ }
+
+ /**
+ * Test basic rolling functionality.
+ * @deprecated Class under test is deprecated.
+ */
+ void test2() {
+ PatternLayoutPtr layout(new PatternLayout(LOG4CXX_STR("%m%n")));
+ log4cxx::DailyRollingFileAppenderPtr rfa(new log4cxx::DailyRollingFileAppender());
+ rfa->setName(LOG4CXX_STR("ROLLING"));
+ rfa->setLayout(layout);
+ rfa->setAppend(false);
+ rfa->setFile(LOG4CXX_STR("output/obsoleteDRFA-test2.log"));
+ rfa->setDatePattern(LOG4CXX_STR("'.'yyyy-MM-dd-HH_mm_ss"));
+ Pool p;
+ rfa->activateOptions(p);
+ LoggerPtr root(Logger::getRootLogger());
+ root->addAppender(rfa);
+ LoggerPtr logger(Logger::getLogger("org.apache.log4j.ObsoleteDailyRollingAppenderTest"));
+
+ int preCount = getFileCount("output", LOG4CXX_STR("obsoleteDRFA-test2.log."));
+
+ char msg[11];
+ strcpy(msg, "Hello---??");
+ for (int i = 0; i < 25; i++) {
+ apr_sleep(100000);
+ msg[8] = (char) ('0' + i / 10);
+ msg[9] = (char) ('0' + i % 10);
+ LOG4CXX_DEBUG(logger, msg);
+ }
+
+ int postCount = getFileCount("output", LOG4CXX_STR("obsoleteDRFA-test2.log."));
+ LOGUNIT_ASSERT_EQUAL(true, postCount > preCount);
+ }
+
+private:
+ static int getFileCount(const char* dir, const LogString& initial) {
+ Pool p;
+ std::vector<LogString> files(File(dir).list(p));
+ int count = 0;
+
+ for (size_t i = 0; i < files.size(); i++) {
+ if (StringHelper::startsWith(files[i], initial)) {
+ count++;
+ }
+ }
+
+ return count;
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(ObsoleteDailyRollingFileAppenderTest);
+
diff --git a/src/test/cpp/rolling/obsoleterollingfileappendertest.cpp b/src/test/cpp/rolling/obsoleterollingfileappendertest.cpp
new file mode 100644
index 0000000..c3840fb
--- /dev/null
+++ b/src/test/cpp/rolling/obsoleterollingfileappendertest.cpp
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "../util/compare.h"
+#include "../insertwide.h"
+#include "../logunit.h"
+#include <apr_time.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/xml/domconfigurator.h>
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/rolling/rollingfileappender.h>
+#include <log4cxx/rolling/fixedwindowrollingpolicy.h>
+#include <log4cxx/rolling/filterbasedtriggeringpolicy.h>
+#include <log4cxx/filter/levelrangefilter.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/propertyconfigurator.h>
+#include <log4cxx/rollingfileappender.h>
+#include <log4cxx/helpers/stringhelper.h>
+
+ using namespace log4cxx;
+ using namespace log4cxx::xml;
+ using namespace log4cxx::filter;
+ using namespace log4cxx::helpers;
+
+/**
+ * Tests the emulation of org.apache.log4j.RollingFileAppender
+ *
+ *
+ *
+ */
+ LOGUNIT_CLASS(ObsoleteRollingFileAppenderTest) {
+ LOGUNIT_TEST_SUITE(ObsoleteRollingFileAppenderTest);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST(testIsOptionHandler);
+ LOGUNIT_TEST(testClassForName);
+ LOGUNIT_TEST_SUITE_END();
+
+
+ public:
+
+ void tearDown() {
+ LogManager::shutdown();
+ }
+
+ /**
+ * Test basic rolling functionality.
+ */
+ void test1() {
+ PropertyConfigurator::configure(File("input/rolling/obsoleteRFA1.properties"));
+
+ char msg[] = { 'H', 'e', 'l', 'l', 'o', '-', '-', '-', '?', 0};
+ LoggerPtr logger(Logger::getLogger("org.apache.logj4.ObsoleteRollingFileAppenderTest"));
+
+ // Write exactly 10 bytes with each log
+ for (int i = 0; i < 25; i++) {
+ apr_sleep(100000);
+
+ if (i < 10) {
+ msg[8] = (char) ('0' + i);
+ LOG4CXX_DEBUG(logger, msg);
+ } else if (i < 100) {
+ msg[7] = (char) ('0' + i / 10);
+ msg[8] = (char) ('0' + i % 10);
+ LOG4CXX_DEBUG(logger, msg);
+ }
+ }
+
+ Pool p;
+ LOGUNIT_ASSERT_EQUAL(true, File("output/obsoleteRFA-test1.log").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/obsoleteRFA-test1.log.1").exists(p));
+ }
+
+ /**
+ * Test basic rolling functionality.
+ * @deprecated Class under test is deprecated.
+ */
+ void test2() {
+ PatternLayoutPtr layout(new PatternLayout(LOG4CXX_STR("%m\n")));
+ log4cxx::RollingFileAppenderPtr rfa(
+ new log4cxx::RollingFileAppender());
+ rfa->setName(LOG4CXX_STR("ROLLING"));
+ rfa->setLayout(layout);
+ rfa->setOption(LOG4CXX_STR("append"), LOG4CXX_STR("false"));
+ rfa->setMaximumFileSize(100);
+ rfa->setFile(LOG4CXX_STR("output/obsoleteRFA-test2.log"));
+ Pool p;
+ rfa->activateOptions(p);
+ LoggerPtr root(Logger::getRootLogger());
+ root->addAppender(rfa);
+
+ char msg[] = { 'H', 'e', 'l', 'l', 'o', '-', '-', '-', '?', 0};
+ LoggerPtr logger(Logger::getLogger("org.apache.logj4.ObsoleteRollingFileAppenderTest"));
+
+ // Write exactly 10 bytes with each log
+ for (int i = 0; i < 25; i++) {
+ apr_sleep(100000);
+
+ if (i < 10) {
+ msg[8] = (char) ('0' + i);
+ LOG4CXX_DEBUG(logger, msg);
+ } else if (i < 100) {
+ msg[7] = (char) ('0' + i / 10);
+ msg[8] = (char) ('0' + i % 10);
+ LOG4CXX_DEBUG(logger, msg);
+ }
+ }
+
+ LOGUNIT_ASSERT_EQUAL(true, File("output/obsoleteRFA-test2.log").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/obsoleteRFA-test2.log.1").exists(p));
+ }
+
+ /**
+ * Tests if class is declared to support the OptionHandler interface.
+ * See LOGCXX-136.
+ */
+ void testIsOptionHandler() {
+ RollingFileAppenderPtr rfa(new RollingFileAppender());
+ LOGUNIT_ASSERT_EQUAL(true, rfa->instanceof(log4cxx::spi::OptionHandler::getStaticClass()));
+ }
+
+ void testClassForName() {
+ LogString className(LOG4CXX_STR("org.apache.log4j.RollingFileAppender"));
+ const Class& myclass = Class::forName(className);
+ LOGUNIT_ASSERT_EQUAL(className, LogString(myclass.getName()));
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(ObsoleteRollingFileAppenderTest);
+
diff --git a/src/test/cpp/rolling/sizebasedrollingtest.cpp b/src/test/cpp/rolling/sizebasedrollingtest.cpp
new file mode 100644
index 0000000..e036b3c
--- /dev/null
+++ b/src/test/cpp/rolling/sizebasedrollingtest.cpp
@@ -0,0 +1,351 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "../util/compare.h"
+#include "../insertwide.h"
+#include "../logunit.h"
+#include <apr_time.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/xml/domconfigurator.h>
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/rolling/fixedwindowrollingpolicy.h>
+#include <log4cxx/rolling/sizebasedtriggeringpolicy.h>
+#include <log4cxx/filter/levelrangefilter.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/propertyconfigurator.h>
+#include <log4cxx/rolling/rollingfileappender.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/consoleappender.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/fileoutputstream.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::xml;
+using namespace log4cxx::filter;
+using namespace log4cxx::helpers;
+using namespace log4cxx::rolling;
+
+/**
+ *
+ * Do not forget to call activateOptions when configuring programatically.
+ *
+ *
+ *
+ */
+LOGUNIT_CLASS(SizeBasedRollingTest) {
+ LOGUNIT_TEST_SUITE(SizeBasedRollingTest);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST(test3);
+ LOGUNIT_TEST(test4);
+ LOGUNIT_TEST(test5);
+ LOGUNIT_TEST(test6);
+ LOGUNIT_TEST_SUITE_END();
+
+ LoggerPtr root;
+ LoggerPtr logger;
+
+ public:
+ void setUp() {
+ PatternLayoutPtr layout(new PatternLayout(LOG4CXX_STR("%d %level %c -%m%n")));
+ AppenderPtr ca(new ConsoleAppender(layout));
+ ca->setName(LOG4CXX_STR("CONSOLE"));
+ root = Logger::getRootLogger();
+ root->addAppender(ca);
+ logger = Logger::getLogger("org.apache.log4j.rolling.SizeBasedRollingTest");
+ }
+
+ void tearDown() {
+ LogManager::shutdown();
+ }
+
+ void common(LoggerPtr& logger1, int /*sleep*/) {
+ char msg[] = { 'H', 'e', 'l', 'l', 'o', '-', '-', '-', 'N', 0 };
+
+ // Write exactly 10 bytes with each log
+ for (int i = 0; i < 25; i++) {
+ if (i < 10) {
+ msg[8] = '0' + i;
+ } else if (i < 100) {
+ msg[7] = '0' + i / 10;
+ msg[8] = '0' + i % 10;
+ }
+ LOG4CXX_DEBUG(logger1, msg);
+ }
+ }
+
+
+ /**
+ * Tests that the lack of an explicit active file will use the
+ * low index as the active file.
+ *
+ */
+ void test1() {
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%m\n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setName(LOG4CXX_STR("ROLLING"));
+ rfa->setAppend(false);
+ rfa->setLayout(layout);
+
+ FixedWindowRollingPolicyPtr swrp = new FixedWindowRollingPolicy();
+ SizeBasedTriggeringPolicyPtr sbtp = new SizeBasedTriggeringPolicy();
+
+ sbtp->setMaxFileSize(100);
+ swrp->setMinIndex(0);
+
+ swrp->setFileNamePattern(LOG4CXX_STR("output/sizeBased-test1.%i"));
+ Pool p;
+ swrp->activateOptions(p);
+
+ rfa->setRollingPolicy(swrp);
+ rfa->setTriggeringPolicy(sbtp);
+ rfa->activateOptions(p);
+ root->addAppender(rfa);
+
+
+ common(logger, 0);
+
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test1.0").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test1.1").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test1.2").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/sizeBased-test1.0"),
+ File("witness/rolling/sbr-test2.log")));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/sizeBased-test1.1"),
+ File("witness/rolling/sbr-test2.0")));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/sizeBased-test1.2"),
+ File("witness/rolling/sbr-test2.1")));
+ }
+
+ /**
+ * Test basic rolling functionality with explicit setting of FileAppender.file.
+ */
+ void test2() {
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%m\n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setName(LOG4CXX_STR("ROLLING"));
+ rfa->setAppend(false);
+ rfa->setLayout(layout);
+ rfa->setFile(LOG4CXX_STR("output/sizeBased-test2.log"));
+
+ FixedWindowRollingPolicyPtr swrp = new FixedWindowRollingPolicy();
+ SizeBasedTriggeringPolicyPtr sbtp = new SizeBasedTriggeringPolicy();
+
+ sbtp->setMaxFileSize(100);
+ swrp->setMinIndex(0);
+
+ swrp->setFileNamePattern(LOG4CXX_STR("output/sizeBased-test2.%i"));
+ Pool p;
+ swrp->activateOptions(p);
+
+ rfa->setRollingPolicy(swrp);
+ rfa->setTriggeringPolicy(sbtp);
+ rfa->activateOptions(p);
+ root->addAppender(rfa);
+
+ common(logger, 0);
+
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test2.log").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test2.0").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test2.1").exists(p));
+
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/sizeBased-test2.log"),
+ File("witness/rolling/sbr-test2.log")));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/sizeBased-test2.0"),
+ File("witness/rolling/sbr-test2.0")));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/sizeBased-test2.1"),
+ File("witness/rolling/sbr-test2.1")));
+ }
+
+ /**
+ * Same as testBasic but also with GZ compression.
+ */
+ void test3() {
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%m\n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setAppend(false);
+ rfa->setLayout(layout);
+
+ FixedWindowRollingPolicyPtr fwrp = new FixedWindowRollingPolicy();
+ SizeBasedTriggeringPolicyPtr sbtp = new SizeBasedTriggeringPolicy();
+
+ sbtp->setMaxFileSize(100);
+ fwrp->setMinIndex(0);
+ rfa->setFile(LOG4CXX_STR("output/sbr-test3.log"));
+ fwrp->setFileNamePattern(LOG4CXX_STR("output/sbr-test3.%i.gz"));
+ Pool p;
+ fwrp->activateOptions(p);
+ rfa->setRollingPolicy(fwrp);
+ rfa->setTriggeringPolicy(sbtp);
+ rfa->activateOptions(p);
+ root->addAppender(rfa);
+
+ common(logger, 100);
+
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sbr-test3.log").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sbr-test3.0.gz").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sbr-test3.1.gz").exists(p));
+
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/sbr-test3.log"), File("witness/rolling/sbr-test3.log")));
+ LOGUNIT_ASSERT_EQUAL(File("witness/rolling/sbr-test3.0.gz").length(p), File("output/sbr-test3.0.gz").length(p));
+ LOGUNIT_ASSERT_EQUAL(File("witness/rolling/sbr-test3.1.gz").length(p), File("output/sbr-test3.1.gz").length(p));
+ }
+
+ /**
+ * Test basic rolling functionality with bogus path in file name pattern.
+ */
+ void test4() {
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%m\n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setName(LOG4CXX_STR("ROLLING"));
+ rfa->setAppend(false);
+ rfa->setLayout(layout);
+ rfa->setFile(LOG4CXX_STR("output/sizeBased-test4.log"));
+
+ FixedWindowRollingPolicyPtr swrp = new FixedWindowRollingPolicy();
+ SizeBasedTriggeringPolicyPtr sbtp = new SizeBasedTriggeringPolicy();
+
+ sbtp->setMaxFileSize(100);
+ swrp->setMinIndex(0);
+
+ //
+ // test4 directory should not exists. Should cause all rollover attempts to fail.
+ //
+ swrp->setFileNamePattern(LOG4CXX_STR("output/test4/sizeBased-test4.%i"));
+ Pool p;
+ swrp->activateOptions(p);
+
+ rfa->setRollingPolicy(swrp);
+ rfa->setTriggeringPolicy(sbtp);
+ rfa->activateOptions(p);
+ root->addAppender(rfa);
+
+ common(logger, 0);
+
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test4.log").exists(p));
+
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/sizeBased-test4.log"),
+ File("witness/rolling/sbr-test4.log")));
+ }
+
+ /**
+ * Checking handling of rename failures due to other access
+ * to the indexed files.
+ */
+ void test5() {
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%m\n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setName(LOG4CXX_STR("ROLLING"));
+ rfa->setAppend(false);
+ rfa->setLayout(layout);
+ rfa->setFile(LOG4CXX_STR("output/sizeBased-test5.log"));
+
+ FixedWindowRollingPolicyPtr swrp = new FixedWindowRollingPolicy();
+ SizeBasedTriggeringPolicyPtr sbtp = new SizeBasedTriggeringPolicy();
+
+ sbtp->setMaxFileSize(100);
+ swrp->setMinIndex(0);
+
+ swrp->setFileNamePattern(LOG4CXX_STR("output/sizeBased-test5.%i"));
+ Pool p;
+ swrp->activateOptions(p);
+
+ rfa->setRollingPolicy(swrp);
+ rfa->setTriggeringPolicy(sbtp);
+ rfa->activateOptions(p);
+ root->addAppender(rfa);
+
+ //
+ // put stray file about locked file
+ FileOutputStream os1(LOG4CXX_STR("output/sizeBased-test5.1"), false);
+ os1.close(p);
+
+
+ FileOutputStream os0(LOG4CXX_STR("output/sizeBased-test5.0"), false);
+
+ common(logger, 0);
+
+ os0.close(p);
+
+ if (File("output/sizeBased-test5.3").exists(p)) {
+ //
+ // looks like platform where open files can be renamed
+ //
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test5.log").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test5.0").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test5.1").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test5.2").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test5.3").exists(p));
+
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/sizeBased-test5.log"),
+ File("witness/rolling/sbr-test2.log")));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/sizeBased-test5.0"),
+ File("witness/rolling/sbr-test2.0")));
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/sizeBased-test5.1"),
+ File("witness/rolling/sbr-test2.1")));
+
+ } else {
+ //
+ // rollover attempts should all fail
+ // so initial log file should have all log content
+ // open file should be unaffected
+ // stray file should have only been moved one slot.
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test5.log").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test5.0").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sizeBased-test5.2").exists(p));
+
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/sizeBased-test5.log"),
+ File("witness/rolling/sbr-test4.log")));
+ }
+ }
+
+ /**
+ * Same as testBasic but also with GZ compression.
+ */
+ void test6() {
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%m\n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setAppend(false);
+ rfa->setLayout(layout);
+
+ FixedWindowRollingPolicyPtr fwrp = new FixedWindowRollingPolicy();
+ SizeBasedTriggeringPolicyPtr sbtp = new SizeBasedTriggeringPolicy();
+
+ sbtp->setMaxFileSize(100);
+ fwrp->setMinIndex(0);
+ rfa->setFile(LOG4CXX_STR("output/sbr-test6.log"));
+ fwrp->setFileNamePattern(LOG4CXX_STR("output/sbr-test6.%i.zip"));
+ Pool p;
+ fwrp->activateOptions(p);
+ rfa->setRollingPolicy(fwrp);
+ rfa->setTriggeringPolicy(sbtp);
+ rfa->activateOptions(p);
+ root->addAppender(rfa);
+
+ common(logger, 100);
+
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sbr-test6.log").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sbr-test6.0.zip").exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File("output/sbr-test6.1.zip").exists(p));
+
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File("output/sbr-test6.log"), File("witness/rolling/sbr-test3.log")));
+ }
+
+};
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(SizeBasedRollingTest);
diff --git a/src/test/cpp/rolling/timebasedrollingtest.cpp b/src/test/cpp/rolling/timebasedrollingtest.cpp
new file mode 100755
index 0000000..3114e2c
--- /dev/null
+++ b/src/test/cpp/rolling/timebasedrollingtest.cpp
@@ -0,0 +1,442 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/rolling/rollingfileappender.h>
+#include <log4cxx/logger.h>
+#include <log4cxx/consoleappender.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/rolling/timebasedrollingpolicy.h>
+#include <log4cxx/helpers/simpledateformat.h>
+#include <iostream>
+#include <log4cxx/helpers/stringhelper.h>
+#include "../util/compare.h"
+#include "../logunit.h"
+#include <apr_strings.h>
+
+
+#ifndef INT64_C
+#define INT64_C(x) x ## LL
+#endif
+#include <apr_time.h>
+
+
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::rolling;
+
+/**
+ * A rather exhaustive set of tests. Tests include leaving the ActiveFileName
+ * argument blank, or setting it, with and without compression, and tests
+ * with or without stopping/restarting the RollingFileAppender.
+ *
+ * The regression tests log a few times using a RollingFileAppender. Then,
+ * they predict the names of the files which sould be generated and compare
+ * them with witness files.
+ *
+ * <pre>
+ Compression ActiveFileName Stop/Restart
+ Test1 NO BLANK NO
+ Test2 NO BLANK YES
+ Test3 YES BLANK NO
+ Test4 NO SET YES
+ Test5 NO SET NO
+ Test6 YES SET NO
+ * </pre>
+ *
+ */
+LOGUNIT_CLASS(TimeBasedRollingTest) {
+
+ LOGUNIT_TEST_SUITE(TimeBasedRollingTest);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST(test3);
+ LOGUNIT_TEST(test4);
+ LOGUNIT_TEST(test5);
+ LOGUNIT_TEST(test6);
+ LOGUNIT_TEST_SUITE_END();
+
+ static LoggerPtr logger;
+
+public:
+
+ void setUp() {
+ LoggerPtr root(Logger::getRootLogger());
+ root->addAppender(
+ new ConsoleAppender(new PatternLayout(
+ LOG4CXX_STR("%d{ABSOLUTE} [%t] %level %c{2}#%M:%L - %m%n"))));
+ }
+
+ void tearDown() {
+ LogManager::shutdown();
+ }
+
+ /**
+ * Test rolling without compression, activeFileName left blank, no stop/start
+ */
+ void test1() {
+ PatternLayoutPtr layout(new PatternLayout(LOG4CXX_STR("%c{1} - %m%n")));
+ RollingFileAppenderPtr rfa(new RollingFileAppender());
+ rfa->setLayout(layout);
+
+ LogString datePattern(LOG4CXX_STR("yyyy-MM-dd_HH_mm_ss"));
+
+ TimeBasedRollingPolicyPtr tbrp(new TimeBasedRollingPolicy());
+ tbrp->setFileNamePattern(LOG4CXX_STR("output/test1-%d{yyyy-MM-dd_HH_mm_ss}"));
+ Pool p;
+ tbrp->activateOptions(p);
+ rfa->setRollingPolicy(tbrp);
+ rfa->activateOptions(p);
+ logger->addAppender(rfa);
+
+ SimpleDateFormat sdf(datePattern);
+ LogString filenames[4];
+
+ Pool pool;
+ apr_time_t now = apr_time_now();
+ { for (int i = 0; i < 4; i++) {
+ filenames[i] = LOG4CXX_STR("output/test1-");
+ sdf.format(filenames[i], now, p);
+ now += APR_USEC_PER_SEC;
+ } }
+
+ std::cout << "Waiting until next second and 100 millis.";
+ delayUntilNextSecond(100);
+ std::cout << "Done waiting.";
+
+ { for (int i = 0; i < 5; i++) {
+ std::string message("Hello---");
+ message.append(pool.itoa(i));
+ LOG4CXX_DEBUG(logger, message);
+ apr_sleep(APR_USEC_PER_SEC/2);
+ } }
+
+ for (int i = 0; i < 4; i++) {
+ LogString witness(LOG4CXX_STR("witness/rolling/tbr-test1."));
+ StringHelper::toString(i, pool, witness);
+ LOGUNIT_ASSERT(Compare::compare(filenames[i], File(witness)));
+ }
+ }
+
+ /**
+ * No compression, with stop/restart, activeFileName left blank
+ */
+ void test2() {
+ LogString datePattern(LOG4CXX_STR("yyyy-MM-dd_HH_mm_ss"));
+
+ PatternLayoutPtr layout1(new PatternLayout(LOG4CXX_STR("%c{1} - %m%n")));
+ RollingFileAppenderPtr rfa1(new RollingFileAppender());
+ rfa1->setLayout(layout1);
+
+ TimeBasedRollingPolicyPtr tbrp1(new TimeBasedRollingPolicy());
+ tbrp1->setFileNamePattern(LOG4CXX_STR("output/test2-%d{yyyy-MM-dd_HH_mm_ss}"));
+ Pool pool;
+ tbrp1->activateOptions(pool);
+ rfa1->setRollingPolicy(tbrp1);
+ rfa1->activateOptions(pool);
+ logger->addAppender(rfa1);
+
+ SimpleDateFormat sdf(datePattern);
+ LogString filenames[4];
+
+ apr_time_t now = apr_time_now();
+ { for (int i = 0; i < 4; i++) {
+ filenames[i] = LOG4CXX_STR("output/test2-");
+ sdf.format(filenames[i], now, pool);
+ now += APR_USEC_PER_SEC;
+ } }
+
+ delayUntilNextSecond(100);
+
+ { for (int i = 0; i <= 2; i++) {
+ std::string message("Hello---");
+ message.append(pool.itoa(i));
+ LOG4CXX_DEBUG(logger, message);
+ apr_sleep(APR_USEC_PER_SEC/2);
+ } }
+
+
+ logger->removeAppender(rfa1);
+ rfa1->close();
+
+ PatternLayoutPtr layout2(new PatternLayout(LOG4CXX_STR("%c{1} - %m%n")));
+ RollingFileAppenderPtr rfa2 = new RollingFileAppender();
+ rfa2->setLayout(layout2);
+
+ TimeBasedRollingPolicyPtr tbrp2 = new TimeBasedRollingPolicy();
+ tbrp2->setFileNamePattern(LOG4CXX_STR("output/test2-%d{yyyy-MM-dd_HH_mm_ss}"));
+ tbrp2->activateOptions(pool);
+ rfa2->setRollingPolicy(tbrp2);
+ rfa2->activateOptions(pool);
+ logger->addAppender(rfa2);
+
+ { for (int i = 3; i <= 4; i++) {
+ std::string message("Hello---");
+ message.append(pool.itoa(i));
+ LOG4CXX_DEBUG(logger, message);
+ apr_sleep(APR_USEC_PER_SEC/2);
+ } }
+
+ for (int i = 0; i < 4; i++) {
+ LogString witness(LOG4CXX_STR("witness/rolling/tbr-test2."));
+ StringHelper::toString(i, pool, witness);
+ LOGUNIT_ASSERT(Compare::compare(filenames[i], File(witness)));
+ }
+ }
+
+ /**
+ * With compression, activeFileName left blank, no stop/restart
+ */
+ void test3() {
+ Pool p;
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%c{1} - %m%n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setAppend(false);
+ rfa->setLayout(layout);
+
+ LogString datePattern = LOG4CXX_STR("yyyy-MM-dd_HH_mm_ss");
+
+ TimeBasedRollingPolicyPtr tbrp = new TimeBasedRollingPolicy();
+ tbrp->setFileNamePattern(LogString(LOG4CXX_STR("output/test3-%d{")) + datePattern + LogString(LOG4CXX_STR("}.gz")));
+ tbrp->activateOptions(p);
+ rfa->setRollingPolicy(tbrp);
+ rfa->activateOptions(p);
+ logger->addAppender(rfa);
+
+ DateFormatPtr sdf = new SimpleDateFormat(datePattern);
+ LogString filenames[4];
+
+ apr_time_t now = apr_time_now();
+ { for (int i = 0; i < 4; i++) {
+ filenames[i] = LOG4CXX_STR("output/test3-");
+ sdf->format(filenames[i], now, p);
+ filenames[i].append(LOG4CXX_STR(".gz"));
+ now += APR_USEC_PER_SEC;
+ } }
+
+ filenames[3].resize(filenames[3].size() - 3);
+
+ delayUntilNextSecond(100);
+
+ { for (int i = 0; i < 5; i++) {
+ std::string message("Hello---");
+ message.append(p.itoa(i));
+ LOG4CXX_DEBUG(logger, message);
+ apr_sleep(APR_USEC_PER_SEC/2);
+ } }
+
+ LOGUNIT_ASSERT_EQUAL(true, File(filenames[0]).exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File(filenames[1]).exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File(filenames[2]).exists(p));
+
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File(filenames[3]), File(LOG4CXX_STR("witness/rolling/tbr-test3.3"))));
+ }
+
+ /**
+ * Without compression, activeFileName set, with stop/restart
+ */
+ void test4() {
+ LogString datePattern = LOG4CXX_STR("yyyy-MM-dd_HH_mm_ss");
+
+ PatternLayoutPtr layout1 = new PatternLayout(LOG4CXX_STR("%c{1} - %m%n"));
+ RollingFileAppenderPtr rfa1 = new RollingFileAppender();
+ rfa1->setLayout(layout1);
+
+ Pool pool;
+
+ TimeBasedRollingPolicyPtr tbrp1 = new TimeBasedRollingPolicy();
+ rfa1->setFile(LOG4CXX_STR("output/test4.log"));
+ tbrp1->setFileNamePattern(LOG4CXX_STR("output/test4-%d{yyyy-MM-dd_HH_mm_ss}"));
+ tbrp1->activateOptions(pool);
+ rfa1->setRollingPolicy(tbrp1);
+ rfa1->activateOptions(pool);
+ logger->addAppender(rfa1);
+
+ SimpleDateFormat sdf(datePattern);
+ LogString filenames[4];
+
+ apr_time_t now = apr_time_now();
+ { for (int i = 0; i < 3; i++) {
+ filenames[i] = LOG4CXX_STR("output/test4-");
+ sdf.format(filenames[i], now, pool);
+ now += APR_USEC_PER_SEC;
+ } }
+ filenames[3] = LOG4CXX_STR("output/test4.log");
+
+ std::cout << "Waiting until next second and 100 millis.";
+ delayUntilNextSecond(100);
+ std::cout << "Done waiting.";
+
+ { for (int i = 0; i <= 2; i++) {
+ std::string message("Hello---");
+ message.append(pool.itoa(i));
+ LOG4CXX_DEBUG(logger, message);
+ apr_sleep(APR_USEC_PER_SEC/2);
+ } }
+
+ logger->removeAppender(rfa1);
+ rfa1->close();
+
+ PatternLayoutPtr layout2 = new PatternLayout(LOG4CXX_STR("%c{1} - %m%n"));
+ RollingFileAppenderPtr rfa2 = new RollingFileAppender();
+ rfa2->setLayout(layout2);
+
+ TimeBasedRollingPolicyPtr tbrp2 = new TimeBasedRollingPolicy();
+ tbrp2->setFileNamePattern(LOG4CXX_STR("output/test4-%d{yyyy-MM-dd_HH_mm_ss}"));
+ rfa2->setFile(LOG4CXX_STR("output/test4.log"));
+ tbrp2->activateOptions(pool);
+ rfa2->setRollingPolicy(tbrp2);
+ rfa2->activateOptions(pool);
+ logger->addAppender(rfa2);
+
+ { for (int i = 3; i <= 4; i++) {
+ std::string message("Hello---");
+ message.append(pool.itoa(i));
+ LOG4CXX_DEBUG(logger, message);
+ apr_sleep(APR_USEC_PER_SEC/2);
+ } }
+
+ for (int i = 0; i < 4; i++) {
+ LogString witness(LOG4CXX_STR("witness/rolling/tbr-test4."));
+ StringHelper::toString(i, pool, witness);
+ LOGUNIT_ASSERT(Compare::compare(filenames[i], File(witness)));
+ }
+ }
+
+ /**
+ * No compression, activeFileName set, without stop/restart
+ */
+ void test5() {
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%c{1} - %m%n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setLayout(layout);
+
+ LogString datePattern(LOG4CXX_STR("yyyy-MM-dd_HH_mm_ss"));
+
+ TimeBasedRollingPolicyPtr tbrp = new TimeBasedRollingPolicy();
+ tbrp->setFileNamePattern(LOG4CXX_STR("output/test5-%d{yyyy-MM-dd_HH_mm_ss}"));
+ rfa->setFile(LOG4CXX_STR("output/test5.log"));
+ Pool pool;
+
+ tbrp->activateOptions(pool);
+ rfa->setRollingPolicy(tbrp);
+ rfa->activateOptions(pool);
+ logger->addAppender(rfa);
+
+ SimpleDateFormat sdf(datePattern);
+ LogString filenames[4];
+
+ apr_time_t now = apr_time_now();
+ { for (int i = 0; i < 3; i++) {
+ filenames[i] = LOG4CXX_STR("output/test5-");
+ sdf.format(filenames[i], now, pool);
+ now += APR_USEC_PER_SEC;
+ } }
+ filenames[3] = LOG4CXX_STR("output/test5.log");
+
+ std::cout << "Waiting until next second and 100 millis.";
+ delayUntilNextSecond(100);
+ std::cout << "Done waiting.";
+
+ { for (int i = 0; i < 5; i++) {
+ std::string message("Hello---");
+ message.append(pool.itoa(i));
+ LOG4CXX_DEBUG(logger, message);
+ apr_sleep(APR_USEC_PER_SEC/2);
+ } }
+
+ for (int i = 0; i < 4; i++) {
+ LogString witness(LOG4CXX_STR("witness/rolling/tbr-test5."));
+ StringHelper::toString(i, pool, witness);
+ LOGUNIT_ASSERT(Compare::compare(filenames[i], File(witness)));
+ }
+ }
+
+ /**
+ * With compression, activeFileName set, no stop/restart,
+ */
+ void test6() {
+ Pool p;
+ PatternLayoutPtr layout = new PatternLayout(LOG4CXX_STR("%c{1} - %m%n"));
+ RollingFileAppenderPtr rfa = new RollingFileAppender();
+ rfa->setAppend(false);
+ rfa->setLayout(layout);
+
+ LogString datePattern = LOG4CXX_STR("yyyy-MM-dd_HH_mm_ss");
+
+ TimeBasedRollingPolicyPtr tbrp = new TimeBasedRollingPolicy();
+ tbrp->setFileNamePattern(LogString(LOG4CXX_STR("output/test6-%d{")) + datePattern + LogString(LOG4CXX_STR("}.gz")));
+ rfa->setFile(LOG4CXX_STR("output/test6.log"));
+ tbrp->activateOptions(p);
+ rfa->setRollingPolicy(tbrp);
+ rfa->activateOptions(p);
+ logger->addAppender(rfa);
+
+ DateFormatPtr sdf = new SimpleDateFormat(datePattern);
+ LogString filenames[4];
+
+ apr_time_t now = apr_time_now();
+ { for (int i = 0; i < 3; i++) {
+ filenames[i] = LOG4CXX_STR("output/test6-");
+ sdf->format(filenames[i], now, p);
+ filenames[i].append(LOG4CXX_STR(".gz"));
+ now += APR_USEC_PER_SEC;
+ } }
+
+ filenames[3] = LOG4CXX_STR("output/test6.log");
+
+ delayUntilNextSecond(100);
+
+ { for (int i = 0; i < 5; i++) {
+ std::string message("Hello---");
+ message.append(p.itoa(i));
+ LOG4CXX_DEBUG(logger, message);
+ apr_sleep(APR_USEC_PER_SEC/2);
+ } }
+
+ LOGUNIT_ASSERT_EQUAL(true, File(filenames[0]).exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File(filenames[1]).exists(p));
+ LOGUNIT_ASSERT_EQUAL(true, File(filenames[2]).exists(p));
+
+ LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File(filenames[3]), File(LOG4CXX_STR("witness/rolling/tbr-test6.3"))));
+
+ }
+
+ void delayUntilNextSecond(int millis) {
+ apr_time_t now = apr_time_now();
+ apr_time_t next = ((now / APR_USEC_PER_SEC) + 1) * APR_USEC_PER_SEC
+ + millis * 1000L;
+
+ apr_sleep(next - now);
+ }
+
+ void delayUntilNextMinute(int seconds) {
+ apr_time_t now = apr_time_now();
+ apr_time_t next = ((now / APR_USEC_PER_SEC) + 1) * APR_USEC_PER_SEC
+ + seconds * 1000000L;
+
+ apr_sleep(next - now);
+ }
+
+};
+
+
+LoggerPtr TimeBasedRollingTest::logger(Logger::getLogger("org.apache.log4j.TimeBasedRollingTest"));
+
+LOGUNIT_TEST_SUITE_REGISTRATION(TimeBasedRollingTest);
diff --git a/src/test/cpp/rollingfileappendertestcase.cpp b/src/test/cpp/rollingfileappendertestcase.cpp
new file mode 100644
index 0000000..7bf1d75
--- /dev/null
+++ b/src/test/cpp/rollingfileappendertestcase.cpp
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/rolling/rollingfileappender.h>
+#include "fileappendertestcase.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+/**
+ Unit tests of log4cxx::RollingFileAppender
+ */
+class RollingFileAppenderTestCase : public FileAppenderAbstractTestCase
+{
+ LOGUNIT_TEST_SUITE(RollingFileAppenderTestCase);
+ //
+ // tests inherited from AppenderSkeletonTestCase
+ //
+ LOGUNIT_TEST(testDefaultThreshold);
+ LOGUNIT_TEST(testSetOptionThreshold);
+
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+
+ FileAppender* createFileAppender() const {
+ return new log4cxx::rolling::RollingFileAppender();
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(RollingFileAppenderTestCase);
diff --git a/src/test/cpp/spi/loggingeventtest.cpp b/src/test/cpp/spi/loggingeventtest.cpp
new file mode 100644
index 0000000..bbe6b84
--- /dev/null
+++ b/src/test/cpp/spi/loggingeventtest.cpp
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/spi/loggingevent.h>
+#include "../util/serializationtesthelper.h"
+#include <log4cxx/logmanager.h>
+#include <log4cxx/ndc.h>
+#include <log4cxx/mdc.h>
+#include "../logunit.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::util;
+using namespace log4cxx::spi;
+using namespace std;
+
+
+/**
+ Unit tests for LoggingEvent
+ */
+LOGUNIT_CLASS(LoggingEventTest)
+{
+ LOGUNIT_TEST_SUITE(LoggingEventTest);
+ LOGUNIT_TEST(testSerializationSimple);
+ LOGUNIT_TEST(testSerializationWithLocation);
+ LOGUNIT_TEST(testSerializationNDC);
+ LOGUNIT_TEST(testSerializationMDC);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ void setUp() {
+ NDC::clear();
+ MDC::clear();
+ }
+
+ void tearDown()
+ {
+ LogManager::shutdown();
+ }
+
+
+
+
+ /**
+ * Serialize a simple logging event and check it against
+ * a witness.
+ * @throws Exception if exception during test.
+ */
+ void testSerializationSimple() {
+ LoggingEventPtr event =
+ new LoggingEvent(
+ LOG4CXX_STR("root"), Level::getInfo(), LOG4CXX_STR("Hello, world."), LocationInfo::getLocationUnavailable());
+
+ LOGUNIT_ASSERT_EQUAL(true, SerializationTestHelper::compare(
+ "witness/serialization/simple.bin", event, 237));
+ }
+
+
+ /**
+ * Serialize a logging event with an exception and check it against
+ * a witness.
+ * @throws Exception if exception during test.
+ *
+ */
+ void testSerializationWithLocation() {
+ LoggingEventPtr event =
+ new LoggingEvent(
+ LOG4CXX_STR("root"), Level::getInfo(), LOG4CXX_STR("Hello, world."), LOG4CXX_LOCATION);
+
+ LOGUNIT_ASSERT_EQUAL(true, SerializationTestHelper::compare(
+ "witness/serialization/location.bin", event, 237));
+ }
+
+ /**
+ * Serialize a logging event with ndc.
+ * @throws Exception if exception during test.
+ *
+ */
+ void testSerializationNDC() {
+ NDC::push("ndc test");
+
+ LoggingEventPtr event =
+ new LoggingEvent(
+ LOG4CXX_STR("root"), Level::getInfo(), LOG4CXX_STR("Hello, world."), LocationInfo::getLocationUnavailable());
+
+ LOGUNIT_ASSERT_EQUAL(true, SerializationTestHelper::compare(
+ "witness/serialization/ndc.bin", event, 237));
+ }
+
+ /**
+ * Serialize a logging event with mdc.
+ * @throws Exception if exception during test.
+ *
+ */
+ void testSerializationMDC() {
+ MDC::put("mdckey", "mdcvalue");
+
+ LoggingEventPtr event =
+ new LoggingEvent(
+ LOG4CXX_STR("root"), Level::getInfo(), LOG4CXX_STR("Hello, world."), LocationInfo::getLocationUnavailable());
+
+ LOGUNIT_ASSERT_EQUAL(true, SerializationTestHelper::compare(
+ "witness/serialization/mdc.bin", event, 237));
+ }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(LoggingEventTest);
diff --git a/src/test/cpp/streamtestcase.cpp b/src/test/cpp/streamtestcase.cpp
new file mode 100644
index 0000000..164a285
--- /dev/null
+++ b/src/test/cpp/streamtestcase.cpp
@@ -0,0 +1,619 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <ostream>
+#include <iomanip>
+
+#include "vectorappender.h"
+#include <log4cxx/logmanager.h>
+#include <log4cxx/simplelayout.h>
+#include <log4cxx/spi/loggingevent.h>
+#include "insertwide.h"
+#include "logunit.h"
+#include <log4cxx/stream.h>
+
+#if LOG4CXX_CFSTRING_API
+#include <CoreFoundation/CFString.h>
+#endif
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace std;
+
+class ExceptionOnInsert {
+public:
+ ExceptionOnInsert() {
+ }
+};
+
+//
+// define an insertion operation that will throw an
+// exception to test that evaluation was short
+// circuited
+//
+template<class Elem, class Tr>
+::std::basic_ostream<Elem, Tr>& operator<<(
+ ::std::basic_ostream<Elem, Tr>&,
+ const ExceptionOnInsert&) {
+ throw std::exception();
+}
+
+
+/**
+ Unit tests for the optional stream-like interface for log4cxx
+ */
+LOGUNIT_CLASS(StreamTestCase)
+{
+ LOGUNIT_TEST_SUITE(StreamTestCase);
+ LOGUNIT_TEST(testSimple);
+ LOGUNIT_TEST(testMultiple);
+ LOGUNIT_TEST(testShortCircuit);
+ LOGUNIT_TEST_EXCEPTION(testInsertException, std::exception);
+ LOGUNIT_TEST(testScientific);
+ LOGUNIT_TEST(testPrecision);
+ LOGUNIT_TEST(testWidth);
+#if LOG4CXX_WCHAR_T_API
+ LOGUNIT_TEST(testWide);
+ LOGUNIT_TEST(testWideAppend);
+ LOGUNIT_TEST(testWideWidth);
+#endif
+ LOGUNIT_TEST(testBaseFlags);
+ LOGUNIT_TEST(testBasePrecisionAndWidth);
+ LOGUNIT_TEST(testLogStreamSimple);
+ LOGUNIT_TEST(testLogStreamMultiple);
+ LOGUNIT_TEST(testLogStreamShortCircuit);
+ LOGUNIT_TEST_EXCEPTION(testLogStreamInsertException, std::exception);
+ LOGUNIT_TEST(testLogStreamScientific);
+ LOGUNIT_TEST(testLogStreamPrecision);
+ LOGUNIT_TEST(testLogStreamWidth);
+ LOGUNIT_TEST(testLogStreamDelegate);
+ LOGUNIT_TEST(testLogStreamFormattingPersists);
+ LOGUNIT_TEST(testSetWidthInsert);
+#if LOG4CXX_WCHAR_T_API
+ LOGUNIT_TEST(testWLogStreamSimple);
+ LOGUNIT_TEST(testWLogStreamMultiple);
+ LOGUNIT_TEST(testWLogStreamShortCircuit);
+ LOGUNIT_TEST_EXCEPTION(testWLogStreamInsertException, std::exception);
+ LOGUNIT_TEST(testWLogStreamScientific);
+ LOGUNIT_TEST(testWLogStreamPrecision);
+ LOGUNIT_TEST(testWLogStreamWidth);
+ LOGUNIT_TEST(testWLogStreamDelegate);
+ LOGUNIT_TEST(testWLogStreamFormattingPersists);
+ LOGUNIT_TEST(testWSetWidthInsert);
+#endif
+#if LOG4CXX_UNICHAR_API
+ LOGUNIT_TEST(testUniChar);
+ LOGUNIT_TEST(testUniCharAppend);
+// LOGUNIT_TEST(testUniCharWidth);
+ LOGUNIT_TEST(testULogStreamSimple);
+ LOGUNIT_TEST(testULogStreamMultiple);
+ LOGUNIT_TEST(testULogStreamShortCircuit);
+ LOGUNIT_TEST_EXCEPTION(testULogStreamInsertException, std::exception);
+// LOGUNIT_TEST(testULogStreamScientific);
+// LOGUNIT_TEST(testULogStreamPrecision);
+// LOGUNIT_TEST(testULogStreamWidth);
+ LOGUNIT_TEST(testULogStreamDelegate);
+// LOGUNIT_TEST(testULogStreamFormattingPersists);
+// LOGUNIT_TEST(testUSetWidthInsert);
+#endif
+#if LOG4CXX_CFSTRING_API
+ LOGUNIT_TEST(testCFString);
+ LOGUNIT_TEST(testCFStringAppend);
+ LOGUNIT_TEST(testULogStreamCFString);
+ LOGUNIT_TEST(testULogStreamCFString2);
+#endif
+ LOGUNIT_TEST_SUITE_END();
+
+ VectorAppenderPtr vectorAppender;
+
+public:
+ void setUp() {
+ LoggerPtr root(Logger::getRootLogger());
+ LayoutPtr layout(new SimpleLayout());
+ vectorAppender = new VectorAppender();
+ root->addAppender(vectorAppender);
+ }
+
+ void tearDown()
+ {
+ LogManager::shutdown();
+ }
+
+ void testSimple() {
+ LoggerPtr root(Logger::getRootLogger());
+ LOG4CXX_INFO(root, "This is a test");
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testMultiple() {
+ LoggerPtr root(Logger::getRootLogger());
+ LOG4CXX_INFO(root, "This is a test" << ": Details to follow");
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testShortCircuit() {
+ LoggerPtr logger(Logger::getLogger("StreamTestCase.shortCircuit"));
+ logger->setLevel(Level::getInfo());
+ ExceptionOnInsert someObj;
+ LOG4CXX_DEBUG(logger, someObj);
+ LOGUNIT_ASSERT_EQUAL((size_t) 0, vectorAppender->getVector().size());
+ }
+
+ void testInsertException() {
+ LoggerPtr logger(Logger::getLogger("StreamTestCase.insertException"));
+ ExceptionOnInsert someObj;
+ LOG4CXX_INFO(logger, someObj);
+ }
+
+ void testScientific() {
+ LoggerPtr root(Logger::getRootLogger());
+ LOG4CXX_INFO(root, std::scientific << 0.000001115);
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT(msg.find(LOG4CXX_STR("e-")) != LogString::npos ||
+ msg.find(LOG4CXX_STR("E-")) != LogString::npos);
+ }
+
+ void testPrecision() {
+ LoggerPtr root(Logger::getRootLogger());
+ LOG4CXX_INFO(root, std::setprecision(4) << 1.000001);
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT(msg.find(LOG4CXX_STR("1.00000")) == LogString::npos);
+ }
+
+
+ void testWidth() {
+ LoggerPtr root(Logger::getRootLogger());
+ LOG4CXX_INFO(root, '[' << std::fixed << std::setprecision(2) << std::setw(7) << std::right << std::setfill('_') << 10.0 << ']');
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("[__10.00]")), msg);
+ }
+
+ void testBaseFlags() {
+ logstream base1(Logger::getRootLogger(), Level::getInfo());
+ logstream base2(Logger::getRootLogger(), Level::getInfo());
+ base1 << std::boolalpha;
+ base2 << std::noboolalpha;
+ std::ostringstream os1a, os1b, os2a, os2b;
+ os1a << std::boolalpha;
+ int fillchar;
+ if (base1.set_stream_state(os1b, fillchar)) {
+ os1b.fill(fillchar);
+ }
+ LOGUNIT_ASSERT_EQUAL(os1a.flags(), os1b.flags());
+ os2a << std::noboolalpha;
+ if (base2.set_stream_state(os2b, fillchar)) {
+ os2b.fill(fillchar);
+ }
+ LOGUNIT_ASSERT_EQUAL(os2a.flags(), os2b.flags());
+ }
+
+
+ void testBasePrecisionAndWidth() {
+ logstream base(Logger::getRootLogger(), Level::getInfo());
+ base.precision(2);
+ base.width(5);
+ std::ostringstream os1, os2;
+ os1.precision(2);
+ os1.width(5);
+ os1 << 3.1415926;
+ int fillchar;
+ if (base.set_stream_state(os2, fillchar)) {
+ os2.fill(fillchar);
+ }
+ os2 << 3.1415926;
+ string expected(os1.str());
+ string actual(os2.str());
+ LOGUNIT_ASSERT_EQUAL(expected, actual);
+ }
+
+ void testLogStreamSimple() {
+ logstream root(Logger::getRootLogger(), Level::getInfo());
+ root << "This is a test" << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testLogStreamMultiple() {
+ logstream root(Logger::getRootLogger(), Level::getInfo());
+ root << "This is a test" << ": Details to follow" << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testLogStreamShortCircuit() {
+ LoggerPtr logger(Logger::getLogger("StreamTestCase.shortCircuit"));
+ logger->setLevel(Level::getInfo());
+ logstream os(logger, Level::getDebug());
+ ExceptionOnInsert someObj;
+ os << someObj << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 0, vectorAppender->getVector().size());
+ }
+
+ void testLogStreamInsertException() {
+ LoggerPtr logger(Logger::getLogger("StreamTestCase.insertException"));
+ ExceptionOnInsert someObj;
+ logstream os(logger, Level::getInfo());
+ os << someObj << LOG4CXX_ENDMSG;
+ }
+
+ void testLogStreamScientific() {
+ LoggerPtr root(Logger::getRootLogger());
+ logstream os(root, Level::getInfo());
+ os << std::scientific << 0.000001115 << LOG4CXX_ENDMSG;
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT(msg.find(LOG4CXX_STR("e-")) != LogString::npos ||
+ msg.find(LOG4CXX_STR("E-")) != LogString::npos);
+ }
+
+ void testLogStreamPrecision() {
+ LoggerPtr root(Logger::getRootLogger());
+ logstream os(root, Level::getInfo());
+ os << std::setprecision(4) << 1.000001 << LOG4CXX_ENDMSG;
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT(msg.find(LOG4CXX_STR("1.00000")) == LogString::npos);
+ }
+
+
+ void testLogStreamWidth() {
+ LoggerPtr root(Logger::getRootLogger());
+ logstream os(root, Level::getInfo());
+ os << '[' << std::fixed << std::setprecision(2) << std::setw(7) << std::right << std::setfill('_') << 10.0 << ']' << LOG4CXX_ENDMSG;
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("[__10.00]")), msg);
+ }
+
+ void report(std::ostream& os) {
+ os << "This just in: \n";
+ os << "Use logstream in places that expect a std::ostream.\n";
+ }
+
+ void testLogStreamDelegate() {
+ logstream root(Logger::getRootLogger(), Level::getInfo());
+ report(root);
+ root << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testLogStreamFormattingPersists() {
+ LoggerPtr root(Logger::getRootLogger());
+ root->setLevel(Level::getInfo());
+ logstream os(root, Level::getDebug());
+ os << std::hex << 20 << LOG4CXX_ENDMSG;
+ os << Level::getInfo() << 16 << LOG4CXX_ENDMSG;
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("10")), msg);
+ }
+
+ void testSetWidthInsert() {
+ LoggerPtr root(Logger::getRootLogger());
+ root->setLevel(Level::getInfo());
+ logstream os(root, Level::getInfo());
+ os << std::setw(5);
+ LOGUNIT_ASSERT_EQUAL(5, os.width());
+ }
+
+
+
+#if LOG4CXX_WCHAR_T_API
+ void testWide() {
+ LoggerPtr root(Logger::getRootLogger());
+ LOG4CXX_INFO(root, L"This is a test");
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testWideAppend() {
+ LoggerPtr root(Logger::getRootLogger());
+ LOG4CXX_INFO(root, L"This is a test" << L": Details to follow");
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testWideWidth() {
+ LoggerPtr root(Logger::getRootLogger());
+ LOG4CXX_INFO(root, L'[' << std::fixed << std::setprecision(2) << std::setw(7) << std::right << std::setfill(L'_') << 10.0 << L"]");
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("[__10.00]")), msg);
+ }
+
+ void testWLogStreamSimple() {
+ wlogstream root(Logger::getRootLogger(), Level::getInfo());
+ root << L"This is a test" << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testWLogStreamMultiple() {
+ wlogstream root(Logger::getRootLogger(), Level::getInfo());
+ root << L"This is a test" << L": Details to follow" << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testWLogStreamShortCircuit() {
+ LoggerPtr logger(Logger::getLogger("StreamTestCase.shortCircuit"));
+ logger->setLevel(Level::getInfo());
+ wlogstream os(logger, Level::getDebug());
+ ExceptionOnInsert someObj;
+ os << someObj << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 0, vectorAppender->getVector().size());
+ }
+
+ void testWLogStreamInsertException() {
+ LoggerPtr logger(Logger::getLogger("StreamTestCase.insertException"));
+ ExceptionOnInsert someObj;
+ wlogstream os(logger, Level::getInfo());
+ os << someObj << LOG4CXX_ENDMSG;
+ }
+
+ void testWLogStreamScientific() {
+ LoggerPtr root(Logger::getRootLogger());
+ wlogstream os(root, Level::getInfo());
+ os << std::scientific << 0.000001115 << LOG4CXX_ENDMSG;
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT(msg.find(LOG4CXX_STR("e-")) != LogString::npos ||
+ msg.find(LOG4CXX_STR("E-")) != LogString::npos);
+ }
+
+ void testWLogStreamPrecision() {
+ LoggerPtr root(Logger::getRootLogger());
+ wlogstream os(root, Level::getInfo());
+ os << std::setprecision(4) << 1.000001 << LOG4CXX_ENDMSG;
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT(msg.find(LOG4CXX_STR("1.00000")) == LogString::npos);
+ }
+
+
+ void testWLogStreamWidth() {
+ LoggerPtr root(Logger::getRootLogger());
+ wlogstream os(root, Level::getInfo());
+ os << L"[" << std::fixed << std::setprecision(2) << std::setw(7) << std::right << std::setfill(L'_') << 10.0 << L"]" << LOG4CXX_ENDMSG;
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("[__10.00]")), msg);
+ }
+
+ void wreport(std::basic_ostream<wchar_t>& os) {
+ os << L"This just in: \n";
+ os << L"Use logstream in places that expect a std::ostream.\n";
+ }
+
+ void testWLogStreamDelegate() {
+ wlogstream root(Logger::getRootLogger(), Level::getInfo());
+ wreport(root);
+ root << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testWLogStreamFormattingPersists() {
+ LoggerPtr root(Logger::getRootLogger());
+ root->setLevel(Level::getInfo());
+ wlogstream os(root, Level::getDebug());
+ os << std::hex << 20 << LOG4CXX_ENDMSG;
+ os << Level::getInfo() << 16 << LOG4CXX_ENDMSG;
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("10")), msg);
+ }
+
+ void testWSetWidthInsert() {
+ LoggerPtr root(Logger::getRootLogger());
+ root->setLevel(Level::getInfo());
+ wlogstream os(root, Level::getInfo());
+ os << std::setw(5);
+ LOGUNIT_ASSERT_EQUAL(5, os.width());
+ }
+
+#endif
+
+#if LOG4CXX_UNICHAR_API
+ void testUniChar() {
+ LoggerPtr root(Logger::getRootLogger());
+ const log4cxx::UniChar msg[] = { 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', 0 };
+ LOG4CXX_INFO(root, msg);
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testUniCharAppend() {
+ LoggerPtr root(Logger::getRootLogger());
+ const log4cxx::UniChar msg1[] = { 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', 0 };
+ const log4cxx::UniChar msg2[] = { ':', ' ', 'D', 'e', 't', 'a', 'i', 'l', 's', ' ', 't', 'o', ' ', 'f', 'o', 'l', 'l', 'o', 'w', 0 };
+ LOG4CXX_INFO(root, msg1 << msg2);
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testUniCharWidth() {
+ LoggerPtr root(Logger::getRootLogger());
+ const log4cxx::UniChar openBracket[] = { '[', 0 };
+ const log4cxx::UniChar closeBracket[] = { ']', 0 };
+ LOG4CXX_INFO(root, openBracket << std::fixed << std::setprecision(2) << std::setw(7) << std::right << std::setfill((log4cxx::UniChar) '_') << 10.0 << closeBracket);
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("[__10.00]")), msg);
+ }
+
+ void testULogStreamSimple() {
+ ulogstream root(Logger::getRootLogger(), Level::getInfo());
+ const log4cxx::UniChar msg[] = { 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', 0 };
+ root << msg << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testULogStreamMultiple() {
+ ulogstream root(Logger::getRootLogger(), Level::getInfo());
+ const log4cxx::UniChar msg1[] = { 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', 0 };
+ const log4cxx::UniChar msg2[] = { ':', ' ', 'D', 'e', 't', 'a', 'i', 'l', 's', ' ', 't', 'o', ' ', 'f', 'o', 'l', 'l', 'o', 'w', 0 };
+ root << msg1 << msg2 << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testULogStreamShortCircuit() {
+ LoggerPtr logger(Logger::getLogger("StreamTestCase.shortCircuit"));
+ logger->setLevel(Level::getInfo());
+ ulogstream os(logger, Level::getDebug());
+ ExceptionOnInsert someObj;
+ os << someObj << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 0, vectorAppender->getVector().size());
+ }
+
+ void testULogStreamInsertException() {
+ LoggerPtr logger(Logger::getLogger("StreamTestCase.insertException"));
+ ExceptionOnInsert someObj;
+ ulogstream os(logger, Level::getInfo());
+ os << someObj << LOG4CXX_ENDMSG;
+ }
+
+ void testULogStreamScientific() {
+ LoggerPtr root(Logger::getRootLogger());
+ ulogstream os(root, Level::getInfo());
+ os << std::scientific << 0.000001115 << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT(msg.find(LOG4CXX_STR("e-")) != LogString::npos ||
+ msg.find(LOG4CXX_STR("E-")) != LogString::npos);
+ }
+
+ void testULogStreamPrecision() {
+ LoggerPtr root(Logger::getRootLogger());
+ ulogstream os(root, Level::getInfo());
+ os << std::setprecision(4) << 1.000001 << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT(msg.find(LOG4CXX_STR("1.00000")) == LogString::npos);
+ }
+
+
+ void testULogStreamWidth() {
+ LoggerPtr root(Logger::getRootLogger());
+ ulogstream os(root, Level::getInfo());
+ const log4cxx::UniChar openBracket[] = { '[', 0 };
+ const log4cxx::UniChar closeBracket[] = { ']', 0 };
+
+ os << openBracket << std::fixed << std::setprecision(2) << std::setw(7) << std::right
+ << std::setfill((log4cxx::UniChar) '_') << 10.0 << closeBracket << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("[__10.00]")), msg);
+ }
+
+ void ureport(std::basic_ostream<log4cxx::UniChar>& os) {
+ const log4cxx::UniChar msg1[] = { 'T', 'h', 'i', 's', ' ', 'j', 'u', 's', 't', ' ' , 'i', 'n', ':', ' ' , '\n', 0 };
+ const log4cxx::UniChar msg2[] = { 'U', 's', 'e', ' ', 'l', 'o', 'g', 's', 't', 'r', 'e', 'a', 'm', '\n', 0 };
+ os << msg1;
+ os << msg2;
+ }
+
+ void testULogStreamDelegate() {
+ ulogstream root(Logger::getRootLogger(), Level::getInfo());
+ ureport(root);
+ root << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testULogStreamFormattingPersists() {
+ LoggerPtr root(Logger::getRootLogger());
+ root->setLevel(Level::getInfo());
+ ulogstream os(root, Level::getDebug());
+ os << std::hex << 20 << LOG4CXX_ENDMSG;
+ os << Level::getInfo() << 16 << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ LOGUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("10")), msg);
+ }
+
+ void testUSetWidthInsert() {
+ LoggerPtr root(Logger::getRootLogger());
+ root->setLevel(Level::getInfo());
+ ulogstream os(root, Level::getInfo());
+ os << std::setw(5);
+ LOGUNIT_ASSERT_EQUAL(5, os.width());
+ }
+
+#endif
+
+#if LOG4CXX_CFSTRING_API
+ void testCFString() {
+ LoggerPtr root(Logger::getRootLogger());
+ LOG4CXX_INFO(root, CFSTR("This is a test"));
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testCFStringAppend() {
+ LoggerPtr root(Logger::getRootLogger());
+ LOG4CXX_INFO(root, CFSTR("This is a test") << CFSTR(": Details to follow"));
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testULogStreamCFString() {
+ ulogstream root(Logger::getRootLogger(), Level::getInfo());
+ root << CFSTR("This is a test") << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+
+ void testULogStreamCFString2() {
+ ulogstream root(Logger::getRootLogger(), Level::getInfo());
+ root << CFSTR("This is a test") << CFSTR(": Details to follow") << LOG4CXX_ENDMSG;
+ LOGUNIT_ASSERT_EQUAL((size_t) 1, vectorAppender->getVector().size());
+ }
+#endif
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(StreamTestCase);
+
+
+#if !LOG4CXX_USE_GLOBAL_SCOPE_TEMPLATE
+//
+// The following code tests compilation errors
+// around bug LOGCXX-150 and is not intended to be executed.
+// Skipped for VC6 since it can't handle having the
+// templated operator<< in class scope.s
+namespace foo
+{
+ class Bar
+ {
+ void fn();
+ };
+
+std::ostream &operator<<(std::ostream &o, Bar const &b)
+ {
+ return o << "Bar";
+ }
+}
+
+
+using namespace foo;
+
+namespace
+{
+ log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("foo"));
+ log4cxx::logstream lout(logger, log4cxx::Level::getDebug());
+}
+
+void Bar::fn()
+{
+ lout << "hi" << LOG4CXX_ENDMSG;
+}
+#endif
+
diff --git a/src/test/cpp/testchar.h b/src/test/cpp/testchar.h
new file mode 100644
index 0000000..0ea7559
--- /dev/null
+++ b/src/test/cpp/testchar.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_LOG4CXX_TESTCHAR_H)
+#define _LOG4CXX_TESTCHAR_H
+
+//
+// This macro and typedef lets many tests
+// check either the wchar_t or char based methods.
+//
+#if LOG4CXX_WCHAR_T_API && defined(LOG4CXX_TEST_WCHAR)
+#define LOG4CXX_TEST_STR(str) L ## str
+typedef wchar_t testchar;
+#else
+#define LOG4CXX_TEST_STR(str) str
+typedef char testchar;
+#endif
+
+#endif
diff --git a/src/test/cpp/testutil.h b/src/test/cpp/testutil.h
new file mode 100644
index 0000000..4de86b4
--- /dev/null
+++ b/src/test/cpp/testutil.h
@@ -0,0 +1,28 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "abts.h"
+
+#ifndef APR_TEST_UTIL
+#define APR_TEST_UTIL
+
+
+
+void initialize(void);
+abts_suite* abts_run_suites(abts_suite*);
+
+
+#endif /* APR_TEST_INCLUDES */
diff --git a/src/test/cpp/util/absolutedateandtimefilter.cpp b/src/test/cpp/util/absolutedateandtimefilter.cpp
new file mode 100644
index 0000000..0e99213
--- /dev/null
+++ b/src/test/cpp/util/absolutedateandtimefilter.cpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "absolutedateandtimefilter.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+AbsoluteDateAndTimeFilter::AbsoluteDateAndTimeFilter() :
+ Filter(ABSOLUTE_DATE_AND_TIME_PAT, "") {}
diff --git a/src/test/cpp/util/absolutedateandtimefilter.h b/src/test/cpp/util/absolutedateandtimefilter.h
new file mode 100644
index 0000000..98398eb
--- /dev/null
+++ b/src/test/cpp/util/absolutedateandtimefilter.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_ABS_DATE_TIME_FILTER_H
+#define _LOG4CXX_TESTS_UTIL_ABS_DATE_TIME_FILTER_H
+
+#include "filter.h"
+
+namespace log4cxx
+{
+ class AbsoluteDateAndTimeFilter : public Filter
+ {
+ public:
+ AbsoluteDateAndTimeFilter();
+ };
+}
+
+
+#endif //_LOG4CXX_TESTS_UTIL_ABS_DATE_TIME_FILTER_H
diff --git a/src/test/cpp/util/absolutetimefilter.cpp b/src/test/cpp/util/absolutetimefilter.cpp
new file mode 100644
index 0000000..082a579
--- /dev/null
+++ b/src/test/cpp/util/absolutetimefilter.cpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "absolutetimefilter.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+AbsoluteTimeFilter::AbsoluteTimeFilter()
+ : Filter(ABSOLUTE_TIME_PAT, "") {}
diff --git a/src/test/cpp/util/absolutetimefilter.h b/src/test/cpp/util/absolutetimefilter.h
new file mode 100644
index 0000000..5869da4
--- /dev/null
+++ b/src/test/cpp/util/absolutetimefilter.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_ABS_TIME_FILTER_H
+#define _LOG4CXX_TESTS_UTIL_ABS_TIME_FILTER_H
+
+#include "filter.h"
+
+namespace log4cxx
+{
+ class AbsoluteTimeFilter : public Filter
+ {
+ public:
+ AbsoluteTimeFilter();
+ };
+}
+
+
+#endif //_LOG4CXX_TESTS_UTIL_ABS_TIME_FILTER_H
diff --git a/src/test/cpp/util/binarycompare.cpp b/src/test/cpp/util/binarycompare.cpp
new file mode 100644
index 0000000..917416b
--- /dev/null
+++ b/src/test/cpp/util/binarycompare.cpp
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "binarycompare.h"
+#include <apr_file_io.h>
+#include <log4cxx/helpers/pool.h>
+#include "../logunit.h"
+#include <apr_pools.h>
+#include <apr_strings.h>
+
+using namespace log4cxx;
+using namespace log4cxx::util;
+using namespace log4cxx::helpers;
+
+void BinaryCompare::compare(const char* filename1,
+ const char* filename2) {
+ Pool p;
+ apr_pool_t* pool = p.getAPRPool();
+ apr_file_t* file1;
+ apr_int32_t flags = APR_FOPEN_READ;
+ apr_fileperms_t perm = APR_OS_DEFAULT;
+ apr_status_t stat1 = apr_file_open(&file1,
+ filename1, flags, perm, pool);
+ if (stat1 != APR_SUCCESS) {
+ LOGUNIT_FAIL(std::string("Unable to open ") + filename1);
+ }
+
+ apr_file_t* file2;
+ apr_status_t stat2 = apr_file_open(&file2,
+ filename2, flags, perm, pool);
+ if (stat2 != APR_SUCCESS) {
+ LOGUNIT_FAIL(std::string("Unable to open ") + filename2);
+ }
+
+ enum { BUFSIZE = 1024 };
+ char* contents1 = (char*) apr_palloc(pool, BUFSIZE);
+ char* contents2 = (char*) apr_palloc(pool, BUFSIZE);
+ memset(contents1, 0, BUFSIZE);
+ memset(contents2, 0, BUFSIZE);
+ apr_size_t bytesRead1 = BUFSIZE;
+ apr_size_t bytesRead2 = BUFSIZE;
+
+ stat1 = apr_file_read(file1, contents1, &bytesRead1);
+ if (stat1 != APR_SUCCESS) {
+ LOGUNIT_FAIL(std::string("Unable to read ") + filename1);
+ }
+
+ stat2 = apr_file_read(file2, contents2, &bytesRead2);
+ if (stat2 != APR_SUCCESS) {
+ LOGUNIT_FAIL(std::string("Unable to read ") + filename2);
+ }
+
+ for (int i = 0; i < BUFSIZE; i++) {
+ if (contents1[i] != contents2[i]) {
+ std::string msg("Contents differ at position ");
+ msg += apr_itoa(pool, i);
+ msg += ": [";
+ msg += filename1;
+ msg += "] has ";
+ msg += apr_itoa(pool, contents1[i]);
+ msg += ", [";
+ msg += filename2;
+ msg += "] has ";
+ msg += apr_itoa(pool, contents2[i]);
+ msg += ".";
+ LOGUNIT_FAIL(msg);
+ }
+ }
+}
diff --git a/src/test/cpp/util/binarycompare.h b/src/test/cpp/util/binarycompare.h
new file mode 100644
index 0000000..d4706f3
--- /dev/null
+++ b/src/test/cpp/util/binarycompare.h
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+
+namespace log4cxx
+{
+ namespace util {
+ class BinaryCompare
+ {
+ private:
+ /**
+ * Class can not be constructed.
+ */
+ BinaryCompare();
+
+ public:
+ static void compare(const char* filename1,
+ const char* filename2);
+ };
+ }
+}
diff --git a/src/test/cpp/util/compare.cpp b/src/test/cpp/util/compare.cpp
new file mode 100644
index 0000000..6c8aa07
--- /dev/null
+++ b/src/test/cpp/util/compare.cpp
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "compare.h"
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/file.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/fileinputstream.h>
+#include <log4cxx/helpers/inputstreamreader.h>
+#include <log4cxx/helpers/systemoutwriter.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+bool Compare::compare(const File& file1, const File& file2)
+{
+ Pool pool;
+ InputStreamPtr fileIn1 = new FileInputStream(file1);
+ InputStreamReaderPtr reader1 = new InputStreamReader(fileIn1);
+ LogString in1(reader1->read(pool));
+
+ Pool pool2;
+ InputStreamPtr fileIn2 = new FileInputStream(file2);
+ InputStreamReaderPtr reader2 = new InputStreamReader(fileIn2);
+ LogString in2(reader2->read(pool2));
+
+ LogString back1(in1);
+ LogString back2(in2);
+
+ LogString s1;
+ LogString s2;
+ int lineCounter = 0;
+
+ while (getline(in1, s1))
+ {
+ lineCounter++;
+
+ if(!getline(in2, s2)) {
+ s2.erase(s2.begin(), s2.end());
+ }
+
+ if (s1 != s2) {
+ LogString msg(LOG4CXX_STR("Files ["));
+ msg += file1.getPath();
+ msg += LOG4CXX_STR("] and [");
+ msg += file2.getPath();
+ msg += LOG4CXX_STR("] differ on line ");
+ StringHelper::toString(lineCounter, pool, msg);
+ msg += LOG4CXX_EOL;
+ msg += LOG4CXX_STR("One reads: [");
+ msg += s1;
+ msg += LOG4CXX_STR("].");
+ msg += LOG4CXX_EOL;
+ msg += LOG4CXX_STR("Other reads:[");
+ msg += s2;
+ msg += LOG4CXX_STR("].");
+ msg += LOG4CXX_EOL;
+ emit(msg);
+
+ outputFile(file1, back1, pool);
+ outputFile(file2, back2, pool);
+
+ return false;
+ }
+ }
+
+ // the second file is longer
+ if (getline(in2, s2)) {
+ LogString msg(LOG4CXX_STR("File ["));
+ msg += file2.getPath();
+ msg += LOG4CXX_STR("] longer than file [");
+ msg += file1.getPath();
+ msg += LOG4CXX_STR("].");
+ msg += LOG4CXX_EOL;
+ emit(msg);
+ outputFile(file1, back1, pool);
+ outputFile(file2, back2, pool);
+
+ return false;
+ }
+
+ return true;
+}
+
+void Compare::outputFile(const File& file,
+ const LogString& contents,
+ log4cxx::helpers::Pool& pool)
+{
+ int lineCounter = 0;
+ emit(LOG4CXX_STR("--------------------------------"));
+ emit(LOG4CXX_EOL);
+ LogString msg(LOG4CXX_STR("Contents of "));
+ msg += file.getPath();
+ msg += LOG4CXX_STR(":");
+ msg += LOG4CXX_EOL;
+ emit(msg);
+ LogString in1(contents);
+ LogString s1;
+
+ while (getline(in1, s1))
+ {
+ lineCounter++;
+ LogString line;
+ StringHelper::toString(lineCounter, pool, line);
+ emit(line);
+
+ if (lineCounter < 10)
+ {
+ emit(LOG4CXX_STR(" : "));
+ }
+ else if (lineCounter < 100)
+ {
+ emit(LOG4CXX_STR(" : "));
+ }
+ else if (lineCounter < 1000)
+ {
+ emit(LOG4CXX_STR(" : "));
+ }
+ else
+ {
+ emit(LOG4CXX_STR(": "));
+ }
+ emit(s1);
+ emit(LOG4CXX_EOL);
+ }
+}
+
+void Compare::emit(const LogString& s1) {
+ SystemOutWriter::write(s1);
+}
+
+
+bool Compare::getline(LogString& in, LogString& line) {
+ if (in.empty()) {
+ return false;
+ }
+ size_t nl = in.find(0x0A);
+ if (nl == std::string::npos) {
+ line = in;
+ in.erase(in.begin(), in.end());
+ } else {
+ //
+ // if the file has CR-LF then
+ // drop the carriage return alse
+ //
+ if(nl > 0 && in[nl -1] == 0x0D) {
+ line.assign(in, 0, nl - 1);
+ } else {
+ line.assign(in, 0, nl);
+ }
+ in.erase(in.begin(), in.begin() + nl + 1);
+ }
+ return true;
+}
+
+
diff --git a/src/test/cpp/util/compare.h b/src/test/cpp/util/compare.h
new file mode 100644
index 0000000..656ebd2
--- /dev/null
+++ b/src/test/cpp/util/compare.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logstring.h>
+
+namespace log4cxx
+{
+ class File;
+ namespace helpers {
+ class Pool;
+ }
+
+ class Compare
+ {
+ public:
+ static bool compare(const File& file1,
+ const File& file2);
+
+ private:
+ /// Prints file on the console.
+ static void outputFile(const File& file,
+ const LogString& contents,
+ log4cxx::helpers::Pool& pool);
+
+ static void emit(const LogString &line);
+ static bool getline(LogString& buf, LogString& line);
+
+ };
+}
diff --git a/src/test/cpp/util/controlfilter.cpp b/src/test/cpp/util/controlfilter.cpp
new file mode 100644
index 0000000..dfd7dec
--- /dev/null
+++ b/src/test/cpp/util/controlfilter.cpp
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "controlfilter.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+ControlFilter::ControlFilter()
+{
+}
+
+ControlFilter& ControlFilter::operator<<(const std::string&)
+{
+ return *this;
+}
diff --git a/src/test/cpp/util/controlfilter.h b/src/test/cpp/util/controlfilter.h
new file mode 100644
index 0000000..5d1b77c
--- /dev/null
+++ b/src/test/cpp/util/controlfilter.h
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_CONTROL_FILTER_H
+#define _LOG4CXX_TESTS_UTIL_CONTROL_FILTER_H
+
+#include "filter.h"
+#include <vector>
+
+namespace log4cxx
+{
+ class ControlFilter : public Filter
+ {
+ public:
+ ControlFilter();
+ ControlFilter& operator<<(const std::string& allowedPattern);
+
+ };
+}
+
+
+#endif //_LOG4CXX_TESTS_UTIL_CONTROL_FILTER_H
diff --git a/src/test/cpp/util/filenamefilter.cpp b/src/test/cpp/util/filenamefilter.cpp
new file mode 100644
index 0000000..af45768
--- /dev/null
+++ b/src/test/cpp/util/filenamefilter.cpp
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "filenamefilter.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+FilenameFilter::FilenameFilter(const std::string& actual, const std::string& expected) {
+ std::string pattern(actual);
+ size_t backslash = pattern.rfind('\\', pattern.length() - 1);
+ while (backslash != std::string::npos) {
+ pattern.replace(backslash, 1, "\\\\", 2);
+ if (backslash == 0) {
+ backslash = std::string::npos;
+ } else {
+ backslash = pattern.rfind('\\', backslash - 1);
+ }
+ }
+
+ patterns.push_back( PatternReplacement(pattern, expected) );
+}
+
+
diff --git a/src/test/cpp/util/filenamefilter.h b/src/test/cpp/util/filenamefilter.h
new file mode 100644
index 0000000..ce12bc6
--- /dev/null
+++ b/src/test/cpp/util/filenamefilter.h
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_FILENAME_FILTER_H
+#define _LOG4CXX_TESTS_UTIL_FILENAME_FILTER_H
+
+#include "filter.h"
+
+namespace log4cxx
+{
+ class FilenameFilter : public Filter
+ {
+ public:
+ FilenameFilter(const std::string& actual, const std::string& expected);
+ static const std::string getMatch(const std::string& actual);
+ };
+}
+
+
+#endif //_LOG4CXX_TESTS_UTIL_FILENAME_FILTER_H
diff --git a/src/test/cpp/util/filter.h b/src/test/cpp/util/filter.h
new file mode 100644
index 0000000..9f999df
--- /dev/null
+++ b/src/test/cpp/util/filter.h
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_FILTER_H
+#define _LOG4CXX_TESTS_UTIL_FILTER_H
+
+#if defined(_MSC_VER)
+#pragma warning (push)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+#include <string>
+#include <vector>
+#include <map>
+#include <log4cxx/helpers/exception.h>
+
+#define BASIC_PAT "\\[0x[0-9A-F]*] (FATAL|ERROR|WARN|INFO|DEBUG)"
+#define ISO8601_PAT "[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [0-9]\\{2\\}:[0-9]\\{2\\}:[0-9]\\{2\\},[0-9]\\{3\\}"
+#define ABSOLUTE_DATE_AND_TIME_PAT \
+ "[0-9]\\{1,2\\} .* 200[0-9] [0-9]\\{2\\}:[0-9]\\{2\\}:[0-9]\\{2\\},[0-9]\\{3\\}"
+#define ABSOLUTE_TIME_PAT "[0-2][0-9]:[0-9][0-9]:[0-9][0-9],[0-9][0-9][0-9]"
+#define RELATIVE_TIME_PAT "^[0-9]+"
+
+namespace log4cxx
+{
+ class UnexpectedFormatException : public std::exception {
+ };
+
+ class Filter
+ {
+ public:
+ Filter(const std::string& match, const std::string& replacement);
+ Filter();
+ virtual ~Filter();
+
+ typedef std::pair<std::string, std::string> PatternReplacement;
+ typedef std::vector <PatternReplacement> PatternList;
+ const PatternList& getPatterns() const{
+ return patterns;
+ }
+
+ private:
+ Filter(const Filter&);
+ Filter& operator=(const Filter&);
+ protected:
+ PatternList patterns;
+ };
+}
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+#endif //_LOG4CXX_TESTS_UTIL_FILTER_H
diff --git a/src/test/cpp/util/iso8601filter.cpp b/src/test/cpp/util/iso8601filter.cpp
new file mode 100644
index 0000000..7129d44
--- /dev/null
+++ b/src/test/cpp/util/iso8601filter.cpp
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "iso8601filter.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+ISO8601Filter::ISO8601Filter() : Filter(ISO8601_PAT, "") {}
diff --git a/src/test/cpp/util/iso8601filter.h b/src/test/cpp/util/iso8601filter.h
new file mode 100644
index 0000000..13f65eb
--- /dev/null
+++ b/src/test/cpp/util/iso8601filter.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_ISO_8601_FILTER_H
+#define _LOG4CXX_TESTS_UTIL_ISO_8601_FILTER_H
+
+#include "filter.h"
+
+namespace log4cxx
+{
+ class ISO8601Filter : public Filter
+ {
+ public:
+ ISO8601Filter();
+ };
+}
+
+
+#endif //_LOG4CXX_TESTS_UTIL_ISO_8601_FILTER_H
diff --git a/src/test/cpp/util/linenumberfilter.cpp b/src/test/cpp/util/linenumberfilter.cpp
new file mode 100644
index 0000000..dad37ed
--- /dev/null
+++ b/src/test/cpp/util/linenumberfilter.cpp
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "linenumberfilter.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+LineNumberFilter::LineNumberFilter()
+{
+ patterns.push_back( PatternReplacement(" [^ ]*[\\\\]", " "));
+ patterns.push_back( PatternReplacement("([0-9]*)", "(X)"));
+}
diff --git a/src/test/cpp/util/linenumberfilter.h b/src/test/cpp/util/linenumberfilter.h
new file mode 100644
index 0000000..baa2fde
--- /dev/null
+++ b/src/test/cpp/util/linenumberfilter.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_LINE_NUMBER_FILTER_H
+#define _LOG4CXX_TESTS_UTIL_LINE_NUMBER_FILTER_H
+
+#include "filter.h"
+
+namespace log4cxx
+{
+ class LineNumberFilter : public Filter
+ {
+ public:
+ LineNumberFilter();
+ };
+}
+
+
+#endif //_LOG4CXX_TESTS_UTIL_LINE_NUMBER_FILTER_H
diff --git a/src/test/cpp/util/relativetimefilter.cpp b/src/test/cpp/util/relativetimefilter.cpp
new file mode 100644
index 0000000..0a2c1bc
--- /dev/null
+++ b/src/test/cpp/util/relativetimefilter.cpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "relativetimefilter.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+RelativeTimeFilter::RelativeTimeFilter()
+ : Filter(RELATIVE_TIME_PAT, "") {}
diff --git a/src/test/cpp/util/relativetimefilter.h b/src/test/cpp/util/relativetimefilter.h
new file mode 100644
index 0000000..1d625cb
--- /dev/null
+++ b/src/test/cpp/util/relativetimefilter.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_REL_TIME_FILTER_H
+#define _LOG4CXX_TESTS_UTIL_REL_TIME_FILTER_H
+
+#include "filter.h"
+
+namespace log4cxx
+{
+ class RelativeTimeFilter : public Filter
+ {
+ public:
+ RelativeTimeFilter();
+ };
+}
+
+
+#endif //_LOG4CXX_TESTS_UTIL_REL_TIME_FILTER_H
diff --git a/src/test/cpp/util/serializationtesthelper.cpp b/src/test/cpp/util/serializationtesthelper.cpp
new file mode 100644
index 0000000..fa4b715
--- /dev/null
+++ b/src/test/cpp/util/serializationtesthelper.cpp
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "serializationtesthelper.h"
+#include <log4cxx/helpers/bytearrayoutputstream.h>
+#include <log4cxx/helpers/objectoutputstream.h>
+#include <log4cxx/helpers/fileinputstream.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/file.h>
+#include "apr_pools.h"
+
+using namespace log4cxx;
+using namespace log4cxx::util;
+using namespace log4cxx::helpers;
+using namespace log4cxx::spi;
+
+
+
+bool SerializationTestHelper::compare(
+ const char* witness, const LoggingEventPtr& event, size_t endCompare) {
+ ByteArrayOutputStreamPtr memOut = new ByteArrayOutputStream();
+ Pool p;
+ ObjectOutputStream objOut(memOut, p);
+ event->write(objOut, p);
+ objOut.close(p);
+ return compare(witness, memOut->toByteArray(), endCompare, p);
+ }
+
+ /**
+ * Asserts the serialized form of an object.
+ * @param witness file name of expected serialization.
+ * @param actual byte array of actual serialization.
+ * @param skip positions to skip comparison.
+ * @param endCompare position to stop comparison.
+ * @throws IOException thrown on IO or serialization exception.
+ */
+bool SerializationTestHelper::compare(
+ const char* witness, const std::vector<unsigned char>& actual,
+ size_t endCompare, Pool& p) {
+ File witnessFile(witness);
+
+ char* expected = p.pstralloc(actual.size());
+ FileInputStreamPtr is(new FileInputStream(witnessFile));
+ ByteBuffer readBuffer(expected, actual.size());
+ int bytesRead = is->read(readBuffer);
+ is->close();
+
+ if(bytesRead < endCompare) {
+ puts("Witness file is shorter than expected");
+ return false;
+ }
+
+ int endScan = actual.size();
+
+ if (endScan > endCompare) {
+ endScan = endCompare;
+ }
+
+ for (int i = 0; i < endScan; i++) {
+ if (((unsigned char) expected[i]) != actual[i]) {
+ printf("Difference at offset %d, expected %x, actual %x\n", i, expected[i], actual[i]);
+ return false;
+ }
+ }
+ return true;
+
+}
diff --git a/src/test/cpp/util/serializationtesthelper.h b/src/test/cpp/util/serializationtesthelper.h
new file mode 100644
index 0000000..63b5b74
--- /dev/null
+++ b/src/test/cpp/util/serializationtesthelper.h
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_SERIALIZATIONTESTHELPER_H
+#define _LOG4CXX_TESTS_UTIL_SERIALIZATIONTESTHELPER_H
+
+#include <log4cxx/spi/loggingevent.h>
+
+namespace log4cxx
+{
+ namespace util {
+ class SerializationTestHelper {
+ public:
+ static bool compare(const char* filename,
+ const log4cxx::spi::LoggingEventPtr& event,
+ size_t stopCompare);
+ static bool compare(const char* filename,
+ const std::vector<unsigned char>& array,
+ size_t stopCompare, log4cxx::helpers::Pool& p);
+ private:
+ SerializationTestHelper();
+ SerializationTestHelper(const SerializationTestHelper&);
+ SerializationTestHelper& operator=(SerializationTestHelper&);
+ };
+ }
+}
+
+#endif
diff --git a/src/test/cpp/util/threadfilter.cpp b/src/test/cpp/util/threadfilter.cpp
new file mode 100644
index 0000000..1c58cdd
--- /dev/null
+++ b/src/test/cpp/util/threadfilter.cpp
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "threadfilter.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+ThreadFilter::ThreadFilter() : Filter("\\[[0-9A-Fa-fXx]*]", "\\[main]") {}
diff --git a/src/test/cpp/util/threadfilter.h b/src/test/cpp/util/threadfilter.h
new file mode 100644
index 0000000..0408fcd
--- /dev/null
+++ b/src/test/cpp/util/threadfilter.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_THREAD_FILTER_H
+#define _LOG4CXX_TESTS_UTIL_THREAD_FILTER_H
+
+#include "filter.h"
+
+namespace log4cxx
+{
+ class ThreadFilter : public Filter
+ {
+ public:
+ ThreadFilter();
+ };
+}
+
+
+#endif //_LOG4CXX_TESTS_UTIL_THREAD_FILTER_H
diff --git a/src/test/cpp/util/transformer.cpp b/src/test/cpp/util/transformer.cpp
new file mode 100644
index 0000000..b7c8ad8
--- /dev/null
+++ b/src/test/cpp/util/transformer.cpp
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "transformer.h"
+#include <log4cxx/file.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <apr_thread_proc.h>
+#include <apr_pools.h>
+#include <apr_file_io.h>
+#include <apr_strings.h>
+#include <assert.h>
+#include <iostream>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+#if !defined(APR_FOPEN_READ)
+#define APR_FOPEN_READ APR_READ
+#define APR_FOPEN_CREATE APR_CREATE
+#define APR_FOPEN_WRITE APR_WRITE
+#define APR_FOPEN_TRUNCATE APR_TRUNCATE
+#define APR_FOPEN_APPEND APR_APPEND
+#endif
+
+void Transformer::transform(const File& in, const File& out,
+ const std::vector<Filter *>& filters)
+{
+ log4cxx::Filter::PatternList patterns;
+ for(std::vector<Filter*>::const_iterator iter = filters.begin();
+ iter != filters.end();
+ iter++) {
+
+ const log4cxx::Filter::PatternList& thesePatterns = (*iter)->getPatterns();
+ for (log4cxx::Filter::PatternList::const_iterator pattern = thesePatterns.begin();
+ pattern != thesePatterns.end();
+ pattern++) {
+ patterns.push_back(*pattern);
+ }
+ }
+ transform(in, out, patterns);
+}
+
+void Transformer::transform(const File& in, const File& out,
+ const Filter& filter)
+{
+ transform(in, out, filter.getPatterns());
+}
+
+
+void Transformer::copyFile(const File& in, const File& out) {
+ Pool p;
+ apr_pool_t* pool = p.getAPRPool();
+
+
+ //
+ // fairly naive file copy code
+ //
+ //
+ apr_file_t* child_out;
+ apr_int32_t flags = APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE;
+ apr_status_t stat = out.open(&child_out, flags, APR_OS_DEFAULT, p);
+ assert(stat == APR_SUCCESS);
+
+ apr_file_t* in_file;
+ stat = in.open(&in_file, APR_FOPEN_READ, APR_OS_DEFAULT, p);
+ assert(stat == APR_SUCCESS);
+ apr_size_t bufsize = 32000;
+ void* buf = apr_palloc(pool, bufsize);
+ apr_size_t bytesRead = bufsize;
+
+ while(stat == 0 && bytesRead == bufsize) {
+ stat = apr_file_read(in_file, buf, &bytesRead);
+ if (stat == 0 && bytesRead > 0) {
+ stat = apr_file_write(child_out, buf, &bytesRead);
+ assert(stat == APR_SUCCESS);
+ }
+ }
+ stat = apr_file_close(child_out);
+ assert(stat == APR_SUCCESS);
+}
+
+void Transformer::createSedCommandFile(const std::string& regexName,
+ const log4cxx::Filter::PatternList& patterns,
+ apr_pool_t* pool) {
+ apr_file_t* regexFile;
+ apr_status_t stat = apr_file_open(&regexFile,
+ regexName.c_str(),
+ APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE, APR_OS_DEFAULT,
+ pool);
+ assert(stat == APR_SUCCESS);
+
+ std::string tmp;
+ for (log4cxx::Filter::PatternList::const_iterator iter = patterns.begin();
+ iter != patterns.end();
+ iter++) {
+ tmp = "sQ";
+ tmp.append(iter->first);
+ tmp.append(1, 'Q');
+ tmp.append(iter->second);
+ tmp.append("Qg\n");
+ apr_file_puts(tmp.c_str(), regexFile);
+ }
+ apr_file_close(regexFile);
+}
+
+void Transformer::transform(const File& in, const File& out,
+ const log4cxx::Filter::PatternList& patterns)
+{
+ //
+ // if no patterns just copy the file
+ //
+ if (patterns.size() == 0) {
+ copyFile(in, out);
+ } else {
+ Pool p;
+ apr_pool_t* pool = p.getAPRPool();
+
+ //
+ // write the regex's to a temporary file since they
+ // may get mangled if passed as parameters
+ //
+ std::string regexName;
+ Transcoder::encode(in.getPath(), regexName);
+ regexName.append(".sed");
+ createSedCommandFile(regexName, patterns, pool);
+
+
+ //
+ // prepare to launch sed
+ //
+ //
+ apr_procattr_t* attr = NULL;
+ apr_status_t stat = apr_procattr_create(&attr, pool);
+ assert(stat == APR_SUCCESS);
+
+ stat = apr_procattr_io_set(attr, APR_NO_PIPE, APR_FULL_BLOCK,
+ APR_FULL_BLOCK);
+ assert(stat == APR_SUCCESS);
+
+ //
+ // find the program on the path
+ //
+ stat = apr_procattr_cmdtype_set(attr, APR_PROGRAM_PATH);
+ assert(stat == APR_SUCCESS);
+
+ //
+ // build the argument list
+ // using Q as regex separator on s command
+ //
+ const char** args = (const char**)
+ apr_palloc(pool, 5 * sizeof(*args));
+ int i = 0;
+
+ //
+ // not well documented
+ // but the first arg is a duplicate of the executable name
+ //
+ args[i++] = "sed";
+
+
+ std::string regexArg("-f");
+ regexArg.append(regexName);
+ args[i++] = apr_pstrdup(pool, regexArg.c_str());
+
+ //
+ // specify the input file
+ args[i++] = Transcoder::encode(in.getPath(), p);
+ args[i] = NULL;
+
+
+
+ //
+ // set the output stream to the filtered file
+ //
+ apr_file_t* child_out;
+ apr_int32_t flags = APR_FOPEN_READ | APR_FOPEN_WRITE |
+ APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE;
+ stat = out.open(&child_out, flags, APR_OS_DEFAULT, p);
+ assert(stat == APR_SUCCESS);
+
+ stat = apr_procattr_child_out_set(attr, child_out, NULL);
+ assert(stat == APR_SUCCESS);
+
+ //
+ // redirect the child's error stream to this processes' error stream
+ //
+ apr_file_t* child_err;
+ stat = apr_file_open_stderr(&child_err, pool);
+ assert(stat == 0);
+ stat = apr_procattr_child_err_set(attr, child_err, NULL);
+ assert(stat == APR_SUCCESS);
+
+
+
+ apr_proc_t pid;
+ stat = apr_proc_create(&pid,"sed", args, NULL, attr, pool);
+ if (stat != APR_SUCCESS) {
+ puts("Error invoking sed, sed must be on the path in order to run unit tests");
+ }
+ assert(stat == APR_SUCCESS);
+
+ apr_proc_wait(&pid, NULL, NULL, APR_WAIT);
+ stat = apr_file_close(child_out);
+ assert(stat == APR_SUCCESS);
+ }
+
+
+}
diff --git a/src/test/cpp/util/transformer.h b/src/test/cpp/util/transformer.h
new file mode 100644
index 0000000..cf7becd
--- /dev/null
+++ b/src/test/cpp/util/transformer.h
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_TRANSFORMER_H
+#define _LOG4CXX_TESTS_UTIL_TRANSFORMER_H
+
+#include "filter.h"
+#include <vector>
+
+extern "C" {
+struct apr_pool_t;
+}
+
+namespace log4cxx
+{
+ class File;
+
+ class Transformer
+ {
+ public:
+ static void transform(const File& in,
+ const File& out,
+ const std::vector<Filter *>& filters);
+
+ static void transform(const File& in,
+ const File& out,
+ const Filter& filter);
+
+ static void transform(const File& in,
+ const File& out,
+ const std::vector< log4cxx::Filter::PatternReplacement >& patterns);
+ private:
+ static void copyFile(const File& in,
+ const File& out);
+ static void createSedCommandFile(const std::string& regexName,
+ const log4cxx::Filter::PatternList& patterns,
+ apr_pool_t* pool);
+
+ };
+}
+
+#endif //_LOG4CXX_TESTS_UTIL_TRANSFORMER_H
diff --git a/src/test/cpp/util/utilfilter.cpp b/src/test/cpp/util/utilfilter.cpp
new file mode 100644
index 0000000..6ec35e5
--- /dev/null
+++ b/src/test/cpp/util/utilfilter.cpp
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "filter.h"
+#include <log4cxx/helpers/transcoder.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+Filter::Filter() {}
+
+Filter::Filter(const std::string& match,
+ const std::string& replacement) {
+ patterns.push_back( PatternReplacement(match, replacement));
+}
+
+Filter::~Filter() {}
diff --git a/src/test/cpp/util/xmlfilenamefilter.cpp b/src/test/cpp/util/xmlfilenamefilter.cpp
new file mode 100644
index 0000000..b2fe716
--- /dev/null
+++ b/src/test/cpp/util/xmlfilenamefilter.cpp
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "xmlfilenamefilter.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+XMLFilenameFilter::XMLFilenameFilter(const std::string& /*actual*/, const std::string& expected) {
+ std::string pattern(" file=\\(.\\).*");
+ pattern += expected;
+
+ std::string replacement(" file=\\\\1");
+ replacement += expected;
+// patterns.push_back( PatternReplacement(pattern, replacement) );
+}
diff --git a/src/test/cpp/util/xmlfilenamefilter.h b/src/test/cpp/util/xmlfilenamefilter.h
new file mode 100644
index 0000000..ff56763
--- /dev/null
+++ b/src/test/cpp/util/xmlfilenamefilter.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_XML_FILENAME_FILTER_H
+#define _LOG4CXX_TESTS_UTIL_XML_FILENAME_FILTER_H
+
+#include "filter.h"
+
+namespace log4cxx
+{
+ class XMLFilenameFilter : public Filter
+ {
+ public:
+ XMLFilenameFilter(const std::string& actual, const std::string& expected);
+ };
+}
+
+
+#endif //_LOG4CXX_TESTS_UTIL_XML_FILENAME_FILTER_H
diff --git a/src/test/cpp/util/xmllineattributefilter.cpp b/src/test/cpp/util/xmllineattributefilter.cpp
new file mode 100644
index 0000000..b5b9714
--- /dev/null
+++ b/src/test/cpp/util/xmllineattributefilter.cpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "xmllineattributefilter.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+XMLLineAttributeFilter::XMLLineAttributeFilter() {
+ patterns.push_back( PatternReplacement("line=\\(.+\\)[0-9]+", "line=\\\\1X"));
+}
diff --git a/src/test/cpp/util/xmllineattributefilter.h b/src/test/cpp/util/xmllineattributefilter.h
new file mode 100644
index 0000000..36f216f
--- /dev/null
+++ b/src/test/cpp/util/xmllineattributefilter.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_XML_LINE_ATTRIBUTE_FILTER_H
+#define _LOG4CXX_TESTS_UTIL_XML_LINE_ATTRIBUTE_FILTER_H
+
+#include "filter.h"
+
+namespace log4cxx
+{
+ class XMLLineAttributeFilter : public Filter
+ {
+ public:
+ XMLLineAttributeFilter();
+ };
+}
+
+
+#endif //_LOG4CXX_TESTS_UTIL_XML_LINE_ATTRIBUTE_FILTER_H
diff --git a/src/test/cpp/util/xmlthreadfilter.cpp b/src/test/cpp/util/xmlthreadfilter.cpp
new file mode 100644
index 0000000..302761e
--- /dev/null
+++ b/src/test/cpp/util/xmlthreadfilter.cpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "xmlthreadfilter.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+XMLThreadFilter::XMLThreadFilter()
+ : Filter("thread=\\\"[0-9A-Fa-fXx]*", "thread=\\\"main") {
+}
diff --git a/src/test/cpp/util/xmlthreadfilter.h b/src/test/cpp/util/xmlthreadfilter.h
new file mode 100644
index 0000000..c246fea
--- /dev/null
+++ b/src/test/cpp/util/xmlthreadfilter.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_XML_THREAD_FILTER_H
+#define _LOG4CXX_TESTS_UTIL_XML_THREAD_FILTER_H
+
+#include "filter.h"
+
+namespace log4cxx
+{
+ class XMLThreadFilter : public Filter
+ {
+ public:
+ XMLThreadFilter();
+ };
+}
+
+
+#endif //_LOG4CXX_TESTS_UTIL_XML_THREAD_FILTER_H
diff --git a/src/test/cpp/util/xmltimestampfilter.cpp b/src/test/cpp/util/xmltimestampfilter.cpp
new file mode 100644
index 0000000..5094de3
--- /dev/null
+++ b/src/test/cpp/util/xmltimestampfilter.cpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "xmltimestampfilter.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+XMLTimestampFilter::XMLTimestampFilter()
+ : Filter("[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]*", "XXX") {}
+
+
diff --git a/src/test/cpp/util/xmltimestampfilter.h b/src/test/cpp/util/xmltimestampfilter.h
new file mode 100644
index 0000000..b0ca75b
--- /dev/null
+++ b/src/test/cpp/util/xmltimestampfilter.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 _LOG4CXX_TESTS_UTIL_XML_TIMESTAMP_FILTER_H
+#define _LOG4CXX_TESTS_UTIL_XML_TIMESTAMP_FILTER_H
+
+#include "filter.h"
+
+namespace log4cxx
+{
+ class XMLTimestampFilter : public Filter
+ {
+ public:
+ XMLTimestampFilter();
+ };
+}
+
+
+#endif //_LOG4CXX_TESTS_UTIL_XML_TIMESTAMP_FILTER_H
diff --git a/src/test/cpp/varia/errorhandlertestcase.cpp b/src/test/cpp/varia/errorhandlertestcase.cpp
new file mode 100644
index 0000000..65fb24a
--- /dev/null
+++ b/src/test/cpp/varia/errorhandlertestcase.cpp
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG4CXX_TEST 1
+#include <log4cxx/private/log4cxx_private.h>
+
+#include <log4cxx/logger.h>
+#include <log4cxx/xml/domconfigurator.h>
+#include "../logunit.h"
+#include "../util/transformer.h"
+#include "../util/compare.h"
+#include "../util/controlfilter.h"
+#include "../util/threadfilter.h"
+#include "../util/linenumberfilter.h"
+#include <iostream>
+#include <log4cxx/file.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::xml;
+
+#define TEST1_A_PAT "FALLBACK - test - Message [0-9]"
+#define TEST1_B_PAT "FALLBACK - root - Message [0-9]"
+#define TEST1_2_PAT \
+ "^[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [0-9]\\{2\\}:[0-9]\\{2\\}:[0-9]\\{2\\},[0-9]\\{3\\} " \
+ "\\[main]\\ (DEBUG|INFO|WARN|ERROR|FATAL) .* - Message [0-9]"
+
+LOGUNIT_CLASS(ErrorHandlerTestCase)
+{
+ LOGUNIT_TEST_SUITE(ErrorHandlerTestCase);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST_SUITE_END();
+
+ LoggerPtr root;
+ LoggerPtr logger;
+
+ static const File TEMP;
+ static const File FILTERED;
+
+
+public:
+ void setUp()
+ {
+ root = Logger::getRootLogger();
+ logger = Logger::getLogger("test");
+ }
+
+ void tearDown()
+ {
+ logger->getLoggerRepository()->resetConfiguration();
+ }
+
+ void test1()
+ {
+ DOMConfigurator::configure("input/xml/fallback1.xml");
+ common();
+
+ ControlFilter cf;
+ cf << TEST1_A_PAT << TEST1_B_PAT << TEST1_2_PAT;
+
+ ThreadFilter threadFilter;
+ LineNumberFilter lineNumberFilter;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&cf);
+ filters.push_back(&threadFilter);
+ filters.push_back(&lineNumberFilter);
+
+ common();
+
+ try
+ {
+ Transformer::transform(TEMP, FILTERED, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ const File witness("witness/fallback");
+ LOGUNIT_ASSERT(Compare::compare(FILTERED, witness));
+ }
+
+ void common()
+ {
+ int i = -1;
+
+ std::ostringstream os;
+ os << "Message " << ++ i;
+ LOG4CXX_DEBUG(logger, os.str());
+ LOG4CXX_DEBUG(root, os.str());
+
+ os.str("");
+ os << "Message " << ++i;
+ LOG4CXX_INFO(logger, os.str());
+ LOG4CXX_INFO(root, os.str());
+
+ os.str("");
+ os << "Message " << ++i;
+ LOG4CXX_WARN(logger, os.str());
+ LOG4CXX_WARN(root, os.str());
+
+ os.str("");
+ os << "Message " << ++i;
+ LOG4CXX_ERROR(logger, os.str());
+ LOG4CXX_ERROR(root, os.str());
+
+ os.str("");
+ os << "Message " << ++i;
+ LOG4CXX_FATAL(logger, os.str());
+ LOG4CXX_FATAL(root, os.str());
+ }
+};
+
+//TODO: Not sure this test ever worked. 0.9.7 didn't call common
+// had nothing that attempted to dispatch any log events
+
+//LOGUNIT_TEST_SUITE_REGISTRATION(ErrorHandlerTestCase);
+
+const File ErrorHandlerTestCase::TEMP("output/temp");
+const File ErrorHandlerTestCase::FILTERED("output/filtered");
+
diff --git a/src/test/cpp/varia/levelmatchfiltertestcase.cpp b/src/test/cpp/varia/levelmatchfiltertestcase.cpp
new file mode 100644
index 0000000..4f4d954
--- /dev/null
+++ b/src/test/cpp/varia/levelmatchfiltertestcase.cpp
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "../logunit.h"
+
+#include <log4cxx/logger.h>
+#include <log4cxx/simplelayout.h>
+#include <log4cxx/fileappender.h>
+#include <log4cxx/level.h>
+#include <log4cxx/filter/levelmatchfilter.h>
+#include <log4cxx/filter/denyallfilter.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/spi/loggerrepository.h>
+
+#include "../util/compare.h"
+#include "../testchar.h"
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::filter;
+
+LOGUNIT_CLASS(LevelMatchFilterTestCase)
+{
+ LOGUNIT_TEST_SUITE(LevelMatchFilterTestCase);
+ LOGUNIT_TEST(accept);
+ LOGUNIT_TEST(deny);
+ LOGUNIT_TEST_SUITE_END();
+
+ LoggerPtr root;
+ LoggerPtr logger;
+
+public:
+ void setUp()
+ {
+ root = Logger::getRootLogger();
+ root->removeAllAppenders();
+ logger = Logger::getLogger(LOG4CXX_TEST_STR("test"));
+ }
+
+ void tearDown()
+ {
+ root->getLoggerRepository()->resetConfiguration();
+ }
+
+ void accept()
+ {
+ // set up appender
+ LayoutPtr layout = new SimpleLayout();
+ AppenderPtr appender = new FileAppender(layout, ACCEPT_FILE, false);
+
+ // create LevelMatchFilter
+ LevelMatchFilterPtr matchFilter = new LevelMatchFilter();
+
+ // attach match filter to appender
+ appender->addFilter(matchFilter);
+
+ // attach DenyAllFilter to end of filter chain to deny neutral
+ // (non matching) messages
+ spi::FilterPtr filter(new DenyAllFilter());
+ appender->addFilter(filter);
+
+ // set appender on root and set level to debug
+ root->addAppender(appender);
+ root->setLevel(Level::getDebug());
+
+ LevelPtr levelArray[] =
+ { Level::getDebug(), Level::getInfo(), Level::getWarn(), Level::getError(), Level::getFatal() };
+
+ int length = sizeof(levelArray)/sizeof(levelArray[0]);
+
+ Pool pool;
+ for (int x = 0; x < length; x++)
+ {
+ // set the level to match
+ matchFilter->setLevelToMatch(levelArray[x]->toString());
+ LogString sbuf(LOG4CXX_STR("pass "));
+ StringHelper::toString(x, pool, sbuf);
+ sbuf.append(LOG4CXX_STR("; filter set to accept only "));
+ sbuf.append(levelArray[x]->toString());
+ sbuf.append(LOG4CXX_STR(" msgs"));
+ common(sbuf);
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(ACCEPT_FILE, ACCEPT_WITNESS));
+ }
+
+ void deny()
+ {
+ // set up appender
+ LayoutPtr layout = new SimpleLayout();
+ AppenderPtr appender = new FileAppender(layout, DENY_FILE, false);
+
+ // create LevelMatchFilter, set to deny matches
+ LevelMatchFilterPtr matchFilter = new LevelMatchFilter();
+ matchFilter->setAcceptOnMatch(false);
+
+ // attach match filter to appender
+ appender->addFilter(matchFilter);
+
+ // set appender on root and set level to debug
+ root->addAppender(appender);
+ root->setLevel(Level::getDebug());
+
+ LevelPtr levelArray[] =
+ { Level::getDebug(), Level::getInfo(), Level::getWarn(), Level::getError(), Level::getFatal() };
+
+ int length = sizeof(levelArray)/sizeof(levelArray[0]);
+
+ Pool pool;
+
+ for (int x = 0; x < length; x++)
+ {
+ // set the level to match
+ matchFilter->setLevelToMatch(levelArray[x]->toString());
+ LogString sbuf(LOG4CXX_STR("pass "));
+
+ StringHelper::toString(x, pool, sbuf);
+ sbuf.append(LOG4CXX_STR("; filter set to deny only "));
+ sbuf.append(levelArray[x]->toString());
+ sbuf.append(LOG4CXX_STR(" msgs"));
+ common(sbuf);
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(DENY_FILE, DENY_WITNESS));
+ }
+
+ void common(const LogString& msg)
+ {
+ logger->debug(msg);
+ logger->info(msg);
+ logger->warn(msg);
+ logger->error(msg);
+ logger->fatal(msg);
+ }
+
+private:
+ static const LogString ACCEPT_FILE;
+ static const LogString ACCEPT_WITNESS;
+ static const LogString DENY_FILE;
+ static const LogString DENY_WITNESS;
+
+
+};
+
+const LogString LevelMatchFilterTestCase::ACCEPT_FILE(LOG4CXX_STR("output/LevelMatchFilter_accept"));
+const LogString LevelMatchFilterTestCase::ACCEPT_WITNESS(LOG4CXX_STR("witness/LevelMatchFilter_accept"));
+const LogString LevelMatchFilterTestCase::DENY_FILE(LOG4CXX_STR("output/LevelMatchFilter_deny"));
+const LogString LevelMatchFilterTestCase::DENY_WITNESS(LOG4CXX_STR("witness/LevelMatchFilter_deny"));
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(LevelMatchFilterTestCase);
diff --git a/src/test/cpp/varia/levelrangefiltertestcase.cpp b/src/test/cpp/varia/levelrangefiltertestcase.cpp
new file mode 100644
index 0000000..f77447a
--- /dev/null
+++ b/src/test/cpp/varia/levelrangefiltertestcase.cpp
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logger.h>
+#include <log4cxx/simplelayout.h>
+#include <log4cxx/fileappender.h>
+#include <log4cxx/level.h>
+#include <log4cxx/filter/levelrangefilter.h>
+
+#include "../util/compare.h"
+
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/transcoder.h>
+#include "../testchar.h"
+#include "../logunit.h"
+#include <log4cxx/spi/loggerrepository.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::filter;
+
+
+
+LOGUNIT_CLASS(LevelRangeFilterTestCase)
+{
+ LOGUNIT_TEST_SUITE(LevelRangeFilterTestCase);
+ LOGUNIT_TEST(accept);
+ LOGUNIT_TEST(neutral);
+ LOGUNIT_TEST_SUITE_END();
+
+ LoggerPtr root;
+ LoggerPtr logger;
+
+public:
+ void setUp()
+ {
+ root = Logger::getRootLogger();
+ root->removeAllAppenders();
+ logger = Logger::getLogger(LOG4CXX_TEST_STR("test"));
+ }
+
+ void tearDown()
+ {
+ root->getLoggerRepository()->resetConfiguration();
+ }
+
+ void accept()
+ {
+ // set up appender
+ LayoutPtr layout = new SimpleLayout();
+ AppenderPtr appender = new FileAppender(layout, ACCEPT_FILE, false);
+
+ // create LevelMatchFilter
+ LevelRangeFilterPtr rangeFilter = new LevelRangeFilter();
+
+ // set it to accept on a match
+ rangeFilter->setAcceptOnMatch(true);
+
+ // attach match filter to appender
+ appender->addFilter(rangeFilter);
+
+ // set appender on root and set level to debug
+ root->addAppender(appender);
+ root->setLevel(Level::getDebug());
+
+ int passCount = 0;
+ LogString sbuf(LOG4CXX_STR("pass "));
+
+ Pool pool;
+ StringHelper::toString(passCount, pool, sbuf);
+
+ sbuf.append(LOG4CXX_STR("; no min or max set"));
+ common(sbuf);
+ passCount++;
+
+ // test with a min set
+ rangeFilter->setLevelMin(Level::getWarn());
+ sbuf.assign(LOG4CXX_STR("pass "));
+ StringHelper::toString(passCount, pool, sbuf);
+ sbuf.append(LOG4CXX_STR("; min set to WARN, max not set"));
+ common(sbuf);
+ passCount++;
+
+ // create a clean filter
+ appender->clearFilters();
+ rangeFilter = new LevelRangeFilter();
+ appender->addFilter(rangeFilter);
+
+ //test with max set
+ rangeFilter->setLevelMax(Level::getWarn());
+ sbuf.assign(LOG4CXX_STR("pass "));
+ StringHelper::toString(passCount, pool, sbuf);
+ sbuf.append(LOG4CXX_STR("; min not set, max set to WARN"));
+ common(sbuf);
+ passCount++;
+
+
+ LevelPtr levelArray[] =
+ { Level::getDebug(), Level::getInfo(), Level::getWarn(),
+ Level::getError(), Level::getFatal() };
+
+ int length = sizeof(levelArray)/sizeof(levelArray[0]);
+
+ for (int x = 0; x < length; x++)
+ {
+ // set the min level to match
+ rangeFilter->setLevelMin(levelArray[x]);
+
+ for (int y = length - 1; y >= 0; y--)
+ {
+ // set max level to match
+ rangeFilter->setLevelMax(levelArray[y]);
+
+ sbuf.assign(LOG4CXX_STR("pass "));
+ StringHelper::toString(passCount, pool, sbuf);
+ sbuf.append(LOG4CXX_STR("; filter set to accept between "));
+ sbuf.append(levelArray[x]->toString());
+ sbuf.append(LOG4CXX_STR(" and "));
+ sbuf.append(levelArray[y]->toString());
+ sbuf.append(LOG4CXX_STR(" msgs"));
+ common(sbuf);
+
+ // increment passCount
+ passCount++;
+ }
+ }
+
+
+ LOGUNIT_ASSERT(Compare::compare(ACCEPT_FILE, ACCEPT_WITNESS));
+ }
+
+ void neutral()
+ {
+ // set up appender
+ LayoutPtr layout = new SimpleLayout();
+ AppenderPtr appender = new FileAppender(layout, NEUTRAL_FILE, false);
+
+ // create LevelMatchFilter
+ LevelRangeFilterPtr rangeFilter = new LevelRangeFilter();
+
+ // set it to accept on a match
+ rangeFilter->setAcceptOnMatch(true);
+
+ // attach match filter to appender
+ appender->addFilter(rangeFilter);
+
+ // set appender on root and set level to debug
+ root->addAppender(appender);
+ root->setLevel(Level::getDebug());
+
+ int passCount = 0;
+ LogString sbuf(LOG4CXX_STR("pass "));
+
+ Pool pool;
+ StringHelper::toString(passCount, pool, sbuf);
+
+ // test with no min or max set
+ sbuf.append(LOG4CXX_STR("; no min or max set"));
+ common(sbuf);
+ passCount++;
+
+ // test with a min set
+ rangeFilter->setLevelMin(Level::getWarn());
+ sbuf.assign(LOG4CXX_STR("pass "));
+
+ StringHelper::toString(passCount, pool, sbuf);
+ sbuf.append(LOG4CXX_STR("; min set to WARN, max not set"));
+ common(sbuf);
+ passCount++;
+
+ // create a clean filter
+ appender->clearFilters();
+ rangeFilter = new LevelRangeFilter();
+ appender->addFilter(rangeFilter);
+
+ //test with max set
+ rangeFilter->setLevelMax(Level::getWarn());
+ sbuf.assign(LOG4CXX_STR("pass "));
+
+ StringHelper::toString(passCount, pool, sbuf);
+
+ sbuf.append(LOG4CXX_STR("; min not set, max set to WARN"));
+ common(sbuf);
+ passCount++;
+
+ LevelPtr levelArray[] =
+ { Level::getDebug(), Level::getInfo(), Level::getWarn(),
+ Level::getError(), Level::getFatal() };
+
+ int length = sizeof(levelArray)/sizeof(levelArray[0]);
+
+ for (int x = 0; x < length; x++)
+ {
+ // set the min level to match
+ rangeFilter->setLevelMin(levelArray[x]);
+
+ for (int y = length - 1; y >= 0; y--)
+ {
+ // set max level to match
+ rangeFilter->setLevelMax(levelArray[y]);
+
+ sbuf.assign(LOG4CXX_STR("pass "));
+ StringHelper::toString(passCount, pool, sbuf);
+ sbuf.append(LOG4CXX_STR("; filter set to accept between "));
+ sbuf.append(levelArray[x]->toString());
+ sbuf.append(LOG4CXX_STR(" and "));
+ sbuf.append(levelArray[y]->toString());
+ sbuf.append(LOG4CXX_STR(" msgs"));
+ common(sbuf);
+
+ // increment passCount
+ passCount++;
+ }
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(NEUTRAL_FILE, NEUTRAL_WITNESS));
+ }
+
+ void common(const LogString& msg)
+ {
+ logger->debug(msg);
+ logger->info(msg);
+ logger->warn(msg);
+ logger->error(msg);
+ logger->fatal(msg);
+ }
+
+ private:
+ static const LogString ACCEPT_FILE;
+ static const LogString ACCEPT_WITNESS;
+ static const LogString NEUTRAL_FILE;
+ static const LogString NEUTRAL_WITNESS;
+
+};
+
+
+const LogString LevelRangeFilterTestCase::ACCEPT_FILE(LOG4CXX_STR("output/LevelRangeFilter_accept"));
+const LogString LevelRangeFilterTestCase::ACCEPT_WITNESS(LOG4CXX_STR("witness/LevelRangeFilter_accept"));
+const LogString LevelRangeFilterTestCase::NEUTRAL_FILE(LOG4CXX_STR("output/LevelRangeFilter_neutral"));
+const LogString LevelRangeFilterTestCase::NEUTRAL_WITNESS(LOG4CXX_STR("witness/LevelRangeFilter_neutral"));
+
+LOGUNIT_TEST_SUITE_REGISTRATION(LevelRangeFilterTestCase);
diff --git a/src/test/cpp/vectorappender.cpp b/src/test/cpp/vectorappender.cpp
new file mode 100644
index 0000000..e91824a
--- /dev/null
+++ b/src/test/cpp/vectorappender.cpp
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "vectorappender.h"
+#include <log4cxx/helpers/thread.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT(VectorAppender)
+
+void VectorAppender::append(const spi::LoggingEventPtr& event, Pool& /*p*/)
+{
+ try
+ {
+ Thread::sleep(100);
+ }
+ catch (Exception&)
+ {
+ }
+
+ vector.push_back(event);
+}
+
+void VectorAppender::close()
+{
+ if (this->closed)
+ {
+ return;
+ }
+
+ this->closed = true;
+}
diff --git a/src/test/cpp/vectorappender.h b/src/test/cpp/vectorappender.h
new file mode 100644
index 0000000..24b3aad
--- /dev/null
+++ b/src/test/cpp/vectorappender.h
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/appenderskeleton.h>
+#include <vector>
+#include <log4cxx/spi/loggingevent.h>
+
+namespace log4cxx
+{
+
+
+ /**
+ An appender that appends logging events to a vector.
+ */
+ class VectorAppender : public AppenderSkeleton
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(VectorAppender)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(VectorAppender)
+ LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+ END_LOG4CXX_CAST_MAP()
+
+ std::vector<spi::LoggingEventPtr> vector;
+
+
+ /**
+ This method is called by the AppenderSkeleton#doAppend
+ method.
+ */
+ void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);
+
+ const std::vector<spi::LoggingEventPtr>& getVector() const
+ { return vector; }
+
+ void close();
+
+ bool isClosed() const
+ { return closed; }
+
+ bool requiresLayout() const
+ { return false; }
+ };
+ typedef helpers::ObjectPtrT<VectorAppender> VectorAppenderPtr;
+}
diff --git a/src/test/cpp/writerappendertestcase.cpp b/src/test/cpp/writerappendertestcase.cpp
new file mode 100644
index 0000000..26921d2
--- /dev/null
+++ b/src/test/cpp/writerappendertestcase.cpp
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "writerappendertestcase.h"
+#include <log4cxx/helpers/objectptr.h>
+#include <log4cxx/writerappender.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+AppenderSkeleton* WriterAppenderTestCase::createAppenderSkeleton() const {
+ return createWriterAppender();
+}
diff --git a/src/test/cpp/writerappendertestcase.h b/src/test/cpp/writerappendertestcase.h
new file mode 100644
index 0000000..dbc3229
--- /dev/null
+++ b/src/test/cpp/writerappendertestcase.h
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/writerappender.h>
+#include "appenderskeletontestcase.h"
+
+
+/**
+ An abstract set of tests for inclusion in concrete
+ appender test case
+ */
+class WriterAppenderTestCase : public AppenderSkeletonTestCase
+{
+
+public:
+ log4cxx::AppenderSkeleton* createAppenderSkeleton() const;
+
+ virtual log4cxx::WriterAppender* createWriterAppender() const = 0;
+
+};
diff --git a/src/test/cpp/xml/customleveltestcase.cpp b/src/test/cpp/xml/customleveltestcase.cpp
new file mode 100644
index 0000000..40b7e4a
--- /dev/null
+++ b/src/test/cpp/xml/customleveltestcase.cpp
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG4CXX_TEST 1
+#include <log4cxx/private/log4cxx_private.h>
+
+
+
+#include "../logunit.h"
+
+#include <log4cxx/logger.h>
+#include <log4cxx/xml/domconfigurator.h>
+#include <log4cxx/consoleappender.h>
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/file.h>
+
+#include "../util/compare.h"
+#include "xlevel.h"
+#include "../testchar.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::xml;
+
+
+LOGUNIT_CLASS(CustomLevelTestCase)
+{
+ LOGUNIT_TEST_SUITE(CustomLevelTestCase);
+ LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
+ LOGUNIT_TEST(test3);
+ LOGUNIT_TEST(test4);
+ LOGUNIT_TEST_SUITE_END();
+
+ LoggerPtr root;
+ LoggerPtr logger;
+ static const File TEMP;
+
+public:
+ void setUp()
+ {
+ root = Logger::getRootLogger();
+ logger = Logger::getLogger(LOG4CXX_TEST_STR("xml.CustomLevelTestCase"));
+ }
+
+ void tearDown()
+ {
+ root->getLoggerRepository()->resetConfiguration();
+
+ LoggerPtr logger1 = Logger::getLogger(LOG4CXX_TEST_STR("LOG4J"));
+ logger1->setAdditivity(false);
+ logger1->addAppender(
+ new ConsoleAppender(new PatternLayout(LOG4CXX_STR("log4j: %-22c{2} - %m%n"))));
+ }
+
+ void test1()
+ {
+ DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/customLevel1.xml"));
+ common();
+ const File witness("witness/customLevel.1");
+ LOGUNIT_ASSERT(Compare::compare(TEMP, witness));
+ }
+
+ void test2()
+ {
+ DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/customLevel2.xml"));
+ common();
+ const File witness("witness/customLevel.2");
+ LOGUNIT_ASSERT(Compare::compare(TEMP, witness));
+ }
+
+ void test3()
+ {
+ DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/customLevel3.xml"));
+ common();
+ const File witness("witness/customLevel.3");
+ LOGUNIT_ASSERT(Compare::compare(TEMP, witness));
+ }
+
+ void test4()
+ {
+ DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/customLevel4.xml"));
+ common();
+ const File witness("witness/customLevel.4");
+ LOGUNIT_ASSERT(Compare::compare(TEMP, witness));
+ }
+
+ void common()
+ {
+ int i = 0;
+ std::ostringstream os;
+ os << "Message " << ++i;
+ LOG4CXX_DEBUG(logger, os.str());
+ os.str("");
+ os << "Message " << ++i;
+ LOG4CXX_INFO(logger, os.str());
+ os.str("");
+ os << "Message " << ++i;
+ LOG4CXX_WARN(logger, os.str());
+ os.str("");
+ os << "Message " << ++i;
+ LOG4CXX_ERROR(logger, os.str());
+ os.str("");
+ os << "Message " << ++i;
+ LOG4CXX_LOG(logger, XLevel::getTrace(), os.str());
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(CustomLevelTestCase);
+
+const File CustomLevelTestCase::TEMP("output/temp");
+
diff --git a/src/test/cpp/xml/domtestcase.cpp b/src/test/cpp/xml/domtestcase.cpp
new file mode 100644
index 0000000..a500628
--- /dev/null
+++ b/src/test/cpp/xml/domtestcase.cpp
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/logger.h>
+#include <log4cxx/xml/domconfigurator.h>
+#include "../logunit.h"
+#include "../util/compare.h"
+#include "xlevel.h"
+#include "../util/controlfilter.h"
+#include "../util/iso8601filter.h"
+#include "../util/threadfilter.h"
+#include "../util/transformer.h"
+#include <iostream>
+#include <log4cxx/file.h>
+#include <log4cxx/fileappender.h>
+#include <apr_pools.h>
+#include <apr_file_io.h>
+#include "../testchar.h"
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::xml;
+
+
+#define TEST1_1A_PAT \
+ "(DEBUG|INFO |WARN |ERROR|FATAL) \\w*\\.\\w* - Message [0-9]"
+
+#define TEST1_1B_PAT "(DEBUG|INFO |WARN |ERROR|FATAL) root - Message [0-9]"
+
+#define TEST1_2_PAT "^[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [0-9]\\{2\\}:[0-9]\\{2\\}:[0-9]\\{2\\},[0-9]\\{3\\} " \
+ "\\[0x[0-9A-F]*]\\ (DEBUG|INFO|WARN|ERROR|FATAL) .* - Message [0-9]"
+
+LOGUNIT_CLASS(DOMTestCase)
+{
+ LOGUNIT_TEST_SUITE(DOMTestCase);
+ LOGUNIT_TEST(test1);
+#if defined(_WIN32)
+ LOGUNIT_TEST(test2);
+#endif
+ LOGUNIT_TEST(test3);
+ LOGUNIT_TEST(test4);
+ LOGUNIT_TEST_SUITE_END();
+
+ LoggerPtr root;
+ LoggerPtr logger;
+
+ static const File TEMP_A1;
+ static const File TEMP_A2;
+ static const File FILTERED_A1;
+ static const File FILTERED_A2;
+ static const File TEMP_A1_2;
+ static const File TEMP_A2_2;
+ static const File FILTERED_A1_2;
+ static const File FILTERED_A2_2;
+
+public:
+ void setUp()
+ {
+ root = Logger::getRootLogger();
+ logger = Logger::getLogger(LOG4CXX_TEST_STR("org.apache.log4j.xml.DOMTestCase"));
+ }
+
+ void tearDown()
+ {
+ root->getLoggerRepository()->resetConfiguration();
+ }
+
+
+ void test1() {
+ DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMTestCase1.xml"));
+ common();
+
+ ControlFilter cf1;
+ cf1 << TEST1_1A_PAT << TEST1_1B_PAT;
+
+ ControlFilter cf2;
+ cf2 << TEST1_2_PAT;
+
+ ThreadFilter threadFilter;
+ ISO8601Filter iso8601Filter;
+
+ std::vector<Filter *> filters1;
+ filters1.push_back(&cf1);
+
+ std::vector<Filter *> filters2;
+ filters2.push_back(&cf2);
+ filters2.push_back(&threadFilter);
+ filters2.push_back(&iso8601Filter);
+
+ try
+ {
+ Transformer::transform(TEMP_A1, FILTERED_A1, filters1);
+ Transformer::transform(TEMP_A2, FILTERED_A2, filters2);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ const File witness1(LOG4CXX_TEST_STR("witness/dom.A1.1"));
+ const File witness2(LOG4CXX_TEST_STR("witness/dom.A2.1"));
+ // TODO: A1 doesn't contain duplicate entries
+ //
+ // LOGUNIT_ASSERT(Compare::compare(FILTERED_A1, witness1));
+ LOGUNIT_ASSERT(Compare::compare(FILTERED_A2, witness2));
+ }
+
+ //
+ // Same test but backslashes instead of forward
+ //
+ void test2() {
+ DOMConfigurator::configure(LOG4CXX_TEST_STR("input\\xml\\DOMTestCase2.xml"));
+ common();
+
+ ThreadFilter threadFilter;
+ ISO8601Filter iso8601Filter;
+
+ std::vector<Filter *> filters1;
+
+ std::vector<Filter *> filters2;
+ filters2.push_back(&threadFilter);
+ filters2.push_back(&iso8601Filter);
+
+ try
+ {
+ Transformer::transform(TEMP_A1_2, FILTERED_A1_2, filters1);
+ Transformer::transform(TEMP_A2_2, FILTERED_A2_2, filters2);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ const File witness1(LOG4CXX_TEST_STR("witness/dom.A1.2"));
+ const File witness2(LOG4CXX_TEST_STR("witness/dom.A2.2"));
+ // TODO: A1 doesn't contain duplicate entries
+ //
+ // LOGUNIT_ASSERT(Compare::compare(FILTERED_A1, witness1));
+ LOGUNIT_ASSERT(Compare::compare(FILTERED_A2, witness2));
+ }
+
+
+ void common()
+ {
+ int i = 0;
+
+ LOG4CXX_DEBUG(logger, "Message " << i);
+ LOG4CXX_DEBUG(root, "Message " << i);
+
+ i++;
+ LOG4CXX_INFO(logger, "Message " << i);
+ LOG4CXX_INFO(root, "Message " << i);
+
+ i++;
+ LOG4CXX_WARN(logger, "Message " << i);
+ LOG4CXX_WARN(root, "Message " << i);
+
+ i++;
+ LOG4CXX_ERROR(logger, "Message " << i);
+ LOG4CXX_ERROR(root, "Message " << i);
+
+ i++;
+ LOG4CXX_FATAL(logger, "Message " << i);
+ LOG4CXX_FATAL(root, "Message " << i);
+
+ }
+
+ /**
+ * Creates a output file that ends with a superscript 3.
+ * Output file is checked by build.xml after completion.
+ */
+ void test3() {
+ DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMTestCase3.xml"));
+ LOG4CXX_INFO(logger, "File name is expected to end with a superscript 3");
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, 0xC2, 0xB3, 0 };
+#else
+ const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, 0xB3, 0 };
+#endif
+ File file;
+ file.setPath(fname);
+ Pool p;
+ bool exists = file.exists(p);
+ LOGUNIT_ASSERT(exists);
+ }
+
+ /**
+ * Creates a output file that ends with a ideographic 4.
+ * Output file is checked by build.xml after completion.
+ */
+ void test4() {
+ DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMTestCase4.xml"));
+ LOG4CXX_INFO(logger, "File name is expected to end with an ideographic 4");
+#if LOG4CXX_LOGCHAR_IS_UTF8
+ const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, 0xE3, 0x86, 0x95, 0 };
+#else
+ const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, 0x3195, 0 };
+#endif
+ File file;
+ file.setPath(fname);
+ Pool p;
+ bool exists = file.exists(p);
+ LOGUNIT_ASSERT(exists);
+ }
+
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(DOMTestCase);
+
+const File DOMTestCase::TEMP_A1(LOG4CXX_TEST_STR("output/temp.A1"));
+const File DOMTestCase::TEMP_A2(LOG4CXX_TEST_STR("output/temp.A2"));
+const File DOMTestCase::FILTERED_A1(LOG4CXX_TEST_STR("output/filtered.A1"));
+const File DOMTestCase::FILTERED_A2(LOG4CXX_TEST_STR("output/filtered.A2"));
+
+const File DOMTestCase::TEMP_A1_2(LOG4CXX_TEST_STR("output/temp.A1.2"));
+const File DOMTestCase::TEMP_A2_2(LOG4CXX_TEST_STR("output/temp.A2.2"));
+const File DOMTestCase::FILTERED_A1_2(LOG4CXX_TEST_STR("output/filtered.A1.2"));
+const File DOMTestCase::FILTERED_A2_2(LOG4CXX_TEST_STR("output/filtered.A2.2"));
+
diff --git a/src/test/cpp/xml/xlevel.cpp b/src/test/cpp/xml/xlevel.cpp
new file mode 100644
index 0000000..9888e53
--- /dev/null
+++ b/src/test/cpp/xml/xlevel.cpp
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "xlevel.h"
+#include <log4cxx/helpers/stringhelper.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_LEVEL(XLevel)
+
+
+XLevel::XLevel(int level1, const LogString& name1, int syslogEquivalent1)
+: Level(level1, name1, syslogEquivalent1)
+{
+}
+
+LevelPtr XLevel::getTrace() {
+ static const LevelPtr trace(new XLevel(XLevel::TRACE_INT, LOG4CXX_STR("TRACE"), 7));
+ return trace;
+}
+
+LevelPtr XLevel::getLethal() {
+ static const LevelPtr lethal(new XLevel(XLevel::LETHAL_INT, LOG4CXX_STR("LETHAL"), 0));
+ return lethal;
+}
+
+LevelPtr XLevel::toLevelLS(const LogString& sArg)
+{
+ return toLevelLS(sArg, getTrace());
+}
+
+
+LevelPtr XLevel::toLevel(int val)
+{
+ return toLevel(val, getTrace());
+}
+
+LevelPtr XLevel::toLevel(int val, const LevelPtr& defaultLevel)
+{
+ switch(val)
+ {
+ case TRACE_INT: return getTrace();
+ case LETHAL_INT: return getLethal();
+ default: return defaultLevel;
+ }
+}
+
+LevelPtr XLevel::toLevelLS(const LogString& sArg, const LevelPtr& defaultLevel)
+{
+ if (sArg.empty())
+ {
+ return defaultLevel;
+ }
+
+ if (StringHelper::equalsIgnoreCase(sArg,
+ LOG4CXX_STR("TRACE"), LOG4CXX_STR("trace"))) {
+ return getTrace();
+ }
+
+ if (StringHelper::equalsIgnoreCase(sArg,
+ LOG4CXX_STR("LETHAL"), LOG4CXX_STR("lethal"))) {
+ return getLethal();
+ }
+
+ return Level::toLevel(sArg, defaultLevel);
+}
+
diff --git a/src/test/cpp/xml/xlevel.h b/src/test/cpp/xml/xlevel.h
new file mode 100644
index 0000000..eed62fa
--- /dev/null
+++ b/src/test/cpp/xml/xlevel.h
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <log4cxx/level.h>
+
+namespace log4cxx
+{
+ class XLevel : public Level
+ {
+ DECLARE_LOG4CXX_LEVEL(XLevel)
+
+ public:
+ enum
+ {
+ TRACE_INT = Level::DEBUG_INT - 1,
+ LETHAL_INT = Level::FATAL_INT + 1
+ };
+
+ static LevelPtr getTrace();
+ static LevelPtr getLethal();
+
+
+ XLevel(int level, const LogString& name, int syslogEquivalent);
+ /**
+ Convert the string passed as argument to a level. If the
+ conversion fails, then this method returns #DEBUG.
+ */
+ static LevelPtr toLevelLS(const LogString& sArg);
+
+ /**
+ Convert an integer passed as argument to a level. If the
+ conversion fails, then this method returns #DEBUG.
+
+ */
+ static LevelPtr toLevel(int val);
+
+ /**
+ Convert an integer passed as argument to a level. If the
+ conversion fails, then this method returns the specified default.
+ */
+ static LevelPtr toLevel(int val, const LevelPtr& defaultLevel);
+
+
+ /**
+ Convert the string passed as argument to a level. If the
+ conversion fails, then this method returns the value of
+ <code>defaultLevel</code>.
+ */
+ static LevelPtr toLevelLS(const LogString& sArg,
+ const LevelPtr& defaultLevel);
+ };
+}
diff --git a/src/test/cpp/xml/xmllayouttest.cpp b/src/test/cpp/xml/xmllayouttest.cpp
new file mode 100644
index 0000000..e1cf8a7
--- /dev/null
+++ b/src/test/cpp/xml/xmllayouttest.cpp
@@ -0,0 +1,417 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "../logunit.h"
+#include <log4cxx/logger.h>
+#include <log4cxx/xml/xmllayout.h>
+#include <log4cxx/fileappender.h>
+#include <log4cxx/mdc.h>
+
+#include "../util/transformer.h"
+#include "../util/compare.h"
+#include "../util/xmltimestampfilter.h"
+#include "../util/xmllineattributefilter.h"
+#include "../util/xmlthreadfilter.h"
+#include "../util/filenamefilter.h"
+#include <iostream>
+#include <log4cxx/helpers/stringhelper.h>
+#include "../testchar.h"
+#include <log4cxx/spi/loggerrepository.h>
+#include <apr_xml.h>
+#include <log4cxx/ndc.h>
+#include <log4cxx/mdc.h>
+#include "../xml/xlevel.h"
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/transcoder.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::xml;
+using namespace log4cxx::spi;
+
+#if defined(__LOG4CXX_FUNC__)
+#undef __LOG4CXX_FUNC__
+#define __LOG4CXX_FUNC__ "X::X()"
+#else
+#error __LOG4CXX_FUNC__ expected to be defined
+#endif
+/**
+ * Test for XMLLayout.
+ *
+ */
+LOGUNIT_CLASS(XMLLayoutTest) {
+ LOGUNIT_TEST_SUITE(XMLLayoutTest);
+ LOGUNIT_TEST(testGetContentType);
+ LOGUNIT_TEST(testIgnoresThrowable);
+ LOGUNIT_TEST(testGetHeader);
+ LOGUNIT_TEST(testGetFooter);
+ LOGUNIT_TEST(testFormat);
+ LOGUNIT_TEST(testFormatWithNDC);
+ LOGUNIT_TEST(testGetSetLocationInfo);
+ LOGUNIT_TEST(testActivateOptions);
+ LOGUNIT_TEST(testProblemCharacters);
+ LOGUNIT_TEST(testNDCWithCDATA);
+ LOGUNIT_TEST_SUITE_END();
+
+
+public:
+ /**
+ * Clear MDC and NDC before test.
+ */
+ void setUp() {
+ NDC::clear();
+ MDC::clear();
+ }
+
+ /**
+ * Clear MDC and NDC after test.
+ */
+ void tearDown() {
+ setUp();
+ }
+
+
+public:
+ /**
+ * Tests getContentType.
+ */
+ void testGetContentType() {
+ LogString expected(LOG4CXX_STR("text/plain"));
+ LogString actual(XMLLayout().getContentType());
+ LOGUNIT_ASSERT(expected == actual);
+ }
+
+ /**
+ * Tests ignoresThrowable.
+ */
+ void testIgnoresThrowable() {
+ LOGUNIT_ASSERT_EQUAL(false, XMLLayout().ignoresThrowable());
+ }
+
+ /**
+ * Tests getHeader.
+ */
+ void testGetHeader() {
+ Pool p;
+ LogString header;
+ XMLLayout().appendHeader(header, p);
+ LOGUNIT_ASSERT_EQUAL((size_t) 0, header.size());
+ }
+
+ /**
+ * Tests getFooter.
+ */
+ void testGetFooter() {
+ Pool p;
+ LogString footer;
+ XMLLayout().appendFooter(footer, p);
+ LOGUNIT_ASSERT_EQUAL((size_t) 0, footer.size());
+ }
+
+private:
+ /**
+ * Parses the string as the body of an XML document and returns the document element.
+ * @param source source string.
+ * @return document element.
+ * @throws Exception if parser can not be constructed or source is not a valid XML document.
+ */
+ static apr_xml_elem* parse(const LogString& source, Pool& p) {
+ char backing[3000];
+ ByteBuffer buf(backing, sizeof(backing));
+ CharsetEncoderPtr encoder(CharsetEncoder::getUTF8Encoder());
+ LogString header(LOG4CXX_STR("<log4j:eventSet xmlns:log4j='http://jakarta.apache.org/log4j/'>"));
+ LogString::const_iterator iter(header.begin());
+ encoder->encode(header, iter, buf);
+ LOGUNIT_ASSERT(iter == header.end());
+ iter = source.begin();
+ encoder->encode(source, iter, buf);
+ LOGUNIT_ASSERT(iter == source.end());
+ LogString footer(LOG4CXX_STR("</log4j:eventSet>"));
+ iter = footer.begin();
+ encoder->encode(footer, iter, buf);
+ buf.flip();
+ apr_pool_t* apr_pool = p.getAPRPool();
+ apr_xml_parser* parser = apr_xml_parser_create(apr_pool);
+ LOGUNIT_ASSERT(parser != 0);
+ apr_status_t stat = apr_xml_parser_feed(parser, buf.data(), buf.remaining());
+ LOGUNIT_ASSERT(stat == APR_SUCCESS);
+ apr_xml_doc* doc = 0;
+ stat = apr_xml_parser_done(parser, &doc);
+ LOGUNIT_ASSERT(doc != 0);
+ apr_xml_elem* eventSet = doc->root;
+ LOGUNIT_ASSERT(eventSet != 0);
+ apr_xml_elem* event = eventSet->first_child;
+ LOGUNIT_ASSERT(event != 0);
+ return event;
+ }
+
+ std::string getAttribute(apr_xml_elem* elem, const char* attrName) {
+ for(apr_xml_attr* attr = elem->attr;
+ attr != NULL;
+ attr = attr->next) {
+ if (strcmp(attr->name, attrName) == 0) {
+ return attr->value;
+ }
+ }
+ return "";
+ }
+
+ std::string getText(apr_xml_elem* elem) {
+ std::string dMessage;
+ for(apr_text* t = elem->first_cdata.first;
+ t != NULL;
+ t = t->next) {
+ dMessage.append(t->text);
+ }
+ return dMessage;
+ }
+ /**
+ * Checks a log4j:event element against expectations.
+ * @param element element, may not be null.
+ * @param event event, may not be null.
+ */
+ void checkEventElement(
+ apr_xml_elem* element, LoggingEventPtr& event) {
+ std::string tagName("event");
+ LOGUNIT_ASSERT_EQUAL(tagName, (std::string) element->name);
+ LOG4CXX_ENCODE_CHAR(cLoggerName, event->getLoggerName());
+ LOGUNIT_ASSERT_EQUAL(cLoggerName, getAttribute(element, "logger"));
+ LOG4CXX_ENCODE_CHAR(cLevelName, event->getLevel()->toString());
+ LOGUNIT_ASSERT_EQUAL(cLevelName, getAttribute(element, "level"));
+ }
+
+ /**
+ * Checks a log4j:message element against expectations.
+ * @param element element, may not be null.
+ * @param message expected message.
+ */
+ void checkMessageElement(
+ apr_xml_elem* element, std::string message) {
+ std::string tagName = "message";
+ LOGUNIT_ASSERT_EQUAL(tagName, (std::string) element->name);
+ LOGUNIT_ASSERT_EQUAL(message, getText(element));
+ }
+
+ /**
+ * Checks a log4j:message element against expectations.
+ * @param element element, may not be null.
+ * @param message expected message.
+ */
+ void checkNDCElement(apr_xml_elem* element, std::string message) {
+ std::string tagName = "NDC";
+ LOGUNIT_ASSERT_EQUAL(tagName, (std::string) element->name);
+ std::string dMessage = getText(element);
+ LOGUNIT_ASSERT_EQUAL(message, dMessage);
+ }
+
+
+ /**
+ * Checks a log4j:properties element against expectations.
+ * @param element element, may not be null.
+ * @param key key.
+ * @param value value.
+ */
+ void checkPropertiesElement(
+ apr_xml_elem* element, std::string key, std::string value) {
+ std::string tagName = "properties";
+ std::string dataTag = "data";
+ int childNodeCount = 0;
+ LOGUNIT_ASSERT_EQUAL(tagName, (std::string) element->name);
+ for(apr_xml_elem* child = element->first_child;
+ child != NULL;
+ child = child->next) {
+ LOGUNIT_ASSERT_EQUAL(dataTag, (std::string) child->name);
+ LOGUNIT_ASSERT_EQUAL(key, getAttribute(child, "name"));
+ LOGUNIT_ASSERT_EQUAL(value, getAttribute(child, "value"));
+ childNodeCount++;
+ }
+ LOGUNIT_ASSERT_EQUAL(1, childNodeCount);
+ }
+
+public:
+ /**
+ * Tests formatted results.
+ * @throws Exception if parser can not be constructed or source is not a valid XML document.
+ */
+ void testFormat() {
+ LogString logger = LOG4CXX_STR("org.apache.log4j.xml.XMLLayoutTest");
+ LoggingEventPtr event =
+ new LoggingEvent(
+ logger, Level::getInfo(), LOG4CXX_STR("Hello, World"), LOG4CXX_LOCATION);
+ Pool p;
+ XMLLayout layout;
+ LogString result;
+ layout.format(result, event, p);
+ apr_xml_elem* parsedResult = parse(result, p);
+ checkEventElement(parsedResult, event);
+
+ int childElementCount = 0;
+ for (
+ apr_xml_elem* node = parsedResult->first_child;
+ node != NULL;
+ node = node->next) {
+ childElementCount++;
+ checkMessageElement(node, "Hello, World");
+ }
+
+ LOGUNIT_ASSERT_EQUAL(1, childElementCount);
+ }
+
+
+ /**
+ * Tests formatted results with an exception.
+ * @throws Exception if parser can not be constructed or source is not a valid XML document.
+ */
+ void testFormatWithNDC() {
+ LogString logger = LOG4CXX_STR("org.apache.log4j.xml.XMLLayoutTest");
+ NDC::push("NDC goes here");
+
+ LoggingEventPtr event =
+ new LoggingEvent(
+ logger, Level::getInfo(), LOG4CXX_STR("Hello, World"), LOG4CXX_LOCATION);
+ Pool p;
+ XMLLayout layout;
+ LogString result;
+ layout.format(result, event, p);
+ NDC::pop();
+
+ apr_xml_elem* parsedResult = parse(result, p);
+ checkEventElement(parsedResult, event);
+
+ int childElementCount = 0;
+
+ for (
+ apr_xml_elem* node = parsedResult->first_child; node != NULL;
+ node = node->next) {
+ childElementCount++;
+
+ if (childElementCount == 1) {
+ checkMessageElement(node, "Hello, World");
+ } else {
+ checkNDCElement(node, "NDC goes here");
+ }
+ }
+
+ LOGUNIT_ASSERT_EQUAL(2, childElementCount);
+ }
+
+ /**
+ * Tests getLocationInfo and setLocationInfo.
+ */
+ void testGetSetLocationInfo() {
+ XMLLayout layout;
+ LOGUNIT_ASSERT_EQUAL(false, layout.getLocationInfo());
+ layout.setLocationInfo(true);
+ LOGUNIT_ASSERT_EQUAL(true, layout.getLocationInfo());
+ layout.setLocationInfo(false);
+ LOGUNIT_ASSERT_EQUAL(false, layout.getLocationInfo());
+ }
+
+ /**
+ * Tests activateOptions().
+ */
+ void testActivateOptions() {
+ Pool p;
+ XMLLayout layout;
+ layout.activateOptions(p);
+ }
+
+ /**
+ * Tests problematic characters in multiple fields.
+ * @throws Exception if parser can not be constructed or source is not a valid XML document.
+ */
+ void testProblemCharacters() {
+ std::string problemName = "com.example.bar<>&\"'";
+ LogString problemNameLS = LOG4CXX_STR("com.example.bar<>&\"'");
+ LevelPtr level = new XLevel(6000, problemNameLS, 7);
+ NDC::push(problemName);
+ MDC::clear();
+ MDC::put(problemName, problemName);
+ LoggingEventPtr event =
+ new LoggingEvent(problemNameLS, level, problemNameLS, LOG4CXX_LOCATION);
+ XMLLayout layout;
+ layout.setProperties(true);
+ Pool p;
+ LogString result;
+ layout.format(result, event, p);
+ MDC::clear();
+
+ apr_xml_elem* parsedResult = parse(result, p);
+ checkEventElement(parsedResult, event);
+
+ int childElementCount = 0;
+
+ for (
+ apr_xml_elem* node = parsedResult->first_child; node != NULL;
+ node = node->next) {
+ childElementCount++;
+ switch(childElementCount) {
+ case 1:
+ checkMessageElement(node, problemName);
+ break;
+
+ case 2:
+ checkNDCElement(node, problemName);
+ break;
+
+ case 3:
+ checkPropertiesElement(node, problemName.c_str(), problemName.c_str());
+ break;
+
+ default:
+ break;
+ }
+
+ }
+ LOGUNIT_ASSERT_EQUAL(3, childElementCount);
+ }
+
+ /**
+ * Tests CDATA element within NDC content. See bug 37560.
+ */
+ void testNDCWithCDATA() {
+ LogString logger = LOG4CXX_STR("com.example.bar");
+ LevelPtr level = Level::getInfo();
+ std::string ndcMessage ="<envelope><faultstring><![CDATA[The EffectiveDate]]></faultstring><envelope>";
+ NDC::push(ndcMessage);
+ LoggingEventPtr event =
+ new LoggingEvent(
+ logger, level, LOG4CXX_STR("Hello, World"), LOG4CXX_LOCATION);
+ XMLLayout layout;
+ Pool p;
+ LogString result;
+ layout.format(result, event, p);
+ NDC::clear();
+ apr_xml_elem* parsedResult = parse(result, p);
+ int ndcCount = 0;
+ for(apr_xml_elem* node = parsedResult->first_child;
+ node != NULL;
+ node = node->next) {
+ if (strcmp(node->name, "NDC") == 0) {
+ ndcCount++;
+ LOGUNIT_ASSERT_EQUAL(ndcMessage, getText(node));
+ }
+ }
+ LOGUNIT_ASSERT_EQUAL(1, ndcCount);
+ }
+
+};
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(XMLLayoutTest);
+
diff --git a/src/test/cpp/xml/xmllayouttestcase.cpp b/src/test/cpp/xml/xmllayouttestcase.cpp
new file mode 100644
index 0000000..bd1cc8b
--- /dev/null
+++ b/src/test/cpp/xml/xmllayouttestcase.cpp
@@ -0,0 +1,357 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "../logunit.h"
+
+#include <log4cxx/logger.h>
+#include <log4cxx/xml/xmllayout.h>
+#include <log4cxx/fileappender.h>
+#include <log4cxx/mdc.h>
+
+#include "../util/transformer.h"
+#include "../util/compare.h"
+#include "../util/xmltimestampfilter.h"
+#include "../util/xmllineattributefilter.h"
+#include "../util/xmlthreadfilter.h"
+#include "../util/filenamefilter.h"
+#include <iostream>
+#include <log4cxx/helpers/stringhelper.h>
+#include "../testchar.h"
+#include <log4cxx/spi/loggerrepository.h>
+
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+using namespace log4cxx::xml;
+
+#if defined(__LOG4CXX_FUNC__)
+#undef __LOG4CXX_FUNC__
+#define __LOG4CXX_FUNC__ "X::X()"
+#else
+#error __LOG4CXX_FUNC__ expected to be defined
+#endif
+
+class X
+{
+public:
+ X()
+ {
+ LoggerPtr logger =
+ Logger::getLogger(LOG4CXX_TEST_STR("org.apache.log4j.xml.XMLLayoutTestCase$X"));
+ LOG4CXX_INFO(logger, LOG4CXX_TEST_STR("in X() constructor"));
+ }
+};
+
+
+LOGUNIT_CLASS(XMLLayoutTestCase)
+{
+ LOGUNIT_TEST_SUITE(XMLLayoutTestCase);
+ LOGUNIT_TEST(basic);
+ LOGUNIT_TEST(locationInfo);
+ LOGUNIT_TEST(testCDATA);
+ LOGUNIT_TEST(testNull);
+ LOGUNIT_TEST(testMDC);
+ LOGUNIT_TEST(testMDCEscaped);
+ LOGUNIT_TEST_SUITE_END();
+
+ LoggerPtr root;
+ LoggerPtr logger;
+
+public:
+ void setUp()
+ {
+ root = Logger::getRootLogger();
+ root->setLevel(Level::getTrace());
+ logger = Logger::getLogger(LOG4CXX_TEST_STR("org.apache.log4j.xml.XMLLayoutTestCase"));
+ logger->setLevel(Level::getTrace());
+ }
+
+ void tearDown()
+ {
+ logger->getLoggerRepository()->resetConfiguration();
+ }
+
+ void basic()
+ {
+ const LogString tempFileName(LOG4CXX_STR("output/temp.xmlLayout.1"));
+ const File filteredFile("output/filtered.xmlLayout.1");
+
+ XMLLayoutPtr xmlLayout = new XMLLayout();
+ AppenderPtr appender(new FileAppender(xmlLayout, tempFileName, false));
+ root->addAppender(appender);
+ common();
+
+ XMLTimestampFilter xmlTimestampFilter;
+ XMLThreadFilter xmlThreadFilter;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&xmlThreadFilter);
+ filters.push_back(&xmlTimestampFilter);
+
+ try
+ {
+ Transformer::transform(tempFileName, filteredFile, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(filteredFile, LOG4CXX_FILE("witness/xmlLayout.1")));
+ }
+
+ void locationInfo()
+ {
+ const LogString tempFileName(LOG4CXX_STR("output/temp.xmlLayout.2"));
+ const File filteredFile("output/filtered.xmlLayout.2");
+
+ XMLLayoutPtr xmlLayout = new XMLLayout();
+ xmlLayout->setLocationInfo(true);
+ root->addAppender(new FileAppender(xmlLayout, tempFileName, false));
+ common();
+
+ XMLTimestampFilter xmlTimestampFilter;
+ XMLThreadFilter xmlThreadFilter;
+ FilenameFilter xmlFilenameFilter(__FILE__, "XMLLayoutTestCase.java");
+ Filter line2XX("[23][0-9][0-9]", "X");
+ Filter line5X("5[0-9]", "X");
+
+ std::vector<Filter *> filters;
+ filters.push_back(&xmlFilenameFilter);
+ filters.push_back(&xmlThreadFilter);
+ filters.push_back(&xmlTimestampFilter);
+ filters.push_back(&line2XX);
+ filters.push_back(&line5X);
+
+ try
+ {
+ Transformer::transform(tempFileName, filteredFile, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(filteredFile, LOG4CXX_FILE("witness/xmlLayout.2")));
+ }
+
+
+
+#undef __LOG4CXX_FUNC__
+#define __LOG4CXX_FUNC__ "void XMLLayoutTestCase::testCDATA()"
+
+
+
+ void testCDATA()
+ {
+ const LogString tempFileName(LOG4CXX_STR("output/temp.xmlLayout.3"));
+ const File filteredFile("output/filtered.xmlLayout.3");
+
+ XMLLayoutPtr xmlLayout = new XMLLayout();
+ xmlLayout->setLocationInfo(true);
+ FileAppenderPtr appender(new FileAppender(xmlLayout, tempFileName, false));
+ root->addAppender(appender);
+
+ LOG4CXX_TRACE(logger,
+ LOG4CXX_TEST_STR("Message with embedded <![CDATA[<hello>hi</hello>]]>."));
+ LOG4CXX_DEBUG(logger,
+ LOG4CXX_TEST_STR("Message with embedded <![CDATA[<hello>hi</hello>]]>."));
+
+ XMLTimestampFilter xmlTimestampFilter;
+ XMLThreadFilter xmlThreadFilter;
+ FilenameFilter xmlFilenameFilter(__FILE__, "XMLLayoutTestCase.java");
+ Filter line1xx("1[0-9][0-9]", "X");
+
+ std::vector<Filter *> filters;
+ filters.push_back(&xmlFilenameFilter);
+ filters.push_back(&xmlThreadFilter);
+ filters.push_back(&xmlTimestampFilter);
+ filters.push_back(&line1xx);
+
+ try
+ {
+ Transformer::transform(tempFileName, filteredFile, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(filteredFile, LOG4CXX_FILE("witness/xmlLayout.3")));
+ }
+
+ void testNull()
+ {
+ const LogString tempFileName(LOG4CXX_STR("output/temp.xmlLayout.null"));
+ const File filteredFile("output/filtered.xmlLayout.null");
+
+ XMLLayoutPtr xmlLayout = new XMLLayout();
+ FileAppenderPtr appender(new FileAppender(xmlLayout, tempFileName, false));
+ root->addAppender(appender);
+
+ LOG4CXX_DEBUG(logger, LOG4CXX_TEST_STR("hi"));
+ LOG4CXX_DEBUG(logger, (char*) 0);
+ LOG4CXX_DEBUG(logger, "hi");
+
+ XMLTimestampFilter xmlTimestampFilter;
+ XMLThreadFilter xmlThreadFilter;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&xmlThreadFilter);
+ filters.push_back(&xmlTimestampFilter);
+
+ try
+ {
+ Transformer::transform(tempFileName, filteredFile, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(filteredFile, LOG4CXX_FILE("witness/xmlLayout.null")));
+ }
+
+ void testMDC()
+ {
+ const LogString tempFileName(LOG4CXX_STR("output/temp.xmlLayout.mdc.1"));
+ const File filteredFile("output/filtered.xmlLayout.mdc.1");
+
+ XMLLayoutPtr xmlLayout = new XMLLayout();
+ xmlLayout->setProperties(true);
+ FileAppenderPtr appender(new FileAppender(xmlLayout, tempFileName, false));
+ root->addAppender(appender);
+
+ MDC::clear();
+ MDC::put(LOG4CXX_TEST_STR("key1"), LOG4CXX_TEST_STR("val1"));
+ MDC::put(LOG4CXX_TEST_STR("key2"), LOG4CXX_TEST_STR("val2"));
+
+ LOG4CXX_DEBUG(logger, LOG4CXX_TEST_STR("Hello"));
+
+ MDC::clear();
+
+ XMLTimestampFilter xmlTimestampFilter;
+ XMLThreadFilter xmlThreadFilter;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&xmlThreadFilter);
+ filters.push_back(&xmlTimestampFilter);
+
+ try
+ {
+ Transformer::transform(tempFileName, filteredFile, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(filteredFile, LOG4CXX_FILE("witness/xmlLayout.mdc.1")));
+ }
+
+ // not incuded in the tests for the moment !
+ void testMDCEscaped()
+ {
+ const LogString tempFileName(LOG4CXX_STR("output/temp.xmlLayout.mdc.2"));
+ const File filteredFile("output/filtered.xmlLayout.mdc.2");
+
+ XMLLayoutPtr xmlLayout = new XMLLayout();
+ xmlLayout->setProperties(true);
+ FileAppenderPtr appender(new FileAppender(xmlLayout, tempFileName, false));
+ root->addAppender(appender);
+
+ MDC::clear();
+ MDC::put(LOG4CXX_TEST_STR("blahAttribute"), LOG4CXX_TEST_STR("<blah value='blah'>"));
+ MDC::put(LOG4CXX_TEST_STR("<blahKey value='blah'/>"), LOG4CXX_TEST_STR("blahValue"));
+
+ LOG4CXX_DEBUG(logger, LOG4CXX_TEST_STR("Hello"));
+
+ MDC::clear();
+
+ XMLTimestampFilter xmlTimestampFilter;
+ XMLThreadFilter xmlThreadFilter;
+
+ std::vector<Filter *> filters;
+ filters.push_back(&xmlThreadFilter);
+ filters.push_back(&xmlTimestampFilter);
+
+ try
+ {
+ Transformer::transform(tempFileName, filteredFile, filters);
+ }
+ catch(UnexpectedFormatException& e)
+ {
+ std::cout << "UnexpectedFormatException :" << e.what() << std::endl;
+ throw;
+ }
+
+ LOGUNIT_ASSERT(Compare::compare(filteredFile, LOG4CXX_FILE("witness/xmlLayout.mdc.2")));
+ }
+
+
+
+#undef __LOG4CXX_FUNC__
+#define __LOG4CXX_FUNC__ "void XMLLayoutTestCase::common()"
+
+
+
+ void common()
+ {
+ int i = 0;
+ X x;
+
+ std::string msg("Message ");
+
+ LOG4CXX_TRACE(logger, msg << i);
+ LOG4CXX_TRACE(root, msg << i);
+
+ i++;
+ LOG4CXX_DEBUG(logger, msg << i);
+ LOG4CXX_DEBUG(root, msg << i);
+
+ i++;
+ LOG4CXX_INFO(logger, msg << i);
+ LOG4CXX_INFO(root, msg << i);
+
+ i++;
+ LOG4CXX_WARN(logger, msg << i);
+ LOG4CXX_WARN(root, msg << i);
+
+ i++;
+ LOG4CXX_ERROR(logger, msg << i);
+ LOG4CXX_ERROR(root, msg << i);
+
+ i++;
+ LOG4CXX_FATAL(logger, msg << i);
+ LOG4CXX_FATAL(root, msg << i);
+
+ i++;
+ LOG4CXX_DEBUG(logger, "Message " << i);
+ LOG4CXX_DEBUG(root, "Message " << i);
+
+ i++;
+ LOG4CXX_ERROR(logger, "Message " << i);
+ LOG4CXX_ERROR(root, "Message " << i);
+ }
+};
+
+LOGUNIT_TEST_SUITE_REGISTRATION(XMLLayoutTestCase);
diff --git a/src/test/java/org/apache/log4j/net/ShortSocketServer.java b/src/test/java/org/apache/log4j/net/ShortSocketServer.java
new file mode 100644
index 0000000..76a46d1
--- /dev/null
+++ b/src/test/java/org/apache/log4j/net/ShortSocketServer.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.log4j.net;
+
+import java.net.Socket;
+import java.net.ServerSocket;
+import java.io.IOException;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.log4j.MDC;
+import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.net.SocketNode;
+import org.apache.log4j.net.SocketServer;
+
+/**
+ * This SocketServer exits after certain number of connections from a
+ * client. This number is determined the totalsTest parameter, that is
+ * the first argument on the commmand line. The second argument,
+ * prefix, determines the prefix of the configuration file to
+ * use. Each run of the server will use a different properties
+ * file. For the i-th run, the path to the file is
+ * (prefix+i+".properties").
+ *
+ * @author Ceki Gulcu */
+
+public class ShortSocketServer {
+
+ static Logger cat = Logger.getLogger(ShortSocketServer.class);
+
+ public
+ static
+ void main(String args[]) throws Exception {
+ int totalTests = 0;
+ String prefix = null;
+
+ if(args.length == 2) {
+ totalTests = Integer.parseInt(args[0]);
+ prefix = args[1];
+ } else {
+ usage("Wrong number of arguments.");
+ }
+
+
+ int port = Integer.valueOf(System.getProperty("port", "12345"));
+ LogLog.debug("Listening on port " + port);
+ ServerSocket serverSocket = new ServerSocket(port);
+
+ MDC.put("hostID", "shortSocketServer");
+
+ for(int i = 1; i <= totalTests; i++) {
+ PropertyConfigurator.configure(prefix+i+".properties");
+ LogLog.debug("Waiting to accept a new client.");
+ Socket socket = serverSocket.accept();
+ LogLog.debug("Connected to client at " + socket.getInetAddress());
+ LogLog.debug("Starting new socket node.");
+ SocketNode sn = new SocketNode(socket, LogManager.getLoggerRepository());
+ Thread t = new Thread(sn);
+ t.start();
+ t.join();
+ }
+ }
+
+
+ static
+ void usage(String msg) {
+ System.err.println(msg);
+ System.err.println(
+ "Usage: java " +ShortSocketServer.class.getName() + " totalTests configFilePrefix");
+ System.exit(1);
+ }
+}
diff --git a/src/test/resources/L7D_en_US.properties b/src/test/resources/L7D_en_US.properties
new file mode 100644
index 0000000..a52cd67
--- /dev/null
+++ b/src/test/resources/L7D_en_US.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+test=This is the English, US test.
+hello_world=Hello world.
+msg1=This is test number {0} with string argument {1}.
diff --git a/src/test/resources/L7D_fr.properties b/src/test/resources/L7D_fr.properties
new file mode 100644
index 0000000..268e6f6
--- /dev/null
+++ b/src/test/resources/L7D_fr.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+test=Ceci est le test en francais pour la France.
+hello_world=Bonjour la France.
+msg1=Ceci est le test numero {0} contenant l'argument {1}.
diff --git a/src/test/resources/L7D_fr_CH.properties b/src/test/resources/L7D_fr_CH.properties
new file mode 100644
index 0000000..7e89891
--- /dev/null
+++ b/src/test/resources/L7D_fr_CH.properties
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+test=Ceci est le test en francais pour la p'tite Suisse.
+hello world=Salut le monde.
diff --git a/src/test/resources/Makefile.am b/src/test/resources/Makefile.am
new file mode 100644
index 0000000..f64b2f0
--- /dev/null
+++ b/src/test/resources/Makefile.am
@@ -0,0 +1,68 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+SUBDIRS = input witness
+EXTRA_DIST = L7D_en_US.properties L7D_fr_CH.properties L7D_fr.properties
+
+
+
+# if we are building in a separate build tree, then copy all necessary files
+all-local:
+ @if test "$(top_srcdir)" != "$(top_builddir)"; then \
+ echo "Copying test suite data files ..." ; \
+ list='$(EXTRA_DIST)'; for file in $$list; do \
+ cp -p $(srcdir)/$$file . ; \
+ done \
+ fi
+
+prepare:
+ @if test ! -d "output"; then \
+ mkdir output; \
+ fi;
+ @rm -rf log4j.xml
+ @rm -rf log4j.properties
+ @rm -rf log4cxx.xml
+ @rm -rf log4cxx.properties
+
+build: check-recursive prepare
+
+cleanOutputDir:
+ @rm -rf output/*
+
+check: prepare run-unittest DefaultInit
+
+run-unittest: build cleanOutputDir
+ @export TOTO=wonderful; \
+ export key1=value1; \
+ export key2=value2; \
+ ../cpp/testsuite -v
+
+DefaultInit: build cleanOutputDir
+ ../cpp/testsuite -v testcase1
+ @cp input/xml/defaultInit.xml log4j.xml
+ ../cpp/testsuite -v testcase2
+ @rm -f log4j.xml
+ @cp input/defaultInit3.properties log4j.properties
+ ../cpp/testsuite -v testcase3
+ @rm -f log4j.properties
+ @cp input/defaultInit3.properties log4j.properties
+ @cp input/xml/defaultInit.xml log4j.xml
+ ../cpp/testsuite -v testcase4
+ @rm -f log4j.xml
+ @rm -f log4j.properties
+
+SocketServer: build cleanOutputDir
+ ../cpp/testsuite -v socketservertestcase
+
diff --git a/src/test/resources/input/Makefile.am b/src/test/resources/input/Makefile.am
new file mode 100644
index 0000000..492d81c
--- /dev/null
+++ b/src/test/resources/input/Makefile.am
@@ -0,0 +1,26 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+SUBDIRS = ndc xml rolling
+EXTRA_DIST = *.properties
+
+# if we are building in a separate build tree, then copy all necessary files
+all-local:
+ @if test "$(top_srcdir)" != "$(top_builddir)"; then \
+ echo "Copying test suite data files ..." ; \
+ list='$(EXTRA_DIST)'; for file in $$list; do \
+ cp -p $(srcdir)/$$file . ; \
+ done \
+ fi
diff --git a/src/test/resources/input/defaultInit3.properties b/src/test/resources/input/defaultInit3.properties
new file mode 100644
index 0000000..6101837
--- /dev/null
+++ b/src/test/resources/input/defaultInit3.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, D3
+log4j.appender.D3=org.apache.log4j.FileAppender
+log4j.appender.D3.File=output/temp
+log4j.appender.D3.Append=false
+log4j.appender.D3.layout=org.apache.log4j.PatternLayout
+log4j.appender.D3.layout.ConversionPattern=%d [%t] %-5p %.16c - %m%n \ No newline at end of file
diff --git a/src/test/resources/input/hierarchyThreshold1.properties b/src/test/resources/input/hierarchyThreshold1.properties
new file mode 100644
index 0000000..2a62676
--- /dev/null
+++ b/src/test/resources/input/hierarchyThreshold1.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.threshold=OFF
+log4j.rootLogger=,A
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.File=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%p %c = %m%n
diff --git a/src/test/resources/input/hierarchyThreshold2.properties b/src/test/resources/input/hierarchyThreshold2.properties
new file mode 100644
index 0000000..a997420
--- /dev/null
+++ b/src/test/resources/input/hierarchyThreshold2.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.threshold=FATAL
+log4j.rootLogger=,A
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.File=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%p %c = %m%n
diff --git a/src/test/resources/input/hierarchyThreshold3.properties b/src/test/resources/input/hierarchyThreshold3.properties
new file mode 100644
index 0000000..d81982d
--- /dev/null
+++ b/src/test/resources/input/hierarchyThreshold3.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.threshold=ERROR
+log4j.rootLogger=,A
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.File=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%p %c = %m%n
diff --git a/src/test/resources/input/hierarchyThreshold4.properties b/src/test/resources/input/hierarchyThreshold4.properties
new file mode 100644
index 0000000..97be410
--- /dev/null
+++ b/src/test/resources/input/hierarchyThreshold4.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.threshold=WARN
+log4j.rootLogger=,A
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.File=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%p %c = %m%n
diff --git a/src/test/resources/input/hierarchyThreshold5.properties b/src/test/resources/input/hierarchyThreshold5.properties
new file mode 100644
index 0000000..dd21f44
--- /dev/null
+++ b/src/test/resources/input/hierarchyThreshold5.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.threshold=INFO
+log4j.rootLogger=,A
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.File=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%p %c = %m%n
diff --git a/src/test/resources/input/hierarchyThreshold6.properties b/src/test/resources/input/hierarchyThreshold6.properties
new file mode 100644
index 0000000..1d57103
--- /dev/null
+++ b/src/test/resources/input/hierarchyThreshold6.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.threshold=DEBUG
+log4j.rootLogger=,A
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.File=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%p %c = %m%n
diff --git a/src/test/resources/input/hierarchyThreshold7.properties b/src/test/resources/input/hierarchyThreshold7.properties
new file mode 100644
index 0000000..4e06b63
--- /dev/null
+++ b/src/test/resources/input/hierarchyThreshold7.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.threshold=TRACE#org.apache.log4j.xml.XLevel
+log4j.rootLogger=ALL,A
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.File=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%p %c = %m%n
diff --git a/src/test/resources/input/hierarchyThreshold8.properties b/src/test/resources/input/hierarchyThreshold8.properties
new file mode 100644
index 0000000..dfec144
--- /dev/null
+++ b/src/test/resources/input/hierarchyThreshold8.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.threshold=ALL
+log4j.rootLogger=ALL,A
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.File=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%p %c = %m%n
diff --git a/src/test/resources/input/l7d1.properties b/src/test/resources/input/l7d1.properties
new file mode 100644
index 0000000..70a7188
--- /dev/null
+++ b/src/test/resources/input/l7d1.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=INFO, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File= output/temp
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=T1 %5p - %m%n
diff --git a/src/test/resources/input/ndc/Makefile.am b/src/test/resources/input/ndc/Makefile.am
new file mode 100644
index 0000000..5b67b7e
--- /dev/null
+++ b/src/test/resources/input/ndc/Makefile.am
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+EXTRA_DIST = *.properties
+
+# if we are building in a separate build tree, then copy all necessary files
+all-local:
+ @if test "$(top_srcdir)" != "$(top_builddir)"; then \
+ echo "Copying test suite data files ..." ; \
+ list='$(EXTRA_DIST)'; for file in $$list; do \
+ cp -p $(srcdir)/$$file . ; \
+ done \
+ fi
diff --git a/src/test/resources/input/ndc/NDC1.properties b/src/test/resources/input/ndc/NDC1.properties
new file mode 100755
index 0000000..8ced024
--- /dev/null
+++ b/src/test/resources/input/ndc/NDC1.properties
@@ -0,0 +1,26 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.file=output/temp
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%-5p %x - %m%n
+
+# Prevent internal log4j DEBUG messages from polluting the output.
+log4j.logger.org.apache.log4j.PropertyConfigurator=INFO
+log4j.logger.org.apache.log4j.config.PropertySetter=INFO
+log4j.logger.org.apache.log4j.FileAppender=INFO
diff --git a/src/test/resources/input/patternLayout.mdc.1.properties b/src/test/resources/input/patternLayout.mdc.1.properties
new file mode 100644
index 0000000..328dfef
--- /dev/null
+++ b/src/test/resources/input/patternLayout.mdc.1.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File=output/temp
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%-5p - %m %X \ No newline at end of file
diff --git a/src/test/resources/input/patternLayout1.properties b/src/test/resources/input/patternLayout1.properties
new file mode 100644
index 0000000..ad485ec
--- /dev/null
+++ b/src/test/resources/input/patternLayout1.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.file=output/temp
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%-5p - %m%n \ No newline at end of file
diff --git a/src/test/resources/input/patternLayout10.properties b/src/test/resources/input/patternLayout10.properties
new file mode 100644
index 0000000..a42de7c
--- /dev/null
+++ b/src/test/resources/input/patternLayout10.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File= output/temp
+log4j.appender.testAppender.Append= false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=[%t] %-5p %l: %m%n
diff --git a/src/test/resources/input/patternLayout11.properties b/src/test/resources/input/patternLayout11.properties
new file mode 100644
index 0000000..9a23d57
--- /dev/null
+++ b/src/test/resources/input/patternLayout11.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File=output/temp
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%-5p [%t] %c{2}: %m%n \ No newline at end of file
diff --git a/src/test/resources/input/patternLayout12.properties b/src/test/resources/input/patternLayout12.properties
new file mode 100644
index 0000000..feb4c32
--- /dev/null
+++ b/src/test/resources/input/patternLayout12.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File=output/temp
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=[%t] %-5p %F(%L): %m%n
diff --git a/src/test/resources/input/patternLayout2.properties b/src/test/resources/input/patternLayout2.properties
new file mode 100644
index 0000000..7cc2bcd
--- /dev/null
+++ b/src/test/resources/input/patternLayout2.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File=output/temp
+log4j.appender.testAppender.Append= false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %.16c - %m%n
diff --git a/src/test/resources/input/patternLayout3.properties b/src/test/resources/input/patternLayout3.properties
new file mode 100644
index 0000000..45c96d3
--- /dev/null
+++ b/src/test/resources/input/patternLayout3.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File=output/layout3
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] %-5p %.16c - %m%n
diff --git a/src/test/resources/input/patternLayout4.properties b/src/test/resources/input/patternLayout4.properties
new file mode 100644
index 0000000..924e333
--- /dev/null
+++ b/src/test/resources/input/patternLayout4.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File=output/temp
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%d{DATE} [%t] %-5p %.16c - %m%n \ No newline at end of file
diff --git a/src/test/resources/input/patternLayout5.properties b/src/test/resources/input/patternLayout5.properties
new file mode 100644
index 0000000..66a0c06
--- /dev/null
+++ b/src/test/resources/input/patternLayout5.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File=output/temp
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%d{dd MMM yyyy HH:mm:ss,SSS} [%t] %-5p %.16c - %m%n
diff --git a/src/test/resources/input/patternLayout6.properties b/src/test/resources/input/patternLayout6.properties
new file mode 100644
index 0000000..2caf150
--- /dev/null
+++ b/src/test/resources/input/patternLayout6.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File=output/temp
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%d{ABSOLUTE} [%t] %-5p %.16c - %m%n \ No newline at end of file
diff --git a/src/test/resources/input/patternLayout7.properties b/src/test/resources/input/patternLayout7.properties
new file mode 100644
index 0000000..278098d
--- /dev/null
+++ b/src/test/resources/input/patternLayout7.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File=output/temp
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%t] %-5p %.16c - %m%n
diff --git a/src/test/resources/input/patternLayout8.properties b/src/test/resources/input/patternLayout8.properties
new file mode 100644
index 0000000..1426163
--- /dev/null
+++ b/src/test/resources/input/patternLayout8.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File=output/temp
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%r [%t] %-5p %.16c - %m%n \ No newline at end of file
diff --git a/src/test/resources/input/patternLayout9.properties b/src/test/resources/input/patternLayout9.properties
new file mode 100644
index 0000000..bdc6623
--- /dev/null
+++ b/src/test/resources/input/patternLayout9.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootCategory=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.FileAppender
+log4j.appender.testAppender.File=output/temp
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=[%t] %-5p %.16c : %m%n \ No newline at end of file
diff --git a/src/test/resources/input/rolling/Makefile.am b/src/test/resources/input/rolling/Makefile.am
new file mode 100644
index 0000000..ae80170
--- /dev/null
+++ b/src/test/resources/input/rolling/Makefile.am
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+EXTRA_DIST = *.xml *.properties
+
+# if we are building in a separate build tree, then copy all necessary files
+all-local:
+ @if test "$(top_srcdir)" != "$(top_builddir)"; then \
+ echo "Copying test suite data files ..." ; \
+ list='$(EXTRA_DIST)'; for file in $$list; do \
+ cp -p $(srcdir)/$$file . ; \
+ done \
+ fi
diff --git a/src/test/resources/input/rolling/filter1.xml b/src/test/resources/input/rolling/filter1.xml
new file mode 100644
index 0000000..2e9314e
--- /dev/null
+++ b/src/test/resources/input/rolling/filter1.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j='http://logging.apache.org/' debug="true">
+
+ <appender name="ROLLING" class="org.apache.log4j.rolling.RollingFileAppender">
+ <rollingPolicy class="org.apache.log4j.rolling.FixedWindowRollingPolicy">
+ <param name="fileNamePattern" value="output/filterBased-test1.%i"/>
+ <param name="minIndex" value="0"/>
+ </rollingPolicy>
+ <triggeringPolicy class="org.apache.log4j.rolling.FilterBasedTriggeringPolicy">
+ <filter class="org.apache.log4j.filter.LevelRangeFilter">
+ <param name="levelMin" value="info" />
+ </filter>
+ </triggeringPolicy>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%m%n"/>
+ </layout>
+ <param name="file" value="output/filterBased-test1.log"/>
+ <param name="append" value="false"/>
+
+ </appender>
+
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%m%n"/>
+ </layout>
+ </appender>
+
+ <logger name="org.apache.log4j.rolling.FilterBasedRollingTest" additivity="false">
+ <appender-ref ref="ROLLING"/>
+ <level value="debug"/>
+ </logger>
+
+ <root>
+ <level value="info"/>
+ <appender-ref ref="CONSOLE"/>
+ </root>
+</log4j:configuration>
diff --git a/src/test/resources/input/rolling/obsoleteDRFA1.properties b/src/test/resources/input/rolling/obsoleteDRFA1.properties
new file mode 100644
index 0000000..43893d8
--- /dev/null
+++ b/src/test/resources/input/rolling/obsoleteDRFA1.properties
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootLogger=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.testAppender.file=output/obsoleteDRFA-test1.log
+log4j.appender.testAppender.datePattern='.'yyyy-MM-dd_HH_mm_ss
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%m%n
+
+# Prevent internal log4j DEBUG messages from polluting the output.
+log4j.logger.org.apache.log4j.PropertyConfigurator=INFO
+log4j.logger.org.apache.log4j.config.PropertySetter=INFO
+log4j.logger.org.apache.log4j.FileAppender=INFO
diff --git a/src/test/resources/input/rolling/obsoleteERFA1.properties b/src/test/resources/input/rolling/obsoleteERFA1.properties
new file mode 100644
index 0000000..73be41f
--- /dev/null
+++ b/src/test/resources/input/rolling/obsoleteERFA1.properties
@@ -0,0 +1,28 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootLogger=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.varia.ExternallyRolledFileAppender
+log4j.appender.testAppender.file=output/obsoleteERFA-test1.log
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%m\n
+log4j.appender.testAppender.maxFileSize=10000
+log4j.appender.testAppender.port=6700
+
+# Prevent internal log4j DEBUG messages from polluting the output.
+log4j.logger.org.apache.log4j.PropertyConfigurator=INFO
+log4j.logger.org.apache.log4j.config.PropertySetter=INFO
+log4j.logger.org.apache.log4j.FileAppender=INFO
diff --git a/src/test/resources/input/rolling/obsoleteRFA1.properties b/src/test/resources/input/rolling/obsoleteRFA1.properties
new file mode 100644
index 0000000..1255605
--- /dev/null
+++ b/src/test/resources/input/rolling/obsoleteRFA1.properties
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+log4j.rootLogger=DEBUG, testAppender
+log4j.appender.testAppender=org.apache.log4j.RollingFileAppender
+log4j.appender.testAppender.file=output/obsoleteRFA-test1.log
+log4j.appender.testAppender.Append=false
+log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.testAppender.layout.ConversionPattern=%m\n
+log4j.appender.testAppender.maxFileSize=100
+
+# Prevent internal log4j DEBUG messages from polluting the output.
+log4j.logger.org.apache.log4j.PropertyConfigurator=INFO
+log4j.logger.org.apache.log4j.config.PropertySetter=INFO
+log4j.logger.org.apache.log4j.FileAppender=INFO
diff --git a/src/test/resources/input/rolling/time1.xml b/src/test/resources/input/rolling/time1.xml
new file mode 100644
index 0000000..54b660c
--- /dev/null
+++ b/src/test/resources/input/rolling/time1.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<!DOCTYPE log4j:configuration>
+
+<log4j:configuration xmlns:log4j='http://logging.apache.org/' debug="true">
+
+ <appender name="ROLL" class="org.apache.log4j.rolling.RollingFileAppender">
+ <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
+ <param name="fileNamePattern" value="output/test1-%d{yyyy-MM-dd_HH_mm_ss}"/>
+ </rollingPolicy>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%c{1} - %m%n"/>
+ </layout>
+ </appender>
+
+<!--
+ <logger name="org.apache.log4j.joran"><level value="INFO"/></logger>
+ <logger name="org.apache.log4j.rolling.RollingFileAppender"><level value="INFO"/></logger>
+ <logger name="org.apache.log4j.rolling.TimeBasedRollingPolicy"><level value="INFO"/></logger>
+ <logger name="org.apache.log4j.config.PropertySetter"><level value="INFO"/></logger>
+-->
+ <logger name="org.apache.log4j.rolling.TimeBasedRollingTest">
+ <appender-ref ref="ROLL"/>
+ </logger>
+
+</log4j:configuration> \ No newline at end of file
diff --git a/src/test/resources/input/socketServer1.properties b/src/test/resources/input/socketServer1.properties
new file mode 100644
index 0000000..573524b
--- /dev/null
+++ b/src/test/resources/input/socketServer1.properties
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+log4j.rootLogger=TRACE, A
+log4j.logger.org.apache.log4j.test.ShortSocketServer=WARN
+log4j.logger.org.apache.log4j.net.SocketNode=WARN
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.file=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%5p %x [%t] %c %m%n
+
diff --git a/src/test/resources/input/socketServer2.properties b/src/test/resources/input/socketServer2.properties
new file mode 100644
index 0000000..aafd7af
--- /dev/null
+++ b/src/test/resources/input/socketServer2.properties
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+log4j.rootLogger=TRACE, A
+log4j.logger.org.apache.log4j.test.ShortSocketServer=WARN
+log4j.logger.org.apache.log4j.net.SocketNode=WARN
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.file=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%5p %x [%t] %C (%F:%L) %m%n
+
diff --git a/src/test/resources/input/socketServer3.properties b/src/test/resources/input/socketServer3.properties
new file mode 100644
index 0000000..7ddb85c
--- /dev/null
+++ b/src/test/resources/input/socketServer3.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+log4j.rootLogger=TRACE, A
+log4j.Logger.org.apache.log4j.test.ShortSocketServer=WARN
+log4j.Logger.org.apache.log4j.net.SocketNode=WARN
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.file=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%5p %x [%t] %C (%F:%L) %m%n
diff --git a/src/test/resources/input/socketServer4.properties b/src/test/resources/input/socketServer4.properties
new file mode 100644
index 0000000..c00fd65
--- /dev/null
+++ b/src/test/resources/input/socketServer4.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+log4j.rootLogger=TRACE, A
+log4j.Logger.org.apache.log4j.test.ShortSocketServer=WARN
+log4j.Logger.org.apache.log4j.net.SocketNode=WARN
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.file=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%5p %x %X{key1}%X{key4} [%t] %c{1} - %m%n
diff --git a/src/test/resources/input/socketServer5.properties b/src/test/resources/input/socketServer5.properties
new file mode 100644
index 0000000..d2d03ce
--- /dev/null
+++ b/src/test/resources/input/socketServer5.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+log4j.rootLogger=TRACE, A
+log4j.Logger.org.apache.log4j.test.ShortSocketServer=WARN
+log4j.Logger.org.apache.log4j.net.SocketNode=WARN
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.file=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%5p %x %X{key1}%X{key5} [%t] %c{1} - %m%n
diff --git a/src/test/resources/input/socketServer6.properties b/src/test/resources/input/socketServer6.properties
new file mode 100644
index 0000000..19a817c
--- /dev/null
+++ b/src/test/resources/input/socketServer6.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+log4j.rootLogger=TRACE, A
+log4j.Logger.org.apache.log4j.test.ShortSocketServer=WARN
+log4j.Logger.org.apache.log4j.net.SocketNode=WARN
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.file=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%5p %x %X{hostID} %X{key6} [%t] %c{1} - %m%n
diff --git a/src/test/resources/input/socketServer7.properties b/src/test/resources/input/socketServer7.properties
new file mode 100644
index 0000000..742eceb
--- /dev/null
+++ b/src/test/resources/input/socketServer7.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+log4j.rootLogger=TRACE, A
+log4j.Logger.org.apache.log4j.test.ShortSocketServer=WARN
+log4j.Logger.org.apache.log4j.net.SocketNode=WARN
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.file=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%5p %x %X{hostID} %X{key7} [%t] %c{1} - %m%n
diff --git a/src/test/resources/input/socketServer8.properties b/src/test/resources/input/socketServer8.properties
new file mode 100644
index 0000000..fa31a08
--- /dev/null
+++ b/src/test/resources/input/socketServer8.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+log4j.rootLogger=TRACE, A
+log4j.Logger.org.apache.log4j.test.ShortSocketServer=WARN
+log4j.Logger.org.apache.log4j.net.SocketNode=WARN
+log4j.appender.A=org.apache.log4j.FileAppender
+log4j.appender.A.file=output/temp
+log4j.appender.A.Append=false
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+log4j.appender.A.layout.ConversionPattern=%5p %x %X{hostID} %X{key8} [%t] %c{1} - %m%n
diff --git a/src/test/resources/input/xml/DOMTestCase1.xml b/src/test/resources/input/xml/DOMTestCase1.xml
new file mode 100755
index 0000000..c75ab26
--- /dev/null
+++ b/src/test/resources/input/xml/DOMTestCase1.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="A1" class="org.apache.log4j.FileAppender">
+
+ <param name="File" value="output/temp.A1" />
+ <param name="Append" value="false" />
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %c{2} - %m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="A2" class="org.apache.log4j.FileAppender">
+ <param name="File" value="output/temp.A2" />
+ <param name="Append" value="false" />
+ <layout class="org.apache.log4j.TTCCLayout">
+ <param name="DateFormat" value="ISO8601" />
+ </layout>
+ </appender>
+
+ <logger name="org.apache.log4j.xml">
+ <level value="debug" />
+ <appender-ref ref="A1" />
+ </logger>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="A1" />
+ <appender-ref ref="A2" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/DOMTestCase2.xml b/src/test/resources/input/xml/DOMTestCase2.xml
new file mode 100755
index 0000000..409d3a3
--- /dev/null
+++ b/src/test/resources/input/xml/DOMTestCase2.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="A1" class="org.apache.log4j.FileAppender">
+
+ <param name="File" value="output\temp.A1.2" />
+ <param name="Append" value="false" />
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %c{2} - %m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="A2" class="org.apache.log4j.FileAppender">
+ <param name="File" value="output\temp.A2.2" />
+ <param name="Append" value="false" />
+ <layout class="org.apache.log4j.TTCCLayout">
+ <param name="DateFormat" value="ISO8601" />
+ </layout>
+ </appender>
+
+ <logger name="org.apache.log4j.xml">
+ <level value="debug" />
+ <appender-ref ref="A1" />
+ </logger>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="A1" />
+ <appender-ref ref="A2" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/DOMTestCase3.xml b/src/test/resources/input/xml/DOMTestCase3.xml
new file mode 100755
index 0000000..46d9f1d
--- /dev/null
+++ b/src/test/resources/input/xml/DOMTestCase3.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="A1" class="org.apache.log4j.FileAppender">
+
+ <param name="File" value="output/dom&#xB3;" />
+ <param name="Append" value="false" />
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %c{2} - %m%n"/>
+ </layout>
+ </appender>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="A1" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/DOMTestCase4.xml b/src/test/resources/input/xml/DOMTestCase4.xml
new file mode 100755
index 0000000..d842666
--- /dev/null
+++ b/src/test/resources/input/xml/DOMTestCase4.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="A1" class="org.apache.log4j.FileAppender">
+
+ <param name="File" value="output/dom&#x3195;" />
+ <param name="Append" value="false" />
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %c{2} - %m%n"/>
+ </layout>
+ </appender>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="A1" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/Makefile.am b/src/test/resources/input/xml/Makefile.am
new file mode 100644
index 0000000..065d1f0
--- /dev/null
+++ b/src/test/resources/input/xml/Makefile.am
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+EXTRA_DIST = log4j.dtd *.xml
+
+# if we are building in a separate build tree, then copy all necessary files
+all-local:
+ @if test "$(top_srcdir)" != "$(top_builddir)"; then \
+ echo "Copying test suite data files ..." ; \
+ list='$(EXTRA_DIST)'; for file in $$list; do \
+ cp -p $(srcdir)/$$file . ; \
+ done \
+ fi
diff --git a/src/test/resources/input/xml/asyncAppender1.xml b/src/test/resources/input/xml/asyncAppender1.xml
new file mode 100755
index 0000000..3ad3afc
--- /dev/null
+++ b/src/test/resources/input/xml/asyncAppender1.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
+
+ <appender name="VECTOR" class="org.apache.log4j.VectorAppender"/>
+
+ <appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
+ <param name="BufferSize" value="100"/>
+ <param name="Blocking" value="false"/>
+ <param name="LocationInfo" value="true"/>
+ <appender-ref ref="VECTOR"/>
+ </appender>
+
+ <root>
+ <level value="DEBUG"/>
+ <appender-ref ref="ASYNC" />
+ </root>
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/customLevel1.xml b/src/test/resources/input/xml/customLevel1.xml
new file mode 100755
index 0000000..19dac18
--- /dev/null
+++ b/src/test/resources/input/xml/customLevel1.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
+
+ <appender name="TEMP" class="org.apache.log4j.FileAppender">
+ <param name="Append" value="false" />
+ <param name="File" value="output/temp" />
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%-5p %c{2} - %m\n"/>
+ </layout>
+ </appender>
+
+ <root>
+ <level value="TRACE" class="org.apache.log4j.xml.XLevel"/>
+ <appender-ref ref="TEMP" />
+ </root>
+</log4j:configuration> \ No newline at end of file
diff --git a/src/test/resources/input/xml/customLevel2.xml b/src/test/resources/input/xml/customLevel2.xml
new file mode 100755
index 0000000..7226550
--- /dev/null
+++ b/src/test/resources/input/xml/customLevel2.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'
+ debug="false">
+
+ <appender name="TEMP" class="org.apache.log4j.FileAppender">
+ <param name="Append" value="false" />
+ <param name="File" value="output/temp" />
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%-5p %c{2} - %m\n"/>
+ </layout>
+
+ <filter class="org.apache.log4j.varia.LevelMatchFilter">
+ <param name="LevelToMatch" value="TRACE#org.apache.log4j.xml.XLevel" />
+ <param name="AcceptOnMatch" value="true" />
+ </filter>
+ </appender>
+
+ <root>
+ <level value="TRACE" class="org.apache.log4j.xml.XLevel"/>
+ <appender-ref ref="TEMP" />
+ </root>
+
+</log4j:configuration> \ No newline at end of file
diff --git a/src/test/resources/input/xml/customLevel3.xml b/src/test/resources/input/xml/customLevel3.xml
new file mode 100755
index 0000000..1ab29bf
--- /dev/null
+++ b/src/test/resources/input/xml/customLevel3.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'
+ debug="false">
+
+ <appender name="TEMP" class="org.apache.log4j.FileAppender">
+ <param name="Append" value="false" />
+ <param name="File" value="output/temp" />
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%-5p %c{2} - %m\n"/>
+ </layout>
+
+ <filter class="org.apache.log4j.varia.LevelMatchFilter">
+ <param name="LevelToMatch" value="TRACE#org.apache.log4j.xml.XLevel" />
+ <param name="AcceptOnMatch" value="true" />
+ </filter>
+
+ <filter class="org.apache.log4j.varia.DenyAllFilter"/>
+
+ </appender>
+
+ <root>
+ <level value="TRACE" class="org.apache.log4j.xml.XLevel"/>
+ <appender-ref ref="TEMP" />
+ </root>
+
+</log4j:configuration> \ No newline at end of file
diff --git a/src/test/resources/input/xml/customLevel4.xml b/src/test/resources/input/xml/customLevel4.xml
new file mode 100755
index 0000000..349d961
--- /dev/null
+++ b/src/test/resources/input/xml/customLevel4.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration debug="false"
+ xmlns:log4j='http://jakarta.apache.org/log4j/'>
+
+ <appender name="TEMP" class="org.apache.log4j.FileAppender">
+ <param name="Append" value="false" />
+ <param name="File" value="output/temp" />
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%-5p %c{2} - %m\n"/>
+ </layout>
+ </appender>
+
+ <root>
+ <level value="TRACE#org.apache.log4j.xml.XLevel"/>
+ <appender-ref ref="TEMP" />
+ </root>
+</log4j:configuration> \ No newline at end of file
diff --git a/src/test/resources/input/xml/customLogger1.xml b/src/test/resources/input/xml/customLogger1.xml
new file mode 100644
index 0000000..88b677e
--- /dev/null
+++ b/src/test/resources/input/xml/customLogger1.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'
+ debug="false">
+
+ <appender name="TEMP" class="org.apache.log4j.FileAppender">
+ <param name="Append" value="false" />
+ <param name="File" value="output/temp" />
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%-5p %c{2} - %m%n"/>
+ </layout>
+ </appender>
+
+ <root>
+ <level value ="TRACE" class="org.apache.log4j.xml.XLevel"/>
+ <appender-ref ref="TEMP" />
+ </root>
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/customLogger2.xml b/src/test/resources/input/xml/customLogger2.xml
new file mode 100644
index 0000000..60832a8
--- /dev/null
+++ b/src/test/resources/input/xml/customLogger2.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'
+ debug="false">
+
+ <appender name="TEMP" class="org.apache.log4j.FileAppender">
+ <param name="Append" value="false" />
+ <param name="File" value="output/temp" />
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%-5p %c{2} - %m%n"/>
+ </layout>
+
+ <filter class="org.apache.log4j.varia.LevelMatchFilter">
+ <param name="LevelToMatch"
+ value="TRACE#org.apache.log4j.xml.XLevel" />
+ <param name="AcceptOnMatch" value="true" />
+ </filter>
+
+ <filter class="org.apache.log4j.varia.DenyAllFilter"/>
+ </appender>
+
+ <root>
+ <level value ="TRACE" class="org.apache.log4j.xml.XLevel"/>
+ <appender-ref ref="TEMP" />
+ </root>
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/defaultInit.xml b/src/test/resources/input/xml/defaultInit.xml
new file mode 100644
index 0000000..2e54309
--- /dev/null
+++ b/src/test/resources/input/xml/defaultInit.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration debug="false" xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+ <appender name="D1" class="org.apache.log4j.ConsoleAppender">
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %c{2} - %m%n"/>
+ </layout>
+ </appender>
+
+ <root>
+ <priority value ="OFF" />
+ <appender-ref ref="D1" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/fallback1.xml b/src/test/resources/input/xml/fallback1.xml
new file mode 100644
index 0000000..4ea9764
--- /dev/null
+++ b/src/test/resources/input/xml/fallback1.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+
+ <appender name="PRIMARY" class="org.apache.log4j.FileAppender">
+ <errorHandler class="org.apache.log4j.varia.FallbackErrorHandler">
+ <root-ref/>
+ <appender-ref ref="FALLBACK" />
+ </errorHandler>
+
+ <param name="File" value="/xyz/x.log" />
+ <param name="Append" value="false" />
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %c{2} - %m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="FALLBACK" class="org.apache.log4j.FileAppender">
+ <param name="File" value="output/temp" />
+ <param name="Append" value="false" />
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="FALLBACK - %c - %m%n"/>
+ </layout>
+ </appender>
+
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="PRIMARY" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/filters.LevelMatchFilter.test4.0.xml b/src/test/resources/input/xml/filters.LevelMatchFilter.test4.0.xml
new file mode 100644
index 0000000..ad5de43
--- /dev/null
+++ b/src/test/resources/input/xml/filters.LevelMatchFilter.test4.0.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="A1" class="org.apache.log4j.FileAppender">
+ <param name="File" value="output/filters.LevelMatchFilter.test4.txt" />
+ <param name="Append" value="true" />
+
+ <layout class="org.apache.log4j.SimpleLayout"/>
+
+ <filter class="org.apache.log4j.filters.LevelMatchFilter">
+ <param name="MatchReturnValue" value="accept"/>
+ <param name="NoMatchReturnValue" value="deny"/>
+ <param name="LevelToMatch" value="debug"/>
+ </filter>
+ </appender>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="A1" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/filters.LevelMatchFilter.test4.1.xml b/src/test/resources/input/xml/filters.LevelMatchFilter.test4.1.xml
new file mode 100644
index 0000000..ab81f4e
--- /dev/null
+++ b/src/test/resources/input/xml/filters.LevelMatchFilter.test4.1.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="A1" class="org.apache.log4j.FileAppender">
+ <param name="File" value="output/filters.LevelMatchFilter.test4.txt" />
+ <param name="Append" value="true" />
+
+ <layout class="org.apache.log4j.SimpleLayout"/>
+
+ <filter class="org.apache.log4j.filters.LevelMatchFilter">
+ <param name="MatchReturnValue" value="accept"/>
+ <param name="NoMatchReturnValue" value="deny"/>
+ <param name="LevelToMatch" value="info"/>
+ </filter>
+ </appender>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="A1" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/filters.LevelMatchFilter.test4.2.xml b/src/test/resources/input/xml/filters.LevelMatchFilter.test4.2.xml
new file mode 100644
index 0000000..03d0cad
--- /dev/null
+++ b/src/test/resources/input/xml/filters.LevelMatchFilter.test4.2.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="A1" class="org.apache.log4j.FileAppender">
+ <param name="File" value="output/filters.LevelMatchFilter.test4.txt" />
+ <param name="Append" value="true" />
+
+ <layout class="org.apache.log4j.SimpleLayout"/>
+
+ <filter class="org.apache.log4j.filters.LevelMatchFilter">
+ <param name="MatchReturnValue" value="accept"/>
+ <param name="NoMatchReturnValue" value="deny"/>
+ <param name="LevelToMatch" value="warn"/>
+ </filter>
+ </appender>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="A1" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/filters.LevelMatchFilter.test4.3.xml b/src/test/resources/input/xml/filters.LevelMatchFilter.test4.3.xml
new file mode 100644
index 0000000..e474b7f
--- /dev/null
+++ b/src/test/resources/input/xml/filters.LevelMatchFilter.test4.3.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="A1" class="org.apache.log4j.FileAppender">
+ <param name="File" value="output/filters.LevelMatchFilter.test4.txt" />
+ <param name="Append" value="true" />
+
+ <layout class="org.apache.log4j.SimpleLayout"/>
+
+ <filter class="org.apache.log4j.filters.LevelMatchFilter">
+ <param name="MatchReturnValue" value="accept"/>
+ <param name="NoMatchReturnValue" value="deny"/>
+ <param name="LevelToMatch" value="error"/>
+ </filter>
+ </appender>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="A1" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/filters.LevelMatchFilter.test4.4.xml b/src/test/resources/input/xml/filters.LevelMatchFilter.test4.4.xml
new file mode 100644
index 0000000..ee1782b
--- /dev/null
+++ b/src/test/resources/input/xml/filters.LevelMatchFilter.test4.4.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="A1" class="org.apache.log4j.FileAppender">
+ <param name="File" value="output/filters.LevelMatchFilter.test4.txt" />
+ <param name="Append" value="true" />
+
+ <layout class="org.apache.log4j.SimpleLayout"/>
+
+ <filter class="org.apache.log4j.filters.LevelMatchFilter">
+ <param name="MatchReturnValue" value="accept"/>
+ <param name="NoMatchReturnValue" value="deny"/>
+ <param name="LevelToMatch" value="fatal"/>
+ </filter>
+ </appender>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="A1" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/test/resources/input/xml/log4j.dtd b/src/test/resources/input/xml/log4j.dtd
new file mode 100755
index 0000000..1aabd96
--- /dev/null
+++ b/src/test/resources/input/xml/log4j.dtd
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Authors: Chris Taylor, Ceki Gulcu. -->
+
+<!-- Version: 1.2 -->
+
+<!-- A configuration element consists of optional renderer
+elements,appender elements, categories and an optional root
+element. -->
+
+<!ELEMENT log4j:configuration (renderer*, appender*,plugin*, (category|logger)*,root?,
+ (categoryFactory|loggerFactory)?)>
+
+<!-- The "threshold" attribute takes a level value below which -->
+<!-- all logging statements are disabled. -->
+
+<!-- Setting the "debug" enable the printing of internal log4j logging -->
+<!-- statements. -->
+
+<!-- By default, debug attribute is "null", meaning that we not do touch -->
+<!-- internal log4j logging settings. The "null" value for the threshold -->
+<!-- attribute can be misleading. The threshold field of a repository -->
+<!-- cannot be set to null. The "null" value for the threshold attribute -->
+<!-- simply means don't touch the threshold field, the threshold field -->
+<!-- keeps its old value. -->
+
+<!ATTLIST log4j:configuration
+ xmlns:log4j CDATA #FIXED "http://jakarta.apache.org/log4j/"
+ threshold (all|trace|debug|info|warn|error|fatal|off|null) "null"
+ debug (true|false|null) "null"
+ reset (true|false) "false"
+>
+
+<!-- renderer elements allow the user to customize the conversion of -->
+<!-- message objects to String. -->
+
+<!ELEMENT renderer EMPTY>
+<!ATTLIST renderer
+ renderedClass CDATA #REQUIRED
+ renderingClass CDATA #REQUIRED
+>
+
+<!-- Appenders must have a name and a class. -->
+<!-- Appenders may contain an error handler, a layout, optional parameters -->
+<!-- and filters. They may also reference (or include) other appenders. -->
+<!ELEMENT appender (errorHandler?, param*,
+ rollingPolicy?, triggeringPolicy?, connectionSource?,
+ layout?, filter*, appender-ref*)>
+<!ATTLIST appender
+ name CDATA #REQUIRED
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT layout (param*)>
+<!ATTLIST layout
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT filter (param*)>
+<!ATTLIST filter
+ class CDATA #REQUIRED
+>
+
+<!-- ErrorHandlers can be of any class. They can admit any number of -->
+<!-- parameters. -->
+
+<!ELEMENT errorHandler (param*, root-ref?, logger-ref*, appender-ref?)>
+<!ATTLIST errorHandler
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT root-ref EMPTY>
+
+<!ELEMENT logger-ref EMPTY>
+<!ATTLIST logger-ref
+ ref CDATA #REQUIRED
+>
+
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+ name CDATA #REQUIRED
+ value CDATA #REQUIRED
+>
+
+
+<!-- The priority class is org.apache.log4j.Level by default -->
+<!ELEMENT priority (param*)>
+<!ATTLIST priority
+ class CDATA #IMPLIED
+ value CDATA #REQUIRED
+>
+
+<!-- The level class is org.apache.log4j.Level by default -->
+<!ELEMENT level (param*)>
+<!ATTLIST level
+ class CDATA #IMPLIED
+ value CDATA #REQUIRED
+>
+
+
+<!-- If no level element is specified, then the configurator MUST not -->
+<!-- touch the level of the named category. -->
+<!ELEMENT category (param*,(priority|level)?,appender-ref*)>
+<!ATTLIST category
+ class CDATA #IMPLIED
+ name CDATA #REQUIRED
+ additivity (true|false) "true"
+>
+
+<!-- If no level element is specified, then the configurator MUST not -->
+<!-- touch the level of the named logger. -->
+<!ELEMENT logger (level?,appender-ref*)>
+<!ATTLIST logger
+ name CDATA #REQUIRED
+ additivity (true|false) "true"
+>
+
+
+<!ELEMENT categoryFactory (param*)>
+<!ATTLIST categoryFactory
+ class CDATA #REQUIRED>
+
+<!ELEMENT loggerFactory (param*)>
+<!ATTLIST loggerFactory
+ class CDATA #REQUIRED>
+
+<!ELEMENT appender-ref EMPTY>
+<!ATTLIST appender-ref
+ ref CDATA #REQUIRED
+>
+
+<!-- plugins must have a name and class and can have optional parameters -->
+<!ELEMENT plugin (param*, connectionSource?)>
+<!ATTLIST plugin
+ name CDATA #REQUIRED
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT connectionSource (dataSource?, param*)>
+<!ATTLIST connectionSource
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT dataSource (param*)>
+<!ATTLIST dataSource
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT triggeringPolicy ((param|filter)*)>
+<!ATTLIST triggeringPolicy
+ name CDATA #IMPLIED
+ class CDATA #REQUIRED
+>
+
+<!ELEMENT rollingPolicy (param*)>
+<!ATTLIST rollingPolicy
+ name CDATA #IMPLIED
+ class CDATA #REQUIRED
+>
+
+
+<!-- If no priority element is specified, then the configurator MUST not -->
+<!-- touch the priority of root. -->
+<!-- The root category always exists and cannot be subclassed. -->
+<!ELEMENT root (param*, (priority|level)?, appender-ref*)>
+
+
+<!-- ==================================================================== -->
+<!-- A logging event -->
+<!-- ==================================================================== -->
+<!ELEMENT log4j:eventSet (log4j:event*)>
+<!ATTLIST log4j:eventSet
+ xmlns:log4j CDATA #FIXED "http://jakarta.apache.org/log4j/"
+ version (1.1|1.2) "1.2"
+ includesLocationInfo (true|false) "true"
+>
+
+
+
+<!ELEMENT log4j:event (log4j:message, log4j:NDC?, log4j:throwable?,
+ log4j:locationInfo?, log4j:properties?) >
+
+<!-- The timestamp format is application dependent. -->
+<!ATTLIST log4j:event
+ logger CDATA #REQUIRED
+ level CDATA #REQUIRED
+ thread CDATA #REQUIRED
+ timestamp CDATA #REQUIRED
+ time CDATA #IMPLIED
+>
+
+<!ELEMENT log4j:message (#PCDATA)>
+<!ELEMENT log4j:NDC (#PCDATA)>
+
+<!ELEMENT log4j:throwable (#PCDATA)>
+
+<!ELEMENT log4j:locationInfo EMPTY>
+<!ATTLIST log4j:locationInfo
+ class CDATA #REQUIRED
+ method CDATA #REQUIRED
+ file CDATA #REQUIRED
+ line CDATA #REQUIRED
+>
+
+<!ELEMENT log4j:properties (log4j:data*)>
+
+<!ELEMENT log4j:data EMPTY>
+<!ATTLIST log4j:data
+ name CDATA #REQUIRED
+ value CDATA #REQUIRED
+>
diff --git a/src/test/resources/input/xml/smtpAppender1.xml b/src/test/resources/input/xml/smtpAppender1.xml
new file mode 100644
index 0000000..c1aebdf
--- /dev/null
+++ b/src/test/resources/input/xml/smtpAppender1.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="A1" class="org.apache.log4j.net.SMTPAppender">
+
+ <param name="from" value="log4j@example.org" />
+ <param name="to" value="somebody@example.org" />
+ <param name="subject" value="Test message" />
+ <param name="SMTPHost" value="localhost"/>
+ <triggeringPolicy class="org.apache.log4j.net.SMTPAppenderTest$MockTriggeringEventEvaluator"/>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %c{2} - %m%n"/>
+ </layout>
+ </appender>
+
+ <root>
+ <priority value ="trace" />
+ <appender-ref ref="A1" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/test/resources/witness/LevelMatchFilter_accept b/src/test/resources/witness/LevelMatchFilter_accept
new file mode 100644
index 0000000..a6a4d48
--- /dev/null
+++ b/src/test/resources/witness/LevelMatchFilter_accept
@@ -0,0 +1,5 @@
+DEBUG - pass 0; filter set to accept only DEBUG msgs
+INFO - pass 1; filter set to accept only INFO msgs
+WARN - pass 2; filter set to accept only WARN msgs
+ERROR - pass 3; filter set to accept only ERROR msgs
+FATAL - pass 4; filter set to accept only FATAL msgs
diff --git a/src/test/resources/witness/LevelMatchFilter_deny b/src/test/resources/witness/LevelMatchFilter_deny
new file mode 100644
index 0000000..5273424
--- /dev/null
+++ b/src/test/resources/witness/LevelMatchFilter_deny
@@ -0,0 +1,20 @@
+INFO - pass 0; filter set to deny only DEBUG msgs
+WARN - pass 0; filter set to deny only DEBUG msgs
+ERROR - pass 0; filter set to deny only DEBUG msgs
+FATAL - pass 0; filter set to deny only DEBUG msgs
+DEBUG - pass 1; filter set to deny only INFO msgs
+WARN - pass 1; filter set to deny only INFO msgs
+ERROR - pass 1; filter set to deny only INFO msgs
+FATAL - pass 1; filter set to deny only INFO msgs
+DEBUG - pass 2; filter set to deny only WARN msgs
+INFO - pass 2; filter set to deny only WARN msgs
+ERROR - pass 2; filter set to deny only WARN msgs
+FATAL - pass 2; filter set to deny only WARN msgs
+DEBUG - pass 3; filter set to deny only ERROR msgs
+INFO - pass 3; filter set to deny only ERROR msgs
+WARN - pass 3; filter set to deny only ERROR msgs
+FATAL - pass 3; filter set to deny only ERROR msgs
+DEBUG - pass 4; filter set to deny only FATAL msgs
+INFO - pass 4; filter set to deny only FATAL msgs
+WARN - pass 4; filter set to deny only FATAL msgs
+ERROR - pass 4; filter set to deny only FATAL msgs
diff --git a/src/test/resources/witness/LevelRangeFilter_accept b/src/test/resources/witness/LevelRangeFilter_accept
new file mode 100644
index 0000000..eff4c7e
--- /dev/null
+++ b/src/test/resources/witness/LevelRangeFilter_accept
@@ -0,0 +1,46 @@
+DEBUG - pass 0; no min or max set
+INFO - pass 0; no min or max set
+WARN - pass 0; no min or max set
+ERROR - pass 0; no min or max set
+FATAL - pass 0; no min or max set
+WARN - pass 1; min set to WARN, max not set
+ERROR - pass 1; min set to WARN, max not set
+FATAL - pass 1; min set to WARN, max not set
+DEBUG - pass 2; min not set, max set to WARN
+INFO - pass 2; min not set, max set to WARN
+WARN - pass 2; min not set, max set to WARN
+DEBUG - pass 3; filter set to accept between DEBUG and FATAL msgs
+INFO - pass 3; filter set to accept between DEBUG and FATAL msgs
+WARN - pass 3; filter set to accept between DEBUG and FATAL msgs
+ERROR - pass 3; filter set to accept between DEBUG and FATAL msgs
+FATAL - pass 3; filter set to accept between DEBUG and FATAL msgs
+DEBUG - pass 4; filter set to accept between DEBUG and ERROR msgs
+INFO - pass 4; filter set to accept between DEBUG and ERROR msgs
+WARN - pass 4; filter set to accept between DEBUG and ERROR msgs
+ERROR - pass 4; filter set to accept between DEBUG and ERROR msgs
+DEBUG - pass 5; filter set to accept between DEBUG and WARN msgs
+INFO - pass 5; filter set to accept between DEBUG and WARN msgs
+WARN - pass 5; filter set to accept between DEBUG and WARN msgs
+DEBUG - pass 6; filter set to accept between DEBUG and INFO msgs
+INFO - pass 6; filter set to accept between DEBUG and INFO msgs
+DEBUG - pass 7; filter set to accept between DEBUG and DEBUG msgs
+INFO - pass 8; filter set to accept between INFO and FATAL msgs
+WARN - pass 8; filter set to accept between INFO and FATAL msgs
+ERROR - pass 8; filter set to accept between INFO and FATAL msgs
+FATAL - pass 8; filter set to accept between INFO and FATAL msgs
+INFO - pass 9; filter set to accept between INFO and ERROR msgs
+WARN - pass 9; filter set to accept between INFO and ERROR msgs
+ERROR - pass 9; filter set to accept between INFO and ERROR msgs
+INFO - pass 10; filter set to accept between INFO and WARN msgs
+WARN - pass 10; filter set to accept between INFO and WARN msgs
+INFO - pass 11; filter set to accept between INFO and INFO msgs
+WARN - pass 13; filter set to accept between WARN and FATAL msgs
+ERROR - pass 13; filter set to accept between WARN and FATAL msgs
+FATAL - pass 13; filter set to accept between WARN and FATAL msgs
+WARN - pass 14; filter set to accept between WARN and ERROR msgs
+ERROR - pass 14; filter set to accept between WARN and ERROR msgs
+WARN - pass 15; filter set to accept between WARN and WARN msgs
+ERROR - pass 18; filter set to accept between ERROR and FATAL msgs
+FATAL - pass 18; filter set to accept between ERROR and FATAL msgs
+ERROR - pass 19; filter set to accept between ERROR and ERROR msgs
+FATAL - pass 23; filter set to accept between FATAL and FATAL msgs
diff --git a/src/test/resources/witness/LevelRangeFilter_neutral b/src/test/resources/witness/LevelRangeFilter_neutral
new file mode 100644
index 0000000..eff4c7e
--- /dev/null
+++ b/src/test/resources/witness/LevelRangeFilter_neutral
@@ -0,0 +1,46 @@
+DEBUG - pass 0; no min or max set
+INFO - pass 0; no min or max set
+WARN - pass 0; no min or max set
+ERROR - pass 0; no min or max set
+FATAL - pass 0; no min or max set
+WARN - pass 1; min set to WARN, max not set
+ERROR - pass 1; min set to WARN, max not set
+FATAL - pass 1; min set to WARN, max not set
+DEBUG - pass 2; min not set, max set to WARN
+INFO - pass 2; min not set, max set to WARN
+WARN - pass 2; min not set, max set to WARN
+DEBUG - pass 3; filter set to accept between DEBUG and FATAL msgs
+INFO - pass 3; filter set to accept between DEBUG and FATAL msgs
+WARN - pass 3; filter set to accept between DEBUG and FATAL msgs
+ERROR - pass 3; filter set to accept between DEBUG and FATAL msgs
+FATAL - pass 3; filter set to accept between DEBUG and FATAL msgs
+DEBUG - pass 4; filter set to accept between DEBUG and ERROR msgs
+INFO - pass 4; filter set to accept between DEBUG and ERROR msgs
+WARN - pass 4; filter set to accept between DEBUG and ERROR msgs
+ERROR - pass 4; filter set to accept between DEBUG and ERROR msgs
+DEBUG - pass 5; filter set to accept between DEBUG and WARN msgs
+INFO - pass 5; filter set to accept between DEBUG and WARN msgs
+WARN - pass 5; filter set to accept between DEBUG and WARN msgs
+DEBUG - pass 6; filter set to accept between DEBUG and INFO msgs
+INFO - pass 6; filter set to accept between DEBUG and INFO msgs
+DEBUG - pass 7; filter set to accept between DEBUG and DEBUG msgs
+INFO - pass 8; filter set to accept between INFO and FATAL msgs
+WARN - pass 8; filter set to accept between INFO and FATAL msgs
+ERROR - pass 8; filter set to accept between INFO and FATAL msgs
+FATAL - pass 8; filter set to accept between INFO and FATAL msgs
+INFO - pass 9; filter set to accept between INFO and ERROR msgs
+WARN - pass 9; filter set to accept between INFO and ERROR msgs
+ERROR - pass 9; filter set to accept between INFO and ERROR msgs
+INFO - pass 10; filter set to accept between INFO and WARN msgs
+WARN - pass 10; filter set to accept between INFO and WARN msgs
+INFO - pass 11; filter set to accept between INFO and INFO msgs
+WARN - pass 13; filter set to accept between WARN and FATAL msgs
+ERROR - pass 13; filter set to accept between WARN and FATAL msgs
+FATAL - pass 13; filter set to accept between WARN and FATAL msgs
+WARN - pass 14; filter set to accept between WARN and ERROR msgs
+ERROR - pass 14; filter set to accept between WARN and ERROR msgs
+WARN - pass 15; filter set to accept between WARN and WARN msgs
+ERROR - pass 18; filter set to accept between ERROR and FATAL msgs
+FATAL - pass 18; filter set to accept between ERROR and FATAL msgs
+ERROR - pass 19; filter set to accept between ERROR and ERROR msgs
+FATAL - pass 23; filter set to accept between FATAL and FATAL msgs
diff --git a/src/test/resources/witness/Makefile.am b/src/test/resources/witness/Makefile.am
new file mode 100644
index 0000000..9464d5b
--- /dev/null
+++ b/src/test/resources/witness/Makefile.am
@@ -0,0 +1,38 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+SUBDIRS = encoding ndc rolling
+EXTRA_DIST = LevelMatchFilter* \
+ LevelRangeFilter* \
+ NDCMatchFilter* \
+ custom* \
+ dom.* \
+ hierarchyThreshold.* \
+ l7d.* \
+ patternLayout.* \
+ socketServer.* \
+ xmlLayout.* \
+ fallback \
+ simple \
+ ttcc
+
+# if we are building in a separate build tree, then copy all necessary files
+all-local:
+ @if test "$(top_srcdir)" != "$(top_builddir)"; then \
+ echo "Copying test suite data files ..." ; \
+ list='$(EXTRA_DIST)'; for file in $$list; do \
+ cp -p $(srcdir)/$$file . ; \
+ done \
+ fi
diff --git a/src/test/resources/witness/NDCMatchFilter_accept b/src/test/resources/witness/NDCMatchFilter_accept
new file mode 100644
index 0000000..4bac420
--- /dev/null
+++ b/src/test/resources/witness/NDCMatchFilter_accept
@@ -0,0 +1,11 @@
+pass 0: "level_1" exactly matches "level_1"
+pass 1: "level_1 level_2" exactly matches "level_1 level_2"
+pass 2: "level_1 level_2 level_3" exactly matches "level_1 level_2 level_3"
+pass 3: "level_1" contained in "level_1 level_2 level_3"
+pass 3: "level_1" contained in "level_1 level_2"
+pass 3: "level_1" contained in "level_1"
+pass 4: "level_1 level_2" contained in "level_1 level_2 level_3"
+pass 4: "level_1 level_2" contained in "level_1 level_2"
+pass 5: "level_1 level_2 level_3" contained in "level_1 level_2 level_3"
+pass 6: "" exactly matches ""
+pass 7: "" contained in ""
diff --git a/src/test/resources/witness/NDCMatchFilter_deny b/src/test/resources/witness/NDCMatchFilter_deny
new file mode 100644
index 0000000..055f2b6
--- /dev/null
+++ b/src/test/resources/witness/NDCMatchFilter_deny
@@ -0,0 +1,21 @@
+pass 0: "level_1" does not exactly match "level_1 level_2 level_3"
+pass 0: "level_1" does not exactly match "level_1 level_2"
+pass 0: "level_1" does not exactly match ""
+pass 1: "level_1 level_2" does not exactly match "level_1 level_2 level_3"
+pass 1: "level_1 level_2" does not exactly match "level_1"
+pass 1: "level_1 level_2" does not exactly match ""
+pass 2: "level_1 level_2 level_3" does not exactly match "level_1 level_2"
+pass 2: "level_1 level_2 level_3" does not exactly match "level_1"
+pass 2: "level_1 level_2 level_3" does not exactly match ""
+pass 3: "level_1" not contained in ""
+pass 4: "level_1 level_2" not contained in "level_1"
+pass 4: "level_1 level_2" not contained in ""
+pass 5: "level_1 level_2 level_3" not contained in "level_1 level_2"
+pass 5: "level_1 level_2 level_3" not contained in "level_1"
+pass 5: "level_1 level_2 level_3" not contained in ""
+pass 6: "" does not exactly match "level_1 level_2 level_3"
+pass 6: "" does not exactly match "level_1 level_2"
+pass 6: "" does not exactly match "level_1"
+pass 7: "" not contained in "level_1 level_2 level_3"
+pass 7: "" not contained in "level_1 level_2"
+pass 7: "" not contained in "level_1"
diff --git a/src/test/resources/witness/customLevel.1 b/src/test/resources/witness/customLevel.1
new file mode 100755
index 0000000..fc957b2
--- /dev/null
+++ b/src/test/resources/witness/customLevel.1
@@ -0,0 +1,5 @@
+DEBUG xml.CustomLevelTestCase - Message 1
+INFO xml.CustomLevelTestCase - Message 2
+WARN xml.CustomLevelTestCase - Message 3
+ERROR xml.CustomLevelTestCase - Message 4
+TRACE xml.CustomLevelTestCase - Message 5
diff --git a/src/test/resources/witness/customLevel.2 b/src/test/resources/witness/customLevel.2
new file mode 100755
index 0000000..fc957b2
--- /dev/null
+++ b/src/test/resources/witness/customLevel.2
@@ -0,0 +1,5 @@
+DEBUG xml.CustomLevelTestCase - Message 1
+INFO xml.CustomLevelTestCase - Message 2
+WARN xml.CustomLevelTestCase - Message 3
+ERROR xml.CustomLevelTestCase - Message 4
+TRACE xml.CustomLevelTestCase - Message 5
diff --git a/src/test/resources/witness/customLevel.3 b/src/test/resources/witness/customLevel.3
new file mode 100755
index 0000000..00a2986
--- /dev/null
+++ b/src/test/resources/witness/customLevel.3
@@ -0,0 +1 @@
+TRACE xml.CustomLevelTestCase - Message 5
diff --git a/src/test/resources/witness/customLevel.4 b/src/test/resources/witness/customLevel.4
new file mode 100755
index 0000000..fc957b2
--- /dev/null
+++ b/src/test/resources/witness/customLevel.4
@@ -0,0 +1,5 @@
+DEBUG xml.CustomLevelTestCase - Message 1
+INFO xml.CustomLevelTestCase - Message 2
+WARN xml.CustomLevelTestCase - Message 3
+ERROR xml.CustomLevelTestCase - Message 4
+TRACE xml.CustomLevelTestCase - Message 5
diff --git a/src/test/resources/witness/customLogger.1 b/src/test/resources/witness/customLogger.1
new file mode 100644
index 0000000..fad914a
--- /dev/null
+++ b/src/test/resources/witness/customLogger.1
@@ -0,0 +1,6 @@
+TRACE customLogger.XLoggerTestCase - Message 0
+DEBUG customLogger.XLoggerTestCase - Message 1
+WARN customLogger.XLoggerTestCase - Message 2
+ERROR customLogger.XLoggerTestCase - Message 3
+FATAL customLogger.XLoggerTestCase - Message 4
+DEBUG customLogger.XLoggerTestCase - Message 5
diff --git a/src/test/resources/witness/customLogger.2 b/src/test/resources/witness/customLogger.2
new file mode 100644
index 0000000..5990833
--- /dev/null
+++ b/src/test/resources/witness/customLogger.2
@@ -0,0 +1 @@
+TRACE customLogger.XLoggerTestCase - Message 0
diff --git a/src/test/resources/witness/dom.A1.1 b/src/test/resources/witness/dom.A1.1
new file mode 100755
index 0000000..5e0a3bb
--- /dev/null
+++ b/src/test/resources/witness/dom.A1.1
@@ -0,0 +1,15 @@
+DEBUG xml.DOMTestCase - Message 0
+DEBUG xml.DOMTestCase - Message 0
+DEBUG root - Message 0
+INFO xml.DOMTestCase - Message 1
+INFO xml.DOMTestCase - Message 1
+INFO root - Message 1
+WARN xml.DOMTestCase - Message 2
+WARN xml.DOMTestCase - Message 2
+WARN root - Message 2
+ERROR xml.DOMTestCase - Message 3
+ERROR xml.DOMTestCase - Message 3
+ERROR root - Message 3
+FATAL xml.DOMTestCase - Message 4
+FATAL xml.DOMTestCase - Message 4
+FATAL root - Message 4
diff --git a/src/test/resources/witness/dom.A1.2 b/src/test/resources/witness/dom.A1.2
new file mode 100755
index 0000000..5e0a3bb
--- /dev/null
+++ b/src/test/resources/witness/dom.A1.2
@@ -0,0 +1,15 @@
+DEBUG xml.DOMTestCase - Message 0
+DEBUG xml.DOMTestCase - Message 0
+DEBUG root - Message 0
+INFO xml.DOMTestCase - Message 1
+INFO xml.DOMTestCase - Message 1
+INFO root - Message 1
+WARN xml.DOMTestCase - Message 2
+WARN xml.DOMTestCase - Message 2
+WARN root - Message 2
+ERROR xml.DOMTestCase - Message 3
+ERROR xml.DOMTestCase - Message 3
+ERROR root - Message 3
+FATAL xml.DOMTestCase - Message 4
+FATAL xml.DOMTestCase - Message 4
+FATAL root - Message 4
diff --git a/src/test/resources/witness/dom.A2.1 b/src/test/resources/witness/dom.A2.1
new file mode 100755
index 0000000..c0a4948
--- /dev/null
+++ b/src/test/resources/witness/dom.A2.1
@@ -0,0 +1,10 @@
+ [main] DEBUG org.apache.log4j.xml.DOMTestCase - Message 0
+ [main] DEBUG root - Message 0
+ [main] INFO org.apache.log4j.xml.DOMTestCase - Message 1
+ [main] INFO root - Message 1
+ [main] WARN org.apache.log4j.xml.DOMTestCase - Message 2
+ [main] WARN root - Message 2
+ [main] ERROR org.apache.log4j.xml.DOMTestCase - Message 3
+ [main] ERROR root - Message 3
+ [main] FATAL org.apache.log4j.xml.DOMTestCase - Message 4
+ [main] FATAL root - Message 4
diff --git a/src/test/resources/witness/dom.A2.2 b/src/test/resources/witness/dom.A2.2
new file mode 100755
index 0000000..c0a4948
--- /dev/null
+++ b/src/test/resources/witness/dom.A2.2
@@ -0,0 +1,10 @@
+ [main] DEBUG org.apache.log4j.xml.DOMTestCase - Message 0
+ [main] DEBUG root - Message 0
+ [main] INFO org.apache.log4j.xml.DOMTestCase - Message 1
+ [main] INFO root - Message 1
+ [main] WARN org.apache.log4j.xml.DOMTestCase - Message 2
+ [main] WARN root - Message 2
+ [main] ERROR org.apache.log4j.xml.DOMTestCase - Message 3
+ [main] ERROR root - Message 3
+ [main] FATAL org.apache.log4j.xml.DOMTestCase - Message 4
+ [main] FATAL root - Message 4
diff --git a/src/test/resources/witness/encoding/Makefile.am b/src/test/resources/witness/encoding/Makefile.am
new file mode 100644
index 0000000..ed1594a
--- /dev/null
+++ b/src/test/resources/witness/encoding/Makefile.am
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+EXTRA_DIST = UTF-* \
+ ascii.log \
+ latin1.log
+
+# if we are building in a separate build tree, then copy all necessary files
+all-local:
+ @if test "$(top_srcdir)" != "$(top_builddir)"; then \
+ echo "Copying test suite data files ..." ; \
+ list='$(EXTRA_DIST)'; for file in $$list; do \
+ cp -p $(srcdir)/$$file . ; \
+ done \
+ fi
diff --git a/src/test/resources/witness/encoding/UTF-16.log b/src/test/resources/witness/encoding/UTF-16.log
new file mode 100644
index 0000000..42469f8
--- /dev/null
+++ b/src/test/resources/witness/encoding/UTF-16.log
Binary files differ
diff --git a/src/test/resources/witness/encoding/UTF-16BE.log b/src/test/resources/witness/encoding/UTF-16BE.log
new file mode 100644
index 0000000..ee13f10
--- /dev/null
+++ b/src/test/resources/witness/encoding/UTF-16BE.log
Binary files differ
diff --git a/src/test/resources/witness/encoding/UTF-16LE.log b/src/test/resources/witness/encoding/UTF-16LE.log
new file mode 100644
index 0000000..c6bdafc
--- /dev/null
+++ b/src/test/resources/witness/encoding/UTF-16LE.log
Binary files differ
diff --git a/src/test/resources/witness/encoding/UTF-8.log b/src/test/resources/witness/encoding/UTF-8.log
new file mode 100644
index 0000000..acb4697
--- /dev/null
+++ b/src/test/resources/witness/encoding/UTF-8.log
@@ -0,0 +1,3 @@
+INFO - Hello, World
+INFO - ¹
+INFO - A؅԰আ七Ѐ
diff --git a/src/test/resources/witness/encoding/ascii.log b/src/test/resources/witness/encoding/ascii.log
new file mode 100644
index 0000000..ef76502
--- /dev/null
+++ b/src/test/resources/witness/encoding/ascii.log
@@ -0,0 +1,3 @@
+INFO - Hello, World
+INFO - ?
+INFO - A?????
diff --git a/src/test/resources/witness/encoding/latin1.log b/src/test/resources/witness/encoding/latin1.log
new file mode 100644
index 0000000..7bd0098
--- /dev/null
+++ b/src/test/resources/witness/encoding/latin1.log
@@ -0,0 +1,3 @@
+INFO - Hello, World
+INFO - ¹
+INFO - A?????
diff --git a/src/test/resources/witness/fallback b/src/test/resources/witness/fallback
new file mode 100644
index 0000000..818931c
--- /dev/null
+++ b/src/test/resources/witness/fallback
@@ -0,0 +1,10 @@
+FALLBACK - test - Message 0
+FALLBACK - root - Message 0
+FALLBACK - test - Message 1
+FALLBACK - root - Message 1
+FALLBACK - test - Message 2
+FALLBACK - root - Message 2
+FALLBACK - test - Message 3
+FALLBACK - root - Message 3
+FALLBACK - test - Message 4
+FALLBACK - root - Message 4
diff --git a/src/test/resources/witness/hierarchyThreshold.1 b/src/test/resources/witness/hierarchyThreshold.1
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/resources/witness/hierarchyThreshold.1
diff --git a/src/test/resources/witness/hierarchyThreshold.2 b/src/test/resources/witness/hierarchyThreshold.2
new file mode 100644
index 0000000..875cc06
--- /dev/null
+++ b/src/test/resources/witness/hierarchyThreshold.2
@@ -0,0 +1 @@
+FATAL HierarchyThresholdTestCase = m5
diff --git a/src/test/resources/witness/hierarchyThreshold.3 b/src/test/resources/witness/hierarchyThreshold.3
new file mode 100644
index 0000000..8c3983e
--- /dev/null
+++ b/src/test/resources/witness/hierarchyThreshold.3
@@ -0,0 +1,2 @@
+ERROR HierarchyThresholdTestCase = m4
+FATAL HierarchyThresholdTestCase = m5
diff --git a/src/test/resources/witness/hierarchyThreshold.4 b/src/test/resources/witness/hierarchyThreshold.4
new file mode 100644
index 0000000..784dca0
--- /dev/null
+++ b/src/test/resources/witness/hierarchyThreshold.4
@@ -0,0 +1,3 @@
+WARN HierarchyThresholdTestCase = m3
+ERROR HierarchyThresholdTestCase = m4
+FATAL HierarchyThresholdTestCase = m5
diff --git a/src/test/resources/witness/hierarchyThreshold.5 b/src/test/resources/witness/hierarchyThreshold.5
new file mode 100644
index 0000000..2b27a11
--- /dev/null
+++ b/src/test/resources/witness/hierarchyThreshold.5
@@ -0,0 +1,4 @@
+INFO HierarchyThresholdTestCase = m2
+WARN HierarchyThresholdTestCase = m3
+ERROR HierarchyThresholdTestCase = m4
+FATAL HierarchyThresholdTestCase = m5
diff --git a/src/test/resources/witness/hierarchyThreshold.6 b/src/test/resources/witness/hierarchyThreshold.6
new file mode 100644
index 0000000..8d33592
--- /dev/null
+++ b/src/test/resources/witness/hierarchyThreshold.6
@@ -0,0 +1,5 @@
+DEBUG HierarchyThresholdTestCase = m1
+INFO HierarchyThresholdTestCase = m2
+WARN HierarchyThresholdTestCase = m3
+ERROR HierarchyThresholdTestCase = m4
+FATAL HierarchyThresholdTestCase = m5
diff --git a/src/test/resources/witness/hierarchyThreshold.7 b/src/test/resources/witness/hierarchyThreshold.7
new file mode 100644
index 0000000..05ac33c
--- /dev/null
+++ b/src/test/resources/witness/hierarchyThreshold.7
@@ -0,0 +1,6 @@
+TRACE HierarchyThresholdTestCase = m0
+DEBUG HierarchyThresholdTestCase = m1
+INFO HierarchyThresholdTestCase = m2
+WARN HierarchyThresholdTestCase = m3
+ERROR HierarchyThresholdTestCase = m4
+FATAL HierarchyThresholdTestCase = m5
diff --git a/src/test/resources/witness/hierarchyThreshold.8 b/src/test/resources/witness/hierarchyThreshold.8
new file mode 100644
index 0000000..05ac33c
--- /dev/null
+++ b/src/test/resources/witness/hierarchyThreshold.8
@@ -0,0 +1,6 @@
+TRACE HierarchyThresholdTestCase = m0
+DEBUG HierarchyThresholdTestCase = m1
+INFO HierarchyThresholdTestCase = m2
+WARN HierarchyThresholdTestCase = m3
+ERROR HierarchyThresholdTestCase = m4
+FATAL HierarchyThresholdTestCase = m5
diff --git a/src/test/resources/witness/l7d.1 b/src/test/resources/witness/l7d.1
new file mode 100644
index 0000000..0bc132b
--- /dev/null
+++ b/src/test/resources/witness/l7d.1
@@ -0,0 +1,21 @@
+T1 INFO - This is the English, US test.
+T1 WARN - Hello world.
+T1 ERROR - No resource is associated with key "bogusMsg".
+T1 ERROR - bogusMsg
+T1 ERROR - This is test number 1 with string argument log4j.
+T1 ERROR - No resource is associated with key "bogus2".
+T1 INFO - bogus2
+T1 INFO - Ceci est le test en francais pour la France.
+T1 WARN - Bonjour la France.
+T1 ERROR - No resource is associated with key "bogusMsg".
+T1 ERROR - bogusMsg
+T1 ERROR - Ceci est le test numero 2 contenant l'argument log4j.
+T1 ERROR - No resource is associated with key "bogus2".
+T1 INFO - bogus2
+T1 INFO - Ceci est le test en francais pour la p'tite Suisse.
+T1 WARN - Bonjour la France.
+T1 ERROR - No resource is associated with key "bogusMsg".
+T1 ERROR - bogusMsg
+T1 ERROR - Ceci est le test numero 3 contenant l'argument log4j.
+T1 ERROR - No resource is associated with key "bogus2".
+T1 INFO - bogus2
diff --git a/src/test/resources/witness/ndc/Makefile.am b/src/test/resources/witness/ndc/Makefile.am
new file mode 100644
index 0000000..8129cc1
--- /dev/null
+++ b/src/test/resources/witness/ndc/Makefile.am
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+EXTRA_DIST = NDC.*
+
+# if we are building in a separate build tree, then copy all necessary files
+all-local:
+ @if test "$(top_srcdir)" != "$(top_builddir)"; then \
+ echo "Copying test suite data files ..." ; \
+ list='$(EXTRA_DIST)'; for file in $$list; do \
+ cp -p $(srcdir)/$$file . ; \
+ done \
+ fi
diff --git a/src/test/resources/witness/ndc/NDC.1 b/src/test/resources/witness/ndc/NDC.1
new file mode 100755
index 0000000..239b8d0
--- /dev/null
+++ b/src/test/resources/witness/ndc/NDC.1
@@ -0,0 +1,25 @@
+DEBUG null - m1
+INFO null - m2
+WARN null - m3
+ERROR null - m4
+FATAL null - m5
+DEBUG n1 - m1
+INFO n1 - m2
+WARN n1 - m3
+ERROR n1 - m4
+FATAL n1 - m5
+DEBUG n1 n2 n3 - m1
+INFO n1 n2 n3 - m2
+WARN n1 n2 n3 - m3
+ERROR n1 n2 n3 - m4
+FATAL n1 n2 n3 - m5
+DEBUG n1 n2 - m1
+INFO n1 n2 - m2
+WARN n1 n2 - m3
+ERROR n1 n2 - m4
+FATAL n1 n2 - m5
+DEBUG null - m1
+INFO null - m2
+WARN null - m3
+ERROR null - m4
+FATAL null - m5
diff --git a/src/test/resources/witness/patternLayout.1 b/src/test/resources/witness/patternLayout.1
new file mode 100644
index 0000000..1399721
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.1
@@ -0,0 +1,10 @@
+DEBUG - Message 0
+DEBUG - Message 0
+INFO - Message 1
+INFO - Message 1
+WARN - Message 2
+WARN - Message 2
+ERROR - Message 3
+ERROR - Message 3
+FATAL - Message 4
+FATAL - Message 4
diff --git a/src/test/resources/witness/patternLayout.10 b/src/test/resources/witness/patternLayout.10
new file mode 100644
index 0000000..e0524ef
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.10
@@ -0,0 +1,10 @@
+[main] DEBUG patternlayouttest.cpp(X): Message 0
+[main] DEBUG patternlayouttest.cpp(X): Message 0
+[main] INFO patternlayouttest.cpp(X): Message 1
+[main] INFO patternlayouttest.cpp(X): Message 1
+[main] WARN patternlayouttest.cpp(X): Message 2
+[main] WARN patternlayouttest.cpp(X): Message 2
+[main] ERROR patternlayouttest.cpp(X): Message 3
+[main] ERROR patternlayouttest.cpp(X): Message 3
+[main] FATAL patternlayouttest.cpp(X): Message 4
+[main] FATAL patternlayouttest.cpp(X): Message 4 \ No newline at end of file
diff --git a/src/test/resources/witness/patternLayout.11 b/src/test/resources/witness/patternLayout.11
new file mode 100644
index 0000000..9ac72a3
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.11
@@ -0,0 +1,10 @@
+DEBUG [main] log4j.PatternLayoutTest: Message 0
+DEBUG [main] root: Message 0
+INFO [main] log4j.PatternLayoutTest: Message 1
+INFO [main] root: Message 1
+WARN [main] log4j.PatternLayoutTest: Message 2
+WARN [main] root: Message 2
+ERROR [main] log4j.PatternLayoutTest: Message 3
+ERROR [main] root: Message 3
+FATAL [main] log4j.PatternLayoutTest: Message 4
+FATAL [main] root: Message 4 \ No newline at end of file
diff --git a/src/test/resources/witness/patternLayout.12 b/src/test/resources/witness/patternLayout.12
new file mode 100644
index 0000000..e0524ef
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.12
@@ -0,0 +1,10 @@
+[main] DEBUG patternlayouttest.cpp(X): Message 0
+[main] DEBUG patternlayouttest.cpp(X): Message 0
+[main] INFO patternlayouttest.cpp(X): Message 1
+[main] INFO patternlayouttest.cpp(X): Message 1
+[main] WARN patternlayouttest.cpp(X): Message 2
+[main] WARN patternlayouttest.cpp(X): Message 2
+[main] ERROR patternlayouttest.cpp(X): Message 3
+[main] ERROR patternlayouttest.cpp(X): Message 3
+[main] FATAL patternlayouttest.cpp(X): Message 4
+[main] FATAL patternlayouttest.cpp(X): Message 4 \ No newline at end of file
diff --git a/src/test/resources/witness/patternLayout.2 b/src/test/resources/witness/patternLayout.2
new file mode 100644
index 0000000..b0ca4e1
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.2
@@ -0,0 +1,10 @@
+ [main] DEBUG atternLayoutTest - Message 0
+ [main] DEBUG root - Message 0
+ [main] INFO atternLayoutTest - Message 1
+ [main] INFO root - Message 1
+ [main] WARN atternLayoutTest - Message 2
+ [main] WARN root - Message 2
+ [main] ERROR atternLayoutTest - Message 3
+ [main] ERROR root - Message 3
+ [main] FATAL atternLayoutTest - Message 4
+ [main] FATAL root - Message 4
diff --git a/src/test/resources/witness/patternLayout.3 b/src/test/resources/witness/patternLayout.3
new file mode 100644
index 0000000..b7fde81
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.3
@@ -0,0 +1,10 @@
+ [main] DEBUG atternLayoutTest - Message 0
+ [main] DEBUG root - Message 0
+ [main] INFO atternLayoutTest - Message 1
+ [main] INFO root - Message 1
+ [main] WARN atternLayoutTest - Message 2
+ [main] WARN root - Message 2
+ [main] ERROR atternLayoutTest - Message 3
+ [main] ERROR root - Message 3
+ [main] FATAL atternLayoutTest - Message 4
+ [main] FATAL root - Message 4 \ No newline at end of file
diff --git a/src/test/resources/witness/patternLayout.4 b/src/test/resources/witness/patternLayout.4
new file mode 100644
index 0000000..b7fde81
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.4
@@ -0,0 +1,10 @@
+ [main] DEBUG atternLayoutTest - Message 0
+ [main] DEBUG root - Message 0
+ [main] INFO atternLayoutTest - Message 1
+ [main] INFO root - Message 1
+ [main] WARN atternLayoutTest - Message 2
+ [main] WARN root - Message 2
+ [main] ERROR atternLayoutTest - Message 3
+ [main] ERROR root - Message 3
+ [main] FATAL atternLayoutTest - Message 4
+ [main] FATAL root - Message 4 \ No newline at end of file
diff --git a/src/test/resources/witness/patternLayout.5 b/src/test/resources/witness/patternLayout.5
new file mode 100644
index 0000000..b7fde81
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.5
@@ -0,0 +1,10 @@
+ [main] DEBUG atternLayoutTest - Message 0
+ [main] DEBUG root - Message 0
+ [main] INFO atternLayoutTest - Message 1
+ [main] INFO root - Message 1
+ [main] WARN atternLayoutTest - Message 2
+ [main] WARN root - Message 2
+ [main] ERROR atternLayoutTest - Message 3
+ [main] ERROR root - Message 3
+ [main] FATAL atternLayoutTest - Message 4
+ [main] FATAL root - Message 4 \ No newline at end of file
diff --git a/src/test/resources/witness/patternLayout.6 b/src/test/resources/witness/patternLayout.6
new file mode 100644
index 0000000..b7fde81
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.6
@@ -0,0 +1,10 @@
+ [main] DEBUG atternLayoutTest - Message 0
+ [main] DEBUG root - Message 0
+ [main] INFO atternLayoutTest - Message 1
+ [main] INFO root - Message 1
+ [main] WARN atternLayoutTest - Message 2
+ [main] WARN root - Message 2
+ [main] ERROR atternLayoutTest - Message 3
+ [main] ERROR root - Message 3
+ [main] FATAL atternLayoutTest - Message 4
+ [main] FATAL root - Message 4 \ No newline at end of file
diff --git a/src/test/resources/witness/patternLayout.7 b/src/test/resources/witness/patternLayout.7
new file mode 100644
index 0000000..b7fde81
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.7
@@ -0,0 +1,10 @@
+ [main] DEBUG atternLayoutTest - Message 0
+ [main] DEBUG root - Message 0
+ [main] INFO atternLayoutTest - Message 1
+ [main] INFO root - Message 1
+ [main] WARN atternLayoutTest - Message 2
+ [main] WARN root - Message 2
+ [main] ERROR atternLayoutTest - Message 3
+ [main] ERROR root - Message 3
+ [main] FATAL atternLayoutTest - Message 4
+ [main] FATAL root - Message 4 \ No newline at end of file
diff --git a/src/test/resources/witness/patternLayout.8 b/src/test/resources/witness/patternLayout.8
new file mode 100644
index 0000000..f7083df
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.8
@@ -0,0 +1,10 @@
+[main] DEBUG atternLayoutTest - Message 0
+[main] DEBUG root - Message 0
+[main] INFO atternLayoutTest - Message 1
+[main] INFO root - Message 1
+[main] WARN atternLayoutTest - Message 2
+[main] WARN root - Message 2
+[main] ERROR atternLayoutTest - Message 3
+[main] ERROR root - Message 3
+[main] FATAL atternLayoutTest - Message 4
+[main] FATAL root - Message 4 \ No newline at end of file
diff --git a/src/test/resources/witness/patternLayout.9 b/src/test/resources/witness/patternLayout.9
new file mode 100644
index 0000000..2b2b6fe
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.9
@@ -0,0 +1,10 @@
+[main] DEBUG atternLayoutTest : Message 0
+[main] DEBUG root : Message 0
+[main] INFO atternLayoutTest : Message 1
+[main] INFO root : Message 1
+[main] WARN atternLayoutTest : Message 2
+[main] WARN root : Message 2
+[main] ERROR atternLayoutTest : Message 3
+[main] ERROR root : Message 3
+[main] FATAL atternLayoutTest : Message 4
+[main] FATAL root : Message 4 \ No newline at end of file
diff --git a/src/test/resources/witness/patternLayout.mdc.1 b/src/test/resources/witness/patternLayout.mdc.1
new file mode 100644
index 0000000..2c4bde6
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.mdc.1
@@ -0,0 +1 @@
+DEBUG - Hello World {{key1,va11}{key2,va12}}
diff --git a/src/test/resources/witness/patternLayout.mdc.2 b/src/test/resources/witness/patternLayout.mdc.2
new file mode 100644
index 0000000..c7104dc
--- /dev/null
+++ b/src/test/resources/witness/patternLayout.mdc.2
@@ -0,0 +1,12 @@
+starting mdc pattern test
+empty mdc, no key specified in pattern : {}
+empty mdc, key1 in pattern :
+empty mdc, key2 in pattern :
+empty mdc, key3 in pattern :
+empty mdc, key1, key2, and key3 in pattern : ,,
+filled mdc, no key specified in pattern : {{key1,value1}{key2,value2}}
+filled mdc, key1 in pattern : value1
+filled mdc, key2 in pattern : value2
+filled mdc, key3 in pattern :
+filled mdc, key1, key2, and key3 in pattern : value1,value2,
+finished mdc pattern test
diff --git a/src/test/resources/witness/rolling/Makefile.am b/src/test/resources/witness/rolling/Makefile.am
new file mode 100644
index 0000000..c154185
--- /dev/null
+++ b/src/test/resources/witness/rolling/Makefile.am
@@ -0,0 +1,26 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+EXTRA_DIST = sbr-test* \
+ tbr-test*
+
+# if we are building in a separate build tree, then copy all necessary files
+all-local:
+ @if test "$(top_srcdir)" != "$(top_builddir)"; then \
+ echo "Copying test suite data files ..." ; \
+ list='$(EXTRA_DIST)'; for file in $$list; do \
+ cp -p $(srcdir)/$$file . ; \
+ done \
+ fi
diff --git a/src/test/resources/witness/rolling/sbr-test2.0 b/src/test/resources/witness/rolling/sbr-test2.0
new file mode 100644
index 0000000..ddeb00f
--- /dev/null
+++ b/src/test/resources/witness/rolling/sbr-test2.0
@@ -0,0 +1,10 @@
+Hello--10
+Hello--11
+Hello--12
+Hello--13
+Hello--14
+Hello--15
+Hello--16
+Hello--17
+Hello--18
+Hello--19
diff --git a/src/test/resources/witness/rolling/sbr-test2.1 b/src/test/resources/witness/rolling/sbr-test2.1
new file mode 100644
index 0000000..e7850d1
--- /dev/null
+++ b/src/test/resources/witness/rolling/sbr-test2.1
@@ -0,0 +1,10 @@
+Hello---0
+Hello---1
+Hello---2
+Hello---3
+Hello---4
+Hello---5
+Hello---6
+Hello---7
+Hello---8
+Hello---9
diff --git a/src/test/resources/witness/rolling/sbr-test2.log b/src/test/resources/witness/rolling/sbr-test2.log
new file mode 100644
index 0000000..7243328
--- /dev/null
+++ b/src/test/resources/witness/rolling/sbr-test2.log
@@ -0,0 +1,5 @@
+Hello--20
+Hello--21
+Hello--22
+Hello--23
+Hello--24
diff --git a/src/test/resources/witness/rolling/sbr-test3.0.gz b/src/test/resources/witness/rolling/sbr-test3.0.gz
new file mode 100644
index 0000000..0e208b2
--- /dev/null
+++ b/src/test/resources/witness/rolling/sbr-test3.0.gz
Binary files differ
diff --git a/src/test/resources/witness/rolling/sbr-test3.1.gz b/src/test/resources/witness/rolling/sbr-test3.1.gz
new file mode 100644
index 0000000..2d00fc4
--- /dev/null
+++ b/src/test/resources/witness/rolling/sbr-test3.1.gz
Binary files differ
diff --git a/src/test/resources/witness/rolling/sbr-test3.log b/src/test/resources/witness/rolling/sbr-test3.log
new file mode 100644
index 0000000..7243328
--- /dev/null
+++ b/src/test/resources/witness/rolling/sbr-test3.log
@@ -0,0 +1,5 @@
+Hello--20
+Hello--21
+Hello--22
+Hello--23
+Hello--24
diff --git a/src/test/resources/witness/rolling/sbr-test4.log b/src/test/resources/witness/rolling/sbr-test4.log
new file mode 100644
index 0000000..2feaa33
--- /dev/null
+++ b/src/test/resources/witness/rolling/sbr-test4.log
@@ -0,0 +1,25 @@
+Hello---0
+Hello---1
+Hello---2
+Hello---3
+Hello---4
+Hello---5
+Hello---6
+Hello---7
+Hello---8
+Hello---9
+Hello--10
+Hello--11
+Hello--12
+Hello--13
+Hello--14
+Hello--15
+Hello--16
+Hello--17
+Hello--18
+Hello--19
+Hello--20
+Hello--21
+Hello--22
+Hello--23
+Hello--24
diff --git a/src/test/resources/witness/rolling/tbr-test1.0 b/src/test/resources/witness/rolling/tbr-test1.0
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test1.0
diff --git a/src/test/resources/witness/rolling/tbr-test1.1 b/src/test/resources/witness/rolling/tbr-test1.1
new file mode 100644
index 0000000..25cf10b
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test1.1
@@ -0,0 +1,2 @@
+TimeBasedRollingTest - Hello---0
+TimeBasedRollingTest - Hello---1
diff --git a/src/test/resources/witness/rolling/tbr-test1.2 b/src/test/resources/witness/rolling/tbr-test1.2
new file mode 100644
index 0000000..39b27e8
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test1.2
@@ -0,0 +1,2 @@
+TimeBasedRollingTest - Hello---2
+TimeBasedRollingTest - Hello---3
diff --git a/src/test/resources/witness/rolling/tbr-test1.3 b/src/test/resources/witness/rolling/tbr-test1.3
new file mode 100644
index 0000000..dfc095d
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test1.3
@@ -0,0 +1 @@
+TimeBasedRollingTest - Hello---4
diff --git a/src/test/resources/witness/rolling/tbr-test2.0 b/src/test/resources/witness/rolling/tbr-test2.0
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test2.0
diff --git a/src/test/resources/witness/rolling/tbr-test2.1 b/src/test/resources/witness/rolling/tbr-test2.1
new file mode 100644
index 0000000..25cf10b
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test2.1
@@ -0,0 +1,2 @@
+TimeBasedRollingTest - Hello---0
+TimeBasedRollingTest - Hello---1
diff --git a/src/test/resources/witness/rolling/tbr-test2.2 b/src/test/resources/witness/rolling/tbr-test2.2
new file mode 100644
index 0000000..39b27e8
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test2.2
@@ -0,0 +1,2 @@
+TimeBasedRollingTest - Hello---2
+TimeBasedRollingTest - Hello---3
diff --git a/src/test/resources/witness/rolling/tbr-test2.3 b/src/test/resources/witness/rolling/tbr-test2.3
new file mode 100644
index 0000000..dfc095d
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test2.3
@@ -0,0 +1 @@
+TimeBasedRollingTest - Hello---4
diff --git a/src/test/resources/witness/rolling/tbr-test3.3 b/src/test/resources/witness/rolling/tbr-test3.3
new file mode 100644
index 0000000..dfc095d
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test3.3
@@ -0,0 +1 @@
+TimeBasedRollingTest - Hello---4
diff --git a/src/test/resources/witness/rolling/tbr-test4.0 b/src/test/resources/witness/rolling/tbr-test4.0
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test4.0
diff --git a/src/test/resources/witness/rolling/tbr-test4.1 b/src/test/resources/witness/rolling/tbr-test4.1
new file mode 100644
index 0000000..25cf10b
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test4.1
@@ -0,0 +1,2 @@
+TimeBasedRollingTest - Hello---0
+TimeBasedRollingTest - Hello---1
diff --git a/src/test/resources/witness/rolling/tbr-test4.2 b/src/test/resources/witness/rolling/tbr-test4.2
new file mode 100644
index 0000000..39b27e8
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test4.2
@@ -0,0 +1,2 @@
+TimeBasedRollingTest - Hello---2
+TimeBasedRollingTest - Hello---3
diff --git a/src/test/resources/witness/rolling/tbr-test4.3 b/src/test/resources/witness/rolling/tbr-test4.3
new file mode 100644
index 0000000..dfc095d
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test4.3
@@ -0,0 +1 @@
+TimeBasedRollingTest - Hello---4
diff --git a/src/test/resources/witness/rolling/tbr-test5.0 b/src/test/resources/witness/rolling/tbr-test5.0
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test5.0
diff --git a/src/test/resources/witness/rolling/tbr-test5.1 b/src/test/resources/witness/rolling/tbr-test5.1
new file mode 100644
index 0000000..25cf10b
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test5.1
@@ -0,0 +1,2 @@
+TimeBasedRollingTest - Hello---0
+TimeBasedRollingTest - Hello---1
diff --git a/src/test/resources/witness/rolling/tbr-test5.2 b/src/test/resources/witness/rolling/tbr-test5.2
new file mode 100644
index 0000000..39b27e8
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test5.2
@@ -0,0 +1,2 @@
+TimeBasedRollingTest - Hello---2
+TimeBasedRollingTest - Hello---3
diff --git a/src/test/resources/witness/rolling/tbr-test5.3 b/src/test/resources/witness/rolling/tbr-test5.3
new file mode 100644
index 0000000..dfc095d
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test5.3
@@ -0,0 +1 @@
+TimeBasedRollingTest - Hello---4
diff --git a/src/test/resources/witness/rolling/tbr-test6.3 b/src/test/resources/witness/rolling/tbr-test6.3
new file mode 100644
index 0000000..dfc095d
--- /dev/null
+++ b/src/test/resources/witness/rolling/tbr-test6.3
@@ -0,0 +1 @@
+TimeBasedRollingTest - Hello---4
diff --git a/src/test/resources/witness/serialization/exception.bin b/src/test/resources/witness/serialization/exception.bin
new file mode 100644
index 0000000..87b0c1d
--- /dev/null
+++ b/src/test/resources/witness/serialization/exception.bin
Binary files differ
diff --git a/src/test/resources/witness/serialization/info.bin b/src/test/resources/witness/serialization/info.bin
new file mode 100644
index 0000000..f887f39
--- /dev/null
+++ b/src/test/resources/witness/serialization/info.bin
Binary files differ
diff --git a/src/test/resources/witness/serialization/location.bin b/src/test/resources/witness/serialization/location.bin
new file mode 100644
index 0000000..c798850
--- /dev/null
+++ b/src/test/resources/witness/serialization/location.bin
Binary files differ
diff --git a/src/test/resources/witness/serialization/mdc.bin b/src/test/resources/witness/serialization/mdc.bin
new file mode 100644
index 0000000..42e994e
--- /dev/null
+++ b/src/test/resources/witness/serialization/mdc.bin
Binary files differ
diff --git a/src/test/resources/witness/serialization/ndc.bin b/src/test/resources/witness/serialization/ndc.bin
new file mode 100644
index 0000000..7f43455
--- /dev/null
+++ b/src/test/resources/witness/serialization/ndc.bin
Binary files differ
diff --git a/src/test/resources/witness/serialization/simple.bin b/src/test/resources/witness/serialization/simple.bin
new file mode 100644
index 0000000..c31f3cf
--- /dev/null
+++ b/src/test/resources/witness/serialization/simple.bin
Binary files differ
diff --git a/src/test/resources/witness/simple b/src/test/resources/witness/simple
new file mode 100644
index 0000000..0cf037e
--- /dev/null
+++ b/src/test/resources/witness/simple
@@ -0,0 +1,25 @@
+FATAL - Message 0
+ERROR - Message 1
+FATAL - Message 2
+ERROR - Message 3
+WARN - Message 4
+INFO - Message 5
+FATAL - Message 6
+ERROR - Message 7
+WARN - Message 8
+INFO - Message 9
+FATAL - Message 10
+ERROR - Message 11
+FATAL - Message 12
+ERROR - Message 13
+FATAL - Message 14
+ERROR - Message 15
+WARN - Message 16
+INFO - Message 17
+DEBUG - Message 18
+FATAL - Message 19
+ERROR - Message 20
+WARN - Message 21
+INFO - Message 22
+DEBUG - Message 23
+INFO - Messages should bear numbers 0 through 23.
diff --git a/src/test/resources/witness/socketServer.1 b/src/test/resources/witness/socketServer.1
new file mode 100644
index 0000000..a44ce7d
--- /dev/null
+++ b/src/test/resources/witness/socketServer.1
@@ -0,0 +1,31 @@
+TRACE T1 [main] org.apache.log4j.net.SocketServerTestCase Message 1
+TRACE T1 [main] root Message 2
+DEBUG T1 [main] org.apache.log4j.net.SocketServerTestCase Message 3
+DEBUG T1 [main] root Message 4
+ INFO T1 [main] org.apache.log4j.net.SocketServerTestCase Message 5
+ WARN T1 [main] org.apache.log4j.net.SocketServerTestCase Message 6
+FATAL T1 [main] org.apache.log4j.net.SocketServerTestCase Message 7
+DEBUG T1 [main] org.apache.log4j.net.SocketServerTestCase Message 8
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test1(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
+ERROR T1 [main] root Message 9
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test1(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
diff --git a/src/test/resources/witness/socketServer.2 b/src/test/resources/witness/socketServer.2
new file mode 100644
index 0000000..8f9b189
--- /dev/null
+++ b/src/test/resources/witness/socketServer.2
@@ -0,0 +1,31 @@
+TRACE T2 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 1
+TRACE T2 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 2
+DEBUG T2 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 3
+DEBUG T2 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 4
+ INFO T2 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 5
+ WARN T2 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 6
+FATAL T2 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 7
+DEBUG T2 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 8
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test2(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
+ERROR T2 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 9
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test2(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
diff --git a/src/test/resources/witness/socketServer.3 b/src/test/resources/witness/socketServer.3
new file mode 100644
index 0000000..1f8e8b6
--- /dev/null
+++ b/src/test/resources/witness/socketServer.3
@@ -0,0 +1,31 @@
+TRACE T3 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 1
+TRACE T3 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 2
+DEBUG T3 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 3
+DEBUG T3 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 4
+ INFO T3 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 5
+ WARN T3 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 6
+FATAL T3 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 7
+DEBUG T3 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 8
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test3(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
+ERROR T3 [main] SocketServerTestCase (socketservertestcase.cpp:XXX) Message 9
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test3(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
diff --git a/src/test/resources/witness/socketServer.4 b/src/test/resources/witness/socketServer.4
new file mode 100644
index 0000000..387d601
--- /dev/null
+++ b/src/test/resources/witness/socketServer.4
@@ -0,0 +1,31 @@
+TRACE some T4 MDC-TEST4 [main] SocketServerTestCase - Message 1
+TRACE some T4 MDC-TEST4 [main] root - Message 2
+DEBUG some T4 MDC-TEST4 [main] SocketServerTestCase - Message 3
+DEBUG some T4 MDC-TEST4 [main] root - Message 4
+ INFO some T4 MDC-TEST4 [main] SocketServerTestCase - Message 5
+ WARN some T4 MDC-TEST4 [main] SocketServerTestCase - Message 6
+FATAL some T4 MDC-TEST4 [main] SocketServerTestCase - Message 7
+DEBUG some T4 MDC-TEST4 [main] SocketServerTestCase - Message 8
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test4(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
+ERROR some T4 MDC-TEST4 [main] root - Message 9
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test4(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
diff --git a/src/test/resources/witness/socketServer.5 b/src/test/resources/witness/socketServer.5
new file mode 100644
index 0000000..1219ace
--- /dev/null
+++ b/src/test/resources/witness/socketServer.5
@@ -0,0 +1,31 @@
+TRACE some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 1
+TRACE some5 T5 MDC-TEST5 [main] root - Message 2
+DEBUG some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 3
+DEBUG some5 T5 MDC-TEST5 [main] root - Message 4
+ INFO some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 5
+ WARN some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 6
+FATAL some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 7
+DEBUG some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 8
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test5(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
+ERROR some5 T5 MDC-TEST5 [main] root - Message 9
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test5(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
diff --git a/src/test/resources/witness/socketServer.6 b/src/test/resources/witness/socketServer.6
new file mode 100644
index 0000000..82ff2e7
--- /dev/null
+++ b/src/test/resources/witness/socketServer.6
@@ -0,0 +1,31 @@
+TRACE some6 T6 client-test6 MDC-TEST6 [main] SocketServerTestCase - Message 1
+TRACE some6 T6 client-test6 MDC-TEST6 [main] root - Message 2
+DEBUG some6 T6 client-test6 MDC-TEST6 [main] SocketServerTestCase - Message 3
+DEBUG some6 T6 client-test6 MDC-TEST6 [main] root - Message 4
+ INFO some6 T6 client-test6 MDC-TEST6 [main] SocketServerTestCase - Message 5
+ WARN some6 T6 client-test6 MDC-TEST6 [main] SocketServerTestCase - Message 6
+FATAL some6 T6 client-test6 MDC-TEST6 [main] SocketServerTestCase - Message 7
+DEBUG some6 T6 client-test6 MDC-TEST6 [main] SocketServerTestCase - Message 8
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test6(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
+ERROR some6 T6 client-test6 MDC-TEST6 [main] root - Message 9
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test6(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
diff --git a/src/test/resources/witness/socketServer.7 b/src/test/resources/witness/socketServer.7
new file mode 100644
index 0000000..3694281
--- /dev/null
+++ b/src/test/resources/witness/socketServer.7
@@ -0,0 +1,31 @@
+TRACE some7 T7 client-test7 MDC-TEST7 [main] SocketServerTestCase - Message 1
+TRACE some7 T7 client-test7 MDC-TEST7 [main] root - Message 2
+DEBUG some7 T7 client-test7 MDC-TEST7 [main] SocketServerTestCase - Message 3
+DEBUG some7 T7 client-test7 MDC-TEST7 [main] root - Message 4
+ INFO some7 T7 client-test7 MDC-TEST7 [main] SocketServerTestCase - Message 5
+ WARN some7 T7 client-test7 MDC-TEST7 [main] SocketServerTestCase - Message 6
+FATAL some7 T7 client-test7 MDC-TEST7 [main] SocketServerTestCase - Message 7
+DEBUG some7 T7 client-test7 MDC-TEST7 [main] SocketServerTestCase - Message 8
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test7(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
+ERROR some7 T7 client-test7 MDC-TEST7 [main] root - Message 9
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test7(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
diff --git a/src/test/resources/witness/socketServer.8 b/src/test/resources/witness/socketServer.8
new file mode 100644
index 0000000..fbd9211
--- /dev/null
+++ b/src/test/resources/witness/socketServer.8
@@ -0,0 +1,31 @@
+TRACE some8 T8 shortSocketServer MDC-TEST8 [main] SocketServerTestCase - Message 1
+TRACE some8 T8 shortSocketServer MDC-TEST8 [main] root - Message 2
+DEBUG some8 T8 shortSocketServer MDC-TEST8 [main] SocketServerTestCase - Message 3
+DEBUG some8 T8 shortSocketServer MDC-TEST8 [main] root - Message 4
+ INFO some8 T8 shortSocketServer MDC-TEST8 [main] SocketServerTestCase - Message 5
+ WARN some8 T8 shortSocketServer MDC-TEST8 [main] SocketServerTestCase - Message 6
+FATAL some8 T8 shortSocketServer MDC-TEST8 [main] SocketServerTestCase - Message 7
+DEBUG some8 T8 shortSocketServer MDC-TEST8 [main] SocketServerTestCase - Message 8
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test8(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
+ERROR some8 T8 shortSocketServer MDC-TEST8 [main] root - Message 9
+java.lang.Exception: Just testing
+ at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX)
+ at org.apache.log4j.net.SocketServerTestCase.test8(SocketServerTestCase.java:XXX)
+ at junit.framework.TestCase.runTest(TestCase.java:XXX)
+ at junit.framework.TestCase.runBare(TestCase.java:XXX)
+ at junit.framework.TestResult$1.protect(TestResult.java:XXX)
+ at junit.framework.TestResult.runProtected(TestResult.java:XXX)
+ at junit.framework.TestResult.run(TestResult.java:XXX)
+ at junit.framework.TestCase.run(TestCase.java:XXX)
+ at junit.framework.TestSuite.runTest(TestSuite.java:XXX)
+ at junit.framework.TestSuite.run(TestSuite.java:XXX)
diff --git a/src/test/resources/witness/ttcc b/src/test/resources/witness/ttcc
new file mode 100644
index 0000000..459718b
--- /dev/null
+++ b/src/test/resources/witness/ttcc
@@ -0,0 +1,25 @@
+ [main] FATAL ERR - Message 0
+ [main] ERROR ERR - Message 1
+ [main] FATAL INF - Message 2
+ [main] ERROR INF - Message 3
+ [main] WARN INF - Message 4
+ [main] INFO INF - Message 5
+ [main] FATAL INF.UNDEF - Message 6
+ [main] ERROR INF.UNDEF - Message 7
+ [main] WARN INF.UNDEF - Message 8
+ [main] INFO INF.UNDEF - Message 9
+ [main] FATAL INF.ERR - Message 10
+ [main] ERROR INF.ERR - Message 11
+ [main] FATAL INF.ERR.UNDEF - Message 12
+ [main] ERROR INF.ERR.UNDEF - Message 13
+ [main] FATAL DEB - Message 14
+ [main] ERROR DEB - Message 15
+ [main] WARN DEB - Message 16
+ [main] INFO DEB - Message 17
+ [main] DEBUG DEB - Message 18
+ [main] FATAL UNDEF - Message 19
+ [main] ERROR UNDEF - Message 20
+ [main] WARN UNDEF - Message 21
+ [main] INFO UNDEF - Message 22
+ [main] DEBUG UNDEF - Message 23
+ [main] INFO INF - Messages should bear numbers 0 through 23.
diff --git a/src/test/resources/witness/xmlLayout.1 b/src/test/resources/witness/xmlLayout.1
new file mode 100644
index 0000000..9e171f1
--- /dev/null
+++ b/src/test/resources/witness/xmlLayout.1
@@ -0,0 +1,68 @@
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase$X" timestamp="XXX" level="INFO" thread="main">
+<log4j:message><![CDATA[in X() constructor]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="TRACE" thread="main">
+<log4j:message><![CDATA[Message 0]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="TRACE" thread="main">
+<log4j:message><![CDATA[Message 0]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[Message 1]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[Message 1]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="INFO" thread="main">
+<log4j:message><![CDATA[Message 2]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="INFO" thread="main">
+<log4j:message><![CDATA[Message 2]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="WARN" thread="main">
+<log4j:message><![CDATA[Message 3]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="WARN" thread="main">
+<log4j:message><![CDATA[Message 3]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="ERROR" thread="main">
+<log4j:message><![CDATA[Message 4]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="ERROR" thread="main">
+<log4j:message><![CDATA[Message 4]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="FATAL" thread="main">
+<log4j:message><![CDATA[Message 5]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="FATAL" thread="main">
+<log4j:message><![CDATA[Message 5]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[Message 6]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[Message 6]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="ERROR" thread="main">
+<log4j:message><![CDATA[Message 7]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="ERROR" thread="main">
+<log4j:message><![CDATA[Message 7]]></log4j:message>
+</log4j:event>
+
diff --git a/src/test/resources/witness/xmlLayout.2 b/src/test/resources/witness/xmlLayout.2
new file mode 100644
index 0000000..41c3664
--- /dev/null
+++ b/src/test/resources/witness/xmlLayout.2
@@ -0,0 +1,85 @@
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase$X" timestamp="XXX" level="INFO" thread="main">
+<log4j:message><![CDATA[in X() constructor]]></log4j:message>
+<log4j:locationInfo class="X" method="X" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="TRACE" thread="main">
+<log4j:message><![CDATA[Message 0]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="TRACE" thread="main">
+<log4j:message><![CDATA[Message 0]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[Message 1]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[Message 1]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="INFO" thread="main">
+<log4j:message><![CDATA[Message 2]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="INFO" thread="main">
+<log4j:message><![CDATA[Message 2]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="WARN" thread="main">
+<log4j:message><![CDATA[Message 3]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="WARN" thread="main">
+<log4j:message><![CDATA[Message 3]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="ERROR" thread="main">
+<log4j:message><![CDATA[Message 4]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="ERROR" thread="main">
+<log4j:message><![CDATA[Message 4]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="FATAL" thread="main">
+<log4j:message><![CDATA[Message 5]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="FATAL" thread="main">
+<log4j:message><![CDATA[Message 5]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[Message 6]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[Message 6]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="ERROR" thread="main">
+<log4j:message><![CDATA[Message 7]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="root" timestamp="XXX" level="ERROR" thread="main">
+<log4j:message><![CDATA[Message 7]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
diff --git a/src/test/resources/witness/xmlLayout.3 b/src/test/resources/witness/xmlLayout.3
new file mode 100644
index 0000000..7ca7809
--- /dev/null
+++ b/src/test/resources/witness/xmlLayout.3
@@ -0,0 +1,10 @@
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="TRACE" thread="main">
+<log4j:message><![CDATA[Message with embedded <![CDATA[<hello>hi</hello>]]>]]&gt;<![CDATA[.]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="testCDATA" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[Message with embedded <![CDATA[<hello>hi</hello>]]>]]&gt;<![CDATA[.]]></log4j:message>
+<log4j:locationInfo class="XMLLayoutTestCase" method="testCDATA" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+
diff --git a/src/test/resources/witness/xmlLayout.mdc.1 b/src/test/resources/witness/xmlLayout.mdc.1
new file mode 100644
index 0000000..9215d1b
--- /dev/null
+++ b/src/test/resources/witness/xmlLayout.mdc.1
@@ -0,0 +1,8 @@
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[Hello]]></log4j:message>
+<log4j:properties>
+<log4j:data name="key1" value="val1"/>
+<log4j:data name="key2" value="val2"/>
+</log4j:properties>
+</log4j:event>
+
diff --git a/src/test/resources/witness/xmlLayout.mdc.2 b/src/test/resources/witness/xmlLayout.mdc.2
new file mode 100644
index 0000000..c690780
--- /dev/null
+++ b/src/test/resources/witness/xmlLayout.mdc.2
@@ -0,0 +1,8 @@
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[Hello]]></log4j:message>
+<log4j:properties>
+<log4j:data name="&lt;blahKey value='blah'/&gt;" value="blahValue"/>
+<log4j:data name="blahAttribute" value="&lt;blah value='blah'&gt;"/>
+</log4j:properties>
+</log4j:event>
+
diff --git a/src/test/resources/witness/xmlLayout.null b/src/test/resources/witness/xmlLayout.null
new file mode 100644
index 0000000..dc22037
--- /dev/null
+++ b/src/test/resources/witness/xmlLayout.null
@@ -0,0 +1,12 @@
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[hi]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[null]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[hi]]></log4j:message>
+</log4j:event>
+