This commit was manufactured by cvs2svn to create tag 'v1_2_6'.
git-svn-id: https://svn.apache.org/repos/asf/logging/log4j/tags/v1_2_6@309627 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/BRANCHES b/BRANCHES
new file mode 100644
index 0000000..da0e39d
--- /dev/null
+++ b/BRANCHES
@@ -0,0 +1,61 @@
+
+Given that log4j 1.3 is not likely to be released before a few months,
+I have created a branch called v1_2-branch in our CVS repository. The
+branch was created by issuing the following command:
+
+cvs -d :ext:ceki@cvs.apache.org:/home/cvs rtag -b -r v1_2final v1_2-branch jakarta-log4j
+
+Using the 1.2 branch, we can incorporate patches to log4j version 1.2
+while version 1.3 continues to be developed on the main trunk. For
+example, we can officially release LogFactor5 (including
+documentation) already in log4j 1.2.1.
+
+The command to access the v1_2-branch is:
+
+cvs -d XYZ checkout -r v1_2-branch jakarta-log4j
+
+where XYZ is the remote repository name, that is
+":ext:ceki@cvs.apache.org:/home/cvs" for me.
+
+Alternatively, you can issue following update command from within any
+existing work copy.
+
+ cvs update -r v1_2-branch
+
+Working with branches is not completely trivial and requires a little
+coordination between committers, in particular in relation with branch
+merge operations. In order to avoid multiple merge conflicts, each
+time we merge from the 1.2 branch to the main trunk, we should tag the
+merged version on the 1.2 branch. Subsequent merges should use the tag
+referring to the latest merged version of the branch. Also do not
+forget to publicly announce a merge operation.
+
+I am suggesting that (1.2 -> trunk) merge operations be done in a
+concerted manner. Before doing a merge you tell everyone that you are
+going to do a merge, you execute the merge operation, and then tag the
+merged version on the 1.2 branch, for example v_1_2_-merged-bug666
+
+The *next* merge operation would be performed as
+
+ cvs update -j v_1_2_-merged-bug666 -j v1_2-branch
+
+from within a working copy of the *trunk*. This merge operation would
+obviously also need to be tagged. According to the CVS manual, this
+procedure eliminates the side effects of merging already merged
+changes.
+
+Bug fixes should and documentation improvements, should be made to the
+1.2 branch, not the trunk. I'll take care of merging the changes to
+the main trunk.
+
+If this sounds like mambo jumbo, I urge you to consult the CVS
+documentation and experiment with branches before hitting the log4j
+repository. Branches are not that complicated really although they
+require slightly more discipline on the part of committers. Do not
+hesitate to shout if you need help.
+
+If you have a better alternative for working with branches please let
+us know.
+
+--
+Ceki
\ No newline at end of file
diff --git a/INSTALL b/INSTALL
index cf4fd20..d3db76b 100644
--- a/INSTALL
+++ b/INSTALL
@@ -11,7 +11,8 @@
version number, under PATH_OF_YOUR_CHOICE. We will refer to the
directory PATH_OF_YOUR_CHOICE/jakarta-log4j-VERSION/ as $LOG4J_HOME/.
-3) Add $LOG4J_HOME/dist/lib/log4j-1.2.jar to your CLASSPATH.
+3) Assuming you are using log4j version 1.2, add
+ $LOG4J_HOME/dist/lib/log4j-1.2.jar to your CLASSPATH,
4) You can now test your installation by first compiling the following
simple program.
@@ -57,8 +58,7 @@
log4j dependencies
==================
-The log4j distribution comes with pre-compiled classes. Log4j is based
-on JDK 1.1 with the following additional requirements:
+Log4j is based on JDK 1.1 with the following additional requirements:
----------------------------
Package org.apache.log4j.xml
@@ -82,7 +82,8 @@
The SMTPAppender relies on the JavaMail API. It has been tested with
JavaMail API version 1.2. The JavaMail API requires the
- JavaBeans Activation Framework package. You can download the JavaMail API at:
+ JavaBeans Activation Framework package. You can download the
+ JavaMail API at:
http://java.sun.com/products/javamail/
@@ -104,8 +105,8 @@
-----------------------
Log4j uses the JUnit framework version 3.7 for internal unit
- testing. If you want to compile all log4j source code, then you
- will need JUnit. JUnit is available from:
+ testing. If you want to compile the source code in the tests/
+ directory, then you will need JUnit. JUnit is available from:
http://www.junit.org
@@ -121,7 +122,7 @@
build.properties.sample file.
In case of problems send an e-mail note to
-log4j-user@jakarta.apache.org. Please do not directly e-mail any of
-the log4j developers. The answer to your question might be useful to
-other users. Moreover, there are many knowledgeable users on the
-log4j-user mailing lists who can quickly answer your questions.
+log4j-user@jakarta.apache.org. Please do not directly e-mail any
+log4j developers. The answer to your question might be useful to other
+users. Moreover, there are many knowledgeable users on the log4j-user
+mailing lists who can quickly answer your questions.
diff --git a/bin/StartLogFactor5.sh b/bin/StartLogFactor5.sh
new file mode 100644
index 0000000..80e296c
--- /dev/null
+++ b/bin/StartLogFactor5.sh
@@ -0,0 +1,20 @@
+#! /bin/sh
+
+if [ -z "$LOG4J_HOME" ] ; then
+ LOG4J_HOME=..
+fi
+
+JAVACMD=$JAVA_HOME/bin/java
+
+# add in the dependency .jar files
+DIRLIBS=${LOG4J_HOME}/dist/lib/*.jar
+for i in ${DIRLIBS}
+do
+
+ if [ "$i" != "${DIRLIBS}" ] ; then
+ LOCALCLASSPATH=$LOCALCLASSPATH:"$i"
+ fi
+
+done
+
+$JAVACMD -classpath "$LOCALCLASSPATH" org.apache.log4j.lf5.StartLogFactor5
\ No newline at end of file
diff --git a/bin/StartLogFactor5Console.bat b/bin/StartLogFactor5Console.bat
new file mode 100644
index 0000000..42cb1ea
--- /dev/null
+++ b/bin/StartLogFactor5Console.bat
@@ -0,0 +1,24 @@
+@echo off
+
+if not "%LOG4J_HOME%" == "" goto start
+
+SET LOG4J_HOME=..
+
+:start
+
+java -fullversion
+set LOCALCLASSPATH=
+for %%i in ("%LOG4J_HOME%\dist\lib\*.jar") do call "%LOG4J_HOME%\bin\lcp.bat" "%%i"
+
+echo using classpath %LOCALCLASSPATH%
+
+java -classpath %LOCALCLASSPATH% org.apache.log4j.lf5.StartLogFactor5
+
+exit
+
+:usage
+echo usage: lf5 (target)
+
+:eof
+pause
+
diff --git a/bin/lcp.bat b/bin/lcp.bat
new file mode 100644
index 0000000..4f26713
--- /dev/null
+++ b/bin/lcp.bat
@@ -0,0 +1,2 @@
+set LOCALCLASSPATH=%1;%LOCALCLASSPATH%
+
diff --git a/build.properties.sample b/build.properties.sample
index 300f021..78029a9 100644
--- a/build.properties.sample
+++ b/build.properties.sample
@@ -19,4 +19,11 @@
jmx-extra.jar=/java/jmx/lib/jmxtools.jar
+# jakarta-site2 module is used to transform xml files to html using
+# Anakia. You do not need to worry about this property unless you
+# intend to build the log4j web site yourself.
+jakarta-site2=../jakarta-site2
+
+# Required to run Checkstyle. Available from http://checkstyle.sf.net
+checkstyle.jar=/java/checkstyle-2.2/checkstyle-all-2.2.jar
diff --git a/build.xml b/build.xml
index 9bcb740..e534741 100644
--- a/build.xml
+++ b/build.xml
@@ -17,7 +17,7 @@
<!-- prefixed with "env". -->
<property environment="env"/>
- <property name="version" value="1.2"/>
+ <property name="version" value="1.2.6"/>
<!-- The base directory relative to which most targets are built -->
<property name="base" value="."/>
@@ -35,11 +35,14 @@
<!-- Destination for generated jar files -->
<property name="jar.dest" value="dist/lib"/>
+ <!-- The jar file that the jar task will generate -->
<property name="jar.filename" value="log4j-${version}.jar"/>
+ <!-- Destination for documentation files -->
+ <property name="docs.dest" value="./docs"/>
+ <!-- Source directory for xml docs -->
+ <property name="xdocs.src" value="./src/xdocs"/>
- <!-- Destination for documentation files generated or not -->
- <property name="docs" value="docs"/>
<!-- Destination for javadoc generated files -->
<property name="javadoc.dest" value="docs/api"/>
@@ -75,6 +78,13 @@
<pathelement location="${jmx-extra.jar}"/>
</path>
+ <!-- Construct compile classpath -->
+ <path id="site2.classpath">
+ <fileset dir="${jakarta-site2}/lib">
+ <include name="*.jar"/>
+ </fileset>
+ </path>
+
<!-- ================================================================= -->
<!-- Default target -->
@@ -179,6 +189,13 @@
<classpath refid="compile.classpath"/>
</javac>
+ <copy todir="${javac.dest}">
+ <fileset dir="${java.source.dir}"
+ includes="${stem}/lf5/**/*.properties"/>
+ <fileset dir="${java.source.dir}"
+ includes="${stem}/lf5/viewer/images/*"/>
+ </copy>
+
</target>
<target name="build.examples" depends="build.core">
@@ -193,6 +210,12 @@
<rmic base="${javac.dest}"
classname="examples.NumberCruncherServer"
/>
+
+ <copy todir="${javac.dest}">
+ <fileset dir="." includes="examples/lf5/**/*.properties"/>
+ <fileset dir="." includes="examples/lf5/**/*.xml"/>
+ </copy>
+
</target>
<target name="build.xml" depends="init, jaxp" if="jaxp-present">
@@ -251,7 +274,7 @@
<!-- ================================================================= -->
<target name="checkstyle" depends="init">
<taskdef resource="checkstyletask.properties"
- classpath="build/lib/checkstyle-all-2.1.jar"/>
+ classpath="${checkstyle.jar}"/>
<!-- by default checkstyle supports the Sun coding standard. -->
<checkstyle lcurlyMethod="nlow"
@@ -270,7 +293,7 @@
<target name="chainsaw" depends="build">
<!-- Need to fork to avoid problems -->
<java classname="org.apache.log4j.chainsaw.Main" fork="yes"
- classpath="${javac.dest}">
+ classpath="${javac.dest};${ant.home}/lib/crimson.jar">
</java>
</target>
@@ -308,6 +331,9 @@
${stem}/jdbc/*.class,
${stem}/varia/*.class,
${stem}/chainsaw/*.class,
+ ${stem}/lf5/**/*.class,
+ ${stem}/lf5/**/*.properties,
+ ${stem}/lf5/**/*.gif,
${stem}/nt/*.class,
${stem}/xml/*.class,
${stem}/jmx/*.class,
@@ -334,6 +360,7 @@
org.apache.log4j.config,
org.apache.log4j.helpers,
org.apache.log4j.jmx,
+ org.apache.log4j.lf5,
org.apache.log4j.net,
org.apache.log4j.nt,
org.apache.log4j.or,
@@ -350,23 +377,66 @@
protected="true"
author="true"
use="true"
- overview="${docs}/overview.html"
+ overview="${docs.dest}/overview.html"
doctitle="log4j version ${version}<br>API Specification"
windowtitle="Log4j Version ${version}"
header="<b>Log4j ${version}</b>"
bottom="Copyright 2000-2002 Apache Software Foundation.">
- <link offline="true"
- href="http://java.sun.com/products/jdk/1.2/docs/api"
- packageListLoc="${packaging.dir}"/>
+ <link href="http://java.sun.com/products/jdk/1.3/docs/api"/>
+ <link href="http://java.sun.com/j2ee/sdk_1.3/techdocs/api/"/>
<classpath refid="compile.classpath"/>
</javadoc>
</target>
+ <!-- ============================================== -->
+ <!-- Build the site files using Anakia -->
+ <!-- ============================================== -->
+ <target name="prepareSite2">
+ <available classname="org.apache.velocity.anakia.AnakiaTask"
+ property="AnakiaTask.present">
+ <classpath refid="site2.classpath"/>
+ </available>
+ </target>
+
+ <target name="checkSite2" depends="prepareSite2" unless="AnakiaTask.present">
+ <echo>
+ AnakiaTask is not present! Please check to make sure that
+ velocity.jar is in your classpath.
+ </echo>
+ </target>
+
+ <target name="site2" depends="checkSite2" if="AnakiaTask.present">
+ <taskdef name="anakia" classname="org.apache.velocity.anakia.AnakiaTask">
+ <classpath refid="site2.classpath"/>
+ </taskdef>
+
+ <anakia basedir="${xdocs.src}" destdir="${docs.dest}/"
+ extension=".html"
+ style="site.vsl"
+ projectFile="stylesheets/project.xml"
+ excludes="**/stylesheets/**, empty.xml, lf5/**"
+ includes="**/*.xml"
+ lastModifiedCheck="true"
+ templatePath="../jakarta-site2/xdocs/stylesheets">
+ </anakia>
+
+ <anakia basedir="${xdocs.src}" destdir="${docs.dest}/"
+ extension=".html"
+ style="site.vsl"
+ projectFile="stylesheets/lf5.xml"
+ excludes="**/stylesheets/**, empty.xml"
+ includes="lf5/*.xml"
+ lastModifiedCheck="true"
+ templatePath="../jakarta-site2/xdocs/stylesheets">
+ </anakia>
+ </target>
+
+
<!-- ================================================================= -->
<!-- Build a complete distribution. Results go to ${dist.images} -->
<!-- ================================================================= -->
- <target name="dist" depends="init, clean, javadoc, jar">
+ <target name="dist" depends="init, clean, javadoc, jar, site2">
<delete verbose="true">
<fileset dir=".">
@@ -403,7 +473,7 @@
</delete>
<mkdir dir="${dist.images}" />
-
+
<mkdir dir="${dist.tmp}/jakarta-log4j-${version}" />
<copy todir="${dist.tmp}/jakarta-log4j-${version}">
@@ -413,6 +483,7 @@
examples/**,
build/*,
build.xml,
+ build.properties.sample,
manifest.mf,
INSTALL,
LICENSE.txt,
@@ -423,6 +494,7 @@
**/*.bak, **/goEnv.bat,
**/Makefile, **/goEnv.bat,
docs/pub-support/*,
+ dist/classes/org/**,
src/java/org/apache/log4j/test/**/*,
**/.#*"/>
</copy>
diff --git a/build/siteBuild.sh b/build/siteBuild.sh
deleted file mode 100644
index d6707e7..0000000
--- a/build/siteBuild.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/sh
-
-if [ "$JAVA_HOME" = "" ] ; then
- echo You must set JAVA_HOME to point at your Java Development Kit directory
- exit 1
-fi
-
-# convert the existing path to unix
-if [ "$OSTYPE" = "cygwin32" ] || [ "$OSTYPE" = "cygwin" ] ; then
- CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
-fi
-
-# Add in the jakarta-site2 library files
-for i in ../../jakarta-site2/lib/*.jar
-do
- CLASSPATH=$CLASSPATH:"$i"
-done
-
-
-# convert the unix path to windows
-if [ "$OSTYPE" = "cygwin32" ] || [ "$OSTYPE" = "cygwin" ] ; then
- CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
-fi
-
-echo "CLASSPATH=$CLASSPATH"
-
-BUILDFILE=siteBuild.xml
-
-#echo $CLASSPATH
-
-java $ANT_OPTS -classpath "$CLASSPATH" org.apache.tools.ant.Main \
- -Dant.home=$ANT_HOME \
- -buildfile ${BUILDFILE} \
- "$@"
diff --git a/build/siteBuild.xml b/build/siteBuild.xml
deleted file mode 100644
index 5f9f844..0000000
--- a/build/siteBuild.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<project name="build-site" default="docs" basedir="..">
-
- <!-- Initialization properties -->
- <property name="project.name" value="log4j.site"/>
-
- <property name="docs.src" value="./src/xdocs"/>
- <property name="docs.dest" value="./docs"/>
-
- <target name="prepare">
- <available classname="org.apache.velocity.anakia.AnakiaTask"
- property="AnakiaTask.present"/>
- </target>
-
- <target depends="prepare" name="prepare-error" unless="AnakiaTask.present">
- <echo>
- AnakiaTask is not present! Please check to make sure that
- velocity.jar is in your classpath.
- </echo>
- </target>
-
- <target name="docs" depends="prepare-error" if="AnakiaTask.present">
- <taskdef name="anakia"
- classname="org.apache.velocity.anakia.AnakiaTask"/>
- <anakia basedir="${docs.src}" destdir="${docs.dest}/"
- extension=".html"
- style="site.vsl"
- projectFile="stylesheets/project.xml"
- excludes="**/stylesheets/**, empty.xml"
- includes="**/*.xml"
- lastModifiedCheck="true"
- templatePath="../jakarta-site2/xdocs/stylesheets">
- </anakia>
- <!--
- <copy todir="${docs.dest}/images" filtering="no">
- <fileset dir="${docs.src}/images">
- <include name="**/*.gif"/>
- <include name="**/*.jpeg"/>
- <include name="**/*.jpg"/>
- </fileset>
- </copy>
- In case we have CSS someday
- <copy todir="${docs.dest}" filtering="no">
- <fileset dir="${docs.src}">
- <include name="**/*.css"/>
- </fileset>
- </copy>
- -->
- </target>
-</project>
diff --git a/docs/FAQ.html b/docs/FAQ.html
index 3b0b0db..8adfa3e 100644
--- a/docs/FAQ.html
+++ b/docs/FAQ.html
@@ -60,8 +60,8 @@
(possibly across multiple timezones) logging to the same file using the
method above, what happens to timestamps?</P>
-<LI><P><A HREF="#j2ee">Why can't Log4J find my properties file in a J2EE or WAR application?</P>
-<LI><P><A HREF="#configureandwatch">Is there a way to get Log4J to automatically reload a configuration file if it changes?</P>
+<LI><P><A HREF="#j2ee">Why can't log4j find my properties file in a J2EE or WAR application?</P>
+<LI><P><A HREF="#configureandwatch">Is there a way to get log4j to automatically reload a configuration file if it changes?</P>
<LI><P><A HREF="#nteventlogproblems">What does the Windows NT Event Viewer complain about missing descriptions for my event messages
when I use the NTEventLogAppender?</P>
<LI><P><A HREF="#morenteventlogproblems">Why can't I map my logger names to the loggers that appear in the
@@ -436,9 +436,8 @@
<p>This policy usually best encapsulates what the user actually wants
to do, as opposed to her mind-projected solution.
-<p>See <a
-href="api/org/apache/log4j/examples/doc-files/sort4.lcf">sort4.lcf</a>
-for an example threshold configuration.
+<p>See <i>examples/sort4.lcf</i> for an example threshold
+configuration.
<p>If you must filter events by exact level match, then you can
attach a <a
@@ -477,10 +476,10 @@
seen in the log file would all appear in order, generated at the time they
arrived at the log server host according to its local clock.
-<p><a name=j2ee><h4>Why can't Log4J find my properties file in a J2EE
+<p><a name=j2ee><h4>Why can't log4j find my properties file in a J2EE
or WAR application?</h4>
-The short answer: the Log4J classes and the properties file are not
+The short answer: the log4j classes and the properties file are not
within the scope of the same classloader.<P>
The long answer (and what to do about it): J2EE or Servlet containers
@@ -490,14 +489,14 @@
classloader needs to find a class or a resource, it first delegates
the request to the parent.
-<P>Log4J only uses the default <CODE>Class.forName()</code> mechanism
+<P>Log4j only uses the default <CODE>Class.forName()</code> mechanism
for loading classes. Resources are handled similarly. See the
documentation for <CODE>java.lang.ClassLoader</CODE> for more details.
<P>So, if you're having problems, try loading the class or resource
-yourself. If you can't find it, neither will Log4J. ;)
+yourself. If you can't find it, neither will log4j. ;)
-<P><A NAME=configureandwatch><H4>Is there a way to get Log4J to
+<P><A NAME=configureandwatch><H4>Is there a way to get log4j to
automatically reload a configuration file if it changes?</H4>
<P>Yes. Both the DOMConfigurator and the PropertyConfigurator support
@@ -593,8 +592,8 @@
<p><li>Take responsibility for your code.
- <p>Authoring software is like parenting. It takes many
- years to raise a child.
+ <p>Authoring software is very much like running a marathon. It
+ takes time and endurance.
<p><li>Did I mention sticking with the indentation style?
diff --git a/docs/HISTORY b/docs/HISTORY
index d20fba1..3170422 100644
--- a/docs/HISTORY
+++ b/docs/HISTORY
@@ -5,7 +5,110 @@
client code.
[***] Changes requiring important modifications to existing client code.
- April, 2002
+
+ July 31st, 2002
+
+ - Release of version 1.2.6
+
+ - Addition of new options in JMSAppender and new command line arguments in
+ JMSSink. [*]
+
+ - Added new method getLoggerName() in LoggingEvent class. The
+ getLoggerName is the preferred way for accessing the logger
+ name. The public access categoryName field should not be accessed
+ directly. Similarly, added the getLevel method which is now the
+ preferred way of accessing the event's level. The public access
+ level field should not be accessd directly. The javadocs now mark
+ the categoryName and level fields as deprecated.
+
+ Modified existing appenders to comply with these new directives. [*]
+
+ - Log4j now will check if a system property named "log4j.ignoreTCL"
+ is set. If it is set, then it will ignore the Thread Context
+ ClassLoader when loading classes. This solves the irritating
+ "appender is not assignable to Appender" messages observed when
+ log4j.jar is loaded by multiple class loaders.
+
+ The error reporting for this problem was also improved. [*]
+
+ - Fixed bug #10528 whereby calling the MDC.get method with a null
+ argument would throw a NullPointerException. [*]
+
+ July 5th, 2002
+
+ - Release of version 1.2.5
+
+ - Minor changes and bug fixes in LF5. [*]
+
+ - Calling an AsyncAppender close method also closes the embedded
+ appender instances. This resolves bug #10185 submitted by Paul
+ Voutier. [*]
+
+ June 12th, 2002
+
+ - Release of version 1.2.4
+
+ - The JDBCAppender is marked as slated for replacement. Do not build
+ critical software using it.
+
+ - Added LF5 documentation and examples. Further tests are required
+ for full integration. [*]
+
+ - XMLLayout can now output messages which contain embedded CDATA
+ sections. This resolves bug #9750. Many thanks to Michael
+ A. McAngus for supplying the relevant patch. [*]
+
+ - The dispatcher thread associated with AsyncAppender is now marked
+ as a deamon thread. This resolves bug #9750. [*]
+
+ - Added missing NTEventLogAppender.dll as reported in bug #9606. [*]
+
+ - In response to bug report 9435, the log4j.dtd was changed so that
+ <log4j:event> is now made of logger and level attributes instead of
+ category and priority. Changed XMLLayout to conform to the
+ DTD. Chainsaw was changed to adapt to the XMLLayout. [*]
+
+ - Added missing LevelRangeFilter file. [*]
+
+ May 24th, 2002
+
+ - Release of version 1.2.3
+
+ - Fixed bug #9285 where the SyslogAppender would incorrectly compute
+ the length of the datagram to send to the remote syslogd host.
+ Reported by Mamoru Kadota. [*]
+
+ - Fixed bug #8505 where the stack trace of exception would not be
+ properly printed on the Compaq tru64 Unix platform. Initially
+ reported by Fabrice Claes and later by Espen H. Kolstad who also
+ provided the fix. [*]
+
+ May 22nd, 2002
+
+ - Release of version 1.2.2
+
+ - Log4j configurators take the "NULL" string value as a synonym for
+ "INHERITED". Both of these two strings are legal level values for
+ setting the level of a logger. Both values are case insensitive. [*]
+
+ - When loading component classes, log4j will now first attempt to use
+ the Thread Context Loader and if that fails, it will use
+ Class.forName. In log4j 1.2 and 1.2.1, only Class.forName was used
+ and the TCL was ignored. This change is a response to bug #9305
+ opened by Scott M. Stark. [*]
+
+ May 17th, 2002
+
+ - Release of version 1.2.1
+
+ - This minor release fixes bug #9155 reported by Nicko Cadell.
+ LoggingEvent.getMDCCopy() method now sets mdcCopyLookupRequired
+ instead of ndcLookupRequired. This bug would cause the wrong MDC
+ information to appear on a log server. It could only occur if the
+ client wrapped an AsyncAppender around a SocketAppender or if the
+ server used an AsyncAppender for its logging. [*]
+
+ May, 2002
- Release of version 1.2
diff --git a/docs/lf5/images/blue_on_white.gif b/docs/lf5/images/blue_on_white.gif
new file mode 100644
index 0000000..caeb5fa
--- /dev/null
+++ b/docs/lf5/images/blue_on_white.gif
Binary files differ
diff --git a/docs/lf5/images/console_window.gif b/docs/lf5/images/console_window.gif
new file mode 100644
index 0000000..315a7c5
--- /dev/null
+++ b/docs/lf5/images/console_window.gif
Binary files differ
diff --git a/docs/lf5/images/lf5.gif b/docs/lf5/images/lf5.gif
new file mode 100644
index 0000000..71c4c08
--- /dev/null
+++ b/docs/lf5/images/lf5.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_about.gif b/docs/lf5/images/lf5_about.gif
new file mode 100644
index 0000000..206b545
--- /dev/null
+++ b/docs/lf5/images/lf5_about.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_category_explorer.gif b/docs/lf5/images/lf5_category_explorer.gif
new file mode 100644
index 0000000..0adf254
--- /dev/null
+++ b/docs/lf5/images/lf5_category_explorer.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_collapseall.gif b/docs/lf5/images/lf5_collapseall.gif
new file mode 100644
index 0000000..c32a665
--- /dev/null
+++ b/docs/lf5/images/lf5_collapseall.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_colorchooser.gif b/docs/lf5/images/lf5_colorchooser.gif
new file mode 100644
index 0000000..4bb0447
--- /dev/null
+++ b/docs/lf5/images/lf5_colorchooser.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_compactview.gif b/docs/lf5/images/lf5_compactview.gif
new file mode 100644
index 0000000..fd84c92
--- /dev/null
+++ b/docs/lf5/images/lf5_compactview.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_configure.gif b/docs/lf5/images/lf5_configure.gif
new file mode 100644
index 0000000..5855c26
--- /dev/null
+++ b/docs/lf5/images/lf5_configure.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_deselectall.gif b/docs/lf5/images/lf5_deselectall.gif
new file mode 100644
index 0000000..943c460
--- /dev/null
+++ b/docs/lf5/images/lf5_deselectall.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_detailedview.gif b/docs/lf5/images/lf5_detailedview.gif
new file mode 100644
index 0000000..cc61b25
--- /dev/null
+++ b/docs/lf5/images/lf5_detailedview.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_expandall.gif b/docs/lf5/images/lf5_expandall.gif
new file mode 100644
index 0000000..69f450c
--- /dev/null
+++ b/docs/lf5/images/lf5_expandall.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_loglevels.gif b/docs/lf5/images/lf5_loglevels.gif
new file mode 100644
index 0000000..204a029
--- /dev/null
+++ b/docs/lf5/images/lf5_loglevels.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_logo.gif b/docs/lf5/images/lf5_logo.gif
new file mode 100644
index 0000000..3fc62b7
--- /dev/null
+++ b/docs/lf5/images/lf5_logo.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_logo_small.gif b/docs/lf5/images/lf5_logo_small.gif
new file mode 100644
index 0000000..c6fa96d
--- /dev/null
+++ b/docs/lf5/images/lf5_logo_small.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_logtable.gif b/docs/lf5/images/lf5_logtable.gif
new file mode 100644
index 0000000..c804d17
--- /dev/null
+++ b/docs/lf5/images/lf5_logtable.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_ndc_filtering.gif b/docs/lf5/images/lf5_ndc_filtering.gif
new file mode 100644
index 0000000..e44fc2f
--- /dev/null
+++ b/docs/lf5/images/lf5_ndc_filtering.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_openfile.gif b/docs/lf5/images/lf5_openfile.gif
new file mode 100644
index 0000000..4ca07c5
--- /dev/null
+++ b/docs/lf5/images/lf5_openfile.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_openurl.gif b/docs/lf5/images/lf5_openurl.gif
new file mode 100644
index 0000000..91a4765
--- /dev/null
+++ b/docs/lf5/images/lf5_openurl.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_properties.gif b/docs/lf5/images/lf5_properties.gif
new file mode 100644
index 0000000..1758d1f
--- /dev/null
+++ b/docs/lf5/images/lf5_properties.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_recorddetail.gif b/docs/lf5/images/lf5_recorddetail.gif
new file mode 100644
index 0000000..cd7c942
--- /dev/null
+++ b/docs/lf5/images/lf5_recorddetail.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_remove_categories.gif b/docs/lf5/images/lf5_remove_categories.gif
new file mode 100644
index 0000000..0c45926
--- /dev/null
+++ b/docs/lf5/images/lf5_remove_categories.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_search.gif b/docs/lf5/images/lf5_search.gif
new file mode 100644
index 0000000..bd218ab
--- /dev/null
+++ b/docs/lf5/images/lf5_search.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_selectall.gif b/docs/lf5/images/lf5_selectall.gif
new file mode 100644
index 0000000..e8224a5
--- /dev/null
+++ b/docs/lf5/images/lf5_selectall.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_small.gif b/docs/lf5/images/lf5_small.gif
new file mode 100644
index 0000000..0c6fc10
--- /dev/null
+++ b/docs/lf5/images/lf5_small.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_standardview.gif b/docs/lf5/images/lf5_standardview.gif
new file mode 100644
index 0000000..5dffd91
--- /dev/null
+++ b/docs/lf5/images/lf5_standardview.gif
Binary files differ
diff --git a/docs/lf5/images/lf5_view.gif b/docs/lf5/images/lf5_view.gif
new file mode 100644
index 0000000..dace2eb
--- /dev/null
+++ b/docs/lf5/images/lf5_view.gif
Binary files differ
diff --git a/docs/lf5/images/small_right_arrow.gif b/docs/lf5/images/small_right_arrow.gif
new file mode 100644
index 0000000..deca2b4
--- /dev/null
+++ b/docs/lf5/images/small_right_arrow.gif
Binary files differ
diff --git a/docs/manual.html b/docs/manual.html
index 50c5331..69e8eed 100644
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -90,7 +90,7 @@
application. If too verbose, it can cause scrolling blindness. To
alleviate these concerns, log4j is designed to be reliable, fast and
extensible. Since logging is rarely the main focus of an application,
-log4j API strives to be simple to understand and to use.
+the log4j API strives to be simple to understand and to use.
<h2>Loggers, Appenders and Layouts</h2>
@@ -114,13 +114,13 @@
earlier versions of log4j, the <code>Logger</code> class can be
considered as a mere alias to the <code>Category</code> class.
-<p> Loggers are named entities. Logger names are case-sensitive and
+<p>Loggers are named entities. Logger names are case-sensitive and
they follow the hierarchical naming rule:
<p>
<table bgcolor="#EEEE99">
<tr>
- <td>
+ <td>
<dl>
<dt><b>Named Hierarchy</b>
@@ -142,11 +142,11 @@
should be familiar to most developers.
<p>The root logger resides at the top of the logger hierarchy. It
-is exceptional in two ways:
+is exceptional in two ways:
<ol>
<li> it always exists,
-<li> it cannot be retrieved by name.
+<li> it cannot be retrieved by name.
</ol>
<p>Invoking the class static <a
href="api/org/apache/log4j/Logger.html#getRootLogger()">Logger.getRootLogger</a>
@@ -162,18 +162,19 @@
<td>
<pre>
package org.apache.log4j;
-
+
public class <b>Logger</b> {
-
+
// Creation & retrieval methods:
public static Logger getRootLogger();
public static Logger getLogger(String name);
-
+
// printing methods:
public void debug(Object message);
public void info(Object message);
public void warn(Object message);
public void error(Object message);
+ public void fatal(Object message);
// generic printing method:
public void log(Level l, Object message);
@@ -183,19 +184,19 @@
</table>
<p>Loggers <em>may</em> be assigned levels. The set of possible
-levels, that is
+levels, that is
-<a href="api/org/apache/log4j/Level.html#DEBUG">DEBUG</a>,
-<a href="api/org/apache/log4j/Level.html#INFO">INFO</a>,
-<a href="api/org/apache/log4j/Level.html#WARN">WARN</a>,
-<a href="api/org/apache/log4j/Level.html#ERROR">ERROR</a> and
-<a href="api/org/apache/log4j/Level.html#FATAL">FATAL</a>
+<a href="api/org/apache/log4j/Level.html#DEBUG">DEBUG</a>,
+<a href="api/org/apache/log4j/Level.html#INFO">INFO</a>,
+<a href="api/org/apache/log4j/Level.html#WARN">WARN</a>,
+<a href="api/org/apache/log4j/Level.html#ERROR">ERROR</a> and
+<a href="api/org/apache/log4j/Level.html#FATAL">FATAL</a>
are defined in the <code><a
href="api/org/apache/log4j/Level.html">org.apache.log4j.Level</a></code>
-class. Although we do not encourage you from doing so, you may define
+class. Although we do not encourage you to do so, you may define
your own levels by sub-classing the <code>Level</code> class. A
-perhaps better approach is will be explained later on.
+perhaps better approach will be explained later on.
<p>If a given logger is not assigned a level, then it inherits
one from its closest ancestor with an assigned level. More
@@ -205,7 +206,7 @@
<p>
<table bgcolor="#EEEE99">
<tr>
- <td>
+ <td>
<dl>
<dt><b>Level Inheritance</b>
@@ -231,10 +232,10 @@
<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>
+ <caption align=bottom>Example 1</caption>
</table>
-<p>In example 1 above, only the root logger is assinged a
+<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>.
@@ -288,17 +289,17 @@
<p>Logging requests are made by invoking one of the printing methods
-of a logger instance. These printing methods are
+of a logger instance. These printing methods are
<code>
<a href="api/org/apache/log4j/Logger.html#debug(java.lang.Object)">debug</a>,
-<a href="api/org/apache/log4j/Logger.html#info(java.lang.Object)">info</a>,
+<a href="api/org/apache/log4j/Logger.html#info(java.lang.Object)">info</a>,
-<a href="api/org/apache/log4j/Logger.html#warn(java.lang.Object)">warn</a>,
+<a href="api/org/apache/log4j/Logger.html#warn(java.lang.Object)">warn</a>,
<a href="api/org/apache/log4j/Logger.html#error(java.lang.Object)">error</a>,
<a href="api/org/apache/log4j/Logger.html#fatal(java.lang.Object)">fatal</a>
- and <a href="api/org/apache/log4j/Logger.html#log(org.apache.log4j.Level, java.lang.Object)">log</a></code>.
+ and <a href="api/org/apache/log4j/Logger.html#log(org.apache.log4j.Level, java.lang.Object)">log</a></code>.
<p>By definition, the printing method determines the level of a
@@ -321,8 +322,8 @@
<dt><b>Basic Selection Rule</b>
<dd><p>A log request of level <i>p</i> in a logger with
- inherited level <i>q</i>, is enabled if <i> p >=
- q</i>.
+ (either assigned or inherited, whichever is appropriate) level <i>q</i>, is enabled if <i> p >=
+ q</i>.
</dl>
</table>
@@ -330,7 +331,7 @@
ordered. For the standard levels, we have <code>DEBUG < INFO
< WARN < ERROR < FATAL</code>.
-<p>Here is an example of this rule.
+<p>Here is an example of this rule.
<p><table bgcolor="CCCCCC">
<tr><td>
@@ -339,35 +340,35 @@
// get a logger instance named "com.foo"
Logger logger = Logger.getLogger(<strong>"com.foo"</strong>);
- // Now set its level. Normally you do not need to set the
- // level of a logger progamitcally. This is usually done
+ // 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>Level.INFO</strong></font>);
Logger barlogger = Logger.getLogger(<strong>"com.foo.Bar"</strong>);
-
+
// This request is enabled, because <font color="00AA00"><strong>WARN</strong></font> >= <font color="0000AA"><strong>INFO</strong></font>.
logger.<font color="00AA00"><strong>warn</strong></font>("Low fuel level.");
-
- // This request is disabled, because <font color="00AA00"><strong>DEBUG</strong></font> < <font color="0000AA"><strong>INFO</strong></font>.
- logger.<font color="00AA00"><strong>debug</strong></font>("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> >= <font color="0000AA"><strong>INFO</strong></font>.
- barlogger.<font color="00AA00"><strong>info</strong></font>("Located nearest gas station.");
// This request is disabled, because <font color="00AA00"><strong>DEBUG</strong></font> < <font color="0000AA"><strong>INFO</strong></font>.
- barlogger.<font color="00AA00"><strong>debug</strong></font>("Exiting gas station search");
+ logger.<font color="00AA00"><strong>debug</strong></font>("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> >= <font color="0000AA"><strong>INFO</strong></font>.
+ barlogger.<font color="00AA00"><strong>info</strong></font>("Located nearest gas station.");
+
+ // This request is disabled, because <font color="00AA00"><strong>DEBUG</strong></font> < <font color="0000AA"><strong>INFO</strong></font>.
+ barlogger.<font color="00AA00"><strong>debug</strong></font>("Exiting gas station search");
</pre>
-</table>
+</table>
<p>Calling the <code>getLogger</code> method with the same name will
-always return a reference to the exact same logger object.
+always return a reference to the exact same logger object.
-<p>For example, in
+<p>For example, in
<table bgcolor="CCCCCC">
<tr><td>
@@ -422,7 +423,7 @@
Event Loggers</a>, and remote UNIX <a
href="api/org/apache/log4j/net/SyslogAppender.html">Syslog</a>
daemons. It is also possible to log <a href="api/org/apache/log4j/AsyncAppender.html">asynchronously</a>.
-
+
<p>More than one appender can be attached to a logger.
<p>The <a
@@ -486,14 +487,14 @@
<tr><td>x.y <td>none <td>true <td>A1, A-x1, A-x2
<td>Appenders of "x" and root.
-<tr><td>x.y.z <td>A-xyz1 <td>true <td>A1, A-x1, A-x2, A-xyz1
+<tr><td>x.y.z <td>A-xyz1 <td>true <td>A1, A-x1, A-x2, A-xyz1
<td>Appenders in "x.y.z", "x" and root.
-<tr><td>security <td>A-sec <td><font color="blue">false</font>
+<tr><td>security <td>A-sec <td><font color="blue">false</font>
<td>A-sec
<td>No appender accumulation since the additivity flag is set to
- <code>false</code>.
+ <code>false</code>.
<tr><td>security.access <td>none <td> true <td> A-sec <td>Only
appenders of "security" because the additivity flag in "security" is
@@ -507,7 +508,7 @@
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.
+to its destination.
The <a
href="api/org/apache/log4j/PatternLayout.html">PatternLayout</a>, part
@@ -533,7 +534,7 @@
frequently need to log <code>Oranges</code>, an object type used in
your current project, then you can register an
<code>OrangeRenderer</code> that will be invoked whenever an orange
-needs to be logged.
+needs to be logged.
<p>Object rendering follows the class hierarchy. For example, assuming
oranges are fruits, if you register an <code>FruitRenderer</code>, all
@@ -570,7 +571,7 @@
// Import log4j classes.
<b>import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;</b>
-
+
public class MyApp {
// Define a static logger variable so that it references the
@@ -585,7 +586,7 @@
logger.info("Entering application.");
Bar bar = new Bar();
bar.doIt();
- logger.info("Exiting application.");
+ logger.info("Exiting application.");
}
}
</pre>
@@ -603,12 +604,12 @@
<pre>
<b>package com.foo;</b>
import org.apache.log4j.Logger;
-
+
public class Bar {
<strong>static</strong> Logger logger = <strong>Logger.getLogger(Bar.class);</strong>
-
+
public void doIt() {
- logger.debug("Did it again!");
+ logger.debug("Did it again!");
}
}
</pre>
@@ -624,7 +625,7 @@
to the pattern "%-4r [%t] %-5p %c %x - %m%n".
<p>Note that by default, the root logger is assigned to
-<code>Level.DEBUG</code>.
+<code>Level.DEBUG</code>.
<p>The output of MyApp is:
<pre>
@@ -635,7 +636,7 @@
<p>The figure below depicts the object diagram of <code>MyApp</code>
after just having called the <code>BasicConfigurator.configure</code>
-method.
+method.
<p>
<center>
@@ -658,7 +659,7 @@
<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.
+version.
<p><table bgcolor="CCCCCC"><tr><td>
<pre>
@@ -666,21 +667,21 @@
import org.apache.log4j.Logger;
<b>import org.apache.log4j.PropertyConfigurator;</b>
-
+
public class MyApp {
static Logger logger = Logger.getLogger(MyApp.class.getName());
public static void main(String[] args) {
-
+
// BasicConfigurator replaced with PropertyConfigurator.
<strong>PropertyConfigurator.configure(args[0]);</strong>
logger.info("Entering application.");
Bar bar = new Bar();
bar.doIt();
- logger.info("Exiting application.");
+ logger.info("Exiting application.");
}
}
</pre>
@@ -697,10 +698,10 @@
<pre>
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1
-
-# A1 is set to be a ConsoleAppender.
+
+# 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
@@ -721,10 +722,10 @@
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>
@@ -813,9 +814,9 @@
<ol>
- <li>Skip default initialization if the system property
- <b>log4j.defaultInitOverride</b> is set to any value other than
- "false".
+ <li>Setting the <b>log4j.defaultInitOverride</b> system property to
+ any other value then "false" will cause log4j to skip the default
+ initialization procedure (this procedure).
<p><li>Set the <code>resource</code> string variable to the value of
the <b>log4j.configuration</b> system property. <em>The preferred
@@ -932,7 +933,7 @@
tells log4j to use the file <code>c:\foobar.lcf</code> as the default
configuration file. The configuration file is fully specified by the
URL <code>file:/c:/foobar.lcf</code>. Thus, the same configuration
-file will be used for all web-applications.
+file will be used for all web-applications.
<p>Different web-applications will load the log4j classes through
@@ -963,9 +964,9 @@
import java.io.IOException;
public class Log4jInit extends HttpServlet {
-
+
public
- void <b>init()</b> {
+ void <b>init()</b> {
String prefix = getServletContext().getRealPath("/");
String file = getInitParameter("log4j-init-file");
// if the log4j-init-file is not set, then no point in trying
@@ -1029,19 +1030,19 @@
<em>Nested Diagnostic Context</em>. The NDC class is shown below.
<pre>
- public class NDC {
- // Used when printing the diagnostic
- public <strong>static</strong> String get();
-
+ public class NDC {
+ // Used when printing the diagnostic
+ public <strong>static</strong> String get();
+
// Remove the top of the context from the NDC.
- public <strong>static</strong> String pop();
-
+ public <strong>static</strong> String pop();
+
// Add diagnostic context for the current thread.
- public <strong>static</strong> void push(String message);
-
- // Remove the diagnostic context for this thread.
- public <strong>static</strong> void remove();
- }
+ public <strong>static</strong> void push(String message);
+
+ // Remove the diagnostic context for this thread.
+ public <strong>static</strong> void remove();
+ }
</pre>
<p>The NDC is managed per thread as a <em>stack</em> of contextual
@@ -1096,7 +1097,7 @@
machine this cost is typically in the 5 to 50 nanosecond range.
<p>However, The method invocation involves the "hidden" cost of
- parameter construction.
+ parameter construction.
<p>For example, for some logger <code>cat</code>, writing,
<pre>
@@ -1113,12 +1114,12 @@
<p>To avoid the parameter construction cost write:
- <pre>
+ <pre>
if(logger.isDebugEnabled() {
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}
</pre>
-
+
<p>This will not incur the cost of parameter
construction if debugging is disabled. On the other hand, if
the logger is debug-enabled, it will incur twice the cost of
@@ -1127,7 +1128,7 @@
<code>debug</code>. This is an insignificant
overhead because evaluating a logger takes about 1%
of the time it takes to actually log.
-
+
<p>In log4j, logging requests are made to instances of the Logger
class. Logger is a class and not an interface. This measurably
reduces the cost of method invocation at the cost of some
diff --git a/examples/lf5/InitUsingDefaultConfigurator/InitUsingDefaultConfigurator.java b/examples/lf5/InitUsingDefaultConfigurator/InitUsingDefaultConfigurator.java
new file mode 100644
index 0000000..e089069
--- /dev/null
+++ b/examples/lf5/InitUsingDefaultConfigurator/InitUsingDefaultConfigurator.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file.
+ */
+package examples.lf5.InitUsingDefaultConfigurator;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.NDC;
+import org.apache.log4j.lf5.DefaultLF5Configurator;
+
+import java.io.IOException;
+
+/**
+ * This class is a simple example of how to configure the LogFactor5
+ * logging window using the DefaultLF5Configurator.
+ *
+ * The DefaultLF5Configurator uses a default configuration file stored
+ * in the log4j.jar in order to provide a default configuration for
+ * the LF5Appender.
+ *
+ * @author Brent Sprecher
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class InitUsingDefaultConfigurator {
+ //--------------------------------------------------------------------------
+ // Constants:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Protected Variables:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Variables:
+ //--------------------------------------------------------------------------
+ private static Logger logger =
+ Logger.getLogger(InitUsingDefaultConfigurator.class);
+
+ //--------------------------------------------------------------------------
+ // Constructors:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Public Methods:
+ //--------------------------------------------------------------------------
+
+ public static void main(String[] args) throws IOException {
+ // Configure the LF5Appender using the DefaultLF5Configurator. This
+ // will add the LF5Appender to the root of the Category tree.
+ DefaultLF5Configurator.configure();
+
+ // Add an NDC to demonstrate how NDC information is output.
+ NDC.push("#23856");
+ // Log some information.
+ for (int i = 0; i < 10; i++) {
+ logger.debug("Hello, my name is Homer Simpson.");
+ logger.info("Mmmmmm .... Chocolate.");
+ logger.warn("Mmm...forbidden donut.");
+ }
+ // Clean up NDC
+ NDC.pop();
+ NDC.remove();
+
+ NDC.push("Another NDC");
+ // Log some information.
+ logger.fatal("Hello, my name is Bart Simpson.");
+ logger.error("Hi diddly ho good neighbour.");
+ // Clean up NDC
+ NDC.pop();
+ NDC.remove();
+
+ // Call methods on both classes.
+ InitUsingDefaultConfigurator.foo();
+ InnerInitUsingDefaultConfigurator.foo();
+
+ logger.info("Exiting InitUsingDefaultConfigurator.");
+
+ }
+
+ public static void foo() {
+ logger.debug("Entered foo in InitUsingDefaultConfigurator class");
+
+ NDC.push("#123456");
+ logger.debug("Hello, my name is Marge Simpson.");
+ logger.info("D'oh!! A deer! A female deer.");
+ // Clean up NDC
+ NDC.pop();
+ NDC.remove();
+ }
+
+ //--------------------------------------------------------------------------
+ // Protected Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Nested Top-Level Classes or Interfaces:
+ //--------------------------------------------------------------------------
+
+ public static class InnerInitUsingDefaultConfigurator {
+ static Logger logger =
+ Logger.getLogger(InnerInitUsingDefaultConfigurator.class.getName());
+
+ static void foo() throws IOException {
+ // Configure the LF5Appender again. You can call
+ // DefaultLF5Configurator.configure() as often as you want
+ // without unexpected behavior.
+ DefaultLF5Configurator.configure();
+
+ logger.info("Entered foo in InnerInitUsingDefaultConfigurator class.");
+ }
+ }
+}
+
+
+
+
+
diff --git a/examples/lf5/InitUsingLog4JProperties/InitUsingLog4JProperties.java b/examples/lf5/InitUsingLog4JProperties/InitUsingLog4JProperties.java
new file mode 100644
index 0000000..2679d6d
--- /dev/null
+++ b/examples/lf5/InitUsingLog4JProperties/InitUsingLog4JProperties.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file.
+ */
+package examples.lf5.InitUsingLog4JProperties;
+
+import org.apache.log4j.Logger;
+
+import java.io.IOException;
+
+/**
+ * This class is a simple example of how to use the LogFactor5 logging
+ * window.
+ *
+ * The LF5Appender is the primary class that enables logging to the
+ * LogFactor5 logging window. The simplest method of using this Appender
+ * is to add the following line to your log4j.properties file:
+ *
+ * log4j.appender.A1=org.apache.log4j.lf5.LF5Appender
+ *
+ * The log4j.properties file MUST be in you system classpath. If this file
+ * is in your system classpath, a static initializer in the Category class
+ * will load the file during class initialization. The LF5Appender will be
+ * added to the root category of the Category tree.
+ *
+ * Create a log4j.properties file and add this line to it, or add this line
+ * to your existing log4j.properties file. Run the example at the command line
+ * and explore the results!
+ *
+ * @author Brent Sprecher
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class InitUsingLog4JProperties {
+ //--------------------------------------------------------------------------
+ // Constants:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Protected Variables:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Variables:
+ //--------------------------------------------------------------------------
+
+ private static Logger logger =
+ Logger.getLogger(InitUsingLog4JProperties.class);
+
+ //--------------------------------------------------------------------------
+ // Constructors:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Public Methods:
+ //--------------------------------------------------------------------------
+
+ public static void main(String argv[]) {
+ // Add a bunch of logging statements ...
+ logger.debug("Hello, my name is Homer Simpson.");
+ logger.debug("Hello, my name is Lisa Simpson.");
+ logger.debug("Hello, my name is Marge Simpson.");
+ logger.debug("Hello, my name is Bart Simpson.");
+ logger.debug("Hello, my name is Maggie Simpson.");
+
+ logger.info("We are the Simpsons!");
+ logger.info("Mmmmmm .... Chocolate.");
+ logger.info("Homer likes chocolate");
+ logger.info("Doh!");
+ logger.info("We are the Simpsons!");
+
+ logger.warn("Bart: I am through with working! Working is for chumps!" +
+ "Homer: Son, I'm proud of you. I was twice your age before " +
+ "I figured that out.");
+ logger.warn("Mmm...forbidden donut.");
+ logger.warn("D'oh! A deer! A female deer!");
+ logger.warn("Truly, yours is a butt that won't quit." +
+ "- Bart, writing as Woodrow to Ms. Krabappel.");
+
+ logger.error("Dear Baby, Welcome to Dumpsville. Population: you.");
+ logger.error("Dear Baby, Welcome to Dumpsville. Population: you.",
+ new IOException("Dumpsville, USA"));
+ logger.error("Mr. Hutz, are you aware you're not wearing pants?");
+ logger.error("Mr. Hutz, are you aware you're not wearing pants?",
+ new IllegalStateException("Error !!"));
+
+
+ logger.fatal("Eep.");
+ logger.fatal("Mmm...forbidden donut.",
+ new SecurityException("Fatal Exception"));
+ logger.fatal("D'oh! A deer! A female deer!");
+ logger.fatal("Mmmmmm .... Chocolate.",
+ new SecurityException("Fatal Exception"));
+ }
+
+ //--------------------------------------------------------------------------
+ // Protected Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Nested Top-Level Classes or Interfaces:
+ //--------------------------------------------------------------------------
+
+}
diff --git a/examples/lf5/InitUsingLog4JProperties/log4j.properties b/examples/lf5/InitUsingLog4JProperties/log4j.properties
new file mode 100644
index 0000000..98b54b5
--- /dev/null
+++ b/examples/lf5/InitUsingLog4JProperties/log4j.properties
@@ -0,0 +1,17 @@
+# For the general syntax of property based configuration files see the
+# documenation of org.apache.log4j.PropertyConfigurator.
+
+# The root category uses the appender called A1. Since no priority is
+# specified, the root category assumes the default priority for root
+# which is DEBUG in log4j. The root category is the only category that
+# has a default priority. All other categories need not be assigned a
+# priority in which case they inherit their priority from the
+# hierarchy.
+
+log4j.rootCategory=, A1
+
+# A1 is set to be a LF5Appender which outputs to a swing
+# logging console.
+
+log4j.appender.A1=org.apache.log4j.lf5.LF5Appender
+log4j.appender.A1.MaxNumberOfRecords=1000
diff --git a/examples/lf5/InitUsingMultipleAppenders/InitUsingMultipleAppenders.java b/examples/lf5/InitUsingMultipleAppenders/InitUsingMultipleAppenders.java
new file mode 100644
index 0000000..c3d7a31
--- /dev/null
+++ b/examples/lf5/InitUsingMultipleAppenders/InitUsingMultipleAppenders.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file.
+ */
+package examples.lf5.InitUsingMultipleAppenders;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * This example shows how to use LogFactor5 with other Log4J appenders
+ * (In this case the RollingFileAppender).
+ *
+ * The following lines can be added to the log4j.properties file or a
+ * standard Java properties file.
+ *
+ * # Two appenders are registered with the root of the Category tree.
+ *
+ * log4j.rootCategory=, A1, R
+ *
+ * # A1 is set to be a LF5Appender which outputs to a swing
+ * # logging console.
+ *
+ * log4j.appender.A1=org.apache.log4j.lf5.LF5Appender
+ *
+ * # R is the RollingFileAppender that outputs to a rolling log
+ * # file called rolling_log_file.log.
+ *
+ * log4j.appender.R=org.apache.log4j.RollingFileAppender
+ * log4j.appender.R.File=rolling_log_file.log
+ *
+ * log4j.appender.R.layout=org.apache.log4j.PatternLayout
+ * log4j.appender.R.layout.ConversionPattern=Date - %d{DATE}%nPriority
+ * - %p%nThread - %t%nCategory - %c%nLocation - %l%nMessage - %m%n%n
+ * log4j.appender.R.MaxFileSize=100KB
+ * log4j.appender.R.MaxBackupIndex=1
+ *
+ * To make this example work, either run the InitUsingMultipleAppenders.bat
+ * file located in the examples folder or run it at the command line. If you
+ * are running the example at the command line, you must ensure that the
+ * example.properties file is in your classpath.
+ *
+ * @author Brent Sprecher
+ * @author Brad Marlborough
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class InitUsingMultipleAppenders {
+
+ //--------------------------------------------------------------------------
+ // Constants:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Protected Variables:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Variables:
+ //--------------------------------------------------------------------------
+
+ private static Logger logger =
+ Logger.getLogger(InitUsingMultipleAppenders.class);
+
+ //--------------------------------------------------------------------------
+ // Constructors:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Public Methods:
+ //--------------------------------------------------------------------------
+
+ public static void main(String argv[]) {
+ // Use a PropertyConfigurator to initialize from a property file.
+ String resource =
+ "/examples/lf5/InitUsingMultipleAppenders/example.properties";
+ URL configFileResource =
+ InitUsingMultipleAppenders.class.getResource(resource);
+ PropertyConfigurator.configure(configFileResource);
+
+ // Add a bunch of logging statements ...
+ logger.debug("Hello, my name is Homer Simpson.");
+ logger.debug("Hello, my name is Lisa Simpson.");
+ logger.debug("Hello, my name is Marge Simpson.");
+ logger.debug("Hello, my name is Bart Simpson.");
+ logger.debug("Hello, my name is Maggie Simpson.");
+
+ logger.info("We are the Simpsons!");
+ logger.info("Mmmmmm .... Chocolate.");
+ logger.info("Homer likes chocolate");
+ logger.info("Doh!");
+ logger.info("We are the Simpsons!");
+
+ logger.warn("Bart: I am through with working! Working is for chumps!" +
+ "Homer: Son, I'm proud of you. I was twice your age before " +
+ "I figured that out.");
+ logger.warn("Mmm...forbidden donut.");
+ logger.warn("D'oh! A deer! A female deer!");
+ logger.warn("Truly, yours is a butt that won't quit." +
+ "- Bart, writing as Woodrow to Ms. Krabappel.");
+
+ logger.error("Dear Baby, Welcome to Dumpsville. Population: you.");
+ logger.error("Dear Baby, Welcome to Dumpsville. Population: you.",
+ new IOException("Dumpsville, USA"));
+ logger.error("Mr. Hutz, are you aware you're not wearing pants?");
+ logger.error("Mr. Hutz, are you aware you're not wearing pants?",
+ new IllegalStateException("Error !!"));
+
+
+ logger.fatal("Eep.");
+ logger.fatal("Mmm...forbidden donut.",
+ new SecurityException("Fatal Exception"));
+ logger.fatal("D'oh! A deer! A female deer!");
+ logger.fatal("Mmmmmm .... Chocolate.",
+ new SecurityException("Fatal Exception"));
+ }
+
+ //--------------------------------------------------------------------------
+ // Protected Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Nested Top-Level Classes or Interfaces:
+ //--------------------------------------------------------------------------
+
+}
diff --git a/examples/lf5/InitUsingMultipleAppenders/example.properties b/examples/lf5/InitUsingMultipleAppenders/example.properties
new file mode 100644
index 0000000..ac1f374
--- /dev/null
+++ b/examples/lf5/InitUsingMultipleAppenders/example.properties
@@ -0,0 +1,34 @@
+# For the general syntax of property based configuration files see the
+# documenation of org.apache.log4j.PropertyConfigurator.
+
+# The root category uses two appenders called A1 and R. Since no priority is
+# specified, the root category assumes the default priority for root
+# which is DEBUG in log4j. The root category is the only category that
+# has a default priority. All other categories need not be assigned a
+# priority in which case they inherit their priority from the
+# hierarchy.
+
+log4j.rootCategory=, A1, R
+
+# A1 is set to be a LF5Appender which outputs to a swing
+# logging console.
+
+log4j.appender.A1=org.apache.log4j.lf5.LF5Appender
+
+# R is the RollingFileAppender that outputs to a rolling log
+# file called rolling_log_file.log.
+
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=rolling_log_file.log
+
+# Define a pattern layout for the file.
+# For more information on conversion characters (i.e. d,p,t,c,l,m,n)
+# please see the PatternLayout class of the Log4j API.
+
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=[slf5s.start]%d{DATE}[slf5s.DATE]%n%p[slf5s.PRIORITY]%n%x[slf5s.NDC]%n%t[slf5s.THREAD]%n%c[slf5s.CATEGORY]%n%l[slf5s.LOCATION]%n%m[slf5s.MESSAGE]%n%n
+
+# Set the max size of the file and the number of backup files
+
+log4j.appender.R.MaxFileSize=100KB
+log4j.appender.R.MaxBackupIndex=1
\ No newline at end of file
diff --git a/examples/lf5/InitUsingPropertiesFile/InitUsingPropertiesFile.java b/examples/lf5/InitUsingPropertiesFile/InitUsingPropertiesFile.java
new file mode 100644
index 0000000..71abb94
--- /dev/null
+++ b/examples/lf5/InitUsingPropertiesFile/InitUsingPropertiesFile.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file.
+ */
+package examples.lf5.InitUsingPropertiesFile;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * This is another simple example of how to use the LogFactor5
+ * logging console.
+ *
+ * The LF5Appender is the primary class that enables logging to the
+ * LogFactor5 logging window. If the following line is added to a properties
+ * file, the LF5Appender will be appended to the root category when
+ * the properties file is loaded:
+ *
+ * log4j.appender.A1=org.apache.log4j.lf5.LF5Appender
+ *
+ * To make this example work, you must ensure that the example.properties file
+ * is in your classpath.You can then run the example at the command line.
+ *
+ * @author Brent Sprecher
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class InitUsingPropertiesFile {
+ //--------------------------------------------------------------------------
+ // Constants:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Protected Variables:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Variables:
+ //--------------------------------------------------------------------------
+
+ private static Logger logger =
+ Logger.getLogger(InitUsingPropertiesFile.class);
+
+ //--------------------------------------------------------------------------
+ // Constructors:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Public Methods:
+ //--------------------------------------------------------------------------
+
+ public static void main(String argv[]) {
+ // Use a PropertyConfigurator to initialize from a property file.
+ String resource =
+ "/examples/lf5/InitUsingPropertiesFile/example.properties";
+ URL configFileResource =
+ InitUsingPropertiesFile.class.getResource(resource);
+ PropertyConfigurator.configure(configFileResource);
+
+ // Add a bunch of logging statements ...
+ logger.debug("Hello, my name is Homer Simpson.");
+ logger.debug("Hello, my name is Lisa Simpson.");
+ logger.debug("Hello, my name is Marge Simpson.");
+ logger.debug("Hello, my name is Bart Simpson.");
+ logger.debug("Hello, my name is Maggie Simpson.");
+
+ logger.info("We are the Simpsons!");
+ logger.info("Mmmmmm .... Chocolate.");
+ logger.info("Homer likes chocolate");
+ logger.info("Doh!");
+ logger.info("We are the Simpsons!");
+
+ logger.warn("Bart: I am through with working! Working is for chumps!" +
+ "Homer: Son, I'm proud of you. I was twice your age before " +
+ "I figured that out.");
+ logger.warn("Mmm...forbidden donut.");
+ logger.warn("D'oh! A deer! A female deer!");
+ logger.warn("Truly, yours is a butt that won't quit." +
+ "- Bart, writing as Woodrow to Ms. Krabappel.");
+
+ logger.error("Dear Baby, Welcome to Dumpsville. Population: you.");
+ logger.error("Dear Baby, Welcome to Dumpsville. Population: you.",
+ new IOException("Dumpsville, USA"));
+ logger.error("Mr. Hutz, are you aware you're not wearing pants?");
+ logger.error("Mr. Hutz, are you aware you're not wearing pants?",
+ new IllegalStateException("Error !!"));
+
+
+ logger.fatal("Eep.");
+ logger.fatal("Mmm...forbidden donut.",
+ new SecurityException("Fatal Exception"));
+ logger.fatal("D'oh! A deer! A female deer!");
+ logger.fatal("Mmmmmm .... Chocolate.",
+ new SecurityException("Fatal Exception"));
+ }
+
+ //--------------------------------------------------------------------------
+ // Protected Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Nested Top-Level Classes or Interfaces:
+ //--------------------------------------------------------------------------
+
+}
diff --git a/examples/lf5/InitUsingPropertiesFile/example.properties b/examples/lf5/InitUsingPropertiesFile/example.properties
new file mode 100644
index 0000000..ab421d3
--- /dev/null
+++ b/examples/lf5/InitUsingPropertiesFile/example.properties
@@ -0,0 +1,17 @@
+# For the general syntax of property based configuration files see the
+# documenation of org.apache.log4j.PropertyConfigurator.
+
+# The root category uses the appender called A1. Since no priority is
+# specified, the root category assumes the default priority for root
+# which is DEBUG in log4j. The root category is the only category that
+# has a default priority. All other categories need not be assigned a
+# priority in which case they inherit their priority from the
+# hierarchy.
+
+log4j.rootCategory=, A1
+
+# A1 is set to be a LF5Appender which outputs to a swing
+# logging console.
+
+log4j.appender.A1=org.apache.log4j.lf5.LF5Appender
+log4j.appender.A1.MaxNumberOfRecords=700
diff --git a/examples/lf5/InitUsingXMLPropertiesFile/InitUsingXMLPropertiesFile.java b/examples/lf5/InitUsingXMLPropertiesFile/InitUsingXMLPropertiesFile.java
new file mode 100644
index 0000000..8b21c98
--- /dev/null
+++ b/examples/lf5/InitUsingXMLPropertiesFile/InitUsingXMLPropertiesFile.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file.
+ */
+package examples.lf5.InitUsingXMLPropertiesFile;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.xml.DOMConfigurator;
+
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * This is another simple example of how to use the LogFactor5
+ * logging console.
+ *
+ * To make this example work, ensure that the lf5.jar, lf5-license.jar
+ * and example.xml files are in your classpath. Once your classpath has
+ * been set up, you can run the example from the command line.
+ *
+ * @author Brent Sprecher
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class InitUsingXMLPropertiesFile {
+ //--------------------------------------------------------------------------
+ // Constants:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Protected Variables:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Variables:
+ //--------------------------------------------------------------------------
+
+ private static Logger logger =
+ Logger.getLogger(InitUsingXMLPropertiesFile.class);
+
+ //--------------------------------------------------------------------------
+ // Constructors:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Public Methods:
+ //--------------------------------------------------------------------------
+
+ public static void main(String argv[]) {
+ // Use a PropertyConfigurator to initialize from a property file.
+ String resource =
+ "/examples/lf5/InitUsingXMLPropertiesFile/example.xml";
+ URL configFileResource =
+ InitUsingXMLPropertiesFile.class.getResource(resource);
+ DOMConfigurator.configure(configFileResource.getFile());
+
+ // Add a bunch of logging statements ...
+ logger.debug("Hello, my name is Homer Simpson.");
+ logger.debug("Hello, my name is Lisa Simpson.");
+ logger.debug("Hello, my name is Marge Simpson.");
+ logger.debug("Hello, my name is Bart Simpson.");
+ logger.debug("Hello, my name is Maggie Simpson.");
+
+ logger.info("We are the Simpsons!");
+ logger.info("Mmmmmm .... Chocolate.");
+ logger.info("Homer likes chocolate");
+ logger.info("Doh!");
+ logger.info("We are the Simpsons!");
+
+ logger.warn("Bart: I am through with working! Working is for chumps!" +
+ "Homer: Son, I'm proud of you. I was twice your age before " +
+ "I figured that out.");
+ logger.warn("Mmm...forbidden donut.");
+ logger.warn("D'oh! A deer! A female deer!");
+ logger.warn("Truly, yours is a butt that won't quit." +
+ "- Bart, writing as Woodrow to Ms. Krabappel.");
+
+ logger.error("Dear Baby, Welcome to Dumpsville. Population: you.");
+ logger.error("Dear Baby, Welcome to Dumpsville. Population: you.",
+ new IOException("Dumpsville, USA"));
+ logger.error("Mr. Hutz, are you aware you're not wearing pants?");
+ logger.error("Mr. Hutz, are you aware you're not wearing pants?",
+ new IllegalStateException("Error !!"));
+
+
+ logger.fatal("Eep.");
+ logger.fatal("Mmm...forbidden donut.",
+ new SecurityException("Fatal Exception"));
+ logger.fatal("D'oh! A deer! A female deer!");
+ logger.fatal("Mmmmmm .... Chocolate.",
+ new SecurityException("Fatal Exception"));
+ }
+
+ //--------------------------------------------------------------------------
+ // Protected Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Nested Top-Level Classes or Interfaces:
+ //--------------------------------------------------------------------------
+
+}
diff --git a/examples/lf5/InitUsingXMLPropertiesFile/example.xml b/examples/lf5/InitUsingXMLPropertiesFile/example.xml
new file mode 100644
index 0000000..d167c5f
--- /dev/null
+++ b/examples/lf5/InitUsingXMLPropertiesFile/example.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration>
+
+ <appender name="LF5Appender" class="org.apache.log4j.lf5.LF5Appender">
+ <param name="MaxNumberOfRecords" value="1000"/>
+ </appender>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="LF5Appender"/>
+ </root>
+
+</log4j:configuration>
\ No newline at end of file
diff --git a/examples/lf5/OpeningLogFiles/sample.log b/examples/lf5/OpeningLogFiles/sample.log
new file mode 100644
index 0000000..1adbea5
--- /dev/null
+++ b/examples/lf5/OpeningLogFiles/sample.log
@@ -0,0 +1,184 @@
+[slf5s.start]26 Jul 2001 15:54:44,673[slf5s.DATE]
+DEBUG[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:102)[slf5s.LOCATION]
+Hello, my name is Homer Simpson.[slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,743[slf5s.DATE]
+DEBUG[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:103)[slf5s.LOCATION]
+Hello, my name is Lisa Simpson.[slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,743[slf5s.DATE]
+DEBUG[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:104)[slf5s.LOCATION]
+Hello, my name is Marge Simpson.[slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,753[slf5s.DATE]
+DEBUG[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:105)[slf5s.LOCATION]
+Hello, my name is Bart Simpson.[slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,793[slf5s.DATE]
+DEBUG[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:106)[slf5s.LOCATION]
+Hello, my name is Maggie Simpson.[slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,793[slf5s.DATE]
+INFO[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:108)[slf5s.LOCATION]
+We are the Simpsons![slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,803[slf5s.DATE]
+INFO[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:109)[slf5s.LOCATION]
+Mmmmmm .... Chocolate.[slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,803[slf5s.DATE]
+INFO[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:110)[slf5s.LOCATION]
+Homer likes chocolate[slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,803[slf5s.DATE]
+INFO[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:111)[slf5s.LOCATION]
+Doh![slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,803[slf5s.DATE]
+INFO[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:112)[slf5s.LOCATION]
+We are the Simpsons![slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,803[slf5s.DATE]
+WARN[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:114)[slf5s.LOCATION]
+Bart: I am through with working! Working is for chumps!Homer: Son, I'm proud of you. I was twice your age before I figured that out.[slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,803[slf5s.DATE]
+WARN[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:117)[slf5s.LOCATION]
+Mmm...forbidden donut.[slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,803[slf5s.DATE]
+WARN[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:118)[slf5s.LOCATION]
+D'oh! A deer! A female deer![slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,803[slf5s.DATE]
+WARN[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:119)[slf5s.LOCATION]
+Truly, yours is a butt that won't quit.- Bart, writing as Woodrow to Ms. Krabappel.[slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,803[slf5s.DATE]
+ERROR[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:122)[slf5s.LOCATION]
+Dear Baby, Welcome to Dumpsville. Population: you.[slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,903[slf5s.DATE]
+ERROR[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:123)[slf5s.LOCATION]
+Dear Baby, Welcome to Dumpsville. Population: you.[slf5s.MESSAGE]
+
+java.io.IOException: Dumpsville, USA
+ at examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:123)
+[slf5s.start]26 Jul 2001 15:54:44,903[slf5s.DATE]
+ERROR[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:125)[slf5s.LOCATION]
+Mr. Hutz, are you aware you're not wearing pants?[slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:44,903[slf5s.DATE]
+ERROR[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:126)[slf5s.LOCATION]
+Mr. Hutz, are you aware you're not wearing pants?[slf5s.MESSAGE]
+
+java.lang.IllegalStateException: Error !!
+ at examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:126)
+[slf5s.start]26 Jul 2001 15:54:44,903[slf5s.DATE]
+FATAL[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:130)[slf5s.LOCATION]
+Eep.[slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:45,063[slf5s.DATE]
+FATAL[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:131)[slf5s.LOCATION]
+Mmm...forbidden donut.[slf5s.MESSAGE]
+
+java.lang.SecurityException: Fatal Exception
+ at examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:131)
+[slf5s.start]26 Jul 2001 15:54:45,063[slf5s.DATE]
+FATAL[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:133)[slf5s.LOCATION]
+D'oh! A deer! A female deer![slf5s.MESSAGE]
+
+[slf5s.start]26 Jul 2001 15:54:45,063[slf5s.DATE]
+FATAL[slf5s.PRIORITY]
+[slf5s.NDC]
+main[slf5s.THREAD]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders[slf5s.CATEGORY]
+examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:134)[slf5s.LOCATION]
+Mmmmmm .... Chocolate.[slf5s.MESSAGE]
+
+java.lang.SecurityException: Fatal Exception
+ at examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders.main(InitUsingMultipleAppenders.java:134)
diff --git a/examples/lf5/UsingLogMonitorAdapter/CustomizedLogLevels.java b/examples/lf5/UsingLogMonitorAdapter/CustomizedLogLevels.java
new file mode 100644
index 0000000..832ed95
--- /dev/null
+++ b/examples/lf5/UsingLogMonitorAdapter/CustomizedLogLevels.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file.
+ */
+
+package examples.lf5.UsingLogMonitorAdapter;
+
+import org.apache.log4j.lf5.LogLevel;
+import org.apache.log4j.lf5.util.LogMonitorAdapter;
+
+/**
+ * This class is a simple example of how use the LogMonitorAdapter to
+ * bypass the Log4JAppender and post LogRecords directly to the LogMonitor
+ * using customized LogLevels
+ *
+ * To make this example work, ensure that the lf5.jar and lf5-license.jar
+ * files are in your classpath, and then run the example at the command line.
+ *
+ * @author Richard Hurst
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class CustomizedLogLevels {
+ //--------------------------------------------------------------------------
+ // Constants:
+ //--------------------------------------------------------------------------
+ public final static LogLevel LEVEL_ONE = new LogLevel("LEVEL 1", 1);
+ public final static LogLevel LEVEL_TWO = new LogLevel("LEVEL 2", 2);
+ public final static LogLevel LEVEL_THREE = new LogLevel("LEVEL 3", 3);
+ public final static LogLevel LEVEL_FOUR = new LogLevel("LEVEL 4", 4);
+ public final static LogLevel DEFAULT = new LogLevel("DEFAULT", 0);
+
+ //--------------------------------------------------------------------------
+ // Protected Variables:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Variables:
+ //--------------------------------------------------------------------------
+ private static LogMonitorAdapter _adapter;
+
+ static {
+ // The first LogLevel in the Array will be used as the default LogLevel.
+ _adapter = LogMonitorAdapter.newInstance(new LogLevel[]{DEFAULT, LEVEL_ONE,
+ LEVEL_TWO, LEVEL_THREE, LEVEL_FOUR, LogLevel.FATAL});
+ // if a different log level is to be used it can be specified as such
+ // _adapter.setDefaultLevel(LEVEL_THREE);
+ }
+ //--------------------------------------------------------------------------
+ // Constructors:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Public Methods:
+ //--------------------------------------------------------------------------
+
+ public static void main(String[] args) {
+ CustomizedLogLevels test = new CustomizedLogLevels();
+ test.doMyBidding();
+ }
+
+ public void doMyBidding() {
+ // tell the LogMonitorAdapter which LogLevel is the severe Level if necessary
+ _adapter.setSevereLevel(LEVEL_ONE);
+
+ String levels = this.getClass().getName();
+
+ // will used the default Level
+ _adapter.log(levels, "Using the customized LogLevels");
+
+ _adapter.log(levels, LEVEL_FOUR, "This is a test");
+ _adapter.log(levels, LEVEL_THREE, "Hmmm fobidden doughnut");
+ _adapter.log(levels, LEVEL_ONE, "Danger Danger Will Robinson",
+ new RuntimeException("DANGER"), "32");
+ _adapter.log(levels, LEVEL_TWO, "Exit stage right->");
+ _adapter.log(levels, LEVEL_FOUR, "What's up Doc?",
+ new NullPointerException("Unfortunate exception"));
+
+ }
+
+ //--------------------------------------------------------------------------
+ // Protected Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Nested Top-Level Classes or Interfaces:
+ //--------------------------------------------------------------------------
+}
+
+
+
+
+
diff --git a/examples/lf5/UsingLogMonitorAdapter/UsingLogMonitorAdapter.java b/examples/lf5/UsingLogMonitorAdapter/UsingLogMonitorAdapter.java
new file mode 100644
index 0000000..0484859
--- /dev/null
+++ b/examples/lf5/UsingLogMonitorAdapter/UsingLogMonitorAdapter.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file.
+ */
+package examples.lf5.UsingLogMonitorAdapter;
+
+import org.apache.log4j.lf5.LogLevel;
+import org.apache.log4j.lf5.util.AdapterLogRecord;
+import org.apache.log4j.lf5.util.LogMonitorAdapter;
+
+/**
+ * This class is a simple example of how use the LogMonitorAdapter to
+ * bypass the Log4JAppender and post LogRecords directly to the LogMonitor
+ *
+ * To make this example work, ensure that the lf5.jar and lf5-license.jar
+ * files are in your classpath, and then run the example at the command line.
+ *
+ * @author Richard Hurst
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class UsingLogMonitorAdapter {
+ //--------------------------------------------------------------------------
+ // Constants:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Protected Variables:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Variables:
+ //--------------------------------------------------------------------------
+ private static LogMonitorAdapter _adapter;
+
+ static {
+ _adapter = LogMonitorAdapter.newInstance(LogMonitorAdapter.LOG4J_LOG_LEVELS);
+ }
+ //--------------------------------------------------------------------------
+ // Constructors:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Public Methods:
+ //--------------------------------------------------------------------------
+
+ public static void main(String[] args) {
+ UsingLogMonitorAdapter test = new UsingLogMonitorAdapter();
+ test.doMyBidding();
+ }
+
+ public void doMyBidding() {
+ String logger = this.getClass().getName();
+
+ // will default to debug log level
+ _adapter.log(logger, "Doh this is a debugging");
+
+ _adapter.log(logger, LogLevel.INFO, "Hmmm fobidden doughnut");
+ _adapter.log(logger, LogLevel.WARN, "Danger Danger Will Robinson",
+ new RuntimeException("DANGER"), "32");
+ _adapter.log(logger, LogLevel.ERROR, "Exit stage right->");
+ _adapter.log(logger, LogLevel.FATAL, "What's up Doc?",
+ new NullPointerException("Unfortunate exception"));
+ }
+
+ //--------------------------------------------------------------------------
+ // Protected Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Nested Top-Level Classes or Interfaces:
+ //--------------------------------------------------------------------------
+}
+
+
+
+
+
diff --git a/examples/lf5/UsingSocketAppenders/UsingSocketAppenders.java b/examples/lf5/UsingSocketAppenders/UsingSocketAppenders.java
new file mode 100644
index 0000000..4274890
--- /dev/null
+++ b/examples/lf5/UsingSocketAppenders/UsingSocketAppenders.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file.
+ */
+
+package examples.lf5.UsingSocketAppenders;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * This is another simple example of how to use the LogFactor5
+ * logging console.
+ *
+ * The LF5Appender is the primary class that enables logging to the
+ * LogFactor5 logging window. If the following line is added to a properties
+ * file, the LF5Appender will be appended to the root category when
+ * the properties file is loaded:
+ *
+ * log4j.appender.A1=org.apache.log4j.lf5.LF5Appender
+ *
+ * To make this example work, you must ensure that the example.properties file
+ * is in your classpath.You can then run the example at the command line.
+ *
+ * @author Brent Sprecher
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class UsingSocketAppenders {
+ //--------------------------------------------------------------------------
+ // Constants:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Protected Variables:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Variables:
+ //--------------------------------------------------------------------------
+
+ private static Logger logger1 =
+ Logger.getLogger(UsingSocketAppenders.class);
+ private static Logger logger2 =
+ Logger.getLogger("TestClass.Subclass");
+ private static Logger logger3 =
+ Logger.getLogger("TestClass.Subclass.Subclass");
+ //--------------------------------------------------------------------------
+ // Constructors:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Public Methods:
+ //--------------------------------------------------------------------------
+
+ public static void main(String argv[]) {
+ // Use a PropertyConfigurator to initialize from a property file.
+ String resource =
+ "/examples/lf5/UsingSocketAppenders/socketclient.properties";
+ URL configFileResource =
+ UsingSocketAppenders.class.getResource(resource);
+ PropertyConfigurator.configure(configFileResource);
+
+ // Add a bunch of logging statements ...
+ logger1.debug("Hello, my name is Homer Simpson.");
+ logger1.debug("Hello, my name is Lisa Simpson.");
+ logger2.debug("Hello, my name is Marge Simpson.");
+ logger2.debug("Hello, my name is Bart Simpson.");
+ logger3.debug("Hello, my name is Maggie Simpson.");
+
+ logger2.info("We are the Simpsons!");
+ logger2.info("Mmmmmm .... Chocolate.");
+ logger3.info("Homer likes chocolate");
+ logger3.info("Doh!");
+ logger3.info("We are the Simpsons!");
+
+ logger1.warn("Bart: I am through with working! Working is for chumps!" +
+ "Homer: Son, I'm proud of you. I was twice your age before " +
+ "I figured that out.");
+ logger1.warn("Mmm...forbidden donut.");
+ logger1.warn("D'oh! A deer! A female deer!");
+ logger1.warn("Truly, yours is a butt that won't quit." +
+ "- Bart, writing as Woodrow to Ms. Krabappel.");
+
+ logger2.error("Dear Baby, Welcome to Dumpsville. Population: you.");
+ logger2.error("Dear Baby, Welcome to Dumpsville. Population: you.",
+ new IOException("Dumpsville, USA"));
+ logger3.error("Mr. Hutz, are you aware you're not wearing pants?");
+ logger3.error("Mr. Hutz, are you aware you're not wearing pants?",
+ new IllegalStateException("Error !!"));
+
+
+ logger3.fatal("Eep.");
+
+ logger3.fatal("Mmm...forbidden donut.",
+ new SecurityException("Fatal Exception ... "));
+
+ logger3.fatal("D'oh! A deer! A female deer!");
+ logger2.fatal("Mmmmmm .... Chocolate.",
+ new SecurityException("Fatal Exception"));
+
+ // Put the main thread is put to sleep for 5 seconds to allow the
+ // SocketServer to process all incoming messages before the Socket is
+ // closed. This is done to overcome some basic limitations with the
+ // way the SocketServer and SocketAppender classes manage sockets.
+ try {
+ Thread.currentThread().sleep(5000);
+ } catch (InterruptedException ie) {
+ }
+
+ }
+
+ //--------------------------------------------------------------------------
+ // Protected Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Private Methods:
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Nested Top-Level Classes or Interfaces:
+ //--------------------------------------------------------------------------
+
+}
diff --git a/examples/lf5/UsingSocketAppenders/socketclient.properties b/examples/lf5/UsingSocketAppenders/socketclient.properties
new file mode 100644
index 0000000..b051365
--- /dev/null
+++ b/examples/lf5/UsingSocketAppenders/socketclient.properties
@@ -0,0 +1,18 @@
+# For the general syntax of property based configuration files see the
+# documenation of org.apache.log4j.PropertyConfigurator.
+
+# The root category uses the appender called A1. Since no priority is
+# specified, the root category assumes the default priority for root
+# which is DEBUG in log4j. The root category is the only category that
+# has a default priority. All other categories need not be assigned a
+# priority in which case they inherit their priority from the
+# hierarchy.
+
+log4j.rootCategory=, A1
+
+# A1 is set to be a LF5Appender which outputs to a swing
+# logging console.
+
+log4j.appender.A1=org.apache.log4j.net.SocketAppender
+log4j.appender.A1.RemoteHost=localhost
+log4j.appender.A1.Port=8887
diff --git a/examples/lf5/UsingSocketAppenders/socketserver.properties b/examples/lf5/UsingSocketAppenders/socketserver.properties
new file mode 100644
index 0000000..da14ac0
--- /dev/null
+++ b/examples/lf5/UsingSocketAppenders/socketserver.properties
@@ -0,0 +1,19 @@
+# For the general syntax of property based configuration files see the
+# documenation of org.apache.log4j.PropertyConfigurator.
+
+# The root category uses the appender called A1. Since no priority is
+# specified, the root category assumes the default priority for root
+# which is DEBUG in log4j. The root category is the only category that
+# has a default priority. All other categories need not be assigned a
+# priority in which case they inherit their priority from the
+# hierarchy.
+
+#log4j.rootCategory=DEBUG, A1
+log4j.rootCategory=, A1
+
+# A1 is set to be a LF5Appender which outputs to a swing
+# logging console.
+
+#log4j.category.org.apache.log4j.net.SocketNode=DEBUG
+log4j.appender.A1=org.apache.log4j.lf5.LF5Appender
+log4j.appender.A1.MaxNumberOfRecords=700
\ No newline at end of file
diff --git a/examples/lf5/index.html b/examples/lf5/index.html
new file mode 100644
index 0000000..9a39752
--- /dev/null
+++ b/examples/lf5/index.html
@@ -0,0 +1,11 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+ <head>
+ </head>
+ <body bgcolor="#FFFFFF" text="#000000">
+
+ <p>See <a href="../../docs/lf5/examples.html">Examples</a>
+ section in the LogFactor5 user guide.
+ </p>
+ </body>
+</html>
diff --git a/examples/mycat.bad b/examples/mycat.bad
index 86ef942..fcfdc61 100644
--- a/examples/mycat.bad
+++ b/examples/mycat.bad
@@ -1,16 +1,18 @@
# The usual stuff. Note that A1 is configured in root not in "some.cat"
-log4j.rootCategory=DEBUG, A1
+log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%5p [%t] %c - %m%n
# Set the priority of "some.cat" to TRACE (defined in
-# org.apache.log4j.xml.examples.XPriority). This will actually have
-# the side effect of instanciating a category object having the name
-# "some.cat" this will cause a ClassCastException if the category
-# object is cast as a MyCategory object.
+# examples.customLevel.XLevel). This will actually have the side
+# effect of instanciating a logger object having the name "some.cat"
+# this will cause a ClassCastException if the logger object is cast
+# as a MyLogger object.
-log4j.category.some.cat=TRACE#org.apache.log4j.xml.examples.XPriority
+log4j.logger.some.cat=TRACE#examples.customLevel.XLevel
+
+
diff --git a/examples/mycat.good b/examples/mycat.good
index 6d08136..c2e02ee 100644
--- a/examples/mycat.good
+++ b/examples/mycat.good
@@ -1,13 +1,13 @@
-# Setting the category factory to MyCategoryFactory solves the
+# Setting the logger factory to MyLoggerFactory solves the
# ClassCastException problem encountered with the "mycat.bad"
# configuration file.
-log4j.categoryFactory=org.apache.log4j.examples.MyCategoryFactory
+log4j.loggerFactory=examples.subclass.MyLoggerFactory
# The usual stuff. Note that A1 is configured in root not in "some.cat"
-log4j.rootCategory=DEBUG, A1
+log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
@@ -15,10 +15,10 @@
# Set the priority of "some.cat" to TRACE (defined in
-# org.apache.log4j.xml.examples.XPriority). Since we specified
-# MyCategoryFactory as the category factory, the following line willl
-# also have the side effect of instanciating a MyCategory object
-# having the name "some.cat".
+# examples.customLevel.XLevel). Since we specified MyLoggerFactory as
+# the logger factory, the following line willl also have the side
+# effect of instanciating a MyLogger object having the name
+# "some.cat".
-log4j.category.some.cat=TRACE#org.apache.log4j.xml.examples.XPriority
+log4j.logger.some.cat=TRACE#examples.customLevel.XLevel
diff --git a/src/java/org/apache/log4j/AppenderSkeleton.java b/src/java/org/apache/log4j/AppenderSkeleton.java
index caf95ba..d815fcd 100644
--- a/src/java/org/apache/log4j/AppenderSkeleton.java
+++ b/src/java/org/apache/log4j/AppenderSkeleton.java
@@ -17,13 +17,14 @@
/**
- Abstract superclass of the other appenders in the package.
-
- This class provides the code for common functionality, such as
- support for threshold filtering and support for general filters.
-
- @since 0.8.1
- @author Ceki Gülcü */
+ * Abstract superclass of the other appenders in the package.
+ *
+ * This class provides the code for common functionality, such as
+ * support for threshold filtering and support for general filters.
+ *
+ * @since 0.8.1
+ * @author Ceki Gülcü
+ * */
public abstract class AppenderSkeleton implements Appender, OptionHandler {
/** The layout variable does not need to be set if the appender
@@ -99,11 +100,10 @@
}
/**
- Finalize this appender by calling the imlenentation's
+ Finalize this appender by calling the derived class'
<code>close</code> method.
- @since 0.8.4
- */
+ @since 0.8.4 */
public
void finalize() {
// An appender might be closed then garbage collected. There is no
@@ -191,11 +191,10 @@
/**
- This method performs threshold checks and invokes filters before
- delegating actual logging to the subclasses specific {@link
- AppenderSkeleton#append} method.
-
- */
+ * This method performs threshold checks and invokes filters before
+ * delegating actual logging to the subclasses specific {@link
+ * AppenderSkeleton#append} method.
+ * */
public
synchronized
void doAppend(LoggingEvent event) {
@@ -204,7 +203,7 @@
return;
}
- if(!isAsSevereAsThreshold(event.level)) {
+ if(!isAsSevereAsThreshold(event.getLevel())) {
return;
}
diff --git a/src/java/org/apache/log4j/AsyncAppender.java b/src/java/org/apache/log4j/AsyncAppender.java
index e9fb7d6..33bc061 100644
--- a/src/java/org/apache/log4j/AsyncAppender.java
+++ b/src/java/org/apache/log4j/AsyncAppender.java
@@ -33,11 +33,7 @@
<p><b>Important note:</b> The <code>AsyncAppender</code> can only
be script configured using the {@link
- org.apache.log4j.xml.DOMConfigurator}. Refer to example configuration
- files <a href="xml/examples/doc-files/sample4.xml">sample4.xml</a>
- and <a href="xml/examples/doc-files/sample5.xml">sample5.xml</a>.
-
-
+ org.apache.log4j.xml.DOMConfigurator}.
@author Ceki Gülcü
@since 0.9.1 */
@@ -57,8 +53,7 @@
boolean interruptedWarningMessage = false;
- public
- AsyncAppender() {
+ public AsyncAppender() {
// Note: The dispatcher code assumes that the aai is set once and
// for all.
aai = new AppenderAttachableImpl();
@@ -67,15 +62,13 @@
}
- public
- void addAppender(Appender newAppender) {
+ public void addAppender(Appender newAppender) {
synchronized(aai) {
aai.addAppender(newAppender);
}
}
- public
- void append(LoggingEvent event) {
+ public void append(LoggingEvent event) {
// Set the NDC and thread name for the calling thread as these
// LoggingEvent fields were not set at event creation time.
event.getNDC();
@@ -114,8 +107,7 @@
dispatcher thread which will process all pending events before
exiting.
*/
- public
- void close() {
+ public void close() {
synchronized(this) {
// avoid multiple close, otherwise one gets NullPointerException
if(closed) {
@@ -139,15 +131,13 @@
bf = null;
}
- public
- Enumeration getAllAppenders() {
+ public Enumeration getAllAppenders() {
synchronized(aai) {
return aai.getAllAppenders();
}
}
- public
- Appender getAppender(String name) {
+ public Appender getAppender(String name) {
synchronized(aai) {
return aai.getAppender(name);
}
@@ -156,89 +146,80 @@
/**
Returns the current value of the <b>LocationInfo</b> option.
*/
- public
- boolean getLocationInfo() {
+ public boolean getLocationInfo() {
return locationInfo;
}
/**
Is the appender passed as parameter attached to this category?
*/
- public
- boolean isAttached(Appender appender) {
+ public boolean isAttached(Appender appender) {
return aai.isAttached(appender);
}
/**
The <code>AsyncAppender</code> does not require a layout. Hence,
- this method always returns <code>false</code>. */
- public
- boolean requiresLayout() {
+ this method always returns <code>false</code>.
+ */
+ public boolean requiresLayout() {
return false;
}
- public
- void removeAllAppenders() {
+ public void removeAllAppenders() {
synchronized(aai) {
aai.removeAllAppenders();
}
}
- public
- void removeAppender(Appender appender) {
+ public void removeAppender(Appender appender) {
synchronized(aai) {
aai.removeAppender(appender);
}
}
- public
- void removeAppender(String name) {
+ public void removeAppender(String name) {
synchronized(aai) {
aai.removeAppender(name);
}
}
/**
- The <b>LocationInfo</b> option takes a boolean value. By
- default, it is set to false which means there will be no effort
- to extract the location information related to the event. As a
- result, the event that will be ultimately logged will likely to
- contain the wrong location information (if present in the log
- format).
-
- <p>Location information extraction is comparatively very slow and
- should be avoided unless performance is not a concern.
- */
- public
- void setLocationInfo(boolean flag) {
+ * The <b>LocationInfo</b> option takes a boolean value. By default,
+ * it is set to false which means there will be no effort to extract
+ * the location information related to the event. As a result, the
+ * event that will be ultimately logged will likely to contain the
+ * wrong location information (if present in the log format).
+ *
+ * <p>Location information extraction is comparatively very slow and
+ * should be avoided unless performance is not a concern.
+ * */
+ public void setLocationInfo(boolean flag) {
locationInfo = flag;
}
/**
- The <b>BufferSize</b> option takes a non-negative integer
- value. This integer value determines the maximum size of the
- bounded buffer. Increasing the size of the buffer is always
- safe. However, if an existing buffer holds unwritten elements,
- then <em>decreasing the buffer size will result in event
- loss.</em> Nevertheless, while script configuring the
- AsyncAppender, it is safe to set a buffer size smaller than the
- {@link #DEFAULT_BUFFER_SIZE default buffer size} because
- configurators guarantee that an appender cannot be used before
- being completely configured.
- */
- public
- void setBufferSize(int size) {
+ * The <b>BufferSize</b> option takes a non-negative integer value.
+ * This integer value determines the maximum size of the bounded
+ * buffer. Increasing the size of the buffer is always
+ * safe. However, if an existing buffer holds unwritten elements,
+ * then <em>decreasing the buffer size will result in event
+ * loss.</em> Nevertheless, while script configuring the
+ * AsyncAppender, it is safe to set a buffer size smaller than the
+ * {@link #DEFAULT_BUFFER_SIZE default buffer size} because
+ * configurators guarantee that an appender cannot be used before
+ * being completely configured.
+ * */
+ public void setBufferSize(int size) {
bf.resize(size);
}
/**
Returns the current value of the <b>BufferSize</b> option.
*/
- public
- int getBufferSize() {
+ public int getBufferSize() {
return bf.getMaxSize();
}
@@ -256,10 +237,14 @@
Dispatcher(BoundedFIFO bf, AsyncAppender container) {
this.bf = bf;
this.container = container;
- this.aai = container.aai;
+ this.aai = container.aai;
+ // It is the user's responsibility to close appenders before
+ // exiting.
+ this.setDaemon(true);
// set the dispatcher priority to lowest possible value
this.setPriority(Thread.MIN_PRIORITY);
this.setName("Dispatcher-"+getName());
+
// set the dispatcher priority to MIN_PRIORITY plus or minus 2
// depending on the direction of MIN to MAX_PRIORITY.
//+ (Thread.MAX_PRIORITY > Thread.MIN_PRIORITY ? 1 : -1)*2);
@@ -289,8 +274,7 @@
<p>Other approaches might yield better results.
*/
- public
- void run() {
+ public void run() {
//Category cat = Category.getInstance(Dispatcher.class.getName());
@@ -302,7 +286,7 @@
// Exit loop if interrupted but only if the the buffer is empty.
if(interrupted) {
//cat.info("Exiting.");
- return;
+ break;
}
try {
//LogLog.debug("Waiting for new event to dispatch.");
@@ -327,5 +311,8 @@
}
}
} // while
+
+ // close and remove all appenders
+ aai.removeAllAppenders();
}
}
diff --git a/src/java/org/apache/log4j/Category.java b/src/java/org/apache/log4j/Category.java
index 110b86d..97f43bb 100644
--- a/src/java/org/apache/log4j/Category.java
+++ b/src/java/org/apache/log4j/Category.java
@@ -77,9 +77,6 @@
//final Hierarchy defaultHierarchy = new Hierarchy(new
// RootCategory(Level.DEBUG));
-
- static int nooptimize;
-
/**
The name of this category.
*/
@@ -431,9 +428,10 @@
}
/**
-
- @deprecated Has been replaced by the {@link #getEffectiveLevel}
- method. */
+ *
+ * @deprecated Please use the the {@link #getEffectiveLevel} method
+ * instead.
+ * */
public
Priority getChainedPriority() {
for(Category c = this; c != null; c=c.parent) {
@@ -513,7 +511,6 @@
public
static
Category getInstance(String name) {
- nooptimize++;
return LogManager.getLogger(name);
}
@@ -530,7 +527,6 @@
public
static
Category getInstance(Class clazz) {
- nooptimize++;
return LogManager.getLogger(clazz);
}
diff --git a/src/java/org/apache/log4j/ConsoleAppender.java b/src/java/org/apache/log4j/ConsoleAppender.java
index fc14474..bd43ede 100644
--- a/src/java/org/apache/log4j/ConsoleAppender.java
+++ b/src/java/org/apache/log4j/ConsoleAppender.java
@@ -11,12 +11,12 @@
import org.apache.log4j.helpers.LogLog;
/**
- ConsoleAppender appends log events to <code>System.out</code> or
- <code>System.err</code> using a layout specified by the
- user. The default target is <code>System.out</code>.
-
- @author Ceki Gülcü
- @since 1.1 */
+ * ConsoleAppender appends log events to <code>System.out</code> or
+ * <code>System.err</code> using a layout specified by the user. The
+ * default target is <code>System.out</code>.
+ *
+ * @author Ceki Gülcü
+ * @since 1.1 */
public class ConsoleAppender extends WriterAppender {
public static final String SYSTEM_OUT = "System.out";
@@ -47,9 +47,10 @@
}
/**
- Sets the value of the <b>Target</b> option. Recognized values are
- "System.out" and "System.err". Any other value will be ignored.
- */
+ * Sets the value of the <b>Target</b> option. Recognized values
+ * are "System.out" and "System.err". Any other value will be
+ * ignored.
+ * */
public
void setTarget(String value) {
String v = value.trim();
@@ -64,12 +65,11 @@
}
/**
- Returns the current value of the <b>Target</b> property. The default
- value of the option is "System.out".
-
- See also {@link #setTarget}.
-
- */
+ * Returns the current value of the <b>Target</b> property. The
+ * default value of the option is "System.out".
+ *
+ * See also {@link #setTarget}.
+ * */
public
String getTarget() {
return target;
@@ -77,7 +77,7 @@
void targetWarn(String val) {
LogLog.warn("["+val+"] should be System.out or System.err.");
- LogLog.warn("Using System.out (default).");
+ LogLog.warn("Using previously set target, System.out by default.");
}
public
@@ -90,8 +90,10 @@
}
/**
- Override the parent method to do nothing.
- */
+ * This method overrides the parent {@link
+ * WriterAppender#closeWriter} implementation to do nothing because
+ * the console stream is not ours to close.
+ * */
protected
final
void closeWriter() {
diff --git a/src/java/org/apache/log4j/DailyRollingFileAppender.java b/src/java/org/apache/log4j/DailyRollingFileAppender.java
index c90a209..50d1e9e 100644
--- a/src/java/org/apache/log4j/DailyRollingFileAppender.java
+++ b/src/java/org/apache/log4j/DailyRollingFileAppender.java
@@ -52,11 +52,10 @@
<td><code>'.'yyyy-MM</code>
<td>Rollover at the beginning of each month</td>
- <td>Assuming the first day of the week is Sunday, at Sunday 00:00,
- March 25th, 2001, <code>/foo/bar.log</code> will be copied to
- <code>/foo/bar.log.2001-03</code>. Logging for the month of April
- will be output to <code>/foo/bar.log</code> until it rolls over
- at the beginning of May.
+ <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>
@@ -64,18 +63,19 @@
<td>Rollover at the first day of each week. The first day of the
week depends on the locale.</td>
- <td>At midnight, on March 31st, 2001, <code>/foo/bar.log</code>
- will be copied to <code>/foo/bar.log.2001-08</code>. Logging for
- the 9th week of 2001 will be output to <code>/foo/bar.log</code>
- until it is rolled over the next week.
+ <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 9th, 2001, <code>/foo/bar.log</code> will
- be copied to <code>/foo/bar.log.2001-03-08</code>. Logging for the
+ <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.
@@ -84,19 +84,19 @@
<td>Rollover at midnight and midday of each day.</td>
- <td>At noon, on March 9th, 2001, <code>/foo/bar.log</code> will be
- copied to <code>/foo/bar.log.2001-03-09-AM</code>. Logging for the
+ <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 the next morning, i.e at midnight 00:00.
+ 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, on March 9th, 2001,
+ <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.2001-03-09-10</code>. Logging for the 11th hour
+ <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.
@@ -143,13 +143,19 @@
private String datePattern = "'.'yyyy-MM-dd";
/**
- The actual formatted filename that is currently being written to.
+ The log file will be renamed to the value of the
+ scheduledFilename variable when the next interval is entered. For
+ example, if the rollover period is one hour, the log file will be
+ renamed to the value of "scheduledFilename" at the beginning of
+ the next hour.
+
+ The precise time when a rollover occurs depends on logging
+ activity.
*/
private String scheduledFilename;
/**
- The timestamp when we shall next recompute the filename.
- */
+ The next time we estimate a rollover should occur. */
private long nextCheck = System.currentTimeMillis () - 1;
Date now = new Date();
@@ -160,14 +166,13 @@
int checkPeriod = TOP_OF_TROUBLE;
-
+ // The gmtTimeZone is used only in computeCheckPeriod() method.
static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");
/**
The default constructor does nothing. */
- public
- DailyRollingFileAppender() {
+ public DailyRollingFileAppender() {
}
/**
@@ -188,19 +193,16 @@
expected by {@link SimpleDateFormat}. This options determines the
rollover schedule.
*/
- public
- void setDatePattern(String pattern) {
+ public void setDatePattern(String pattern) {
datePattern = pattern;
}
/** Returns the value of the <b>DatePattern</b> option. */
- public
- String getDatePattern() {
+ public String getDatePattern() {
return datePattern;
}
- public
- void activateOptions() {
+ public void activateOptions() {
super.activateOptions();
if(datePattern != null && fileName != null) {
now.setTime(System.currentTimeMillis());
@@ -212,8 +214,8 @@
scheduledFilename = fileName+sdf.format(new Date(file.lastModified()));
} else {
- LogLog.error("Either Filename or DatePattern options are not set for ["+
- name+"].");
+ LogLog.error("Either File or DatePattern options are not set for appender ["
+ +name+"].");
}
}
@@ -290,6 +292,9 @@
}
String datedFilename = fileName+sdf.format(now);
+ // It is too early to roll over because we are still within the
+ // bounds of the current interval. Rollover will occur once the
+ // next interval is reached.
if (scheduledFilename.equals(datedFilename)) {
return;
}
@@ -303,8 +308,12 @@
}
File file = new File(fileName);
- file.renameTo(target);
- LogLog.debug(fileName +" -> "+ scheduledFilename);
+ boolean result = file.renameTo(target);
+ if(result) {
+ LogLog.debug(fileName +" -> "+ scheduledFilename);
+ } else {
+ LogLog.error("Failed to rename ["+fileName+"] to ["+scheduledFilename+"].");
+ }
try {
// This will also close the file. This is OK since multiple
@@ -318,17 +327,14 @@
}
/**
- This method differentiates DailyRollingFileAppender from its
- super class.
-
- <p>Before actually logging, this method will check whether it is
- time to do a rollover. If it is, it will schedule the next
- rollover time and then rollover.
-
-
- */
- protected
- void subAppend(LoggingEvent event) {
+ * This method differentiates DailyRollingFileAppender from its
+ * super class.
+ *
+ * <p>Before actually logging, this method will check whether it is
+ * time to do a rollover. If it is, it will schedule the next
+ * rollover time and then rollover.
+ * */
+ protected void subAppend(LoggingEvent event) {
long n = System.currentTimeMillis();
if (n >= nextCheck) {
now.setTime(n);
@@ -345,16 +351,10 @@
}
/**
- RollingCalendar is a helper class to
- DailyRollingFileAppender. Using this class, it is easy to compute
- and access the next Millis().
-
- It subclasses the standard {@link GregorianCalendar}-object, to
- allow access to the protected function getTimeInMillis(), which it
- then exports.
-
- @author <a HREF="mailto:eirik.lygre@evita.no">Eirik Lygre</a> */
-
+ * RollingCalendar is a helper class to DailyRollingFileAppender.
+ * Given a periodicity type and the current time, it computes the
+ * start of the next interval.
+ * */
class RollingCalendar extends GregorianCalendar {
int type = DailyRollingFileAppender.TOP_OF_TROUBLE;
@@ -371,13 +371,11 @@
this.type = type;
}
- public
- long getNextCheckMillis(Date now) {
+ public long getNextCheckMillis(Date now) {
return getNextCheckDate(now).getTime();
}
- public
- Date getNextCheckDate(Date now) {
+ public Date getNextCheckDate(Date now) {
this.setTime(now);
switch(type) {
diff --git a/src/java/org/apache/log4j/FileAppender.java b/src/java/org/apache/log4j/FileAppender.java
index e3b212e..4971577 100644
--- a/src/java/org/apache/log4j/FileAppender.java
+++ b/src/java/org/apache/log4j/FileAppender.java
@@ -20,14 +20,14 @@
// Ben Sandee
/**
- 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: {@link WriterAppender} and {@link ConsoleAppender}.
-
-
- @author Ceki Gülcü */
+ * 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: {@link WriterAppender} and {@link ConsoleAppender}.
+ *
+ * @author Ceki Gülcü
+ * */
public class FileAppender extends WriterAppender {
/** Append to or truncate the file? The default value for this
diff --git a/src/java/org/apache/log4j/HTMLLayout.java b/src/java/org/apache/log4j/HTMLLayout.java
index 013b7c5..961c301 100644
--- a/src/java/org/apache/log4j/HTMLLayout.java
+++ b/src/java/org/apache/log4j/HTMLLayout.java
@@ -130,22 +130,22 @@
sbuf.append("</td>" + Layout.LINE_SEP);
sbuf.append("<td title=\"Level\">");
- if (event.level.equals(Level.DEBUG)) {
+ if (event.getLevel().equals(Level.DEBUG)) {
sbuf.append("<font color=\"#339933\">");
- sbuf.append(event.level);
+ sbuf.append(event.getLevel());
sbuf.append("</font>");
}
- else if(event.level.isGreaterOrEqual(Level.WARN)) {
+ else if(event.getLevel().isGreaterOrEqual(Level.WARN)) {
sbuf.append("<font color=\"#993300\"><strong>");
- sbuf.append(event.level);
+ sbuf.append(event.getLevel());
sbuf.append("</strong></font>");
} else {
- sbuf.append(event.level);
+ sbuf.append(event.getLevel());
}
sbuf.append("</td>" + Layout.LINE_SEP);
- sbuf.append("<td title=\"" + event.categoryName + " category\">");
- sbuf.append(Transform.escapeTags(event.categoryName));
+ sbuf.append("<td title=\"" + event.getLoggerName() + " category\">");
+ sbuf.append(Transform.escapeTags(event.getLoggerName()));
sbuf.append("</td>" + Layout.LINE_SEP);
if(locationInfo) {
diff --git a/src/java/org/apache/log4j/MDC.java b/src/java/org/apache/log4j/MDC.java
index 002b399..4e92716 100644
--- a/src/java/org/apache/log4j/MDC.java
+++ b/src/java/org/apache/log4j/MDC.java
@@ -104,8 +104,8 @@
} else {
Hashtable ht = (Hashtable) ((ThreadLocalMap)tlm).get();
if(ht == null) {
- ht = new Hashtable(HT_SIZE);
- ((ThreadLocalMap)tlm).set(ht);
+ ht = new Hashtable(HT_SIZE);
+ ((ThreadLocalMap)tlm).set(ht);
}
ht.put(key, o);
}
@@ -117,10 +117,10 @@
return null;
} else {
Hashtable ht = (Hashtable) ((ThreadLocalMap)tlm).get();
- if(ht != null) {
- return ht.get(key);
+ if(ht != null && key != null) {
+ return ht.get(key);
} else {
- return null;
+ return null;
}
}
}
@@ -130,7 +130,7 @@
if(!java1) {
Hashtable ht = (Hashtable) ((ThreadLocalMap)tlm).get();
if(ht != null) {
- ht.remove(key);
+ ht.remove(key);
}
}
}
diff --git a/src/java/org/apache/log4j/NDC.java b/src/java/org/apache/log4j/NDC.java
index aa44615..b032744 100644
--- a/src/java/org/apache/log4j/NDC.java
+++ b/src/java/org/apache/log4j/NDC.java
@@ -192,7 +192,8 @@
/**
- Used when printing the diagnostic context.
+ <font color="#FF4040"><b>Never use this method directly, use the {@link
+ org.apache.log4j.spi.LoggingEvent#getNDC} method instead.</b></font>
*/
static
public
diff --git a/src/java/org/apache/log4j/PropertyConfigurator.java b/src/java/org/apache/log4j/PropertyConfigurator.java
index c15d438..27f8446 100644
--- a/src/java/org/apache/log4j/PropertyConfigurator.java
+++ b/src/java/org/apache/log4j/PropertyConfigurator.java
@@ -118,7 +118,7 @@
</pre>
<p>The level value can consist of the string values OFF, FATAL,
- ERROR, WARN, INFO, DEBUG, ALL or a <em>custom level</e> value. A
+ 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>.
@@ -175,7 +175,7 @@
<p>For non-root categories the syntax is almost the same:
<pre>
- log4j.logger.logger_name=[level|INHERITED], appenderName, appenderName, ...
+ log4j.logger.logger_name=[level|INHERITED|NULL], appenderName, appenderName, ...
</pre>
<p>The meaning of the optional level value is discussed above
@@ -187,9 +187,10 @@
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.
+ 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.
@@ -576,9 +577,13 @@
// If the level value is inherited, set category level value to
// null. We also check that the user has not specified inherited for the
// root category.
- if(levelStr.equalsIgnoreCase(INHERITED) &&
- !loggerName.equals(INTERNAL_ROOT_NAME)) {
- logger.setLevel(null);
+ if(INHERITED.equalsIgnoreCase(levelStr) ||
+ NULL.equalsIgnoreCase(levelStr)) {
+ if(loggerName.equals(INTERNAL_ROOT_NAME)) {
+ LogLog.warn("The root logger cannot be set to null.");
+ } else {
+ logger.setLevel(null);
+ }
} else {
logger.setLevel(OptionConverter.toLevel(levelStr, (Level) Level.DEBUG));
}
diff --git a/src/java/org/apache/log4j/SimpleLayout.java b/src/java/org/apache/log4j/SimpleLayout.java
index 565ca54..8c58eeb 100644
--- a/src/java/org/apache/log4j/SimpleLayout.java
+++ b/src/java/org/apache/log4j/SimpleLayout.java
@@ -49,7 +49,7 @@
String format(LoggingEvent event) {
sbuf.setLength(0);
- sbuf.append(event.level.toString());
+ sbuf.append(event.getLevel().toString());
sbuf.append(" - ");
sbuf.append(event.getRenderedMessage());
sbuf.append(LINE_SEP);
diff --git a/src/java/org/apache/log4j/TTCCLayout.java b/src/java/org/apache/log4j/TTCCLayout.java
index 5ce94e6..ae3b7d7 100644
--- a/src/java/org/apache/log4j/TTCCLayout.java
+++ b/src/java/org/apache/log4j/TTCCLayout.java
@@ -175,11 +175,11 @@
buf.append(event.getThreadName());
buf.append("] ");
}
- buf.append(event.level.toString());
+ buf.append(event.getLevel().toString());
buf.append(' ');
if(this.categoryPrefixing) {
- buf.append(event.categoryName);
+ buf.append(event.getLoggerName());
buf.append(' ');
}
diff --git a/src/java/org/apache/log4j/WriterAppender.java b/src/java/org/apache/log4j/WriterAppender.java
index 50b33f4..456d35b 100644
--- a/src/java/org/apache/log4j/WriterAppender.java
+++ b/src/java/org/apache/log4j/WriterAppender.java
@@ -194,17 +194,18 @@
writeFooter();
reset();
}
+
/**
- Close the underlying {@link java.io.Writer}.
- */
- protected
- void closeWriter() {
+ * Close the underlying {@link java.io.Writer}.
+ * */
+ protected void closeWriter() {
if(qw != null) {
try {
qw.close();
} catch(IOException e) {
- LogLog.error("Could not close " + qw, e); // do need to invoke an error handler
- // at this late stage
+ // There is do need to invoke an error handler at this late
+ // stage.
+ LogLog.error("Could not close " + qw, e);
}
}
}
@@ -234,13 +235,11 @@
return retval;
}
- public
- String getEncoding() {
+ public String getEncoding() {
return encoding;
}
- public
- void setEncoding(String value) {
+ public void setEncoding(String value) {
encoding = value;
}
@@ -250,9 +249,7 @@
/**
Set the {@link ErrorHandler} for this WriterAppender and also the
underlying {@link QuietWriter} if any. */
- public
- synchronized
- void setErrorHandler(ErrorHandler eh) {
+ public synchronized void setErrorHandler(ErrorHandler eh) {
if(eh == null) {
LogLog.warn("You have tried to set a null error-handler.");
} else {
@@ -275,9 +272,7 @@
<p><b>WARNING:</b> Logging to an unopened Writer will fail.
<p>
@param writer An already opened Writer. */
- public
- synchronized
- void setWriter(Writer writer) {
+ public synchronized void setWriter(Writer writer) {
reset();
this.qw = new QuietWriter(writer, errorHandler);
//this.tp = new TracerPrintWriter(qw);
diff --git a/src/java/org/apache/log4j/chainsaw/EventDetails.java b/src/java/org/apache/log4j/chainsaw/EventDetails.java
index 12ddc51..a0538e6 100644
--- a/src/java/org/apache/log4j/chainsaw/EventDetails.java
+++ b/src/java/org/apache/log4j/chainsaw/EventDetails.java
@@ -73,8 +73,8 @@
EventDetails(LoggingEvent aEvent) {
this(aEvent.timeStamp,
- aEvent.level,
- aEvent.categoryName,
+ aEvent.getLevel(),
+ aEvent.getLoggerName(),
aEvent.getNDC(),
aEvent.getThreadName(),
aEvent.getRenderedMessage(),
diff --git a/src/java/org/apache/log4j/chainsaw/LoggingReceiver.java b/src/java/org/apache/log4j/chainsaw/LoggingReceiver.java
index c69b3de..3cd3455 100644
--- a/src/java/org/apache/log4j/chainsaw/LoggingReceiver.java
+++ b/src/java/org/apache/log4j/chainsaw/LoggingReceiver.java
@@ -23,7 +23,7 @@
*/
class LoggingReceiver extends Thread {
/** used to log messages **/
- private static final Logger logger = Logger.getLogger(LoggingReceiver.class);
+ private static final Logger LOG = Logger.getLogger(LoggingReceiver.class);
/**
* Helper that actually processes a client connection. It receives events
@@ -46,7 +46,7 @@
/** loops getting the events **/
public void run() {
- logger.debug("Starting to get data");
+ LOG.debug("Starting to get data");
try {
final ObjectInputStream ois =
new ObjectInputStream(mClient.getInputStream());
@@ -55,19 +55,19 @@
mModel.addEvent(new EventDetails(event));
}
} catch (EOFException e) {
- logger.info("Reached EOF, closing connection");
+ LOG.info("Reached EOF, closing connection");
} catch (SocketException e) {
- logger.info("Caught SocketException, closing connection");
+ LOG.info("Caught SocketException, closing connection");
} catch (IOException e) {
- logger.warn("Got IOException, closing connection", e);
+ LOG.warn("Got IOException, closing connection", e);
} catch (ClassNotFoundException e) {
- logger.warn("Got ClassNotFoundException, closing connection", e);
+ LOG.warn("Got ClassNotFoundException, closing connection", e);
}
try {
mClient.close();
} catch (IOException e) {
- logger.warn("Error closing connection", e);
+ LOG.warn("Error closing connection", e);
}
}
}
@@ -93,19 +93,19 @@
/** Listens for client connections **/
public void run() {
- logger.info("Thread started");
+ LOG.info("Thread started");
try {
while (true) {
- logger.debug("Waiting for a connection");
+ LOG.debug("Waiting for a connection");
final Socket client = mSvrSock.accept();
- logger.debug("Got a connection from " +
+ LOG.debug("Got a connection from " +
client.getInetAddress().getHostName());
final Thread t = new Thread(new Slurper(client));
t.setDaemon(true);
t.start();
}
} catch (IOException e) {
- logger.error("Error in accepting connections, stopping.", e);
+ LOG.error("Error in accepting connections, stopping.", e);
}
}
}
diff --git a/src/java/org/apache/log4j/chainsaw/XMLFileHandler.java b/src/java/org/apache/log4j/chainsaw/XMLFileHandler.java
index 5ce82d0..a5e7d4f 100644
--- a/src/java/org/apache/log4j/chainsaw/XMLFileHandler.java
+++ b/src/java/org/apache/log4j/chainsaw/XMLFileHandler.java
@@ -37,12 +37,10 @@
private final MyTableModel mModel;
/** the number of events in the document **/
private int mNumEvents;
- /** the current element being parsed **/
- private String mCurrentElement;
/** the time of the event **/
private long mTimeStamp;
- /** the priority of the event **/
+ /** the priority (level) of the event **/
private Priority mPriority;
/** the category of the event **/
private String mCategoryName;
@@ -56,7 +54,8 @@
private String[] mThrowableStrRep;
/** the location details for the event **/
private String mLocationDetails;
-
+ /** buffer for collecting text **/
+ private final StringBuffer mBuf = new StringBuffer();
/**
* Creates a new <code>XMLFileHandler</code> instance.
@@ -76,13 +75,24 @@
/** @see DefaultHandler **/
public void characters(char[] aChars, int aStart, int aLength) {
- if (mCurrentElement == TAG_NDC) {
- mNDC = new String(aChars, aStart, aLength);
- } else if (mCurrentElement == TAG_MESSAGE) {
- mMessage = new String(aChars, aStart, aLength);
- } else if (mCurrentElement == TAG_THROWABLE) {
+ mBuf.append(String.valueOf(aChars, aStart, aLength));
+ }
+
+ /** @see DefaultHandler **/
+ public void endElement(String aNamespaceURI,
+ String aLocalName,
+ String aQName)
+ {
+ if (TAG_EVENT.equals(aQName)) {
+ addEvent();
+ resetData();
+ } else if (TAG_NDC.equals(aQName)) {
+ mNDC = mBuf.toString();
+ } else if (TAG_MESSAGE.equals(aQName)) {
+ mMessage = mBuf.toString();
+ } else if (TAG_THROWABLE.equals(aQName)) {
final StringTokenizer st =
- new StringTokenizer(new String(aChars, aStart, aLength), "\t");
+ new StringTokenizer(mBuf.toString(), "\n\t");
mThrowableStrRep = new String[st.countTokens()];
if (mThrowableStrRep.length > 0) {
mThrowableStrRep[0] = st.nextToken();
@@ -94,40 +104,23 @@
}
/** @see DefaultHandler **/
- public void endElement(String aNamespaceURI,
- String aLocalName,
- String aQName)
- {
- if (TAG_EVENT.equals(aQName)) {
- addEvent();
- resetData();
- } else if (mCurrentElement != TAG_EVENT) {
- mCurrentElement = TAG_EVENT; // hack - but only thing I care about
- }
- }
-
- /** @see DefaultHandler **/
public void startElement(String aNamespaceURI,
String aLocalName,
String aQName,
Attributes aAtts)
{
+ mBuf.setLength(0);
+
if (TAG_EVENT.equals(aQName)) {
mThreadName = aAtts.getValue("thread");
mTimeStamp = Long.parseLong(aAtts.getValue("timestamp"));
- mCategoryName = aAtts.getValue("category");
+ mCategoryName = aAtts.getValue("logger");
mPriority = Priority.toPriority(aAtts.getValue("level"));
} else if (TAG_LOCATION_INFO.equals(aQName)) {
mLocationDetails = aAtts.getValue("class") + "."
+ aAtts.getValue("method")
+ "(" + aAtts.getValue("file") + ":" + aAtts.getValue("line")
+ ")";
- } else if (TAG_NDC.equals(aQName)) {
- mCurrentElement = TAG_NDC;
- } else if (TAG_MESSAGE.equals(aQName)) {
- mCurrentElement = TAG_MESSAGE;
- } else if (TAG_THROWABLE.equals(aQName)) {
- mCurrentElement = TAG_THROWABLE;
}
}
diff --git a/src/java/org/apache/log4j/config/PropertyGetter.java b/src/java/org/apache/log4j/config/PropertyGetter.java
index 3c6f8db..bc88da1 100644
--- a/src/java/org/apache/log4j/config/PropertyGetter.java
+++ b/src/java/org/apache/log4j/config/PropertyGetter.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file.
+ * distribution in the LICENSE.txt file.
*/
package org.apache.log4j.config;
diff --git a/src/java/org/apache/log4j/config/PropertyPrinter.java b/src/java/org/apache/log4j/config/PropertyPrinter.java
index 23c950c..8f1e4d4 100644
--- a/src/java/org/apache/log4j/config/PropertyPrinter.java
+++ b/src/java/org/apache/log4j/config/PropertyPrinter.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file.
+ * distribution in the LICENSE.txt file.
*/
package org.apache.log4j.config;
diff --git a/src/java/org/apache/log4j/config/PropertySetter.java b/src/java/org/apache/log4j/config/PropertySetter.java
index c1b2ec1..8f6a155 100644
--- a/src/java/org/apache/log4j/config/PropertySetter.java
+++ b/src/java/org/apache/log4j/config/PropertySetter.java
@@ -1,10 +1,9 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
- * This software is published under the terms of the Apache Software License
- * version 1.1, a copy of which has been included with this distribution in
- * the LICENSE.APL file.
- */
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file. */
// Contributors: Georg Lundesgaard
@@ -156,7 +155,7 @@
setProperty(prop, name, value);
} catch (PropertySetterException ex) {
LogLog.warn("Failed to set property [" + name +
- "] to value \"" + value + "\". " + ex.getMessage());
+ "] to value \"" + value + "\". ", ex.rootCause);
}
}
}
diff --git a/src/java/org/apache/log4j/config/PropertySetterException.java b/src/java/org/apache/log4j/config/PropertySetterException.java
index b8cb0e0..3accdf3 100644
--- a/src/java/org/apache/log4j/config/PropertySetterException.java
+++ b/src/java/org/apache/log4j/config/PropertySetterException.java
@@ -1,10 +1,9 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
- * This software is published under the terms of the Apache Software License
- * version 1.1, a copy of which has been included with this distribution in
- * the LICENSE.APL file.
- */
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.config;
@@ -41,4 +40,4 @@
}
return msg;
}
-}
\ No newline at end of file
+}
diff --git a/src/java/org/apache/log4j/helpers/AppenderAttachableImpl.java b/src/java/org/apache/log4j/helpers/AppenderAttachableImpl.java
index ec01c76..d3d2680 100644
--- a/src/java/org/apache/log4j/helpers/AppenderAttachableImpl.java
+++ b/src/java/org/apache/log4j/helpers/AppenderAttachableImpl.java
@@ -121,8 +121,8 @@
/**
- Remove all previously attached appenders.
- */
+ * Remove and close all previously attached appenders.
+ * */
public
void removeAllAppenders() {
if(appenderList != null) {
diff --git a/src/java/org/apache/log4j/helpers/Loader.java b/src/java/org/apache/log4j/helpers/Loader.java
index 222c2cc..6376ecf 100644
--- a/src/java/org/apache/log4j/helpers/Loader.java
+++ b/src/java/org/apache/log4j/helpers/Loader.java
@@ -8,6 +8,10 @@
package org.apache.log4j.helpers;
import java.net.URL;
+import java.lang.IllegalAccessException;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
//import java.awt.Image;
//import java.awt.Toolkit;
@@ -23,7 +27,9 @@
// We conservatively assume that we are running under Java 1.x
static private boolean java1 = true;
-
+
+ static private boolean ignoreTCL = false;
+
static {
String prop = OptionConverter.getSystemProperty("java.version", null);
@@ -34,8 +40,15 @@
java1 = false;
}
}
+ String ignoreTCLProp = OptionConverter.getSystemProperty("log4j.ignoreTCL", null);
+ if(ignoreTCLProp != null) {
+ ignoreTCL = OptionConverter.toBoolean(ignoreTCLProp, true);
+ }
}
+ /* A cache for
+ private static Method GET_TCL_METHOD;
+
/**
This method will search for <code>resource</code> in different
places. The rearch order is as follows:
@@ -56,41 +69,36 @@
</ol>
*/
- static
- public
- URL getResource(String resource) {
+ static public URL getResource(String resource) {
ClassLoader classLoader = null;
URL url = null;
try {
- if(!java1) {
- classLoader = Thread.currentThread().getContextClassLoader();
- if(classLoader != null) {
- LogLog.debug("Trying to find ["+resource+"] using context classloader "
- +classLoader+".");
- url = classLoader.getResource(resource);
- if(url != null) {
- return url;
- }
- }
- }
-
- // We could not find resource. Ler us now try with the
- // classloader that loaded this class.
- classLoader = Loader.class.getClassLoader();
- if(classLoader == null) {
- LogLog.warn("Loader.class.getClassLoader returned null!");
- } else {
-
- LogLog.debug("Trying to find ["+resource+"] using "+classLoader
- +" class loader.");
- url = classLoader.getResource(resource);
- if(url != null) {
- return url;
- }
- }
+ if(!java1) {
+ classLoader = getTCL();
+ if(classLoader != null) {
+ LogLog.debug("Trying to find ["+resource+"] using context classloader "
+ +classLoader+".");
+ url = classLoader.getResource(resource);
+ if(url != null) {
+ return url;
+ }
+ }
+ }
+
+ // We could not find resource. Ler us now try with the
+ // classloader that loaded this class.
+ classLoader = Loader.class.getClassLoader();
+ if(classLoader != null) {
+ LogLog.debug("Trying to find ["+resource+"] using "+classLoader
+ +" class loader.");
+ url = classLoader.getResource(resource);
+ if(url != null) {
+ return url;
+ }
+ }
} catch(Throwable t) {
- LogLog.warn(TSTR, t);
+ LogLog.warn(TSTR, t);
}
// Last ditch attempt: get the resource from the class path. It
@@ -98,7 +106,7 @@
// loader which the parent of the system class loader. Hence the
// code below.
LogLog.debug("Trying to find ["+resource+
- "] using ClassLoader.getSystemResource().");
+ "] using ClassLoader.getSystemResource().");
return ClassLoader.getSystemResource(resource);
}
@@ -111,28 +119,50 @@
return java1;
}
+ /**
+ * Get the Thread Context Loader which is a JDK 1.2 feature. If we
+ * are running under JDK 1.1 or anything else goes wrong the method
+ * returns <code>null<code>.
+ *
+ * */
+ private static ClassLoader getTCL() throws IllegalAccessException,
+ InvocationTargetException {
+
+ // Are we running on a JDK 1.2 or later system?
+ Method method = null;
+ try {
+ method = Thread.class.getMethod("getContextClassLoader", null);
+ } catch (NoSuchMethodException e) {
+ // We are running on JDK 1.1
+ return null;
+ }
+
+ return (ClassLoader) method.invoke(Thread.currentThread(), null);
+ }
+
+
/**
- Load the specified class using the <code>Thread</code>
- <code>contextClassLoader</code> if running under Java2 or current
- class loader if running under JDK 1.1.
- */
- static
- public
- Class loadClass (Double clazz) throws ClassNotFoundException {
- return null;
- // if(java1) {
- // return Class.forName(clazz);
- // } else {
- // try {
- // return Thread.currentThread().getContextClassLoader().loadClass(clazz);
- // } catch(Exception e) {
- // // we reached here because
- // // currentThread().getContextClassLoader() is null or because
- // // of a security exceptio, or because clazz could not be
- // // loaded, in any case we now try one more time
- // return Class.forName(clazz);
- // }
- // }
+ * If running under JDK 1.2 load the specified class using the
+ * <code>Thread</code> <code>contextClassLoader</code> if that
+ * fails try Class.forname. Under JDK 1.1 only Class.forName is
+ * used.
+ *
+ */
+ static public Class loadClass (String clazz) throws ClassNotFoundException {
+ // Just call Class.forName(clazz) if we are running under JDK 1.1
+ // or if we are instructed to ignore the TCL.
+ if(java1 || ignoreTCL) {
+ return Class.forName(clazz);
+ } else {
+ try {
+ return getTCL().loadClass(clazz);
+ } catch(Throwable e) {
+ // we reached here because tcl was null or because of a
+ // security exception, or because clazz could not be loaded...
+ // In any case we now try one more time
+ return Class.forName(clazz);
+ }
+ }
}
}
diff --git a/src/java/org/apache/log4j/helpers/NullEnumeration.java b/src/java/org/apache/log4j/helpers/NullEnumeration.java
index e7dd29e..b1e8319 100644
--- a/src/java/org/apache/log4j/helpers/NullEnumeration.java
+++ b/src/java/org/apache/log4j/helpers/NullEnumeration.java
@@ -25,9 +25,7 @@
NullEnumeration() {
}
- public
- static
- NullEnumeration getInstance() {
+ public static NullEnumeration getInstance() {
return instance;
}
diff --git a/src/java/org/apache/log4j/helpers/OptionConverter.java b/src/java/org/apache/log4j/helpers/OptionConverter.java
index 2131b48..00e7017 100644
--- a/src/java/org/apache/log4j/helpers/OptionConverter.java
+++ b/src/java/org/apache/log4j/helpers/OptionConverter.java
@@ -199,7 +199,7 @@
+ ":pri=[" + levelName + "]");
try {
- Class customLevel = Class.forName(clazz);
+ Class customLevel = Loader.loadClass(clazz);
// get a ref to the specified class' static method
// toLevel(String, org.apache.log4j.Level)
@@ -306,10 +306,14 @@
Object defaultValue) {
if(className != null) {
try {
- Class classObj = Class.forName(className);
+ Class classObj = Loader.loadClass(className);
if(!superClass.isAssignableFrom(classObj)) {
LogLog.error("A \""+className+"\" object is not assignable to a \""+
superClass.getName() + "\" variable.");
+ LogLog.error("The class \""+ superClass.getName()+"\" was loaded by ");
+ LogLog.error("["+superClass.getClassLoader()+"] whereas object of type ");
+ LogLog.error("\"" +classObj.getName()+"\" was loaded by ["
+ +classObj.getClassLoader()+"].");
return defaultValue;
}
return classObj.newInstance();
diff --git a/src/java/org/apache/log4j/helpers/PatternParser.java b/src/java/org/apache/log4j/helpers/PatternParser.java
index f6fecf3..1e78876 100644
--- a/src/java/org/apache/log4j/helpers/PatternParser.java
+++ b/src/java/org/apache/log4j/helpers/PatternParser.java
@@ -388,7 +388,7 @@
case THREAD_CONVERTER:
return event.getThreadName();
case LEVEL_CONVERTER:
- return event.level.toString();
+ return event.getLevel().toString();
case NDC_CONVERTER:
return event.getNDC();
case MESSAGE_CONVERTER: {
@@ -538,7 +538,7 @@
}
String getFullyQualifiedName(LoggingEvent event) {
- return event.categoryName;
+ return event.getLoggerName();
}
}
}
diff --git a/src/java/org/apache/log4j/helpers/SyslogWriter.java b/src/java/org/apache/log4j/helpers/SyslogWriter.java
index 81a05f1..50f52fe 100644
--- a/src/java/org/apache/log4j/helpers/SyslogWriter.java
+++ b/src/java/org/apache/log4j/helpers/SyslogWriter.java
@@ -61,8 +61,8 @@
public
void write(String string) throws IOException {
- DatagramPacket packet = new DatagramPacket(string.getBytes(),
- string.length(),
+ byte[] bytes = string.getBytes();
+ DatagramPacket packet = new DatagramPacket(bytes, bytes.length,
address, SYSLOG_PORT);
if(this.ds != null)
diff --git a/src/java/org/apache/log4j/helpers/Transform.java b/src/java/org/apache/log4j/helpers/Transform.java
index 66e6c80..fe2ef9d 100644
--- a/src/java/org/apache/log4j/helpers/Transform.java
+++ b/src/java/org/apache/log4j/helpers/Transform.java
@@ -12,21 +12,28 @@
/**
Utility class for transforming strings.
+
+ @author Ceki Gülcü
+ @author Michael A. McAngus
*/
public class Transform {
+ private static final String CDATA_START = "<![CDATA[";
+ private static final String CDATA_END = "]]>";
+ private static final String CDATA_PSEUDO_END = "]]>";
+ private static final String CDATA_EMBEDED_END = CDATA_END + CDATA_PSEUDO_END + CDATA_START;
+ private static final int CDATA_END_LEN = CDATA_END.length();
+
/**
- * This method takes a string which may contain HTML tags (ie, <b>, <table>,
- * etc) and converts the '<' and '>' characters to their HTML escape
- * sequences.
+ * This method takes a string which may contain HTML tags (ie,
+ * <b>, <table>, etc) and replaces any '<' and '>'
+ * characters with respective predefined entity references.
*
* @param input The text to be converted.
* @return The input string with the characters '<' and '>' replaced with
- * < and > respectively.
- */
- static
- public
- String escapeTags(String input) {
+ * &lt; and &gt; respectively.
+ * */
+ static public String escapeTags(String input) {
//Check if the string is null or zero length -- if so, return
//what was sent in.
@@ -53,4 +60,36 @@
}
return buf.toString();
}
+
+ /**
+ * Ensures that embeded CDEnd strings (]]>) are handled properly
+ * within message, NDC and throwable tag text.
+ *
+ * @param buf StringBuffer 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 str The String that is inserted into an existing CDATA Section within buf.
+ * */
+ static public void appendEscapingCDATA(StringBuffer buf, String str) {
+ int end = str.indexOf(CDATA_END);
+
+ if (end < 0) {
+ buf.append(str);
+ return;
+ }
+
+ int start = 0;
+ while (end > -1) {
+ buf.append(str.substring(start,end));
+ buf.append(CDATA_EMBEDED_END);
+ start = end + CDATA_END_LEN;
+ if (start < str.length()) {
+ end = str.indexOf(CDATA_END, start);
+ } else {
+ return;
+ }
+ }
+
+ buf.append(str.substring(start));
+ }
}
diff --git a/src/java/org/apache/log4j/jdbc/JDBCAppender.java b/src/java/org/apache/log4j/jdbc/JDBCAppender.java
index 31bf000..5660b18 100644
--- a/src/java/org/apache/log4j/jdbc/JDBCAppender.java
+++ b/src/java/org/apache/log4j/jdbc/JDBCAppender.java
@@ -14,8 +14,13 @@
/**
- The JDBCAppender provides for sending log events to a database.
+ <p><b><font color="#FF2222">WARNING: This version of JDBCAppender
+ is very likely to be completely replaced in the future. Moreoever,
+ it does not log exceptions.</font></b> </p>
+ The JDBCAppender 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.
@@ -247,10 +252,10 @@
/**
- * JDBCAppender builds a layout internally if one is not provided.
- */
+ * JDBCAppender requires a layout.
+ * */
public boolean requiresLayout() {
- return false;
+ return true;
}
diff --git a/src/java/org/apache/log4j/lf5/LF5Appender.java b/src/java/org/apache/log4j/lf5/LF5Appender.java
index 444b76e..e27dbee 100644
--- a/src/java/org/apache/log4j/lf5/LF5Appender.java
+++ b/src/java/org/apache/log4j/lf5/LF5Appender.java
@@ -88,11 +88,11 @@
*/
public void append(LoggingEvent event) {
// Retrieve the information from the log4j LoggingEvent.
- String category = event.categoryName;
+ String category = event.getLoggerName();
String logMessage = event.getRenderedMessage();
String nestedDiagnosticContext = event.getNDC();
String threadDescription = event.getThreadName();
- String level = event.level.toString();
+ String level = event.getLevel().toString();
long time = event.timeStamp;
LocationInfo locationInfo = event.getLocationInformation();
@@ -255,4 +255,4 @@
// Nested Top-Level Classes or Interfaces:
//--------------------------------------------------------------------------
-}
\ No newline at end of file
+}
diff --git a/src/java/org/apache/log4j/lf5/config/defaultconfig.properties b/src/java/org/apache/log4j/lf5/config/defaultconfig.properties
new file mode 100644
index 0000000..10e30ba
--- /dev/null
+++ b/src/java/org/apache/log4j/lf5/config/defaultconfig.properties
@@ -0,0 +1,16 @@
+# For the general syntax of property based configuration files see the
+# documenation of org.apache.log4j.PropertyConfigurator.
+
+# The root category uses the appender called A1. Since no priority is
+# specified, the root category assumes the default priority for root
+# which is DEBUG in log4j. The root category is the only category that
+# has a default priority. All other categories need not be assigned a
+# priority in which case they inherit their priority from the
+# hierarchy.
+
+log4j.rootCategory=, A1
+
+# A1 is set to be a LogMonitorAppender which outputs to a swing
+# logging console.
+
+log4j.appender.A1=org.apache.log4j.lf5.LF5Appender
diff --git a/src/java/org/apache/log4j/lf5/util/ProductProperties.java b/src/java/org/apache/log4j/lf5/util/ProductProperties.java
deleted file mode 100644
index dc9e41b..0000000
--- a/src/java/org/apache/log4j/lf5/util/ProductProperties.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) The Apache Software Foundation. All rights reserved.
- *
- * This software is published under the terms of the Apache Software
- * License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.txt file.
- */
-package org.apache.log4j.lf5.util;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Properties;
-
-/**
- * ProductProperties holds the properties dealing with
- * this product. There is never a need
- * for multiple instances of this class, thus this class
- * is a singleton.
- *
- * The properties file format is as follows:
- *
- * #Any arbitrary comments are denoted with a #
- *
- * #Mandatory properties
- * product.name=<Product name>
- * product.version.number=<Product version number>
- * product.release.date=<Product release date>
- * product.release.type=<Product release type>
- *
- *
- * Note that this class will throw an ExceptionInInitializerError if
- * initialization fails, or if the required properties are absent.
- *
- * @author Robert Shaw
- * @author Michael J. Sikorsky
- * @author Brent Sprecher
- */
-
-// Contributed by ThoughtWorks Inc.
-
-public class ProductProperties {
- //--------------------------------------------------------------------------
- // Constants:
- //--------------------------------------------------------------------------
-
- //--------------------------------------------------------------------------
- // Protected Variables:
- //--------------------------------------------------------------------------
-
- /** Collection of properties. */
- protected Properties _productProperties;
- //protected final boolean _validFlag;
-
- //--------------------------------------------------------------------------
- // Private Variables:
- //--------------------------------------------------------------------------
- private static ProductProperties _reference = null;
- private static Object _synchronizingObject = new Object();
-
- //--------------------------------------------------------------------------
- // Constructors:
- //--------------------------------------------------------------------------
-
- /**
- * Construct an ProductProperties with the mandatory properties.
- * Use the constructor that configures a ProductProperties
- * off of a properties file if you wish to take advantage
- * of additional properties.
- *
- */
- private ProductProperties() {
- this(new Resource("org/apache/log4j/lf5/lf5.properties"));
- }
-
- private ProductProperties(Resource resource) {
- super();
-
- _productProperties = new Properties();
-
- try {
- InputStream source = getSource(resource);
- byte[] contents = StreamUtils.getBytes(source);
- _productProperties = getProperties(contents);
- source.close();
- validateProductProperties();
- } catch (Exception e) {
- String error = e.getMessage();
- throw new ExceptionInInitializerError(error);
- }
- }
-
-
- //--------------------------------------------------------------------------
- // Public Methods:
- //--------------------------------------------------------------------------
-
- public static ProductProperties getInstance() {
- if (_reference == null) {
- synchronized (_synchronizingObject) {
- if (_reference == null) {
- _reference = new ProductProperties();
- }
- }
- }
- return _reference;
- }
-
- /**
- * Mandatory internally recognized property.
- */
- public static String getPropertyNameOfProductName() {
- return "product.name";
- }
-
- /**
- * Mandatory internally recognized property.
- */
- public static String getPropertyNameOfProductVersionNumber() {
- return "product.version.number";
- }
-
- /**
- * Mandatory internally recognized property.
- */
- public static String getPropertyNameOfProductReleaseDate() {
- return "product.release.date";
- }
-
- /**
- * Get the product name.
- */
- public String getProductName() {
- return _productProperties.getProperty(getPropertyNameOfProductName());
- }
-
- /**
- * Set the product name.
- */
- public void setProductName(String productName) {
- _productProperties.setProperty(getPropertyNameOfProductName(),
- productName);
- }
-
- /**
- * Get the product version number.
- */
- public String getProductVersionNumber() {
- return
- _productProperties.getProperty(getPropertyNameOfProductVersionNumber());
- }
-
- /**
- * Set the product version number.
- */
- public void setProductVersionNumber(String productVersionNumber) {
- _productProperties.setProperty(getPropertyNameOfProductVersionNumber(),
- productVersionNumber);
- }
-
- /**
- * Get the product release date.
- */
- public String getProductReleaseDate() {
- return
- _productProperties.getProperty(getPropertyNameOfProductReleaseDate());
- }
-
- /**
- * Set the product release date.
- */
- public void setProductReleaseDate(String productReleaseDate) {
- _productProperties.setProperty(getPropertyNameOfProductReleaseDate(),
- productReleaseDate);
- }
-
- /**
- * Retrieve any of the mandatory properties, or any additional
- * properties that were placed in the database configuration file.
- */
- public String get(String name) {
- return _productProperties.getProperty(name);
- }
-
- /**
- * Set any property.
- */
- public Object set(String name, String value) {
- return _productProperties.setProperty(name, value);
- }
-
- public String getLogFactor5() {
- return getString("lf5");
- }
-
- public String getString(String propertyName) {
- return String.valueOf(get(propertyName));
- }
-
- //--------------------------------------------------------------------------
- // Protected Methods:
- //--------------------------------------------------------------------------
- /**
- * @throws java.lang.Exception
- */
- protected void validateProductProperties() throws Exception {
- String value = null;
-
- value = getProductVersionNumber();
- if ((value == null) || value.equals("")) {
- throw new Exception("Product version number is null.");
- }
-
- value = getProductReleaseDate();
- if ((value == null) || value.equals("")) {
- throw new Exception("Product release date is null.");
- }
-
- }
-
- //--------------------------------------------------------------------------
- // Private Methods:
- //--------------------------------------------------------------------------
-
- private InputStream getSource(Resource resource) {
- return new BufferedInputStream(
- ResourceUtils.getResourceAsStream(this, resource));
- }
-
- private Properties getProperties(byte[] contents) throws IOException {
- ByteArrayInputStream source = new ByteArrayInputStream(contents);
- Properties result = new Properties();
- result.load(source);
- source.close();
- return result;
- }
-
- //--------------------------------------------------------------------------
- // Nested Top-Level Classes or Interfaces
- //--------------------------------------------------------------------------
-}
-
-
-
-
-
-
diff --git a/src/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java b/src/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java
index 5eacbed..438619e 100644
--- a/src/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java
+++ b/src/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java
@@ -12,7 +12,6 @@
import org.apache.log4j.lf5.LogRecordFilter;
import org.apache.log4j.lf5.util.DateFormatManager;
import org.apache.log4j.lf5.util.LogFileParser;
-import org.apache.log4j.lf5.util.ProductProperties;
import org.apache.log4j.lf5.util.StreamUtils;
import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryExplorerTree;
import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryPath;
@@ -475,8 +474,6 @@
//
// Configure the Frame.
//
- ProductProperties props = ProductProperties.getInstance();
-
_logMonitorFrame = new JFrame("LogFactor5");
_logMonitorFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
@@ -1070,8 +1067,6 @@
JMenu helpMenu = new JMenu("Help");
helpMenu.setMnemonic('h');
helpMenu.add(createHelpProperties());
- helpMenu.addSeparator();
- helpMenu.add(createHelpAbout());
return helpMenu;
}
@@ -1096,25 +1091,6 @@
);
}
- protected JMenuItem createHelpAbout() {
- JMenuItem aboutMI = new JMenuItem("About LogFactor5...");
- aboutMI.setMnemonic('a');
- //aboutMI.setAccelerator( KeyStroke.getKeyStroke("control A") );
-
- aboutMI.addActionListener(
- new ActionListener() {
- protected LogFactor5AboutDialog dialog =
- new LogFactor5AboutDialog(_logMonitorFrame);
-
- public void actionPerformed(ActionEvent e) {
- dialog.show();
- }
- }
-
- );
- return aboutMI;
- }
-
protected JMenu createEditMenu() {
JMenu editMenu = new JMenu("Edit");
editMenu.setMnemonic('e');
@@ -1216,7 +1192,10 @@
_fontSizeCombo = fontSizeCombo;
ClassLoader cl = this.getClass().getClassLoader();
- URL newIconURL = cl.getResource("org/apache/log4j/viewer/" +
+ if(cl == null) {
+ cl = ClassLoader.getSystemClassLoader();
+ }
+ URL newIconURL = cl.getResource("org/apache/log4j/lf5/viewer/" +
"images/channelexplorer_new.gif");
ImageIcon newIcon = null;
diff --git a/src/java/org/apache/log4j/lf5/viewer/LogFactor5AboutDialog.java b/src/java/org/apache/log4j/lf5/viewer/LogFactor5AboutDialog.java
deleted file mode 100644
index ef24a82..0000000
--- a/src/java/org/apache/log4j/lf5/viewer/LogFactor5AboutDialog.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) The Apache Software Foundation. All rights reserved.
- *
- * This software is published under the terms of the Apache Software
- * License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.txt file.
- */
-package org.apache.log4j.lf5.viewer;
-
-import org.apache.log4j.lf5.util.ProductProperties;
-import org.apache.log4j.lf5.util.Resource;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.net.URL;
-
-/**
- * LogFactor5AboutDialog
- *
- * @author Michael J. Sikorsky
- * @author Robert Shaw
- * @author Brent Sprecher
- * @author Brad Marlborough
- */
-
-// Contributed by ThoughtWorks Inc.
-
-public class LogFactor5AboutDialog extends JDialog {
- //--------------------------------------------------------------------------
- // Constants:
- //--------------------------------------------------------------------------
-
- //--------------------------------------------------------------------------
- // Protected Variables:
- //--------------------------------------------------------------------------
-
- //--------------------------------------------------------------------------
- // Private Variables:
- //--------------------------------------------------------------------------
-
- //--------------------------------------------------------------------------
- // Constructors:
- //--------------------------------------------------------------------------
-
- //--------------------------------------------------------------------------
- // Public Methods:
- //--------------------------------------------------------------------------
-
- public LogFactor5AboutDialog(Frame owner) {
- super(owner, "About LogFactor5", true);
-
- ProductProperties props = ProductProperties.getInstance();
-
- setTitle("About LogFactor5");
-
- JPanel imagePanel = new JPanel();
- Resource aboutResource = new Resource("org/apache/log4j/lf5/viewer/images/" +
- "lf5_about.gif");
- URL aboutIconURL = aboutResource.getURL();
- ImageIcon aboutIcon = null;
- if (aboutIconURL != null) {
- aboutIcon = new ImageIcon(aboutIconURL);
- }
-
- JLabel imageLabel = new JLabel();
-
- if (aboutIcon != null) {
- imageLabel.setIcon(aboutIcon);
- }
- imagePanel.add(imageLabel);
-
- JPanel textPanel = new JPanel();
- textPanel.setLayout(new GridLayout(3, 1));
-
-
- int numberOfRows = 13;
- numberOfRows = 11; // we need less room for a registered user.
- JPanel mainPanel = new JPanel();
- mainPanel.setLayout(new GridLayout(numberOfRows, 1));
- JLabel aboutLF5 = new JLabel("LogFactor5 v" + props.getProductVersionNumber(), JLabel.CENTER);
- aboutLF5.setHorizontalAlignment(SwingConstants.CENTER);
- JLabel donate = new JLabel("Contributed by ThoughtWorks Inc.");
- donate.setHorizontalAlignment(SwingConstants.CENTER);
- mainPanel.add(aboutLF5);
- mainPanel.add(Box.createVerticalStrut(10));
- mainPanel.add(donate);
- mainPanel.add(Box.createVerticalStrut(10));
-
- JButton ok = new JButton("OK");
- JPanel southPanel = new JPanel();
- southPanel.setLayout(new FlowLayout());
- southPanel.add(ok);
- ok.addActionListener(
- new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- hide();
- }
- }
-
- );
- getContentPane().add(imagePanel, BorderLayout.NORTH);
- getContentPane().add(mainPanel, BorderLayout.CENTER);
- getContentPane().add(southPanel, BorderLayout.SOUTH);
- setSize(414, 400);
- center();
- }
- //--------------------------------------------------------------------------
- // Protected Methods:
- //--------------------------------------------------------------------------
-
- protected void center() {
- Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
- Dimension comp = getSize();
-
- setLocation(((screen.width - comp.width) / 2),
- ((screen.height - comp.height) / 2));
-
- }
-
- //--------------------------------------------------------------------------
- // Private Methods:
- //--------------------------------------------------------------------------
-
- //--------------------------------------------------------------------------
- // Nested Top-Level Classes or Interfaces:
- //--------------------------------------------------------------------------
-
-}
-
-
-
-
-
-
diff --git a/src/java/org/apache/log4j/lf5/viewer/configure/ConfigurationManager.java b/src/java/org/apache/log4j/lf5/viewer/configure/ConfigurationManager.java
index 3e389d8..0fb1c26 100644
--- a/src/java/org/apache/log4j/lf5/viewer/configure/ConfigurationManager.java
+++ b/src/java/org/apache/log4j/lf5/viewer/configure/ConfigurationManager.java
@@ -330,8 +330,7 @@
protected String getFilename() {
String home = System.getProperty("user.home");
- String sep = (home.startsWith(MRUFileManager.UNIX_SEPARATOR))
- ? MRUFileManager.UNIX_SEPARATOR : MRUFileManager.DOS_SEPARATOR;
+ String sep = System.getProperty("file.separator");
return home + sep + "lf5" + sep + CONFIG_FILE_NAME;
}
diff --git a/src/java/org/apache/log4j/lf5/viewer/configure/MRUFileManager.java b/src/java/org/apache/log4j/lf5/viewer/configure/MRUFileManager.java
index 5163a07..5e124ca 100644
--- a/src/java/org/apache/log4j/lf5/viewer/configure/MRUFileManager.java
+++ b/src/java/org/apache/log4j/lf5/viewer/configure/MRUFileManager.java
@@ -29,8 +29,6 @@
//--------------------------------------------------------------------------
private static final String CONFIG_FILE_NAME = "mru_file_manager";
private static final int DEFAULT_MAX_SIZE = 3;
- public static final String UNIX_SEPARATOR = "/";
- public static final String DOS_SEPARATOR = "\\";
//--------------------------------------------------------------------------
// Protected Variables:
@@ -74,7 +72,6 @@
// do nothing
e.printStackTrace();
}
-
}
/**
@@ -112,7 +109,6 @@
return null;
}
-
/**
* Adds a file name to the MRU file list.
*/
@@ -168,7 +164,7 @@
*/
public static void createConfigurationDirectory() {
String home = System.getProperty("user.home");
- String sep = (home.startsWith(UNIX_SEPARATOR)) ? UNIX_SEPARATOR : DOS_SEPARATOR;
+ String sep = System.getProperty("file.separator");
File f = new File(home + sep + "lf5");
if (!f.exists()) {
try {
@@ -253,7 +249,7 @@
protected String getFilename() {
String home = System.getProperty("user.home");
- String sep = (home.startsWith(UNIX_SEPARATOR)) ? UNIX_SEPARATOR : DOS_SEPARATOR;
+ String sep = System.getProperty("file.separator");
return home + sep + "lf5" + sep + CONFIG_FILE_NAME;
}
@@ -264,7 +260,7 @@
protected void setMaxSize(int maxSize) {
if (maxSize < _mruFileList.size()) {
for (int i = 0; i < _mruFileList.size() - maxSize; i++) {
- _mruFileList.removeFirst();
+ _mruFileList.removeLast();
}
}
diff --git a/src/java/org/apache/log4j/lf5/viewer/images/lf5_about.gif b/src/java/org/apache/log4j/lf5/viewer/images/lf5_about.gif
deleted file mode 100644
index cdc59ef..0000000
--- a/src/java/org/apache/log4j/lf5/viewer/images/lf5_about.gif
+++ /dev/null
Binary files differ
diff --git a/src/java/org/apache/log4j/lf5/viewer/images/lf5_small_icon.png b/src/java/org/apache/log4j/lf5/viewer/images/lf5_small_icon.png
deleted file mode 100644
index d3462e3..0000000
--- a/src/java/org/apache/log4j/lf5/viewer/images/lf5_small_icon.png
+++ /dev/null
Binary files differ
diff --git a/src/java/org/apache/log4j/net/JMSAppender.java b/src/java/org/apache/log4j/net/JMSAppender.java
index 165ed1a..21895c9 100644
--- a/src/java/org/apache/log4j/net/JMSAppender.java
+++ b/src/java/org/apache/log4j/net/JMSAppender.java
@@ -12,25 +12,98 @@
import org.apache.log4j.spi.ErrorCode;
import org.apache.log4j.helpers.LogLog;
-import javax.jms.*;
+import java.util.Properties;
+import javax.jms.TopicConnection;
+import javax.jms.TopicConnectionFactory;
+import javax.jms.Topic;
+import javax.jms.TopicPublisher;
+import javax.jms.TopicSession;
+import javax.jms.Session;
+import javax.jms.ObjectMessage;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
/**
- A simple appender based on JMS.
+ * A simple appender that publishes events to a JMS Topic. The events
+ * are serialized and transmitted as JMS message type {@link
+ * ObjectMessage}.
- @author Ceki Gülcü
-*/
+ * <p>JMS {@link Topic topics} and {@link TopicConnectionFactory topic
+ * connection factories} are administered objects that are retrieved
+ * using JNDI messaging which in turn requires the retreival of a JNDI
+ * {@link Context}.
+
+ * <p>There are two common methods for retrieving a JNDI {@link
+ * Context}. If a file resource named <em>jndi.properties</em> is
+ * available to the JNDI API, it will use the information found
+ * therein to retrieve an initial JNDI context. To obtain an initial
+ * context, your code will simply call:
+
+ <pre>
+ InitialContext jndiContext = new InitialContext();
+ </pre>
+
+ * <p>Calling the no-argument <code>InitialContext()</code> method
+ * will also work from within Enterprise Java Beans (EJBs) because it
+ * is part of the EJB contract for application servers to provide each
+ * bean an environment naming context (ENC).
+
+ * <p>In the second approach, several predetermined properties are set
+ * and these properties are passed to the <code>InitialContext</code>
+ * contructor to connect to the naming service provider. For example,
+ * to connect to JBoss naming service one would write:
+
+<pre>
+ Properties env = new Properties( );
+ env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
+ env.put(Context.PROVIDER_URL, "jnp://hostname:1099");
+ env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
+ InitialContext jndiContext = new InitialContext(env);
+</pre>
+
+ * where <em>hostname</em> is the host where the JBoss applicaiton
+ * server is running.
+ *
+ * <p>To connect to the the naming service of Weblogic application
+ * server one would write:
+
+<pre>
+ Properties env = new Properties( );
+ env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
+ env.put(Context.PROVIDER_URL, "t3://localhost:7001");
+ InitialContext jndiContext = new InitialContext(env);
+</pre>
+
+ * <p>Other JMS providers will obviously require different values.
+ *
+ * The initial JNDI context can be obtained by calling the
+ * no-argument <code>InitialContext()</code> method in EJBs. Only
+ * clients running in a separate JVM need to be concerned about the
+ * <em>jndi.properties</em> file and calling {@link
+ * InitialContext#InitialContext()} or alternatively correctly
+ * setting the different properties before calling {@link
+ * InitialContext#InitialContext(java.util.Hashtable)} method.
+
+
+ @author Ceki Gülcü */
public class JMSAppender extends AppenderSkeleton {
+ String securityPrincipalName;
+ String securityCredentials;
+ String initialContextFactoryName;
+ String urlPkgPrefixes;
+ String providerURL;
+ String topicBindingName;
+ String tcfBindingName;
+ String userName;
+ String password;
+ boolean locationInfo;
+
TopicConnection topicConnection;
TopicSession topicSession;
TopicPublisher topicPublisher;
- String topicBindingName;
- String tcfBindingName;
- boolean locationInfo;
public
JMSAppender() {
@@ -82,31 +155,75 @@
return locationInfo;
}
- public
- void activateOptions() {
+ /**
+ * Options are activated and become effective only after calling
+ * this method.*/
+ public void activateOptions() {
TopicConnectionFactory topicConnectionFactory;
try {
- Context ctx = new InitialContext();
- topicConnectionFactory = (TopicConnectionFactory) lookup(ctx, tcfBindingName);
- topicConnection = topicConnectionFactory.createTopicConnection();
- topicConnection.start();
+ Context jndi;
+ LogLog.debug("Getting initial context.");
+ if(initialContextFactoryName != null) {
+ Properties env = new Properties( );
+ env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactoryName);
+ if(providerURL != null) {
+ env.put(Context.PROVIDER_URL, providerURL);
+ } else {
+ LogLog.warn("You have set InitialContextFactoryName option but not the "
+ +"ProviderURL. This is likely to cause problems.");
+ }
+ if(urlPkgPrefixes != null) {
+ env.put(Context.URL_PKG_PREFIXES, urlPkgPrefixes);
+ }
+
+ if(securityPrincipalName != null) {
+ env.put(Context.SECURITY_PRINCIPAL, securityPrincipalName);
+ if(securityCredentials != null) {
+ env.put(Context.SECURITY_CREDENTIALS, securityCredentials);
+ } else {
+ LogLog.warn("You have set SecurityPrincipalName option but not the "
+ +"SecurityCredentials. This is likely to cause problems.");
+ }
+ }
+ jndi = new InitialContext(env);
+ } else {
+ jndi = new InitialContext();
+ }
+
+ LogLog.debug("Looking up ["+tcfBindingName+"]");
+ topicConnectionFactory = (TopicConnectionFactory) lookup(jndi, tcfBindingName);
+ LogLog.debug("About to create TopicConnection.");
+ if(userName != null) {
+ topicConnection = topicConnectionFactory.createTopicConnection(userName,
+ password);
+ } else {
+ topicConnection = topicConnectionFactory.createTopicConnection();
+ }
+
+ LogLog.debug("Creating TopicSession, non-transactional, "
+ +"in AUTO_ACKNOWLEDGE mode.");
topicSession = topicConnection.createTopicSession(false,
Session.AUTO_ACKNOWLEDGE);
- Topic topic = (Topic) lookup(ctx, topicBindingName);
- topicPublisher = topicSession.createPublisher(topic);
+ LogLog.debug("Looking up topic name ["+topicBindingName+"].");
+ Topic topic = (Topic) lookup(jndi, topicBindingName);
- ctx.close();
+ LogLog.debug("Creating TopicPublisher.");
+ topicPublisher = topicSession.createPublisher(topic);
+
+ LogLog.debug("Starting TopicConnection.");
+ topicConnection.start();
+
+ jndi.close();
} catch(Exception e) {
errorHandler.error("Error while activating options for appender named ["+name+
"].", e, ErrorCode.GENERIC_FAILURE);
}
}
- protected
- Object lookup(Context ctx, String name) throws NamingException {
+ protected Object lookup(Context ctx, String name) throws NamingException {
try {
return ctx.lookup(name);
} catch(NameNotFoundException e) {
@@ -115,8 +232,7 @@
}
}
- protected
- boolean checkEntryConditions() {
+ protected boolean checkEntryConditions() {
String fail = null;
if(this.topicConnection == null) {
@@ -138,9 +254,9 @@
/**
Close this JMSAppender. Closing releases all resources used by the
appender. A closed appender cannot be re-opened. */
- public
- synchronized // avoid concurrent append and close operations
- void close() {
+ public synchronized void close() {
+ // The synchronized modifier avoids concurrent append and close operations
+
if(this.closed)
return;
@@ -164,8 +280,7 @@
/**
This method called by {@link AppenderSkeleton#doAppend} method to
do most of the real appending work. */
- public
- void append(LoggingEvent event) {
+ public void append(LoggingEvent event) {
if(!checkEntryConditions()) {
return;
}
@@ -184,17 +299,101 @@
}
/**
- If true, the information sent to the remote subscriber will include
- location information. By default no location information is sent
- to the subscriber. */
- public
- void setLocationInfo(boolean locationInfo) {
+ * Returns the value of the <b>InitialContextFactoryName</b> option.
+ * See {@link #setInitialContextFactoryName} for more details on the
+ * meaning of this option.
+ * */
+ public String getInitialContextFactoryName() {
+ return initialContextFactoryName;
+ }
+
+ /**
+ * Setting the <b>InitialContextFactoryName</b> method will cause
+ * this <code>JMSAppender</code> instance to use the {@link
+ * InitialContext#InitialContext(Hashtable)} method instead of the
+ * no-argument constructor. If you set this option, you should also
+ * at least set the <b>ProviderURL</b> option.
+ *
+ * <p>See also {@link #setProviderURL(String)}.
+ * */
+ public void setInitialContextFactoryName(String initialContextFactoryName) {
+ this.initialContextFactoryName = initialContextFactoryName;
+ }
+
+ public String getProviderURL() {
+ return providerURL;
+ }
+
+ public void setProviderURL(String providerURL) {
+ this.providerURL = providerURL;
+ }
+
+ String getURLPkgPrefixes( ) {
+ return urlPkgPrefixes;;
+ }
+
+ public void setURLPkgPrefixes(String urlPkgPrefixes ) {
+ this.urlPkgPrefixes = urlPkgPrefixes;
+ }
+
+ public String getSecurityCredentials() {
+ return securityCredentials;
+ }
+
+ public void setSecurityCredentials(String securityCredentials) {
+ this.securityCredentials = securityCredentials;
+ }
+
+
+ public String getSecurityPrincipalName() {
+ return securityPrincipalName;
+ }
+
+ public void setSecurityPrincipalName(String securityPrincipalName) {
+ this.securityPrincipalName = securityPrincipalName;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ /**
+ * The user name to use when {@link
+ * TopicConnectionFactory#createTopicConnection(String, String)
+ * creating a topic session}. If you set this option, you should
+ * also set the <b>Password</b> option. See {@link
+ * #setPassword(String)}.
+ * */
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ /**
+ * The paswword to use when creating a topic session.
+ */
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+
+ /**
+ If true, the information sent to the remote subscriber will
+ include caller's location information. By default no location
+ information is sent to the subscriber. */
+ public void setLocationInfo(boolean locationInfo) {
this.locationInfo = locationInfo;
}
- public
- boolean requiresLayout() {
+ /**
+ * The JMSAppender sends serialized events and consequently does not
+ * require a layout.
+ * */
+ public boolean requiresLayout() {
return false;
}
}
diff --git a/src/java/org/apache/log4j/net/JMSSink.java b/src/java/org/apache/log4j/net/JMSSink.java
index 877df00..f55e629 100644
--- a/src/java/org/apache/log4j/net/JMSSink.java
+++ b/src/java/org/apache/log4j/net/JMSSink.java
@@ -8,43 +8,83 @@
package org.apache.log4j.net;
import org.apache.log4j.spi.LoggingEvent;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import org.apache.log4j.spi.RendererSupport;
import org.apache.log4j.spi.LoggerRepository;
import org.apache.log4j.or.jms.MessageRenderer;
import org.apache.log4j.PropertyConfigurator;
+import org.apache.log4j.xml.DOMConfigurator;
import org.apache.log4j.helpers.LogLog;
-import javax.jms.*;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.TopicConnection;
+import javax.jms.Topic;
+import javax.jms.TopicConnectionFactory;
+import javax.jms.TopicSubscriber;
+import javax.jms.Session;
+import javax.jms.TopicSession;
+import javax.jms.ObjectMessage;
+import javax.jms.JMSException;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
+import java.util.Properties;
/**
- A simple application receiving the logging events sent by a JMSAppender.
+ * A simple application that consumes logging events sent by a {@link
+ * JMSAppender}.
+ *
+ *
+ * @author Ceki Gülcü
+ * */
+public class JMSSink implements javax.jms.MessageListener {
+ static Logger logger = Logger.getLogger(JMSSink.class);
- @author Ceki Gülcü
-*/
-public class JMSSink {
-
- static public void main(String[] args) {
- if(args.length != 3) {
+ static public void main(String[] args) throws Exception {
+ if(args.length != 5) {
usage("Wrong number of arguments.");
}
-
+
String tcfBindingName = args[0];
String topicBindingName = args[1];
- PropertyConfigurator.configure(args[2]);
+ String username = args[2];
+ String password = args[3];
+
+
+ String configFile = args[4];
- LoggerRepository rep = LogManager.getLoggerRepository();
- if(rep instanceof RendererSupport) {
- ((RendererSupport) rep).setRenderer(Message.class, new MessageRenderer());
+ if(configFile.endsWith(".xml")) {
+ new DOMConfigurator().configure(configFile);
+ } else {
+ new PropertyConfigurator().configure(configFile);
}
+
+ new JMSSink(tcfBindingName, topicBindingName, username, password);
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ // Loop until the word "exit" is typed
+ System.out.println("Type \"exit\" to quit JMSSink.");
+ while(true){
+ String s = stdin.readLine( );
+ if (s.equalsIgnoreCase("exit")) {
+ System.out.println("Exiting. Kill the application if it does not exit "
+ + "due to daemon threads.");
+ return;
+ }
+ }
+ }
+
+ public JMSSink( String tcfBindingName, String topicBindingName, String username,
+ String password) {
+
try {
Context ctx = new InitialContext();
TopicConnectionFactory topicConnectionFactory;
@@ -52,7 +92,8 @@
tcfBindingName);
TopicConnection topicConnection =
- topicConnectionFactory.createTopicConnection();
+ topicConnectionFactory.createTopicConnection(username,
+ password);
topicConnection.start();
TopicSession topicSession = topicConnection.createTopicSession(false,
@@ -60,47 +101,49 @@
Topic topic = (Topic)ctx.lookup(topicBindingName);
- //TopicSubscriber topicSubscriber = topicSession.createSubscriber(topic);
- TopicSubscriber topicSubscriber =
- topicSession.createDurableSubscriber(topic, "x");
+ TopicSubscriber topicSubscriber = topicSession.createSubscriber(topic);
+
+ topicSubscriber.setMessageListener(this);
-
- LoggingEvent event;
- Category remoteCategory;
-
- while(true) {
- ObjectMessage msg = (ObjectMessage)topicSubscriber.receive();
- event = (LoggingEvent) msg.getObject();
- remoteCategory = Category.getInstance(event.categoryName);
- remoteCategory.callAppenders(event);
-
- // dump the JMSMessage
- // remoteCategory.debug(msg);
-
- }
} catch(Exception e) {
- LogLog.error("Could not read JMS message.", e);
+ logger.error("Could not read JMS message.", e);
+ }
+ }
+
+ public void onMessage(javax.jms.Message message) {
+ LoggingEvent event;
+ Logger remoteLogger;
+
+ try {
+ if(message instanceof ObjectMessage) {
+ ObjectMessage objectMessage = (ObjectMessage) message;
+ event = (LoggingEvent) objectMessage.getObject();
+ remoteLogger = Logger.getLogger(event.getLoggerName());
+ remoteLogger.callAppenders(event);
+ } else {
+ logger.warn("Received message is of type "+message.getJMSType()
+ +", was expecting ObjectMessage.");
+ }
+ } catch(JMSException jmse) {
+ logger.error("Exception thrown while processing incoming message.",
+ jmse);
}
}
- protected
- static
- Object lookup(Context ctx, String name) throws NamingException {
+ protected static Object lookup(Context ctx, String name) throws NamingException {
try {
return ctx.lookup(name);
} catch(NameNotFoundException e) {
- LogLog.error("Could not find name ["+name+"].");
+ logger.error("Could not find name ["+name+"].");
throw e;
}
}
-
- static
- void usage(String msg) {
+ static void usage(String msg) {
System.err.println(msg);
System.err.println("Usage: java " + JMSSink.class.getName()
- + " TopicConnectionFactoryBindingName TopicBindingName configFile");
+ + " TopicConnectionFactoryBindingName TopicBindingName username password configFile");
System.exit(1);
}
}
diff --git a/src/java/org/apache/log4j/net/SMTPAppender.java b/src/java/org/apache/log4j/net/SMTPAppender.java
index bca7aca..3e4929d 100644
--- a/src/java/org/apache/log4j/net/SMTPAppender.java
+++ b/src/java/org/apache/log4j/net/SMTPAppender.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.net;
diff --git a/src/java/org/apache/log4j/net/SimpleSocketServer.java b/src/java/org/apache/log4j/net/SimpleSocketServer.java
index f8ca382..8467d89 100644
--- a/src/java/org/apache/log4j/net/SimpleSocketServer.java
+++ b/src/java/org/apache/log4j/net/SimpleSocketServer.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.net;
@@ -13,23 +13,24 @@
import org.apache.log4j.Category;
import org.apache.log4j.LogManager;
import org.apache.log4j.PropertyConfigurator;
+import org.apache.log4j.xml.DOMConfigurator;
/**
- A simple {@link SocketNode} based server.
-
+ * A simple {@link SocketNode} based server.
+ *
<pre>
- <b>Usage:</b> java org.apache.log4j.net.SimpleSocketServer port configFile
+ <b>Usage:</b> java org.apache.log4j.net.SimpleSocketServer port configFile
- where <em>port</em> is a part number where the server listens and
- <em>configFile</em> is a configuration file fed to the {@link
- PropertyConfigurator}.
+ where <em>port</em> is a part number where the server listens and
+ <em>configFile</em> is a configuration file fed to the {@link
+ PropertyConfigurator} or to {@link DOMConfigurator} if an XML file.
</pre>
-
- @author Ceki Gülcü
-
- @since 0.8.4 */
-
+ *
+ * @author Ceki Gülcü
+ *
+ * @since 0.8.4
+ * */
public class SimpleSocketServer {
static Category cat = Category.getInstance(SimpleSocketServer.class.getName());
@@ -39,11 +40,12 @@
public
static
void main(String argv[]) {
- if(argv.length == 2)
+ if(argv.length == 2) {
init(argv[0], argv[1]);
- else
+ } else {
usage("Wrong number of arguments.");
-
+ }
+
try {
cat.info("Listening on port " + port);
ServerSocket serverSocket = new ServerSocket(port);
@@ -55,30 +57,31 @@
new Thread(new SocketNode(socket,
LogManager.getLoggerRepository())).start();
}
- }
- catch(Exception e) {
+ } catch(Exception e) {
e.printStackTrace();
}
}
- static
- void usage(String msg) {
+ static void usage(String msg) {
System.err.println(msg);
System.err.println(
"Usage: java " +SimpleSocketServer.class.getName() + " port configFile");
System.exit(1);
}
- static
- void init(String portStr, String configFile) {
+ static void init(String portStr, String configFile) {
try {
port = Integer.parseInt(portStr);
- }
- catch(java.lang.NumberFormatException e) {
+ } catch(java.lang.NumberFormatException e) {
e.printStackTrace();
usage("Could not interpret port number ["+ portStr +"].");
}
- PropertyConfigurator.configure(configFile);
+
+ if(configFile.endsWith(".xml")) {
+ new DOMConfigurator().configure(configFile);
+ } else {
+ new PropertyConfigurator().configure(configFile);
+ }
}
}
diff --git a/src/java/org/apache/log4j/net/SocketAppender.java b/src/java/org/apache/log4j/net/SocketAppender.java
index 6b91bea..fcdb27b 100644
--- a/src/java/org/apache/log4j/net/SocketAppender.java
+++ b/src/java/org/apache/log4j/net/SocketAppender.java
@@ -128,8 +128,7 @@
/**
Connects to remote server at <code>address</code> and <code>port</code>.
*/
- public
- SocketAppender(InetAddress address, int port) {
+ public SocketAppender(InetAddress address, int port) {
this.address = address;
this.remoteHost = address.getHostName();
this.port = port;
@@ -139,8 +138,7 @@
/**
Connects to remote server at <code>host</code> and <code>port</code>.
*/
- public
- SocketAppender(String host, int port) {
+ public SocketAppender(String host, int port) {
this.port = port;
this.address = getAddressByName(host);
this.remoteHost = host;
@@ -150,19 +148,17 @@
/**
Connect to the specified <b>RemoteHost</b> and <b>Port</b>.
*/
- public
- void activateOptions() {
+ public void activateOptions() {
connect(address, port);
}
/**
- Close this appender.
- <p>This will mark the appender as closed and
- call then {@link #cleanUp} method.
- */
- synchronized
- public
- void close() {
+ * Close this appender.
+ *
+ * <p>This will mark the appender as closed and call then {@link
+ * #cleanUp} method.
+ * */
+ synchronized public void close() {
if(closed)
return;
@@ -171,16 +167,14 @@
}
/**
- Drop the connection to the remote host and release the underlying
- connector thread if it has been created
- */
- public
- void cleanUp() {
+ * Drop the connection to the remote host and release the underlying
+ * connector thread if it has been created
+ * */
+ public void cleanUp() {
if(oos != null) {
try {
oos.close();
- }
- catch(IOException e) {
+ } catch(IOException e) {
LogLog.error("Could not close oos.", e);
}
oos = null;
@@ -199,8 +193,7 @@
// First, close the previous connection if any.
cleanUp();
oos = new ObjectOutputStream(new Socket(address, port).getOutputStream());
- }
- catch(IOException e) {
+ } catch(IOException e) {
LogLog.error("Could not connect to remote log4j server at ["
+address.getHostName()+"]. We will try again later.", e);
fireConnector();
@@ -208,8 +201,7 @@
}
- public
- void append(LoggingEvent event) {
+ public void append(LoggingEvent event) {
if(event == null)
return;
@@ -234,8 +226,7 @@
//System.err.println("Doing oos.reset()");
oos.reset();
}
- }
- catch(IOException e) {
+ } catch(IOException e) {
oos = null;
LogLog.warn("Detected problem with connection: "+e);
if(reconnectionDelay > 0) {
@@ -259,28 +250,26 @@
InetAddress getAddressByName(String host) {
try {
return InetAddress.getByName(host);
- }
- catch(Exception e) {
+ } catch(Exception e) {
LogLog.error("Could not find address of ["+host+"].", e);
return null;
}
}
/**
- The SocketAppender does not use a layout. Hence, this method returns
- <code>false</code>.
- */
- public
- boolean requiresLayout() {
+ * The SocketAppender does not use a layout. Hence, this method
+ * returns <code>false</code>.
+ * */
+ public boolean requiresLayout() {
return false;
}
/**
- The <b>RemoteHost</b> option takes a string value which should be
- the host name of the server where a {@link SocketNode} is running.
- */
- public
- void setRemoteHost(String host) {
+ * The <b>RemoteHost</b> option takes a string value which should be
+ * the host name of the server where a {@link SocketNode} is
+ * running.
+ * */
+ public void setRemoteHost(String host) {
address = getAddressByName(host);
remoteHost = host;
}
@@ -288,8 +277,7 @@
/**
Returns value of the <b>RemoteHost</b> option.
*/
- public
- String getRemoteHost() {
+ public String getRemoteHost() {
return remoteHost;
}
@@ -297,16 +285,14 @@
The <b>Port</b> option takes a positive integer representing
the port where the server is waiting for connections.
*/
- public
- void setPort(int port) {
+ public void setPort(int port) {
this.port = port;
}
/**
Returns value of the <b>Port</b> option.
*/
- public
- int getPort() {
+ public int getPort() {
return port;
}
@@ -315,16 +301,14 @@
the information sent to the remote host will include location
information. By default no location information is sent to the server.
*/
- public
- void setLocationInfo(boolean locationInfo) {
+ public void setLocationInfo(boolean locationInfo) {
this.locationInfo = locationInfo;
}
/**
Returns value of the <b>LocationInfo</b> option.
*/
- public
- boolean getLocationInfo() {
+ public boolean getLocationInfo() {
return locationInfo;
}
@@ -337,16 +321,14 @@
<p>Setting this option to zero turns off reconnection
capability.
*/
- public
- void setReconnectionDelay(int delay) {
+ public void setReconnectionDelay(int delay) {
this.reconnectionDelay = delay;
}
/**
Returns value of the <b>ReconnectionDelay</b> option.
*/
- public
- int getReconnectionDelay() {
+ public int getReconnectionDelay() {
return reconnectionDelay;
}
@@ -377,18 +359,16 @@
synchronized(this) {
oos = new ObjectOutputStream(socket.getOutputStream());
connector = null;
+ LogLog.debug("Connection established. Exiting connector thread.");
break;
}
- }
- catch(InterruptedException e) {
+ } catch(InterruptedException e) {
LogLog.debug("Connector interrupted. Leaving loop.");
return;
- }
- catch(java.net.ConnectException e) {
+ } catch(java.net.ConnectException e) {
LogLog.debug("Remote host "+address.getHostName()
+" refused connection.");
- }
- catch(IOException e) {
+ } catch(IOException e) {
LogLog.debug("Could not connect to " + address.getHostName()+
". Exception is " + e);
}
diff --git a/src/java/org/apache/log4j/net/SocketNode.java b/src/java/org/apache/log4j/net/SocketNode.java
index 4bcbd82..981689a 100644
--- a/src/java/org/apache/log4j/net/SocketNode.java
+++ b/src/java/org/apache/log4j/net/SocketNode.java
@@ -39,8 +39,7 @@
static Logger logger = Logger.getLogger(SocketNode.class);
- public
- SocketNode(Socket socket, LoggerRepository hierarchy) {
+ public SocketNode(Socket socket, LoggerRepository hierarchy) {
this.socket = socket;
this.hierarchy = hierarchy;
try {
@@ -64,15 +63,18 @@
try {
while(true) {
+ // read an event from the wire
event = (LoggingEvent) ois.readObject();
- remoteLogger = hierarchy.getLogger(event.categoryName);
- event.logger = remoteLogger;
- if(event.level.isGreaterOrEqual(remoteLogger.getEffectiveLevel())) {
+ // get a logger from the hierarchy. The name of the logger is taken to be the name contained in the event.
+ remoteLogger = hierarchy.getLogger(event.getLoggerName());
+ //event.logger = remoteLogger;
+ // apply the logger-level filter
+ if(event.getLevel().isGreaterOrEqual(remoteLogger.getEffectiveLevel())) {
+ // finally log the event as if was generated locally
remoteLogger.callAppenders(event);
}
}
- }
- catch(java.io.EOFException e) {
+ } catch(java.io.EOFException e) {
logger.info("Caught java.io.EOFException closing conneciton.");
} catch(java.net.SocketException e) {
logger.info("Caught java.net.SocketException closing conneciton.");
diff --git a/src/java/org/apache/log4j/net/SyslogAppender.java b/src/java/org/apache/log4j/net/SyslogAppender.java
index d3c2d83..a3fae19 100644
--- a/src/java/org/apache/log4j/net/SyslogAppender.java
+++ b/src/java/org/apache/log4j/net/SyslogAppender.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.net;
@@ -228,7 +228,7 @@
public
void append(LoggingEvent event) {
- if(!isAsSevereAsThreshold(event.level))
+ if(!isAsSevereAsThreshold(event.getLevel()))
return;
// We must not attempt to append if sqw is null.
@@ -241,7 +241,7 @@
String buffer = (facilityPrinting? facilityStr : "") +
layout.format(event);
- sqw.setLevel(event.level.getSyslogEquivalent());
+ sqw.setLevel(event.getLevel().getSyslogEquivalent());
sqw.write(buffer);
String[] s = event.getThrowableStrRep();
diff --git a/src/java/org/apache/log4j/net/test/Loop.java b/src/java/org/apache/log4j/net/test/Loop.java
index e5242f3..40643b6 100644
--- a/src/java/org/apache/log4j/net/test/Loop.java
+++ b/src/java/org/apache/log4j/net/test/Loop.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.net.test;
diff --git a/src/java/org/apache/log4j/net/test/SMTPMin.java b/src/java/org/apache/log4j/net/test/SMTPMin.java
index 6777157..51e86e6 100644
--- a/src/java/org/apache/log4j/net/test/SMTPMin.java
+++ b/src/java/org/apache/log4j/net/test/SMTPMin.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.net.test;
diff --git a/src/java/org/apache/log4j/net/test/SocketMin.java b/src/java/org/apache/log4j/net/test/SocketMin.java
index 15ab781..cf317ba 100644
--- a/src/java/org/apache/log4j/net/test/SocketMin.java
+++ b/src/java/org/apache/log4j/net/test/SocketMin.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.net.test;
diff --git a/src/java/org/apache/log4j/net/test/SyslogMin.java b/src/java/org/apache/log4j/net/test/SyslogMin.java
index 3c8f039..6cacc73 100644
--- a/src/java/org/apache/log4j/net/test/SyslogMin.java
+++ b/src/java/org/apache/log4j/net/test/SyslogMin.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.net.test;
diff --git a/src/java/org/apache/log4j/nt/NTEventLogAppender.java b/src/java/org/apache/log4j/nt/NTEventLogAppender.java
index 0f663a3..b401239 100644
--- a/src/java/org/apache/log4j/nt/NTEventLogAppender.java
+++ b/src/java/org/apache/log4j/nt/NTEventLogAppender.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.nt;
@@ -110,7 +110,7 @@
}
}
// Normalize the log message level into the supported categories
- int nt_category = event.level.toInt();
+ int nt_category = event.getLevel().toInt();
// Anything above FATAL or below DEBUG is labeled as INFO.
//if (nt_category > FATAL || nt_category < DEBUG) {
diff --git a/src/java/org/apache/log4j/nt/test/NTMin.java b/src/java/org/apache/log4j/nt/test/NTMin.java
index 52351c1..49fc20a 100644
--- a/src/java/org/apache/log4j/nt/test/NTMin.java
+++ b/src/java/org/apache/log4j/nt/test/NTMin.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.nt.test;
diff --git a/src/java/org/apache/log4j/or/DefaultRenderer.java b/src/java/org/apache/log4j/or/DefaultRenderer.java
index d4066c9..acf191d 100644
--- a/src/java/org/apache/log4j/or/DefaultRenderer.java
+++ b/src/java/org/apache/log4j/or/DefaultRenderer.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.or;
diff --git a/src/java/org/apache/log4j/or/ObjectRenderer.java b/src/java/org/apache/log4j/or/ObjectRenderer.java
index 5d98d69..843bad4 100644
--- a/src/java/org/apache/log4j/or/ObjectRenderer.java
+++ b/src/java/org/apache/log4j/or/ObjectRenderer.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.or;
diff --git a/src/java/org/apache/log4j/or/RendererMap.java b/src/java/org/apache/log4j/or/RendererMap.java
index 7909478..e71bdd7 100644
--- a/src/java/org/apache/log4j/or/RendererMap.java
+++ b/src/java/org/apache/log4j/or/RendererMap.java
@@ -3,12 +3,13 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.or;
import org.apache.log4j.spi.RendererSupport;
import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.helpers.Loader;
import org.apache.log4j.helpers.OptionConverter;
import java.util.Hashtable;
@@ -46,7 +47,7 @@
return;
} else {
try {
- Class renderedClass = Class.forName(renderedClassName);
+ Class renderedClass = Loader.loadClass(renderedClassName);
repository.setRenderer(renderedClass, renderer);
} catch(ClassNotFoundException e) {
LogLog.error("Could not find class ["+renderedClassName+"].", e);
diff --git a/src/java/org/apache/log4j/or/ThreadGroupRenderer.java b/src/java/org/apache/log4j/or/ThreadGroupRenderer.java
index db00814..3f63860 100644
--- a/src/java/org/apache/log4j/or/ThreadGroupRenderer.java
+++ b/src/java/org/apache/log4j/or/ThreadGroupRenderer.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.or;
diff --git a/src/java/org/apache/log4j/performance/ListVsVector.java b/src/java/org/apache/log4j/performance/ListVsVector.java
index 16440ce..6322d02 100644
--- a/src/java/org/apache/log4j/performance/ListVsVector.java
+++ b/src/java/org/apache/log4j/performance/ListVsVector.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.performance;
diff --git a/src/java/org/apache/log4j/performance/NOPWriter.java b/src/java/org/apache/log4j/performance/NOPWriter.java
index 9662360..6876544 100644
--- a/src/java/org/apache/log4j/performance/NOPWriter.java
+++ b/src/java/org/apache/log4j/performance/NOPWriter.java
@@ -1,5 +1,9 @@
-// Copyright 1996-1999, International Business Machines
-// Corporation. All Rights Reserved.
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.performance;
@@ -7,42 +11,35 @@
import java.io.IOException;
/**
- Extends {@link Writer} with methods that return immediately without
- doing anything. This class is used to measure the cost of
- constructing a log message but not actually writing to the
- OutputStream.
-
- @author Ceki Gülcü
-*/
+ * <p>Extends {@link Writer} with methods that return immediately
+ * without doing anything. This class is used to measure the cost of
+ * constructing a log message but not actually writing to any device.
+ * </p>
+
+ * <p><b> <font color="#FF2222">The
+ * <code>org.apache.log4j.performance.NOPWriter</code> class is
+ * intended for internal use only.</font> Consequently, it is not
+ * included in the <em>log4j.jar</em> file.</b> </p>
+ *
+ * @author Ceki Gülcü
+ * */
public class NOPWriter extends Writer {
- //public
- //NOPWriter() {
- //}
-
+ public void write(char[] cbuf) throws IOException {}
- public
- void write(char[] cbuf) throws IOException {}
-
- public
- void write(char[] cbuf, int off, int len) throws IOException {}
+ public void write(char[] cbuf, int off, int len) throws IOException {}
- public
- void write(int b) throws IOException {}
+ public void write(int b) throws IOException {}
- public
- void write(String s) throws IOException {}
+ public void write(String s) throws IOException {}
- public
- void write(String s, int off, int len) throws IOException {}
+ public void write(String s, int off, int len) throws IOException {}
- public
- void flush() throws IOException {
+ public void flush() throws IOException {
}
- public
- void close() throws IOException {
+ public void close() throws IOException {
System.err.println("Close called.");
}
}
diff --git a/src/java/org/apache/log4j/performance/NewVsSetLen.java b/src/java/org/apache/log4j/performance/NewVsSetLen.java
index 07f96e7..ae6de43 100644
--- a/src/java/org/apache/log4j/performance/NewVsSetLen.java
+++ b/src/java/org/apache/log4j/performance/NewVsSetLen.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.performance;
diff --git a/src/java/org/apache/log4j/performance/NullAppender.java b/src/java/org/apache/log4j/performance/NullAppender.java
index e7ce56e..937c58a 100644
--- a/src/java/org/apache/log4j/performance/NullAppender.java
+++ b/src/java/org/apache/log4j/performance/NullAppender.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.performance;
@@ -12,9 +12,14 @@
import org.apache.log4j.AppenderSkeleton;
/**
- A bogus appender which calls the format method of its layout object
- but does not write the result anywhere.
- */
+ * A bogus appender which calls the format method of its layout object
+ * but does not write the result anywhere.
+ *
+ * <p><b> <font color="#FF2222">The
+ * <code>org.apache.log4j.performance.NullAppender</code> class is
+ * intended for internal use only.</font> Consequently, it is not
+ * included in the <em>log4j.jar</em> file.</b> </p>
+ * */
public class NullAppender extends AppenderSkeleton {
public static String s;
diff --git a/src/java/org/apache/log4j/performance/SystemTime.java b/src/java/org/apache/log4j/performance/SystemTime.java
index aff304c..44bf68b 100644
--- a/src/java/org/apache/log4j/performance/SystemTime.java
+++ b/src/java/org/apache/log4j/performance/SystemTime.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.performance;
diff --git a/src/java/org/apache/log4j/performance/logging b/src/java/org/apache/log4j/performance/logging
index 20da7cb..adec4f4 100644
--- a/src/java/org/apache/log4j/performance/logging
+++ b/src/java/org/apache/log4j/performance/logging
@@ -251,6 +251,56 @@
multiRun xml/logging$TEST.xml 8 "PatternLayout \"$format\"" $SHORTRUN
fi
+echo -------------------------------------
+echo "FileAppender: BufferedIO=true"
+echo -------------------------------------
+
+TEST=220
+if [ $TEST -ge $start ]; then
+ multiRun xml/logging$TEST.xml 8 "SimpleLayout" $LONGRUN
+fi
+
+TEST=221
+if [ $TEST -ge $start ]; then
+ format="%p - %m%n"
+ multiRun xml/logging$TEST.xml 8 "PatternLayout \"$format\"" $LONGRUN
+fi
+
+TEST=222
+if [ $TEST -ge $start ]; then
+ multiRun xml/logging$TEST.xml 8 "TTCC/RELATIVE" $LONGRUN
+fi
+
+TEST=223
+if [ $TEST -ge $start ]; then
+ format="%r [%t] %-5p %c - %m%n"
+ multiRun xml/logging$TEST.xml 8 "PatternLayout \"$format\"" $LONGRUN
+fi
+
+TEST=224
+if [ $TEST -ge $start ]; then
+ multiRun xml/logging$TEST.xml 8 "TTCCLayout/ISO8601" $LONGRUN
+fi
+
+TEST=225
+if [ $TEST -ge $start ]; then
+ format="%d{ISO8601} [%t] %-5p %c %x - %m%n"
+ multiRun xml/logging$TEST.xml 8 "PatternLayout \"$format\"" $LONGRUN
+fi
+
+TEST=226
+if [ $TEST -ge $start ]; then
+ format="%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] %-5p %c %x - %m%n"
+ multiRun xml/logging$TEST.xml 8 "PatternLayout \"$format\"" $LONGRUN
+fi
+
+TEST=227
+if [ $TEST -ge $start ]; then
+ format="%l - %m%n"
+ multiRun xml/logging$TEST.xml 8 "PatternLayout \"$format\"" $SHORTRUN
+fi
+
+
echo ==================================
echo Async appender
echo ==================================
diff --git a/src/java/org/apache/log4j/performance/package.html b/src/java/org/apache/log4j/performance/package.html
index 91f326a..e57b59e 100644
--- a/src/java/org/apache/log4j/performance/package.html
+++ b/src/java/org/apache/log4j/performance/package.html
@@ -3,13 +3,17 @@
<title></title>
</head>
-<body>
-<p>Package to measure the performance of the different log4j components.
+ <body>
+ <p>Package to measure the performance of the different log4j
+ components.
+ </p>
-<hr>
-<address></address>
-<!-- hhmts start -->
-Last modified: Thu Dec 16 10:32:43 MET 1999
-<!-- hhmts end -->
-</body> </html>
+ <p><b> <font color="#FF2222">The
+ <code>org.apache.log4j.performance</code> package is intended
+ for internal use only.</font> Consequently, the classes in this
+ package are not included in the <em>log4j.jar</em> file.</b>
+ </p>
+
+ </body>
+</html>
diff --git a/src/java/org/apache/log4j/performance/xml/logging201.xml b/src/java/org/apache/log4j/performance/xml/logging201.xml
index d1c21e2..5b8fcb2 100644
--- a/src/java/org/apache/log4j/performance/xml/logging201.xml
+++ b/src/java/org/apache/log4j/performance/xml/logging201.xml
@@ -2,23 +2,23 @@
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
- <appender name="NULL" class="org.apache.log4j.FileAppender">
- <param name="File" value="temp"/>
- <param name="Append" value="false"/>
- <param name="ImmediateFlush" value="false"/>
- <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern"
- value="%p - %m%n"/>
- </layout>
- </appender>
-
- <category name="A0123456789">
- <priority value ="info" />
- </category>
-
- <root>
- <priority value ="debug" />
- <appender-ref ref="NULL" />
- </root>
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%p - %m%n"/>
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging202.xml b/src/java/org/apache/log4j/performance/xml/logging202.xml
index 5850075..ff93a00 100644
--- a/src/java/org/apache/log4j/performance/xml/logging202.xml
+++ b/src/java/org/apache/log4j/performance/xml/logging202.xml
@@ -2,22 +2,22 @@
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
- <appender name="NULL" class="org.apache.log4j.FileAppender">
- <param name="File" value="temp"/>
- <param name="Append" value="false"/>
- <param name="ImmediateFlush" value="false"/>
- <layout class="org.apache.log4j.TTCCLayout">
- <param name="DateFormat" value="RELATIVE"/>
- </layout>
- </appender>
-
- <category name="A0123456789">
- <priority value ="info" />
- </category>
-
- <root>
- <priority value ="debug" />
- <appender-ref ref="NULL" />
- </root>
-
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <layout class="org.apache.log4j.TTCCLayout">
+ <param name="DateFormat" value="RELATIVE"/>
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
+
</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging203.xml b/src/java/org/apache/log4j/performance/xml/logging203.xml
index 7d2d704..741c49e 100644
--- a/src/java/org/apache/log4j/performance/xml/logging203.xml
+++ b/src/java/org/apache/log4j/performance/xml/logging203.xml
@@ -2,23 +2,23 @@
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
- <appender name="NULL" class="org.apache.log4j.FileAppender">
- <param name="File" value="temp"/>
- <param name="Append" value="false"/>
- <param name="ImmediateFlush" value="false"/>
- <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern"
- value="%r [%t] %-5p %c - %m%n"/>
- </layout>
- </appender>
-
- <category name="A0123456789">
- <priority value ="info" />
- </category>
-
- <root>
- <priority value ="debug" />
- <appender-ref ref="NULL" />
- </root>
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%r [%t] %-5p %c - %m%n"/>
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging204.xml b/src/java/org/apache/log4j/performance/xml/logging204.xml
index 05210f3..ceaa45c 100644
--- a/src/java/org/apache/log4j/performance/xml/logging204.xml
+++ b/src/java/org/apache/log4j/performance/xml/logging204.xml
@@ -2,23 +2,23 @@
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
- <appender name="NULL" class="org.apache.log4j.FileAppender">
- <param name="File" value="temp"/>
- <param name="Append" value="false"/>
- <param name="ImmediateFlush" value="false"/>
- <layout class="org.apache.log4j.TTCCLayout">
- <param name="DateFormat"
- value="ISO8601"/>
- </layout>
- </appender>
-
- <category name="A0123456789">
- <priority value ="info" />
- </category>
-
- <root>
- <priority value ="debug" />
- <appender-ref ref="NULL" />
- </root>
-
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <layout class="org.apache.log4j.TTCCLayout">
+ <param name="DateFormat"
+ value="ISO8601"/>
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
+
</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging205.xml b/src/java/org/apache/log4j/performance/xml/logging205.xml
index f9d0ad3..63093dd 100644
--- a/src/java/org/apache/log4j/performance/xml/logging205.xml
+++ b/src/java/org/apache/log4j/performance/xml/logging205.xml
@@ -2,23 +2,23 @@
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
- <appender name="NULL" class="org.apache.log4j.FileAppender">
- <param name="File" value="temp"/>
- <param name="Append" value="false"/>
- <param name="ImmediateFlush" value="false"/>
- <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern"
- value="%d{ISO8601} [%t] %-5p %c %x - %m%n"/>
- </layout>
- </appender>
-
- <category name="A0123456789">
- <priority value ="info" />
- </category>
-
- <root>
- <priority value ="debug" />
- <appender-ref ref="NULL" />
- </root>
-
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%d{ISO8601} [%t] %-5p %c %x - %m%n"/>
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
+
</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging206.xml b/src/java/org/apache/log4j/performance/xml/logging206.xml
index a695214..cb80b32 100644
--- a/src/java/org/apache/log4j/performance/xml/logging206.xml
+++ b/src/java/org/apache/log4j/performance/xml/logging206.xml
@@ -2,23 +2,23 @@
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
- <appender name="NULL" class="org.apache.log4j.FileAppender">
- <param name="File" value="temp"/>
- <param name="Append" value="false"/>
- <param name="ImmediateFlush" value="false"/>
- <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern"
- value="%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] %-5p %c %x - %m%n"/>
- </layout>
- </appender>
-
- <category name="A0123456789">
- <priority value ="info" />
- </category>
-
- <root>
- <priority value ="debug" />
- <appender-ref ref="NULL" />
- </root>
-
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] %-5p %c %x - %m%n"/>
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
+
</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging207.xml b/src/java/org/apache/log4j/performance/xml/logging207.xml
index a4098a9..22fce85 100644
--- a/src/java/org/apache/log4j/performance/xml/logging207.xml
+++ b/src/java/org/apache/log4j/performance/xml/logging207.xml
@@ -2,23 +2,23 @@
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
- <appender name="NULL" class="org.apache.log4j.FileAppender">
- <param name="File" value="temp"/>
- <param name="Append" value="false"/>
- <param name="ImmediateFlush" value="false"/>
- <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern"
- value="%l - %m%n"/>
- </layout>
- </appender>
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%l - %m%n"/>
+ </layout>
+ </appender>
- <category name="A0123456789">
- <priority value ="info" />
- </category>
-
- <root>
- <priority value ="debug" />
- <appender-ref ref="NULL" />
- </root>
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging220.xml b/src/java/org/apache/log4j/performance/xml/logging220.xml
new file mode 100644
index 0000000..12faaab
--- /dev/null
+++ b/src/java/org/apache/log4j/performance/xml/logging220.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="test"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <param name="BufferedIO" value="true"/>
+ <layout class="org.apache.log4j.SimpleLayout">
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging221.xml b/src/java/org/apache/log4j/performance/xml/logging221.xml
new file mode 100644
index 0000000..0833be0
--- /dev/null
+++ b/src/java/org/apache/log4j/performance/xml/logging221.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <param name="BufferedIO" value="true"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%p - %m%n"/>
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging222.xml b/src/java/org/apache/log4j/performance/xml/logging222.xml
new file mode 100644
index 0000000..57ee68a
--- /dev/null
+++ b/src/java/org/apache/log4j/performance/xml/logging222.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <param name="BufferedIO" value="true"/>
+ <layout class="org.apache.log4j.TTCCLayout">
+ <param name="DateFormat" value="RELATIVE"/>
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging223.xml b/src/java/org/apache/log4j/performance/xml/logging223.xml
new file mode 100644
index 0000000..ca7dc8e
--- /dev/null
+++ b/src/java/org/apache/log4j/performance/xml/logging223.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <param name="BufferedIO" value="true"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%r [%t] %-5p %c - %m%n"/>
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging224.xml b/src/java/org/apache/log4j/performance/xml/logging224.xml
new file mode 100644
index 0000000..a79ff1c
--- /dev/null
+++ b/src/java/org/apache/log4j/performance/xml/logging224.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <param name="BufferedIO" value="true"/>
+ <layout class="org.apache.log4j.TTCCLayout">
+ <param name="DateFormat"
+ value="ISO8601"/>
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging225.xml b/src/java/org/apache/log4j/performance/xml/logging225.xml
new file mode 100644
index 0000000..94c45a6
--- /dev/null
+++ b/src/java/org/apache/log4j/performance/xml/logging225.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <param name="BufferedIO" value="true"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%d{ISO8601} [%t] %-5p %c %x - %m%n"/>
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging226.xml b/src/java/org/apache/log4j/performance/xml/logging226.xml
new file mode 100644
index 0000000..13117e4
--- /dev/null
+++ b/src/java/org/apache/log4j/performance/xml/logging226.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <param name="BufferedIO" value="true"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] %-5p %c %x - %m%n"/>
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/java/org/apache/log4j/performance/xml/logging227.xml b/src/java/org/apache/log4j/performance/xml/logging227.xml
new file mode 100644
index 0000000..c3a61e2
--- /dev/null
+++ b/src/java/org/apache/log4j/performance/xml/logging227.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
+ <appender name="NULL" class="org.apache.log4j.FileAppender">
+ <param name="File" value="temp"/>
+ <param name="Append" value="false"/>
+ <param name="ImmediateFlush" value="false"/>
+ <param name="BufferedIO" value="true"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern"
+ value="%l - %m%n"/>
+ </layout>
+ </appender>
+
+ <category name="A0123456789">
+ <priority value ="info" />
+ </category>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="NULL" />
+ </root>
+
+</log4j:configuration>
diff --git a/src/java/org/apache/log4j/spi/Configurator.java b/src/java/org/apache/log4j/spi/Configurator.java
index 7b7c7ab..28de296 100644
--- a/src/java/org/apache/log4j/spi/Configurator.java
+++ b/src/java/org/apache/log4j/spi/Configurator.java
@@ -19,22 +19,16 @@
public interface Configurator {
/**
- <p><code>ENABLE_KEY</code> is the name of the constant
- holding the string value <b>log4j.enable</b>.
-
- <p>Setting the system property <b>log4j.disable</b> to DEBUG,
- INFO, WARN, ERROR or FATAL is equivalent to calling the {@link
- Hierarchy#disable} method with the corresponding level.
-
- @since 1.2 */
- // public static final String ENABLE_KEY = "log4j.enable";
-
+ Special level value signifying inherited behaviour. The current
+ value of this string constant is <b>inherited</b>. {@link #NULL}
+ is a synonym. */
+ public static final String INHERITED = "inherited";
/**
- Special level value signifying inherited behaviour. The
- current value of this string constant is <b>inherited</b>.
- */
- public static final String INHERITED = "inherited";
+ Special level signifying inherited behaviour, same as {@link
+ #INHERITED}. The current value of this string constant is
+ <b>null</b>. */
+ public static final String NULL = "null";
diff --git a/src/java/org/apache/log4j/spi/LoggingEvent.java b/src/java/org/apache/log4j/spi/LoggingEvent.java
index 5cd6e42..fb78c7b 100644
--- a/src/java/org/apache/log4j/spi/LoggingEvent.java
+++ b/src/java/org/apache/log4j/spi/LoggingEvent.java
@@ -10,7 +10,7 @@
import org.apache.log4j.*;
import org.apache.log4j.helpers.LogLog;
-
+import org.apache.log4j.helpers.Loader;
import java.lang.reflect.Method;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
@@ -39,19 +39,40 @@
/** Fully qualified name of the calling category class. */
transient public final String fqnOfCategoryClass;
- /** The category of the logging event. The category field is not
- serialized for performance reasons.
+ /**
+ * The category of the logging event. This field is not serialized
+ * for performance reasons.
+ *
+ * <p>It is set by the LoggingEvent constructor or set by a remote
+ * entity after deserialization.
+ *
+ * @deprecated This field will be marked as private or be completely
+ * removed in future releases. Please do not use it.
+ * */
+ transient private Category logger;
- <p>It is set by the LoggingEvent constructor or set by a remote
- entity after deserialization. */
- transient public Category logger;
+ /**
+ * <p>The category (logger) name.
+ *
+ * @deprecated This field will be marked as private in future
+ * releases. Please do not access it directly. Use the {@link
+ * #getLoggerName} method instead.
- /** The category (logger) name. */
- public final String categoryName;
+ * */
+ final public String categoryName;
- /** Level of logging event. Level cannot be serializable
- because it is a flyweight. Due to its special seralization it
- cannot be declared final either. */
+ /**
+ * Level of logging event. Level cannot be serializable because it
+ * is a flyweight. Due to its special seralization it cannot be
+ * declared final either.
+ *
+ * <p> This field should not be accessed directly. You shoud use the
+ * {@link #getLevel} method instead.
+ *
+ * @deprecated This field will be marked as private in future
+ * releases. Please do not access it directly. Use the {@link
+ * #getLevel} method instead.
+ * */
transient public Priority level;
/** The nested diagnostic context (NDC) of logging event. */
@@ -62,18 +83,16 @@
/** 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. */
+ * 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. */
private boolean ndcLookupRequired = true;
- /** 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. Thus, a receiving SocketNode will never use it's own
- (incorrect) MDC. See also writeObject method. */
- private boolean mdcLookupRequired = true;
-
+ /** 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. */
+ private boolean mdcCopyLookupRequired = true;
/** The application supplied message of logging event. */
transient private Object message;
@@ -154,20 +173,31 @@
this.timeStamp = timeStamp;
}
-
-
/**
Set the location information for this logging event. The collected
information is cached for future use.
*/
- public
- LocationInfo getLocationInformation() {
+ public LocationInfo getLocationInformation() {
if(locationInfo == null) {
locationInfo = new LocationInfo(new Throwable(), fqnOfCategoryClass);
}
return locationInfo;
}
+ /**
+ * Return the level of this event. Use this form instead of directly
+ * accessing the <code>level</code> field. */
+ public Level getLevel() {
+ return (Level) level;
+ }
+
+ /**
+ * Return the name of the logger. Use this form instead of directly
+ * accessing the <code>categoryName</code> field.
+ */
+ public String getLoggerName() {
+ return categoryName;
+ }
/**
Return the message for this logging event.
@@ -187,6 +217,11 @@
}
}
+ /**
+ * This method returns the NDC for this event. It will return the
+ * correct content even if the event was generated in a different
+ * thread or even on a different machine. The {@link NDC#get} method
+ * should <em>never</em> be called directly. */
public
String getNDC() {
if(ndcLookupRequired) {
@@ -199,9 +234,11 @@
/**
Returns the the context corresponding to the <code>key</code>
- parameter. If there is a local MDC copy (probably from a remote
- machine, the we use it, if that fails then the current thread's
- <code>MDC</code> is used.
+ 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 a null
+ 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.
@@ -223,11 +260,12 @@
/**
Obtain a copy of this thread's MDC prior to serialization or
- asynchronous logging. */
+ asynchronous logging.
+ */
public
void getMDCCopy() {
- if(mdcLookupRequired) {
- ndcLookupRequired = false;
+ if(mdcCopyLookupRequired) {
+ mdcCopyLookupRequired = false;
// the clone call is required for asynchronous logging.
// See also bug #5932.
Hashtable t = (Hashtable) MDC.getContext();
@@ -259,9 +297,7 @@
/**
Returns the time when the application started, in milliseconds
elapsed since 01.01.1970. */
- public
- static
- long getStartTime() {
+ public static long getStartTime() {
return startTime;
}
@@ -310,7 +346,7 @@
} else {
Method m = (Method) methodCache.get(className);
if(m == null) {
- Class clazz = Class.forName(className);
+ Class clazz = Loader.loadClass(className);
// Note that we use Class.getDeclaredMethod instead of
// Class.getMethod. This assumes that the Level subclass
// implements the toLevel(int) method which is a
diff --git a/src/java/org/apache/log4j/spi/ThrowableInformation.java b/src/java/org/apache/log4j/spi/ThrowableInformation.java
index 06d13c1..c71457e 100644
--- a/src/java/org/apache/log4j/spi/ThrowableInformation.java
+++ b/src/java/org/apache/log4j/spi/ThrowableInformation.java
@@ -12,10 +12,18 @@
import java.util.Vector;
/**
-
-
-
- */
+ * ThrowableInformation is log4j's internal representation of
+ * throwables. It essentially consists of a string array, called
+ * 'rep', where the first element, that is rep[0], represents the
+ * string representation of the throwable (i.e. the value you get
+ * when you do throwable.toString()) and subsequent elements
+ * correspond the stack trace with the top most entry of the stack
+ * corresponding to the second entry of the 'rep' array that is
+ * rep[1].
+ *
+ * @author Ceki Gülcü
+ *
+ * */
public class ThrowableInformation implements java.io.Serializable {
static final long serialVersionUID = -4748765566864322735L;
@@ -41,12 +49,20 @@
VectorWriter vw = new VectorWriter();
throwable.printStackTrace(vw);
rep = vw.toStringArray();
- vw.clear();
return rep;
}
}
}
+/**
+ * VectorWriter is a seemingly trivial implemtantion of PrintWriter.
+ * The throwable instance that we are trying to represnt is asked to
+ * print itself to a VectorWriter.
+ *
+ * By our design choice, r string representation of the throwable
+ * does not contain any line separators. It follows that println()
+ * methods of VectorWriter ignore the 'ln' part.
+ * */
class VectorWriter extends PrintWriter {
private Vector v;
@@ -56,34 +72,27 @@
v = new Vector();
}
- // Support for Orion
- public
- void print(Object o) {
+ public void print(Object o) {
v.addElement(o.toString());
}
- // Support for Orion
- public
- void print(char[] s) {
- v.addElement(new String(s));
+ public void print(char[] chars) {
+ v.addElement(new String(chars));
}
- // Support for Orion
- public
- void print(String s) {
+ public void print(String s) {
v.addElement(s);
}
- public
- void println(Object o) {
+ public void println(Object o) {
v.addElement(o.toString());
}
// JDK 1.1.x apprenly uses this form of println while in
// printStackTrace()
public
- void println(char[] s) {
- v.addElement(new String(s));
+ void println(char[] chars) {
+ v.addElement(new String(chars));
}
public
@@ -91,8 +100,23 @@
v.addElement(s);
}
- public
- String[] toStringArray() {
+ public void write(char[] chars) {
+ v.addElement(new String(chars));
+ }
+
+ public void write(char[] chars, int off, int len) {
+ v.addElement(new String(chars, off, len));
+ }
+
+ public void write(String s, int off, int len) {
+ v.addElement(s.substring(off, off+len));
+ }
+
+ public void write(String s) {
+ v.addElement(s);
+ }
+
+ public String[] toStringArray() {
int len = v.size();
String[] sa = new String[len];
for(int i = 0; i < len; i++) {
@@ -101,24 +125,20 @@
return sa;
}
- public
- void clear() {
- v.setSize(0);
- }
}
class NullWriter extends Writer {
- public
- void close() {
+ public void close() {
+ // blank
}
- public
- void flush() {
+ public void flush() {
+ // blank
}
- public
- void write(char[] cbuf, int off, int len) {
+ public void write(char[] cbuf, int off, int len) {
+ // blank
}
}
diff --git a/src/java/org/apache/log4j/test/AsyncAppenderTest.java b/src/java/org/apache/log4j/test/AsyncAppenderTest.java
index b3eff7f..17060f1 100644
--- a/src/java/org/apache/log4j/test/AsyncAppenderTest.java
+++ b/src/java/org/apache/log4j/test/AsyncAppenderTest.java
@@ -1,9 +1,8 @@
/* Copyright (C) The Apache Software Foundation. All rights reserved.
*
- * This software is published under the terms of the Apache Software License
- * version 1.1, a copy of which has been included with this distribution in
- * the LICENSE.APL file.
- */
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.test;
diff --git a/src/java/org/apache/log4j/test/ConfigurationFileParsing.java b/src/java/org/apache/log4j/test/ConfigurationFileParsing.java
index 0e274df..d6b0a52 100644
--- a/src/java/org/apache/log4j/test/ConfigurationFileParsing.java
+++ b/src/java/org/apache/log4j/test/ConfigurationFileParsing.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
- * distribution in the LICENSE.APL file. */
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.test;
diff --git a/src/java/org/apache/log4j/varia/ExternallyRolledFileAppender.java b/src/java/org/apache/log4j/varia/ExternallyRolledFileAppender.java
index 736abe1..a48619e 100644
--- a/src/java/org/apache/log4j/varia/ExternallyRolledFileAppender.java
+++ b/src/java/org/apache/log4j/varia/ExternallyRolledFileAppender.java
@@ -1,10 +1,9 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
- * This software is published under the terms of the Apache Software License
- * version 1.1, a copy of which has been included with this distribution in
- * the LICENSE.APL file.
- */
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file. */
package org.apache.log4j.varia;
diff --git a/src/java/org/apache/log4j/varia/FallbackErrorHandler.java b/src/java/org/apache/log4j/varia/FallbackErrorHandler.java
index a7ebb9f..18ccb3d 100644
--- a/src/java/org/apache/log4j/varia/FallbackErrorHandler.java
+++ b/src/java/org/apache/log4j/varia/FallbackErrorHandler.java
@@ -16,16 +16,17 @@
import java.util.Vector;
/**
-
- 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.
-
-*/
+ *
+ * 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.
+ *
+ * @author Ceki Gücü
+ * */
public class FallbackErrorHandler implements ErrorHandler {
@@ -73,13 +74,15 @@
*/
public
void error(String message, Exception e, int errorCode, LoggingEvent event) {
+ LogLog.debug("FB: The following error reported: " + message, e);
+ LogLog.debug("FB: INITIATING FALLBACK PROCEDURE.");
for(int i = 0; i < loggers.size(); i++) {
Logger l = (Logger) loggers.elementAt(i);
- LogLog.debug("FB: Searching for ["+primary.getName()+"] in logger"
- +l.getName());
+ LogLog.debug("FB: Searching for ["+primary.getName()+"] in logger ["
+ +l.getName() + "].");
//if(l.isAttached(primary)) {
LogLog.debug("FB: Replacing ["+primary.getName()+"] by ["
- + backup.getName() + " in logger"+ l);
+ + backup.getName() + "] in logger ["+ l.getName() +"].");
l.removeAppender(primary);
LogLog.debug("FB: Adding appender ["+backup.getName()+"] to logger "
+ l.getName());
diff --git a/src/java/org/apache/log4j/varia/LevelMatchFilter.java b/src/java/org/apache/log4j/varia/LevelMatchFilter.java
index b028c83..1d47c4b 100644
--- a/src/java/org/apache/log4j/varia/LevelMatchFilter.java
+++ b/src/java/org/apache/log4j/varia/LevelMatchFilter.java
@@ -3,7 +3,7 @@
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
- * the LICENSE.APL file.
+ * the LICENSE.txt file.
*/
package org.apache.log4j.varia;
@@ -79,7 +79,7 @@
}
boolean matchOccured = false;
- if(this.levelToMatch.equals(event.level)) {
+ if(this.levelToMatch.equals(event.getLevel())) {
matchOccured = true;
}
diff --git a/src/java/org/apache/log4j/varia/LevelRangeFilter.java b/src/java/org/apache/log4j/varia/LevelRangeFilter.java
new file mode 100644
index 0000000..faefb6f
--- /dev/null
+++ b/src/java/org/apache/log4j/varia/LevelRangeFilter.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file. */
+
+package org.apache.log4j.varia;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.spi.Filter;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.helpers.OptionConverter;
+
+/**
+ 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 LoggingEvent} is not between Min and Max
+ (inclusive), then {@link Filter#DENY} is returned.
+
+ <p> If the Logging event level is within the specified range, then if
+ <b>AcceptOnMatch</b> is true, {@link Filter#ACCEPT} is returned, and if
+ <b>AcceptOnMatch</b> is false, {@link Filter#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
+ org.apache.log4j.AppenderSkeleton#setThreshold setThreshold} method
+ available to <code>all</code> appenders extending {@link
+ org.apache.log4j.AppenderSkeleton} for a more convenient way to
+ filter out events by level.
+
+ @author Simon Kitching
+ @author based on code by Ceki Gülcü
+*/
+public class LevelRangeFilter extends Filter {
+
+ /**
+ Do we return ACCEPT when a match occurs. Default is
+ <code>false</code>, so that later filters get run by default */
+ boolean acceptOnMatch = false;
+
+ Level levelMin;
+ Level levelMax;
+
+
+ /**
+ Return the decision of this filter.
+ */
+ public
+ int decide(LoggingEvent event) {
+ if(this.levelMin != null) {
+ if (event.getLevel().isGreaterOrEqual(levelMin) == false) {
+ // level of event is less than minimum
+ return Filter.DENY;
+ }
+ }
+
+ if(this.levelMax != null) {
+ if (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;
+ }
+ }
+
+ /**
+ Get the value of the <code>LevelMax</code> option. */
+ public
+ Level getLevelMax() {
+ return levelMax;
+ }
+
+
+ /**
+ Get the value of the <code>LevelMin</code> option. */
+ public
+ Level getLevelMin() {
+ return levelMin;
+ }
+
+ /**
+ Get the value of the <code>AcceptOnMatch</code> option.
+ */
+ public
+ boolean getAcceptOnMatch() {
+ return acceptOnMatch;
+ }
+
+ /**
+ Set the <code>LevelMax</code> option.
+ */
+ public
+ void setLevelMax(Level levelMax) {
+ this.levelMax = levelMax;
+ }
+
+ /**
+ Set the <code>LevelMin</code> option.
+ */
+ public
+ void setLevelMin(Level levelMin) {
+ this.levelMin = levelMin;
+ }
+
+ /**
+ Set the <code>AcceptOnMatch</code> option.
+ */
+ public
+ void setAcceptOnMatch(boolean acceptOnMatch) {
+ this.acceptOnMatch = acceptOnMatch;
+ }
+}
+
diff --git a/src/java/org/apache/log4j/varia/NullAppender.java b/src/java/org/apache/log4j/varia/NullAppender.java
new file mode 100644
index 0000000..d892ded
--- /dev/null
+++ b/src/java/org/apache/log4j/varia/NullAppender.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file. */
+
+package org.apache.log4j.varia;
+
+import org.apache.log4j.Appender;
+import org.apache.log4j.Layout;
+import org.apache.log4j.spi.OptionHandler;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.log4j.spi.ErrorHandler;
+import org.apache.log4j.spi.Filter;
+import org.apache.log4j.AppenderSkeleton;
+
+/**
+ * A NullAppender merely exists, it never outputs a message to any
+ * device.
+ * @author Ceki Gülc¨
+ */
+public class NullAppender extends AppenderSkeleton {
+
+ private static NullAppender instance = new NullAppender();
+
+ public NullAppender() {
+ }
+
+ /**
+ * There are no options to acticate.
+ * */
+ public void activateOptions() {
+ }
+
+ /**
+ * Whenever you can, use this method to retreive an instance instead
+ * of instantiating a new one with <code>new</code>.
+ * */
+ public NullAppender getInstance() {
+ return instance;
+ }
+
+ public void close() {
+ }
+
+ /**
+ * Does not do anything.
+ * */
+ public void doAppend(LoggingEvent event) {
+ }
+
+ /**
+ * Does not do anything.
+ * */
+ protected void append(LoggingEvent event) {
+ }
+
+ /**
+ * NullAppenders do not need a layout.
+ * */
+ public boolean requiresLayout() {
+ return false;
+ }
+}
diff --git a/src/java/org/apache/log4j/xml/DOMConfigurator.java b/src/java/org/apache/log4j/xml/DOMConfigurator.java
index 8060989..a61259e 100644
--- a/src/java/org/apache/log4j/xml/DOMConfigurator.java
+++ b/src/java/org/apache/log4j/xml/DOMConfigurator.java
@@ -161,7 +161,7 @@
String className = subst(appenderElement.getAttribute(CLASS_ATTR));
LogLog.debug("Class name: [" + className+']');
try {
- Object instance = Class.forName(className).newInstance();
+ Object instance = Loader.loadClass(className).newInstance();
Appender appender = (Appender)instance;
PropertySetter propSetter = new PropertySetter(appender);
@@ -311,7 +311,7 @@
else {
LogLog.debug("Desired logger sub-class: ["+className+']');
try {
- Class clazz = Class.forName(className);
+ Class clazz = Loader.loadClass(className);
Method getInstanceMethod = clazz.getMethod("getLogger",
ONE_STRING_PARAM);
cat = (Logger) getInstanceMethod.invoke(null, new Object[] {catName});
@@ -442,7 +442,7 @@
String className = subst(layout_element.getAttribute(CLASS_ATTR));
LogLog.debug("Parsing layout of class: \""+className+"\"");
try {
- Object instance = Class.forName(className).newInstance();
+ Object instance = Loader.loadClass(className).newInstance();
Layout layout = (Layout)instance;
PropertySetter propSetter = new PropertySetter(layout);
@@ -493,7 +493,7 @@
String priStr = subst(element.getAttribute(VALUE_ATTR));
LogLog.debug("Level value for "+catName+" is ["+priStr+"].");
- if(INHERITED.equals(priStr)) {
+ if(INHERITED.equalsIgnoreCase(priStr) || NULL.equalsIgnoreCase(priStr)) {
if(isRoot) {
LogLog.error("Root level cannot be inherited. Ignoring directive.");
} else {
@@ -506,7 +506,7 @@
} else {
LogLog.debug("Desired Level sub-class: ["+className+']');
try {
- Class clazz = Class.forName(className);
+ Class clazz = Loader.loadClass(className);
Method toLevelMethod = clazz.getMethod("toLevel",
ONE_STRING_PARAM);
Level pri = (Level) toLevelMethod.invoke(null,
diff --git a/src/java/org/apache/log4j/xml/XMLLayout.java b/src/java/org/apache/log4j/xml/XMLLayout.java
index abc2fa2..de1db86 100644
--- a/src/java/org/apache/log4j/xml/XMLLayout.java
+++ b/src/java/org/apache/log4j/xml/XMLLayout.java
@@ -17,37 +17,38 @@
import org.apache.log4j.helpers.Transform;
/**
- The output of the XMLLayout consists of a series of log4j:event
- elements as defined in the <a
- href="doc-files/log4j.dtd">log4j.dtd</a>. 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:
-
- <pre>
+ * The output of the XMLLayout consists of a series of log4j:event
+ * elements as defined in the <a
+ * href="doc-files/log4j.dtd">log4j.dtd</a>. 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:
+ *
+ <pre>
<?xml version="1.0" ?>
-
- <!DOCTYPE log4j:eventSet SYSTEM "log4j.dtd" [<!ENTITY data SYSTEM "abc">]>
-
- <log4j:eventSet version="1.2" xmlns:log4j="http://jakarta.apache.org/log4j/">
- &data;
- </log4j:eventSet>
- </pre>
-
- <p>This approach enforces the independence of the XMLLayout and the
- appender where it is embedded.
-
- <p>The <code>version</code> attribute helps components to correctly
- intrepret output generated by XMLLayout. The value of this
- attribute should be "1.1" for output generated by log4j versions
- prior to log4j 1.2 (final release) and "1.2" for relase 1.2 and
- later.
-
- @author Ceki Gülcü
- @since 0.9.0 */
+
+ <!DOCTYPE log4j:eventSet SYSTEM "log4j.dtd" [<!ENTITY data SYSTEM "abc">]>
+
+ <log4j:eventSet version="1.2" xmlns:log4j="http://jakarta.apache.org/log4j/">
+ &data;
+ </log4j:eventSet>
+ </pre>
+
+ * <p>This approach enforces the independence of the XMLLayout and the
+ * appender where it is embedded.
+ *
+ * <p>The <code>version</code> attribute helps components to correctly
+ * intrepret output generated by XMLLayout. The value of this
+ * attribute should be "1.1" for output generated by log4j versions
+ * prior to log4j 1.2 (final release) and "1.2" for relase 1.2 and
+ * later.
+ *
+ * @author Ceki Gülcü
+ * @since 0.9.0
+ * */
public class XMLLayout extends Layout {
private final int DEFAULT_SIZE = 256;
@@ -55,41 +56,38 @@
private StringBuffer buf = new StringBuffer(DEFAULT_SIZE);
private boolean locationInfo = false;
-
/**
- 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
- org.apache.log4j.net.SMTPAppender} then make sure to set the
- <b>LocationInfo</b> option of that appender as well.
- */
- public
- void setLocationInfo(boolean flag) {
+ * 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
+ * org.apache.log4j.net.SMTPAppender} then make sure to set the
+ * <b>LocationInfo</b> option of that appender as well.
+ * */
+ public void setLocationInfo(boolean flag) {
locationInfo = flag;
}
/**
Returns the current value of the <b>LocationInfo</b> option.
*/
- public
- boolean getLocationInfo() {
+ public boolean getLocationInfo() {
return locationInfo;
}
- public
- void activateOptions() {
+ /** No options to activate. */
+ public void activateOptions() {
}
/**
- Formats a {@link LoggingEvent} in conformance with the log4j.dtd. */
- public
- String format(LoggingEvent event) {
+ * Formats a {@link LoggingEvent} in conformance with the log4j.dtd.
+ * */
+ public String format(LoggingEvent event) {
// Reset working buffer. If the buffer is too large, then we need a new
// one in order to avoid the penalty of creating a large array.
@@ -101,53 +99,54 @@
// We yield to the \r\n heresy.
- buf.append("<log4j:event category=\"");
- buf.append(event.categoryName);
+ buf.append("<log4j:event logger=\"");
+ buf.append(event.getLoggerName());
buf.append("\" timestamp=\"");
buf.append(event.timeStamp);
buf.append("\" level=\"");
- buf.append(event.level);
+ buf.append(event.getLevel());
buf.append("\" thread=\"");
buf.append(event.getThreadName());
buf.append("\">\r\n");
-
- buf.append("<log4j:message><![CDATA[");
- buf.append(event.getRenderedMessage());
- buf.append("]]></log4j:message>\r\n");
-
- String ndc = event.getNDC();
- if(ndc != null) {
- buf.append("<log4j:NDC><![CDATA[");
- buf.append(ndc);
- buf.append("]]></log4j:NDC>\r\n");
- }
-
- String[] s = event.getThrowableStrRep();
- if(s != null) {
- buf.append("<log4j:throwable><![CDATA[");
- for(int i = 0; i < s.length; i++) {
- buf.append(s[i]);
- buf.append("\r\n");
- }
- buf.append("]]></log4j:throwable>\r\n");
- }
-
- if(locationInfo) {
- LocationInfo locationInfo = event.getLocationInformation();
- buf.append("<log4j:locationInfo class=\"");
- buf.append(locationInfo.getClassName());
- buf.append("\" method=\"");
- buf.append(Transform.escapeTags(locationInfo.getMethodName()));
- buf.append("\" file=\"");
- buf.append(locationInfo.getFileName());
- buf.append("\" line=\"");
- buf.append(locationInfo.getLineNumber());
- buf.append("\"/>\r\n");
- }
-
+ buf.append("<log4j:message><![CDATA[");
+ // Append the rendered message. Also make sure to escape any
+ // existing CDATA sections.
+ Transform.appendEscapingCDATA(buf, event.getRenderedMessage());
+ buf.append("]]></log4j:message>\r\n");
+
+ String ndc = event.getNDC();
+ if(ndc != null) {
+ buf.append("<log4j:NDC><![CDATA[");
+ buf.append(ndc);
+ buf.append("]]></log4j:NDC>\r\n");
+ }
+
+ String[] s = event.getThrowableStrRep();
+ if(s != null) {
+ buf.append("<log4j:throwable><![CDATA[");
+ for(int i = 0; i < s.length; i++) {
+ buf.append(s[i]);
+ buf.append("\r\n");
+ }
+ buf.append("]]></log4j:throwable>\r\n");
+ }
+
+ if(locationInfo) {
+ LocationInfo locationInfo = event.getLocationInformation();
+ buf.append("<log4j:locationInfo class=\"");
+ buf.append(locationInfo.getClassName());
+ buf.append("\" method=\"");
+ buf.append(Transform.escapeTags(locationInfo.getMethodName()));
+ buf.append("\" file=\"");
+ buf.append(locationInfo.getFileName());
+ buf.append("\" line=\"");
+ buf.append(locationInfo.getLineNumber());
+ buf.append("\"/>\r\n");
+ }
+
buf.append("</log4j:event>\r\n\r\n");
-
+
return buf.toString();
}
@@ -155,8 +154,7 @@
The XMLLayout prints and does not ignore exceptions. Hence the
return value <code>false</code>.
*/
- public
- boolean ignoresThrowable() {
+ public boolean ignoresThrowable() {
return false;
}
}
diff --git a/src/java/org/apache/log4j/xml/log4j.dtd b/src/java/org/apache/log4j/xml/log4j.dtd
index 12f373c..2a87e0c 100644
--- a/src/java/org/apache/log4j/xml/log4j.dtd
+++ b/src/java/org/apache/log4j/xml/log4j.dtd
@@ -143,8 +143,8 @@
<!-- The timestamp format is application dependent. -->
<!ATTLIST log4j:event
- category CDATA #REQUIRED
- priority CDATA #REQUIRED
+ logger CDATA #REQUIRED
+ level CDATA #REQUIRED
thread CDATA #REQUIRED
timestamp CDATA #REQUIRED
>
diff --git a/src/xdocs/contributors.xml b/src/xdocs/contributors.xml
index 87634e4..ab43c74 100644
--- a/src/xdocs/contributors.xml
+++ b/src/xdocs/contributors.xml
@@ -8,7 +8,7 @@
<body>
<section name="Log4j contributors">
-
+
<p>Log4j is the result of contributions from several dozen
developers and hundreds of users across the globe. Some of the
more prominent contributors are listed below in alphabetical
@@ -64,9 +64,13 @@
</li>
<li><b>Jon Skeet</b>
-
- <p>Jon acts as a moderator for the log4j mailing lists where
- he is one of the most active participants.
+
+ <p>Jon is a software developer in his mid-twenties living in
+ the UK. He is a Java enthusiast and very active participant
+ in the comp.lang.java.* newsgroups as well as a moderator
+ for the log4j mailing lists. He is a committer for the Ant
+ project, involved (when time permits!) in tidying up the
+ code documentation.
</p>
</li>
diff --git a/src/xdocs/documentation.xml b/src/xdocs/documentation.xml
index 0f2690a..569ad4f 100644
--- a/src/xdocs/documentation.xml
+++ b/src/xdocs/documentation.xml
@@ -15,15 +15,27 @@
<ul>
<p>
+ <a href="http://www.flashline.com/components/view.jsp?prodid=4702&affiliateid=657173"><img align="right" src="images/coverSmall.png"></img></a>
<li><a href="manual.html"><b>short manual</b></a>,
</li>
</p>
+
+ <p>
+ <li><a href="http://www.flashline.com/components/view.jsp?prodid=4702&affiliateid=657173"><b>complete manual</b></a> (commercial),
+ </li>
+ </p>
<p>
<li>
<a href="api/index.html"><b>javadoc documentation</b></a>,
</li>
</p>
+
+ <p>
+ <li>
+ <a href="lf5/overview.html"><b>LogFactor5 documentation</b></a>,
+ </li>
+ </p>
<p>
<li>
@@ -58,10 +70,6 @@
Add logging to your Java Applications</a> by Kevin Brown
</li>
- <li><a href="http://www.entwickler.com/jm/ausgaben/2001/4/artikel/17/online.shtml">
- Computer: captains, new entry... DasJakarta Logging-System log4j</a> by Thomas Poschmann
- </li>
-
<li>
<a href="http://www.opensymphony.com/guidelines/logging.jsp">OpenSymphony Logging Primer</a>
</li>
diff --git a/src/xdocs/download.xml b/src/xdocs/download.xml
index 6f40fb1..a3c9aee 100644
--- a/src/xdocs/download.xml
+++ b/src/xdocs/download.xml
@@ -9,13 +9,17 @@
<meta name="keywords" content="java, logging, tracing, component, framework, API, log4j"/>
<body>
- <section name="log4j version 1.2 (final)">
- <p>log4j 1.2 is now available in <a
- href="../jakarta-log4j-1.2.tar.gz"><b>TAR.GZ</b></a> format or
- in <a href="../jakarta-log4j-1.2.zip"><b>ZIP</b></a> format.
+ <section name="log4j version 1.2.6">
+ <p>log4j 1.2.6 is available in <a
+ href="../jakarta-log4j-1.2.6.tar.gz"><b>TAR.GZ</b></a> format
+ or in <a href="../jakarta-log4j-1.2.6.zip"><b>ZIP</b></a>
+ format.
</p>
-
+ <p>Release 1.2.6 fixes minor bugs. See the <a
+ href="HISTORY">HISTORY</a> file for the exact details.
+ </p>
+
<p>In addition to many performance improvements, bug fixes, and
other small enhancements, log4j 1.2 adds JMX support, Mapped
Diagnostic Contexts, JDBC logging, graphical log viewer
@@ -35,14 +39,15 @@
replacement for log4j 1.1.3. The only exception is the
renaming of the <code>CategoryFactory</code> class to
<code>LoggerFactory</code> class such that subclasses of
- <code>Category</code> class to be modified and recompiled. By
- the way, we strongly discourage casual users from subclassing
- the <code>Category</code> or <code>Logger</code> classes.
+ <code>Category</code> class must be modified and
+ recompiled. By the way, <b>we strongly discourage casual users
+ from subclassing the <code>Category</code> or
+ <code>Logger</code> classes.</b>
</p>
<p>We also maintain a list of <a href="earlier.html">earlier
versions</a> of log4j for download, intended for the curious
- paleontologist.
+ paleontologist -- there seems to be thousands of them!
</p>
@@ -57,9 +62,9 @@
<dt><a
href="http://logui.sourceforge.net/"><b>Chainsaw</b></a></dt>
- <dd>Chainsaw is now integrated with log4j and ships with the
- official distribution. Chainsaw is a graphical log viewer and
- filter for the log4j package. It listens for <a
+ <dd><b>Chainsaw is now integrated with log4j and ships with
+ the official distribution.</b> Chainsaw is a graphical log
+ viewer and filter for the log4j package. It listens for <a
href="http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/spi/LoggingEvent.html">LoggingEvent</a>
objects sent using the <a
href="http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/net/SocketAppender.html">SocketAppender</a>
@@ -198,14 +203,24 @@
</dd>
<!-- =========================================================================== -->
-
+ <dt><a
+ href="http://log4perl.sourceforge.net"><b>Log::Log4perl</b></a></dt>
+
+ <dd>Log::Log4perl is a Perl port of log4j by Kevin Goess and
+ Mike Schilli. The authors made sure that their port was as
+ close as possible to the original implementation. Even the
+ configuration files are similar! The project is still being
+ enhanced, however the current release is stable and has been
+ released to CPAN.
+ </dd>
+ <!-- =========================================================================== -->
<dt><a
href="http://www.neoworks.com/products/log4net/"><b>log4net</b></a></dt>
<dd>The .NET implementation of the popular log4j Java API
providing flexible and arbitrarily granular control over log
management and configuration.</dd>
-
+
<!-- =========================================================================== -->
<dt><a
href="http://www.its4you.at/log4py.php"><b>log4py</b></a></dt>
diff --git a/src/xdocs/index.xml b/src/xdocs/index.xml
index 61cc1bd..73337c0 100644
--- a/src/xdocs/index.xml
+++ b/src/xdocs/index.xml
@@ -53,14 +53,13 @@
remote log4j server, a remote Unix Syslog daemon, or even a NT
Event logger among many other output targets.</p>
- <p>On a 233 MHz ThinkPad running JDK 1.1.7B, it costs about 46
- nanoseconds to determine if that statement should be logged or
- not. Actual logging is also quite fast, ranging from 79
- microseconds using the SimpleLayout, 164 microseconds using
- the TTCCLayout and around a millisecond when printing
- exceptions. The performance of the PatternLayout is almost as
- good as the dedicated layouts, except that it is a lot more
- flexible.</p>
+ <p>On an AMD Duron clocked at 800Mhz running JDK 1.3.1, it costs
+ about 5 nanoseconds to determine if a logging statement should
+ be logged or not. Actual logging is also quite fast, ranging
+ from 21 microseconds microseconds using the SimpleLayout, 37
+ microseconds using the TTCCLayout. The performance of the
+ PatternLayout is almost as good as the dedicated layouts,
+ except that it is much more flexible.</p>
<p>The package is being constantly improved thanks to input from
users and code contributed by authors in the community.
diff --git a/src/xdocs/lf5/configuration.xml b/src/xdocs/lf5/configuration.xml
new file mode 100644
index 0000000..ea38eab
--- /dev/null
+++ b/src/xdocs/lf5/configuration.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0"?>
+<document>
+
+ <properties>
+ <author email="BMarlborough@thoughtworks.com">Brad Marlborough</author>
+ <title>LogFactor5 Users' Guide</title>
+ </properties>
+
+ <body>
+ <section name="LogFactor5 Configuration Information">
+
+
+ <p>There are two ways of configuring LogFactor5: using a log4j properties file,
+ or using the Configure menu in the LogFactor5 GUI.
+ </p>
+
+ <h3>Configuration Using a Properties File</h3>
+
+ <p>The <code>LF5Appender</code> has a single property that can
+ be set via a log4j properties file, the
+ <b>MaxNumberOfRecords</b> property. This property is used by
+ LogFactor5 to determine the maximum number of records to
+ display at any one time in the GUI. If this maximum number is
+ exceeded, LogFactor5 begins to remove the oldest records, one
+ at a time. Removing records in this fashion reduces the risk
+ that your computer will run out of memory while the GUI is
+ running. If the <b>MaxNumberOfRecords</b> property is not set,
+ LogFactor5 sets a default value of 5000.</p>
+
+ <p>To set the <b>MaxNumberOfRecords</b> property using a regular
+ <i>java.util.Properties</i> file, you should use the following
+ line (replace A1 with the name of your appender):
+ </p>
+
+<pre> log4j.appender.A1.MaxNumberOfRecords=2000
+</pre>
+
+ <p>To set the <b>MaxNumberOfRecords</b> property using an XML
+ properties file, you should use the following lines (replace
+ the name LF5Appender with the name of your appender):</p>
+<pre>
+ <appender name="LF5Appender" class="org.apache.log4j.lf5.LF5Appender">
+ <param name="MaxNumberOfRecords" value="1000"/>
+ </appender>
+
+ <root>
+ <priority value ="debug" />
+ <appender-ref ref="LF5Appender"/>
+ </root>
+</pre>
+
+ <p><b>Note:</b> Setting the maximum number of records to display
+ via the Configure->Set Max Number Of Records menu in the
+ LogFactor5 GUI will override any value that you set in this
+ configuration file.
+ </p>
+
+ <h3>Configuration Using the GUI</h3>
+ <h4>Save</h4>
+
+ <p> LogFactor5 allows you to save the current configuration of
+ your logging console using the Configure menu. The
+ Configure->Save menu option saves your current GUI
+ configuration to a file called
+ <b>lf5_configuration.xml</b>. This configuration file is a
+ saved to the location <USER_HOME>/lf5 on your local
+ drive.
+ </p>
+
+ <p>The information saved in the configuration file is as
+ follows:</p>
+
+ <ul>
+ <li>The current configuration of the logger explorer window including all
+ selected and de-selected channels</li>
+ <li>The current configuration of all level</li>
+ <li>The view settings, and</li>
+ <li>The last NDC filter used (if the Restore All NDC's item was not selected
+ prior to saving).</li>
+ </ul>
+
+ <p>Once you have saved a configuration, your configuration is loaded each time
+ that you start LogFactor5.</p>
+
+ <h4>Reset</h4>
+
+ <p> You can remove your currently saved configuration by using
+ the Configure->Reset menu option. This will delete the
+ lf5_configuration.xml file from your local file system.</p>
+
+ <h4>Set Max Number Of Records</h4>
+
+ <p>The Configure menu also includes a "Set Max Number Of Records" option,
+ which allows you to change the maximum number of records that will be displayed
+ in the GUI at any time. Setting the maximum number of records using this menu
+ item will override any value that you set in your log4j property file (see below).
+ <b>Note:</b> The value that you set using this option <b>is not</b> saved into
+ the lf5_configuration file.</p>
+
+ <h4>Removing Empty Categories</h4>
+
+ <p>When you save your configuration using the Configure->Save menu option,
+ and then start logging from a different application, you will likely find that
+ many of the categories you saved are empty. You can remove these "dead"
+ categories from the display by right clicking on the root of the category tree
+ in the category explorer, and choosing the "Remove All Empty Categories"
+ option. This will prune the category explorer tree to display only those channels
+ that contain information.</p>
+
+ <p><img src="images/lf5_remove_categories.gif" width="600" height="490"/></p>
+
+ </section>
+ </body>
+</document>
\ No newline at end of file
diff --git a/src/xdocs/lf5/examples.xml b/src/xdocs/lf5/examples.xml
new file mode 100644
index 0000000..24c5f2d
--- /dev/null
+++ b/src/xdocs/lf5/examples.xml
@@ -0,0 +1,564 @@
+<?xml version="1.0"?>
+<document>
+
+ <properties>
+ <author email="BMarlborough@thoughtworks.com">Brad Marlborough</author>
+ <title>LogFactor5 Users' Guide</title>
+ </properties>
+
+ <body>
+ <section name="LogFactor5 Examples">
+
+ <h3><b><font color="#000099">Example 1: InitUsingDefaultConfigurator</font></b>
+ </h3>
+ <h4>Example Description:</h4>
+
+ <p>The LogFactor5 library has a DefaultLF5Configurator class which provides a
+ very basic LogFactor5 configuration for you. This class can be used to programmatically
+ register an LF5Appender at the root of the <i>org.apache.log4j.Category</i>
+ tree. The InitUsingDefaultConfigurator.java class demonstrates how to use this
+ configurator. </p>
+
+ <p>When using this class, all that you have to do is make a call to the static l
+ method DefaultLF5Configurator.configure( ), and your basic configuration will
+ be done for you.</p>
+
+ <h4>Running the Example:</h4>
+
+ <p>Let <code>LOG4J_HOME</code> be the the directory where you
+ installed log4j and let VERSION stand for the log4j version.</p>
+
+ <ul>
+ <li>Ensure that <i>LOG4J_HOME/dist/lib/log4j-VERSION.jar</i>
+ is in your CLASSPATH.</li>
+
+ <li>Ensure that <i>LOG4J_HOME/dist/classes</i> is in your
+ CLASSPATH. This directory contains the binary class files for
+ running the lf5 examples. <em>It is not needed under normal
+ operational circumstances.</em> </li>
+
+ <li>Ensure that a JAXP compatible XML parser is in is in your
+ CLASSPATH.</li>
+
+ <li>Type<b> </b>the following at the command line:
+
+ <p><b> java examples.lf5.InitUsingDefaultConfigurator.InitUsingDefaultConfigurator</b></p>
+ </li>
+ </ul>
+
+ <h3><b><font color="#000099">Example 2: InitUsingPropertiesFile</font> </b> </h3>
+ <h4>Example Description:</h4>
+
+ <p>The log4j environment is fully configurable
+ programmatically. However, it is far more flexible to
+ configure log4j using configuration files. One common method
+ of configuring log4j involves using a properties file, and the
+ <code>org.apache.log4j.PropertyConfigurator</code> class. The
+ <code>PropertyConfigurator</code> class allows you to load
+ properties from a standard properties document consisting of
+ key=value pairs. This example demonstrates how to load
+ LogFactor5 via a configuration file used by a
+ PropertyConfigurator.</p>
+
+ <p>This example uses a very basic properties file, which is
+ loaded via a PropertyConfigurator. The
+ <i>example.properties</i> file has only one property, which
+ registers a <code>LF5Appender</code> with the root of the
+ Category tree. The <code>InitUsingPropertiesFile</code> class
+ loads this file using the <code>PropertyConfigurator</code>
+ class. </p>
+
+ <p><b>Note:</b> The <i>example.properties</i> file used in this
+ example is loaded as a resource via your CLASSPATH. For this
+ reason, the example will only work if the
+ <i>LOG4J_HOME/dist/classes</i> directory is in your
+ CLASSPATH</p>
+
+ <h4>Running the Example:</h4>
+
+ <p>Let <code>LOG4J_HOME</code> be the the directory where you
+ installed log4j.</p>
+
+ <ul>
+ <li>Set up your CLASSPATH as in Example 1 above.</li>
+
+ <li>Type<b> </b>the following at the command line:
+
+ <p><b> java
+ examples.lf5.InitUsingPropertiesFile</b>.<b>InitUsingPropertiesFile</b></p>
+ </li>
+ </ul>
+
+ <!-- ======================================================== -->
+ <!-- Example 3 -->
+ <!-- ======================================================== -->
+
+ <h3><b><font color="#000099">Example 3: InitUsingXMLPropertiesFile</font></b>
+ </h3>
+
+ <h4>Example Description:</h4>
+
+ <p>Log4j can also be configured using an XML properties file,
+ and the <i>org.apache.log4j.xml.DOMConfigurator</i> class. The
+ DOMConfigurator class allows you to load properties from an
+ XML based properties file. This example demonstrates how to
+ load LogFactor5 via an XMLconfiguration file used by a
+ DOMConfigurator.
+ </p>
+
+ <p>This example uses a very basic XML properties file. The
+ example.xml file registers an LF5Appender with the root of the
+ Category tree. The InitUsingXMLPropertiesFile.java class loads
+ this file using the DOMConfigurator class.
+ </p>
+
+ <p><b>Note:</b> The <i>example.xml</i> file used in this example
+ is loaded as a resource via your CLASSPATH. For this reason,
+ the example will only work if the
+ <i>LOG4J_HOME/dist/classes</i> directory is in your
+ CLASSPATH. You will also need an XML parser in order to run
+ this example.
+ </p>
+
+ <h4>Running the Example:</h4>
+
+ <p>Let <code>LOG4J_HOME</code> be the the directory where you
+ installed log4j.</p>
+
+ <ul>
+ <li>Set up your CLASSPATH as in Example 1 above.</li>
+
+ <li>Type<b> </b>the following at the command line:
+
+ <p><b> java
+ examples.lf5.InitUsingXMLPropertiesFile.InitUsingXMLPropertiesFile</b></p>
+ </li>
+ </ul>
+
+ <!-- ======================================================== -->
+ <!-- Example 4 -->
+ <!-- ======================================================== -->
+
+ <h3><b><font color="#000099">Example 4:
+ InitUsingLog4JProperties</font></b> </h3>
+
+ <h4>Example Description:</h4>
+
+ <p>The log4j library does not make any assumptions about its
+ environment. In particular, there are no default log4j
+ appenders. Under certain well-defined circumstances however,
+ the static initializer of the <i>org.apache.log4j.Category
+ </i>class will attempt to automatically configure log4j. The
+ Java language guarantees that the static initializer of a
+ class is called once and only during the loading of a class
+ into memory. This automatic configuration is done from a file
+ named <b>log4j.properties</b>. If you have a log4j.properties
+ file in your CLASSPATH at the time that you instantiate a
+ Category, log4j will register any appenders in this file at
+ the root of the Category tree.
+ </p>
+
+ <p>This example provides you with a very basic log4j.properties
+ file that you can add to your CLASSPATH in order to register
+ the LF5Appender with the Category class. If you put this file
+ somewhere in your CLASSPATH, all logging requests will now
+ automatically be redirected to the LogFactor5 logging console
+ in addition to any other Appenders you may have enabled.
+ </p>
+
+ <p>If you look at the InitUsingLog4JProperties.java file you
+ will notice that no Configurators are used in the code. A
+ Category is instantiated using the getInstance() method, and
+ logging calls such as cat.debug( ) can be used immediately.
+ </p>
+
+ <p><b>Note: </b>Adding the
+ <i>LOG4J_HOME/examples/lf5/InitUsingLog4JProperties/log4j.properties</i>
+ file to your CLASSPATH will reduce the number of lines of code
+ you have to write (e.g. you will not need to add lines such as
+ PropertyConfigurator.configure(configFileResource)). However,
+ you should be aware that using this default static
+ initialization has application wide effects. All logging will
+ be directed to LogFactor5 if you use this approach!
+ </p>
+
+ <h4>Running the Example:</h4>
+
+ <ul>
+ <li>Set up your CLASSPATH as in Example 1 above.</li>
+
+ <li>Copy the provided
+ <i>LOG4J_HOME/examples/lf5/InitUsingLog4JProperties/log4j.properties</i>
+ file to a directory that is currently in your
+ CLASSPATH. </li>
+
+ <li>Type<b> </b>the following at the command line:
+
+ <p><b> java
+ examples.lf5.InitUsingLog4JProperties.InitUsingLog4JProperties</b></p>
+ </li>
+
+ <li>After you are done running the example, make sure to
+ remove the <i>log4j.properties</i> file again, otherwise the
+ log4j will always be using the same configuration.</li>
+ </ul>
+
+ <!-- ======================================================== -->
+ <!-- Example 5 -->
+ <!-- ======================================================== -->
+
+ <h3><b><font color="#000099">Example 5: InitUsingMultipleAppenders</font></b>
+ </h3>
+ <h4>Example Description:</h4>
+
+ <p>In Log4J, output destinations are called
+ appenders. Currently, appenders exit for the console, rolling
+ log files, remote socket servers, NT Event Loggers, and remote
+ UNIX Syslog daemons. Suppose you want to output log messages
+ to more than one appender...</p>
+
+ <p>This example demonstrates how to use LogFactor5 along with
+ Log4J's RollingFileAppender to output log messages to both the
+ LogFactor5 console and a series of rolling log files. The
+ example.properties registers two appenders with the root of
+ the Category tree. </p>
+
+<pre><font face="Courier New, Courier, mono">log4j.rootCategory=, A1, R
+
+# A1 is set to be a LF5Appender which outputs to a swing
+# logging console.
+
+log4j.appender.A1=org.apache.log4j.lf5.LF5Appender
+
+# R is the RollingFileAppender that outputs to a rolling log
+# file called rolling_log_file.log.
+
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=rolling_log_file.log</font>
+</pre>
+
+ <p>Users must also define a Pattern Layout for the log
+ file. That is, which pieces of information you want logged to
+ the log file and in which order. Information on the various
+ conversion specifiers (i.e. d, p, t, l, m, n) are documented
+ in the PatternLayout class of the Log4J API.</p>
+
+<pre>log4j.appender.R.layout=org.apache.log4j.PatternLayout
+# Next line is editited to fit.
+log4j.appender.R.layout.ConversionPattern=[slf5s.start]%d{DATE}[slf5s.DATE]%n\
+ %p[slf5s.PRIORITY]%n%x[slf5s.NDC]%n%t[slf5s.THREAD]%n%c[slf5s.CATEGORY]%n\
+ %l[slf5s.LOCATION]%n%m[slf5s.MESSAGE]%n%n
+</pre>
+
+ <p>Users also have the ability to set the size of the rolling log file(s) and
+ the number of backup files that should be kept. In this case the the size of
+ the maximum size of the log file is 100KB and the number of backup files kept
+ is 1.</p>
+<pre>
+log4j.appender.R.MaxFileSize=100KB
+log4j.appender.R.MaxBackupIndex=1
+</pre>
+
+ <p>The InitUsingMultipleAppenders.java class loads this file
+ using the PropertyConfigurator class. </p>
+
+ <p><b>Note:</b> Another approach would be to add the
+ RollingFileAppender configuration to the log4j.properties
+ file. This would cause the InitUsingLog4JProperties example to
+ use both the LogFactor5 console and a rolling log file as it's
+ output destinations.
+ </p>
+
+ <h4>Running the Example:</h4>
+
+ <ul>
+ <li>Set up your CLASSPATH as in Example 1 above.</li>
+
+ <li>Type<b> </b>the following at the command line:
+
+ <p><b> java
+ examples.lf5.InitUsingMultipleAppenders.InitUsingMultipleAppenders</b></p>
+ </li>
+ </ul>
+
+
+ <!-- ======================================================== -->
+ <!-- Example 6 -->
+ <!-- ======================================================== -->
+ <h3><b><font color="#000099">Example 6: UsingSocketAppenders</font></b> </h3>
+ <h4>Example Description:</h4>
+
+ <p>When logging messages from an application, it is often useful
+ to log the messages to a remote location over a socket. Log4j
+ comes with a variety of classes designed for this
+ purpose. This example is designed to show you how to use these
+ log4j classes in conjunction with the LF5Appender.
+ </p>
+
+ <p>Two specific log4j classes are instrumental for logging
+ messages over a socket: the
+ <i>org.apache.log4j.net.SocketAppender</i> class and the
+ <i>org.apache.log4j.net.SocketServer</i> class. </p>
+
+ <p><b>The SocketAppender class:</b></p>
+
+ <p>The SocketAppender class is used on the application side,
+ where log messages are being created. This class sends all
+ logging messages to a specific host and port as specified in a
+ properties file. The properties file can be either an
+ application specific properties file, or the system
+ log4j.properties file. In this example, the
+ socketclient.properties file contains the information that
+ registers the SocketAppender with log4j. The following lines
+ from the socketclient.properties file register the
+ SocketAppender with log4j:
+ </p>
+<pre>
+ log4j.appender.A1=org.apache.log4j.net.SocketAppender
+ log4j.appender.A1.RemoteHost=localhost
+ log4j.appender.A1.Port=8887
+</pre>
+
+ <p>For additional details about properties files, refer to the log4j documentation
+ or the other LogFactor5 examples.
+ </p>
+
+ <p><b>The SocketServer class:</b></p>
+
+ <p>The SocketServer class listens on a port specified as a
+ command line argument. The host and port of the machine
+ running the SocketServer class must correspond to the host and
+ port in the socketclient.properties file. The SocketServer
+ class uses a separate properties file to determine which
+ Appenders it should forward incoming messages to. In this
+ example, the socketserver.properties file contains the
+ information that registers the LF5Appender with log4j. The
+ following lines from the socketserver.properties file register
+ the LF5Appender with log4j on the server side:</p>
+
+<pre>
+ log4j.appender.A=org.apache.log4j.lf5.LF5Appender
+ log4j.appender.A1.MaxNumberOfRecords=700
+</pre>
+
+ <p> The first line registers the LF5Appender with log4j, and the
+ second line tells LogFactor5 the maximum number of records to
+ display in the GUI at any one time. For additional
+ information about how the SocketServer class loads properties
+ files (including default properties files) please refer to the
+ log4j documenation.
+ </p>
+
+ <h4>Running the Example:</h4>
+ <ul>
+ <li>Set up your CLASSPATH as in Example 1 above.</li>
+
+ <li> Start the SocketServer using the following command: </li>
+
+ <p><b>java org.apache.log4j.net.SimpleSocketServer 8887
+ LOG4J_HOME/examples/lf5/UsingSocketAppenders/socketserver.properties</b></p>
+
+ <li>At another command line, start the client using the
+ following command:</li>
+
+ <p><b> java examples.lf5.UsingSocketAppenders.UsingSocketAppenders</b></p>
+ </ul>
+
+ <!-- ======================================================== -->
+ <!-- Example 7 -->
+ <!-- ======================================================== -->
+
+ <h3><b><font color="#000099">Example 7: OpeningLogFiles</font></b> </h3>
+ <h4>Example Description:</h4>
+
+ <p>Log4J's RollingFileAppender gives you the ability to output
+ log messages to a series of rolling files. However, there are
+ no utilities available for reading in and viewing those files
+ once they have been written. LogFactor5 provides developers
+ with two easy ways to open and view log files. Log files can
+ be opened locally using the 'Open' menu item or log files can
+ be opened from a remote server using the 'Open URL' menu
+ item.
+ </p>
+
+ <p>An additional feature that was added to LogFactor5 was the
+ ability to start the console window independent of Log4J. That
+ is to say, you do not need to add a LF5Appender to your
+ properties file to use LogFactor5. The benefit of this feature
+ is that developers who run utilities like Ant to test their
+ applications can now view their log files off-line (i.e. after
+ their application has completed the test and the JVM has shut
+ down). Moreover, the ability to open log files on a remote
+ server provides the ability for multiple developers working on
+ the same application to view log files independently. It also
+ gives developers the ability to view log files both internally
+ and from remote locations.
+ </p>
+
+ <p>This example uses the sample.log file created by Log4J's
+ RollingFileAppender. 1The format of the log file can be set in
+ the log4j.properties or a standard properties file and
+ <b>must</b> follow the LogFactor5 layout conventions in order
+ for LogFactor5 to open the file. The following is an example
+ of a properties file with the LogFactor5 conversion pattern
+ added:
+ </p>
+
+<pre><font face="Times New Roman, Times, serif">log4j.rootCategory= R
+
+# R is the RollingFileAppender that outputs to a rolling log
+# file called sample.log.
+
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=sample.log
+
+# Define a pattern layout for the file.
+# For more information on conversion characters (i.e. d,p,t,c,l,m,n)
+# please see the PatternLayout class of the Log4j API.
+
+<b>log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=</b><b>[slf5s.start]%d{DATE}[slf5s.DATE]%n\
+%p[slf5s.PRIORITY]%n%x[slf5s.NDC]%n%t[slf5s.THREAD]%n\
+%c[slf5s.CATEGORY]%n%l[slf5s.LOCATION]%n%m[slf5s.MESSAGE]%n%n</b>
+
+# Set the max size of the file
+
+log4j.appender.R.MaxFileSize=500KB</font></pre>
+
+ <p>You are free to use any or all of the main conversion
+ characters to create ml your log file (i.e. %p for
+ Priority). There are only two requirements for the conversion
+ pattern. First, the conversion pattern string <b>must</b>
+ start with the tag <b>[slf5s.start]</b>. Second, for each
+ log4j conversion character listed in the conversion pattern
+ string, a corresponding LogFactor5 tag <b>must</b> be placed
+ immediately <b>after</b> the character. The following is a
+ complete list of the log4j characters and LogFactor5 tags:
+ </p>
+
+<pre><font face="Times New Roman, Times, serif">Date - %d{DATE}[slf5s.DATE]
+Priority - %p[slf5s.PRIORITY]
+NDC - %x[slf5s.NDC]
+Thread - %t[slf5s.THREAD]
+Category - %c[slf5s.CATEGORY]
+Location - %l[slf5s.LOCATION]
+Message - %m[slf5s.MESSAGE]</font>
+</pre>
+
+ <p> <b>Note:</b> The order of the characters does not matter so
+ you are free to layout your log file any way you like. Just
+ remember to include the LogFactor5 start tag at the beginning
+ of the string and any LogFactor5 tags after each corresponding
+ log4j conversion character.</p>
+
+ <h4>Running the Example:</h4>
+
+ <ul>
+ <li>Set up your CLASSPATH as in Example 1 above.</li>
+
+ <li>Type<b> </b>the following at the command line:<b> java
+ org.apache.log4j.lf5.StartLogFactor5</b>
+ </li>
+
+ <li>Under the 'File' menu, select 'Open'.</li>
+
+ <li>Open the <i>sample.log</i> file located in the <font
+ face="Courier New, Courier,
+ mono">examples/lf5/OpeningLogFiles</font> directory.</li>
+
+ <li>Clear the log table using the Clear Log Table button.</li>
+ </ul>
+
+ <!-- ======================================================== -->
+ <!-- Example 8 -->
+ <!-- ======================================================== -->
+ <h3><b><font color="#000099">Example 8</font></b></h3>
+ <h4><b><font color="#000099">Example 8a: UsingLogMonitorAdapter</font></b></h4>
+ <h4>Example Description:</h4>
+
+ <p>Ideally LogFactor5's intended use is with Log4J, but this
+ does not preclude its use with other logging schemes. The
+ LogMonitorAdapter API allows developers to log directly to the
+ LogFactor5 GUI Monitor with a minimum of effort.
+ </p>
+
+ <p>The UsingLogMonitorAdapter.java class demonstrates how to use
+ the LogMonitorAdapter. This example requests a new instance
+ of the LogMonitorAdapter, and uses the log4j Priority
+ levels. </p>
+
+<pre> _adapter = LogMonitorAdapter.newInstance(LogMonitorAdapter.LOG4J_LOG_LEVELS);</pre>
+<p>When you log to the LogFactor5 GUI Monitor, simply call one of the many log
+ methods on the LogMonitorAdapter object:</p>
+<pre> _adapter.log(channel,"Doh this is a debugging");
+
+ _adapter.log(channel,LogLevel.INFO,"Hmmm fobidden doughnut");
+ _adapter.log(channel,LogLevel.WARN,"Danger Danger Will Robinson",
+ new RuntimeException("DANGER"), "32");
+ _adapter.log(channel,LogLevel.ERROR,"Exit stage right->");
+ _adapter.log(channel,LogLevel.FATAL,"What's up Doc?",
+ new NullPointerException("Unfortunate exception"));
+</pre>
+
+ <h4>Running the Example:</h4>
+ <ul>
+ <li>Set up your CLASSPATH as in Example 1 above.</li>
+
+ <li>Type<b> </b>the following at the command line:
+
+ <p><b>java
+ examples.lf5.UsingLogMonitorAdapter.UsingLogMonitorAdapter</b></p>
+ </li>
+ </ul>
+
+ <h4><b><font color="#000099">Example 8b: CustomizedLogLevels</font></b> </h4>
+ <h4>Example Description:</h4>
+
+ <p>What good is a LogMonitorAdapter if you can only use preset
+ LogLevels? This example illustrates how to use the
+ LogMonitorAdapter with a set of user-defined LogLevels.</p>
+
+ <p>The CustomizedLogLevels.java class demonstrates how to customize LogLevels ml
+ to suit your logging needs. As with the previous example we request an instance
+ of the LogMonitorAdapter, but this time an array of defined LogLevels is supplied:</p>
+
+<pre> _adapter = LogMonitorAdapter.newInstance(new LogLevel[] {DEFAULT, LEVEL_ONE,
+ LEVEL_TWO,LEVEL_THREE, LEVEL_FOUR });
+</pre>
+
+ <p>The LogMonitorAdapter will set the first entry in the array to be the default
+ LogLevel. For example, when logging a message where no LogLevel has been specified,
+ the DEFAULT LogLevel will be used. The default LogLevel can also be set using
+ the LogMonitorAdapter's setDefaultLevel method, while the severe LogLevel can
+ be set as follows:
+ </p>
+
+<pre> _adapter.setSevereLevel(LEVEL_ONE);</pre>
+ <p></p>
+
+ <p>Logging messages then follow the same rules as the example above.</p>
+
+<pre> _adapter.log(channel,"Using the customized LogLevels");
+
+ _adapter.log(channel,LEVEL_FOUR,"This is a test");
+ _adapter.log(channel,LEVEL_THREE,"Hmmm fobidden doughnut");
+ _adapter.log(channel,LEVEL_ONE,"Danger Danger Will Robinson",
+ new RuntimeException("DANGER"), "32");
+ _adapter.log(channel,LEVEL_TWO,"Exit stage right->");
+ _adapter.log(channel,LEVEL_FOUR,"What's up Doc?",
+ new NullPointerException("Unfortunate exception"));
+ </pre>
+
+ <h4>Running the Example:</h4>
+ <ul>
+ <li>Set up your CLASSPATH as in Example 1 above.</li>
+
+ <li>Type<b> </b>the following at the command line:
+
+ <p><b> java
+ examples.lf5.UsingLogMonitorAdapter.CustomizedLogLevels</b></p>
+ </li>
+ </ul>
+ </section>
+ </body>
+</document>
\ No newline at end of file
diff --git a/src/xdocs/lf5/faq.xml b/src/xdocs/lf5/faq.xml
new file mode 100644
index 0000000..33bb853
--- /dev/null
+++ b/src/xdocs/lf5/faq.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<document>
+
+ <properties>
+ <author email="BMarlborough@thoughtworks.com">Brad Marlborough</author>
+ <title>LogFactor5 Users' Guide</title>
+ </properties>
+
+ <body>
+ <section name="Frequently Asked Questions">
+
+
+ <p><b>Q. What is LogFactor5?</b> </p>
+
+ <p><b>A.</b> LogFactor5 is a Swing based GUI that leverages the
+ power of log4j to provide developers with a sophisticated,
+ feature-rich, visual tool for managing log messages.</p>
+
+ <hr/>
+
+ <p><b>Q. Do I need to know how to use log4j in order to use LogFactor5?</b></p>
+
+ <p><b>A.</b> Yes, the documentation for LogFactor5 assumes the
+ user has some understanding of how log4j works. Note however
+ that the LogFactor5 examples will run regardless of a user's
+ log4j knowledge level.</p> <hr/>
+
+ <p><b>Q. What are the memory requirements for LogFactor5?</b></p>
+
+ <p><b>A.</b> The LogFactor5 logging console window uses around
+ 13 MB of memory to run on a Windows OS. Our memory profiling
+ has shown that with a logging message of 25 words in length,
+ and a stack trace nested seven methods deep, every 1000
+ records displayed in the logging console uses about 6.5 MB of
+ memory. For this reason, when you are setting the maximum
+ number of log records to be shown, you should be careful that
+ you have enough memory to display all of the records. The
+ default maximum number of records that will be displayed is
+ set to 5000 to minimize the possibility of running out of
+ memory. We recommend that Windows users have at least 96 MB of
+ RAM when using LogFactor5.</p>
+
+ </section>
+ </body>
+</document>
diff --git a/src/xdocs/lf5/features.xml b/src/xdocs/lf5/features.xml
new file mode 100644
index 0000000..a90dca7
--- /dev/null
+++ b/src/xdocs/lf5/features.xml
@@ -0,0 +1,249 @@
+<?xml version="1.0"?>
+<document>
+
+ <properties>
+ <author email="BMarlborough@thoughtworks.com">Brad Marlborough</author>
+ <title>LogFactor5 Features Users' Guide</title>
+ </properties>
+
+ <body>
+ <section name="LogFactor5 Features">
+
+ <h3><font color="#000099">Manage Log Messages</font></h3>
+
+ <p>The Log Table pane shows the listing of LogRecords that have
+ been sent to the LogFactor5 appender. The newest log messages
+ appear at the bottom of the table.
+ </p>
+
+ <p><img src="images/lf5_logtable.gif" align="absbottom" alt="Log Table" width="600" height="489"></img></p>
+
+ <h4><font face="Verdana, Arial, Helvetica, sans-serif" size="3"><a name="levels"></a></font>Log
+ Level Selection </h4>
+
+ <p>The LogFactor5 toolbar applies directly to the Log Table
+ area. Log levels can be toggled on and off to filter out
+ messages that you want to view or hide. Levels include FATAL,
+ ERROR, WARN, INFO and DEBUG. </p>
+
+
+ <p><img src="images/lf5_loglevels.gif" width="600" height="488"
+ alt="Log Levels"/></p>
+
+ <p><a name="color"></a><b>Log Level Color Configuration</b></p>
+
+ <p>To help distiguish the various log events displayed in the
+ LogTable, LogFactor5 allows users to set the colors of their
+ log events based on level.</p>
+
+ <p><img src="images/lf5_colorchooser.gif" width="600"
+ height="489" alt="Log Level Color Configuration"/></p>
+
+ <h4><a name="search"></a>Full Text Searching</h4>
+
+ <p>The Log Table supports full text searching. To perform a
+ search, choose Edit->Find from the menu bar or CTRL-F and
+ then enter the text you want to search for. LogFactor5 will
+ find any strings that are an exact match for the string you
+ entered. Pressing F3 will find the next occurrence of the
+ string.
+ </p>
+
+ <p><img src="images/lf5_search.gif" width="600" height="488"
+ alt="Full Text Searching"/></p>
+
+ <h4><a name="views"></a>Log Table Views</h4>
+
+ <!-- =========================================================== -->
+ <!-- In the next paragraph, changed category to logger, priority -->
+ <!-- to level, LogRecord to event. (Ceki) -->
+ <!-- =========================================================== -->
+ <p>The Log Table has three views; compact, standard and
+ detailed. The compact view only displays the Nested Diagnostic
+ Context (NDC), logger and message. The standard view is the
+ default view, and displays the level, NDC, logger and message
+ of the logging event. The detailed view displays, in addition,
+ the date, message number, location (i.e. the method that is
+ logging the message), thread description and the
+ throwable. The view selector on the toolbar switches between
+ the three views. Columns in the Log Table can be re-sized and
+ moved by interacting with the column headers.
+ </p>
+
+ <p><img src="images/lf5_view.gif" width="600" height="489"
+ alt="Log Table View"/></p>
+
+ <h4><a name="recorddetails"></a>Log Record Details</h4>
+
+ <p>The Log Record Detail area displays all of the attributes of
+ the LogRecord which is selected in the Log Table. When a row,
+ or LogRecord, is selected in the Log Table, the complete
+ details of that LogRecord are displayed in the LogRecord
+ Detail area, independent of the view in effect.
+ </p>
+
+ <p><img src="images/lf5_recorddetail.gif" width="600"
+ height="481" alt="LogRecord Details"/>
+ </p>
+
+ <!-- ============================================================ -->
+ <!-- In the next 2 paragraphs, changed category to logger. (Ceki) -->
+ <!-- ============================================================ -->
+ <h4><a name="explorer"></a>Logger Explorer</h4>
+
+ <p>The Logger Explorer area enables the filtering of incoming
+ log messages based on logger. If a logger is deselected
+ (no checkmark is shown next to it) then new messages on that
+ logger will not be displayed. The Logger Explorer has no
+ effect on log messages already in the Log Table.
+ </p>
+
+ <p>The Logger Explorer displays loggers in a hierarchical
+ tree-like fashion. Loggers are identified with
+ dot-separated names similar to Java package and class
+ names. The name components are mapped to the levels in the
+ hierarchy in the Logger Explorer. For example, the logger
+ name org.apache.applications.log4j.InitUsing Log4JProperties
+ is displayed below:
+ </p>
+
+ <p><img src="images/lf5_category_explorer.gif" width="600"
+ height="481" alt="Logger Explorer"/></p>
+
+
+ <h4><a name="selectloggers"></a>Selecting and Deselecting Loggers</h4>
+
+ <p>When a logger in a hierarchy is deselected, no messages at
+ that level or below will appear in the Log Table. For example,
+ if just the first InitUsingMultipleAppenders logger in the
+ examples.InitUsingMultipleAppenders.InitUsingMultipleAppenders
+ logger is deselected, then messages with the logger examples
+ would be displayed in the Log Table, but messages with the
+ logger InitUsingMultipleAppenders.InitUsingMultipleAppenders
+ would be filtered and not displayed in the Log Table.
+ </p>
+
+ <p>To quickly select or deselect loggers in the hierarchy,
+ the right-mouse button can be used to bring up the pop-up menu
+ displayed below. </p>
+
+ <p><img src="images/lf5_deselectall.gif" width="600"
+ height="488" alt="Deselect All Descendants"/></p>
+
+ <p><img src="images/lf5_selectall.gif" width="600"
+ height="488" alt="Select All Descendants"/></p>
+
+
+ <h4><a name="expandcattree"></a>Expanding and Collapsing the Logger Tree</h4>
+
+ <p>You can also expand and collapse the hierarchy tree using
+ the pop-up menu displayed below.</p>
+
+ <p><img src="images/lf5_expandall.gif" width="600" height="488"
+ alt="Expand Tree"/></p>
+
+ <p><img src="images/lf5_collapseall.gif" width="600"
+ height="488" alt="Collapse Tree"/></p>
+
+ <H4><a name="ndcfiltering"></a>NDC Record Filtering</H4>
+
+
+ <p>Log4j provides a lightweight technique for stamping log
+ requests initiated from the same client within a multithreaded
+ system. The Nested Diagnostic Context (NDC) provides an easy
+ way to differentiate logging output of one client from
+ another. The NDC is also useful for differentiating log
+ messages being output by different members of a large
+ development team building an application on the same
+ server. To improve the sorting of potentially thousands of log
+ records being output from multiple clients, a NDC filter has
+ been provided. To use the NDC filter, select the Edit menu
+ item and choose 'Sort by NDC'. Fill in the name of the NDC you
+ would like to filter on. All records containing the filter key
+ word will be displayed in the Log Table. To restore all of the
+ log records use the Edit -> Restore all NDC's. You can also
+ use the Edit->Find feature to locate NDC's without removing
+ log records from the Log Table. Furthermore, you can use the
+ Configure->Save feature to persist the last NDC filter key
+ word that was used. Note however that restoring all NDCs will
+ effectively erase the NDC filter key word. Refer to the <a
+ href="#configuration">Configuration section</a> below for more
+ information on saving NDC filter key words.</p>
+
+ <p><img src="images/lf5_ndc_filtering.gif" width="600"
+ height="488" alt="NDC Filtering"/></p>
+
+
+ <font color="#000099"><h3>Read Log Files</h3>
+ </font>
+
+ <h4><a name="readfile"></a>Read a File</h4>
+
+ <p>LogFactor5 supports reading in log files that were created
+ using log4j's RollingFileAppender. The benefit of this
+ feature is that developers who run utilities like Ant to test
+ their applications can now view their log files off-line
+ (i.e. after their application has completed the test and the
+ JVM has shut down). Reading log files currently only works for
+ files written a LogFactor5's unique ConversionPattern. For
+ more information on setting the LogFactor5 conversion pattern,
+ please see the OpeningLogFiles example. To open a file and
+ read it into LogFactor5, you need to start the logging console
+ using the StartLogFactor5Console.bat file provided in the bin
+ directory. Once the console is open, choose File->Open from
+ the menu at the top of the GUI.
+ </p>
+
+ <p><img src="images/lf5_openfile.gif" width="600" height="488"
+ align="absbottom" alt="Log Table"/></p>
+
+ <h4><a name="readurl"></a>Read a File From a URL</h4>
+
+ <p>LogFactor5 supports reading log files created using log4j
+ from a URL. Having the ability to open log files on a remote
+ server provides the ability for multiple developers working on
+ the same application to view log files independently. It also
+ gives developers the ability to view log files both internally
+ and from remote locations. Reading log files currently only
+ works for files written a LogFactor5's unique
+ ConversionPattern. For more information on setting the
+ LogFactor5 conversion pattern, please see the <a
+ href="example7.html">OpeningLogFiles</a> example. To open a
+ file and read it into LogFactor5, you need to start the
+ logging console using the StartLogFactor5Console.bat file
+ provided in the bin directory. Once the console is open,
+ choose File->Open URL from the menu at the top of the GUI.
+ </p>
+
+ <p><img src="images/lf5_openurl.gif" width="600" height="488" align="absbottom" alt="Log Table"/> </p>
+
+ <p><a href="#top"><font size="2"><< Return to Top of Page >></font></a></p>
+
+ <font color="#000099"> <h3>Configuration</h3></font>
+
+ <h4><a name="configuration"></a>Save Configuration Information</h4>
+
+ <p>LogFactor5 allows you to save your current
+ configuration. When you choose the Configuration->Save
+ option from the menu at the top of the GUI, the loggers and
+ levels that you currently have selected, along with the last
+ NDC filter key word used (assuming 'Restore all NDC's' has not
+ been selected), are saved to your local file system. This
+ means that the next time you start up the console you will not
+ need to reselect the loggers, levels, and NDC filter that you
+ would like used for filtering.
+ </p>
+
+ <p>LogFactor5 also allows you to remove your saved
+ configuration, and to configure the maximum number of records
+ that will be displayed at any time in the logging
+ console. Setting the maximum number of records to display
+ allows you to optimize LogFactor5's performance for your
+ system. The maximum number of records can also be configured
+ via a log4j properties file.
+ </p>
+
+ <p><img src="images/lf5_configure.gif" width="600" height="488" align="absbottom" alt="Log Table"/></p>
+ </section>
+ </body>
+</document>
\ No newline at end of file
diff --git a/src/xdocs/lf5/overview.xml b/src/xdocs/lf5/overview.xml
new file mode 100644
index 0000000..bfea0bb
--- /dev/null
+++ b/src/xdocs/lf5/overview.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0"?>
+<document>
+
+ <properties>
+ <author email="BMarlborough@thoughtworks.com">Brad Marlborough</author>
+ <title>LogFactor5 Users' Guide</title>
+ </properties>
+
+ <body>
+ <section name="LogFactor5 Overview">
+
+ <p><b>What is LogFactor5?</b> - LogFactor5 is a Swing based GUI
+ that leverages the power of log4j logging framework and
+ provides developers with a sophisticated, feature-rich,
+ logging interface for managing log messages.
+ </p>
+
+ <p><b>How does it work?</b> - LogFactor5 seamlessly plugs into
+ log4j and provides developers with an alternate destination
+ for outputting messages. </p>
+
+ <p><b>Benefits:</b></p>
+ <ul>
+ <li>Quickly isolate problems in your application.</li>
+ <li>Enable only the categories that you are interested in without affecting
+ other messages.</li>
+ <li>Filter out priority levels you don't need.</li>
+ <li>Filter out records based on NDC.</li>
+ <li>Reduce the time required to locate specific messages.</li>
+ <li>Read in and view log4j log files from either a file or a URL.</li>
+ <li>Start the LogFactor5 GUI up independent of your application.</li>
+ </ul>
+ <p><b>Features: </b>
+ <ul>
+ <li>Real-time category and log level filtering.</li>
+ <li>Read log files from a file.</li>
+ <li>Read log files from a URL.</li>
+ <li>Customizable Log Table view.</li>
+ <li>Category level tree navigation.</li>
+ <li>NDC record filtering.</li>
+ <li>Full text searching on logged messages.</li>
+ <li>Save configuration and filtering settings for later sessions.</li>
+ <li>Configure the number of log records to be displayed.</li>
+ <li>Customizable record colors.</li>
+ <li>Configurable font face and size.</li>
+ <li>Customizable Log Table column layout.</li>
+ <li>Full support for all log4j levels.</li>
+ <li>Full support for custom levels.</li>
+ <li>Dynamic message counting.</li>
+ </ul>
+ </p>
+
+ <p><b>LogFactor5 System Requirements:</b></p>
+
+ <p>LogFactor5 requires Java (TM) Virtual Machine 1.2.2 and log4j
+ 1.2 or later.
+ </p>
+
+ <p><b> Documentation and Help</b></p>
+ <ul>
+ <li>All documentation is in HTML format.</li>
+
+ <li>For additional documentation on logging, please see the <a
+ href="suggested_reading.html">Suggested Reading</a>
+ section. </li>
+ </ul>
+ <p><b> Platform Support</b></p>
+ <ul>
+ <li>LogFactor5 is written in 100% Java and will work with any
+ system supporting the Java 2 platform.</li>
+ </ul>
+ <p></p>
+
+ </section>
+ </body>
+</document>
\ No newline at end of file
diff --git a/src/xdocs/lf5/readingfiles.xml b/src/xdocs/lf5/readingfiles.xml
new file mode 100644
index 0000000..9039bda
--- /dev/null
+++ b/src/xdocs/lf5/readingfiles.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0"?>
+<document>
+
+ <properties>
+ <author email="BMarlborough@thoughtworks.com">Brad Marlborough</author>
+ <title>LogFactor5 Users' Guide</title>
+ </properties>
+
+ <body>
+ <section name="Reading Log Files">
+
+ <p><code>FileAppender</code> and derived classes give you the
+ ability to output log messages to a files. LogFactor5 provides
+ developers with two easy ways to open and view these log
+ files. Log files can be opened locally using the File->Open
+ menu item or log files can be opened from a remote server
+ using the File->Open URL menu item.
+ </p>
+
+ <p>An additional feature that was added to LogFactor5 was the
+ ability to start the console window independently of
+ log4j. That is to say, you do not need to add a
+ <code>LF5Appender</code> to your properties file to use
+ LogFactor5. The benefit of this feature is that developers who
+ run utilities like Ant to test their applications can now view
+ their log files off-line (i.e. after their application has
+ completed the test and the JVM has shut down). Moreover, the
+ ability to open log files on a remote server provides the
+ ability for multiple developers working on the same
+ application to view log files independently. It also gives
+ developers the ability to view log files both internally and
+ from remote locations.
+ </p>
+
+ <p>LogFactor5 can read in log files created with
+ <code>RollingFileAppender</code>. The format of the log file
+ can be set in the log4j.properties or a standard properties
+ file and <b>must</b> follow the LogFactor5 layout conventions
+ in order for LogFactor5 to read the file. The following is an
+ example of a properties file with the LogFactor5 conversion
+ pattern added:
+ </p>
+
+<pre><font face="Times New Roman, Times, serif">
+log4j.rootLogger=debug, R
+
+# R is the RollingFileAppender that outputs to a rolling log
+# file called sample.log.
+
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=sample.log
+
+# Define a pattern layout for the file.
+# For more information on conversion characters (i.e. d,p,t,c,l,m,n)
+# please see the PatternLayout class of the Log4j API.
+
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+
+# The following normally appears on one single line.
+<b>log4j.appender.R.layout.ConversionPattern=[slf5s.start]%d{DATE}[slf5s.DATE]%n\
+ %p[slf5s.PRIORITY]%n%x[slf5s.NDC]%n%t[slf5s.THREAD]%n\
+ %c[slf5s.CATEGORY]%n%l[slf5s.LOCATION]%n%m[slf5s.MESSAGE]%n%n</b>
+
+# Set the max size of the file
+log4j.appender.R.MaxFileSize=500KB</font></pre>
+
+ <p>You are free to use any or all of the main conversion
+ characters to create your log file (i.e. %p for
+ Priority). There are only two requirements for the conversion
+ pattern. First, the conversion pattern string <b>must</b>
+ start with the tag <b>[slf5s.start]</b>. Second, for each
+ log4j conversion character listed in the conversion pattern
+ string, a corresponding LogFactor5 tag <b>must</b> be placed
+ immediately <b>after</b> the character. The following is a
+ complete list of the log4j characters and LogFactor5 tags:
+ </p>
+
+<pre><font face="Times New Roman, Times, serif">Date - %d{DATE}[slf5s.DATE]
+Priority - %p[slf5s.PRIORITY]
+NDC - %x[slf5s.NDC]
+Thread - %t[slf5s.THREAD]
+Category - %c[slf5s.CATEGORY]
+Location - %l[slf5s.LOCATION]
+Message - %m[slf5s.MESSAGE]</font>
+</pre>
+
+ <p> <b>Note:</b> The order of the characters does not matter so
+ you are free to layout your log file any way you like. Just
+ remember to include the LogFactor5 start tag at the beginning
+ of the string and any LogFactor5 tags after each corresponding
+ log4j conversion character. For more information or to see a
+ working example, try the OpeningLogFiles example in the
+ examples directory.
+ </p>
+ </section>
+ </body>
+</document>
+
+
diff --git a/src/xdocs/lf5/trouble.xml b/src/xdocs/lf5/trouble.xml
new file mode 100644
index 0000000..a72db0c
--- /dev/null
+++ b/src/xdocs/lf5/trouble.xml
@@ -0,0 +1,307 @@
+<?xml version="1.0"?>
+<document>
+
+ <properties>
+ <author email="BMarlborough@thoughtworks.com">Brad Marlborough</author>
+ <title>LogFactor5 Users' Guide</title>
+ </properties>
+
+ <body>
+ <section name="Troubleshooting Examples">
+
+ <p><b>Q. How do I send log messages to both LogFactor5 and a rolling log file?</b>
+ </p>
+
+ <p><b>A.</b> Log4J gives you the ability to log to mulitple
+ appenders. The <i>RollingFileAppender</i> class is the
+ appender used to log messages to a series of files. The
+ following code snippet shows how to configure a
+ log4j.properties file or a standard properites file so that it
+ logs to both the LogFactor5 console and a rolling log
+ file.</p>
+
+<pre><font face="Courier New, Courier, mono"># Register both appenders
+with the root of the logger tree.
+
+log4j.rootLogger=, A1, R
+
+# A1 is set to be a LF5Appender which outputs to a swing
+# logging console.
+
+log4j.appender.A1=org.apache.log4j.lf5.LF5Appender
+
+# R is the RollingFileAppender that outputs to a rolling log
+# file called rolling_log_file.log.
+
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=rolling_log_file.log
+
+# Configure a pattern layout, the size of the file and the number
+# of backup files.
+
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+# Edited to fit.
+log4j.appender.R.layout.ConversionPattern=[slf5s.start]%d{DATE}[slf5s.DATE]%n\
+ %p[slf5s.PRIORITY]%n%x[slf5s.NDC]%n%t[slf5s.THREAD]%n\
+ %c[slf5s.CATEGORY]%n%l[slf5s.LOCATION]%n%m[slf5s.MESSAGE]%n%n
+log4j.appender.R.MaxFileSize=100KB
+log4j.appender.R.MaxBackupIndex=1</font></pre>
+
+ <p>For more information on logging to multiple appenders along
+ with a demo, please see the <a
+ href="example5.html">IntiUsingMultipleAppenders</a> example in the
+ examples folder.
+ </p>
+
+ <hr/>
+
+ <p><b>Q. What is the maximum number of log records that will be visible at any
+ one time?</b>
+ </p>
+
+ <p><b>A.</b> The logging console will only display up to 5000 LogRecords as a
+ default. When this limit has reached, the oldest record will be removed from
+ those that are displayed.</p>
+ <hr/>
+
+ <p><b>Q. Is the maximum number of records shown configurable? </b></p>
+
+ <p><b>A.</b> The maximum number of records shown is configurable
+ via a log4j properties file, or via the Configure menu item in
+ the LogFactor5 GUI. Our memory profiling has shown that with a
+ logging message of 25 words in length, and a stack trace
+ nested seven methods deep, every 1000 records displayed in the
+ logging console uses about 6 MB of memory. For this reason,
+ when you are setting the maximum number of log records to be
+ shown, it is possible to run out of memory if you are not
+ careful. The default maximum number of records is set to 5000
+ records to minimize the possibility of running out of
+ memory.</p>
+ <hr/>
+
+ <p><b>Q. Why does the command prompt hang when I close the
+ console? </b></p>
+
+ <p><b>A.</b> If you close the LogFactor5 console (as opposed to
+ exiting) you are effectively hiding the console and turning
+ off any logging to console. However, closing the console does
+ not shut down the Java virtual machine. As a result, the
+ command prompt hangs until the virtual machine is properly
+ shut down.</p>
+ <hr/>
+
+ <p><b>Q. How do I shut down the console completely including the virtual machine?
+ </b>
+ </p>
+ <p><b>A.</b> Selecting exit (as opposed to close) will shut down the LogFactor5
+ console along with the virtual machine. </p>
+ <hr/>
+
+ <p><b>Q. I have not added LogFactor5 via a configurator or the addAppender() method,
+ yet the console still pops up every time. What's happening? </b></p>
+
+ <p><b>A. </b>The example log4j.properties file that ships with
+ LogFactor5 is in your CLASSPATH, and is being loaded during
+ static initialization of the Category class. If you remove the
+ file from your CLASSPATH, or rename the file, the logging
+ console should stop loading.</p>
+ <hr/>
+
+
+ <p><b>Q. If I close the LogFactor5 logging console, but don't shut down the virtual
+ machine (i.e. use close rather than exit) does the console continue to log messages?
+ </b></p>
+
+ <p><b>A.</b> No. Once the LogFactor5 console is closed, it stops logging messages.
+ This does not effect any other appenders you may be using (i.e. rolling log
+ files).</p>
+ <hr/>
+
+ <p><b>Q. When I call the removeAppender( ) method on the Category class, the logging
+ window does not disappear. What's happening?</b></p>
+ <p><b>A. </b>The LF5Appender <b>is</b> being removed from the list of registered
+ Appenders in the Category class, and messages are no longer being sent to the
+ logging window. However, the logging window is being kept alive by the Swing
+ thread, so you will need to close the window manually in order to get rid of
+ it. </p>
+ <hr/>
+
+ <p><b>Q. How do I send log messages to LogFactor5 using log4j's SocketAppender
+ and SocketServer classes?</b></p>
+
+ <p><b>A.</b> Log4 gives you the ability to send messages to a remote location
+ over a socket for logging purposes. The org.apache.log4j.net.SocketAppender
+ and org.apache.log4j.net.SocketServer classes are the key classes used in remote
+ logging.</p>
+
+ <p>If you want to use the LF5Appender to log messages remotely,
+ you can simply register the LF5Appender in the properties file
+ being loaded by your SocketServer. The following steps give
+ you a high level description of how to do this. For more
+ information on using the SocketAppender, along with a demo,
+ please see the UsingSocketAppenders example in the examples
+ folder.</p>
+
+ <p>STEP 1: On the client side (the application producing the
+ logging messages), modify your configuration properties file
+ to write to a SocketAppender. If you add lines similar to the
+ following to your configuration file, it should do the trick:
+ </p>
+<pre>
+ log4j.rootCategory=, A1
+ log4j.appender.A1=org.apache.log4j.net.SocketAppender
+ log4j.appender.A1.RemoteHost=localhost
+ log4j.appender.A1.Port=8888
+</pre>
+
+ <p>Once you have loaded this configuration, all messages will be written to the
+ machine and port that you specify. </p>
+
+ <p>STEP 2: On the server side (where you are listening for
+ messages), you will need to run log4j's SocketServer
+ class. You should create a configuration file with
+ configuration information similar to the following: </p>
+<pre>
+ log4j.rootCategory=DEBUG,A
+ log4j.category.org.apache.log4j.net.SocketNode=DEBUG
+ log4j.appender.A=org.apache.log4j.lf5.LF5Appender
+</pre>
+
+ <p>STEP 3: Set up your CLASSPATH on both the client and server
+ to run log4j and LogFactor5. </p>
+
+ <p>STEP 4: Run the SocketServer at the command line. The command
+ line syntax for the SocketServer is as follows: </p>
+
+<pre>
+ java org.apache.log4j.net.SocketServer portNumber configurationFile\
+ configurationDirectory
+</pre>
+
+
+ <p> For example, we ran the following at the command line: java
+ org.apache.log4j.net.SocketServer 8888
+ C:\temp\socketserver.properties C:\temp
+ </p>
+
+ <p>STEP 5: Start your client, and start logging messages to the SocketAppender.</p>
+
+ <hr/>
+
+ <p><b>Q. How do I save my current configuration?</b></p>
+
+ <p><b>A. </b>LogFactor5 has a Configure menu item in the top
+ menu bar. If you choose save from this menu, it will save your
+ current configuration. If you choose reset from this menu, it
+ will delete any saved configuration information.
+ </p>
+ <hr/>
+
+ <p><b>Q. What configuration information is saved?</b></p>
+ <p><b>A. </b>If you choose Configure->Save from the LogFactor5 menu, LogFactor5
+ saves the configuration of the category explorer window. This means that the
+ next time you open LogFactor5, any channels that you have selected or de-selected
+ will remain as they were when you last exited the GUI.</p>
+ <hr/>
+
+ <p><b>Q. When I open LogFactor5, I have a bunch of old categories from another
+ application. What's going on here, and how do I get rid of these dead categories?</b>
+ </p>
+
+ <p><b>A. </b>You must have saved your configuration in the other
+ application. LogFactor5 is displaying your saved
+ configuration, as well as any new categories in the
+ application you are now running. To remove these empty
+ categories, right-click at the root of the category tree in
+ the category explorer window, and choose "Remove All
+ Empty Categories". If you want to get rid of this old
+ configuration information permanently, you should choose
+ Configure->Reset from the menu as well.</p>
+
+ <hr/>
+
+ <p><b>Q. I'm using Ant to build my project and one of my tasks
+ is to execute a series of JUnit tests. When I attempt to use
+ the LF5Appender as an appender I get the following exception
+ thrown: </b>
+ </p>
+
+<pre>
+ java.lang.NullPointerException
+ at javax.swing.ImageIcon.<init>(ImageIcon.java:134)
+ at org.apache.log4j.lf5.viewer.channelexplorer.ChannelNodeRenderer.
+ <init>(ChannelNodeRenderer.java:71)
+ ... etc.
+</pre>
+
+ <p><b>What do I need to do to fix this problem?</b></p>
+
+ <p><b>A. </b>This problem is related to the way that Ant's class
+ loader works. The solution for this problem is to fork the
+ junit task into a separate Java Virtual Machine. The
+ appropriate code to fork the VM is a follows:
+ </p>
+
+<pre>
+ <junit fork="yes">
+ ...
+ </junit>
+</pre>
+ <hr/>
+
+ <p><b>Q. When I try to open a file, I get the following error:
+ 'Error - Invalid log file format!'. What is going
+ on?</b></p>
+
+ <p><b>A. </b>LogFactor5 can read in log files created with
+ Log4J's RollingFileAppender. The format of the log file
+ <b>must</b> follow the LogFactor5 layout conventions in order
+ for LogFactor5 to open the file. For more information on
+ LogFactor5's layout conventions and how to set the conversion
+ pattern in a Log4J properties file, please see the
+ OpeningLogFiles example.</p>
+
+ <hr/>
+
+ <p><b>Q. Why can't I set my own custom date format?</b></p>
+
+ <p><b>A. </b>Log4j allows users to cutomize the date format of
+ their log records. Unfortunately LogFactor5 does not support
+ this feature. LogFactor5 uses a date manager to ensure that
+ only one date format is ever used. The reason for this is that
+ LogFactor5 can read in log files created with Log4J's
+ RollingFileAppender. However, the data in the log files is
+ text rather than objects. In order for LogFactor5 to read in
+ the log file, it must know the exact format of the data in
+ order to parse the information. This include the format of the
+ date. Any files containing invalid date formats would not be
+ able to be opened and read. As a result, users are forced to
+ use a default date format provided by Log4j ( %d{Date} ).</p>
+
+ <hr/>
+
+ <p><b>Q. Why does the LogFactor5 GUI hang when I use Tomcat
+ 1.4's reload feature to reload my application?</b></p>
+
+ <p><b>A. </b>When an application using LogFactor5 is deployed
+ using Tomcat, the GUI binds itself to the naming context of
+ the application. However, when the application is reloaded
+ using Tomcat's reload feature, the naming context is nulled
+ and a new naming context is created. Since the VM is not shut
+ down and restarted during the reload process, and there is no
+ longer a naming context to bind to, the LogFactor5 console
+ hangs. When the application is reloaded, a new LogFactor5
+ console is created while the old one is left hanging in limbo.
+ One way around this problem is to use Tomcat in conjunction
+ with JBoss to redeploy the application. JBoss also has a
+ reload feature that allows users to redeploy their application
+ without having to bounce the web/application server. The
+ difference is that JBoss has a naming context manager that
+ keeps track of an applications naming context between deploys
+ rather than nulling the context and creating a new one. As a
+ result, the LogFactor5 console will remain bound to the
+ application between each deploy. </p>
+
+ </section>
+ </body>
+</document>
diff --git a/src/xdocs/plan.xml b/src/xdocs/plan.xml
index 72a51a6..7d240c8 100644
--- a/src/xdocs/plan.xml
+++ b/src/xdocs/plan.xml
@@ -3,7 +3,7 @@
<properties>
<author email="ceki@apache.org">Ceki Gulcu</author>
- <title>Release plan for log4j 1.2</title>
+ <title>Release plan for log4j 1.3</title>
</properties>
<body>
@@ -35,10 +35,13 @@
<section name="Workplan for log4j 1.3">
- <p>With log4j 1.2 still in beta, the workplan for log4j 1.3 is
- obviously not final. It is included here to give you an idea
- of the future. The items are not listed in any particular
- order.
+ <p>The workplan for log4j 1.3 is not final. It is included here
+ to give you an idea of the future. The items are not listed in
+ any particular order. As always, there is no scheduled
+ release date. The lack of schedule suprises and disturbs some
+ people. Writing good software, like good cooking, takes
+ time. If we make you wait, it is to create a better and more
+ reliable product.
</p>
<table border="1" cellpadding="3" cellspacing="2">
@@ -234,11 +237,7 @@
<section name="Workplan for log4j 1.2">
<p>
- Here is workplan for the 1.2 release. As always, there is no
- scheduled release date. The lack of schedule suprises and
- disturbs some people. Writing good software, like good
- cooking, takes time. If we make you wait, it is to create a
- better and more reliable product.
+ Here is workplan for the 1.2 release.
</p>
<table border="1" cellpadding="3" cellspacing="2">
diff --git a/src/xdocs/stylesheets/lf5.xml b/src/xdocs/stylesheets/lf5.xml
new file mode 100644
index 0000000..f0952e7
--- /dev/null
+++ b/src/xdocs/stylesheets/lf5.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="Jakarta Site"
+ href="http://jakarta.apache.org/">
+
+ <title>Log4j project</title>
+ <logo href="lf5/images/lf5_logo.gif">LogFactor5</logo>
+ <body>
+
+ <menu name="LF5 User Guide">
+ <item name="Overview" href="/lf5/overview.html"/>
+ <item name="Features" href="/lf5/features.html"/>
+ <item name="Reading Files" href="/lf5/readingfiles.html"/>
+ <item name="Configuration" href="/lf5/configuration.html"/>
+ <item name="Library" href="/lf5/library.html"/>
+ <item name="Examples" href="/lf5/examples.html"/>
+ <item name="Troubleshoot" href="/lf5/trouble.html"/>
+ <item name="FAQ" href="/lf5/faq.html"/>
+ </menu>
+
+
+ <menu name="Log4j Project">
+ <item name="Home page" href="/index.html"/>
+ </menu>
+
+
+ </body>
+</project>
diff --git a/tests/build.xml b/tests/build.xml
index a249bdd..8ea45c8 100644
--- a/tests/build.xml
+++ b/tests/build.xml
@@ -51,9 +51,7 @@
build - compile all project files, if a certain library is missing,
then the compilation of its dependents are skipped.
- regression - Run regression ests which check large parts of log4j.
- unit - Run unit tests which check one component at a time.
- longUnit - Run long unit tests which check one component at a time.
+ regression - Run regression tests which check large parts of log4j.
runAll - run all available tests
</echo>
@@ -101,8 +99,8 @@
HierarchyThreshold, SocketServer,
XMLLayout, AsyncAppender,
OptionConverter, BoundedFIFO,
- CyclicBuffer, OR, LevelMatchFilter,
- DRFA"/>
+ CyclicBuffer, PatternParser, OR,
+ LevelMatchFilter, DRFA"/>
<!-- ================================================================= -->
<!-- Longer unit tests -->
@@ -172,7 +170,7 @@
<target name="SocketServer" depends="build">
<parallel>
<java classname="org.apache.log4j.net.ShortSocketServer" fork="yes">
- <arg value="4"/>
+ <arg value="8"/>
<arg value="input/socketServer"/>
<classpath refid="tests.classpath"/>
</java>
@@ -212,6 +210,13 @@
</junit>
</target>
+ <target name="ErrorHandler" depends="build">
+ <junit printsummary="yes" fork="yes" haltonfailure="yes">
+ <classpath refid="tests.classpath"/>
+ <formatter type="plain" usefile="false" />
+ <test name="org.apache.log4j.varia.ErrorHandlerTestCase" />
+ </junit>
+ </target>
<target name="OptionConverter" depends="build">
<junit printsummary="yes" fork="yes" haltonfailure="yes">
@@ -237,6 +242,14 @@
</junit>
</target>
+ <target name="PatternParser" depends="build">
+ <junit printsummary="yes" fork="yes" haltonfailure="yes">
+ <classpath refid="tests.classpath"/>
+ <formatter type="plain" usefile="false"/>
+ <test name="org.apache.log4j.helpers.PatternParserTestCase" />
+ </junit>
+ </target>
+
<target name="OR" depends="build">
<junit printsummary="yes" fork="yes" haltonfailure="yes">
diff --git a/tests/input/socketServer5.properties b/tests/input/socketServer5.properties
new file mode 100644
index 0000000..9772442
--- /dev/null
+++ b/tests/input/socketServer5.properties
@@ -0,0 +1,8 @@
+log4j.rootLogger=DEBUG, 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/tests/input/socketServer6.properties b/tests/input/socketServer6.properties
new file mode 100644
index 0000000..5c0742a
--- /dev/null
+++ b/tests/input/socketServer6.properties
@@ -0,0 +1,8 @@
+log4j.rootLogger=DEBUG, 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/tests/input/xml/fallback1.xml b/tests/input/xml/fallback1.xml
new file mode 100644
index 0000000..e11e95b
--- /dev/null
+++ b/tests/input/xml/fallback1.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration debug="true" 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/tests/src/java/org/apache/log4j/AsyncAppenderTestCase.java b/tests/src/java/org/apache/log4j/AsyncAppenderTestCase.java
index 7d42aca..7dafc0d 100644
--- a/tests/src/java/org/apache/log4j/AsyncAppenderTestCase.java
+++ b/tests/src/java/org/apache/log4j/AsyncAppenderTestCase.java
@@ -28,14 +28,17 @@
public void setUp() {
}
- public void tearDown() {
+ public void tearDown() {
+ LogManager.shutdown();
}
+ // this test checks whether it is possible to write to a closed AsyncAppender
public void closeTest() throws Exception {
Logger root = Logger.getRootLogger();
Layout layout = new SimpleLayout();
VectorAppender vectorAppender = new VectorAppender();
AsyncAppender asyncAppender = new AsyncAppender();
+ asyncAppender.setName("async-CloseTest");
asyncAppender.addAppender(vectorAppender);
root.addAppender(asyncAppender);
@@ -45,13 +48,60 @@
Vector v = vectorAppender.getVector();
assertEquals(v.size(), 1);
-
-
}
+ // this test checks whether appenders embedded within an AsyncAppender are also
+ // closed
+ public void test2() {
+ Logger root = Logger.getRootLogger();
+ Layout layout = new SimpleLayout();
+ VectorAppender vectorAppender = new VectorAppender();
+ AsyncAppender asyncAppender = new AsyncAppender();
+ asyncAppender.setName("async-test2");
+ asyncAppender.addAppender(vectorAppender);
+ root.addAppender(asyncAppender);
+
+ root.debug("m1");
+ asyncAppender.close();
+ root.debug("m2");
+
+ Vector v = vectorAppender.getVector();
+ assertEquals(v.size(), 1);
+ assertTrue(vectorAppender.isClosed());
+ }
+
+ // this test checks whether appenders embedded within an AsyncAppender are also
+ // closed
+ public void test3() {
+ int LEN = 200;
+ Logger root = Logger.getRootLogger();
+ Layout layout = new SimpleLayout();
+ VectorAppender vectorAppender = new VectorAppender();
+ AsyncAppender asyncAppender = new AsyncAppender();
+ asyncAppender.setName("async-test3");
+ asyncAppender.addAppender(vectorAppender);
+ root.addAppender(asyncAppender);
+
+ for(int i = 0; i < LEN; i++) {
+ root.debug("message"+i);
+ }
+
+ System.out.println("Done loop.");
+ System.out.flush();
+ asyncAppender.close();
+ root.debug("m2");
+
+ Vector v = vectorAppender.getVector();
+ assertEquals(v.size(), LEN);
+ assertTrue(vectorAppender.isClosed());
+ }
+
+
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new AsyncAppenderTestCase("closeTest"));
+ suite.addTest(new AsyncAppenderTestCase("test2"));
+ suite.addTest(new AsyncAppenderTestCase("test3"));
return suite;
}
diff --git a/tests/src/java/org/apache/log4j/VectorAppender.java b/tests/src/java/org/apache/log4j/VectorAppender.java
index 6621bc7..146b8cf 100644
--- a/tests/src/java/org/apache/log4j/VectorAppender.java
+++ b/tests/src/java/org/apache/log4j/VectorAppender.java
@@ -24,16 +24,14 @@
public Vector vector;
- public
- VectorAppender() {
+ public VectorAppender() {
vector = new Vector();
}
/**
Does nothing.
*/
- public
- void activateOptions() {
+ public void activateOptions() {
}
@@ -42,28 +40,32 @@
method.
*/
- public
- void append(LoggingEvent event) {
- System.out.println("---Vector appender called with message ["+event.getRenderedMessage()+"].");
+ public void append(LoggingEvent event) {
+ //System.out.println("---Vector appender called with message ["+event.getRenderedMessage()+"].");
+ //System.out.flush();
+ try {
+ Thread.currentThread().sleep(100);
+ } catch(Exception e) {
+ }
vector.addElement(event);
}
- public
- Vector getVector() {
+ public Vector getVector() {
return vector;
}
- public
- synchronized
- void close() {
+ public synchronized void close() {
if(this.closed)
return;
this.closed = true;
}
- public
- boolean requiresLayout() {
+ public boolean isClosed() {
+ return closed;
+ }
+
+ public boolean requiresLayout() {
return false;
}
}
diff --git a/tests/src/java/org/apache/log4j/helpers/PatternParserTestCase.java b/tests/src/java/org/apache/log4j/helpers/PatternParserTestCase.java
new file mode 100644
index 0000000..f4f3058
--- /dev/null
+++ b/tests/src/java/org/apache/log4j/helpers/PatternParserTestCase.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file. */
+
+package org.apache.log4j.helpers;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.framework.Test;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.Level;
+import org.apache.log4j.Appender;
+import org.apache.log4j.FileAppender;
+import org.apache.log4j.PatternLayout;
+import org.apache.log4j.MDC;
+
+import org.apache.log4j.util.Compare;
+
+/**
+ Test case for helpers/PatternParser.java. Tests the various
+ conversion patterns supported by PatternParser. This test
+ class tests PatternParser via the PatternLayout class which
+ uses it.
+ */
+public class PatternParserTestCase extends TestCase {
+
+ static String OUTPUT_FILE = "output/PatternParser";
+ static String WITNESS_FILE = "witness/PatternParser";
+
+ static String msgPattern = "%m%n";
+
+ Logger root;
+ Logger logger;
+
+ public PatternParserTestCase(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ root = Logger.getRootLogger();
+ root.removeAllAppenders();
+ }
+
+ public void tearDown() {
+ root.getLoggerRepository().resetConfiguration();
+ }
+
+ /**
+ Test case for MDC conversion pattern. */
+ public void mdcPattern() throws Exception {
+
+ String mdcMsgPattern1 = "%m : %X%n";
+ String mdcMsgPattern2 = "%m : %X{key1}%n";
+ String mdcMsgPattern3 = "%m : %X{key2}%n";
+ String mdcMsgPattern4 = "%m : %X{key3}%n";
+ String mdcMsgPattern5 = "%m : %X{key1},%X{key2},%X{key3}%n";
+
+ // set up appender
+ PatternLayout layout = new PatternLayout(msgPattern);
+ Appender appender = new FileAppender(layout, OUTPUT_FILE+"_mdc", false);
+
+ // set appender on root and set level to debug
+ root.addAppender(appender);
+ root.setLevel(Level.DEBUG);
+
+ // output starting message
+ root.debug("starting mdc pattern test");
+
+ layout.setConversionPattern(mdcMsgPattern1);
+ root.debug("empty mdc, no key specified in pattern");
+
+ layout.setConversionPattern(mdcMsgPattern2);
+ root.debug("empty mdc, key1 in pattern");
+
+ layout.setConversionPattern(mdcMsgPattern3);
+ root.debug("empty mdc, key2 in pattern");
+
+ layout.setConversionPattern(mdcMsgPattern4);
+ root.debug("empty mdc, key3 in pattern");
+
+ layout.setConversionPattern(mdcMsgPattern5);
+ root.debug("empty mdc, key1, key2, and key3 in pattern");
+
+ MDC.put("key1", "value1");
+ MDC.put("key2", "value2");
+
+ layout.setConversionPattern(mdcMsgPattern1);
+ root.debug("filled mdc, no key specified in pattern");
+
+ layout.setConversionPattern(mdcMsgPattern2);
+ root.debug("filled mdc, key1 in pattern");
+
+ layout.setConversionPattern(mdcMsgPattern3);
+ root.debug("filled mdc, key2 in pattern");
+
+ layout.setConversionPattern(mdcMsgPattern4);
+ root.debug("filled mdc, key3 in pattern");
+
+ layout.setConversionPattern(mdcMsgPattern5);
+ root.debug("filled mdc, key1, key2, and key3 in pattern");
+
+ MDC.remove("key1");
+ MDC.remove("key2");
+
+ layout.setConversionPattern(msgPattern);
+ root.debug("finished mdc pattern test");
+
+ assertTrue(Compare.compare(OUTPUT_FILE+"_mdc", WITNESS_FILE+"_mdc"));
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(new PatternParserTestCase("mdcPattern"));
+ return suite;
+ }
+
+}
diff --git a/tests/src/java/org/apache/log4j/net/ShortSocketServer.java b/tests/src/java/org/apache/log4j/net/ShortSocketServer.java
index 99b8d5c..33e0d56 100644
--- a/tests/src/java/org/apache/log4j/net/ShortSocketServer.java
+++ b/tests/src/java/org/apache/log4j/net/ShortSocketServer.java
@@ -15,15 +15,21 @@
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 just one connection from a client.
-
- @author Ceki Gulcu
-*/
+ * 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 {
@@ -46,6 +52,8 @@
LogLog.debug("Listening on port " + SocketServerTestCase.PORT);
ServerSocket serverSocket = new ServerSocket(SocketServerTestCase.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.");
@@ -61,7 +69,7 @@
static
- void usage(String msg) {
+ void usage(String msg) {
System.err.println(msg);
System.err.println(
"Usage: java " +ShortSocketServer.class.getName() + " totalTests configFilePrefix");
diff --git a/tests/src/java/org/apache/log4j/net/SocketServerTestCase.java b/tests/src/java/org/apache/log4j/net/SocketServerTestCase.java
index 3810ac2..d4c67cf 100644
--- a/tests/src/java/org/apache/log4j/net/SocketServerTestCase.java
+++ b/tests/src/java/org/apache/log4j/net/SocketServerTestCase.java
@@ -55,6 +55,20 @@
static String PAT4 = "^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some T4 MDC-TEST4 \\[main]\\"
+ " (root|SocketServerTestCase) - Message \\d{1,2}";
+ static String PAT5 = "^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some5 T5 MDC-TEST5 \\[main]\\"
+ + " (root|SocketServerTestCase) - Message \\d{1,2}";
+
+ static String PAT6 = "^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some6 T6 client-test6 MDC-TEST6"
+ + " \\[main]\\ (root|SocketServerTestCase) - Message \\d{1,2}";
+
+ static String PAT7 = "^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some7 T7 client-test7 MDC-TEST7"
+ + " \\[main]\\ (root|SocketServerTestCase) - Message \\d{1,2}";
+
+ // DEBUG some8 T8 shortSocketServer MDC-TEST7 [main] SocketServerTestCase - Message 1
+ static String PAT8 = "^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some8 T8 shortSocketServer"
+ + " MDC-TEST8 \\[main]\\ (root|SocketServerTestCase) - Message \\d{1,2}";
+
+
static String EXCEPTION1 = "java.lang.Exception: Just testing";
static String EXCEPTION2 = "\\s*at .*\\(.*:\\d{1,4}\\)";
@@ -72,8 +86,6 @@
public void setUp() {
System.out.println("Setting up test case.");
- socketAppender = new SocketAppender("localhost", PORT);
- rootLogger.addAppender(socketAppender);
}
public void tearDown() {
@@ -81,8 +93,15 @@
socketAppender = null;
rootLogger.removeAllAppenders();
}
-
+
+ /**
+ * The pattern on the server side: %5p %x [%t] %c %m%n
+ *
+ * We are testing NDC functionality across the wire.
+ */
public void test1() throws Exception {
+ socketAppender = new SocketAppender("localhost", PORT);
+ rootLogger.addAppender(socketAppender);
common("T1", "key1", "MDC-TEST1");
delay(1);
ControlFilter cf = new ControlFilter(new String[]{PAT1, EXCEPTION1,
@@ -93,7 +112,16 @@
assertTrue(Compare.compare(FILTERED, "witness/socketServer.1"));
}
+ /**
+ * The pattern on the server side: %5p %x [%t] %C (%F:%L) %m%n
+ *
+ * We are testing NDC across the wire. Localization is turned off by
+ * default so it is not tested here even if the conversion pattern
+ * uses localization. */
public void test2() throws Exception {
+ socketAppender = new SocketAppender("localhost", PORT);
+ rootLogger.addAppender(socketAppender);
+
common("T2", "key2", "MDC-TEST2");
delay(1);
ControlFilter cf = new ControlFilter(new String[]{PAT2, EXCEPTION1,
@@ -104,8 +132,15 @@
assertTrue(Compare.compare(FILTERED, "witness/socketServer.2"));
}
+ /**
+ * The pattern on the server side: %5p %x [%t] %C (%F:%L) %m%n
+ * meaning that we are testing NDC and locatization functionality
+ * across the wire. */
public void test3() throws Exception {
+ socketAppender = new SocketAppender("localhost", PORT);
socketAppender.setLocationInfo(true);
+ rootLogger.addAppender(socketAppender);
+
common("T3", "key3", "MDC-TEST3");
delay(1);
ControlFilter cf = new ControlFilter(new String[]{PAT3, EXCEPTION1,
@@ -116,10 +151,19 @@
assertTrue(Compare.compare(FILTERED, "witness/socketServer.3"));
}
+ /**
+ * The pattern on the server side: %5p %x %X{key1}%X{key4} [%t] %c{1} - %m%n
+ * meaning that we are testing NDC, MDC and localization functionality across
+ * the wire.
+ */
public void test4() throws Exception {
+ socketAppender = new SocketAppender("localhost", PORT);
socketAppender.setLocationInfo(true);
+ rootLogger.addAppender(socketAppender);
+
NDC.push("some");
common("T4", "key4", "MDC-TEST4");
+ NDC.pop();
delay(1);
ControlFilter cf = new ControlFilter(new String[]{PAT4, EXCEPTION1,
EXCEPTION2, EXCEPTION3});
@@ -129,6 +173,110 @@
assertTrue(Compare.compare(FILTERED, "witness/socketServer.4"));
}
+ /**
+ * The pattern on the server side: %5p %x %X{key1}%X{key5} [%t] %c{1} - %m%n
+ *
+ * The test case uses wraps an AsyncAppender around the
+ * SocketAppender. This tests was written specifically for bug
+ * report #9155.
+
+ * Prior to the bug fix the output on the server did not contain the
+ * MDC-TEST5 string because the MDC clone operation (in getMDCCopy
+ * method) operation is performed twice, once from the main thread
+ * which is correct, and a second time from the AsyncAppender's
+ * dispatch thread which is incrorrect.
+
+ */
+ public void test5() throws Exception {
+ socketAppender = new SocketAppender("localhost", PORT);
+ socketAppender.setLocationInfo(true);
+ AsyncAppender asyncAppender = new AsyncAppender();
+ asyncAppender.setLocationInfo(true);
+ asyncAppender.addAppender(socketAppender);
+ rootLogger.addAppender(asyncAppender);
+
+ NDC.push("some5");
+ common("T5", "key5", "MDC-TEST5");
+ NDC.pop();
+ delay(2);
+ ControlFilter cf = new ControlFilter(new String[]{PAT5, EXCEPTION1,
+ EXCEPTION2, EXCEPTION3});
+
+ Transformer.transform(TEMP, FILTERED, new Filter[] {cf, new LineNumberFilter()});
+ assertTrue(Compare.compare(FILTERED, "witness/socketServer.5"));
+ }
+
+ /**
+ * The pattern on the server side: %5p %x %X{hostID}${key6} [%t] %c{1} - %m%n
+ *
+ * This test checks whether client-side MDC overrides the server side.
+ * It uses an AsyncAppender encapsulating a SocketAppender
+ */
+ public void test6() throws Exception {
+ socketAppender = new SocketAppender("localhost", PORT);
+ socketAppender.setLocationInfo(true);
+ AsyncAppender asyncAppender = new AsyncAppender();
+ asyncAppender.setLocationInfo(true);
+ asyncAppender.addAppender(socketAppender);
+ rootLogger.addAppender(asyncAppender);
+
+ NDC.push("some6");
+ MDC.put("hostID", "client-test6");
+ common("T6", "key6", "MDC-TEST6");
+ NDC.pop();
+ MDC.remove("hostID");
+ delay(2);
+ ControlFilter cf = new ControlFilter(new String[]{PAT6, EXCEPTION1,
+ EXCEPTION2, EXCEPTION3});
+
+ Transformer.transform(TEMP, FILTERED, new Filter[] {cf, new LineNumberFilter()});
+ assertTrue(Compare.compare(FILTERED, "witness/socketServer.6"));
+ }
+
+ /**
+ * The pattern on the server side: %5p %x %X{hostID}${key7} [%t] %c{1} - %m%n
+ *
+ * This test checks whether client-side MDC overrides the server side.
+ */
+ public void test7() throws Exception {
+ socketAppender = new SocketAppender("localhost", PORT);
+ socketAppender.setLocationInfo(true);
+ rootLogger.addAppender(socketAppender);
+
+ NDC.push("some7");
+ MDC.put("hostID", "client-test7");
+ common("T7", "key7", "MDC-TEST7");
+ NDC.pop();
+ MDC.remove("hostID");
+ delay(2);
+ ControlFilter cf = new ControlFilter(new String[]{PAT7, EXCEPTION1,
+ EXCEPTION2, EXCEPTION3});
+
+ Transformer.transform(TEMP, FILTERED, new Filter[] {cf, new LineNumberFilter()});
+ assertTrue(Compare.compare(FILTERED, "witness/socketServer.7"));
+ }
+
+ /**
+ * The pattern on the server side: %5p %x %X{hostID}${key7} [%t] %c{1} - %m%n
+ *
+ * This test checks whether server side MDC works.
+ */
+ public void test8() throws Exception {
+ socketAppender = new SocketAppender("localhost", PORT);
+ socketAppender.setLocationInfo(true);
+ rootLogger.addAppender(socketAppender);
+
+ NDC.push("some8");
+ common("T8", "key8", "MDC-TEST8");
+ NDC.pop();
+ delay(2);
+ ControlFilter cf = new ControlFilter(new String[]{PAT8, EXCEPTION1,
+ EXCEPTION2, EXCEPTION3});
+
+ Transformer.transform(TEMP, FILTERED, new Filter[] {cf, new LineNumberFilter()});
+ assertTrue(Compare.compare(FILTERED, "witness/socketServer.8"));
+ }
+
static
void common(String dc, String key, Object o) {
int i = -1;
@@ -161,6 +309,10 @@
suite.addTest(new SocketServerTestCase("test2"));
suite.addTest(new SocketServerTestCase("test3"));
suite.addTest(new SocketServerTestCase("test4"));
+ suite.addTest(new SocketServerTestCase("test5"));
+ suite.addTest(new SocketServerTestCase("test6"));
+ suite.addTest(new SocketServerTestCase("test7"));
+ suite.addTest(new SocketServerTestCase("test8"));
return suite;
}
}
diff --git a/tests/src/java/org/apache/log4j/varia/ErrorHandlerTestCase.java b/tests/src/java/org/apache/log4j/varia/ErrorHandlerTestCase.java
new file mode 100644
index 0000000..826602c
--- /dev/null
+++ b/tests/src/java/org/apache/log4j/varia/ErrorHandlerTestCase.java
@@ -0,0 +1,109 @@
+
+package org.apache.log4j.varia;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.framework.Test;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.Level;
+import org.apache.log4j.xml.DOMConfigurator;
+import org.apache.log4j.util.Filter;
+import org.apache.log4j.util.LineNumberFilter;
+import org.apache.log4j.util.ControlFilter;
+import org.apache.log4j.util.ISO8601Filter;
+import org.apache.log4j.util.Transformer;
+import org.apache.log4j.util.Compare;
+
+public class ErrorHandlerTestCase extends TestCase {
+
+ static String TEMP_A1 = "output/temp.A1";
+ static String TEMP_A2 = "output/temp.A2";
+ static String FILTERED_A1 = "output/filtered.A1";
+ static String FILTERED_A2 = "output/filtered.A2";
+
+
+ static String EXCEPTION1 = "java.lang.Exception: Just testing";
+ static String EXCEPTION2 = "\\s*at .*\\(.*:\\d{1,4}\\)";
+ static String EXCEPTION3 = "\\s*at .*\\(Native Method\\)";
+
+ static String TEST1_1A_PAT =
+ "(DEBUG|INFO |WARN |ERROR|FATAL) \\w*\\.\\w* - Message \\d";
+
+ static String TEST1_1B_PAT = "(DEBUG|INFO |WARN |ERROR|FATAL) root - Message \\d";
+
+ static String TEST1_2_PAT = "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2},\\d{3} "+
+ "\\[main]\\ (DEBUG|INFO|WARN|ERROR|FATAL) .* - Message \\d";
+
+
+
+ Logger root;
+ Logger logger;
+
+ public ErrorHandlerTestCase(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ root = Logger.getRootLogger();
+ logger = Logger.getLogger("test");
+ }
+
+ public void tearDown() {
+ root.getLoggerRepository().resetConfiguration();
+ }
+
+ public void test1() throws Exception {
+ DOMConfigurator.configure("input/xml/fallback1.xml");
+ common();
+
+ ControlFilter cf1 = new ControlFilter(new String[]{TEST1_1A_PAT, TEST1_1B_PAT,
+ EXCEPTION1, EXCEPTION2, EXCEPTION3});
+
+ ControlFilter cf2 = new ControlFilter(new String[]{TEST1_2_PAT,
+ EXCEPTION1, EXCEPTION2, EXCEPTION3});
+
+ Transformer.transform(TEMP_A1, FILTERED_A1, new Filter[] {cf1,
+ new LineNumberFilter()});
+
+ Transformer.transform(TEMP_A2, FILTERED_A2, new Filter[] {cf2,
+ new LineNumberFilter(), new ISO8601Filter()});
+
+ assertTrue(Compare.compare(FILTERED_A1, "witness/dom.A1.1"));
+ assertTrue(Compare.compare(FILTERED_A2, "witness/dom.A2.1"));
+ }
+
+ void common() {
+ int i = -1;
+
+ logger.debug("Message " + ++i);
+ root.debug("Message " + i);
+
+ logger.info ("Message " + ++i);
+ root.info("Message " + i);
+
+ logger.warn ("Message " + ++i);
+ root.warn("Message " + i);
+
+ logger.error("Message " + ++i);
+ root.error("Message " + i);
+
+ logger.log(Level.FATAL, "Message " + ++i);
+ root.log(Level.FATAL, "Message " + i);
+
+ Exception e = new Exception("Just testing");
+ logger.debug("Message " + ++i, e);
+ root.debug("Message " + i, e);
+
+ logger.error("Message " + ++i, e);
+ root.error("Message " + i, e);
+
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(new ErrorHandlerTestCase("test1"));
+ return suite;
+ }
+
+}
diff --git a/tests/src/java/org/apache/log4j/xml/XMLLayoutTestCase.java b/tests/src/java/org/apache/log4j/xml/XMLLayoutTestCase.java
index 49c214d..5941c66 100644
--- a/tests/src/java/org/apache/log4j/xml/XMLLayoutTestCase.java
+++ b/tests/src/java/org/apache/log4j/xml/XMLLayoutTestCase.java
@@ -58,6 +58,19 @@
assertTrue(Compare.compare(FILTERED, "witness/xmlLayout.2"));
}
+ public void testCDATA() throws Exception {
+ XMLLayout xmlLayout = new XMLLayout();
+ xmlLayout.setLocationInfo(true);
+ root.addAppender(new FileAppender(xmlLayout, TEMP, false));
+
+ logger.debug("Message with embedded <![CDATA[<hello>hi</hello>]]>.");
+
+ Transformer.transform(TEMP, FILTERED, new Filter[] {new LineNumberFilter(),
+ new XMLTimestampFilter(),
+ new XMLLineAttributeFilter()});
+ assertTrue(Compare.compare(FILTERED, "witness/xmlLayout.3"));
+ }
+
void common() {
int i = -1;
@@ -84,13 +97,13 @@
logger.error("Message " + ++i, e);
root.error("Message " + i, e);
-
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new XMLLayoutTestCase("basic"));
suite.addTest(new XMLLayoutTestCase("locationInfo"));
+ suite.addTest(new XMLLayoutTestCase("testCDATA"));
return suite;
}
diff --git a/tests/witness/PatternParser_mdc b/tests/witness/PatternParser_mdc
new file mode 100644
index 0000000..6960248
--- /dev/null
+++ b/tests/witness/PatternParser_mdc
@@ -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 :
+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/tests/witness/socketServer.5 b/tests/witness/socketServer.5
new file mode 100644
index 0000000..dec6b0e
--- /dev/null
+++ b/tests/witness/socketServer.5
@@ -0,0 +1,35 @@
+DEBUG some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 1
+DEBUG some5 T5 MDC-TEST5 [main] root - Message 2
+ INFO some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 3
+ WARN some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 4
+LETHAL some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 5
+DEBUG some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 6
+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 java.lang.reflect.Method.invoke(Native Method)
+ 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)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:XXX)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:XXX)
+ERROR some5 T5 MDC-TEST5 [main] root - Message 7
+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 java.lang.reflect.Method.invoke(Native Method)
+ 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)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:XXX)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:XXX)
diff --git a/tests/witness/socketServer.6 b/tests/witness/socketServer.6
new file mode 100644
index 0000000..056383c
--- /dev/null
+++ b/tests/witness/socketServer.6
@@ -0,0 +1,35 @@
+DEBUG some6 T6 client-test6 MDC-TEST6 [main] SocketServerTestCase - Message 1
+DEBUG some6 T6 client-test6 MDC-TEST6 [main] root - Message 2
+ INFO some6 T6 client-test6 MDC-TEST6 [main] SocketServerTestCase - Message 3
+ WARN some6 T6 client-test6 MDC-TEST6 [main] SocketServerTestCase - Message 4
+LETHAL some6 T6 client-test6 MDC-TEST6 [main] SocketServerTestCase - Message 5
+DEBUG some6 T6 client-test6 MDC-TEST6 [main] SocketServerTestCase - Message 6
+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 java.lang.reflect.Method.invoke(Native Method)
+ 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)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:XXX)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:XXX)
+ERROR some6 T6 client-test6 MDC-TEST6 [main] root - Message 7
+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 java.lang.reflect.Method.invoke(Native Method)
+ 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)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:XXX)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:XXX)
diff --git a/tests/witness/socketServer.7 b/tests/witness/socketServer.7
new file mode 100644
index 0000000..1197578
--- /dev/null
+++ b/tests/witness/socketServer.7
@@ -0,0 +1,35 @@
+DEBUG some7 T7 client-test7 MDC-TEST7 [main] SocketServerTestCase - Message 1
+DEBUG some7 T7 client-test7 MDC-TEST7 [main] root - Message 2
+ INFO some7 T7 client-test7 MDC-TEST7 [main] SocketServerTestCase - Message 3
+ WARN some7 T7 client-test7 MDC-TEST7 [main] SocketServerTestCase - Message 4
+LETHAL some7 T7 client-test7 MDC-TEST7 [main] SocketServerTestCase - Message 5
+DEBUG some7 T7 client-test7 MDC-TEST7 [main] SocketServerTestCase - Message 6
+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 java.lang.reflect.Method.invoke(Native Method)
+ 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)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:XXX)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:XXX)
+ERROR some7 T7 client-test7 MDC-TEST7 [main] root - Message 7
+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 java.lang.reflect.Method.invoke(Native Method)
+ 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)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:XXX)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:XXX)
diff --git a/tests/witness/socketServer.8 b/tests/witness/socketServer.8
new file mode 100644
index 0000000..a3964fa
--- /dev/null
+++ b/tests/witness/socketServer.8
@@ -0,0 +1,35 @@
+DEBUG some8 T8 shortSocketServer MDC-TEST8 [main] SocketServerTestCase - Message 1
+DEBUG some8 T8 shortSocketServer MDC-TEST8 [main] root - Message 2
+ INFO some8 T8 shortSocketServer MDC-TEST8 [main] SocketServerTestCase - Message 3
+ WARN some8 T8 shortSocketServer MDC-TEST8 [main] SocketServerTestCase - Message 4
+LETHAL some8 T8 shortSocketServer MDC-TEST8 [main] SocketServerTestCase - Message 5
+DEBUG some8 T8 shortSocketServer MDC-TEST8 [main] SocketServerTestCase - Message 6
+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 java.lang.reflect.Method.invoke(Native Method)
+ 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)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:XXX)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:XXX)
+ERROR some8 T8 shortSocketServer MDC-TEST8 [main] root - Message 7
+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 java.lang.reflect.Method.invoke(Native Method)
+ 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)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:XXX)
+ at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:XXX)
diff --git a/tests/witness/xmlLayout.1 b/tests/witness/xmlLayout.1
index dd160c2..4c36198 100644
--- a/tests/witness/xmlLayout.1
+++ b/tests/witness/xmlLayout.1
@@ -1,48 +1,48 @@
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase$X" timestamp="XXX" level="INFO" thread="main">
+<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 category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
<log4j:message><![CDATA[Message 0]]></log4j:message>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="DEBUG" thread="main">
<log4j:message><![CDATA[Message 0]]></log4j:message>
</log4j:event>
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="INFO" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="INFO" thread="main">
<log4j:message><![CDATA[Message 1]]></log4j:message>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="INFO" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="INFO" thread="main">
<log4j:message><![CDATA[Message 1]]></log4j:message>
</log4j:event>
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="WARN" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="WARN" thread="main">
<log4j:message><![CDATA[Message 2]]></log4j:message>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="WARN" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="WARN" thread="main">
<log4j:message><![CDATA[Message 2]]></log4j:message>
</log4j:event>
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="ERROR" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="ERROR" thread="main">
<log4j:message><![CDATA[Message 3]]></log4j:message>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="ERROR" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="ERROR" thread="main">
<log4j:message><![CDATA[Message 3]]></log4j:message>
</log4j:event>
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="FATAL" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="FATAL" thread="main">
<log4j:message><![CDATA[Message 4]]></log4j:message>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="FATAL" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="FATAL" thread="main">
<log4j:message><![CDATA[Message 4]]></log4j:message>
</log4j:event>
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
<log4j:message><![CDATA[Message 5]]></log4j:message>
<log4j:throwable><![CDATA[java.lang.Exception: Just testing
at org.apache.log4j.xml.XMLLayoutTestCase.common(XMLLayoutTestCase.java:XXX)
@@ -61,7 +61,7 @@
]]></log4j:throwable>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="DEBUG" thread="main">
<log4j:message><![CDATA[Message 5]]></log4j:message>
<log4j:throwable><![CDATA[java.lang.Exception: Just testing
at org.apache.log4j.xml.XMLLayoutTestCase.common(XMLLayoutTestCase.java:XXX)
@@ -80,7 +80,7 @@
]]></log4j:throwable>
</log4j:event>
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="ERROR" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="ERROR" thread="main">
<log4j:message><![CDATA[Message 6]]></log4j:message>
<log4j:throwable><![CDATA[java.lang.Exception: Just testing
at org.apache.log4j.xml.XMLLayoutTestCase.common(XMLLayoutTestCase.java:XXX)
@@ -99,7 +99,7 @@
]]></log4j:throwable>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="ERROR" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="ERROR" thread="main">
<log4j:message><![CDATA[Message 6]]></log4j:message>
<log4j:throwable><![CDATA[java.lang.Exception: Just testing
at org.apache.log4j.xml.XMLLayoutTestCase.common(XMLLayoutTestCase.java:XXX)
diff --git a/tests/witness/xmlLayout.2 b/tests/witness/xmlLayout.2
index be20b34..e181eb5 100644
--- a/tests/witness/xmlLayout.2
+++ b/tests/witness/xmlLayout.2
@@ -1,59 +1,59 @@
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase$X" timestamp="XXX" level="INFO" thread="main">
+<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="org.apache.log4j.xml.XMLLayoutTestCase$X" method="<init>" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
<log4j:message><![CDATA[Message 0]]></log4j:message>
<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="DEBUG" thread="main">
<log4j:message><![CDATA[Message 0]]></log4j:message>
<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="INFO" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="INFO" thread="main">
<log4j:message><![CDATA[Message 1]]></log4j:message>
<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="INFO" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="INFO" thread="main">
<log4j:message><![CDATA[Message 1]]></log4j:message>
<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="WARN" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="WARN" thread="main">
<log4j:message><![CDATA[Message 2]]></log4j:message>
<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="WARN" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="WARN" thread="main">
<log4j:message><![CDATA[Message 2]]></log4j:message>
<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="ERROR" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="ERROR" thread="main">
<log4j:message><![CDATA[Message 3]]></log4j:message>
<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="ERROR" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="ERROR" thread="main">
<log4j:message><![CDATA[Message 3]]></log4j:message>
<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="FATAL" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="FATAL" thread="main">
<log4j:message><![CDATA[Message 4]]></log4j:message>
<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="FATAL" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="FATAL" thread="main">
<log4j:message><![CDATA[Message 4]]></log4j:message>
<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
<log4j:message><![CDATA[Message 5]]></log4j:message>
<log4j:throwable><![CDATA[java.lang.Exception: Just testing
at org.apache.log4j.xml.XMLLayoutTestCase.common(XMLLayoutTestCase.java:XXX)
@@ -73,7 +73,7 @@
<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="DEBUG" thread="main">
<log4j:message><![CDATA[Message 5]]></log4j:message>
<log4j:throwable><![CDATA[java.lang.Exception: Just testing
at org.apache.log4j.xml.XMLLayoutTestCase.common(XMLLayoutTestCase.java:XXX)
@@ -93,7 +93,7 @@
<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="ERROR" thread="main">
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="ERROR" thread="main">
<log4j:message><![CDATA[Message 6]]></log4j:message>
<log4j:throwable><![CDATA[java.lang.Exception: Just testing
at org.apache.log4j.xml.XMLLayoutTestCase.common(XMLLayoutTestCase.java:XXX)
@@ -113,7 +113,7 @@
<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="common" file="XMLLayoutTestCase.java" line="X"/>
</log4j:event>
-<log4j:event category="root" timestamp="XXX" level="ERROR" thread="main">
+<log4j:event logger="root" timestamp="XXX" level="ERROR" thread="main">
<log4j:message><![CDATA[Message 6]]></log4j:message>
<log4j:throwable><![CDATA[java.lang.Exception: Just testing
at org.apache.log4j.xml.XMLLayoutTestCase.common(XMLLayoutTestCase.java:XXX)
diff --git a/tests/witness/xmlLayout.3 b/tests/witness/xmlLayout.3
new file mode 100644
index 0000000..cf1c467
--- /dev/null
+++ b/tests/witness/xmlLayout.3
@@ -0,0 +1,5 @@
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[Message with embedded <![CDATA[<hello>hi</hello>]]>]]><![CDATA[.]]></log4j:message>
+<log4j:locationInfo class="org.apache.log4j.xml.XMLLayoutTestCase" method="testCDATA" file="XMLLayoutTestCase.java" line="X"/>
+</log4j:event>
+