This commit was manufactured by cvs2svn to create tag
'v1_2_10-recalled'.
git-svn-id: https://svn.apache.org/repos/asf/logging/log4j/tags/v1_2_10-recalled@311334 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..6463df2 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.
@@ -47,7 +48,7 @@
=========
The log4j distribution comes with one jar file: log4j-VERSION.jar
-under the $LOG4J_HOME/dist/lib/ directory.
+under the LOG4J_HOME/dist/lib/ directory.
This jar file contains all the class files of the log4j project,
except test cases and classes from the "examples" and
@@ -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..c5555f6 100644
--- a/build.properties.sample
+++ b/build.properties.sample
@@ -19,4 +19,16 @@
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
+
+
+
+# The templates for the creation of the web-pages are inherited
+# from the parent project.
+logging-site=../logging-site
\ No newline at end of file
diff --git a/build.xml b/build.xml
index 9bcb740..1a1a443 100644
--- a/build.xml
+++ b/build.xml
@@ -4,7 +4,7 @@
<!-- ================================================================= -->
-<!-- NOTE: all directories are relative to jakarta-log4j/ -->
+<!-- NOTE: all directories are relative to logging-log4j/ -->
<!-- the parent of build/ -->
<!-- ================================================================= -->
<project name="log4j" default="usage" basedir="." >
@@ -17,11 +17,14 @@
<!-- prefixed with "env". -->
<property environment="env"/>
- <property name="version" value="1.2"/>
+ <property name="version" value="1.2.10"/>
<!-- The base directory relative to which most targets are built -->
<property name="base" value="."/>
+
+ <property name="deprecation" value="on"/>
+
<!-- The directory where source files are stored. -->
<property name="java.source.dir" value="src/java/"/>
@@ -35,11 +38,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 +81,12 @@
<pathelement location="${jmx-extra.jar}"/>
</path>
+ <!-- Construct classpath for building the html pages-->
+ <path id="site.classpath">
+ <fileset dir="${logging-site}/lib">
+ <include name="*.jar"/>
+ </fileset>
+ </path>
<!-- ================================================================= -->
<!-- Default target -->
@@ -149,6 +161,19 @@
<echo message="JAVAMAIL is present."/>
</target>
+ <target name="slf4jCheck">
+ <available file="${java.source.dir}/org/slf4j/ULogger.java"
+ property="slf4j-present"/>
+
+ <fail unless="slf4j-present">
+ Missing src/java/org/slf4j/*.java source files.
+
+ Just run the refresh-slf4j target with the command:
+
+ ant refresh-slf4j
+ </fail>
+ </target>
+
<!-- ================================================================= -->
<!-- Initialize variables -->
<!-- NOTE: all directories are relative to jakarta-log4j/ -->
@@ -157,14 +182,23 @@
<tstamp />
</target>
+
+ <target name="refresh-slf4j">
+ <echo>Fecthing required source files from SLF4J.ORG</echo>
+ <!-- copy required SLF4J files into log4j -->
+ <ant antfile="slf4j.xml" target="refresh-slf4j"/>
+ </target>
+
<target name="build" depends="init, build.core, build.examples, build.xml,
build.javamail, build.jms, build.jmx"/>
- <target name="build.core" depends="init">
+ <target name="build.core" depends="init, slf4jCheck">
<mkdir dir="${javac.dest}" />
<javac srcdir="${java.source.dir}"
destdir="${javac.dest}"
- includes="${stem}/**/*.java, ${stem}/xml/XMLLayout.java,"
+ includes="org/slf4j/**/*.java,
+ ${stem}/**/*.java,
+ ${stem}/xml/XMLLayout.java"
excludes="misc/*, **/UnitTest*.java,
**/StressCategory.java,
**/doc-files/*,
@@ -179,6 +213,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 +234,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">
@@ -223,7 +270,7 @@
<javac deprecation="${deprecation}"
srcdir="${java.source.dir}"
destdir="${javac.dest}"
- includes="${stem}/net/JMS*.java">
+ includes="${stem}/net/JMS*.java, ${stem}/or/jms/*.java">
<classpath refid="compile.classpath"/>
</javac>
</target>
@@ -251,7 +298,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 +317,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>
@@ -300,7 +347,9 @@
</delete>
<jar jarfile="${jar.dest}/${jar.filename}" basedir="${javac.dest}"
- includes="${stem}/*.class, ${stem}/xml/log4j.dtd,
+ includes="org/slf4j/**/*.class,
+ ${stem}/*.class,
+ ${stem}/xml/log4j.dtd,
${stem}/config/*.class,
${stem}/helpers/*.class,
${stem}/spi/*.class,
@@ -308,6 +357,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 +386,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 +403,63 @@
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.">
+ bottom="Copyright 2000-2005 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/"/>
+ <link href="http://www.slf4j.org/api/"/>
<classpath refid="compile.classpath"/>
</javadoc>
</target>
+ <!-- ============================================== -->
+ <!-- Build the site files using Anakia -->
+ <!-- ============================================== -->
+ <!-- ============================================== -->
+ <!-- Build the site files using Anakia -->
+ <!-- ============================================== -->
+ <target name="prepareSite">
+ <available classname="org.apache.velocity.anakia.AnakiaTask"
+ property="AnakiaTask.present">
+ <classpath refid="site.classpath"/>
+ </available>
+ </target>
+
+ <target name="checkSite" depends="prepareSite" unless="AnakiaTask.present">
+ <echo>
+ AnakiaTask is not present! Please check to make sure that
+ velocity.jar is in your classpath.
+ </echo>
+ </target>
+
+ <target name="site" depends="checkSite" if="AnakiaTask.present">
+ <taskdef name="anakia" classname="org.apache.velocity.anakia.AnakiaTask">
+ <classpath refid="site.classpath"/>
+ </taskdef>
+
+ <mkdir dir="${docs.dest}/css"/>
+ <copy file="${logging-site}/docs/css/site.css" tofile="${docs.dest}/css/site.css"/>
+
+ <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="${logging-site}/src/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, site">
<delete verbose="true">
<fileset dir=".">
@@ -403,16 +496,17 @@
</delete>
<mkdir dir="${dist.images}" />
+
+ <mkdir dir="${dist.tmp}/logging-log4j-${version}" />
- <mkdir dir="${dist.tmp}/jakarta-log4j-${version}" />
-
- <copy todir="${dist.tmp}/jakarta-log4j-${version}">
+ <copy todir="${dist.tmp}/logging-log4j-${version}">
<fileset dir="${base}"
includes="src/java/**,
docs/**,
examples/**,
build/*,
build.xml,
+ build.properties.sample,
manifest.mf,
INSTALL,
LICENSE.txt,
@@ -423,28 +517,29 @@
**/*.bak, **/goEnv.bat,
**/Makefile, **/goEnv.bat,
docs/pub-support/*,
+ dist/classes/org/**,
src/java/org/apache/log4j/test/**/*,
**/.#*"/>
</copy>
- <fixcrlf srcdir="${dist.tmp}/jakarta-log4j-${version}"
+ <fixcrlf srcdir="${dist.tmp}/logging-log4j-${version}"
includes="build.sh" cr="remove"/>
- <fixcrlf srcdir="${dist.tmp}/jakarta-log4j-${version}"
+ <fixcrlf srcdir="${dist.tmp}/logging-log4j-${version}"
includes="build.bat" cr="add"/>
- <chmod dir="${dist.tmp}/jakarta-log4j-${version}"
+ <chmod dir="${dist.tmp}/logging-log4j-${version}"
includes="build.sh" perm="+x"/>
- <tar tarfile="${dist.images}/jakarta-log4j-${version}.tar"
+ <tar tarfile="${dist.images}/logging-log4j-${version}.tar"
basedir="${dist.tmp}"
- includes="jakarta-log4j-${version}/**" />
+ includes="logging-log4j-${version}/**" />
- <gzip src="${dist.images}/jakarta-log4j-${version}.tar"
- zipfile="${dist.images}/jakarta-log4j-${version}.tar.gz" />
+ <gzip src="${dist.images}/logging-log4j-${version}.tar"
+ zipfile="${dist.images}/logging-log4j-${version}.tar.gz" />
- <zip zipfile="${dist.images}/jakarta-log4j-${version}.zip"
+ <zip zipfile="${dist.images}/logging-log4j-${version}.zip"
basedir="${dist.tmp}"
- includes="jakarta-log4j-${version}/**" />
+ includes="logging-log4j-${version}/**" />
<delete dir="${dist.tmp}" />
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..f2a9f67 100644
--- a/docs/FAQ.html
+++ b/docs/FAQ.html
@@ -1,212 +1,407 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html> <head>
-<title>log4j FAQ</title>
-</head>
-<body bgcolor=#FFFFFF>
-
-<center>
-<h1>Frequently Asked Questions about log4j</h1>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<b>Ceki Gülcü</b> and <b>Chris Taylor</b>
-<h2>May 2002</h2>
-</center>
-<ul>
+<!-- Content Stylesheet for Site -->
-<li><p><a href=#whatIs>What is log4j?</a></p>
+
+
+
+
+<!-- start the processing -->
+ <!-- ====================================================================== -->
+ <!-- GENERATED FILE, DO NOT EDIT, EDIT THE XML FILE IN xdocs INSTEAD! -->
+ <!-- Main Page Section -->
+ <!-- ====================================================================== -->
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
-<li><p><a href=#reliable>Is log4j a reliable logging system?</a></p>
-<li><p><a href=#prerequisites>What are the prerequisites for log4j?</a></p>
-<li><p><a href=#javadoc>Is there javadoc documentation for log4j?</a></p>
-<li><p><a href=#alternatives>What other logging packages are there?</a></p>
-<li><p><a HREF=#usageExample>Is there example code for using log4j?</a></p>
-<li><p><a href=#features>What are the features of log4j?</a></p>
-<li><p><a href=#thread-safety>Is log4j thread-safe?</a></p>
-<li><p><a href=#sample>What does log output look like?</a></p>
-<li><p><a href=#logger>What are <em>Loggers</em>?</a></p>
-<li><p><a href=#behavior>How can I change log behavior at runtime?</a></p>
-<li><p><a HREF=#fastLogging>What is the fastest way of (not) logging?</a></p>
-<li><p><a HREF=#arrayDebug>What is the use of the <code>debug</code> method
-expecting a <code>String</code> array as one of its parameters?</a></p>
+ <meta name="author" value="Ceki Gulcu">
+ <meta name="email" value="cgu@apache.org">
+
+
+
+
+ <link href="./css/site.css" rel="stylesheet" type="text/css"/>
+
-<li><p><a href=#introCat>Why was the Logger class introduced and how
-do I migrate from the previous String based implementation?</a></p>
+ <title>Log4j project - Frequently Asked Questions about log4j</title>
+ </head>
-<li><p><a href=#namingLoggers>Are there any suggested ways for naming
-loggers?</a></p>
+ <body bgcolor="#ffffff" text="#000000" link="#525D76">
+ <!-- START Header table -->
+ <table class="banner" border="0">
+ <tr>
+ <td valign="top">
+ <a href="http://logging.apache.org/">
+ <img src="http://logging.apache.org/images/ls-logo.jpg" border="0"/>
+ </a>
+ </td>
+ <td align="right">
+ <a href="http://logging.apache.org/log4j/docs/">
+ <img src="./images/logo.jpg" alt="The log4j project" border="0"/>
+ </a>
+ </td>
+ </tr>
+ </table>
+ <!-- END Header table -->
-<li><p><a href=#className>How do I get the fully-qualified name of a class in
-a static block?</a></p>
-
-<li><p><a href=#customLayouts>Can the log output format be
-customized?</a></p>
-
-<li><p><a href="#options">What are the configurable options for
-<code>ForBarAppender</code>?</a></p>
-
-
-<li><p><a href=#NDC>Can the outputs of multiple client request go to
-different log files?</a></p>
-
-<li><p><a href=#rm>Logger instances seem to be create only. Why isn't
-there a method to remove logger instances?</a></p>
-
-<li><p><a href=#filterByLevel>Is it possible to direct log output
-to different appenders by level?</a></p>
-
-<li><p><a href=#many21>How do I get multiple processes to log to the
-same file?</a></p>
-
-<li><p><a href=#timestamp>If I have many process across multiple hosts
-(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="#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
-NT Event Log when I use the NTEventLogAppender?</p>
-<li><p><a href=#tax>Why should I donate my log4j extensions back to the
-project?</a></p>
-<li><p><a href=#help>What should I keep in mind when contributing code?</a></p>
-
-
-<li><p><a href=#download>Where can I find the latest distribution of log4j?</a></p>
-
-</ul>
-
-<hr>
-<p><a name=whatIs><h4 id="whatIs">What is log4j?</h4>
-
-log4j is a tool to help the programmer output log statements to a
-variety of output targets.
-
-<p>In case of problems with an application, it is helpful to enable
-logging so that the problem can be located. With log4j it is possible
-to enable logging at runtime without modifying the application binary.
-The log4j package is designed so that log statements can remain in
-<i>shipped</i> code without incurring a high performance cost. It
-follows that the speed of logging (or rather not logging) is capital.
-
-<p>At the same time, log output can be so voluminous that it quickly
-becomes overwhelming. One of the distinctive features of log4j is the
-notion of <i>hierarchical loggers</i>. Using loggers it is
-possible to selectively control which log statements are output at
-arbitrary granularity.
-
-<p>log4j is designed with two distinct goals in mind: speed and
-flexibility. There is a tight balance between these two
-requirements. I believe that log4j strikes the right balance.
-
-<a name=reliable><h4>Is log4j a reliable logging system?</h4>
-
-No. log4j is not reliable. It is a best-effort and <em>fail-stop</em>
-logging system.
-
-<p>By fail-stop, we mean that log4j will not throw unexpected
-exceptions at run-time potentially causing your application to
-crash. <b>If for any reason, log4j throws an uncaught exception,
-please send an email to the <a
-href="mailto:log4j-user@jakarta.apache.org">log4j-user@jakarta.apache.org</a>
-mailing list</b>. Uncaught exceptions are handled as serious bugs
-requiring immediate attention.
-
-
-<p>Moreover, log4j will not revert to System.out or System.err
-when its designated output stream is not opened, is not writable or
-becomes full. This avoids corrupting an otherwise working program by
-flooding the user's terminal because logging fails. However, log4j
-will output a single message to System.err indicating that logging can
-not be performed.
-
-<a name=prerequisites><h4>What are the prerequisites for log4j?</h4>
-
-<ul>
-
- <p><li>Log4j is JDK 1.1.x compatible.
+ <div class="centercol">
+ <hr noshade="" size="1"/>
+
+ <center>
+ <h2>Frequently Asked Questions about log4j</h2>
+ <h3>Ceki Gülcü, Paul Smith, Chris Taylor<br />
+ May 2002, last updated on September 15th, 2004</h3>
+ </center>
+
+
- <p><li>The DOMConfigurator is based on the DOM Level 1 API. The
- DOMConfigurator.configure(Element) method will work with any XML
- parser that will pass it a DOM tree.
+ <br/>
+ <div class="index-faqSection">
+ Section 1. <a href="#1"> Generalities</a>
+ </div>
+
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 1.1</td>
+ <td><a href="#1.1">What is log4j?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 1.2</td>
+ <td><a href="#1.2">Is log4j a reliable logging system?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 1.3</td>
+ <td><a href="#1.3">What are the prerequisites for log4j?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 1.4</td>
+ <td><a href="#1.4">What are the features of log4j?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 1.5</td>
+ <td><a href="#1.5">Is there example code for using log4j?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 1.6</td>
+ <td><a href="#1.6">What documentation should I read to learn more about
+ log4j?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 1.7</td>
+ <td><a href="#1.7">Is log4j thread-safe?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 1.8</td>
+ <td><a href="#1.8">What does log output look like?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 1.9</td>
+ <td><a href="#1.9">Why should I use log4j when JDK 1.4 already ships with a
+ logging API?</a></td>
+ </table>
+ <br/>
+ <div class="index-faqSection">
+ Section 2. <a href="#2"> Using log4j</a>
+ </div>
+
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 2.1</td>
+ <td><a href="#2.1">What are <em>Loggers</em>?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 2.2</td>
+ <td><a href="#2.2">How can I change log behavior at runtime?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 2.3</td>
+ <td><a href="#2.3">What is the fastest way of (not) logging?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 2.4</td>
+ <td><a href="#2.4"> Are there any suggested ways for naming loggers?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 2.5</td>
+ <td><a href="#2.5">How do I get the fully-qualified name of a class in a static block?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 2.6</td>
+ <td><a href="#2.6">Can the log output format be customized? </a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 2.7</td>
+ <td><a href="#2.7">What are the configurable options for <code>FooBarAppender</code>?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 2.8</td>
+ <td><a href="#2.8">What is the recommended way of migrating from
+ java.util.logging to log4j?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 2.9</td>
+ <td><a href="#2.9">Is it possible to direct log output to
+ different appenders by level? </a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 2.10</td>
+ <td><a href="#2.10">What does the Windows NT Event Viewer complain about
+ missing descriptions for my event messages when I use the
+ <code>NTEventLogAppender</code>?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 2.11</td>
+ <td><a href="#2.11">Why can't I map my logger names to the loggers that
+ appear in the NT Event Log when I use the
+ NTEventLogAppender?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 2.12</td>
+ <td><a href="#2.12">Are there suggested approaches for logging in JSP pages?</a></td>
+ </table>
+ <br/>
+ <div class="index-faqSection">
+ Section 3. <a href="#3"> Advanced questions</a>
+ </div>
+
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 3.1</td>
+ <td><a href="#3.1">Can the outputs of multiple client request go to
+ different log files?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 3.2</td>
+ <td><a href="#3.2">Logger instances seem to be create only. Why isn't
+ there a method to remove logger instances?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 3.3</td>
+ <td><a href="#3.3">How do I get multiple process to log to the same file?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 3.4</td>
+ <td><a href="#3.4">How about the timesamps of events generated by multiple
+ processes across multiple hosts (possibly across multiple
+ timezones)?
+ </a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 3.5</td>
+ <td><a href="#3.5">Why can't log4j find my properties file in a J2EE or WAR
+ application?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 3.6</td>
+ <td><a href="#3.6">Is there a way to get log4j to automatically reload a
+ configuration file if it changes?</a></td>
+ </table>
+ <br/>
+ <div class="index-faqSection">
+ Section 4. <a href="#4"> Contributing to the project</a>
+ </div>
+
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 4.1</td>
+ <td><a href="#4.1">Why should I donate my extensions to log4j back to the
+ project?
+ </a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 4.2</td>
+ <td><a href="#4.2">What should I keep in mind when contributing code?</a></td>
+ </table>
+ <table class="index-question">
+ <td nowrap="true" valign="top">Question 4.3</td>
+ <td><a href="#4.3">How can I contribute a new question/answer to this
+ document?</a></td>
+ </table>
+ <hr/>
+
+
+ <div class="faqSection">
+ <a name="1">Section 1.</a> Generalities
+ </div>
+
+ <p>This section contains general questions about log4j.</p>
- <p>The DOMConfigurator.configure(String filename) method and its
- variants require a JAXP compatible XML parser, for example <a
- href="http://xml.apache.org/">Xerces</a> or Sun's
- parser. Compiling the DOMConfigurator requires the presence of a
- JAXP parser in the classpath.
+ <div class="question">
+ <a name="1.1">1.1 What is log4j?</a>
+ </div>
+
+ <p>log4j is a tool to help the programmer output log statements to a
+ variety of output targets.
+ </p>
- <p><li>The <code>org.apache.log4j.net.SMTPAppender</code> relies
- on the <a href="http://java.sun.com/products/javamail/">JavaMail
- API</a>. It has been tested with JavaMail API version 1.2. The
- JavaMail API requires the <a
- href="http://java.sun.com/beans/glasgow/jaf.html">JavaBeans
- Activation Framework</a> package.
-
- <p><li>The <code>org.apache.log4j.net.JMSAppender</code> requires
- the presence of the JMS API as well as JNDI.
+ <p>In case of problems with an application, it is helpful to
+ enable logging so that the problem can be located. With log4j
+ it is possible to enable logging at runtime without modifying
+ the application binary. The log4j package is designed so that
+ log statements can remain in <i>shipped</i> code without
+ incurring a high performance cost. It follows that the speed
+ of logging (or rather not logging) is capital.
+ </p>
+ <p>At the same time, log output can be so voluminous that it quickly
+ becomes overwhelming. One of the distinctive features of log4j is the
+ notion of <i>hierarchical loggers</i>. Using loggers it is
+ possible to selectively control which log statements are output at
+ arbitrary granularity.
+ </p>
- <p><li>log4j test code relies on the <a
- href="http://www.junit.org">JUnit</a> testing framework.
-
-</ul>
-
-<a name=usageExample><h4>Is there example code for using log4j?</h4>
-
-<p>See the <code>examples/</code> directory.
-
-<a name=features><h4 id="">What are the features of log4j?</h4>
-
-<ul>
-
- <p><li>log4j is optimized for speed.
-
- <p><li>log4j is based on a named logger hierarchy.
+ <p>log4j is designed with two three goals in mind:
+ reliability, speed and flexibility. There is a tight balance
+ between these requirements. We believe that log4j strikes the
+ right balance.
+ </p>
- <p><li>log4j is fail-stop but not reliable.
+ <div class="question">
+ <a name="1.2">1.2 Is log4j a reliable logging system?</a>
+ </div>
+
+ <p>No. log4j is not reliable. It is a best-effort
+ <em>fail-stop</em> logging system.
+ </p>
- <p><li>log4j is thread-safe.
+ <p>By fail-stop, we mean that log4j will not throw unexpected
+ exceptions at run-time potentially causing your application to
+ crash. <b>If for any reason, log4j throws an uncaught exception,
+ please send an email to the <a href="mailto:log4j-user@logging.apache.org">log4j-user@logging.apache.org</a>
+ mailing list</b>. Uncaught exceptions are handled as serious bugs
+ requiring immediate attention.
+ </p>
- <p><li>log4j is not restricted to a predefined set of facilities.
-
- <p><li>Logging behavior can be set at runtime using a configuration
- file. Configuration files can be property files or in XML format.
+ <p>Moreover, log4j will not revert to System.out or System.err
+ when its designated output stream is not opened, is not writable or
+ becomes full. This avoids corrupting an otherwise working program by
+ flooding the user's terminal because logging fails. However, log4j
+ will output a single message to System.err indicating that logging can
+ not be performed.
+ </p>
- <p><li>log4j is designed to handle Java Exceptions from the start.
+ <div class="question">
+ <a name="1.3">1.3 What are the prerequisites for log4j?</a>
+ </div>
+
+ <ul>
+ <li><p>Log4j versions upto and including 1.2.8 are
+ compatible with JDK 1.1.x and later. Log4j version 1.3 will
+ be compatilble with JDK 1.2 and later.
+ </p></li>
+
+ <li><p>The DOMConfigurator is based on the DOM Level 1
+ API. The DOMConfigurator.configure(Element) method will work
+ with any XML parser that will pass it a DOM tree.
+ </p>
+ <p>The DOMConfigurator.configure(String filename) method and its
+ variants require a JAXP compatible XML parser, for example <a href="http://xml.apache.org/">Xerces</a> or Sun's
+ parser. Compiling the DOMConfigurator requires the presence of a
+ JAXP parser in the classpath.
+ </p>
+ </li>
+
+ <li><p>The <code>org.apache.log4j.net.SMTPAppender</code>
+ relies on the <a href="http://java.sun.com/products/javamail/">JavaMail
+ API</a>. It has been tested with JavaMail API version
+ 1.2. The JavaMail API requires the <a href="http://java.sun.com/beans/glasgow/jaf.html">JavaBeans
+ Activation Framework</a> package.
+ </p></li>
+
+ <li><p>The <code>org.apache.log4j.net.JMSAppender</code>
+ requires the presence of the JMS API as well as JNDI.
+ </p></li>
+
+ <li><p>log4j test code relies on the <a href="http://www.junit.org">JUnit</a> testing framework.
+ </p></li>
+ </ul>
- <p><li>log4j can direct its output to a file, the console, an
- <code>java.io.OutputStream</code>, <code>java.io.Writer</code>,
- a remote server using TCP, a remote Unix Syslog daemon, to a
- remote listener using JMS, to the NT EventLog or even send e-mail.
+ <div class="question">
+ <a name="1.4">1.4 What are the features of log4j?</a>
+ </div>
+
+ <ul>
- <p><li>log4j uses 5 levels, namely DEBUG, INFO, WARN, ERROR and
- FATAL.
+ <li><p>log4j is optimized for speed.</p></li>
- <p><li>The format of the log output can be easily changed by
- extending the Layout class.
+ <li><p>log4j is based on a named logger hierarchy.</p></li>
+
+ <li><p>log4j is fail-stop. However, altough it certainly
+ strives to ensure delivery, log4j does not guarantee that
+ each log statement will be delivered to its destination.
+ </p></li>
- <p><li>The target of the log output as well as the writing strategy
- can be altered by implementations of the Appender interface.
+ <li><p>log4j is thread-safe.</p></li>
- <p><li>log4j supports multiple output appenders per logger.
+ <li><p>log4j is not restricted to a predefined set of
+ facilities.</p></li>
- <p><li>log4j supports internationalization.
-
-</ul>
+ <li><p>Logging behavior can be set at runtime using a
+ configuration file. Configuration files can be property
+ files or in XML format. </p></li>
-<a name=thread-safety><h4 id="">Is log4j thread-safe?</h4>
+ <li><p>log4j is designed to handle Java Exceptions from the
+ start.</p></li>
+
+ <li><p>log4j can direct its output to a file, the console,
+ an <code>java.io.OutputStream</code>,
+ <code>java.io.Writer</code>, a remote server using TCP, a
+ remote Unix Syslog daemon, to a remote listener using JMS,
+ to the NT EventLog or even send e-mail. </p></li>
-Yes, log4j is thread-safe.
+ <li><p>log4j uses 6 levels, namely TRACE, DEBUG, INFO, WARN,
+ ERROR and FATAL. </p></li>
-<a name=sample><h4 id="">What does log output look like?</h4>
+ <li><p>The format of the log output can be easily changed by
+ extending the <code>Layout</code>
+ class. </p></li>
-The log output can be customized in many ways. Moreover, one can completely
-override the output format by implementing one's own Layout.
+ <li><p>The target of the log output as well as the writing
+ strategy can be altered by implementations of the
+ <code>Appender</code> interface. </p></li>
-<p>Here is an example output using <em>PatternLayout</em> with
-the conversion pattern <b>"%r [%t] %-5p %c{2} %x - %m%n"</b>
+ <li><p>log4j supports multiple output appenders per logger.
+ </p></li>
-<pre>
+ <li><p>log4j supports internationalization.</p></li>
+ </ul>
+
+ <div class="question">
+ <a name="1.5">1.5 Is there example code for using log4j?</a>
+ </div>
+
+ <p>See the <code>examples/</code> directory.</p>
+
+ <div class="question">
+ <a name="1.6">1.6 What documentation should I read to learn more about
+ log4j?</a>
+ </div>
+
+ <p>Make sure to read the <a href="manual.html">short
+ manual</a>. It is also recommended to you read <a href="https://www.qos.ch/shop/products/log4j/log4j-Manual.jsp">The complete
+ log4j manual</a> which is much more detailed and up to
+ date. Both documents were written by Ceki Gülcü.
+ </p>
+
+ <div class="question">
+ <a name="1.7">1.7 Is log4j thread-safe?</a>
+ </div>
+
+ <p>Yes, log4j is thread-safe. Log4j components are designed to
+ be used in heavily multithreaded systems.</p>
+
+ <div class="question">
+ <a name="1.8">1.8 What does log output look like?</a>
+ </div>
+
+
+ <p>The log output can be customized in many ways. Moreover,
+ one can completely override the output format by implementing
+ one's own Layout.
+ </p>
+
+ <p>Here is an example output using <em>PatternLayout</em> with
+ the conversion pattern <b>"%r [%t] %-5p %c{2} %x - %m%n"</b>
+ </p>
+
+ <pre class="screen_output">
176 [main] INFO examples.Sort - Populating an array of 2 elements in reverse order.
225 [main] INFO examples.SortAlgo - Entered the sort method.
262 [main] DEBUG SortAlgo.OUTER i=1 - Outer loop.
@@ -220,394 +415,739 @@
at org.log4j.examples.SortAlgo.dump(SortAlgo.java:58)
at org.log4j.examples.Sort.main(Sort.java:64)
467 [main] INFO examples.Sort - Exiting main method.
-</pre>
+ </pre>
-<p>The first field is the number of milliseconds elapsed since the
-start of the program. The second field is the thread outputting the
-log statement. The third field is the level of the log
-statement. The fourth field is the rightmost two components of the
-logger making the log request. The fifth field (just before the '-')
-is the <em>nested diagnostic context</em> (NDC). Note the nested diagnostic
-context may be empty as in the first two statements. The text after
-the '-' is the message of the statement.
+ <p>The first field is the number of milliseconds elapsed since
+ the start of the program. The second field is the thread
+ outputting the log statement. The third field is the level of
+ the log statement. The fourth field is the rightmost two
+ components of the logger making the log request. The fifth
+ field (just before the '-') is the <em>nested diagnostic
+ context</em> (NDC). Note the nested diagnostic context may be
+ empty as in the first two statements. The text after the '-'
+ is the message of the statement.
+ </p>
+
+ <div class="question">
+ <a name="1.9">1.9 Why should I use log4j when JDK 1.4 already ships with a
+ logging API?</a>
+ </div>
+
+ <p>
+ Although both APIs are conceptually similar, the log4j API is
+ significantly more flexible and offers many more features, too
+ numerous to be listed here. You will discover that the
+ additional features and flexibility turn out to be
+ indispensable in the context of a mission-critical
+ application.
+ </p>
-<a name=logger><h4 id="">What are <em>Loggers</em>?</h4>
+ <p>The open and collaborative way in which log4j is developped
+ ensures that it continues to preserve and even widen its
+ competitive edge. At some point, input from bright developpers
+ from all over the world is bound to make a difference.
+ </p>
+
+ <div class="faqSection">
+ <a name="2">Section 2.</a> Using log4j
+ </div>
+
+ <p>This section contains answers to questions encountered while
+ using log4j.</p>
+
+ <div class="question">
+ <a name="2.1">2.1 What are <em>Loggers</em>?</a>
+ </div>
+
+ <p>Lggers lie at the heart of log4j. Loggers define a hierarchy and give
+ the programmer <em>run-time</em> control on which statements are
+ printed or not.
+ </p>
+
+ <p>Loggers are assigned levels. A log statement is printed
+ depending on its level <em>and</em> its logger.
+ </p>
+
+ <p>Make sure to read the <a href="manual.html">log4j manual</a>
+ for more information.
+ </p>
+
+ <div class="question">
+ <a name="2.2">2.2 How can I change log behavior at runtime?</a>
+ </div>
+
+ <p>Log behavior can be set using configuration files which are parsed
+ at runtime. Using configuration files the programmer can define
+ loggers and set their levels.
+ </p>
+
+ <p>The <code>PropertyConfigurator</code> defines a particular format
+ of a configuration file. See also the <code>examples/Sort.java</code>
+ example and associated configuration files.
+ </p>
+
+ <p>Configuration files can be specified in XML. See
+ <code>log4j.dtd</code> and
+ <code>org.log4j.xml.DOMConfigurator</code> for more details.
+ </p>
+
+ <p>See the various Layout and Appender components for specific
+ configuration options.
+ </p>
+
+ <p>In addition to configuration files, the user may disable all
+ messages belonging to a set of levels. See next item.
+ </p>
+
+ <div class="question">
+ <a name="2.3">2.3 What is the fastest way of (not) logging?</a>
+ </div>
+
-Lggers lie at the heart of log4j. Loggers define a hierarchy and give
-the programmer <em>run-time</em> control on which statements are
-printed or not.
+ <p> For some logger <code>l</code>, writing,
+ </p>
+
+ <pre class="source">
+ l.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
+ </pre>
+
+ <p>incurs the cost of constructing the message parameter, that is
+ converting both integer <code>i</code> and <code>entry[i]</code> to a
+ String, and concatenating intermediate strings. This, regardless of
+ whether the message will be logged or not.
+ </p>
-<p>Loggers are assigned levels. A log statement is printed
-depending on its level <em>and</em> its logger.
-
-<p>Make sure to read the <a href=manual.html>log4j manual</a>
-for more information.
-
-<a name=behavior><h4 id="">How can I change log behavior at runtime?</h4>
-
-<p>Log behavior can be set using configuration files which are parsed
-at runtime. Using configuration files the programmer can define
-loggers and set their levels.
-
-<p>The <code>PropertyConfigurator</code> defines a particular format
-of a configuration file. See also the <code>examples/Sort.java</code>
-example and associated configuration files.
-
-<p>Configuration files can be specified in XML. See
-<code>log4j.dtd</code> and
-<code>org.log4j.xml.DOMConfigurator</code> for more details.
-
-<p>See the various Layout and Appender components for specific
-configuration options.
-
-<p>In addition to configuration files, the user may disable all
-messages belonging to a set of levels. See next item.
-
-<a name=fastLogging><h4>What is the fastest way of (not) logging?</h4>
-
-<p> For some logger <code>l</code>, writing, <pre>
- l.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
-</pre>
-
-<p>incurs the cost of constructing the message parameter, that is
-converting both integer <code>i</code> and <code>entry[i]</code> to a
-String, and concatenating intermediate strings. This, regardless of
-whether the message will be logged or not.
-
-<p>If you are worried about speed, then write
-<pre>
+ <p>If you are worried about speed, then write</p>
+ <pre class="source">
if(l.isDebugEnabled()) {
l.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}
-</pre>
+ </pre>
-<p>This way you will not incur the cost of parameter construction if
-debugging is disabled for logger <code>l</code>. On the other
-hand, if the logger is debug enabled, you will incur the cost of
-evaluating whether the logger is enabled or not, twice: once in
-<code>debugEnabled</code> and once in <code>debug</code>. This is an
-insignificant overhead since evaluating a logger takes less than 1%
-of the time it takes to actually log a statement.
+ <p>This way you will not incur the cost of parameter
+ construction if debugging is disabled for logger
+ <code>l</code>. On the other hand, if the logger is debug
+ enabled, you will incur the cost of evaluating whether the
+ logger is enabled or not, twice: once in
+ <code>debugEnabled</code> and once in <code>debug</code>.
+ This is an insignificant overhead since evaluating a logger
+ takes less than 1% of the time it takes to actually log a
+ statement.
+ </p>
+
+ <h3>Better alternative based on message patterns</h3>
+ <p>As of log4j version 1.3, there exists a significantly more
+ convenient alternative based on message patterns. Assuming
+ <code>entry</code> is an object, you can write:
+ </p>
-<a name=namingLoggers><h4>Are there any suggested ways for naming
-loggers?</a></h4>
+ <p class="source">
+ l.debug("The new entry is {}.", entry);
+ </p>
-<p>Yes, there are.
+ <p>After evaluting whether to log or not, and only if the
+ decision is positive, will the logger instace format the
+ message and replace the '{}' pair with the string value of
+ <code>entry</code>. In other words, the paramerized form does
+ not incur the cost of parameter construction in case the log
+ statement is disabled.
+ </p>
+
+ <p>Thus, the following two lines will yield the exact same
+ output. However, the second form will perform at least 30
+ (thirty) times faster in case of a <em>disabled</em> logging
+ statement.
+ </p>
+
+ <p class="source">
+ l.debug("The new entry is "+entry+"."); <br />
+ l.debug("The new entry is {}.", entry);
+ </p>
+
+ <p>A two argument variant is also availalble. For example, you
+ can write:
+ </p>
+ <p class="source">
+ l.debug("The new entry is {}. It replaces {}.", entry, oldEntry);
+ </p>
+
+
-<p>You can name loggers by <strong>locality</strong>. It turns out
-that instantiating a logger in each class, with the logger name
-equal to the fully-qualified name of the class, is a useful and
-straightforward approach of defining loggers. This approach has
-many benefits:
+
+ <div class="question">
+ <a name="2.4">2.4 Are there any suggested ways for naming loggers?</a>
+ </div>
+
+
-<ul>
- <li>It is very simple to implement.
+ <p>Yes, there are.</p>
- <li>It is very simple to explain to new developers.
+ <p>You can name loggers by <strong>locality</strong>. It turns out
+ that instantiating a logger in each class, with the logger name
+ equal to the fully-qualified name of the class, is a useful and
+ straightforward approach of defining loggers. This approach has
+ many benefits:
+ </p>
+
+ <ul>
+ <li>It is very simple to implement.</li>
+
+ <li>It is very simple to explain to new developers.</li>
+
+ <li>It automatically mirrors your application's own modular design.
+ </li>
+ <li>It can be further refined at will.</li>
+
+ <li>Printing the logger automatically gives information on the locality
+ of the log statement. </li>
+ </ul>
- <li>It automatically mirrors your application's own modular design.
+ <p>However, this is not the only way for naming loggers. A
+ common alternative is to name loggers by <strong>functional
+ areas</strong>. For example, the "database" logger, "RMI"
+ logger, "security" logger, or the "XML" logger.
+ </p>
- <li>It can be further refined at will.
+ <p>You may choose to name loggers by functionality and
+ subcategorize by locality, as in "DATABASE.com.foo.some.package.someClass" or
+ "DATABASE.com.foo.some.other.package.someOtherClass".
+ </p>
+
+ <p><em>You are totally free in choosing the names of your
+ loggers.</em> The log4j package merely allows you to manage your
+ names in a hierarchy. However, it is your responsibility to define
+ this hierarchy.
+ </p>
+
+ <p>Note by naming loggers by locality one tends to name things by
+ functionality, since in most cases the locality relates closely to
+ functionality.
+ </p>
- <li>Printing the logger automatically gives information on the locality
- of the log statement.
+
+ <div class="question">
+ <a name="2.5">2.5 How do I get the fully-qualified name of a class in a static block?</a>
+ </div>
+
+ <p>You can easily retrieve the fully-qualified name of a class in a
+ static block for class X, with the statement
+ <code>X.class.getName()</code>. Note that <code>X</code> is the class
+ name and not an instance. The <code>X.class</code> statement does
+ <i>not</i> create a new instance of class <code>X</code>.
+ </p>
+
+ <p>Here is the suggested usage template:</p>
-</ul>
-
-
-<p>However, this is not the only way for naming loggers. A common
-alternative is to name loggers by <strong>functional
-areas</strong>. For example, the "database" logger, "RMI" logger,
-"security" logger, or the "XML" logger.
-
-<p>You may choose to name loggers by functionality and
-subcategorize by locality, as in "DATABASE.com.foo.some.package.someClass" or
-"DATABASE.com.foo.some.other.package.someOtherClass".
-
-<p><em>You are totally free in choosing the names of your
-loggers.</em> The log4j package merely allows you to manage your
-names in a hierarchy. However, it is your responsibility to define
-this hierarchy.
-
-<p>Note by naming loggers by locality one tends to name things by
-functionality, since in most cases the locality relates closely to
-functionality.
-
-<a name=className><h4>How do I get the fully-qualified name of a class
-in a static block?</a></h4>
-
-<p>You can easily retrieve the fully-qualified name of a class in a
-static block for class X, with the statement
-<code>X.class.getName()</code>. Note that <code>X</code> is the class
-name and not an instance. The <code>X.class</code> statement does
-<i>not</i> create a new instance of class <code>X</code>.
-
-<p>Here is the suggested usage template:
-
-<font color=BLUE><pre>
+ <pre class="source">
package a.b.c;
public class Foo {
- static Logger logger = Logger.getLogger(Foo.class);
+ final static Logger logger = Logger.getLogger(Foo.class);
... other code
}
-</pre></font>
-
-<a name=customLayouts><h4>Can the log output format be customized?</h4>
-
-<p>Yes. Since release 0.7.0, you can extend the <code>Layout</code>
-class to create you own customized log format. Appenders can be
-parameterized to use the layout of your choice.
-
-<a name=NDC><h4>Can the outputs of multiple client request go to
-different log files?</h4>
-
-Many developers are confronted with the problem of distinguishing the
-log output originating from the same class but different client
-requests. They come up with ingenious mechanisms to fan out the log
-output to different files. In most cases, this is not the right
-approach.
-
-<p>It is simpler to use a nested diagnostic context (NDC). Typically,
-one would <em>NDC.push()</em> client specific information, such as the
-client's hostname, ID or any other distinguishing information when
-starting to handle the client's request. Thereafter, log output will
-automatically include the nested diagnostic context so that you can
-distinguish logs from different client requests even if they are
-output to the same file.
-
-<p>See the <code>NDC</code> and the <code>PatternLayout</code> classes
-for more information. The <code>NumberCruncher</code> example shows
-how the NDC can be used to distinguish the log output from multiple
-clients even if they share the same log file.
-
-<p>For select applications, such as virtual hosting web-servers, the
-NDC solution is not sufficient. As of version 0.9.0, log4j supports
-multiple hierarchy trees. Thus, it is possible to log to different
-targets from the same logger depending on the current context.
-
-<p><a name="#options"><h4>What are the configurable options for
-FooBarAppender?</h4>
-
-Log4j uses JavaBeans style configuration.
-
-<p>Thus, any setter method in <code>FooBarAppender</code> corresponds
-to a configurable option. For example, in <a
-href="api\org\apache\log4j\RollingFileAppender.html">RollingFileAppender</a>
-the <a
-href="api/org/apache/log4j/RollingFileAppender.html#setMaxBackupIndex(int)">setMaxBackupIndex(int
-maxBackups)</a> method corresponds to the <code>maxBackupIndex</code>
-option. The first letter of the option can be upper case, i.e.
-<code>MaxBackupIndex</code> and <code>maxBackupIndex</code> are
-equivalent but not <code>MAXBACKUPIndex</code> nor
-<code>mAXBackupIndex</code>.
-
-<p>Layouts options are also defined by their setter methods. Same goes
-for most other log4j components.
-
-<!-- ------------------------------------------------------------------ -->
-
-<p><a name=rm><h4>Logger instances seem to be create only. Why isn't
-there a method to remove logger instances?</h4>
-
-It is quite nontrivial to define the semantics of a "removed" logger
-which is still referenced by the user. Future releases <em>may</em>
-include a remove method in the Logger class.
-
-<a name=filterByLevel><h4>Is it possible to direct log output to
-different appenders by level?</h4>
-
-<p>Yes it is. Setting the <b>Threshold</b> option of any appender
-extending <a
-href="api/org/apache/log4j/AppenderSkeleton.html">AppenderSkeleton</a>,
-(most log4j appenders extend AppenderSkeleton) to filter out all log
-events with <em>lower</em> level than the value of the threshold
-option.
-
-<p>For example, setting the threshold of an appender to DEBUG also
-allow INFO, WARN, ERROR and FATAL messages to log along with DEBUG
-messages. This is usually acceptable as there is little use for DEBUG
-messages without the surrounding INFO, WARN, ERROR and FATAL
-messages. Similarly, setting the threshold of an appender to ERROR
-will filter out DEBUG, INFO and WARN messages but not ERROR or FATAL
-messages.
-
-<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>If you must filter events by exact level match, then you can
-attach a <a
-href="api/org/apache/log4j/varia/LevelMatchFilter.html">LevelMatchFilter</a>
-to any appender to filter out logging events by exact level match.
-
-
-<p><a name=many21><h4>How do I get multiple process to log to the same file?</h4></a>
-
-<p>You may have each process log to a
-<a href="api/org/apache/log4j/net/SocketAppender.html"><code>SocketAppender</code></a>.
-The receiving
-<a href="api/org/apache/log4j/net/SocketServer.html"><code>SocketServer</code></a>
-(or
-<a href="api/org/apache/log4j/net/SimpleSocketServer.html"><code>SimpleSocketServer</code></a>)
-can receive all the events and send them to a single
-log file.
-
-<p><a name=timestamp><h4>If I have many processes across multiple hosts
-(possibly across multiple timezones) logging to the same file using the
-method above, what happens to timestamps?</h4>
-
-<p>The timestamp is created when the logging event is created. That is
-so say, when the <code>debug</code>, <code>info</code>, <code>warn</code>,
-<code>error</code> or <code>fatal</code> method is invoked.
-This is unaffected by the time at which they may arrive at a remote
-socket server. Since the timestamps are stored in UTC format inside
-the event, they all appear in the same timezone as the host creating the
-logfile. Since the clocks of various machines may not be synchronized,
-this may account for time interval inconsistencies between events generated
-on different hosts.
-
-<p>While this is the intended behavior, it only recently became so due to
-a bug discovery between version 1.0.4 and 1.1b1. Versions 1.0.4 and before
-had their timestamp regenerated in the converter. In this case the timestamps
-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
-or WAR application?</h4>
-
-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
-utilize Java's class loading system. Sun changed the way classloading
-works with the release of Java 2. In Java 2, classloaders are
-arranged in a hierarchial parent-child relationship. When a child
-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
-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. ;)
-
-<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
-automatic reloading through the <CODE>configureAndWatch</CODE> APIs.
-See the API documentation for more details.
-
-<P><A NAME=nteventlogproblems><H4>What does the Windows NT Event
-Viewer complain about missing descriptions for my event messages when
-I use the NTEventLogAppender?</H4>
-
-<P>The NT Event Viewer relies on <I>message resource</I> DLLs to
-properly view an event message. The NTEventLogAppender.dll contains
-these message resources, but that DLL must be copied to
-%SYSTEMROOT%\SYSTEM32 for it to work properly.
-
-
-<P><A NAME=morenteventlogproblems><H4>Why can't I map my logger names
-to the loggers that appear in the NT Event Log when I use the
-NTEventLogAppender?</H4>
-
-<P>Unfotunately, the logger names are hardcoded within the message
-resource DLL (see previous question about NTEventLogAppender), so
-there isn't any easy way to override those dynamically... in fact, I
-don't think it's possible to do it, as you'd have to modify the DLL
-resources for every application. Since most native applications don't
-use the Logger column anyway...
-
-<p><a name=tax><h4>Why should I donate my extensions to log4j back to the
-project?</h4>
-
-Contrary to the GNU Public License (GPL) the Apache Software License
-does not make any claims over your extensions. By extensions, we mean
-totally new code that invokes existing log4j classes. <em>You are free
-to do whatever you wish with your proprietary log4j extensions.</em>
-In particular, you may choose to never release your extensions to the
-wider public.
-
-<p>We are very careful not to change the log4j client API so that
-newer log4j releases are backward compatible with previous
-versions. We are a lot less scrupulous with the internal log4j
-API. Thus, if your extension is designed to work with log4j version
-<code>n</code>, then when log4j release version <code>n+1</code> comes
-out, you will probably need to adapt your proprietary extensions to
-the new release.
-
-Thus, you will be forced to spend precious resources in order to keep
-up with log4j changes. This is commonly referred to as the
-"stupid-tax." By donating the code and making it part of the standard
-distribution, you save yourself the unnecessary maintenance work.
-
-<p>If your extensions are useful then someone will eventually write an
-extension providing the same or very similar functionality. Your
-development effort will be wasted. Unless the proprietary log4j
-extension is business critical, there is little reason for not
-donating your extensions back to the project.
-
-<a name=help><h4>What should I keep in mind when contributing
-code?</h4>
-
-<ol>
-
- <li><b>Write a test case for your contribution.</b>
-
- <p>There is nothing more irritating than finding the bugs in
- debugging (i.e. logging) code. Writing a test case takes some
- effort but is crucial for a widely used library such as
- log4j. Writing a test case will go a long way in earning you the
- respect of fellow developers. See the tests/ directory for exiting
- test cases.
-
- </li>
-
-
- <p><li>Stick to the existing indentation style even if you hate it.
-
- <p>Alternating between indentation styles makes it hard to
- understand the source code. Make it hard on yourself but easier
- on others. Log4j follows the <a
- href=http://java.sun.com/docs/codeconv/>Code Conventions for
- the JavaTM Programming Language</a>.
-
- <p><li>Make every effort to stick to the JDK 1.1 API.
-
- <p>One of the important advantages of log4j is its compatibility with
- JDK 1.1.x.
+ </pre>
- <p><li>Keep it simple, small and fast.
+ <div class="question">
+ <a name="2.6">2.6 Can the log output format be customized? </a>
+ </div>
+
+ <p>Yes, you can extend the <code>Layout</code> class to create
+ you own customized log format. Appenders can be parameterized
+ to use the layout of your choice.
+ </p>
+
+ <div class="question">
+ <a name="2.7">2.7 What are the configurable options for <code>FooBarAppender</code>?</a>
+ </div>
+
+ <p>Log4j uses JavaBeans style configuration.</p>
- <p>It's all about the application not about logging.
+ <p>Thus, any setter method in <code>FooBarAppender</code>
+ corresponds to a configurable option. For example, in <a href="api\org\apache\log4j\RollingFileAppender.html"><code>RollingFileAppender</code></a>
+ the <a href="api/org/apache/log4j/RollingFileAppender.html#setMaxBackupIndex(int)"><code>setMaxBackupIndex(int
+ maxBackups)</code></a> method corresponds to the
+ <code>maxBackupIndex</code> option. The first letter of the
+ option can be upper case, i.e. <code>MaxBackupIndex</code>
+ and <code>maxBackupIndex</code> are equivalent but not
+ <code>MAXBACKUPIndex</code> nor <code>mAXBackupIndex</code>.
+ </p>
- <p><li>Identify yourself as the contributor at the top of the
- relevant file.
-
- <p><li>Take responsibility for your code.
+ <p>Layouts options are also defined by their setter methods. The same goes
+ for most other log4j components.
+ </p>
+
+ <div class="question">
+ <a name="2.8">2.8 What is the recommended way of migrating from
+ java.util.logging to log4j?</a>
+ </div>
+
- <p>Authoring software is like parenting. It takes many
- years to raise a child.
-
- <p><li>Did I mention sticking with the indentation style?
-
- <p><li>Did I mention writing test cases?
+ <p>We suggest to just use global file search/replace. You should be able
+ to replace all the "java.util.Logger" references with
+ "org.apache.log4j.Logger", and you should be on your way.
+ </p>
-</ol>
+ <p>If you're on a Win32 platform, we recommend <a href="http://www.textpad.com/">Textpad</a>. You can use the
+ CTRL+SHIFT+O to open all *.java files from a directory including all
+ its sub-directories, and then use the search/replace function to
+ replace in all files, and then CTRL+SHIFT+S to save all. Should take
+ about 60 seconds! :)
+ </p>
+
+ <div class="question">
+ <a name="2.9">2.9 Is it possible to direct log output to
+ different appenders by level? </a>
+ </div>
+
+ <p>Yes it is. Setting the <b>Threshold</b> option of any appender
+ extending <a href="api/org/apache/log4j/AppenderSkeleton.html">AppenderSkeleton</a>,
+ (most log4j appenders extend AppenderSkeleton) to filter out all log
+ events with <em>lower</em> level than the value of the threshold
+ option.
+ </p>
-<a name=download><h4>Where can I find the latest distribution of log4j?</h4>
+ <p>For example, setting the threshold of an appender to DEBUG
+ also allow INFO, WARN, ERROR and FATAL messages to log along
+ with DEBUG messages. This is usually acceptable as there is
+ little use for DEBUG messages without the surrounding INFO,
+ WARN, ERROR and FATAL messages. Similarly, setting the
+ threshold of an appender to ERROR will filter out DEBUG, INFO
+ and WARN messages but not ERROR or FATAL messages.
+ </p>
-<p>The log4j project is hosted at <a
-href="http://jakarta.apache.org/log4j/">http://jakarta.apache.org/log4j/</a>.
-<p>
-<hr>
+ <p>This policy usually best encapsulates what the user
+ actually wants to do, as opposed to her mind-projected
+ solution.
+ </p>
+ <p>See <i>examples/sort4.lcf</i> for an example threshold
+ configuration.</p>
+
+ <p>If you must filter events by exact level match, then you can
+ attach a <a href="api/org/apache/log4j/varia/LevelMatchFilter.html">LevelMatchFilter</a>
+ to any appender to filter out logging events by exact level match.
+ </p>
+
+
+ <div class="question">
+ <a name="2.10">2.10 What does the Windows NT Event Viewer complain about
+ missing descriptions for my event messages when I use the
+ <code>NTEventLogAppender</code>?</a>
+ </div>
+
+ <p>The NT Event Viewer relies on <i>message resource</i> DLLs
+ to properly view an event message. The NTEventLogAppender.dll
+ contains these message resources, but that DLL must be copied
+ to %SYSTEMROOT%\SYSTEM32 for it to work properly.
+ </p>
+
+ <div class="question">
+ <a name="2.11">2.11 Why can't I map my logger names to the loggers that
+ appear in the NT Event Log when I use the
+ NTEventLogAppender?</a>
+ </div>
+
+
+ <p>Unfotunately, the logger names are hardcoded within the
+ message resource DLL (see previous question about
+ NTEventLogAppender), so there isn't any easy way to override
+ those dynamically... in fact, I don't think it's possible to
+ do it, as you'd have to modify the DLL resources for every
+ application. Since most native applications don't use the
+ Logger column anyway...
+ </p>
+
+ <div class="question">
+ <a name="2.12">2.12 Are there suggested approaches for logging in JSP pages?</a>
+ </div>
+
+ <p>
+ The suggested approach depends on your design requirements. If you or
+ your organization has no constraints on the use of Java in JSP pages,
+ simply use log4j normally in <code><% ... %></code> statements
+ as indicated in the Short Manual and the rest of the documentation.
+ </p>
+ <p>
+ However, if your design calls for a minimum amount of Java in your JSP
+ pages, consider using the
+ <a href="http://jakarta.apache.org/taglibs/doc/log-doc/intro.html">Log Taglib</a>
+ from the Jakarta Taglibs project. It provides logging JSP tags that invoke
+ log4j.
+ </p>
+
+ <div class="faqSection">
+ <a name="3">Section 3.</a> Advanced questions
+ </div>
+
+ <p>This section contains answers to more advanced questions about log4j.</p>
+
+ <div class="question">
+ <a name="3.1">3.1 Can the outputs of multiple client request go to
+ different log files?</a>
+ </div>
+
+
+ <p>Many developers are confronted with the problem of
+ distinguishing the log output originating from the same class
+ but different client requests. They come up with ingenious
+ mechanisms to fan out the log output to different files. In
+ most cases, this is not the right approach.
+ </p>
+
+ <p>It is simpler to use a nested diagnostic context
+ (NDC). Typically, one would <em>NDC.push()</em> client
+ specific information, such as the client's hostname, ID or any
+ other distinguishing information when starting to handle the
+ client's request. Thereafter, log output will automatically
+ include the nested diagnostic context so that you can
+ distinguish logs from different client requests even if they
+ are output to the same file.
+ </p>
+
+ <p>See the <code>NDC</code> and the <code>PatternLayout</code>
+ classes for more information. The <code>NumberCruncher</code>
+ example shows how the NDC can be used to distinguish the log
+ output from multiple clients even if they share the same log
+ file.
+ </p>
+
+ <p>For select applications, such as virtual hosting
+ web-servers, the NDC solution is not sufficient. As of version
+ 0.9.0, log4j supports multiple hierarchy trees. Thus, it is
+ possible to log to different targets from the same logger
+ depending on the current context.
+ </p>
+
+
+ <div class="question">
+ <a name="3.2">3.2 Logger instances seem to be create only. Why isn't
+ there a method to remove logger instances?</a>
+ </div>
+
+ <p>It is quite nontrivial to define the semantics of a
+ "removed" logger escecially if it is still referenced by the
+ user. Future releases <em>may</em> include a remove method in
+ the Logger class.</p>
+
+ <div class="question">
+ <a name="3.3">3.3 How do I get multiple process to log to the same file?</a>
+ </div>
+
+ <p>You may have each process log to a
+ <a href="api/org/apache/log4j/net/SocketAppender.html"><code>SocketAppender</code></a>.
+ The receiving
+ <a href="api/org/apache/log4j/net/SocketServer.html"><code>SocketServer</code></a>
+ (or
+ <a href="api/org/apache/log4j/net/SimpleSocketServer.html"><code>SimpleSocketServer</code></a>)
+ can receive all the events and send them to a single
+ log file.
+ </p>
+
+ <div class="question">
+ <a name="3.4">3.4 How about the timesamps of events generated by multiple
+ processes across multiple hosts (possibly across multiple
+ timezones)?
+ </a>
+ </div>
+
+
+ <p>The timestamp is created when the logging event is created.
+ That is so say, when the <code>debug</code>,
+ <code>info</code>, <code>warn</code>, <code>error</code> or
+ <code>fatal</code> method is invoked. Thus, the timestamp is
+ unaffected by the time at which event arrive at a remote
+ socket server.
+ </p>
+
+ <p>Timestamps are stored in UTC format inside the
+ event. Consequently, when displayed or written to a log file,
+ timestamps appear in the same timezone as the host displaying
+ or creating the logfile. Note that because the clocks of
+ various machines may not be synchronized, there may be
+ timestamp inconsistencies between events generated on
+ different hosts.
+ </p>
+
+ <div class="question">
+ <a name="3.5">3.5 Why can't log4j find my properties file in a J2EE or WAR
+ application?</a>
+ </div>
+
+
+ <p>The short answer: the log4j classes and the properties file
+ are not within the scope of the same classloader.
+ </p>
+
+ <p>The long answer (and what to do about it): J2EE or Servlet
+ containers utilize Java's class loading system. Sun changed
+ the way classloading works with the release of Java 2. In
+ Java 2, classloaders are arranged in a hierarchial
+ parent-child relationship. When a child classloader needs to
+ find a class or a resource, it first delegates the request to
+ the parent.
+ </p>
+
+ <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>
+
+ <p>So, if you're having problems, try loading the class or
+ resource yourself. If you can't find it, neither will
+ log4j. ;)
+ </p>
+
+
+ <div class="question">
+ <a name="3.6">3.6 Is there a way to get log4j to automatically reload a
+ configuration file if it changes?</a>
+ </div>
+
+ <p>Yes. Both the DOMConfigurator and the PropertyConfigurator support
+ automatic reloading through the <code>configureAndWatch</code> method.
+ See the API documentation for more details.
+ </p>
-</body> </html>
+ <p>Because the <code>configureAndWatch</code> launches a
+ separate wathdog thread, and because there is no way to stop
+ this thread in log4j 1.2, the <code>configureAndWatch</code>
+ method is unsafe for use in J2EE envrironments where
+ applications are recycled.
+ </p>
+
+
+ <div class="faqSection">
+ <a name="4">Section 4.</a> Contributing to the project
+ </div>
+
+ <p>This section includes questions about contributing to the
+ project</p>
+
+ <div class="question">
+ <a name="4.1">4.1 Why should I donate my extensions to log4j back to the
+ project?
+ </a>
+ </div>
+
+ <p>Contrary to the GNU Public License (GPL) the Apache
+ Software License does not make any claims over your
+ extensions. By extensions, we mean totally new code that
+ invokes existing log4j classes. <em>You are free to do
+ whatever you wish with your proprietary log4j extensions.</em>
+ In particular, you may choose to never release your extensions
+ to the wider public.
+ </p>
+
+ <p>We are very careful not to change the log4j client API so
+ that newer log4j releases are backward compatible with
+ previous versions. We are a lot less scrupulous with the
+ internal log4j API. Thus, if your extension is designed to
+ work with log4j version <code>n</code>, then when log4j
+ release version <code>n+1</code> comes out, you will probably
+ need to adapt your proprietary extensions to the new release.
+ </p>
+
+ <p>Thus, you will be forced to spend precious resources in
+ order to keep up with log4j changes. This is commonly referred
+ to as the "stupid-tax." By donating the code and making it
+ part of the standard distribution, you save yourself the
+ unnecessary maintenance work.
+ </p>
+
+ <p>If your extensions are useful then someone will eventually
+ write an extension providing the same or very similar
+ functionality. Your development effort will be wasted. Unless
+ the proprietary log4j extension is business critical, there is
+ little reason for not donating your extensions back to the
+ project.
+ </p>
+
+ <div class="question">
+ <a name="4.2">4.2 What should I keep in mind when contributing code?</a>
+ </div>
+
+ <ol>
+
+ <li>
+ <p>Write a test case for your contribution.</p>
+
+ <p>There is nothing more irritating than finding the bugs
+ in debugging (i.e. logging) code. Writing a test case
+ takes some effort but is crucial for a widely used library
+ such as log4j. Writing a test case will go a long way in
+ earning you the respect of fellow developers. See the
+ tests/ directory for exiting test cases.
+ </p>
+ </li>
+
+
+ <li>
+ <p>Stick to the existing indentation style even if you hate it.</p>
+
+ <p>Alternating between indentation styles makes it hard to
+ understand the source code. Make it a little harder on
+ yourself but easier on others.
+ </p>
+
+ <p>Log4j has adopted a rather conservative approach by
+ following the <a href="http://java.sun.com/docs/codeconv/">Code Conventions
+ for the JavaTM Programming Language</a>. <b>We use 2 (two)
+ spaces for indentation and no tabs.</b>
+ </p>
+ </li>
+
+ <li>
+ <p>Please do not both modify the code and change the
+ indentation in a single commit.</p>
+
+ <p>If you change the code and reformat it at the same time
+ and then commit, the commit notification message will be
+ hard to read. It will contain many diffs associated with
+ the reformatting in addition to logical changes.
+ </p>
+
+ <p>If you must reformat and change the code, then perform
+ each step separately. For example, reformat the code and
+ commit. Following that, you can change the logic and
+ commit. The two steps can be performed in the reverse
+ order just as well. You can first change the logic and
+ commit and only later reformat and commit.
+ </p>
+
+ </li>
+ <li>
+ <p>Make every effort to stick to the JDK 1.1 API.</p>
+
+ <p>One of the important advantages of log4j is its
+ compatibility with JDK 1.1.x.
+ </p>
+ </li>
+
+ <li>
+ <p>Always keep it simple, small and fast when
+ possible.</p>
+
+ <p>It's all about the application not about logging.</p>
+ </li>
+
+ <li>
+ <p>Identify yourself as a contributor at the top of the
+ relevant file.
+ </p>
+ </li>
+ <li>
+ <p>Take responsibility for your code.</p>
+
+ <p>Authoring software is very much like running a marathon. It
+ takes time and endurance.
+ </p>
+ </li>
+ <li>
+ <p>Did we mention sticking with the indentation style? </p>
+ </li>
+ <li><p>Did we mention writing test cases? </p>
+ </li>
+
+ </ol>
+
+ <div class="question">
+ <a name="4.3">4.3 How can I contribute a new question/answer to this
+ document?</a>
+ </div>
+
+ <p>Log4j uses <a href="http://jakarta.apache.org/velocity/anakia.html">velocity-anakia</a>
+ to generate its web-site, including this FAQ. We have devised
+ special macros to help us automatically generate labeled
+ question/answer pairs.
+ </p>
+
+ <p>If you are not a commiter, you can simply submit your new
+ question/answer pair to the log4j-dev@logging.apache.org
+ mailing list. The committers will take it from there.
+ </p>
+
+ <p>If you are a committer, then you must edit the
+ <em>/src/xdocs/faq.xml</em> file. The format of the file
+ should be self-evident. After you have made your changes, run
+ the command
+ </p>
+ <pre class="source">ant site</pre>
+
+ <p>After the appropriate transformation, your changes should
+ appear in the file <em>/docs/faq.html</em>.
+ </p>
+
+
+
+
+ <!-- FOOTER -->
+ <div align="center"><font color="#525D76" size="-1"><em>
+ Copyright © 1999-2005, Apache Software Foundation
+ </em></font></div>
+
+ <!-- END main table -->
+
+ <!-- LEFT SIDE NAVIGATION -->
+ <!-- ============================================================ -->
+ <div class="leftcol">
+ <div class="menu_header">Log4j Project</div>
+ <div class="menu_item"> <a href="./index.html">Introduction</a>
+ </div>
+ <div class="menu_item"> <a href="./download.html">Download</a>
+ </div>
+ <div class="menu_item"> <a href="./documentation.html">Documentation</a>
+ </div>
+ <div class="menu_item"> <a href="./contactUs.html">Contact us</a>
+ </div>
+ <div class="menu_item"> <a href="./contributors.html">Contributors</a>
+ </div>
+ <div class="menu_item"> <a href="./chainsaw.html">Chainsaw</a>
+ </div>
+ <div class="menu_item"> <a href="./history.html">History</a>
+ </div>
+ <div class="menu_header">Support</div>
+ <div class="menu_item"> <a href="http://logging.apache.org/site/binindex.cgi">Binary distributions</a>
+ </div>
+ <div class="menu_item"> <a href="http://logging.apache.org/site/cvs-repositories.html">CVS Repositories</a>
+ </div>
+ <div class="menu_item"> <a href="http://logging.apache.org/site/mailing-lists.html">Mailing Lists</a>
+ </div>
+ <div class="menu_item"> <a href="http://logging.apache.org/site/bugreport.html">Bug Reporting</a>
+ </div>
+ <div class="menu_header">Related Projects</div>
+ <div class="menu_item"> <a href="http://www.slf4j.org">SLF4J</a>
+ </div>
+ <div class="menu_header">Translations</div>
+ <div class="menu_item"> <a href="http://jakarta.apache-korea.org/log4j/index.html">Korean</a>
+ </div>
+ <div class="menu_item"> <a href="http://www.ingrid.org/jajakarta/log4j/">Japanese</a>
+ </div>
+ </div>
+
+
+ </body>
+ </html>
+<!-- end the processing -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/HISTORY b/docs/HISTORY.txt
similarity index 90%
rename from docs/HISTORY
rename to docs/HISTORY.txt
index d20fba1..620e09f 100644
--- a/docs/HISTORY
+++ b/docs/HISTORY.txt
@@ -5,7 +5,170 @@
client code.
[***] Changes requiring important modifications to existing client code.
- April, 2002
+
+ April 28th, 2005
+
+ - Release of version 1.2.10
+
+ - Added support for the SLF4J project. The Logger class now
+ implements the ULogger interface defined by the SLF4J. See
+
+ http://www.slf4j.org
+
+ for more detailed information.
+
+ - Fixed bug #34491 whereby the class o.a.log4j.or.jms.MessageRenderer
+ would not be compiled in the build.jms target. Bug reported by Andy
+ McBride.
+
+ http://issues.apache.org/bugzilla/show_bug.cgi?id=34491
+
+ November 1st, 2004
+
+ - Release of version 1.2.9
+
+ Log4j version 1.2.9, is identical to version 1.2.8, except that
+ several key methods have been deprecated in preparation for version
+ 1.3.0, the next major release of log4j. These changes are intended to
+ enforce the rule that client code should never refer to the Category
+ class directly, but use the Logger class instead. Similarly, client
+ code should not refer to the Priority class but to the Level class
+ instead.
+
+ For a more detailed discussion, refer to the document entitled
+ preparing for log4j 1.3 at:
+
+ http://www.qos.ch/logging/preparingFor13.jsp
+
+ February 19th, 2003
+
+ - Release of version 1.2.8
+
+ - Fixed bug #11570 whereby XMLAppender would throw a
+ NullPointerException if the input message was null. Many thanks to
+ David Vandegrift for reporting the bug and to Hendrik Brummermann for
+ supplying the patch. [*]
+
+ - Fixed bug #12366 whereby various versions of Xerces would not parse
+ log4j configuration scripts expressed in XML format. [*]
+
+ - Fixed bug #14827. The "removes" buffer used in the flushBuffer() method
+ of JDBCAppender is now cleared, solving the memory leak. Thanks to John
+ Landers for reporting the bug and suggesting the fix. [*]
+
+ - Fixed bug #15599. SocketAppender now honors ReconnectionDelay of 0.
+ Many thanks to Scott Schram for reporting the bug and providing the fix. [*]
+
+ October 9th, 2002
+
+ - Release of version 1.2.7
+
+ - Log4j now searches for the file log4j.xml as well as the file
+ log4j.properties during log4j initialization. [*]
+
+ 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 accessed 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/critique.html b/docs/critique.html
deleted file mode 100644
index 55c2d70..0000000
--- a/docs/critique.html
+++ /dev/null
@@ -1,294 +0,0 @@
-<HTML>
-<document>
-
-<HEAD>
-<title>JSR47 vs. log4j</title>
-</HEAD>
-
-<body>
-
-<CENTER>
-<H1>JSR47 vs. log4j</H1>
-</CENTER>
-
-<hr>
-<p>I consider it quite distasteful to criticize other people's work,
-especially in public. However, since the logging API included in JDK
-1.4 will be considered by many as the "standard", I feel compelled to
-react. I am not alone in my criticism of JSR47, Greg Davis has his own
-set of <a
-href="http://www.swzoo.org/documents/miscellaneous/jsr047/">comments</a>.
-
-<p>The JDK 1.4 logging API is a result of the <a
-href="http://jcp.org/aboutJava/communityprocess/review/jsr047/index.html">JSR47
-effort</a>, led by Graham Hamilton.
-
-<p>Before delving into the details, some historical perspective is in
-order. I am the founder of the log4j project. I participated in the
-specification of the JSR47 API, although not as an expert. In 1999, I
-was still working for IBM and could not join the experts group because
-big blue had already Chris Barlock as a member in the JSR47 experts
-group. Chris is the author of <a
-href="http://www.alphaworks.ibm.com/tech/loggingtoolkit4j">IBM's
-logging toolkit for Java</a>.
-
-<p>On the surface, his toolkit has heavily influenced the JSR47
-API. In particular, the two share the same basic components, namely
-loggers, levels, handlers and formatters. In log4j, these components
-are called categories, priorities, appenders and layouts
-respectively. Pairwise, they are identical in purpose. As such, the
-terms logger and category, level and priority, handler and appender,
-formatter and layout will be used interchangeably in the remainder of
-this document.
-
-<p>Even after a casual review it should be apparent that the log4j and
-JSR47 APIs are <em>very</em> similar. For one, they are the only
-logging APIs which are based on a named hierarchy. If you understand
-one API, then understanding the concepts of the other should be a
-breeze. There are differences however.
-
-<h2>On Parents and Children</h2>
-
-<p>In JSR47, a parent logger knows about its children but not the
-other way around. Children do not have links to their parent. For
-example, the logger named <code>"foo"</code> knows about
-<code>"foo.bar1"</code> and <code>"foo.bar2"</code>. However,
-<code>"foo.bar1"</code> has no links to its parent <code>"foo"</code>.
-
-<p>In log4j, it is exactly the other way around. A log4j category
-contains a link to its parent but a parent does not have links to its
-children.
-
-<p>At first glance, this might look like a mundane implementation
-detail but it is actually quite fundamental.
-
-<ol>
-<p><b><li>Configuration order matters</b>
-
-<p>In JSR47, when you set the level of a logger, say
-<code>wombat</code>, JSR47 traverses the tree below
-<code>wombat</code>. In other words, the levels for all the loggers
-descending from <code>wombat</code> are overwritten. This can be a
-very expensive operation for large trees. In particular, for the most
-common case where one sets the level of the root logger. However,
-performance is not the point I am trying to make.
-
-<p>In log4j, changing the priority of a category involves the change
-of a single field. Children categories dynamically inherit the
-priority of their parent by traversing the hierarchy tree upwards.
-
-<p>It follows that with JSR47 if you configure the level for logger
-"foo.bar1" before configuring the level for "foo", then the latter
-instruction will overwrite the first exactly as if the first
-instruction for configuring "foo.bar1" had never
-existed. <em>Configuration order dependence is not a show stopper but
-it is something that will bite you time and again.</em>
-
-<p>In contrast, in log4j categories can be configured in any
-order. You never have to worry about configuration order.
-
-<p><b><li>Limited inheritance</b>
-
-<p>In JSR47, a logger does not walk the hierarchy to inherit its level
-but possesses a copy of it.
-
-<p>Unfortunately, in the JSR47 API, handlers cannot be inherited
-because it would be prohibitively expensive to let each logger to
-contain a distinct Vector of all inherited handlers, especially in
-large trees.
-
-<p>To circumvent this problem by JSR47 defines global handlers. A
-logger logs to global handlers and to the handlers attached to itself
-directly. <em>It does not inherit any handlers from the
-hierarchy.</em>
-
-<p>In log4j, appenders are inherited additively from the hierarchy. A
-category will log to the appenders attached to itself as well as the
-appenders attached to its ancestors. This might not seem like much
-until the day you need handler inheritance; probably a week after you
-decide to adopt a logging API.
-
-<p>Similarly, in log4j resource bundles are inherited from the
-hierarchy. In JSR47, a resource bundle <em>must</em> be attached to
-each logger individually. There is no resource bundle inheritance in
-JSR47. In practice, this means that you have to choose between
-internationalization and the benefits of the named logger
-hierarchy. It's one or the other. This limitation is particularly
-surprising because support for internationalization is advocated as
-one of the primary advantages of the JSR47 API.
-
-</ol>
-
-<h2>Bogus Levels</h2>
-
-<p>JSR 47 defines the levels <code>ALL</code>, <code>SEVERE</code>,
-<code>WARNING</code>, <code>INFO</code>, <code>CONFIG</code>,
-<code>FINE</code>, <code>FINER</code>, <code>FINEST</code> and
-<code>OFF</code>. Experience shows that the levels <code>ALL</code>
-and <code>OFF</code> are never needed. The <code>SEVERE</code> and
-<code>CONFIG</code> levels are unique to JSR47.
-
-<p>Having three debugging levels <code>FINE</code>,
-<code>FINER</code>, <code>FINEST</code> could seem like a good
-idea. However, you will soon discover that even when by yourself, it
-is hard to decide when to use which level. It is plain impossible in
-groups.
-
-<p>Log4j in contrast has a limited but self-evident set of priorities:
-<code>FATAL</code>, <code>ERROR</code>, <code>WARN</code>,
-<code>INFO</code> and <code>DEBUG</code>.
-
-<p>Both JSR47 and log4j allow the user to extend the set of
-priorities. Log4j supports subclasses of priorities in configuration
-files as well as across the wire. JSR47 does not.
-
-<h2>Limited functionality</h2>
-
-<p>Log4j has appenders capable of logging to the console, to files, to
-Unix Syslog daemons, to Microsoft NT EventLoggers, remote servers, to
-JMS channels, automatically generate email etc. It can roll log files
-by size or date and log asynchronously.
-
-<p>JSR47 can log to the console, to files, to sockets and to a memory
-buffer.
-
-<p>Log4j has an extensible and powerful layout called the
-<code>PatternLayout</code>. JSR47 offers the much weaker
-<code>SimpleFormatter</code> as an alternative.
-
-<p>Log4j supports configuration through property files as well as XML
-documents. JSR47 currently admits only property files. Moreover, the
-language of JSR47 configuration files is very weak. In particular, you
-can only configure one instance of a given handler class. <em>This
-means that you can log to just one file at a time.</em>
-
-<h2>Other differences</h2>
-
-<p>There are many other details in which log4j differs from
-JSR47. Even if the log4j core is small, the project contains a total
-of over 30'000 lines of well-tested code. JSR47 contains about 5'000
-lines of code.
-
-<p>Log4j has been around for a number of years, enjoys the support of
-five active developers (committers) and is being used in thousands of
-projects. Our site gets over 500 downloads each and every day, and the
-numbers are on the rise. Log4j has been ported to C++ and
-Python. Companies are also offering commercial products extending
-log4j.
-
-<p>Here is a short list of opensource projects or sites that are known
-to use log4j.
-
-<ul>
-<li><a href="http://www.cryptix.org/products/sasl/">Cryptix</a>
-<li><a href="http://www.jcorporate.com/html/products/expresso/logging.html">Expresso Framework</a>
-<li><a href="http://www.free-project.org/">Free E-Democracy Project</a>
-<li><a href="http://java.freehep.org">FreeHEP</a>
-<li><a href="http://www.jboss.org">JBoss</a>
-
-<li><a href="http://www.opensymphony.com/guidelines/logging.jsp">OpenSymphony</a>
-<li><a href="http://theserverside.com">TheServerSide</a>
-<li><a href="http://jakarta.apache.org/turbine/index.html">Turbine</a>
-<li><a href="http://jakarta.apache.org/velocity/index.html">Velocity</a>
-<li><a href="http://wired2.web.cern.ch/wired2/">WIRED</a>
-
-</ul>
-
-
-<p>By the way, log4j runs fine under JDK 1.1 and above. JSR 47 will
-run under JDK 1.4 and only under JDK 1.4. Interestingly enough, no
-package shipped with JDK 1.4 is using the JSR47 API.
-
-<p>Brian R. Gilstrap has <A
-href="http://javalogging.sourceforge.net/">re-written</a> JSR47 API to
-run under JDK 1.2 and 1.3. He has also published an <a
-href="http://www.ociweb.com/jnb/archive/jnbJun2001.html">article</a>
-in JavaWorld. This is all very promising but since
-<code>java.util.logging</code> is under the <code>java.*</code>
-namespace, when running under JDK 1.3, you will systematically
-encounter:
-<pre>
-Exception in thread "main" java.lang.ExceptionInInitializerError: java.lang.SecurityException: Prohibited package name: java.util.logging
- at java.lang.ClassLoader.defineClass(ClassLoader.java:477)
- at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:111)
- at java.net.URLClassLoader.defineClass(URLClassLoader.java:248)
- at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
- at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
- at java.security.AccessController.doPrivileged(Native Method)
- at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
- at java.lang.ClassLoader.loadClass(ClassLoader.java:297)
- at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:286)
- at java.lang.ClassLoader.loadClass(ClassLoader.java:253)
- at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:313)
-</pre>
-
-<p>Jochen Hiller had observed this problem in early 2001 when he
-implemented the JSR47 API by wrapping log4j.
-
-<p>Note that any third-party implementation using the
-<code>java.*</code> or <code>javax.*</code> namespaces violates Sun's
-trademark on Java. Without explicit permission from Sun, such software
-remains under the threat of litigation.
-
-<h2>Error Handling</h2>
-
-In JSR 47 when an error occurs then either a
-<code>RunTimeException</code> is thrown to the user or (in handlers
-only) an internal field is set. In the first case, the
-<code>RunTimeException</code> will cause your application to crash. In
-the latter case, you can retrieve the last caught exception in the
-handler by querying the <code>getException</code> method of that
-handler. <em>The former is totally unacceptable while the latter is
-impractical.</em>
-
-<p>In log4j, under no circumstances are exceptions thrown at the
-user. However, all appenders have an associated
-<code>ErrorHandler</code>. This <code>ErrorHandler</code> is invoked
-by the appender whenever a handler-specific error occurs. By default,
-log4j appenders are associated with an
-<code>OnlyOnceErrorHandler</code> which emits a message on the console
-for the first error in an appender and ignoring all following errors.
-
-<p>An <code>ErrorHandler</code> can implement an arbitrary error
-handling policy. For example, after a failure to write to a database a
-<code>JDBCAppender</code> can be redirected to fall back on a
-<code>FileAppender</code>. This functionality is supported in XML
-configuration files. You do not need to change a single line of client
-code.
-
-<p>But again who cares about errors, right?
-
-<h2>Performance</h2>
-
-<p>Logging performance must be studied in three distinct cases: when
-logging is turned off, when turned on but due to priority comparison
-logic not enabled, and when actually logging. Please refer to the <a
-href="manual.html#performance">log4j manual</a> for a more detailed
-discussion of logging performance.
-
-<p>When logging is turned on, log4j will be about two to three times
-slower to decide whether a log statement is enabled or not. This is
-due to the dynamic nature of log4j which requires it to walk the
-hierarchy. To give you an idea about the figures involved, under JDK
-1.4 beta, we are talking about 90 <em>nanoseconds</em> instead of 30
-<em>nanoseconds</em> on a 800Mhz Intel processor. In other words, one
-million disabled logging requests will cost under a second in both
-environments.
-
-<p>In a shipped binary, you can turn off logging entirely and both
-APIs will perform identically. Note that if one is not careful, the
-cost of parameter construction before invoking a disabled log
-statement will overwhelm any other performance consideration.
-Regardless of the API you decide to use, logging statements should
-never be placed in tight loops, for example, before or after an
-element swap instruction in a sort algorithm.
-
-<p>In log4j, caller localization information is optional whereas in
-JSR47 it is always extracted. Since the extraction of caller
-localization is a very slow operation, in the common case where caller
-information is not needed, log4j will log the same information 4 to
-100 times faster.
-
-
-</body>
-</HTML>
diff --git a/docs/deepExtension.html b/docs/deepExtension.html
deleted file mode 100644
index 05e0eb7..0000000
--- a/docs/deepExtension.html
+++ /dev/null
@@ -1,735 +0,0 @@
-<html>
-<head>
-<title>Extending Log4J</title>
-</head>
-
-<body bgcolor="white">
-
-<center>
-<h1>Adding Conversion Characters to PatternLayout</h1>
-
- "Paul Glezen"
-
- January 2001 <br><br>
-</center>
-
-<hr>
-<h2>Abstract</h2>
-
-<p>
-This article describes a systematic way to extend the
-<a href="http://jakarta.apache.org/log4j">log4j</a> API to include
-additional attributes formatted using the
-<code><a href="../docs/api/org/apache/log4j/PatternLayout.html">PatternLayout</a></code>
-class.
-<p>
-<hr>
-<h2>Contents</h2>
-<ul>
- <li><a href="#intro">Introduction</a>
- <ul>
- <li><a href=#case>The Case Study</a>
- <li><a href=#peek>A Peek Under the Hood</a>
- </ul>
- <li><a href="#process">The Process</a>
- <ul>
- <li><a href="#LoggingEvent">Extending <code>LoggingEvent</code></a>
- <li><a href="#PatternLayout">Extending <code>PatternLayout</code></a>
- <li><a href="#PatternParser">Extending <code>PatternParser</code> and
- <code>PatternConverter</code></a>
- <li><a href="#Category">Extending <code>Category</code></a>
- <li><a href="#CategoryFactory">Extending <code>CategoryFactory</code></a>
- </ul>
- <li><a href="#usage">Usage</a>
- <ul>
- <li><a href="#configurators">Configurators</a>
- </ul>
- <li><a href="#enhancements">Further Enhancements</a>
-</ul>
-<p>
-<hr>
-<a name="intro"><h2>Introduction</h2></a>
-
-<p>
-This article assumes familiarity with the log4j
-<a href="manual.html">User Manual</a>. It builds on fundamental
-classes described in both the User Manual and the
-<a href="api/index.html" target="_top">Javadoc API</a>. To assist in illustrating the
-concepts, a simple case study will be developed along side the
-explanations. The resulting classes may be used as a template
-for your own extensions. Condensed (i.e. statements compressed,
-comments removed) snippets of the case study code
-are included in this document.
-
-<a name="case"><h3>The Case Study</h3></a>
-The case study was developed in a CORBA environment in which the
-following information for each log entry was needed. The letters in
-parenthesis represent the corresponding character to be used by the
-<code><a href="api/org/apache/log4j/PatternLayout.html">PatternLayout</a></code>
-class for formatting.
-
-<p>
-<ul>
-<li><b>Host Name (h)</b> - the IP address or hostname of the physical machine
- on which the Category was running.
-<li><b>Server Name (s)</b> - The name of the application server process. In
- this context, a <i>server</i> refers to a process that accepts requests
- rather than referring to a machine. The term <i>host</i> refers to a
- physical machine. Several servers may run on the same host.
-<li><b>Component Name (b)</b> - Rather than getting bogged down on what
- constitutes a component, let's assume for the case study that a component
- is a unit of software worth denoting in the logs.
-<li><b>Version (v)</b> - the version of the component from which the log entry
- originated.
-</ul>
-<p>
-It seems odd to use "b" for the component name. Presently
-<code><a href="api/org/apache/log4j/PatternLayout.html">PatternLayout</a></code>
-already defines both "C" and "c" for class name and category name respectively.
-
-<h3><a name="peek">A Peek Under the Hood</a></h3>
-<p>
-In principle, if the steps described below are followed closely, there is
-not a need to understand how the extended classes will be used by log4j.
-But sometimes software development can be entirely unprincipled. You may
-wish to extend log4j in a different manner than describe here or you may
-make a mistake that requires knowledge of what is really going on. (Heaven
-forbid there be a mistake in this document). In any case, it doesn't hurt
-to get an idea of what's going on.
-<p>
-The following describes a "typical" logging scenario in the un-extended log4j
-case.
-<p>
-<ol>
-<li>Application code invokes a log request on a
-<code><a href="api/org/apache/log4j/Category.html">Category</a></code>
-object. Let's say the <code>info</code> method was invoked.
-<p>
-<li>The first thing <code>info</code> does is to check if logging has
-been turned off entirely for the info level. If so, it returns
-immediately. We'll assume for this scenario that logging has not
-been turned off for the info level.
-<p>
-<li>Next <code>info</code> compares the
-<code><a href="api/org/apache/log4j/Priority.html">Priority</a></code>
-level for this category against <code>Priority.INFO</code>. Assuming
-the priority warrants logging the message, the category instantiates a
-<code><a href="api/org/apache/log4j/spi/LoggingEvent.html">LoggingEvent</a></code>
-object populated with information available for logging.
-<p>
-<li>The <code>Category</code> instance passes the <code>LoggingEvent</code>
-instance to all its
-<code><a href="api/org/apache/log4j/Appender.html">Appender</a></code>
-implementations.
-<p>
-<li>Most (but not all) <code>Appender</code> implementations should have
-an associated subclass of
-<code><a href="api/org/apache/log4j/Layout.html">Layout</a></code>.
-The <code>Layout</code> subclass is passed the <code>LoggingEvent</code>
-instance and returns the event's information formatted in a
-<code>String</code> according to the configuration of the <code>Layout</code>.
-<p>
-When the <code>Layout</code> subclass is
-<code><a href="api/org/apache/log4j/PatternLayout.html">PatternLayout</a></code>,
-the format of the event's information is determined by a character sequence
-similar to the <b>C</b> language library's <code>printf</code> routine.
-<code>PatternLayout</code> delegates the parsing of this character sequence to a
-<code><a href="api/org/apache/log4j/helpers/PatternParser.html">PatternParser</a></code>
-instance.
-<p>
-When the <code>PatternLayout</code> was constructed, it created a
-<code>PatternParser</code> to tokenize the character sequence. Upon
-recognizing a token, the <code>PatternParser</code> constructs an appropriate
-<code><a href="api/org/apache/log4j/helpers/PatternConverter.html">PatternConverter</a></code>
-subclass, passing it formatting information from the token. Often the
-<code>PatternConverter</code> subclasses are implemented as static inner
-classes of <code>PatternParser</code>. The <code>parse</code> method of
-the <code>PatternParser</code> returns a linked list of these
-<code>PatternConverter</code> subclasses.
-<p>
-<li><code>PatternLayout.format()</code> passes the <code>LoggingEvent</code>
-to each <code>PatternConverter</code> subclass in the linked list. Each link
-in the list selects a particular item from the <code>LoggingEvent</code>,
-converts this item to a <code>String</code> in the proper format and appends
-it to a <code>StringBuffer</code>.
-<p>
-<li>The <code>format</code> method returns the resulting <code>String</code>
-to the <code>Appender</code> for output.
-</ol>
-<p>
-The above discussing involved most of the classes that we must extend or
-implement.
-<p>
-<ul>
-<li><code><a href="api/org/apache/log4j/PatternLayout.html">org.apache.log4j.PatternLayout</a></code>
-<li><code><a href="api/org/apache/log4j/Category.html">org.apache.log4j.Category</a></code>
-<li><code><a href="api/org/apache/log4j/spi/LoggerFactory.html">org.apache.log4j.spi.CategoryFactory</a></code>
-<li><code><a href="api/org/apache/log4j/spi/LoggingEvent.html">org.apache.log4j.spi.LoggingEvent</a></code>
-<li><code><a href="api/org/apache/log4j/helpers/PatternParser.html">org.apache.log4j.helpers.PatternParser</a></code>
-<li><code><a href="api/org/apache/log4j/helpers/PatternConverter.html">org.apache.log4j.helpers.PatternConverter</a></code>
-</ul>
-<p>
-<hr>
-<a name="process"><h2>The Process</h2></a>
-Below are steps required to add additional attributes available
-for logging by extending log4j. This will allow you to specify
-their output formats in the same manner as those provided by the
-<code>PatternLayout</code> class. The steps are numbered for
-reference only. It makes no difference in which order they are
-followed.
-<p>
-It's helpful if you know the attributes you wish to add and a
-<code>PatternLayout</code> symbol for each one before you begin. Be
-sure to consult the <code>PatternLayout</code> documentation to ensure
-the symbols you select are not already in use.
-<p>
-Before we dig in, I should give the standard lecture on comments.
-If the log4j library were not well documented, it would be useless
-to everyone but the log4j creators; likewise with your extensions.
-Much like eating vegetables and saving the environment, we all agree
-commenting code properly should be done. Yet it is often sacrificed
-for more immediate pleasures. We all write code faster without
-comments; especially those pesky Javadoc comments. But the reality
-is that the utility of undocumented code fades exponentially with time.
-<p>
-Since the log4j product comes with Javadoc comments together with
-the documentation it produces, it makes sense to include Javadoc
-comments in your extensions. By their very nature, logging tools
-are strong candidates for reuse. They can only be independently
-re-used if they are supported by strong documentation component.
-<p>
-This all having been said, I have elected to remove most comments from
-examples in the interest of space rather than including them to serve
-as a nagging reminder. The reader is referred to the case study source
-code files for a Javadoc version and a
-<a href="http://java.sun.com/javadoc">Javadoc website</a>
-for more information on Javadoc conventions.
-
-<a name="LoggingEvent"><h3>1. Extending <code>LoggingEvent</code></h3></a>
-
-Extending the <code>LoggingEvent</code> class should be one of the
-trivial steps. All that is needed in the extension is the addition
-of public data members representing the new attributes and a new
-constructor to populate them.
-<p>
-<table border=1>
-<tr><td>
-<pre>
-import org.apache.log4j.Category;
-import org.apache.log4j.Priority;
-import org.apache.log4j.spi.LoggingEvent;
-
-public class AppServerLoggingEvent extends LoggingEvent
- implements java.io.Serializable
-{
- public String hostname;
- public String component;
- public String server;
- public String version;
-
- public AppServerLoggingEvent( String fqnOfCategoryClass,
- AppServerCategory category,
- Priority priority,
- Object message,
- Throwable throwable)
- {
- super( fqnOfCategoryClass,
- category,
- priority,
- message,
- throwable );
-
- hostname = category.getHostname();
- component = category.getComponent();
- server = category.getServer();
- version = category.getVersion();
- }
-}
-</pre>
-</table>
-<p>
-The constructor demonstrates that in most cases, the <code>Category</code>
-subclass will contain most of the information necessary to populate
-the attributes of the <code>LoggingEvent</code> subclass. Extensions
-to <code>LoggingEvent</code> seem no more than a collection of strings
-with a constructor. Most of the work is done by the super class.
-
-<a name="PatternLayout"><h3>2. Extending <code>PatternLayout</code></h3></a>
-
-Extending the <code>PatternLayout</code> class should be another
-simple matter. The extension to <code>PatternLayout</code> should
-differ from its parent only in the creation of a
-<code>PatternParser</code> instance. The extended
-<code>PatternLayout</code> should create an extended
-<code>PatternParser</code> class. Fortunately, this task in
-<code>PatternLayout</code> is encapsulated within a single method.
-<p>
-<table border=1> <tr><td>
-<pre>
-import org.apache.log4j.PatternParser;
-import org.apache.log4j.PatternLayout;
-
-public class AppServerPatternLayout extends PatternLayout
-{
- public AppServerPatternLayout()
- {
- this(DEFAULT_CONVERSION_PATTERN);
- }
-
- public MyPatternLayout(String pattern)
- {
- super(pattern);
- }
-
- public PatternParser createPatternParser(String pattern)
- {
- PatternParser result;
- if ( pattern == null )
- result = new AppserverPatternParser( DEFAULT_CONVERSION_PATTERN );
- else
- result = new AppServerPatternParser ( pattern );
-
- return result;
- }
-}
-</pre>
-</table>
-
-<a name="PatternParser"><h3>3. Extend <code>PatternParser</code> and <code>PatternConverter</code></h3></a>
-
-Recall from our <a href="#peek">peek under the hood</a> that the
-<code>PatternParser</code> does much of its work in its
-<code>parse</code> method. The <code>PatternLayout</code> object
-instantiates a <code>PatternParser</code> object by passing it
-the pattern string. The PatternLayout then invokes the
-<code>parse</code> method of <code>PatternParser</code> to produce
-a linked list of <code>PatternConverter</code> subclass instances.
-It is this linked list of converters that is used to convert an
-event instance into a string used by appenders.
-<p>
-Our job will be to subclass <code>PatternParser</code> to properly
-interpret formatting characters we wish to add. Fortunately,
-<code>PatternParser</code> has been designed so that only the one
-step in the parsing process differing for each formatting character
-has to be overridden. The grunt work of parsing is still performed
-by the <code>PatternParser.parse()</code> method. Only the
-<code>PatternParser.finalizeConverter</code> method has to be
-overridden. This is the method that decides which
-<code>PatternConverter</code> to create based on a formatting
-character.
-<p>
-The extension to <code>PatternParser</code>,
-<code>AppServerPatternParser</code>, is similar to its super class.
-It uses
-<ul>
-<li>constants to identify the various formats
-<li>a converter defined as private static inner-classes of
- <code>AppServerPatternParser</code>.
-<li>a <code>finalizeConverter</code> method which instantiates
- the appropriate converter for a given format character.
-</ul>
-<p>
-<code>AppServerPatternParser</code> differs principally by
-dedicating a separate converter type for each logging
-attribute to be formatted.
-Rather than placing switch logic in the converter, like its
-parent class, each converter only converts one format character.
-This means the decision of which converter subclass
-to instantiate is made at layout instantiation time rather
-than in a switch statement at logging time.
-<p>
-It also differs in that the format constants are characters
-rather than integers.
-<p>
-<table border=1>
-<tr><td>
-<pre>
-import org.apache.log4j.*;
-import org.apache.log4j.helpers.FormattingInfo;
-import org.apache.log4j.helpers.PatternConverter;
-import org.apache.log4j.helpers.PatternParser;
-import org.apache.log4j.spi.LoggingEvent;
-
-public class AppServerPatternParser extends PatternParser
-{
- static final char HOSTNAME_CHAR = 'h';
- static final char SERVER_CHAR = 's';
- static final char COMPONENT_CHAR = 'b';
- static final char VERSION_CHAR = 'v';
-
- public AppServerPatternParser(String pattern)
- {
- super(pattern);
- }
-
- public void finalizeConverter(char formatChar)
- {
- PatternConverter pc = null;
- switch( formatChar )
- {
- case HOSTNAME_CHAR:
- pc = new HostnamePatternConverter( formattingInfo );
- currentLiteral.setLength(0);
- addConverter( pc );
- break;
- case SERVER_CHAR:
- pc = new ServerPatternConverter( formattingInfo );
- currentLiteral.setLength(0);
- addConverter( pc );
- break;
- case COMPONENT_CHAR:
- pc = new ComponentPatternConverter( formattingInfo );
- currentLiteral.setLength(0);
- addConverter( pc );
- break;
- case VERSION_CHAR:
- pc = new VersionPatternConverter( formattingInfo );
- currentLiteral.setLength(0);
- addConverter( pc );
- break;
- default:
- super.finalizeConverter( formatChar );
- }
- }
-
- private static abstract class AppServerPatternConverter extends PatternConverter
- {
- AppServerPatternConverter(FormattingInfo formattingInfo)
- {
- super(formattingInfo);
- }
-
- public String convert(LoggingEvent event)
- {
- String result = null;
- AppServerLoggingEvent appEvent = null;
-
- if ( event instanceof AppServerLoggingEvent )
- {
- appEvent = (AppServerLoggingEvent) event;
- result = convert( appEvent );
- }
- return result;
- }
-
- public abstract String convert( AppServerLoggingEvent event );
- }
-
- private static class HostnamePatternConverter extends AppServerPatternConverter
- {
- HostnamePatternConverter( FormattingInfo formatInfo )
- { super( formatInfo ); }
-
- public String convert( AppServerLoggingEvent event )
- { return event.hostname; }
- }
-
- private static class ServerPatternConverter extends AppServerPatternConverter
- {
- ServerPatternConverter( FormattingInfo formatInfo )
- { super( formatInfo ); }
-
- public String convert( AppServerLoggingEvent event )
- { return event.server; }
- }
-
- private static class ComponentPatternConverter extends AppServerPatternConverter
- {
- ComponentPatternConverter( FormattingInfo formatInfo )
- { super( formatInfo ); }
-
- public String convert( AppServerLoggingEvent event )
- { return event.component; }
- }
-
- private static class VersionPatternConverter extends AppServerPatternConverter
- {
- VersionPatternConverter( FormattingInfo formatInfo )
- { super( formatInfo ); }
-
- public String convert( AppServerLoggingEvent event )
- { return event.version; }
- }
-}
-</pre>
-</table>
-<p>
-<a name="Category"><h3>4. Extending <code>Category</code></h3></a>
-Extending <code>Category</code> and its factory will be more straight
-forward than extending <code>PatternParser</code> and the converters.
-The following tasks are involved in overridding
-<code>Category</code> for our purposes.
-<p>
-<ul>
-<li>Add fields corresponding to the new attributes with their
- corresponding getters and setters.
-<p>
-<li>Override the constructor to accept or acquire information
- about new attributes.
-<p>
-<li>Override the <code>forcedLog</code> method to ensure that a
- correctly populated instance of
- <code>AppServerLoggingEvent</code> is instantiated rather than
- the default <code>LoggingEvent</code>.
-<p>
-<li>Override the <code>getInstance</code> method to use our
- <code>CategoryFactory</code> (described in the next step). This will
- require that we hold a static reference to our factory and provide a
- way to initialize it.
-</ul>
-<p>
-Most of the code below is standard getter/setter verbage which has been
-somewhat abbreviated. The notable parts are in bold. We add five more
-attributes to <code>Category</code>: the four new logging attributes
-plus a static <code>AppServerCategoryFactory</code> reference. This is
-pre-initialized to an instance with attributes set to null as a
-precautionary measure. Otherwise the <code>getInstance</code> method
-will result in a null pointer exception if invoked before the
-<code>setFactory</code> method.
-<p>
-The <code>getInstance</code> method simply invokes its parent class
-method that accepts a <code>CategoryFactory</code> reference in
-addition to the category name.
-<p>
-The <code>forcedLog</code> method follows closely the corresponding
-parent class method. The most important difference is the instantiation
-of the <code>AppServerLoggingEvent</code>. A minor yet necessary
-difference is the use of the <code>getRendererMap()</code> method rather
-than accessing the data member directory as in <code>Category</code>.
-<code>Category</code> can do this because the rendererMap
-is package level accessible.
-<p>
-The <code>setFactory</code> method is provided to allow application code
-to set the factory used in the <code>getInstance</code> method.
-<p>
-<table border=1>
-<tr><td>
-<pre>
-import org.apache.log4j.Priority;
-import org.apache.log4j.Category;
-import org.apache.log4j.spi.CategoryFactory;
-import org.apache.log4j.spi.LoggingEvent;
-
-public class AppServerCategory extends Category
-{
- protected String <b>component</b>;
- protected String <b>hostname</b>;
- protected String <b>server</b>;
- protected String <b>version</b>;
- private static CategoryFactory <b>factory =
- new AppServerCategoryFactory(null, null, null)</b>;
-
- protected AppServerCategory( String categoryName,
- String hostname,
- String server,
- String component,
- String version )
- {
- super( categoryName );
- <b>instanceFQN = "org.apache.log4j.examples.appserver.AppServerCategory";</b>
-
- this.hostname = hostname;
- this.server = server;
- this.component = component;
- this.version = version;
- }
-
- public String getComponent()
- { return (component == null ) ? "" : result; }
-
- public String getHostname()
- { return ( hostname == null ) ? "" : hostname; }
-
- public static Category <b>getInstance</b>(String name)
- {
- return Category.getInstance(name, factory);
- }
-
- public String getServer()
- { return ( server == null ) ? "" : server; }
-
- public String getVersion()
- { return ( version == null ) ? "" : version; }
-
- protected void <b>forcedLog</b>( String fqn,
- Priority priority,
- Object message,
- Throwable t)
- {
-<b> LoggingEvent event = new AppServerLoggingEvent(fqn, this, priority, message, t);</b>
- callAppenders( event );
- }
-
- public void setComponent(String componentName)
- { component = componentName; }
-
- public static void <b>setFactory</b>(CategoryFactory factory)
- { AppServerCategory.factory = factory; }
-
- public void setHostname(String hostname)
- { this.hostname = hostname; }
-
- public void setServer(String serverName)
- { server = serverName; }
-
- public void setVersion(String versionName)
- { version = versionName; }
-}
-</pre>
-</table>
-<p>
-
-<a name="CategoryFactory"><h3>5. Extending <code>CategoryFactory</code></h3></a>
-
-The last step is to provide an implementation of the
-<code>CategoryFactory</code> interface that will correctly
-instantiate our <code>AppServerCategory</code> objects. It
-will obtain the hostname of the machine on which it runs using the
-<code>java.net</code> API. Aside from providing getters and
-setters for the attributes introduced, the only method to
-be implemented is the <code>makeNewCategoryInstance</code>.
-<p>
-Below is a snippet from <code>AppServerCategoryFactory</code>
-with getters, setters and comments removed.
-<p>
-<table border=1>
-<tr><td>
-<pre>
-import org.apache.log4j.Category;
-import org.apache.log4j.spi.CategoryFactory;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-public class AppServerCategoryFactory implements CategoryFactory
-{
- protected String hostname;
- protected String server;
- protected String component;
- protected String version;
- protected ResourceBundle messageBundle;
-
- protected AppServerCategoryFactory( String serverName,
- String componentName,
- String versionName )
- {
- try
- {
- hostname = java.net.InetAddress.getLocalHost().getHostName();
- }
- catch ( java.net.UnknownHostException uhe )
- {
- System.err.println("Could not determine local hostname.");
- }
-
- server = serverName;
- component = componentName;
- version = versionName;
- }
-
- public Category makeNewCategoryInstance(String name)
- {
- Category result = new AppServerCategory( name,
- hostname,
- server,
- component,
- version);
- return result;
- }
-}
-</pre>
-</table>
-<p>
-<hr>
-<a name="usage"><h2>Usage</h2></a>
-We now arrive at how to use what we have created. We must remember to
-initialize log4j by creating an instance of
-<code>AppServerCategoryFactory</code> and passing it to
-<code>AppServerCategory</code>. Once done, we can obtain a
-<code>AppServerCategoryInstance</code> anytime by using the static
-<code>getInstance</code> method of <code>AppServerCategory</code>.
-This will ensure that <code>AppServerLoggingEvent</code> instances
-are generated by the category logging methods.
-<p>
-<table border=1>
-<tr><td>
-<pre>
-import org.apache.log4j.*;
-import org.apache.log4j.appserver.AppServerCategory;
-import org.apache.log4j.appserver.AppServerCategoryFactory;
-import org.apache.log4j.appserver.AppServerPatternLayout;
-
-public class test
-{
- private static String formatString =
- "---------------------------------------------------%n" +
- "Time: %d%n" +
- "Host: %h%n" +
- "Server: %s%n" +
- "Component: %b%n" +
- "Version: %v%n" +
- "Priority: %p%n" +
- "Thread Id: %t%n" +
- "Context: %x%n" +
- "Message: %m%n";
-
- public static void main(String[] args)
- {
- AppServerCategoryFactory factory;
- factory = new AppServerCategoryFactory("MyServer", "MyComponent", "1.0");
- AppServerCategory.setFactory( factory );
- Category cat = AppServerCategory.getInstance("some.cat");
-
- PatternLayout layout = new AppServerPatternLayout( formatString );
- cat.addAppender( new FileAppender( layout, System.out) );
-
- cat.debug("This is a debug statement.");
- cat.info("This is an info statement.");
- cat.warn("This is a warning statement.");
- cat.error("This is an error statement.");
- cat.fatal("This is a fatal statement.");
- }
-}
-</pre>
-</table>
-<a name="configurators"><h3>Configurators</h3></a>
-There is one a word of caution concerning the use of configurators that
-may create <code>Category</code> instances (such as
-<a href="api/org/apache/log4j/PropertyConfigurator.html">
-<code>PropertyConfigurator</code></a>
-and
-<a href="api/org/apache/log4j/xml/DOMConfigurator.html">
-<code>DOMConfigurator</code></a>). Since these configurators do not
-know about our extensions, any <code>Category</code> instances they
-create will not be <code>AppServerCategory</code> instances. To
-prevent this problem, any <code>AppServerCategory</code> that one
-might want to be configured through a configurator should be
-instantiated before the configure method is invoked. In this way,
-the configurator will configure the <code>AppServerCategory</code>
-that already exists rather than creating an instance of its super
-class.
-<p>
-The consequence of a configurator creating the super class by
-mistake is merely that the extra attributes will not appear in
-the log output. All other attributes are conveyed properly.
-<p>
-<hr>
-<a name="enhancements"><h2>Further Enhancements</h2></a>
-There are some other directions in which this log4j extension
-may be enhanced:
-<p>
-<ol>
-<li>The hostname attribute could incorportate a formatting convention
- similar to that of class and category names whereby only a certain
- number of the more significant components are displayed. But
- whereas with class and category names, the most significant component
- is on the right, with host names, it is on the left.
-<p>
-<li>Specifying a version number could be dangerous since programmers
- are apt to change versions of the code without changing the
- string constant in the code which specifies the version. Some
- source control programs provide for insertion of a version number
- into source. For those that don't, including the version number as
- a constant is likely to lead to confusion later on. It would be
- nice to see this short-coming addressed.
-</body>
-</html>
diff --git a/docs/images/ceki-72x101.gif b/docs/images/ceki-72x101.gif
new file mode 100644
index 0000000..7c7f002
--- /dev/null
+++ b/docs/images/ceki-72x101.gif
Binary files differ
diff --git a/docs/images/chainsaw-fullscreen-small.jpg b/docs/images/chainsaw-fullscreen-small.jpg
new file mode 100644
index 0000000..e4de51f
--- /dev/null
+++ b/docs/images/chainsaw-fullscreen-small.jpg
Binary files differ
diff --git a/docs/images/chainsaw-fullscreen.jpg b/docs/images/chainsaw-fullscreen.jpg
new file mode 100644
index 0000000..14835d1
--- /dev/null
+++ b/docs/images/chainsaw-fullscreen.jpg
Binary files differ
diff --git a/docs/images/coverSmall.png b/docs/images/coverSmall.png
new file mode 100644
index 0000000..4b19db9
--- /dev/null
+++ b/docs/images/coverSmall.png
Binary files differ
diff --git a/docs/images/mark-72x99.gif b/docs/images/mark-72x99.gif
new file mode 100644
index 0000000..8d50730
--- /dev/null
+++ b/docs/images/mark-72x99.gif
Binary files differ
diff --git a/docs/images/psmith.jpg b/docs/images/psmith.jpg
new file mode 100644
index 0000000..edde7ad
--- /dev/null
+++ b/docs/images/psmith.jpg
Binary files differ
diff --git a/docs/images/yshapira.bmp b/docs/images/yshapira.bmp
new file mode 100644
index 0000000..c2f2bdd
--- /dev/null
+++ b/docs/images/yshapira.bmp
Binary files differ
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..db910d5 100644
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -22,12 +22,12 @@
distribution. This document is based on the article <a
href="http://www.javaworld.com/jw-11-2000/jw-1122-log4j.html">"Log4j
delivers control over logging"</a> published in November 2000
- edition of <a
- href="http://www.javaworld.com">JavaWorld</a>. However, the
- present article contains more detailed and up to date
- information. The short manual also borrows some text from the
- book "log4j: the Manual" by the same author (yours truly).
-
+ edition of JavaWorld. However, the present article contains more
+ detailed and up to date information. The present short manual
+ also borrows some text from <a
+ href="https://www.qos.ch/shop/products/eclm/">"<em>The
+ complete log4j manual</em>"</a> by the same author (yours
+ truly).
<h2>Abstract</h2>
@@ -52,9 +52,9 @@
href="http://www.opensource.org">open source</a> initiative. The
latest log4j version, including full-source code, class files and
documentation can be found at <a
-href="http://jakarta.apache.org/log4j/"><b>http://jakarta.apache.org/log4j/</b></a>.
-By the way, log4j has been ported to the C, C++, C#, Python, Ruby, and
-Eiffel languages.
+href="http://logging.apache.org/log4j/"><b>http://logging.apache.org/log4j/</b></a>.
+By the way, log4j has been ported to the C, C++, C#, Perl, Python,
+Ruby, and Eiffel languages.
<p>Inserting log statements into code is a low-tech method for
debugging it. It may also be the only way because debuggers are not
@@ -70,7 +70,7 @@
development cycle, a sufficiently rich logging package can also be
viewed as an auditing tool.
-<p>As Brian W. Kernigan and Rob Pike put it in their truly excellent
+<p>As Brian W. Kernighan and Rob Pike put it in their truly excellent
book <i>"The Practice of Programming"</i>
<pre>
As personal choice, we tend not to use debuggers beyond getting a
@@ -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,13 +814,13 @@
<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
- way to specify the default initialization file is thourough the
+ way to specify the default initialization file is through the
<b>log4j.configuration</b> system property.</em> In case the system
property <b>log4j.configuration</b> is not defined, then set the
string variable <code>resource</code> to its default value
@@ -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/docs/overview.html b/docs/overview.html
index 40efccd..1dbe3ee 100644
--- a/docs/overview.html
+++ b/docs/overview.html
@@ -7,5 +7,6 @@
<p>Make sure to read the <a href="../manual.html"><b>user manual</b></a>
in addition to this javadoc documentation.
+</p>
</body> </html>
diff --git a/docs/praise.html b/docs/praise.html
deleted file mode 100755
index e6d10d0..0000000
--- a/docs/praise.html
+++ /dev/null
@@ -1,266 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html> <head>
-<title>Praise from log4j users</title>
-</head>
-
-<body bgcolor="white">
-<h2>Praise from log4j users</h2>
-
-<hr><blockquote>
-Log4J was named as a finalist in the "Most Useful New or Revised Java API/Technology"
-category, and Tomcat 3.2 was named as a finalist in the "Most Innovative Java Product" category.
-</blockquote>
-<p align=right><a href="http://www.javaworld.com" target="_blank">JavaWorld</a>, April 2001
-
-<hr><blockquote>
-<p>Log4j is an incredibly well designed and functional logging tool. I
-caught the religion last summer and with every project I work on, most
-everyone agrees it's a must know/have tool. Previously I was using
-another Java logging library developed internally within my company
-which I liked. I had no desire to learn another but did so for the
-sake of due diligence. Log4j has the following features which set it
-apart from others I have seen.
-
-<p><b>Highly configurable</b> - the ability to configure the
-properties of your loggers (called Categories in log4j) from within a
-property file is indispensible. This allows you to change the
-characteristics of your logging without changing code. You can change
-the logging level, the format of the output and the output targets
-very easily. One can also use XML files (though I haven't).
-
-<p><b>Unobtrusive</b> - I'm finishing a project where we started using another
-logging tool. The log statements were clumsily long and required using
-predefined constants that were hard to remember. When writing the
-initial code, "System.out.println" was so much easier to type that
-people did this for tracing with the best of intentions to place
-legitimate logging in later. You know the story. It never
-happened. Log4j statements are shorter than "System.out.println"
-statements. This encourages people to actually use it rather than
-simply agreeing to.
-
-<p><b>Easy configuration</b> - With just one statement, log4j will
-configure itself with a set of defaults that are useful until you get
-around to actually writing your property file, XML file or
-whatever. Like the point just made before, this allows log4j to be
-used at the outset of coding rather than having to wait because you
-haven't considered how you wish logging to be configured. The
-application code itself does not have to know how logging will be
-configured.
-
-<p><b>Performance Concerns</b> - Since Java does not use pre-processor
-macros, most Java tracing is always compiled into the code. That means
-that the decision to compile is made at runtime. There are times when
-performance is so paramount that even checking whether to log is a
-concern. There are other extremes where other delays make this
-insignificant so that the performance is easily sacrificed for the
-increased amount of information logged (such as method name, class
-name and line number in source code). The log4j javadoc documentation
-explains which information elements are quickly logged and which may
-compromise performance. It also includes benchmarks that demonstrate
-how fast certain statements are logged for a few sample machine
-configurations.
-
-<p><b>Hierarchical Categories</b> - This is highly useful in component
-based development. Each component has its own set of logging
-categories. When individually tested, the properties of these
-categories may be set however the developer wishes. When combined with
-other components, the categories inherit the properties determined by
-the integrator of the components. One can selectively elevate logging
-priorities on one component without affecting the other
-components. This is useful when you need a detailed trace from just a
-single component without crowding the trace file with messages from
-other components. All this can be done with property files - no change
-in the code is required.
-
-<p><b>Easily specified output format</b> - Some Java and OO purist
-disagree with me on this, but allowing one to use printf-style output
-format specification is powerful, convenient and compact. Log4j
-provides a Layout class with this capability. Of course, for those who
-wish, you may implement the Layout interface yourself with something
-"more OO". Naturally, the printf-style pattern can be specified in a
-property file.
-
-<p><b>Customization</b> - Like other loggers, log4j is interface-based
-making it possible to extend. Log4j supplies useful implementations
-that are extended easily without having to implement the interface
-from scratch.
-</blockquote>
-
-<p align=right>Paul Glezen (pglezen at atdial.net), December 3rd, 2000
-
-<hr><blockquote>
-This Java package is probably one of the best and most reliable packages
-around, and really helps development and maintenance of quality software.
-Thanks to all contributors who have made such a good work.
-</blockquote>
-
-<p align=right>Denis Balazuc (denis.balazuc at trader.com), December 8th, 2000
-
-<hr><blockquote> This is just a quick note of thanks for publishing
-your article in Javaworld. Log4j is really easy to use. While I was
-initially skeptical of the idea, code like this makes me a believer in
-the concept of Open Source.
-</blockquote>
-
-<p align=right>Paul Hyndman (PaulHyndman at mynd.com), November 29th, 2000
-
-<hr><blockquote>
-I just recently became aware of log4j and am just now begining to use
-it. I want to thank you and the rest of the log4j development team for
-making this functionality available. You are providing an outstanding
-service to the development community. Please pass my regards on to the
-other team members.
-</blockquote>
-
-<p align=right>Rich Coco (racoco at celoxnetworks.com), November 16th, 2000
-
-
-
-<hr><blockquote>
-
-Just thought I'd let you know that I am using your log4j as a part of
-an e-commerce application (<a
-href="http://www.consumerd.com">www.consumerd.com</a>). I am using
-the XML configuration classes and have to say that I am most
-impressed.
-</blockquote>
-
-<p align=right>Richard King (Richard.King at capgemini.co.uk), October 25th, 2000
-
-<hr><blockquote>
-
-You should see what we've used log4j for at work... I put together
-this Servlet that can interpret SOAP messages and invoke little
-"handlers". Logging is pervasive through out the system, and the
-handler developers can "create" their own Categories dynamically using
-the getInstance method of Category.
-
-<p>It's funny when I get an email from someone at work who's using the
-toolkit with a "it didn't work" question, and I ask them to check out
-the log... due to the coolness of log4j, they can track down their
-mistake immediately.
-
-</blockquote>
-<p align=right>Christopher Taylor (cstaylor at pacbell.net), September 2nd, 2000
-
-<hr><blockquote>
-I am using log4j for a project I am currently working on. The
-simplicity and ease with which new appenders can be written makes it
-one of the best logging systems I have ever used.
-</blockquote>
-
-<p align=right> Manish Balsara (manishb at aumsoft.com) August 28th, 2000
-
-<hr><blockquote>
-Thank you for writing this incredibly effective piece of software. You
-have made my and my team's lives much easier.
-</blockquote>
-
-<p align=right>Guy Nirpaz, Java Architect (guyn at tantian.com) August
-14th, 2000
-
-<hr><blockquote>
-Thank you <em>so</em> much for developing such a
-sleek package. I think it's going to be a part of many of my projects in
-the future :)
-</blockquote>
-
-<p align=right>Alice Nakajima (alice.t.nakajima at saic.com) May 10th,
-2000
-
-
-<hr><blockquote>
-Thank you very much for your great work on log4j, which is really
-powerful and flexible logging system. Log4j is now playing an
-important role in our project.
-</blockquote>
-
-<p align=right> Zeng Qiang (zeng.qiang at europeloan.com) April 26th, 2000
-
-<hr>
-<blockquote> Thank you and your team giving us a excellent tool to
-help us to develop our Java applications. After evaluation, our team
-is ready to use log4j as our eCare product's diagnostic strategy.
-</blockquote> <p align=right>Jianbo Wang (jiwang at Daleen.com) April
-25th, 2000
-
-<hr>
-<blockquote> <!-- OK -->
-Was trying to use the log4j tracer ... great job, by the way !
-
-<p>Actually I'm evaluating the log4j package for use in our commercial
-projects. We have our own tracer package which is by far less
-powerfull and less configurable than yours.
-</blockquote>
-<p align=right>Joerg Palmer (Joerg.Palmer at Compart.net) April 14th, 2000
-
-
-<hr>
-<blockquote><!-- OK -->
-Hooray, log4j! It's now all over my current project, and my colleagues
-were pleasantly surprised at the ease of debugging. I gave them my
-jarfile, it didn't work, I said "oh, just change this configuration
-file" and <em>presto</em>, logging to a file. They're happy.
-</blockquote>
-<p align=right>Nelson Minar CTO, Popular Power, Inc. (nelson at popularpower.com) April 14th, 2000
-
-<hr>
-<blockquote><!-- OK -->
-I really dig your log4j package... just started using it on our linux
-and os390 boxes for the java servlets we run in websphere. Still
-trying to get the hang of it properly, but what I do have working is
-working great. (Not to mention your makefile tutorial which has
-improved my life significantly! :-)
-</blockquote>
-<p align=right>Anthony (ant at sanlam.co.za) April 13th, 2000
-
-
-<hr><!-- OK -->
-<blockquote>
-Thanks for providing log4j: it's a very useful package.
-</blockquote>
-<p align=right>Andrew Harris (Andrew.Harris at capgemini.co.uk) April 10th, 2000
-
-<hr>
-<blockquote><!-- OK -->
-I just started using log4j v.0.8.1. It is quite what I was looking for.
-<p>So here is my <b>"THANK YOU"</b> to all the contributors.
-I think I'll join the club.
-</blockquote>
-<p align=right>Avy Sharell (asharell at club-internet.fr) March 8th, 2000
-
-
-<hr>
-<blockquote><!-- OK -->
-I just wanted to thank you for log4j which is a great piece of software!
-
-<p>We are using it in the FREE e-democracy project
-<a href="http://www.thecouch.org/free/">http://www.thecouch.org/free/</a> to provide an effective security audit
-trail in our electronic voting software.
-</blockquote>
-<p align=right> Jason Kitcat (jeep at thecouch.org) March 29th, 2000
-
-
-<hr>
-<blockquote>
-Thanks for making log4j available.
-I like the changes in v0.8 and am using it in all my java projects.
-</blockquote>
-<p align=right>Steven Marcus (srnm at awaretechnologies.com) February 19th, 2000
-
-<hr>
-<blockquote><!-- OK -->
-First congratulation for your great job on the Log mechanism log4j,
-it's really valuable.
-</blockquote>
-<p align=right>Sebastien Sahuc (ssahuc at imediation.com) January 4th, 2000
-
-
-<hr> <blockquote> Just a few remarks to your log4j Logging-Tool. First
-of all, in my opinion, it is exactly what many Java programmers need:
-A small but very useful tool complementing the debugger ;-) The logs
-help me to debug results generated on a distant client. <p
-align=right>Jens Uwe Pipka (jens.pipka at gmx.de) October 25th, 1999
-
-<hr>
-</body> </html>
diff --git a/examples/MyPatternLayout.java b/examples/MyPatternLayout.java
index eba1787..9116864 100644
--- a/examples/MyPatternLayout.java
+++ b/examples/MyPatternLayout.java
@@ -46,9 +46,9 @@
public
static void main(String[] args) {
Layout layout = new MyPatternLayout("[counter=%.10#] - %m%n");
- Category cat = Category.getInstance("some.cat");
- cat.addAppender(new ConsoleAppender(layout, ConsoleAppender.SYSTEM_OUT));
- cat.debug("Hello, log");
- cat.info("Hello again...");
+ Logger logger = Logger.getLogger("some.cat");
+ logger.addAppender(new ConsoleAppender(layout, ConsoleAppender.SYSTEM_OUT));
+ logger.debug("Hello, log");
+ logger.info("Hello again...");
}
}
diff --git a/examples/NumberCruncherServer.java b/examples/NumberCruncherServer.java
index d2eec74..a5dde22 100644
--- a/examples/NumberCruncherServer.java
+++ b/examples/NumberCruncherServer.java
@@ -14,7 +14,7 @@
import java.util.Vector;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
import org.apache.log4j.PropertyConfigurator;
@@ -54,8 +54,7 @@
implements NumberCruncher {
- static Category cat = Category.getInstance(
- NumberCruncherServer.class.getName());
+ static Logger logger = Logger.getLogger(NumberCruncherServer.class);
public
NumberCruncherServer() throws RemoteException {
@@ -79,7 +78,7 @@
// contained in cookies.
NDC.push(String.valueOf(number));
- cat.info("Beginning to factor.");
+ logger.info("Beginning to factor.");
if(number <= 0) {
throw new IllegalArgumentException(number+" is not a positive integer.");
}
@@ -93,10 +92,10 @@
// It is bad practice to place log requests within tight loops.
// It is done here to show interleaved log output from
// different requests.
- cat.debug("Trying to see if " + i + " is a factor.");
+ logger.debug("Trying to see if " + i + " is a factor.");
if((n % i) == 0) {
- cat.info("Found factor "+i);
+ logger.info("Found factor "+i);
factors.addElement(new Integer(i));
do {
n /= i;
@@ -108,7 +107,7 @@
}
if(n != 1) {
- cat.info("Found factor "+n);
+ logger.info("Found factor "+n);
factors.addElement(new Integer(n));
}
@@ -153,10 +152,10 @@
try {
ncs = new NumberCruncherServer();
Naming.rebind("Factor", ncs);
- cat.info("NumberCruncherServer bound and ready to serve.");
+ logger.info("NumberCruncherServer bound and ready to serve.");
}
catch(Exception e) {
- cat.error("Could not bind NumberCruncherServer.", e);
+ logger.error("Could not bind NumberCruncherServer.", e);
return;
}
NumberCruncherClient.loop(ncs);
diff --git a/examples/SortAlgo.java b/examples/SortAlgo.java
index a5a3f53..98a4b04 100644
--- a/examples/SortAlgo.java
+++ b/examples/SortAlgo.java
@@ -1,7 +1,7 @@
package examples;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
/**
@@ -16,11 +16,11 @@
public class SortAlgo {
final static String className = SortAlgo.class.getName();
- final static Category CAT = Category.getInstance(className);
- final static Category OUTER = Category.getInstance(className + ".OUTER");
- final static Category INNER = Category.getInstance(className + ".INNER");
- final static Category DUMP = Category.getInstance(className + ".DUMP");
- final static Category SWAP = Category.getInstance(className + ".SWAP");
+ final static Logger LOG = Logger.getLogger(className);
+ final static Logger OUTER = Logger.getLogger(className + ".OUTER");
+ final static Logger INNER = Logger.getLogger(className + ".INNER");
+ final static Logger DUMP = Logger.getLogger(className + ".DUMP");
+ final static Logger SWAP = Logger.getLogger(className + ".SWAP");
int[] intArray;
@@ -29,7 +29,7 @@
}
void bubbleSort() {
- CAT.info( "Entered the sort method.");
+ LOG.info( "Entered the sort method.");
for(int i = intArray.length -1; i >= 0 ; i--) {
NDC.push("i=" + i);
diff --git a/examples/Trivial.java b/examples/Trivial.java
index 0f97056..9be452d 100644
--- a/examples/Trivial.java
+++ b/examples/Trivial.java
@@ -2,7 +2,7 @@
package examples;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.NDC;
@@ -33,31 +33,31 @@
*/
public class Trivial {
- static Category cat = Category.getInstance(Trivial.class.getName());
+ static Logger logger = Logger.getLogger(Trivial.class);
public static void main(String[] args) {
BasicConfigurator.configure();
NDC.push("Client #45890");
- cat.info("Awake awake. Put on thy strength.");
+ logger.info("Awake awake. Put on thy strength.");
Trivial.foo();
InnerTrivial.foo();
- cat.info("Exiting Trivial.");
+ logger.info("Exiting Trivial.");
}
static
void foo() {
NDC.push("DB");
- cat.debug("Now king David was old.");
+ logger.debug("Now king David was old.");
NDC.pop();
}
static class InnerTrivial {
- static Category cat = Category.getInstance(InnerTrivial.class.getName());
+ static Logger logger = Logger.getLogger(InnerTrivial.class);
static
void foo() {
- cat.info("Entered foo.");
+ logger.info("Entered foo.");
}
}
}
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/examples/subclass/MyLogger.java b/examples/subclass/MyLogger.java
index e91c46f..521dea5 100644
--- a/examples/subclass/MyLogger.java
+++ b/examples/subclass/MyLogger.java
@@ -50,16 +50,6 @@
}
/**
- This method overrides {@link Logger#getInstance} by supplying
- its own factory type as a parameter.
- */
- public
- static
- Category getInstance(String name) {
- return Logger.getLogger(name, myFactory);
- }
-
- /**
This method overrides {@link Logger#getLogger} by supplying
its own factory type as a parameter.
*/
diff --git a/examples/subclass/MyLoggerTest.java b/examples/subclass/MyLoggerTest.java
index 4f1ffa1..5c69dea 100644
--- a/examples/subclass/MyLoggerTest.java
+++ b/examples/subclass/MyLoggerTest.java
@@ -58,7 +58,7 @@
usage("Incorrect number of parameters.");
}
try {
- MyLogger c = (MyLogger) MyLogger.getInstance("some.cat");
+ MyLogger c = (MyLogger) MyLogger.getLogger("some.cat");
c.trace("Hello");
c.debug("Hello");
} catch(ClassCastException e) {
diff --git a/slf4j.xml b/slf4j.xml
new file mode 100644
index 0000000..c314fb5
--- /dev/null
+++ b/slf4j.xml
@@ -0,0 +1,82 @@
+<project name="slf4j" default="usage" basedir="." >
+
+ <!-- The directory where source files are stored. -->
+ <property name="java.source.dir" value="./src/java/"/>
+
+ <!-- Destination for compiled files -->
+ <property name="javac.dest" value="./classes"/>
+
+ <!-- The directory where source files are stored. -->
+ <property name="version" value="1.0alpha"/>
+
+ <!-- Deprecation warning? -->
+ <property name="deprecation" value="on"/>
+
+
+ <property name="SLF4J_STEM" value="org/slf4j"/>
+
+
+ <!-- ================================================================= -->
+ <!-- Default target -->
+ <!-- ================================================================= -->
+ <target name="usage">
+ <echo>
+ These are some of the targets supported by this ANT build scpript:
+
+ svnCheckout - get SLF4J files into src/filtered-java
+
+ refresh-slf4j - copy source files into the log4j source tree, using
+ variable substitution
+ </echo>
+ </target>
+
+ <target name="init">
+ <mkdir dir="tmp"/>
+ <mkdir dir="${java.source.dir}/${SLF4J_STEM}"/>
+ </target>
+
+ <!-- ================================================================= -->
+ <!-- Remove all generated (compiled) class files. -->
+ <!-- ================================================================= -->
+ <target name="clean" description="Delete all compiled SLF4J files.">
+ <delete dir="${javac.dest}/org/slf4j" />
+ </target>
+
+ <!-- =================================================================== -->
+ <!-- Copy SLF4J files into log4j source tree. This step is necessary for -->
+ <!-- building log4j. However, it needs to be done whenever code in SLF4J -->
+ <!-- changes, that is seldom -->
+ <!-- =================================================================== -->
+ <target name="refresh-slf4j" depends="init, svnCheckout">
+ <!-- delete any stale copy of LoggerFactory.java -->
+ <delete>
+ <fileset dir="src/java/org/slf4j"
+ includes="**/*.java"
+ excludes="impl/Log4jLoggerFA.java"/>
+ </delete>
+
+ <!-- copy a filtered version of slf4j to tmp/src -->
+ <copy todir="src/java">
+ <fileset dir="src/filtered-java">
+ <include name="**/*.java"/>
+ <exclude name="**/impl/JDK14*.java"/>
+ </fileset>
+ <filterset><filter token="IMPL" value="Log4j"/></filterset>
+ </copy>
+ </target>
+
+
+ <target name="svnCheckout">
+ <property name="repository.URL" value="http://svn.slf4j.org/repos/slf4j/trunk/src/filtered-java"/>
+ <java classname="org.tmatesoft.svn.cli.SVN" dir="src/" fork="true">
+ <arg value="co"/>
+ <arg value="${repository.URL}"/>
+ <arg value="filtered-java"/>
+ <classpath>
+ <pathelement location="lib/javasvn.jar" />
+ <pathelement location="lib/javasvn-cli.jar" />
+ </classpath>
+ </java>
+ </target>
+
+</project>
diff --git a/src/filtered-java/org/slf4j/LoggerFactory.java b/src/filtered-java/org/slf4j/LoggerFactory.java
new file mode 100644
index 0000000..e4bb471
--- /dev/null
+++ b/src/filtered-java/org/slf4j/LoggerFactory.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j;
+
+// WARNING
+// WARNING Modifications MUST be made to the original file found at
+// WARNING $SLF4J_HOME/src/filtered-java/org/slf4j/LoggerFactory.java
+// WARNING
+
+/**
+ * The <code>LoggerFactory</code> can produce Loggers for various logging APIs,
+ * most notably for log4j, JDK 1.4 logging. Other implemenations such as
+ * {@link org.slf4j.impl.NOPLogger NOPLogger} and
+ * {@link org.slf4j.impl.SimpleLogger SimpleLogger} are also supported.
+ *
+ * @author Ceki Gülcü
+ */
+public class LoggerFactory {
+ static LoggerFactoryAdapter adapter;
+
+ //
+ // WARNING Modify the original in
+ // $SLF4J_HOME/src/filtered-java/org/slf4j/
+
+ static {
+ String adapterClassStr = "org.slf4j.impl.@IMPL@LoggerFA";
+ System.out.println("SLF4J built for "+adapterClassStr);
+ try {
+ adapter = new org.slf4j.impl.@IMPL@LoggerFA();
+ } catch (Exception e) {
+ // unless there was a problem with the build or the JVM we will never
+ // get exceptions
+ System.err.println(
+ "Could not instantiate instance of class [" + adapterClassStr + "]");
+ e.printStackTrace();
+ }
+ }
+
+ public static ULogger getLogger(String name) {
+ return adapter.getLogger(name);
+ }
+
+ public static ULogger getLogger(String domainName, String subDomainName) {
+ return adapter.getLogger(domainName, subDomainName);
+ }
+
+ public static ULogger getLogger(Class clazz) {
+ return adapter.getLogger(clazz.getName());
+ }
+
+ public static ULogger getLogger(Class clazz, String subDomainName) {
+ return adapter.getLogger(clazz.getName(), subDomainName);
+ }
+}
diff --git a/src/filtered-java/org/slf4j/LoggerFactoryAdapter.java b/src/filtered-java/org/slf4j/LoggerFactoryAdapter.java
new file mode 100644
index 0000000..55b047e
--- /dev/null
+++ b/src/filtered-java/org/slf4j/LoggerFactoryAdapter.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j;
+
+/**
+ * LoggerFactoryAdapter interface is used internally by {@link
+ * LoggerFactory}.
+ *
+ * <p>Only developers wishing to write new UGLI adapters need to worry
+ * about this interface.
+ *
+ * @author Ceki Gülcü
+ *
+ */
+public interface LoggerFactoryAdapter {
+
+ /**
+ * Return the appropriate named {@link ULogger} instance.
+ */
+ public ULogger getLogger(String name);
+
+ /**
+ * Return a {@link ULogger} instance in <code>domain</code>, <code>subDomain</code>.
+ *
+ * @param domain
+ * @param subDomain
+ * @return ULogger instance
+ */
+ public ULogger getLogger(String domain, String subDomain);
+}
diff --git a/src/filtered-java/org/slf4j/ULogger.java b/src/filtered-java/org/slf4j/ULogger.java
new file mode 100644
index 0000000..279178e
--- /dev/null
+++ b/src/filtered-java/org/slf4j/ULogger.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j;
+
+/**
+ *
+ * The main user inteface to logging. It is expected that logging
+ * takes places through concerete implemetations of the ULogger
+ * interface.
+ *
+ * @author Ceki Gülcü
+ */
+public interface ULogger {
+
+ /**
+ * Is the logger instance enabled for the DEBUG level?
+ * @return True if this ULogger is enabled for the DEBUG level,
+ * false otherwise.
+ */
+ public boolean isDebugEnabled();
+
+ /**
+ * Log a message object with the DEBUG level.
+ * @param msg - the message object to be logged
+ */
+ public void debug(Object msg);
+
+
+ /**
+ * Log a parameterized message object at the DEBUG level.
+ *
+ * <p>This form is useful in avoiding the superflous object creation
+ * problem when invoking this method while it is disabled.
+ * </p>
+ * @param parameterizedMsg - the parameterized message object
+ * @param param1 - the parameter
+ */
+ public void debug(Object parameterizedMsg, Object param1);
+
+ /**
+ * Log a parameterized message object at the DEBUG level.
+ *
+ * <p>This form is useful in avoiding the superflous object creation
+ * problem when invoking this method while it is disabled.
+ * </p>
+ * @param parameterizedMsg - the parameterized message object
+ * @param param1 - the first parameter
+ * @param param2 - the second parameter
+ */
+ public void debug(String parameterizedMsg, Object param1, Object param2);
+ public void debug(Object msg, Throwable t);
+
+
+ public boolean isInfoEnabled();
+ public void info(Object msg);
+ public void info(Object parameterizedMsg, Object param1);
+ public void info(String parameterizedMsg, Object param1, Object param2);
+ public void info(Object msg, Throwable t);
+
+
+ public boolean isWarnEnabled();
+ public void warn(Object msg);
+ public void warn(Object parameterizedMsg, Object param1);
+ public void warn(String parameterizedMsg, Object param1, Object param2);
+ public void warn(Object msg, Throwable t);
+
+
+ public boolean isErrorEnabled();
+ public void error(Object msg);
+ public void error(Object parameterizedMsg, Object param1);
+ public void error(String parameterizedMsg, Object param1, Object param2);
+ public void error(Object msg, Throwable t);
+
+}
diff --git a/src/filtered-java/org/slf4j/impl/JDK14Logger.java b/src/filtered-java/org/slf4j/impl/JDK14Logger.java
new file mode 100644
index 0000000..9ae8506
--- /dev/null
+++ b/src/filtered-java/org/slf4j/impl/JDK14Logger.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ * Copyright (c) 2004-2005 QOS.ch
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j.impl;
+import org.slf4j.ULogger;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+/**
+ * A wrapper over @{link java.utill.Logger} which conforms to the
+ * {@link ULogger} interface.
+ *
+ * @author Ceki Gülcü
+ */
+public class JDK14Logger implements ULogger {
+ final Logger logger;
+
+ // WARN: JDK14Logger constructor should have only package access so that
+ // only JDK14LoggerFA be able to create one.
+ JDK14Logger(Logger logger) {
+ this.logger = logger;
+ }
+
+ /**
+ * Is the logger instance enabled for the DEBUG level?
+ * @return
+ */
+ public boolean isDebugEnabled() {
+ return logger.isLoggable(Level.FINE);
+ }
+
+ //
+
+ /**
+ * Log a message object with the DEBUG level.
+ * @param msg - the message object to be logged
+ */
+ public void debug(Object msg) {
+ logger.fine(String.valueOf(msg));
+ }
+
+ /**
+ * Log a parameterized message object at the DEBUG level.
+ *
+ * <p>This form is useful in avoiding the superflous object creation
+ * problem when invoking this method while it is disabled.
+ * </p>
+ * @param parameterizedMsg - the parameterized message object
+ * @param param1 - the parameter
+ */
+ public void debug(Object parameterizedMsg, Object param1) {
+ if (logger.isLoggable(Level.FINE)) {
+ if (parameterizedMsg instanceof String) {
+ String msgStr = (String) parameterizedMsg;
+ msgStr = MessageFormatter.format(msgStr, param1);
+ logger.fine(msgStr);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should not happen.
+ logger.fine(parameterizedMsg.toString());
+ }
+ }
+ }
+
+ /**
+ * Log a parameterized message object at the DEBUG level.
+ *
+ * <p>This form is useful in avoiding the superflous object creation
+ * problem when invoking this method while it is disabled.
+ * </p>
+ * @param parameterizedMsg - the parameterized message object
+ * @param param1 - the first parameter
+ * @param param2 - the second parameter
+ */
+ public void debug(String parameterizedMsg, Object param1, Object param2) {
+ if (logger.isLoggable(Level.FINE)) {
+ if (parameterizedMsg instanceof String) {
+ String msgStr = (String) parameterizedMsg;
+ msgStr = MessageFormatter.format(msgStr, param1, param2);
+ logger.fine(msgStr);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should not happen.
+ logger.fine(parameterizedMsg.toString());
+ }
+ }
+ }
+
+ public void debug(Object msg, Throwable t) {
+ logger.log(Level.FINE, msg.toString(), t);
+ }
+
+ public boolean isInfoEnabled() {
+ return logger.isLoggable(Level.INFO);
+ }
+
+ public void info(Object msg) {
+ logger.info(msg.toString());
+ }
+
+ public void info(Object parameterizedMsg, Object param1) {
+ if (logger.isLoggable(Level.INFO)) {
+ if (parameterizedMsg instanceof String) {
+ String msgStr = (String) parameterizedMsg;
+ msgStr = MessageFormatter.format(msgStr, param1);
+ logger.info(msgStr);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should not happen.
+ logger.info(parameterizedMsg.toString());
+ }
+ }
+ }
+
+ public void info(String parameterizedMsg, Object param1, Object param2) {
+ if (logger.isLoggable(Level.INFO)) {
+ if (parameterizedMsg instanceof String) {
+ String msgStr = (String) parameterizedMsg;
+ msgStr = MessageFormatter.format(msgStr, param1, param2);
+ logger.info(msgStr);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should not happen.
+ logger.info(parameterizedMsg.toString());
+ }
+ }
+ }
+
+ public void info(Object msg, Throwable t) {
+ logger.log(Level.INFO, msg.toString(), t);
+ }
+
+ public boolean isWarnEnabled() {
+ return logger.isLoggable(Level.WARNING);
+ }
+
+ public void warn(Object msg) {
+ logger.warning(msg.toString());
+ }
+
+ public void warn(Object parameterizedMsg, Object param1) {
+ if (logger.isLoggable(Level.WARNING)) {
+ if (parameterizedMsg instanceof String) {
+ String msgStr = (String) parameterizedMsg;
+ msgStr = MessageFormatter.format(msgStr, param1);
+ logger.warning(msgStr);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should not happen.
+ logger.warning(parameterizedMsg.toString());
+ }
+ }
+ }
+
+ public void warn(String parameterizedMsg, Object param1, Object param2) {
+ if (logger.isLoggable(Level.WARNING)) {
+ if (parameterizedMsg instanceof String) {
+ String msgStr = (String) parameterizedMsg;
+ msgStr = MessageFormatter.format(msgStr, param1, param2);
+ logger.warning(msgStr);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should not happen.
+ logger.warning(parameterizedMsg.toString());
+ }
+ }
+ }
+
+ public void warn(Object msg, Throwable t) {
+ logger.log(Level.WARNING, msg.toString(), t);
+ }
+
+ public boolean isErrorEnabled() {
+ return logger.isLoggable(Level.SEVERE);
+ }
+
+ public void error(Object msg) {
+ logger.severe(msg.toString());
+ }
+
+ public void error(Object parameterizedMsg, Object param1) {
+ if (logger.isLoggable(Level.WARNING)) {
+ if (parameterizedMsg instanceof String) {
+ String msgStr = (String) parameterizedMsg;
+ msgStr = MessageFormatter.format(msgStr, param1);
+ logger.severe(msgStr);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should not happen.
+ logger.severe(parameterizedMsg.toString());
+ }
+ }
+ }
+
+ public void error(String parameterizedMsg, Object param1, Object param2) {
+ if (logger.isLoggable(Level.WARNING)) {
+ if (parameterizedMsg instanceof String) {
+ String msgStr = (String) parameterizedMsg;
+ msgStr = MessageFormatter.format(msgStr, param1, param2);
+ logger.severe(msgStr);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should not happen.
+ logger.severe(parameterizedMsg.toString());
+ }
+ }
+ }
+ public void error(Object msg, Throwable t) {
+ logger.log(Level.SEVERE, msg.toString(), t);
+ }
+}
diff --git a/src/filtered-java/org/slf4j/impl/JDK14LoggerFA.java b/src/filtered-java/org/slf4j/impl/JDK14LoggerFA.java
new file mode 100644
index 0000000..b90154c
--- /dev/null
+++ b/src/filtered-java/org/slf4j/impl/JDK14LoggerFA.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ * Copyright (c) 2004-2005 QOS.ch
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j.impl;
+
+import org.slf4j.LoggerFactoryAdapter;
+import org.slf4j.ULogger;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+
+/**
+ *
+ * @author Ceki Gülcü
+ */
+public class JDK14LoggerFA implements LoggerFactoryAdapter {
+ Map map;
+
+ public JDK14LoggerFA() {
+ map = new HashMap();
+ }
+
+ /* (non-Javadoc)
+ * @see org.slf4j.LoggerFactoryAdapter#getLogger(java.lang.String)
+ */
+ public ULogger getLogger(String name) {
+ ULogger ulogger = (ULogger) map.get(name);
+ if (ulogger == null) {
+ Logger logger = Logger.getLogger(name);
+ ulogger = new JDK14Logger(logger);
+ map.put(name, ulogger);
+ }
+ return ulogger;
+ }
+
+ /* (non-Javadoc)
+ * @see org.slf4j.LoggerFactoryAdapter#getLogger(java.lang.String, java.lang.String)
+ */
+ public ULogger getLogger(String domainName, String subDomainName) {
+ return getLogger(domainName);
+ }
+}
diff --git a/src/filtered-java/org/slf4j/impl/MessageFormatter.java b/src/filtered-java/org/slf4j/impl/MessageFormatter.java
new file mode 100644
index 0000000..c650c39
--- /dev/null
+++ b/src/filtered-java/org/slf4j/impl/MessageFormatter.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ * Copyright (c) 2004-2005 QOS.ch
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j.impl;
+
+
+/**
+ * Formats messages according to very simple rules.
+ * See {@link #format(String, Object)} and
+ * {@link #format(String, Object, Object)} for more details.
+ *
+ * @author Ceki Gülcü
+ */
+public class MessageFormatter {
+ static final char DELIM_START = '{';
+ static final char DELIM_STOP = '}';
+
+ /**
+ * Performs single argument substitution for the 'messagePattern' passed as
+ * parameter.
+ * <p>
+ * For example, <code>MessageFormatter.format("Hi {}.", "there");</code> will
+ * return the string "Hi there.".
+ * <p>
+ * The {} pair is called the formatting element. It serves to designate the
+ * location where the argument needs to be inserted within the pattern.
+ *
+ * @param messagePattern The message pattern which will be parsed and formatted
+ * @param argument The argument to be inserted instead of the formatting element
+ * @return The formatted message
+ */
+ public static String format(String messagePattern, Object argument) {
+ int j = messagePattern.indexOf(DELIM_START);
+ int len = messagePattern.length();
+ char escape = 'x';
+
+ // if there are no { characters or { is the last character of the messsage
+ // then we just return messagePattern
+ if (j == -1 || (j+1 == len)) {
+ return messagePattern;
+ } else {
+ if(j+1 == len) {
+ }
+
+ char delimStop = messagePattern.charAt(j + 1);
+ if (j > 0) {
+ escape = messagePattern.charAt(j - 1);
+ }
+ if ((delimStop != DELIM_STOP) || (escape == '\\')) {
+ // invalid DELIM_START/DELIM_STOP pair or espace character is
+ // present
+ return messagePattern;
+ } else {
+ StringBuffer sbuf = new StringBuffer(len + 20);
+ sbuf.append(messagePattern.substring(0, j));
+ sbuf.append(argument);
+ sbuf.append(messagePattern.substring(j + 2));
+ return sbuf.toString();
+ }
+ }
+ }
+
+ /**
+ * /**
+ * Performs a two argument substitution for the 'messagePattern' passed as
+ * parameter.
+ * <p>
+ * For example, <code>MessageFormatter.format("Hi {}. My name is {}.",
+ * "there", "David");</code> will return the string "Hi there. My name is David.".
+ * <p>
+ * The '{}' pair is called a formatting element. It serves to designate the
+ * location where the arguments need to be inserted within the message pattern.
+ *
+ * @param messagePattern The message pattern which will be parsed and formatted
+ * @param arg1 The first argument to replace the first formatting element
+ * @param arg2 The second argument to replace the second formatting element
+ * @return The formatted message
+ */
+ public static String format(String messagePattern, Object arg1, Object arg2) {
+ int i = 0;
+ int len = messagePattern.length();
+ int j = messagePattern.indexOf(DELIM_START);
+
+ StringBuffer sbuf = new StringBuffer(messagePattern.length() + 50);
+
+ for (int L = 0; L < 2; L++) {
+ j = messagePattern.indexOf(DELIM_START, i);
+
+ if (j == -1 || (j+1 == len)) {
+ // no more variables
+ if (i == 0) { // this is a simple string
+ return messagePattern;
+ } else { // add the tail string which contains no variables and return the result.
+ sbuf.append(messagePattern.substring(i, messagePattern.length()));
+ return sbuf.toString();
+ }
+ } else {
+ char delimStop = messagePattern.charAt(j + 1);
+ if ((delimStop != DELIM_STOP)) {
+ // invalid DELIM_START/DELIM_STOP pair
+ sbuf.append(messagePattern.substring(i, messagePattern.length()));
+ return sbuf.toString();
+ }
+ sbuf.append(messagePattern.substring(i, j));
+ sbuf.append((L == 0) ? arg1 : arg2);
+ i = j + 2;
+ }
+ }
+ // append the characters following the second {} pair.
+ sbuf.append(messagePattern.substring(i, messagePattern.length()));
+ return sbuf.toString();
+ }
+}
diff --git a/src/filtered-java/org/slf4j/impl/NOPLogger.java b/src/filtered-java/org/slf4j/impl/NOPLogger.java
new file mode 100644
index 0000000..d0c4820
--- /dev/null
+++ b/src/filtered-java/org/slf4j/impl/NOPLogger.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ * Copyright (c) 2004-2005 QOS.ch
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j.impl;
+
+import org.slf4j.ULogger;
+
+
+/**
+ * A no operation (NOP) implementation of {@link ULogger}.
+ *
+ * @author Ceki Gülcü
+ */
+public class NOPLogger implements ULogger {
+
+ /**
+ * The unique instance of NOPLogger.
+ */
+ public final static NOPLogger NOP_LOGGER = new NOPLogger();
+
+ /**
+ * There is no point in people creating multiple instances of NullLogger.
+ * Hence, the private access modifier.
+ */
+ private NOPLogger() {
+ }
+
+ /* Always returns false.
+ *
+ * @see org.slf4j.Logger#isDebugEnabled()
+ */
+ public boolean isDebugEnabled() {
+ return false;
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#debug(java.lang.Object)
+ */
+ public void debug(Object msg) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#debug(java.lang.Object, java.lang.Object)
+ */
+ public void debug(Object parameterizedMsg, Object param1) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#debug(java.lang.Object, java.lang.Object, java.lang.Object)
+ */
+ public void debug(String parameterizedMsg, Object param1, Object param2) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#debug(java.lang.Object, java.lang.Throwable)
+ */
+ public void debug(Object msg, Throwable t) {
+ // NOP
+ }
+
+ /* Always returns false.
+ * @see org.slf4j.Logger#isInfoEnabled()
+ */
+ public boolean isInfoEnabled() {
+ // NOP
+ return false;
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#info(java.lang.Object)
+ */
+ public void info(Object msg) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#info(java.lang.Object, java.lang.Object)
+ */
+ public void info(Object parameterizedMsg, Object param1) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#info(java.lang.Object, java.lang.Object, java.lang.Object)
+ */
+ public void info(String parameterizedMsg, Object param1, Object param2) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#info(java.lang.Object, java.lang.Throwable)
+ */
+ public void info(Object msg, Throwable t) {
+ // NOP
+ }
+
+ /* Always returns false.
+ * @see org.slf4j.Logger#isWarnEnabled()
+ */
+ public boolean isWarnEnabled() {
+ return false;
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#warn(java.lang.Object)
+ */
+ public void warn(Object msg) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#warn(java.lang.Object, java.lang.Object)
+ */
+ public void warn(Object parameterizedMsg, Object param1) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#warn(java.lang.Object, java.lang.Object, java.lang.Object)
+ */
+ public void warn(String parameterizedMsg, Object param1, Object param2) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#warn(java.lang.Object, java.lang.Throwable)
+ */
+ public void warn(Object msg, Throwable t) {
+ // NOP
+ }
+
+ /* Always returns false.
+ * @see org.slf4j.Logger#isErrorEnabled()
+ */
+ public boolean isErrorEnabled() {
+ return false;
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#error(java.lang.Object)
+ */
+ public void error(Object msg) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#error(java.lang.Object, java.lang.Object)
+ */
+ public void error(Object parameterizedMsg, Object param1) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#error(java.lang.Object, java.lang.Object, java.lang.Object)
+ */
+ public void error(String parameterizedMsg, Object param1, Object param2) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#error(java.lang.Object, java.lang.Throwable)
+ */
+ public void error(Object msg, Throwable t) {
+ // NOP
+ }
+
+}
diff --git a/src/filtered-java/org/slf4j/impl/NOPLoggerFA.java b/src/filtered-java/org/slf4j/impl/NOPLoggerFA.java
new file mode 100644
index 0000000..2d321ad
--- /dev/null
+++ b/src/filtered-java/org/slf4j/impl/NOPLoggerFA.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ * Copyright (c) 2004-2005 QOS.ch
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j.impl;
+
+import org.slf4j.LoggerFactoryAdapter;
+import org.slf4j.ULogger;
+
+
+/**
+ * NOPLoggerFA is am implementation of {@link LoggerFactoryAdapter}
+ * which always returns the unique instance of NOPLogger.
+ *
+ * @author Ceki Gulcu
+ */
+public class NOPLoggerFA implements LoggerFactoryAdapter {
+
+ public NOPLoggerFA() {
+ // nothing to do
+ }
+
+ public ULogger getLogger(String name) {
+ return NOPLogger.NOP_LOGGER;
+ }
+ public ULogger getLogger(String domainName, String subDomainName) {
+ return NOPLogger.NOP_LOGGER;
+ }
+}
diff --git a/src/filtered-java/org/slf4j/impl/SimpleLogger.java b/src/filtered-java/org/slf4j/impl/SimpleLogger.java
new file mode 100644
index 0000000..7b8be4a
--- /dev/null
+++ b/src/filtered-java/org/slf4j/impl/SimpleLogger.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ * Copyright (c) 2004-2005 QOS.ch
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j.impl;
+
+import org.slf4j.ULogger;
+
+
+/**
+ * A simple implementation that logs messages of level INFO or higher on
+ * the console (<code>System.out<code>).
+ * <p>
+ * The output includes the relative time in milliseconds, thread name, the level,
+ * logger name, and the message followed by the line separator for the host.
+ * In log4j terms it amounts to the "%r [%t] %level %logger - %m%n" pattern.
+ * <pre>
+176 [main] INFO examples.Sort - Populating an array of 2 elements in reverse order.
+225 [main] INFO examples.SortAlgo - Entered the sort method.
+304 [main] INFO SortAlgo.DUMP - Dump of interger array:
+317 [main] INFO SortAlgo.DUMP - Element [0] = 0
+331 [main] INFO SortAlgo.DUMP - Element [1] = 1
+343 [main] INFO examples.Sort - The next log statement should be an error message.
+346 [main] ERROR SortAlgo.DUMP - Tried to dump an uninitialized array.
+ at org.log4j.examples.SortAlgo.dump(SortAlgo.java:58)
+ at org.log4j.examples.Sort.main(Sort.java:64)
+467 [main] INFO examples.Sort - Exiting main method.
+</pre>
+ *
+ * @author Ceki Gülcü
+ */
+public class SimpleLogger implements ULogger {
+
+ String loggerName;
+
+ /**
+ * Mark the time when this class gets loaded into memory.
+ */
+ static private long startTime = System.currentTimeMillis();
+
+ public static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ static private String INFO_STR = "INFO";
+ static private String WARN_STR = "WARN";
+ static private String ERROR_STR = "ERROR";
+
+ /**
+ * Package access allows only {@link SimpleLoggerFA} to instantiate
+ * SimpleLogger instances.
+ */
+ SimpleLogger(String name) {
+ this.loggerName = name;
+ }
+
+ /**
+ * Always returns false.
+ */
+ public boolean isDebugEnabled() {
+ return false;
+ }
+
+ /**
+ * A NOP implementation.
+ */
+ public void debug(Object msg) {
+ // NOP
+ }
+
+ /**
+ * A NOP implementation.
+ */
+ public void debug(Object parameterizedMsg, Object param1) {
+ // NOP
+ }
+
+ /**
+ * A NOP implementation.
+ */
+ public void debug(String parameterizedMsg, Object param1, Object param2) {
+ // NOP
+ }
+
+ /**
+ * A NOP implementation.
+ */
+ public void debug(Object msg, Throwable t) {
+ // NOP
+ }
+
+ /**
+ * This is our internal implementation for logging regular (non-parameterized)
+ * log messages.
+ *
+ * @param level
+ * @param message
+ * @param t
+ */
+ private void log(String level, String message, Throwable t) {
+ StringBuffer buf = new StringBuffer();
+
+ long millis = System.currentTimeMillis();
+ buf.append(millis-startTime);
+
+ buf.append(" [");
+ buf.append(Thread.currentThread().getName());
+ buf.append("] ");
+
+ buf.append(level);
+ buf.append(" ");
+
+ buf.append(loggerName);
+ buf.append(" - ");
+
+ buf.append(message);
+
+ buf.append(LINE_SEPARATOR);
+
+ System.out.print(buf.toString());
+ if(t != null) {
+ t.printStackTrace(System.out);
+ }
+ System.out.flush();
+ }
+ /**
+ * For parameterized messages, first substitute parameters and then log.
+ *
+ * @param level
+ * @param parameterizedMsg
+ * @param param1
+ * @param param2
+ */
+ private void parameterizedLog(String level, Object parameterizedMsg, Object param1, Object param2) {
+ if (parameterizedMsg instanceof String) {
+ String msgStr = (String) parameterizedMsg;
+ msgStr = MessageFormatter.format(msgStr, param1, param2);
+ log(level, msgStr, null);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should not happen.
+ log(level, parameterizedMsg.toString(), null);
+ }
+ }
+
+ /**
+ * Always returns true.
+ */
+ public boolean isInfoEnabled() {
+ return true;
+ }
+
+ /**
+ * A simple implementation which always logs messages of level INFO according
+ * to the format outlined above.
+ */
+ public void info(Object msg) {
+ log(INFO_STR, msg.toString(), null);
+ }
+
+
+ /**
+ * Perform single parameter substituion before logging the message of level
+ * INFO according to the format outlined above.
+ */
+ public void info(Object parameterizedMsg, Object param1) {
+ parameterizedLog(INFO_STR, parameterizedMsg, param1, null);
+ }
+
+ /**
+ * Perform double parameter substituion before logging the message of level
+ * INFO according to the format outlined above.
+ */
+
+ public void info(String parameterizedMsg, Object param1, Object param2) {
+ parameterizedLog(INFO_STR, parameterizedMsg, param1, param2);
+ }
+
+ /**
+ * Log a message of level INFO, including an exception.
+ */
+ public void info(Object msg, Throwable t) {
+ log(INFO_STR, msg.toString(), t);
+ }
+
+ /**
+ * Always returns true.
+ */
+ public boolean isWarnEnabled() {
+ return true;
+ }
+
+ /**
+ * A simple implementation which always logs messages of level WARN according
+ * to the format outlined above.
+ */
+ public void warn(Object msg) {
+ log(WARN_STR, msg.toString(), null);
+ }
+
+ /**
+ * Perform single parameter substituion before logging the message of level
+ * WARN according to the format outlined above.
+ */
+ public void warn(Object parameterizedMsg, Object param1) {
+ parameterizedLog(WARN_STR, parameterizedMsg, param1, null);
+ }
+
+ /**
+ * Perform double parameter substituion before logging the message of level
+ * WARN according to the format outlined above.
+ */
+ public void warn(String parameterizedMsg, Object param1, Object param2) {
+ parameterizedLog(WARN_STR, parameterizedMsg, param1, param2);
+ }
+
+ /**
+ * Log a message of level WARN, including an exception.
+ */
+ public void warn(Object msg, Throwable t) {
+ log(WARN_STR, msg.toString(), t);
+ }
+
+ /**
+ * Always returns true.
+ */
+ public boolean isErrorEnabled() {
+ return true;
+ }
+
+ /**
+ * A simple implementation which always logs messages of level ERROR acoording
+ * to the format outlined above.
+ */
+ public void error(Object msg) {
+ log(ERROR_STR, msg.toString(), null);
+ }
+
+
+ /**
+ * Perform single parameter substituion before logging the message of level
+ * ERROR according to the format outlined above.
+ */
+ public void error(Object parameterizedMsg, Object param1) {
+ parameterizedLog(ERROR_STR, parameterizedMsg, param1, null);
+ }
+
+ /**
+ * Perform double parameter substituion before logging the message of level
+ * ERROR according to the format outlined above.
+ */
+ public void error(String parameterizedMsg, Object param1, Object param2) {
+ parameterizedLog(ERROR_STR, parameterizedMsg, param1, param2);
+ }
+
+ /**
+ * Log a message of level ERROR, including an exception.
+ */
+ public void error(Object msg, Throwable t) {
+ log(ERROR_STR, msg.toString(), t);
+ }
+
+}
diff --git a/src/filtered-java/org/slf4j/impl/SimpleLoggerFA.java b/src/filtered-java/org/slf4j/impl/SimpleLoggerFA.java
new file mode 100644
index 0000000..6b04340
--- /dev/null
+++ b/src/filtered-java/org/slf4j/impl/SimpleLoggerFA.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ * Copyright (c) 2004-2005 QOS.ch
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.slf4j.LoggerFactoryAdapter;
+import org.slf4j.ULogger;
+
+
+/**
+ * An implementation of {@link LoggerFactoryAdapter} which always returns
+ * {@link SimpleLogger} instances.
+ *
+ * @author Ceki Gülcü
+ */
+public class SimpleLoggerFA implements LoggerFactoryAdapter {
+
+ Map map;
+
+ public SimpleLoggerFA() {
+ map = new HashMap();
+ }
+
+
+ /**
+ * Return an appropriate {@link SimpleLogger} instance by name. At this time,
+ *
+ */
+ /**
+ * Return an appropriate {@link SimpleLogger} instance.
+ * */
+ public ULogger getLogger(String name) {
+ ULogger ulogger = (ULogger) map.get(name);
+ if(ulogger == null) {
+ ulogger = new SimpleLogger(name);
+ map.put(name, ulogger);
+ }
+ return ulogger;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.slf4j.LoggerFactoryAdapter#getLogger(java.lang.String, java.lang.String)
+ */
+ public ULogger getLogger(String domainName, String subDomainName) {
+ return getLogger(domainName);
+ }
+
+
+}
diff --git a/src/java/org/apache/log4j/Appender.java b/src/java/org/apache/log4j/Appender.java
index 3642811..aa8a310 100644
--- a/src/java/org/apache/log4j/Appender.java
+++ b/src/java/org/apache/log4j/Appender.java
@@ -73,7 +73,7 @@
/**
Set the {@link ErrorHandler} for this appender.
- @ since 0.9.0
+ @since 0.9.0
*/
public
void setErrorHandler(ErrorHandler errorHandler);
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..f8dfdf4 100644
--- a/src/java/org/apache/log4j/Category.java
+++ b/src/java/org/apache/log4j/Category.java
@@ -31,42 +31,50 @@
import java.util.MissingResourceException;
import java.util.ResourceBundle;
+import org.slf4j.impl.MessageFormatter;
/**
- <font color="#AA2222"><b>This class has been deprecated and
- replaced by the {@link Logger} <em>subclass</em>.</b></font> It
- will be kept around to preserve backward compatibility until mid
- 2003.
-
- <p><code>Logger</code> is a subclass of Category, i.e. it extends
- Category. In other words, a logger <em>is</em> a category. Thus,
- all operations that can be performed on a category can be performed
- on a logger. Whenever log4j is asked to produce a Category object,
- it will instead produce a Logger object. However, methods that
- previously accepted category objects still continue to accept
- category objects.
-
- <p>For example, the following are all legal and will work as expected.
-
+ * <font color="#AA2222"><b>This class has been deprecated and
+ * replaced by the {@link Logger} <em>subclass</em></b></font>. It
+ * will be kept around to preserve backward compatibility until mid
+ * 2003.
+ *
+ * <p><code>Logger</code> is a subclass of Category, i.e. it extends
+ * Category. In other words, a logger <em>is</em> a category. Thus,
+ * all operations that can be performed on a category can be
+ * performed on a logger. Internally, whenever log4j is asked to
+ * produce a Category object, it will instead produce a Logger
+ * object. Log4j 1.2 will <em>never</em> produce Category objects but
+ * only <code>Logger</code> instances. In order to preserve backward
+ * compatibility, methods that previously accepted category objects
+ * still continue to accept category objects.
+ *
+ * <p>For example, the following are all legal and will work as
+ * expected.
+ *
<pre>
- // Deprecated form:
- Category cat = Category.getInstance("foo.bar")
-
- // Preferred form for retrieving loggers:
- Logger logger = Logger.getLogger("foo.bar")
+ // Deprecated form:
+ Category cat = Category.getInstance("foo.bar")
+
+ // Preferred form for retrieving loggers:
+ Logger logger = Logger.getLogger("foo.bar")
</pre>
-
- <p>The first form is deprecated and should be avoided.
-
- <p><b>There is absolutely no need for new client code to use or
- refer to the <code>Category</code> class.</b> Whenever possible,
- please avoid referring to it or using it.
-
- <p>See the <a href="../../../../manual.html">short manual</a> for an
- introduction on this class.
-
- @author Ceki Gülcü
- @author Anders Kristensen */
+
+ * <p>The first form is deprecated and should be avoided.
+ *
+ * <p><b>There is absolutely no need for new client code to use or
+ * refer to the <code>Category</code> class.</b> Whenever possible,
+ * please avoid referring to it or using it.
+ *
+ * <p>See the <a href="../../../../manual.html">short manual</a> for an
+ * introduction on this class.
+ * <p>
+ * See the document entitled <a href="http://www.qos.ch/logging/preparingFor13.html">preparing
+ * for log4j 1.3</a> for a more detailed discussion.
+ *
+ * @author Ceki Gülcü
+ * @author Anders Kristensen
+ */
public class Category implements AppenderAttachable {
/**
@@ -77,9 +85,6 @@
//final Hierarchy defaultHierarchy = new Hierarchy(new
// RootCategory(Level.DEBUG));
-
- static int nooptimize;
-
/**
The name of this category.
*/
@@ -207,10 +212,10 @@
*/
synchronized
void closeNestedAppenders() {
- Enumeration enum = this.getAllAppenders();
- if(enum != null) {
- while(enum.hasMoreElements()) {
- Appender a = (Appender) enum.nextElement();
+ Enumeration enumeration = this.getAllAppenders();
+ if(enumeration != null) {
+ while(enumeration.hasMoreElements()) {
+ Appender a = (Appender) enumeration.nextElement();
if(a instanceof AppenderAttachable) {
a.close();
}
@@ -245,6 +250,60 @@
}
}
+ /**
+ * Log a message with the <code>DEBUG</code> level with message formatting
+ * done according to the value of <code>messagePattern</code> and
+ * <code>arg</code> parameters.
+ * <p>
+ * This form avoids superflous parameter construction. Whenever possible,
+ * you should use this form instead of constructing the message parameter
+ * using string concatenation.
+ *
+ * @param messagePattern The message pattern which will be parsed and formatted
+ * @param arg The argument to replace the formatting element, i,e,
+ * the '{}' pair within <code>messagePattern</code>.
+ * @since 1.2.10
+ */
+ public void debug(Object messagePattern, Object arg) {
+ if (repository.isDisabled(Level.DEBUG_INT)) {
+ return;
+ }
+
+ if (Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel())) {
+ if (messagePattern instanceof String){
+ String msgStr = (String) messagePattern;
+ msgStr = MessageFormatter.format(msgStr, arg);
+ forcedLog(FQCN, Level.DEBUG, msgStr, null);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should never happen.
+ forcedLog(FQCN, Level.DEBUG, messagePattern, null);
+ }
+ }
+ }
+
+ /**
+ * Log a message with the <code>DEBUG</code> level with message formatting
+ * done according to the messagePattern and the arguments arg1 and arg2.
+ * <p>
+ * This form avoids superflous parameter construction. Whenever possible,
+ * you should use this form instead of constructing the message parameter
+ * using string concatenation.
+ *
+ * @param messagePattern The message pattern which will be parsed and formatted
+ * @param arg1 The first argument to replace the first formatting element
+ * @param arg2 The second argument to replace the second formatting element
+ * @since 1.2.10
+ */
+ public void debug(String messagePattern, Object arg1, Object arg2) {
+ if (repository.isDisabled(Level.DEBUG_INT)) {
+ return;
+ }
+ if (Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel())) {
+ messagePattern = MessageFormatter.format(messagePattern, arg1, arg2);
+ forcedLog(FQCN, Level.DEBUG, messagePattern, null);
+ }
+ }
/**
Log a message object with the <code>DEBUG</code> level including
@@ -289,6 +348,62 @@
forcedLog(FQCN, Level.ERROR, message, null);
}
+
+/**
+ * Log a message with the <code>ERROR</code> level with message formatting
+ * done according to the value of <code>messagePattern</code> and
+ * <code>arg</code> parameters.
+ * <p>
+ * This form avoids superflous parameter construction. Whenever possible,
+ * you should use this form instead of constructing the message parameter
+ * using string concatenation.
+ *
+ * @param messagePattern The message pattern which will be parsed and formatted
+ * @param arg The argument to replace the formatting element, i,e,
+ * the '{}' pair within <code>messagePattern</code>.
+ * @since 1.2.10
+ */
+ public void error(Object messagePattern, Object arg) {
+ if (repository.isDisabled(Level.ERROR_INT)) {
+ return;
+ }
+
+ if (Level.ERROR.isGreaterOrEqual(this.getEffectiveLevel())) {
+ if (messagePattern instanceof String){
+ String msgStr = (String) messagePattern;
+ msgStr = MessageFormatter.format(msgStr, arg);
+ forcedLog(FQCN, Level.ERROR, msgStr, null);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should never happen.
+ forcedLog(FQCN, Level.ERROR, messagePattern, null);
+ }
+ }
+ }
+
+ /**
+ * Log a message with the <code>ERROR</code> level with message formatting
+ * done according to the messagePattern and the arguments arg1 and arg2.
+ * <p>
+ * This form avoids superflous parameter construction. Whenever possible,
+ * you should use this form instead of constructing the message parameter
+ * using string concatenation.
+ *
+ * @param messagePattern The message pattern which will be parsed and formatted
+ * @param arg1 The first argument to replace the first formatting element
+ * @param arg2 The second argument to replace the second formatting element
+ * @since 1.2.10
+ */
+ public void error(String messagePattern, Object arg1, Object arg2) {
+ if (repository.isDisabled(Level.ERROR_INT)) {
+ return;
+ }
+ if (Level.ERROR.isGreaterOrEqual(this.getEffectiveLevel())) {
+ messagePattern = MessageFormatter.format(messagePattern, arg1, arg2);
+ forcedLog(FQCN, Level.ERROR, messagePattern, null);
+ }
+ }
+
/**
Log a message object with the <code>ERROR</code> level including
the stack trace of the {@link Throwable} <code>t</code> passed as
@@ -315,7 +430,7 @@
@deprecated Please use {@link LogManager#exists} instead.
- @version 0.8.5 */
+ @since 0.8.5 */
public
static
Logger exists(String name) {
@@ -431,9 +546,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) {
@@ -497,40 +613,20 @@
/**
- Retrieve a category with named as the <code>name</code>
- parameter. If the named category already exists, then the
- existing instance will be reutrned. Otherwise, a new instance is
- created.
-
- By default, categories do not have a set level but inherit
- it from the hierarchy. This is one of the central features of
- log4j.
-
- <b>Deprecated</b> Please use {@link Logger#getLogger(String)}
- instead.
-
- @param name The name of the category to retrieve. */
+ * @deprecated Make sure to use {@link Logger#getLogger(String)} instead.
+ */
public
static
Category getInstance(String name) {
- nooptimize++;
return LogManager.getLogger(name);
}
/**
- Shorthand for <code>getInstance(clazz.getName())</code>.
-
- @param clazz The name of <code>clazz</code> will be used as the
- name of the category to retrieve. See {@link
- #getInstance(String)} for more detailed information.
-
- <b>Deprecated</b> Please use {@link Logger#getLogger(Class)} instead.
-
- @since 1.0 */
+ * @deprecated Please make sure to use {@link Logger#getLogger(Class)} instead.
+ */
public
static
Category getInstance(Class clazz) {
- nooptimize++;
return LogManager.getLogger(clazz);
}
@@ -581,16 +677,7 @@
/**
- Return the root of the default category hierrachy.
-
- <p>The root category is always instantiated and available. It's
- name is "root".
-
- <p>Nevertheless, calling {@link #getInstance
- Category.getInstance("root")} does not retrieve the root category
- but a category just under root named "root".
-
- <b>Deprecated</b> Use {@link Logger#getRootLogger()} instead.
+ * @deprecated Please use {@link Logger#getRootLogger()} instead.
*/
final
public
@@ -679,6 +766,60 @@
}
/**
+ * Log a message with the <code>INFO</code> level with message formatting
+ * done according to the value of <code>messagePattern</code> and
+ * <code>arg</code> parameters.
+ * <p>
+ * This form avoids superflous parameter construction. Whenever possible,
+ * you should use this form instead of constructing the message parameter
+ * using string concatenation.
+ *
+ * @param messagePattern The message pattern which will be parsed and formatted
+ * @param arg The argument to replace the formatting element, i,e,
+ * the '{}' pair within <code>messagePattern</code>.
+ * @since 1.2.10
+ */
+ public void info(Object messagePattern, Object arg) {
+ if (repository.isDisabled(Level.INFO_INT)) {
+ return;
+ }
+
+ if (Level.INFO.isGreaterOrEqual(this.getEffectiveLevel())) {
+ if (messagePattern instanceof String){
+ String msgStr = (String) messagePattern;
+ msgStr = MessageFormatter.format(msgStr, arg);
+ forcedLog(FQCN, Level.INFO, msgStr, null);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should never happen.
+ forcedLog(FQCN, Level.INFO, messagePattern, null);
+ }
+ }
+ }
+
+ /**
+ * Log a message with the <code>INFO</code> level with message formatting
+ * done according to the messagePattern and the arguments arg1 and arg2.
+ * <p>
+ * This form avoids superflous parameter construction. Whenever possible,
+ * you should use this form instead of constructing the message parameter
+ * using string concatenation.
+ *
+ * @param messagePattern The message pattern which will be parsed and formatted
+ * @param arg1 The first argument to replace the first formatting element
+ * @param arg2 The second argument to replace the second formatting element
+ * @since 1.2.10
+ */
+ public void info(String messagePattern, Object arg1, Object arg2) {
+ if (repository.isDisabled(Level.INFO_INT)) {
+ return;
+ }
+ if (Level.INFO.isGreaterOrEqual(this.getEffectiveLevel())) {
+ messagePattern = MessageFormatter.format(messagePattern, arg1, arg2);
+ forcedLog(FQCN, Level.INFO, messagePattern, null);
+ }
+ }
+ /**
Log a message object with the <code>INFO</code> level including
the stack trace of the {@link Throwable} <code>t</code> passed as
parameter.
@@ -777,6 +918,33 @@
return Level.INFO.isGreaterOrEqual(this.getEffectiveLevel());
}
+ /**
+ Check whether this category is enabled for the info Level.
+ See also {@link #isDebugEnabled}.
+
+ @return boolean - <code>true</code> if this category is enabled
+ for level WARN, <code>false</code> otherwise.
+ @since 1.2.10
+ */
+ public boolean isWarnEnabled() {
+ if(repository.isDisabled(Level.WARN_INT))
+ return false;
+ return Level.WARN.isGreaterOrEqual(this.getEffectiveLevel());
+ }
+
+ /**
+ Check whether this category is enabled for the info Level.
+ See also {@link #isDebugEnabled}.
+
+ @return boolean - <code>true</code> if this category is enabled
+ for level ERROR, <code>false</code> otherwise.
+ @since 1.2.10
+ */
+ public boolean isErrorEnabled() {
+ if(repository.isDisabled(Level.ERROR_INT))
+ return false;
+ return Level.ERROR.isGreaterOrEqual(this.getEffectiveLevel());
+ }
/**
Log a localized message. The user supplied parameter
@@ -1023,6 +1191,60 @@
forcedLog(FQCN, Level.WARN, message, null);
}
+ /**
+ * Log a message with the <code>WARN</code> level with message formatting
+ * done according to the value of <code>messagePattern</code> and
+ * <code>arg</code> parameters.
+ * <p>
+ * This form avoids superflous parameter construction. Whenever possible,
+ * you should use this form instead of constructing the message parameter
+ * using string concatenation.
+ *
+ * @param messagePattern The message pattern which will be parsed and formatted
+ * @param arg The argument to replace the formatting element, i,e,
+ * the '{}' pair within <code>messagePattern</code>.
+ * @since 1.2.10
+ */
+ public void warn(Object messagePattern, Object arg) {
+ if (repository.isDisabled(Level.WARN_INT)) {
+ return;
+ }
+
+ if (Level.WARN.isGreaterOrEqual(this.getEffectiveLevel())) {
+ if (messagePattern instanceof String){
+ String msgStr = (String) messagePattern;
+ msgStr = MessageFormatter.format(msgStr, arg);
+ forcedLog(FQCN, Level.WARN, msgStr, null);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should never happen.
+ forcedLog(FQCN, Level.WARN, messagePattern, null);
+ }
+ }
+ }
+ /**
+ * Log a message with the <code>WARN</code> level with message formatting
+ * done according to the messagePattern and the arguments arg1 and arg2.
+ * <p>
+ * This form avoids superflous parameter construction. Whenever possible,
+ * you should use this form instead of constructing the message parameter
+ * using string concatenation.
+ *
+ * @param messagePattern The message pattern which will be parsed and formatted
+ * @param arg1 The first argument to replace the first formatting element
+ * @param arg2 The second argument to replace the second formatting element
+ * @since 1.2.10
+ */
+ public void warn(String messagePattern, Object arg1, Object arg2) {
+ if (repository.isDisabled(Level.WARN_INT)) {
+ return;
+ }
+ if (Level.WARN.isGreaterOrEqual(this.getEffectiveLevel())) {
+ messagePattern = MessageFormatter.format(messagePattern, arg1, arg2);
+ forcedLog(FQCN, Level.WARN, messagePattern, null);
+ }
+ }
+
/**
Log a message with the <code>WARN</code> level including the
stack trace of the {@link Throwable} <code>t</code> passed as
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..c1de794 100644
--- a/src/java/org/apache/log4j/FileAppender.java
+++ b/src/java/org/apache/log4j/FileAppender.java
@@ -20,24 +20,24 @@
// 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
- variable is <code>true</code>, meaning that by default a
- <code>FileAppender</code> will append to an existing file and
- not truncate it.
-
- <p>This option is meaningful only if the FileAppender opens the
- file.
- */
+ /** Controls file truncatation. The default value for this variable
+ * is <code>true</code>, meaning that by default a
+ * <code>FileAppender</code> will append to an existing file and not
+ * truncate it.
+ *
+ * <p>This option is meaningful only if the FileAppender opens the
+ * file.
+ */
protected boolean fileAppend = true;
/**
@@ -49,7 +49,8 @@
protected boolean bufferedIO = false;
/**
- How big should the IO buffer be? Default is 8K. */
+ * Determines the size of IO buffer be. Default is 8K.
+ */
protected int bufferSize = 8*1024;
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/LogManager.java b/src/java/org/apache/log4j/LogManager.java
index 0189b8a..d01b99e 100644
--- a/src/java/org/apache/log4j/LogManager.java
+++ b/src/java/org/apache/log4j/LogManager.java
@@ -11,7 +11,7 @@
import org.apache.log4j.spi.LoggerFactory;
import org.apache.log4j.spi.RepositorySelector;
import org.apache.log4j.spi.DefaultRepositorySelector;
-import org.apache.log4j.spi.RootCategory;
+import org.apache.log4j.spi.RootLogger;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.helpers.LogLog;
@@ -23,84 +23,40 @@
import java.util.Enumeration;
/**
- Use the <code>LogManager</code> to retreive instances of {@link Logger}.
-
- @author Ceki Gülcü
-*/
+ * Use the <code>LogManager</code> class to retreive {@link Logger}
+ * instances or to operate on the current {@link
+ * LoggerRepository}. When the <code>LogManager</code> class is loaded
+ * into memory the default initalzation procedure is inititated. The
+ * default intialization procedure</a> is described in the <a
+ * href="../../../../manual.html#defaultInit">short log4j manual</a>.
+ *
+ * @author Ceki Gülcü */
public class LogManager {
/**
- This string constant is set to <b>log4j.properties</b> the name
- of the file that will be searched by default in classpath. If the
- file can be found, then it is fed to the {@link
- PropertyConfigurator}.
-
- See also {@link #DEFAULT_CONFIGURATION_KEY} for a more general
- alternative.
-
- <p>See also the full description of <a
- href="../../../../manual.html#defaultInit">default
- intialization</a> procedure.
-
- @since 0.8.5 */
- static public final String DEFAULT_CONFIGURATION_FILE = "log4j.properties";
-
- /**
- This string constant is set to <b>log4j.configuration</b>.
-
- <p>It corresponds to name of a system property that, if set,
- specifies the name of the resource containing the properties file
- or {@link URL} with which log4j should configure itself. See
- {@link OptionConverter#selectAndConfigure} for more detailed
- information on the processing of this option.
-
- <p>Setting the <b>log4j.configuration</b> system property
- overrides the default search for the file <b>log4j.properties</b>.
-
- <p>Note that all property keys are case sensitive.
-
- <p>See also the full description of <a
- href="../../../../manual.html#defaultInit">default
- intialization</a> procedure.
-
- @since 1.0 */
- static final public String DEFAULT_CONFIGURATION_KEY="log4j.configuration";
-
- /**
- This string constant is set to <b>log4j.configuratorClass</b>.
-
- <p>It corresponds to name of a system property that, if set,
- specifies the class name to use to automatically configure
- log4j. See {@link OptionConverter#selectAndConfigure} for more
- detailed information on the processing of this option.
-
- <p>Setting the <b>log4j.configuration</b> system property
- overrides the default search for the file <b>log4j.properties</b>.
-
- <p>Note that all property keys are case sensitive.
-
- <p>See also the full description of <a
- href="../../../../manual.html#defaultInit">default
- intialization</a> procedure.
+ * @deprecated This variable is for internal use only. It will
+ * become package protected in future versions.
+ * */
+ static public final String DEFAULT_CONFIGURATION_FILE = "log4j.properties";
+
+ static final String DEFAULT_XML_CONFIGURATION_FILE = "log4j.xml";
- @since 1.2 */
- static final public String CONFIGURATOR_CLASS_KEY="log4j.configuratorClass";
+ /**
+ * @deprecated This variable is for internal use only. It will
+ * become private in future versions.
+ * */
+ static final public String DEFAULT_CONFIGURATION_KEY="log4j.configuration";
/**
- Setting the system property <b>log4j.defaultInitOverride</b> to
- "true" or any other value than "false" will skip default
- configuration process.
+ * @deprecated This variable is for internal use only. It will
+ * become private in future versions.
+ * */
+ static final public String CONFIGURATOR_CLASS_KEY="log4j.configuratorClass";
- <p>The current value of the DEFAULT_INIT_OVERRIDE_KEY string
- constant is <b>log4j.defaultInitOverride</b>.
-
- <p>See also the full description of <a
- href="../../../../manual.html#defaultInit">default
- intialization</a> procedure.
-
- <p>Note that all property keys are case sensitive.
-
- @since 0.8.5 */
+ /**
+ * @deprecated This variable is for internal use only. It will
+ * become private in future versions.
+ */
public static final String DEFAULT_INIT_OVERRIDE_KEY =
"log4j.defaultInitOverride";
@@ -110,42 +66,54 @@
static {
// By default we use a DefaultRepositorySelector which always returns 'h'.
- Hierarchy h = new Hierarchy(new RootCategory((Level) Level.DEBUG));
+ Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));
repositorySelector = new DefaultRepositorySelector(h);
/** Search for the properties file log4j.properties in the CLASSPATH. */
String override =OptionConverter.getSystemProperty(DEFAULT_INIT_OVERRIDE_KEY,
null);
- // if there is no default init override, them get the resource
+ // if there is no default init override, then get the resource
// specified by the user or the default config file.
if(override == null || "false".equalsIgnoreCase(override)) {
- String resource = OptionConverter.getSystemProperty(
- DEFAULT_CONFIGURATION_KEY,
- DEFAULT_CONFIGURATION_FILE);
+
+ String configurationOptionStr = OptionConverter.getSystemProperty(
+ DEFAULT_CONFIGURATION_KEY,
+ null);
String configuratorClassName = OptionConverter.getSystemProperty(
CONFIGURATOR_CLASS_KEY,
null);
URL url = null;
- try {
- // so, resource is not a URL:
- // attempt to get the resource from the class path
- url = new URL(resource);
- } catch (MalformedURLException ex) {
- url = Loader.getResource(resource);
- }
+
+ // if the user has not specified the log4j.configuration
+ // property, we search first for the file "log4j.xml" and then
+ // "log4j.properties"
+ if(configurationOptionStr == null) {
+ url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE);
+ if(url == null) {
+ url = Loader.getResource(DEFAULT_CONFIGURATION_FILE);
+ }
+ } else {
+ try {
+ url = new URL(configurationOptionStr);
+ } catch (MalformedURLException ex) {
+ // so, resource is not a URL:
+ // attempt to get the resource from the class path
+ url = Loader.getResource(configurationOptionStr);
+ }
+ }
// If we have a non-null url, then delegate the rest of the
// configuration to the OptionConverter.selectAndConfigure
// method.
if(url != null) {
- LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");
+ LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");
OptionConverter.selectAndConfigure(url, configuratorClassName,
LogManager.getLoggerRepository());
} else {
- LogLog.debug("Could not find resource: ["+resource+"].");
+ LogLog.debug("Could not find resource: ["+configurationOptionStr+"].");
}
}
}
diff --git a/src/java/org/apache/log4j/Logger.java b/src/java/org/apache/log4j/Logger.java
index aab789d..369d952 100644
--- a/src/java/org/apache/log4j/Logger.java
+++ b/src/java/org/apache/log4j/Logger.java
@@ -8,6 +8,7 @@
package org.apache.log4j;
import org.apache.log4j.spi.LoggerFactory;
+import org.slf4j.ULogger;
/**
@@ -17,7 +18,7 @@
@since log4j 1.2
@author Ceki Gülcü */
-public class Logger extends Category {
+public class Logger extends Category implements ULogger {
/**
The fully qualified name of the Level class. See also the
@@ -77,7 +78,16 @@
//}
/**
- Retrieve a logger by name.
+ * Retrieve a logger named according to the value of the
+ * <code>name</code> parameter. If the named logger already exists,
+ * then the existing instance will be returned. Otherwise, a new
+ * instance is created.
+ *
+ * <p>By default, loggers do not have a set level but inherit it
+ * from their neareast ancestor with a set level. This is one of the
+ * central features of log4j.
+ *
+ * @param name The name of the logger to retrieve.
*/
static
public
@@ -86,7 +96,11 @@
}
/**
- Same as calling <code>getLogger(clazz.getName())</code>.
+ * Shorthand for <code>getLogger(clazz.getName())</code>.
+ *
+ * @param clazz The name of <code>clazz</code> will be used as the
+ * name of the logger to retrieve. See {@link #getLogger(String)}
+ * for more detailed information.
*/
static
public
@@ -96,7 +110,15 @@
/**
- Retrieve the root logger.
+ * Return the root logger for the current logger repository.
+ * <p>
+ * The {@link #getName Logger.getName()} method for the root logger always returns
+ * stirng value: "root". However, calling
+ * <code>Logger.getLogger("root")</code> does not retrieve the root
+ * logger but a logger just under root named "root".
+ * <p>
+ * In other words, calling this method is the only way to retrieve the
+ * root logger.
*/
public
static
diff --git a/src/java/org/apache/log4j/MDC.java b/src/java/org/apache/log4j/MDC.java
index 002b399..9fd93ff 100644
--- a/src/java/org/apache/log4j/MDC.java
+++ b/src/java/org/apache/log4j/MDC.java
@@ -88,11 +88,10 @@
/**
- Get the current thread's MDC as a hashtable.
- */
- public
- static
- Hashtable getContext() {
+ * Get the current thread's MDC as a hashtable. This method is
+ * intended to be used internally.
+ * */
+ public static Hashtable getContext() {
return mdc.getContext0();
}
@@ -104,8 +103,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 +116,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 +129,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..ee34b21 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
@@ -205,10 +206,10 @@
}
/**
- Get the current nesting depth of this diagnostic context.
-
- @see #setMaxDepth
- @since 0.7.5
+ * Get the current nesting depth of this diagnostic context.
+ *
+ * @see #setMaxDepth
+ * @since 0.7.5
*/
public
static
@@ -239,13 +240,13 @@
int misses = 0;
v = new Vector();
- Enumeration enum = ht.keys();
+ Enumeration enumeration = ht.keys();
// We give up after 4 straigt missses. That is 4 consecutive
// inspected threads in 'ht' that turn out to be alive.
// The higher the proportion on dead threads in ht, the higher the
// chances of removal.
- while(enum.hasMoreElements() && (misses <= 4)) {
- Thread t = (Thread) enum.nextElement();
+ while(enumeration.hasMoreElements() && (misses <= 4)) {
+ Thread t = (Thread) enumeration.nextElement();
if(t.isAlive()) {
misses++;
} else {
diff --git a/src/java/org/apache/log4j/Priority.java b/src/java/org/apache/log4j/Priority.java
index fd2fe98..61e82a4 100644
--- a/src/java/org/apache/log4j/Priority.java
+++ b/src/java/org/apache/log4j/Priority.java
@@ -9,10 +9,10 @@
// Contributors: Kitching Simon <Simon.Kitching@orange.ch>
package org.apache.log4j;
-
+
/**
<font color="#AA4444">Refrain from using this class directly, use
- the {@link Level} class instead.</font>
+ the {@link Level} class instead</font>.
@author Ceki Gülcü */
public class Priority {
@@ -31,31 +31,28 @@
public final static int ALL_INT = Integer.MIN_VALUE;
/**
- The <code>FATAL</code> level designates very severe error
- events that will presumably lead the application to abort.
+ * @deprecated Use {@link Level#FATAL} instead.
*/
final static public Priority FATAL = new Level(FATAL_INT, "FATAL", 0);
/**
- The <code>ERROR</code> level designates error events that
- might still allow the application to continue running. */
+ * @deprecated Use {@link Level#ERROR} instead.
+ */
final static public Priority ERROR = new Level(ERROR_INT, "ERROR", 3);
/**
- The <code>WARN</code> level designates potentially harmful situations.
- */
+ * @deprecated Use {@link Level#WARN} instead.
+ */
final static public Priority WARN = new Level(WARN_INT, "WARN", 4);
/**
- The <code>INFO</code> level designates informational messages
- that highlight the progress of the application at coarse-grained
- level. */
+ * @deprecated Use {@link Level#INFO} instead.
+ */
final static public Priority INFO = new Level(INFO_INT, "INFO", 6);
/**
- The <code>DEBUG</code> priority designates fine-grained
- informational events that are most useful to debug an
- application. */
+ * @deprecated Use {@link Level#DEBUG} instead.
+ */
final static public Priority DEBUG = new Level(DEBUG_INT, "DEBUG", 7);
@@ -141,12 +138,7 @@
}
/**
- Convert the string passed as argument to a priority. If the
- conversion fails, then this method returns {@link #DEBUG}.
-
- @deprecated Please use the {@link Level#toLevel(String)} method instead.}
-
-
+ * @deprecated Please use the {@link Level#toLevel(String)} method instead.
*/
public
static
@@ -155,10 +147,8 @@
}
/**
- Convert an integer passed as argument to a priority. If the
- conversion fails, then this method returns {@link #DEBUG}.
-
- */
+ * @deprecated Please use the {@link Level#toLevel(int)} method instead.
+ */
public
static
Priority toPriority(int val) {
@@ -166,8 +156,7 @@
}
/**
- Convert an integer passed as argument to a priority. If the
- conversion fails, then this method returns the specified default.
+ * @deprecated Please use the {@link Level#toLevel(int, Level)} method instead.
*/
public
static
@@ -176,10 +165,8 @@
}
/**
- Convert the string passed as argument to a priority. If the
- conversion fails, then this method returns the value of
- <code>defaultPriority</code>.
- */
+ * @deprecated Please use the {@link Level#toLevel(String, Level)} method instead.
+ */
public
static
Priority toPriority(String sArg, Priority defaultPriority) {
diff --git a/src/java/org/apache/log4j/PropertyConfigurator.java b/src/java/org/apache/log4j/PropertyConfigurator.java
index c15d438..b6b99b6 100644
--- a/src/java/org/apache/log4j/PropertyConfigurator.java
+++ b/src/java/org/apache/log4j/PropertyConfigurator.java
@@ -33,8 +33,8 @@
import java.util.Hashtable;
/**
- Extends {@link BasicConfigurator} to provide configuration from an
- external file. See <b>{@link #doConfigure(String, LoggerRepository)}</b> for the
+ Allows the configuration of log4j from an external file. See
+ <b>{@link #doConfigure(String, LoggerRepository)}</b> for the
expected format.
<p>It is sometimes useful to see how log4j is reading configuration
@@ -100,7 +100,7 @@
/**
Read configuration from a file. <b>The existing configuration is
not cleared nor reset.</b> If you require a different behavior,
- then call {@link BasicConfigurator#resetConfiguration
+ then call {@link LogManager#resetConfiguration
resetConfiguration} method before calling
<code>doConfigure</code>.
@@ -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.
@@ -507,9 +508,9 @@
*/
protected
void parseCatsAndRenderers(Properties props, LoggerRepository hierarchy) {
- Enumeration enum = props.propertyNames();
- while(enum.hasMoreElements()) {
- String key = (String) enum.nextElement();
+ Enumeration enumeration = props.propertyNames();
+ while(enumeration.hasMoreElements()) {
+ String key = (String) enumeration.nextElement();
if(key.startsWith(CATEGORY_PREFIX) || key.startsWith(LOGGER_PREFIX)) {
String loggerName = null;
if(key.startsWith(CATEGORY_PREFIX)) {
@@ -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..ceb526a 100644
--- a/src/java/org/apache/log4j/TTCCLayout.java
+++ b/src/java/org/apache/log4j/TTCCLayout.java
@@ -157,9 +157,7 @@
<p>Time, thread, category and diagnostic context are printed
depending on options.
- @param category
- @param level
- @param message
+ @param event The event to format
*/
public
@@ -175,11 +173,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/ControlPanel.java b/src/java/org/apache/log4j/chainsaw/ControlPanel.java
index 741edec..d9169e7 100644
--- a/src/java/org/apache/log4j/chainsaw/ControlPanel.java
+++ b/src/java/org/apache/log4j/chainsaw/ControlPanel.java
@@ -18,7 +18,7 @@
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.Priority;
/**
@@ -28,8 +28,8 @@
*/
class ControlPanel extends JPanel {
/** use the log messages **/
- private static final Category LOG =
- Category.getInstance(ControlPanel.class);
+ private static final Logger LOG =
+ Logger.getLogger(ControlPanel.class);
/**
* Creates a new <code>ControlPanel</code> instance.
@@ -61,7 +61,7 @@
add(label);
c.gridy++;
- label = new JLabel("Filter Category:");
+ label = new JLabel("Filter Logger:");
gridbag.setConstraints(label, c);
add(label);
diff --git a/src/java/org/apache/log4j/chainsaw/DetailPanel.java b/src/java/org/apache/log4j/chainsaw/DetailPanel.java
index c051987..9b28748 100644
--- a/src/java/org/apache/log4j/chainsaw/DetailPanel.java
+++ b/src/java/org/apache/log4j/chainsaw/DetailPanel.java
@@ -17,7 +17,7 @@
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
/**
* A panel for showing a stack trace.
@@ -29,8 +29,8 @@
implements ListSelectionListener
{
/** used to log events **/
- private static final Category LOG =
- Category.getInstance(DetailPanel.class);
+ private static final Logger LOG =
+ Logger.getLogger(DetailPanel.class);
/** used to format the logging event **/
private static final MessageFormat FORMATTER = new MessageFormat(
@@ -38,7 +38,7 @@
" <b>Priority:</b> <code>{1}</code>" +
" <b>Thread:</b> <code>{2}</code>" +
" <b>NDC:</b> <code>{3}</code>" +
- "<br><b>Category:</b> <code>{4}</code>" +
+ "<br><b>Logger:</b> <code>{4}</code>" +
"<br><b>Location:</b> <code>{5}</code>" +
"<br><b>Message:</b>" +
"<pre>{6}</pre>" +
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/ExitAction.java b/src/java/org/apache/log4j/chainsaw/ExitAction.java
index 8fb0ce8..c8eda2a 100644
--- a/src/java/org/apache/log4j/chainsaw/ExitAction.java
+++ b/src/java/org/apache/log4j/chainsaw/ExitAction.java
@@ -8,7 +8,7 @@
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
/**
* Encapsulates the action to exit.
@@ -20,7 +20,7 @@
extends AbstractAction
{
/** use to log messages **/
- private static final Category LOG = Category.getInstance(ExitAction.class);
+ private static final Logger LOG = Logger.getLogger(ExitAction.class);
/** The instance to share **/
public static final ExitAction INSTANCE = new ExitAction();
diff --git a/src/java/org/apache/log4j/chainsaw/LoadXMLAction.java b/src/java/org/apache/log4j/chainsaw/LoadXMLAction.java
index 9912e7d..cc91139 100644
--- a/src/java/org/apache/log4j/chainsaw/LoadXMLAction.java
+++ b/src/java/org/apache/log4j/chainsaw/LoadXMLAction.java
@@ -16,7 +16,7 @@
import javax.swing.JOptionPane;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
@@ -31,8 +31,7 @@
extends AbstractAction
{
/** use to log messages **/
- private static final Category LOG =
- Category.getInstance(LoadXMLAction.class);
+ private static final Logger LOG = Logger.getLogger(LoadXMLAction.class);
/** the parent frame **/
private final JFrame mParent;
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/Main.java b/src/java/org/apache/log4j/chainsaw/Main.java
index b67a9ae..9dacd28 100644
--- a/src/java/org/apache/log4j/chainsaw/Main.java
+++ b/src/java/org/apache/log4j/chainsaw/Main.java
@@ -23,7 +23,7 @@
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
/**
@@ -41,7 +41,7 @@
public static final String PORT_PROP_NAME = "chainsaw.port";
/** use to log messages **/
- private static final Category LOG = Category.getInstance(Main.class);
+ private static final Logger LOG = Logger.getLogger(Main.class);
/**
@@ -162,7 +162,7 @@
/** initialise log4j **/
private static void initLog4J() {
final Properties props = new Properties();
- props.setProperty("log4j.rootCategory", "DEBUG, A1");
+ props.setProperty("log4j.rootLogger", "DEBUG, A1");
props.setProperty("log4j.appender.A1",
"org.apache.log4j.ConsoleAppender");
props.setProperty("log4j.appender.A1.layout",
diff --git a/src/java/org/apache/log4j/chainsaw/MyTableModel.java b/src/java/org/apache/log4j/chainsaw/MyTableModel.java
index d1af076..b0d8898 100644
--- a/src/java/org/apache/log4j/chainsaw/MyTableModel.java
+++ b/src/java/org/apache/log4j/chainsaw/MyTableModel.java
@@ -16,7 +16,7 @@
import java.util.TreeSet;
import javax.swing.table.AbstractTableModel;
import org.apache.log4j.Priority;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
/**
* Represents a list of <code>EventDetails</code> objects that are sorted on
@@ -29,8 +29,7 @@
{
/** used to log messages **/
- private static final Category LOG =
- Category.getInstance(MyTableModel.class);
+ private static final Logger LOG = Logger.getLogger(MyTableModel.class);
/** use the compare logging events **/
private static final Comparator MY_COMP = new Comparator()
diff --git a/src/java/org/apache/log4j/chainsaw/XMLFileHandler.java b/src/java/org/apache/log4j/chainsaw/XMLFileHandler.java
index 5ce82d0..5944da3 100644
--- a/src/java/org/apache/log4j/chainsaw/XMLFileHandler.java
+++ b/src/java/org/apache/log4j/chainsaw/XMLFileHandler.java
@@ -7,7 +7,7 @@
package org.apache.log4j.chainsaw;
import java.util.StringTokenizer;
-import org.apache.log4j.Priority;
+import org.apache.log4j.Level;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
@@ -37,13 +37,11 @@
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 **/
- private Priority mPriority;
+ /** the priority (level) of the event **/
+ private Level mLevel;
/** the category of the event **/
private String mCategoryName;
/** the NDC for the event **/
@@ -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");
- mPriority = Priority.toPriority(aAtts.getValue("level"));
+ mCategoryName = aAtts.getValue("logger");
+ mLevel = Level.toLevel(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;
}
}
@@ -143,7 +136,7 @@
/** Add an event to the model **/
private void addEvent() {
mModel.addEvent(new EventDetails(mTimeStamp,
- mPriority,
+ mLevel,
mCategoryName,
mNDC,
mThreadName,
@@ -156,7 +149,7 @@
/** Reset the data for an event **/
private void resetData() {
mTimeStamp = 0;
- mPriority = null;
+ mLevel = null;
mCategoryName = null;
mNDC = null;
mThreadName = null;
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..77cdb5b 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;
@@ -46,8 +46,8 @@
}
/**
- Returns true if the specified appender name is considered to have
- been generated, i.e. if it is of the form A[0-9]+.
+ * Returns true if the specified appender name is considered to have
+ * been generated, that is, if it is of the form A[0-9]+.
*/
protected
boolean isGenAppName(String name) {
@@ -67,16 +67,16 @@
*/
public
void print(PrintWriter out) {
- printOptions(out, Category.getRoot());
+ printOptions(out, Logger.getRootLogger());
- Enumeration cats = Category.getCurrentCategories();
+ Enumeration cats = LogManager.getCurrentLoggers();
while (cats.hasMoreElements()) {
- printOptions(out, (Category) cats.nextElement());
+ printOptions(out, (Logger) cats.nextElement());
}
}
protected
- void printOptions(PrintWriter out, Category cat) {
+ void printOptions(PrintWriter out, Logger cat) {
Enumeration appenders = cat.getAllAppenders();
Level prio = cat.getLevel();
String appenderString = (prio == null ? "" : prio.toString());
@@ -100,9 +100,9 @@
}
appenderString += ", " + name;
}
- String catKey = (cat == Category.getRoot())
- ? "log4j.rootCategory"
- : "log4j.category." + cat.getName();
+ String catKey = (cat == Logger.getRootLogger())
+ ? "log4j.rootLogger"
+ : "log4j.logger." + cat.getName();
if (appenderString != "") {
out.println(catKey + "=" + appenderString);
}
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/BoundedFIFO.java b/src/java/org/apache/log4j/helpers/BoundedFIFO.java
index 2a17966..4ef8e4a 100644
--- a/src/java/org/apache/log4j/helpers/BoundedFIFO.java
+++ b/src/java/org/apache/log4j/helpers/BoundedFIFO.java
@@ -82,8 +82,8 @@
}
/**
- Return <code>true</code> if the buffer is full, i.e. of the
- number of elements in the buffer equals the buffer size. */
+ Return <code>true</code> if the buffer is full, that is, whether
+ the number of elements in the buffer equals the buffer size. */
public
boolean isFull() {
return numElements == maxSize;
diff --git a/src/java/org/apache/log4j/helpers/Loader.java b/src/java/org/apache/log4j/helpers/Loader.java
index 222c2cc..4698ca6 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,6 +40,10 @@
java1 = false;
}
}
+ String ignoreTCLProp = OptionConverter.getSystemProperty("log4j.ignoreTCL", null);
+ if(ignoreTCLProp != null) {
+ ignoreTCL = OptionConverter.toBoolean(ignoreTCLProp, true);
+ }
}
/**
@@ -54,43 +64,37 @@
built-in class loader in JDK 1.1.
</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 +102,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 +115,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..d02b63e 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,40 @@
}
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) {
+ if(str == null) {
+ buf.append("");
+ return;
+ }
+
+ 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..c2ccaed 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>.
+ 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.
@@ -53,7 +58,7 @@
</ul>
- @author: Kevin Steppe (<A HREF="mailto:ksteppe@pacbell.net">ksteppe@pacbell.net</A>)
+ @author Kevin Steppe (<A HREF="mailto:ksteppe@pacbell.net">ksteppe@pacbell.net</A>)
*/
public class JDBCAppender extends org.apache.log4j.AppenderSkeleton
@@ -86,7 +91,7 @@
/**
* Stores the string given to the pattern layout for conversion into a SQL
* statement, eg: insert into LogTable (Thread, Class, Message) values
- * ("%t", "%c", "%m")
+ * ("%t", "%c", "%m").
*
* Be careful of quotes in your messages!
*
@@ -235,8 +240,12 @@
ErrorCode.FLUSH_FAILURE);
}
}
+
+ // remove from the buffer any events that were reported
buffer.removeAll(removes);
- //buffer.clear();
+
+ // clear the buffer of reported events
+ removes.clear();
}
@@ -247,10 +256,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/jmx/Agent.java b/src/java/org/apache/log4j/jmx/Agent.java
index 3049a91..68de333 100644
--- a/src/java/org/apache/log4j/jmx/Agent.java
+++ b/src/java/org/apache/log4j/jmx/Agent.java
@@ -6,12 +6,12 @@
import javax.management.MBeanServerFactory;
import com.sun.jdmk.comm.HtmlAdaptorServer;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
public class Agent {
- static Category log = Category.getInstance(Agent.class);
+ static Logger log = Logger.getLogger(Agent.class);
public Agent() {
}
diff --git a/src/java/org/apache/log4j/jmx/HierarchyDynamicMBean.java b/src/java/org/apache/log4j/jmx/HierarchyDynamicMBean.java
index 361409b..95097fd 100644
--- a/src/java/org/apache/log4j/jmx/HierarchyDynamicMBean.java
+++ b/src/java/org/apache/log4j/jmx/HierarchyDynamicMBean.java
@@ -93,7 +93,7 @@
public
ObjectName addLoggerMBean(String name) {
- Logger cat = Logger.exists(name);
+ Logger cat = LogManager.exists(name);
if(cat != null) {
return addLoggerMBean(cat);
diff --git a/src/java/org/apache/log4j/jmx/LoggerDynamicMBean.java b/src/java/org/apache/log4j/jmx/LoggerDynamicMBean.java
index 086f99c..ea3afd8 100644
--- a/src/java/org/apache/log4j/jmx/LoggerDynamicMBean.java
+++ b/src/java/org/apache/log4j/jmx/LoggerDynamicMBean.java
@@ -218,7 +218,7 @@
} else {
p = OptionConverter.toLevel(s, p);
}
- logger.setPriority(p);
+ logger.setLevel(p);
}
} else {
throw(new AttributeNotFoundException("Attribute " + name +
@@ -228,9 +228,9 @@
}
void appenderMBeanRegistration() {
- Enumeration enum = logger.getAllAppenders();
- while(enum.hasMoreElements()) {
- Appender appender = (Appender) enum.nextElement();
+ Enumeration enumeration = logger.getAllAppenders();
+ while(enumeration.hasMoreElements()) {
+ Appender appender = (Appender) enumeration.nextElement();
registerAppenderMBean(appender);
}
}
diff --git a/src/java/org/apache/log4j/jmx/T.java b/src/java/org/apache/log4j/jmx/T.java
deleted file mode 100644
index 2472474..0000000
--- a/src/java/org/apache/log4j/jmx/T.java
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-import org.apache.log4j.jmx.Agent;
-import org.apache.log4j.Category;
-import org.apache.log4j.BasicConfigurator;
-import org.apache.log4j.*;
-
-public class T {
-
-
- public static void main(String[] args) {
- Category cat = Category.getInstance(T.class);
- Layout layout = new PatternLayout("%r %p [%t] %c - %m%n");
- ConsoleAppender consoleAppender = new ConsoleAppender(layout);
-
- consoleAppender.setName("console");
- BasicConfigurator.configure(consoleAppender);
- Agent agent = new Agent();
- agent.start();
- }
-
-}
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/LogRecord.java b/src/java/org/apache/log4j/lf5/LogRecord.java
index 8d1cfa4..b8ab25a 100644
--- a/src/java/org/apache/log4j/lf5/LogRecord.java
+++ b/src/java/org/apache/log4j/lf5/LogRecord.java
@@ -350,7 +350,7 @@
/**
* Set the location in code where this LogRecord originated.
*
- * @param ndc A string containing location information.
+ * @param location A string containing location information.
*/
public void setLocation(String location) {
_location = location;
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/categoryexplorer/CategoryNodeEditor.java b/src/java/org/apache/log4j/lf5/viewer/categoryexplorer/CategoryNodeEditor.java
index fbb6a9b..369032e 100644
--- a/src/java/org/apache/log4j/lf5/viewer/categoryexplorer/CategoryNodeEditor.java
+++ b/src/java/org/apache/log4j/lf5/viewer/categoryexplorer/CategoryNodeEditor.java
@@ -241,9 +241,9 @@
protected int removeUnusedNodes() {
int count = 0;
CategoryNode root = _categoryModel.getRootCategoryNode();
- Enumeration enum = root.depthFirstEnumeration();
- while (enum.hasMoreElements()) {
- CategoryNode node = (CategoryNode) enum.nextElement();
+ Enumeration enumeration = root.depthFirstEnumeration();
+ while (enumeration.hasMoreElements()) {
+ CategoryNode node = (CategoryNode) enumeration.nextElement();
if (node.isLeaf() && node.getNumberOfContainedRecords() == 0
&& node.getParent() != null) {
_categoryModel.removeNodeFromParent(node);
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..a97adc4 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..803824f 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;
@@ -386,6 +386,6 @@
<code>false</code>. */
public
boolean isTriggeringEvent(LoggingEvent event) {
- return event.level.isGreaterOrEqual(Level.ERROR);
+ return event.getLevel().isGreaterOrEqual(Level.ERROR);
}
}
diff --git a/src/java/org/apache/log4j/net/SimpleSocketServer.java b/src/java/org/apache/log4j/net/SimpleSocketServer.java
index f8ca382..2fddf06 100644
--- a/src/java/org/apache/log4j/net/SimpleSocketServer.java
+++ b/src/java/org/apache/log4j/net/SimpleSocketServer.java
@@ -3,47 +3,49 @@
*
* 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;
import java.net.Socket;
import java.net.ServerSocket;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
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());
+ static Logger cat = Logger.getLogger(SimpleSocketServer.class);
static int port;
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..ddb4145 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,17 +193,20 @@
// First, close the previous connection if any.
cleanUp();
oos = new ObjectOutputStream(new Socket(address, port).getOutputStream());
- }
- catch(IOException e) {
- LogLog.error("Could not connect to remote log4j server at ["
- +address.getHostName()+"]. We will try again later.", e);
- fireConnector();
+ } catch(IOException e) {
+
+ String msg = "Could not connect to remote log4j server at ["
+ +address.getHostName()+"].";
+ if(reconnectionDelay > 0) {
+ msg += " We will try again later.";
+ fireConnector(); // fire the connector thread
+ }
+ LogLog.error(msg, e);
}
}
- public
- void append(LoggingEvent event) {
+ public void append(LoggingEvent event) {
if(event == null)
return;
@@ -234,8 +231,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 +255,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 +282,7 @@
/**
Returns value of the <b>RemoteHost</b> option.
*/
- public
- String getRemoteHost() {
+ public String getRemoteHost() {
return remoteHost;
}
@@ -297,16 +290,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 +306,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 +326,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 +364,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/SocketServer.java b/src/java/org/apache/log4j/net/SocketServer.java
index 4127258..b3f4d75 100644
--- a/src/java/org/apache/log4j/net/SocketServer.java
+++ b/src/java/org/apache/log4j/net/SocketServer.java
@@ -75,7 +75,7 @@
static String GENERIC = "generic";
static String CONFIG_FILE_EXT = ".lcf";
- static Category cat = Category.getInstance(SocketServer.class);
+ static Logger cat = Logger.getLogger(SocketServer.class);
static SocketServer server;
static int port;
@@ -167,7 +167,7 @@
File configFile = new File(dir, key+CONFIG_FILE_EXT);
if(configFile.exists()) {
- Hierarchy h = new Hierarchy(new RootCategory((Level) Priority.DEBUG));
+ Hierarchy h = new Hierarchy(new RootLogger((Level) Priority.DEBUG));
hierarchyMap.put(inetAddress, h);
new PropertyConfigurator().doConfigure(configFile.getAbsolutePath(), h);
@@ -184,7 +184,7 @@
if(genericHierarchy == null) {
File f = new File(dir, GENERIC+CONFIG_FILE_EXT);
if(f.exists()) {
- genericHierarchy = new Hierarchy(new RootCategory((Level) Priority.DEBUG));
+ genericHierarchy = new Hierarchy(new RootLogger((Level) Priority.DEBUG));
new PropertyConfigurator().doConfigure(f.getAbsolutePath(), genericHierarchy);
} else {
cat.warn("Could not find config file ["+f+
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..a784f85 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;
@@ -15,8 +15,8 @@
public static void main(String[] args) {
- Category root = Category.getRoot();
- Category cat = Category.getInstance(Loop.class.getName());
+ Logger root = Logger.getRootLogger();
+ Logger cat = Logger.getLogger(Loop.class.getName());
if(args.length != 2)
usage("Wrong number of arguments.");
diff --git a/src/java/org/apache/log4j/net/test/SMTPMin.java b/src/java/org/apache/log4j/net/test/SMTPMin.java
index 6777157..0975ff0 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;
@@ -11,7 +11,7 @@
public class SMTPMin {
- static Category cat = Category.getInstance(SMTPMin.class);
+ static Logger cat = Logger.getLogger(SMTPMin.class);
public
static
@@ -48,7 +48,7 @@
cat.warn( "Message " + i++);
cat.error( "Message " + i++);
cat.log(Priority.FATAL, "Message " + i++);
- Category.shutdown();
+ LogManager.shutdown();
Thread.currentThread().getThreadGroup().list();
}
diff --git a/src/java/org/apache/log4j/net/test/SocketMin.java b/src/java/org/apache/log4j/net/test/SocketMin.java
index 15ab781..334afa6 100644
--- a/src/java/org/apache/log4j/net/test/SocketMin.java
+++ b/src/java/org/apache/log4j/net/test/SocketMin.java
@@ -3,11 +3,11 @@
*
* 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;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.net.SocketAppender;
import org.apache.log4j.Priority;
@@ -16,7 +16,7 @@
public class SocketMin {
- static Category cat = Category.getInstance(SyslogMin.class.getName());
+ static Logger cat = Logger.getLogger(SyslogMin.class.getName());
static SocketAppender s;
public
@@ -46,7 +46,7 @@
static
void init(String host, String portStr) {
- Category root = Category.getRoot();
+ Logger root = Logger.getRootLogger();
BasicConfigurator.configure();
try {
int port = Integer.parseInt(portStr);
@@ -68,7 +68,7 @@
static
void loop() {
- Category root = Category.getRoot();
+ Logger root = Logger.getRootLogger();
InputStreamReader in = new InputStreamReader(System.in);
System.out.println("Type 'q' to quit");
int i;
diff --git a/src/java/org/apache/log4j/net/test/SyslogMin.java b/src/java/org/apache/log4j/net/test/SyslogMin.java
index 3c8f039..5bca2fe 100644
--- a/src/java/org/apache/log4j/net/test/SyslogMin.java
+++ b/src/java/org/apache/log4j/net/test/SyslogMin.java
@@ -3,12 +3,12 @@
*
* 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;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.Priority;
import org.apache.log4j.NDC;
@@ -16,7 +16,7 @@
public class SyslogMin {
- static Category CAT = Category.getInstance(SyslogMin.class.getName());
+ static Logger CAT = Logger.getLogger(SyslogMin.class);
public
static
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..6a46387 100644
--- a/src/java/org/apache/log4j/nt/test/NTMin.java
+++ b/src/java/org/apache/log4j/nt/test/NTMin.java
@@ -3,12 +3,12 @@
*
* 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;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.nt.NTEventLogAppender;
import org.apache.log4j.Priority;
@@ -17,7 +17,7 @@
public class NTMin {
- static Category cat = Category.getInstance(NTMin.class.getName());
+ static Logger cat = Logger.getLogger(NTMin.class.getName());
public
static
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/ConcatVsArray.java b/src/java/org/apache/log4j/performance/ConcatVsArray.java
deleted file mode 100644
index a3f6aca..0000000
--- a/src/java/org/apache/log4j/performance/ConcatVsArray.java
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 1996-1999, International Business Machines
-// Corporation. All Rights Reserved.
-
-package org.apache.log4j.performance;
-
-import java.util.Date;
-
-/**
- Measure difference in performance of string concatenation versus
- creating an anonymous string array.
-
- <p>You should be able to see that anonymous string array
- construction is significatnly faster than string concatenation. The
- difference increases proportionally with the length of the strings
- to be concatanated.
-
- @author Ceki Gülcü
- */
-public class ConcatVsArray {
-
-
- static
- void Usage() {
- System.err.println("Usage: java org.apache.log4j.performance.ConcatVsArray " +
- "string1 string2 runLength\n" +
- " where runLength is an integer.");
- System.exit(1);
- }
-
- public static void main(String args[]) {
-
- if(args.length != 3) {
- Usage();
- }
-
- String s1 = args[0];
- String s2 = args[1];
- int runLength = 0;
- try {
- runLength = Integer.parseInt(args[2]);
- }
- catch(java.lang.NumberFormatException e) {
- System.err.println(e);
- Usage();
- }
-
- double micros;
-
- String[] sa;
- long before = new Date().getTime();
- for(int i = 0; i < runLength; i++) {
- sa = new String[]{s1, s2};
- }
- micros = (new Date().getTime() - before)*1000.0/runLength;
- System.out.println("The anonymous array loop took around " + micros + " microseconds.");
-
- String s;
- before = new Date().getTime();
- for(int i = 0; i < runLength; i++) {
- s = s1 + s2;
- }
- micros = (new Date().getTime() - before)*1000.0/runLength;
- System.out.println("The append loop took around " + micros + " microseconds.");
-
- }
-}
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/Logging.java b/src/java/org/apache/log4j/performance/Logging.java
deleted file mode 100644
index 8bf504d..0000000
--- a/src/java/org/apache/log4j/performance/Logging.java
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright 1996-1999, International Business Machines
-// Corporation. All Rights Reserved.
-
-// Copyright 2000, Ceki Gulcu. All Rights Reserved.
-
-// See the LICENCE file for the terms of distribution.
-
-package org.apache.log4j.performance;
-
-import org.apache.log4j.Category;
-import org.apache.log4j.xml.DOMConfigurator;
-
-import org.apache.log4j.NDC;
-import org.apache.log4j.performance.NOPWriter;
-
-
-/**
- Measure the performance of logging.
-
- <p>Experimental results are listed below in units of
- <b>micro-seconds</b>. Measurements were done on a AMD Duron clocked
- at 800Mhz running Windows 2000 and Sun's 1.3 JDK.
-
-<p><table border=1>
-
-<tr>
-<th>Layout
-<th>NullAppender
-<th>FileAppender
-<th>FileAppender (no flush)
-<th>AsyncAppender (no flush)
-
-<tr>
-<td>SimpleLayout
-<td>4
-<td>21
-<td>16
-<td>33
-
-<tr>
-<td>PatternLayout "%p - %m%n"
-<td>4
-<td>21
-<td>16
-<td>32
-
-<tr>
-<td>PatternLayout "%-5p - %m%n"
-<td>4
-<td>NA
-<td>NA
-<td>NA
-
-<tr>
-<td>TTCCLayout/RELATIVE
-<td>10
-<td>37
-<td>31
-<td>45
-
-<tr>
-<td>PatternLayout "%r [%t] %-5p %c{2} %x - %m%n"
-<td>11
-<td>NA
-<td>NA
-<td>NA
-
-<tr>
-<td>PatternLayout "%r [%t] %-5p %.10c %x - %m%n"
-<td>11
-<td>NA
-<td>NA
-<td>NA
-
-<tr>
-<td>PatternLayout "%r [%t] %-5p %.20c %x - %m%n"
-<td>11
-<td>NA
-<td>NA
-<td>NA
-
-<tr>
-<td>PatternLayout "%r [%t] %-5p %c - %m%n"
-<td>9
-<td>36
-<td>29
-<td>45
-
-<tr>
-<td>TTCCLayout/ISO8601
-<td>25
-<td>58
-<td>51
-<td>71
-
-<tr>
-<td>PatternLayout "%d{ISO8601} [%t] %-5p %c %x - %m%n"
-<td>28
-<td>62
-<td>55
-<td>76
-
-<tr>
-<td>PatternLayout "%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] %-5p %c %x - %m%n"
-<td>46
-<td>82
-<td>72
-<td>94
-
-<tr>
-<td>PatternLayout "%l - %m%n"
-<td> 241
-<td> 317
-<td> 299
-<td> 251
-
-<tr>
-<td>PatternLayout "%C.%M.%L - %m%n"
-<td>267
-<td>NA
-<td>NA
-<td>NA
-
-</table>
-
- <p>The results of the measurements (should) show that:
-
- <ol>
-
- <li><b>The PatternLayout perforance is very close to the performance of
- a dedicated layout of equivalent format.</b>
-
- <p><li>Format specifiers in conversion patterns have almost no impact
- on performance.
-
- <p><li>Formating time and date information is costly. Using relative
- time has the least impact on performance. It is recommended that to
- use log4j specific date formatters such as the {@link
- org.apache.log4j.helpers.ISO8601DateFormat} instead of the standard {@link
- java.text.SimpleDateFormat} because of its poor performance. See
- the <b>%d</b> conversion character in {@link
- org.apache.log4j.PatternLayout}.
-
- <p><li>Avoiding the flush operation at the end of each append
- results in a performance gain of 10 to 20 percent. However, there
- is safety tradeoff invloved in skipping flushing. Indeed, when
- flushing is skipped, then it is likely that the last few log events
- will not be recorded on disk when the application exits. This is a
- high price to pay even for a 20% performance gain.
-
- <p><li>The <code>AsyncAppender</code> does not automatically
- increase performance. On the contrary, it significantly degrades
- performance. The performance tests done here very quickly fill up
- the bounded buffer of the <code>AsyncAppender</code> and there is
- cosiderable overhead in managing this bounded buffer.
-
- <p>On the other hand, had we interleaved logging operations with
- long blocking and non CPU-intensive operations, such as I/O,
- network access, sleeping threads, then the
- <code>AsyncAppender</code> would have tremendously reduced the cost
- of logging in terms of overall application runtime.
-
- <p>In a variant of this test, we have inserted a short sleep
- operation between every 10 log operations. When the total slept
- time is substracted, logging with the <code>AsyncLogger</code>
- takes no time at all. In other words, logging is done for "free".
-
- <p><li>Extracting location information is comparatively slow. It
- implies at least a ten fold increase in logging time! It should be
- avoided unless performace is not a concern. It has been reported
- from a trusted source that logging with location information on AIX
- machines will <em>kill</em> your application's performance.
-
- </ol>
-
- @author Ceki Gülcü
-
- */
-public class Logging {
-
- static int runLength;
- static int delay = -1;
- /**
- A delay is applied after every <code>burstLen</code> log
- requests. The default value of this constant is 100. */
- static int burstLen = 100;
- static int DELAY_MULT = 1000/burstLen;
-
- static Category cat = Category.getInstance("A0123456789.B0123456789.C0123456789");
-
- static
- void Usage(String msg) {
- System.err.println(msg);
- System.err.println(
- "Usage: java "+Logging.class.getName()+" confFile runLength [delay] [burstLen]\n"+
- " confFile is an XML configuration file and\n"+
- " runLength (integer) is the length of test loop.\n"+
- " delay is the time in millisecs to wait every bustLen log requests.");
- System.exit(1);
- }
-
- /**
- <b>Usage:</b> <code>java org.apache.log4j.performance.Logging confFile runLength [delay] [burstLen]</code>
-
- <p><code>confFile</code> is an XML configuration file and
- <code>runLength</code> (integer) is the length of test loop,
- <code>delay</code> is the time in millisecs to sleep every
- <code>bustLen</code> log requests.
-
- <p>This application just prints the average time it took to log.
-
-
- */
- public static void main(String argv[]) {
-
- if(argv.length == 2)
- init(argv[0], argv[1], null, null);
- else if( argv.length == 4)
- init(argv[0], argv[1], argv[2], argv[3]);
- else
- Usage("Wrong number of arguments.");
-
-
- NDC.push("some context");
-
- double delta;
- String msg = "ABCDEGHIJKLMNOPQRSTUVWXYZabcdeghijklmnopqrstuvwxyz1234567890";
- if(delay <= 0)
- delta = NoDelayLoop(cat, msg);
- else
- delta = DelayedLoop(cat, msg);
-
- System.out.print((int)delta);
-
- Category.shutdown();
-
- }
-
- /**
- Program wide initialization method.
- */
- static
- void init(String configFile, String runLengthStr, String delayStr,
- String burstLenStr) {
- try {
- runLength = Integer.parseInt(runLengthStr);
- if(delayStr != null) {
- delay = Integer.parseInt(delayStr);
- }
- if(delayStr != null) {
- burstLen = Integer.parseInt(burstLenStr);
- DELAY_MULT = 1000/burstLen;
- }
- }
- catch(java.lang.NumberFormatException e) {
- e.printStackTrace();
- }
- DOMConfigurator.configure(configFile);
- }
-
- static
- double NoDelayLoop(Category category, String msg) {
- long before = System.currentTimeMillis();
- for(int i = 0; i < runLength; i++) {
- category.info(msg);
- }
- return ((System.currentTimeMillis() - before)*1000.0)/runLength;
- }
-
- static
- double DelayedLoop(Category category, String msg) {
- long before = System.currentTimeMillis();
- int j = 0;
- Thread currentThread = Thread.currentThread();
- for(int i = 0; i < runLength; i++) {
- category.info(msg);
- if(j++ == burstLen) {
- j = 0;
- try{currentThread.sleep(delay);}catch(Exception e){}
- }
-
- }
- double actualTime = ((System.currentTimeMillis()-before)*1000.0/runLength);
- System.out.println("actual time: "+actualTime);
- return (actualTime - delay*DELAY_MULT);
- }
-}
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..b69b80e 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;
@@ -160,7 +160,7 @@
for(int second = 0; second < 16;) {
System.out.println("SECOND loop="+second +", RUN_LENGTH="
+RUN_LENGTH+", len="+len);
- t = (int)newBuffer(len, second);;
+ t = (int)newBuffer(len, second);
System.out.print("<td>" + t);
t = (int)setLen(len, second);
diff --git a/src/java/org/apache/log4j/performance/NotLogging.java b/src/java/org/apache/log4j/performance/NotLogging.java
deleted file mode 100644
index 783655a..0000000
--- a/src/java/org/apache/log4j/performance/NotLogging.java
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 1996-2000, International Business Machines
-// Corporation. All Rights Reserved.
-
-package org.apache.log4j.performance;
-
-
-import org.apache.log4j.Category;
-import org.apache.log4j.SimpleLayout;
-import org.apache.log4j.ConsoleAppender;
-
-import org.apache.log4j.Level;
-
-/**
- Measure the performance of evaluating whether to log or not to log,
- but not actually logging.
-
- <p>This program takes two arguments, a string which should be
- "true" for testing shipped code performance and "false" for testing
- debug-enabled performance the second argument is the run length of
- the measurement loops.
-
- <p>The results of the measurement (should) show that
-
- <ul>
-
- <p>
- <li>Category evaluation is independent of the length of the category name.
-
- <p>
- <li>As expected, using the {@link Category#isDebugEnabled
- isDebugEnabled} and {@link Category#isInfoEnabled isInfoEnabled}
- methods eliminates the overhead of message argument construction.
-
- <p> <li>Message argument construction can be an important slowing
- factor while evaluating whether to log or not.
-
- </ul>
-
- @author Ceki Gülcü
-
-*/
-public class NotLogging {
-
- static int runLength;
-
- final static int INITIAL_HASH_SIZE = 101;
-
- static String SHORT_MSG = "Hello World";
-
- static Category SHORT_CAT = Category.getInstance("A0123456789");
- static Category MEDIUM_CAT= Category.getInstance("A0123456789.B0123456789");
- static Category LONG_CAT =
- Category.getInstance("A0123456789.B0123456789.C0123456789");
-
- static Category INEXISTENT_SHORT_CAT = Category.getInstance("I0123456789");
- static Category INEXISTENT_MEDIUM_CAT=
- Category.getInstance("I0123456789.B0123456789");
- static Category INEXISTENT_LONG_CAT=
- Category.getInstance("I0123456789.B0123456789.C0123456789");
-
-
- static Category[] CAT_ARRAY = new Category[] {SHORT_CAT, MEDIUM_CAT,
- LONG_CAT, INEXISTENT_SHORT_CAT,
- INEXISTENT_MEDIUM_CAT,
- INEXISTENT_LONG_CAT};
-
- static
- void Usage() {
- System.err.println(
- "Usage: java org.apache.log4j.test.NotLogging true|false runLength\n" +
- "true indicates shipped code, false indicates code in development" +
- " where runLength is an int representing the run length of loops\n"+
- "We suggest that runLength be at least 100'000.");
- System.exit(1);
- }
-
- public static void main(String argv[]) {
-
- if(argv.length != 2) {
- Usage();
- }
- ProgramInit(argv);
- double delta;
-
-
- System.out.println();
- for(int i = 0; i < CAT_ARRAY.length; i++) {
- delta = SimpleMessage(CAT_ARRAY[i], SHORT_MSG, runLength);
- System.out.println("Simple argument, " + delta
- + " micros. Cat: " + CAT_ARRAY[i].getName());
- }
-
- System.out.println();
- for(int i = 0; i < CAT_ARRAY.length; i++) {
- delta = FullyOptimizedComplexMessage(CAT_ARRAY[i], runLength);
- System.out.println("Fully optimized complex, " + delta +
- " micros. Cat: " + CAT_ARRAY[i].getName());
- }
-
- System.out.println();
- for(int i = 0; i < CAT_ARRAY.length; i++) {
- delta = ComplexMessage(CAT_ARRAY[i], runLength);
- System.out.println("Complex message argument, " + delta +
- " micros. Cat: " + CAT_ARRAY[i].getName());
- }
-
- }
-
- /**
- Program wide initialization method. */
- static
- void ProgramInit(String[] args) {
-
- try {
- runLength = Integer.parseInt(args[1]);
- }
- catch(java.lang.NumberFormatException e) {
- System.err.println(e);
- Usage();
- }
-
-
- ConsoleAppender appender = new ConsoleAppender(new SimpleLayout());
-
- if("false".equals(args[0])) {
- // nothing to do
- } else if ("true".equals(args[0])) {
- System.out.println("Flagging as shipped code.");
- Category.getDefaultHierarchy().setThreshold((Level) Level.WARN);
- } else
- Usage();
-
- SHORT_CAT.setLevel((Level) Level.INFO);
- Category.getRoot().setLevel((Level) Level.INFO);
-
- }
-
-
- static
- double SimpleMessage(Category category, String msg, long runLength) {
- long before = System.currentTimeMillis();
- for(int i = 0; i < runLength; i++) {
- category.debug(msg);
- }
- return (System.currentTimeMillis() - before)*1000.0/runLength;
- }
-
- static
- double FullyOptimizedComplexMessage(Category category, long runLength) {
- long before = System.currentTimeMillis();
- for(int i = 0; i < runLength; i++) {
- if(category.isDebugEnabled())
- category.debug("Message" + i +
- " bottles of beer standing on the wall.");
- }
- return (System.currentTimeMillis() - before)*1000.0/runLength;
- }
-
- static
- double ComplexMessage(Category category, long runLength) {
- long before = System.currentTimeMillis();
- for(int i = 0; i < runLength; i++) {
- category.debug("Message" + i +
- " bottles of beer standing on the wall.");
- }
- return (System.currentTimeMillis() - before)*1000.0/runLength;
- }
-}
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..d862a0e 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";
@@ -45,7 +39,7 @@
parameter.
@param url The URL to parse
- @param hierarchy The hierarchy to operation upon.
+ @param repository The hierarchy to operation upon.
*/
void doConfigure(URL url, LoggerRepository repository);
}
diff --git a/src/java/org/apache/log4j/spi/Filter.java b/src/java/org/apache/log4j/spi/Filter.java
index 3f12dbd..ffa564d 100644
--- a/src/java/org/apache/log4j/spi/Filter.java
+++ b/src/java/org/apache/log4j/spi/Filter.java
@@ -91,7 +91,7 @@
the chain.
@param event The LoggingEvent to decide upon.
- @param decision The decision of the filter. */
+ @return decision The decision of the filter. */
abstract
public
int decide(LoggingEvent event);
diff --git a/src/java/org/apache/log4j/spi/LoggerRepository.java b/src/java/org/apache/log4j/spi/LoggerRepository.java
index 22ce2b3..11e468f 100644
--- a/src/java/org/apache/log4j/spi/LoggerRepository.java
+++ b/src/java/org/apache/log4j/spi/LoggerRepository.java
@@ -31,9 +31,10 @@
void addHierarchyEventListener(HierarchyEventListener listener);
/**
- Is the repository disabled for a given level? The answer depends
- on the repository threshold and the <code>level</code>
- parameter. See also {@link #setThreshold} method. */
+ Returns whether this repository is disabled for a given
+ level. The answer depends on the repository threshold and the
+ <code>level</code> parameter. See also {@link #setThreshold}
+ method. */
boolean isDisabled(int level);
/**
diff --git a/src/java/org/apache/log4j/spi/LoggingEvent.java b/src/java/org/apache/log4j/spi/LoggingEvent.java
index 5cd6e42..9170c3a 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;
@@ -111,16 +130,16 @@
<p>Except {@link #timeStamp} all the other fields of
<code>LoggingEvent</code> are filled when actually needed.
<p>
- @param category The category of this event.
+ @param logger The logger generating this event.
@param level The level of this event.
@param message The message of this event.
@param throwable The throwable of this event. */
public LoggingEvent(String fqnOfCategoryClass, Category logger,
- Priority priority, Object message, Throwable throwable) {
+ Priority level, Object message, Throwable throwable) {
this.fqnOfCategoryClass = fqnOfCategoryClass;
this.logger = logger;
this.categoryName = logger.getName();
- this.level = priority;
+ this.level = level;
this.message = message;
if(throwable != null) {
this.throwableInfo = new ThrowableInformation(throwable);
@@ -134,18 +153,18 @@
<p>Except {@link #timeStamp} all the other fields of
<code>LoggingEvent</code> are filled when actually needed.
<p>
- @param category The category of this event.
+ @param logger The logger generating this event.
@param timeStamp the timestamp of this logging event
@param level The level of this event.
@param message The message of this event.
@param throwable The throwable of this event. */
public LoggingEvent(String fqnOfCategoryClass, Category logger,
- long timeStamp, Priority priority, Object message,
+ long timeStamp, Priority level, Object message,
Throwable throwable) {
this.fqnOfCategoryClass = fqnOfCategoryClass;
this.logger = logger;
this.categoryName = logger.getName();
- this.level = priority;
+ this.level = level;
this.message = message;
if(throwable != null) {
this.throwableInfo = new ThrowableInformation(throwable);
@@ -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();
@@ -243,7 +281,7 @@
if(message instanceof String)
renderedMessage = (String) message;
else {
- LoggerRepository repository = logger.getHierarchy();
+ LoggerRepository repository = logger.getLoggerRepository();
if(repository instanceof RendererSupport) {
RendererSupport rs = (RendererSupport) repository;
@@ -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/RootCategory.java b/src/java/org/apache/log4j/spi/RootCategory.java
index 7ec80b4..f83e0ec 100644
--- a/src/java/org/apache/log4j/spi/RootCategory.java
+++ b/src/java/org/apache/log4j/spi/RootCategory.java
@@ -13,16 +13,7 @@
// Contibutors: Mathias Bogaert
/**
- RootCategory sits at the top of the category hierachy. It is a
- regular category except that it provides several guarantees.
-
- <p>First, it cannot be assigned a <code>null</code>
- priority. Second, since root category cannot have a parent, the
- {@link #getChainedLevel} method always returns the value of the
- level field without walking the hierarchy.
-
- @author Ceki Gülcü
-
+ * @deprecated Replaced by {@link RootLogger}.
*/
final public class RootCategory extends Logger {
diff --git a/src/java/org/apache/log4j/spi/RootLogger.java b/src/java/org/apache/log4j/spi/RootLogger.java
new file mode 100644
index 0000000..5e2dbae
--- /dev/null
+++ b/src/java/org/apache/log4j/spi/RootLogger.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.spi;
+
+import org.apache.log4j.*;
+import org.apache.log4j.helpers.LogLog;
+
+
+// Contibutors: Mathias Bogaert
+
+/**
+ RootLogger sits at the top of the logger hierachy. It is a
+ regular logger except that it provides several guarantees.
+
+ <p>First, it cannot be assigned a <code>null</code>
+ level. Second, since root logger cannot have a parent, the
+ {@link #getChainedLevel} method always returns the value of the
+ level field without walking the hierarchy.
+
+ @author Ceki Gülcü
+
+ */
+public final class RootLogger extends Logger {
+ /**
+ The root logger names itself as "root". However, the root
+ logger cannot be retrieved by name.
+ */
+ public RootLogger(Level level) {
+ super("root");
+ setLevel(level);
+ }
+
+ /**
+ Return the assigned level value without walking the logger
+ hierarchy.
+ */
+ public final Level getChainedLevel() {
+ return level;
+ }
+
+ /**
+ Setting a null value to the level of the root logger may have catastrophic
+ results. We prevent this here.
+
+ @since 0.8.3 */
+ public final void setLevel(Level level) {
+ if (level == null) {
+ LogLog.error(
+ "You have tried to set a null level to root.", new Throwable());
+ } else {
+ this.level = level;
+ }
+ }
+
+}
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..b9a7107 100644
--- a/src/java/org/apache/log4j/test/AsyncAppenderTest.java
+++ b/src/java/org/apache/log4j/test/AsyncAppenderTest.java
@@ -1,13 +1,13 @@
/* 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;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
+import org.apache.log4j.LogManager;
import org.apache.log4j.xml.DOMConfigurator;
/**
@@ -16,7 +16,7 @@
*/
public class AsyncAppenderTest {
- static Category cat = Category.getInstance(AsyncAppenderTest.class);
+ static Logger cat = Logger.getLogger(AsyncAppenderTest.class);
static int delayBeforeClose;
@@ -54,13 +54,13 @@
static
void test() {
- Category root = Category.getRoot();
+ Logger root = Logger.getRootLogger();
for(int i = 0; i < 100; i++) {
root.debug("Message " + i);
}
try{Thread.currentThread().sleep(delayBeforeClose);}catch(Exception e){}
- Category.shutdown();
+ LogManager.shutdown();
}
diff --git a/src/java/org/apache/log4j/test/Base64.java b/src/java/org/apache/log4j/test/Base64.java
deleted file mode 100644
index a3b1fc2..0000000
--- a/src/java/org/apache/log4j/test/Base64.java
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 1996-1999, International Business Machines
-// Corporation. All Rights Reserved.
-
-
-package org.apache.log4j.test;
-
-class Base64 {
-
- final static int MAX_LINE = 76;
-
- static byte[] asciiEncoding =
- //A B C D E F G H I J K L M N O P Q
- {65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- //R S ... Z a b c d e f g
- 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103,
- //h i j k l m n o p q r s t u
- 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
- //v w x y z 0 1 2 3 4 5 6 7 8 9 + /
- 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47};
-
- static char[] charEnc = new char[64];
-
- static {
- for(int i = 0; i < 26; i ++) {
- charEnc[i] = (char) ('A' + i);
- charEnc[i+26] = (char) ('a' + i);
- }
- for(int i = 0; i < 10; i ++) {
- charEnc[i+52] = (char) ('0' + i);
- }
- charEnc[62] = '+';
- charEnc[63] = '/';
- }
-
-
-
- static
- String toString(byte[] inbuf) {
- return toString(inbuf, 0, inbuf.length);
- }
- /**
-
- */
- static
- String toString(byte[] inbuf, int offset, int length) {
-
- StringBuffer output = new StringBuffer((length)*4/3 + 1);
-
- int in;
- char[] out = new char[4];
-
- int i = offset;
- boolean ended = false;
- int last = offset + length;
- int j;
- int bitsRead;
-
- while(!ended) {
- in = 0;
- bitsRead = 0;
- for(j = 0; j < 3; j++) {
- if(i == last) {
- ended = true;
- break;
- }
- in = (in << 8) | (inbuf[i++] & 0xFF);
- bitsRead += 8;
- }
-
- while(bitsRead >= 6) {
- bitsRead -= 6;
- output.append(charEnc[(in >>> bitsRead) & 0x3F]);
- }
-
- if(bitsRead == 4) {
- output.append(charEnc[(in & 0x0F) << 2]);
- output.append("=");
- }
- else if (bitsRead == 2) {
- output.append(charEnc[(in & 0x03) << 4]);
- output.append("==");
- }
- }
- return output.toString();
- }
-
-
- public static void main(String[] args) {
-
- byte[] inbuf = new byte[MAX_LINE];
-
- while(true) {
- try {
- int read = System.in.read(inbuf, 0, MAX_LINE);
- if(read == -1) break;
- System.out.println("Read " + read + " chars.");
- System.out.println(Base64.toString(inbuf, 0, read));
- }
- catch (Exception e) {
- System.out.println("Exception " + e);
- }
-
- }
- }
-}
diff --git a/src/java/org/apache/log4j/test/CategoryWrapper.java b/src/java/org/apache/log4j/test/CategoryWrapper.java
index fd5928d..947a2ca 100644
--- a/src/java/org/apache/log4j/test/CategoryWrapper.java
+++ b/src/java/org/apache/log4j/test/CategoryWrapper.java
@@ -12,11 +12,11 @@
public class CategoryWrapper {
- Category c;
+ Logger c;
static String FQCN = CategoryWrapper.class.getName();
CategoryWrapper(String name) {
- c = Category.getInstance(name);
+ c = Logger.getLogger(name);
}
public
@@ -39,7 +39,7 @@
void print(String msg) {
// You have to supply the fully qualified named of the wrapper
- // class to the specially tailored category.log method for
+ // class to the specially tailored logger.log method for
// PatternLayout's %C conversion pattern to work.
// We have to add the ".print" string because the invocation of
diff --git a/src/java/org/apache/log4j/test/ConfigurationFileParsing.java b/src/java/org/apache/log4j/test/ConfigurationFileParsing.java
index 0e274df..8a0725f 100644
--- a/src/java/org/apache/log4j/test/ConfigurationFileParsing.java
+++ b/src/java/org/apache/log4j/test/ConfigurationFileParsing.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.test;
import org.apache.log4j.PropertyConfigurator;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
+import org.apache.log4j.LogManager;
import org.apache.log4j.NDC;
public class ConfigurationFileParsing {
@@ -20,11 +21,11 @@
if(argv.length == 1) {
NDC.push("testing");
PropertyConfigurator.configure(argv[0]);
- Category root = Category.getRoot();
+ Logger root = Logger.getRootLogger();
root.debug("Message 1");
root.debug("Message 2");
NDC.pop();
- Category.shutdown();
+ LogManager.shutdown();
}
else {
Usage("Wrong number of arguments.");
diff --git a/src/java/org/apache/log4j/test/DRFATest.java b/src/java/org/apache/log4j/test/DRFATest.java
index 07b0968..6408457 100644
--- a/src/java/org/apache/log4j/test/DRFATest.java
+++ b/src/java/org/apache/log4j/test/DRFATest.java
@@ -7,7 +7,7 @@
package org.apache.log4j.test;
import org.apache.log4j.BasicConfigurator;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.Layout;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.Appender;
@@ -20,7 +20,7 @@
*/
public class DRFATest {
- static Category cat = Category.getInstance(DRFATest.class);
+ static Logger cat = Logger.getLogger(DRFATest.class);
static int limit;
diff --git a/src/java/org/apache/log4j/test/DefaultInit.java b/src/java/org/apache/log4j/test/DefaultInit.java
index 8c3616d..3f14f77 100644
--- a/src/java/org/apache/log4j/test/DefaultInit.java
+++ b/src/java/org/apache/log4j/test/DefaultInit.java
@@ -1,11 +1,11 @@
package org.apache.log4j.test;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
public class DefaultInit {
- static Category cat = Category.getInstance(DefaultInit.class);
+ static Logger cat = Logger.getLogger(DefaultInit.class);
public static void main( String[] argv) {
cat.debug("Hello world");
diff --git a/src/java/org/apache/log4j/test/DelayedLoop.java b/src/java/org/apache/log4j/test/DelayedLoop.java
index 3af6a48..581235e 100644
--- a/src/java/org/apache/log4j/test/DelayedLoop.java
+++ b/src/java/org/apache/log4j/test/DelayedLoop.java
@@ -7,7 +7,7 @@
package org.apache.log4j.test;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.DOMConfigurator;
@@ -20,7 +20,7 @@
@author Ceki Gülcü */
public class DelayedLoop {
- static Category cat = Category.getInstance(DelayedLoop.class);
+ static Logger cat = Logger.getLogger(DelayedLoop.class);
static int loopLength;
public
diff --git a/src/java/org/apache/log4j/test/FQCNTest.java b/src/java/org/apache/log4j/test/FQCNTest.java
index 5d6a337..5b92ff3 100644
--- a/src/java/org/apache/log4j/test/FQCNTest.java
+++ b/src/java/org/apache/log4j/test/FQCNTest.java
@@ -18,7 +18,7 @@
*/
public class FQCNTest {
- //static Logger cat = Logger.getLoggerInstance("dddd");
+ //static Logger cat = Logger.getLogger("dddd");
public
static
@@ -42,7 +42,7 @@
Layout layout = new PatternLayout("%p %c (%C{2}#%M) - %m%n");
FileAppender appender = new FileAppender(layout, file, false);
appender.setLayout(layout);
- Category root = Category.getRoot();
+ Logger root = Logger.getRootLogger();
root.addAppender(appender);
}
diff --git a/src/java/org/apache/log4j/test/Finalize.java b/src/java/org/apache/log4j/test/Finalize.java
index 3c9c8ba..9e0f17c 100644
--- a/src/java/org/apache/log4j/test/Finalize.java
+++ b/src/java/org/apache/log4j/test/Finalize.java
@@ -3,13 +3,13 @@
package org.apache.log4j.test;
import org.apache.log4j.PropertyConfigurator;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import java.io.InputStreamReader;
import java.util.Enumeration;
public class Finalize {
- static Category CAT = Category.getInstance(Finalize.class.getName());
+ static Logger CAT = Logger.getLogger(Finalize.class.getName());
public
static
@@ -42,7 +42,7 @@
int i = -1;
InputStreamReader in = new InputStreamReader(System.in);
- Category root = Category.getRoot();
+ Logger root = Logger.getRootLogger();
System.out.println("Type 'q' to quit");
int j = 0;
@@ -68,10 +68,10 @@
}
static
- void foo(Category cat) {
- Enumeration enum = cat.getAllAppenders();
- while(enum != null && enum.hasMoreElements()) {
- ((org.apache.log4j.Appender) enum.nextElement()).close();
+ void foo(Logger cat) {
+ Enumeration enumaration = cat.getAllAppenders();
+ while(enumaration != null && enumaration.hasMoreElements()) {
+ ((org.apache.log4j.Appender) enumaration.nextElement()).close();
}
}
diff --git a/src/java/org/apache/log4j/test/Hello.java b/src/java/org/apache/log4j/test/Hello.java
index ac663f3..02746a5 100644
--- a/src/java/org/apache/log4j/test/Hello.java
+++ b/src/java/org/apache/log4j/test/Hello.java
@@ -7,7 +7,7 @@
package org.apache.log4j.test;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
/**
@@ -17,7 +17,7 @@
*/
public class Hello {
- static Category cat = Category.getInstance(Hello.class);
+ static Logger cat = Logger.getLogger(Hello.class);
public
static
diff --git a/src/java/org/apache/log4j/test/L7D.java b/src/java/org/apache/log4j/test/L7D.java
deleted file mode 100644
index edc663b..0000000
--- a/src/java/org/apache/log4j/test/L7D.java
+++ /dev/null
@@ -1,79 +0,0 @@
-
-
-// Copyright 1996-2000, International Business Machines
-// Corporation. All Rights Reserved.
-//
-// See the LICENCE file for the terms of distribution.
-
-package org.apache.log4j.test;
-
-import org.apache.log4j.*;
-import java.util.*;
-import java.text.*;
-
-/**
- This class is a simple test of the localization routines in
- Category class.
-
- @author Ceki Gülcü, IBM Zurich Research Laboratory */
-public class L7D {
- static ResourceBundle[] bundles;
-
-
- public
- static
- void main(String args[]) {
- if(args.length == 3)
- init(args[0], args[1], args[2]);
- else
- Usage("Wrong number of arguments.");
-
- test();
- }
-
- static
- void Usage(String msg) {
- System.err.println(msg);
- System.err.println( "Usage: java " + L7D.class.getName() +
- "configFile ISO639LanguageCode ISO2166CountryCode");
- System.exit(1);
- }
-
- static
- void init(String configFile, String lanCode, String countryCode) {
- PropertyConfigurator.configure(configFile);
- bundles = new ResourceBundle[3];
-
- try {
- bundles[0] = ResourceBundle.getBundle("L7D", new Locale("en", "US"));
- bundles[1] = ResourceBundle.getBundle("L7D", new Locale("fr", "FR"));
- bundles[2] = ResourceBundle.getBundle("L7D", new Locale("fr", "CH"));
-
- }
- catch(MissingResourceException e) {
- e.printStackTrace();
- }
- }
-
- static
- void test() {
- Category root = Category.getRoot();
-
- for(int i = 0; i < bundles.length; i++) {
- root.setResourceBundle(bundles[i]);
-
- root.l7dlog(Priority.DEBUG, "bogus1", null);
- root.l7dlog(Priority.INFO, "test", null);
- root.l7dlog(Priority.WARN, "hello_world", null);
- root.l7dlog(Priority.DEBUG, "msg1",
- new Object[] {new Integer(i+1), "log4j"}, null);
- root.l7dlog(Priority.ERROR, "bogusMsg",
- new Object[] {new Integer(i+1), "log4j"}, null);
- root.l7dlog(Priority.ERROR, "msg1",
- new Object[] {new Integer(i+1), "log4j"}, null);
- root.l7dlog(Priority.INFO, "bogus2", null);
- }
-
- }
-
-}
diff --git a/src/java/org/apache/log4j/test/MDCStress.java b/src/java/org/apache/log4j/test/MDCStress.java
index 9e7b97c..315d018 100644
--- a/src/java/org/apache/log4j/test/MDCStress.java
+++ b/src/java/org/apache/log4j/test/MDCStress.java
@@ -8,8 +8,8 @@
public class MDCStress extends Thread {
- static Category root = Category.getRoot();
- static Category log = Category.getInstance(MDCStress.class);
+ static Logger root = Logger.getRootLogger();
+ static Logger log = Logger.getLogger(MDCStress.class);
static Random random = new Random(17);
diff --git a/src/java/org/apache/log4j/test/MultipleAppenders.java b/src/java/org/apache/log4j/test/MultipleAppenders.java
index 3ffd335..505f368 100644
--- a/src/java/org/apache/log4j/test/MultipleAppenders.java
+++ b/src/java/org/apache/log4j/test/MultipleAppenders.java
@@ -2,7 +2,7 @@
package org.apache.log4j.test;
import org.apache.log4j.PropertyConfigurator;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.Appender;
import java.util.Enumeration;
import java.util.Vector;
@@ -16,7 +16,7 @@
// A1 and A2 should be added to root by reading the config file
PropertyConfigurator.configure(argv[0]);
- Category root = Category.getRoot();
+ Logger root = Logger.getRootLogger();
Enumeration e1 = root.getAllAppenders();
Vector v = new Vector(1);
diff --git a/src/java/org/apache/log4j/test/PatternTest.java b/src/java/org/apache/log4j/test/PatternTest.java
index b7feaed..b6da2e6 100644
--- a/src/java/org/apache/log4j/test/PatternTest.java
+++ b/src/java/org/apache/log4j/test/PatternTest.java
@@ -2,7 +2,8 @@
package org.apache.log4j.test;
import org.apache.log4j.PropertyConfigurator;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
+import org.apache.log4j.LogManager;
import org.apache.log4j.Priority;
/**
This class is a test of the PatternLayout class.
@@ -10,7 +11,7 @@
@author Ceki Gülcü
*/
public class PatternTest {
- static Category CAT = Category.getInstance(PatternTest.class);
+ static Logger CAT = Logger.getLogger(PatternTest.class);
public
@@ -40,7 +41,7 @@
static
void test() {
int i = -1;
- Category root = Category.getRoot();
+ Logger root = Logger.getRootLogger();
CAT.debug("Message " + ++i);
root.debug("Message " + i);
@@ -73,6 +74,6 @@
CAT.log(Priority.FATAL, "Message " + ++i, e);
root.log(Priority.FATAL, "Message " + i, e);
- Category.shutdown();
+ LogManager.shutdown();
}
}
diff --git a/src/java/org/apache/log4j/test/ROFile.java b/src/java/org/apache/log4j/test/ROFile.java
index 4f36a0f..c6eeefd 100644
--- a/src/java/org/apache/log4j/test/ROFile.java
+++ b/src/java/org/apache/log4j/test/ROFile.java
@@ -1,11 +1,11 @@
package org.apache.log4j.test;
import org.apache.log4j.PropertyConfigurator;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
public class ROFile {
- static Category cat = Category.getInstance(ROFile.class.getName());
+ static Logger cat = Logger.getLogger(ROFile.class);
public
static
diff --git a/src/java/org/apache/log4j/test/Shallow.java b/src/java/org/apache/log4j/test/Shallow.java
index 2a202d0..fc4bb33 100644
--- a/src/java/org/apache/log4j/test/Shallow.java
+++ b/src/java/org/apache/log4j/test/Shallow.java
@@ -8,9 +8,11 @@
package org.apache.log4j.test;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.DOMConfigurator;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
+import org.apache.log4j.Logger;
+import org.apache.log4j.LogManager;
import org.apache.log4j.NDC;
-import org.apache.log4j.Priority;
+import org.apache.log4j.Level;
/**
This class is a shallow test of the various appenders and
layouts. It also tests their reading of the configuration file.
@@ -18,7 +20,7 @@
*/
public class Shallow {
- static Category cat = Category.getInstance(Shallow.class);
+ static Logger cat = Logger.getLogger(Shallow.class);
public
static
@@ -49,7 +51,7 @@
void test() {
int i = -1;
NDC.push("NDC");
- Category root = Category.getRoot();
+ Logger root = Logger.getRootLogger();
cat.debug("Message " + ++i);
root.debug("Message " + i);
@@ -62,8 +64,8 @@
cat.error("Message " + ++i);
root.error("Message " + i);
- cat.log(Priority.FATAL, "Message " + ++i);
- root.log(Priority.FATAL, "Message " + i);
+ cat.log(Level.FATAL, "Message " + ++i);
+ root.log(Level.FATAL, "Message " + i);
Exception e = new Exception("Just testing");
cat.debug("Message " + ++i, e);
@@ -78,14 +80,14 @@
cat.error("Message " + ++i, e);
root.error("Message " + i, e);
- cat.log(Priority.FATAL, "Message " + ++i, e);
- root.log(Priority.FATAL, "Message " + i, e);
+ cat.log(Level.FATAL, "Message " + ++i, e);
+ root.log(Level.FATAL, "Message " + i, e);
- root.setPriority(Priority.FATAL);
+ root.setLevel(Level.FATAL);
// It is always a good idea to call this method when exiting an
// application.
- Category.shutdown();
+ LogManager.shutdown();
}
diff --git a/src/java/org/apache/log4j/test/ShortSocketServer.java b/src/java/org/apache/log4j/test/ShortSocketServer.java
index e1ba36b..5eb02cc 100644
--- a/src/java/org/apache/log4j/test/ShortSocketServer.java
+++ b/src/java/org/apache/log4j/test/ShortSocketServer.java
@@ -5,7 +5,8 @@
import java.net.Socket;
import java.net.ServerSocket;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
+import org.apache.log4j.LogManager;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.net.SocketNode;
@@ -15,7 +16,7 @@
public class ShortSocketServer {
- static Category cat = Category.getInstance(ShortSocketServer.class.getName());
+ static Logger cat = Logger.getLogger(ShortSocketServer.class.getName());
static int port;
@@ -35,7 +36,7 @@
Socket socket = serverSocket.accept();
LogLog.debug("Connected to client at " + socket.getInetAddress());
LogLog.debug("Starting new socket node.");
- SocketNode sn = new SocketNode(socket, Category.getDefaultHierarchy());
+ SocketNode sn = new SocketNode(socket, LogManager.getLoggerRepository());
Thread t = new Thread(sn);
t.start();
t.join();
diff --git a/src/java/org/apache/log4j/test/StressAsyncAppender.java b/src/java/org/apache/log4j/test/StressAsyncAppender.java
index 549f609..4f32ccb 100644
--- a/src/java/org/apache/log4j/test/StressAsyncAppender.java
+++ b/src/java/org/apache/log4j/test/StressAsyncAppender.java
@@ -4,7 +4,7 @@
package org.apache.log4j.test;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
@@ -16,7 +16,7 @@
*/
public class StressAsyncAppender extends Thread {
- static Category root = Category.getRoot();
+ static Logger root = Logger.getRootLogger();
static Random random = new Random(101);
diff --git a/src/java/org/apache/log4j/test/StressNDC.java b/src/java/org/apache/log4j/test/StressNDC.java
deleted file mode 100644
index 7d93774..0000000
--- a/src/java/org/apache/log4j/test/StressNDC.java
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 1996-1999, International Business Machines
-// Corporation and others. All Rights Reserved.
-
-package org.apache.log4j.test;
-
-
-import org.apache.log4j.Category;
-import org.apache.log4j.BasicConfigurator;
-import org.apache.log4j.NDC;
-
-
-import java.util.Random;
-import java.util.Stack;
-
-/**
- Stress test {@link NDC}.
-
- */
-public class StressNDC extends Thread {
-
- static Category root = Category.getRoot();
-
- static Random random = new Random(101);
-
- static final int LOOP_LENGTH = 24;
- static final int PUSH_MISS = LOOP_LENGTH/2;
- static final int POP_MISS = PUSH_MISS*2;
-
- static final int BRANCHING_FACTOR = 4 + 1; // add 1 to the number you want
-
- static int maxThreads;
- static int msgCounter = 0;
- static int threadCounter = 0;
-
- static double LOG_2 = Math.log(2);
-
- static Object lock = new Object();
-
-
- public
- static
- void main(String args[]) {
- BasicConfigurator.configure();
-
- if(args.length != 1) {
- usage();
- }
-
- try {
- maxThreads = Integer.parseInt(args[0]);
- }
- catch(java.lang.NumberFormatException e) {
- System.err.println(e);
- usage();
- }
-
- root.debug( "push(IP=127.0.0.1)");
-
- NDC.push("IP=127.0.0.1");
-
- while(true) {
- synchronized(lock) {
- // Adding 1 to ensure that at least 1 child is created.
- createChildren(randomInt(BRANCHING_FACTOR) + 1);
-
- // wait until all threads are finished
- try {
- root.debug( "About to wait for notification.");
- lock.wait();
- root.debug( "Got a notification.");
- }
- catch(InterruptedException e) {
- root.warn("Unpextected InterruptedException received.", e);
- }
- }
- }
- }
-
- static
- void usage() {
- System.err.println( "Usage: java org.apache.log4j.test.StressNDC " +
- "MAX_THREADS");
- System.exit(1);
- }
-
-
- Stack parentDC;
-
- public
- StressNDC(Stack parentDC) {
- this.setName(randomID());
- this.parentDC = parentDC;
- }
-
- public
- void run() {
- NDC.inherit(parentDC);
-
- int loopLength = StressNDC.randomInt(LOOP_LENGTH);
- root.debug("In run loop.debug( loopLength = "+loopLength);
-
- int createIndex = loopLength/2;
-
- for(int i = 0; i <= loopLength; i++) {
-
- if(i == createIndex)
- createChildren(randomInt(BRANCHING_FACTOR));
-
- if(randomInt(PUSH_MISS) == 0) {
- String id = randomID();
- root.debug( "push("+id+")");
- NDC.push(id);
- }
- root.debug( "Message number " + StressNDC.msgCounter++);
- if(randomInt(POP_MISS) == 0) {
- root.debug( "pop()");
- NDC.pop();
- }
- }
-
- synchronized(lock) {
- StressNDC.threadCounter--;
- root.debug( "Exiting run loop. " + threadCounter);
- if(StressNDC.threadCounter <= 0) {
- root.debug( "Notifying [main] thread.");
- lock.notify(); // wake up the main thread
- }
- }
-
- // We sometimes forget to remove references
- if((loopLength % 2) == 0) {
- root.debug("Removing NDC for this thread.");
- NDC.remove();
- }
- }
-
- public
- static
- void createChildren(int n) {
- if (n <= 0)
- return;
-
- synchronized(lock) {
- n = maxThreadsConstained(n);
- root.debug("Creating " + n+ " child StressNDC threads.");
- for(int i = 0; i < n; i++) {
- root.debug("New StressNDC, threadCounter = " + (++threadCounter));
- new StressNDC(NDC.cloneStack()).start();
- }
- }
- }
-
- static
- public
- int maxThreadsConstained(int a) {
- int maxAllowed = StressNDC.maxThreads - StressNDC.threadCounter;
- return a <= maxAllowed ? a : maxAllowed;
- }
-
- /**
- Return a random value in the range
- */
- public
- static
- int randomInt(int n) {
- int r = random.nextInt() % n;
- return r >= 0 ? r : -r;
- }
-
- public
- static
- String randomID() {
- return Integer.toString(random.nextInt()& 0xFFFFFF);
- }
-}
diff --git a/src/java/org/apache/log4j/test/SysoutConfigurator.java b/src/java/org/apache/log4j/test/SysoutConfigurator.java
index aa87c85..2007ce9 100644
--- a/src/java/org/apache/log4j/test/SysoutConfigurator.java
+++ b/src/java/org/apache/log4j/test/SysoutConfigurator.java
@@ -5,14 +5,14 @@
/**
* This configurator simply always adds a FileAppender writing to
- * System.out to the root Category and ignores whatever is in the
+ * System.out to the root Logger and ignores whatever is in the
* properties file.
*/
public class SysoutConfigurator implements Configurator {
public
void
doConfigure(java.net.URL url, LoggerRepository hierarchy) {
- Category.getRoot().addAppender(
+ Logger.getRootLogger().addAppender(
new ConsoleAppender(
new SimpleLayout(), ConsoleAppender.SYSTEM_OUT));
}
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/varia/Roller.java b/src/java/org/apache/log4j/varia/Roller.java
index d416896..8e96317 100644
--- a/src/java/org/apache/log4j/varia/Roller.java
+++ b/src/java/org/apache/log4j/varia/Roller.java
@@ -8,7 +8,7 @@
package org.apache.log4j.varia;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
import java.io.IOException;
@@ -29,7 +29,7 @@
@since version 0.9.0 */
public class Roller {
- static Category cat = Category.getInstance(Roller.class.getName());
+ static Logger cat = Logger.getLogger(Roller.class);
static String host;
diff --git a/src/java/org/apache/log4j/varia/test/Loop.java b/src/java/org/apache/log4j/varia/test/Loop.java
index ae60aa2..a43fdf5 100644
--- a/src/java/org/apache/log4j/varia/test/Loop.java
+++ b/src/java/org/apache/log4j/varia/test/Loop.java
@@ -1,7 +1,7 @@
package org.apache.log4j.varia.test;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
/**
@@ -12,7 +12,7 @@
@author Ceki Gülcü */
public class Loop {
- static Category cat = Category.getInstance(Loop.class.getName());
+ static Logger cat = Logger.getLogger(Loop.class);
static int loopLength;
public
diff --git a/src/java/org/apache/log4j/xml/DOMConfigurator.java b/src/java/org/apache/log4j/xml/DOMConfigurator.java
index 8060989..60ef03f 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,
@@ -651,25 +651,18 @@
}
try {
- // This makes ID/IDREF attributes to have a meaning. Don't ask
- // me why.
dbf.setValidating(true);
- //dbf.setNamespaceAware(true);
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
- docBuilder.setErrorHandler(new SAXErrorHandler());
- Class clazz = this.getClass();
- URL dtdURL = clazz.getResource("/org/apache/log4j/xml/log4j.dtd");
- if(dtdURL == null) {
- LogLog.error("Could not find [log4j.dtd]. Used ["+clazz.getClassLoader()+
- "] class loader in the search.");
- }
- else {
- LogLog.debug("URL to log4j.dtd is [" + dtdURL.toString()+"].");
- inputSource.setSystemId(dtdURL.toString());
- }
- Document doc = docBuilder.parse(inputSource);
+ docBuilder.setErrorHandler(new SAXErrorHandler());
+ docBuilder.setEntityResolver(new Log4jEntityResolver());
+ // we change the system ID to a valid URI so that Crimson won't
+ // complain. Indeed, "log4j.dtd" alone is not a valid URI which
+ // causes Crimson to barf. The Log4jEntityResolver only cares
+ // about the "log4j.dtd" ending.
+ inputSource.setSystemId("dummy://log4j.dtd");
+ Document doc = docBuilder.parse(inputSource);
parse(doc.getDocumentElement());
} catch (Exception e) {
// I know this is miserable...
@@ -677,13 +670,13 @@
}
}
- /**
- Configure by taking in an DOM element.
- */
- public void doConfigure(Element element, LoggerRepository repository) {
- this.repository = repository;
- parse(element);
- }
+ /**
+ Configure by taking in an DOM element.
+ */
+ public void doConfigure(Element element, LoggerRepository repository) {
+ this.repository = repository;
+ parse(element);
+ }
/**
@@ -733,9 +726,9 @@
// "debug" attribute is returned as the empty string.
if(!debugAttrib.equals("") && !debugAttrib.equals("null")) {
LogLog.setInternalDebugging(OptionConverter.toBoolean(debugAttrib, true));
- }
- else
+ } else {
LogLog.debug("Ignoring " + INTERNAL_DEBUG_ATTR + " attribute.");
+ }
String confDebug = subst(element.getAttribute(CONFIG_DEBUG_ATTR));
diff --git a/src/java/org/apache/log4j/xml/Log4jEntityResolver.java b/src/java/org/apache/log4j/xml/Log4jEntityResolver.java
new file mode 100644
index 0000000..79707cb
--- /dev/null
+++ b/src/java/org/apache/log4j/xml/Log4jEntityResolver.java
@@ -0,0 +1,44 @@
+/*
+ * 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.xml;
+
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+
+import org.apache.log4j.helpers.LogLog;
+
+/**
+ * An {@link EntityResolver} specifically designed to return
+ * <code>log4j.dtd</code> which is embedded within the log4j jar
+ * file.
+ *
+ * @author Paul Austin
+ * */
+public class Log4jEntityResolver implements EntityResolver {
+
+ public InputSource resolveEntity (String publicId, String systemId) {
+ if (systemId.endsWith("log4j.dtd")) {
+ Class clazz = getClass();
+ InputStream in = clazz.getResourceAsStream("/org/apache/log4j/xml/log4j.dtd");
+ if (in == null) {
+ LogLog.error("Could not find [log4j.dtd]. Used [" + clazz.getClassLoader()
+ + "] class loader in the search.");
+ return null;
+ } else {
+ return new InputSource(in);
+ }
+ } else {
+ return 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/examples/XMLSample.java b/src/java/org/apache/log4j/xml/examples/XMLSample.java
index d3ee98c..91c4882 100644
--- a/src/java/org/apache/log4j/xml/examples/XMLSample.java
+++ b/src/java/org/apache/log4j/xml/examples/XMLSample.java
@@ -2,7 +2,7 @@
package org.apache.log4j.xml.examples;
import org.apache.log4j.xml.DOMConfigurator;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import java.net.*;
/**
@@ -22,7 +22,7 @@
*/
public class XMLSample {
- static Category cat = Category.getInstance(XMLSample.class.getName());
+ static Logger cat = Logger.getLogger(XMLSample.class);
public
static
@@ -51,7 +51,7 @@
static
void sample() {
int i = -1;
- Category root = Category.getRoot();
+ Logger root = Logger.getRootLogger();
cat.debug("Message " + ++i);
cat.warn ("Message " + ++i);
cat.error("Message " + ++i);
diff --git a/src/java/org/apache/log4j/xml/log4j.dtd b/src/java/org/apache/log4j/xml/log4j.dtd
index 12f373c..d92a6e7 100644
--- a/src/java/org/apache/log4j/xml/log4j.dtd
+++ b/src/java/org/apache/log4j/xml/log4j.dtd
@@ -15,12 +15,15 @@
<!-- logging statements with a level equal or below this value are -->
<!-- disabled. -->
-<!-- Setting the "debug" or "configDebug" attributes enable the printing -->
-<!-- of internal log4j logging statements. -->
+<!-- Setting the "debug" enable the printing of internal log4j logging -->
+<!-- statements. -->
-<!-- By default, debug attribute is "null", meaning that we not touch -->
-<!-- internal log4j logging settings. -->
-
+<!-- By default, debug attribute is "null", meaning that we not do touch -->
+<!-- internal log4j logging settings. The "null" value for the threshold -->
+<!-- attribute can be misleading. The threshold field of a repository -->
+<!-- cannot be set to null. The "null" value for the threshold attribute -->
+<!-- simply means don't touch the threshold field, the threshold field -->
+<!-- keeps its old value. -->
<!ATTLIST log4j:configuration
xmlns:log4j CDATA #FIXED "http://jakarta.apache.org/log4j/"
@@ -143,8 +146,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/java/org/apache/log4j/xml/test/DOMTest.java b/src/java/org/apache/log4j/xml/test/DOMTest.java
index 225cfb6..b6c303c 100644
--- a/src/java/org/apache/log4j/xml/test/DOMTest.java
+++ b/src/java/org/apache/log4j/xml/test/DOMTest.java
@@ -8,8 +8,9 @@
package org.apache.log4j.xml.test;
import org.apache.log4j.xml.DOMConfigurator;
-import org.apache.log4j.Category;
-import org.apache.log4j.Priority;
+import org.apache.log4j.Logger;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Level;
//import org.apache.log4j.xml.examples.ReportParserError;
//import org.apache.xerces.parsers.DOMParser;
//import java.io.FileInputStream;
@@ -19,7 +20,7 @@
@author Ceki Gülcü
*/
public class DOMTest {
- static Category cat = Category.getInstance(DOMTest.class.getName());
+ static Logger cat = Logger.getLogger(DOMTest.class.getName());
public
@@ -50,7 +51,7 @@
static
void test() {
int i = -1;
- Category root = Category.getRoot();
+ Logger root = Logger.getRootLogger();
cat.debug("Message " + ++i);
root.debug("Message " + i);
@@ -64,8 +65,8 @@
cat.error("Message " + ++i);
root.error("Message " + i);
- cat.log(Priority.FATAL, "Message " + ++i);
- root.log(Priority.FATAL, "Message " + i);
+ cat.log(Level.FATAL, "Message " + ++i);
+ root.log(Level.FATAL, "Message " + i);
Exception e = new Exception("Just testing");
cat.debug("Message " + ++i, e);
@@ -74,6 +75,6 @@
cat.error("Message " + ++i, e);
root.error("Message " + i, e);
- Category.shutdown();
+ LogManager.shutdown();
}
}
diff --git a/src/java/org/slf4j/LoggerFactory.java b/src/java/org/slf4j/LoggerFactory.java
new file mode 100644
index 0000000..cf7ce74
--- /dev/null
+++ b/src/java/org/slf4j/LoggerFactory.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j;
+
+// WARNING
+// WARNING Modifications MUST be made to the original file found at
+// WARNING $SLF4J_HOME/src/filtered-java/org/slf4j/LoggerFactory.java
+// WARNING
+
+/**
+ * The <code>LoggerFactory</code> can produce Loggers for various logging APIs,
+ * most notably for log4j, JDK 1.4 logging. Other implemenations such as
+ * {@link org.slf4j.impl.NOPLogger NOPLogger} and
+ * {@link org.slf4j.impl.SimpleLogger SimpleLogger} are also supported.
+ *
+ * @author Ceki Gülcü
+ */
+public class LoggerFactory {
+ static LoggerFactoryAdapter adapter;
+
+ //
+ // WARNING Modify the original in
+ // $SLF4J_HOME/src/filtered-java/org/slf4j/
+
+ static {
+ String adapterClassStr = "org.slf4j.impl.Log4jLoggerFA";
+ System.out.println("SLF4J built for "+adapterClassStr);
+ try {
+ adapter = new org.slf4j.impl.Log4jLoggerFA();
+ } catch (Exception e) {
+ // unless there was a problem with the build or the JVM we will never
+ // get exceptions
+ System.err.println(
+ "Could not instantiate instance of class [" + adapterClassStr + "]");
+ e.printStackTrace();
+ }
+ }
+
+ public static ULogger getLogger(String name) {
+ return adapter.getLogger(name);
+ }
+
+ public static ULogger getLogger(String domainName, String subDomainName) {
+ return adapter.getLogger(domainName, subDomainName);
+ }
+
+ public static ULogger getLogger(Class clazz) {
+ return adapter.getLogger(clazz.getName());
+ }
+
+ public static ULogger getLogger(Class clazz, String subDomainName) {
+ return adapter.getLogger(clazz.getName(), subDomainName);
+ }
+}
diff --git a/src/java/org/slf4j/LoggerFactoryAdapter.java b/src/java/org/slf4j/LoggerFactoryAdapter.java
new file mode 100644
index 0000000..55b047e
--- /dev/null
+++ b/src/java/org/slf4j/LoggerFactoryAdapter.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j;
+
+/**
+ * LoggerFactoryAdapter interface is used internally by {@link
+ * LoggerFactory}.
+ *
+ * <p>Only developers wishing to write new UGLI adapters need to worry
+ * about this interface.
+ *
+ * @author Ceki Gülcü
+ *
+ */
+public interface LoggerFactoryAdapter {
+
+ /**
+ * Return the appropriate named {@link ULogger} instance.
+ */
+ public ULogger getLogger(String name);
+
+ /**
+ * Return a {@link ULogger} instance in <code>domain</code>, <code>subDomain</code>.
+ *
+ * @param domain
+ * @param subDomain
+ * @return ULogger instance
+ */
+ public ULogger getLogger(String domain, String subDomain);
+}
diff --git a/src/java/org/slf4j/ULogger.java b/src/java/org/slf4j/ULogger.java
new file mode 100644
index 0000000..279178e
--- /dev/null
+++ b/src/java/org/slf4j/ULogger.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j;
+
+/**
+ *
+ * The main user inteface to logging. It is expected that logging
+ * takes places through concerete implemetations of the ULogger
+ * interface.
+ *
+ * @author Ceki Gülcü
+ */
+public interface ULogger {
+
+ /**
+ * Is the logger instance enabled for the DEBUG level?
+ * @return True if this ULogger is enabled for the DEBUG level,
+ * false otherwise.
+ */
+ public boolean isDebugEnabled();
+
+ /**
+ * Log a message object with the DEBUG level.
+ * @param msg - the message object to be logged
+ */
+ public void debug(Object msg);
+
+
+ /**
+ * Log a parameterized message object at the DEBUG level.
+ *
+ * <p>This form is useful in avoiding the superflous object creation
+ * problem when invoking this method while it is disabled.
+ * </p>
+ * @param parameterizedMsg - the parameterized message object
+ * @param param1 - the parameter
+ */
+ public void debug(Object parameterizedMsg, Object param1);
+
+ /**
+ * Log a parameterized message object at the DEBUG level.
+ *
+ * <p>This form is useful in avoiding the superflous object creation
+ * problem when invoking this method while it is disabled.
+ * </p>
+ * @param parameterizedMsg - the parameterized message object
+ * @param param1 - the first parameter
+ * @param param2 - the second parameter
+ */
+ public void debug(String parameterizedMsg, Object param1, Object param2);
+ public void debug(Object msg, Throwable t);
+
+
+ public boolean isInfoEnabled();
+ public void info(Object msg);
+ public void info(Object parameterizedMsg, Object param1);
+ public void info(String parameterizedMsg, Object param1, Object param2);
+ public void info(Object msg, Throwable t);
+
+
+ public boolean isWarnEnabled();
+ public void warn(Object msg);
+ public void warn(Object parameterizedMsg, Object param1);
+ public void warn(String parameterizedMsg, Object param1, Object param2);
+ public void warn(Object msg, Throwable t);
+
+
+ public boolean isErrorEnabled();
+ public void error(Object msg);
+ public void error(Object parameterizedMsg, Object param1);
+ public void error(String parameterizedMsg, Object param1, Object param2);
+ public void error(Object msg, Throwable t);
+
+}
diff --git a/src/java/org/slf4j/impl/Log4jLoggerFA.java b/src/java/org/slf4j/impl/Log4jLoggerFA.java
new file mode 100644
index 0000000..0995d49
--- /dev/null
+++ b/src/java/org/slf4j/impl/Log4jLoggerFA.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.slf4j.impl;
+
+import org.apache.log4j.LogManager;
+import org.slf4j.LoggerFactoryAdapter;
+import org.slf4j.ULogger;
+
+/**
+ * This factory adapter relies on log4's {@link LogManager} to do its job.
+ *
+ * @author Ceki Gülcü
+ *
+ */
+public class Log4jLoggerFA implements LoggerFactoryAdapter {
+
+ public Log4jLoggerFA() {
+ }
+
+ /**
+ * Get a {@link ULogger} by name, by delegating all work to log4's
+ * {@link LogManager}.
+ *
+ * <p>The implementation is trivial because log4j
+ * {@link org.apache.log4j.Logger loggers} directly implement the
+ * {@link ULogger} interface.
+ */
+ public ULogger getLogger(String name) {
+ return LogManager.getLogger(name);
+ }
+
+ /**
+ * Get a {@link ULogger} by domain and subdomain name, by delegating all work
+ * to log4's {@link LogManager}.
+ *
+ * <p>The implementation is trivial because log4j
+ * {@link org.apache.log4j.Logger loggers} directly implement the
+ * {@link ULogger} interface.
+ */
+ public ULogger getLogger(String domainName, String subDomainName) {
+ return LogManager.getLogger(domainName);
+ }
+}
+
diff --git a/src/java/org/slf4j/impl/MessageFormatter.java b/src/java/org/slf4j/impl/MessageFormatter.java
new file mode 100644
index 0000000..c650c39
--- /dev/null
+++ b/src/java/org/slf4j/impl/MessageFormatter.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ * Copyright (c) 2004-2005 QOS.ch
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j.impl;
+
+
+/**
+ * Formats messages according to very simple rules.
+ * See {@link #format(String, Object)} and
+ * {@link #format(String, Object, Object)} for more details.
+ *
+ * @author Ceki Gülcü
+ */
+public class MessageFormatter {
+ static final char DELIM_START = '{';
+ static final char DELIM_STOP = '}';
+
+ /**
+ * Performs single argument substitution for the 'messagePattern' passed as
+ * parameter.
+ * <p>
+ * For example, <code>MessageFormatter.format("Hi {}.", "there");</code> will
+ * return the string "Hi there.".
+ * <p>
+ * The {} pair is called the formatting element. It serves to designate the
+ * location where the argument needs to be inserted within the pattern.
+ *
+ * @param messagePattern The message pattern which will be parsed and formatted
+ * @param argument The argument to be inserted instead of the formatting element
+ * @return The formatted message
+ */
+ public static String format(String messagePattern, Object argument) {
+ int j = messagePattern.indexOf(DELIM_START);
+ int len = messagePattern.length();
+ char escape = 'x';
+
+ // if there are no { characters or { is the last character of the messsage
+ // then we just return messagePattern
+ if (j == -1 || (j+1 == len)) {
+ return messagePattern;
+ } else {
+ if(j+1 == len) {
+ }
+
+ char delimStop = messagePattern.charAt(j + 1);
+ if (j > 0) {
+ escape = messagePattern.charAt(j - 1);
+ }
+ if ((delimStop != DELIM_STOP) || (escape == '\\')) {
+ // invalid DELIM_START/DELIM_STOP pair or espace character is
+ // present
+ return messagePattern;
+ } else {
+ StringBuffer sbuf = new StringBuffer(len + 20);
+ sbuf.append(messagePattern.substring(0, j));
+ sbuf.append(argument);
+ sbuf.append(messagePattern.substring(j + 2));
+ return sbuf.toString();
+ }
+ }
+ }
+
+ /**
+ * /**
+ * Performs a two argument substitution for the 'messagePattern' passed as
+ * parameter.
+ * <p>
+ * For example, <code>MessageFormatter.format("Hi {}. My name is {}.",
+ * "there", "David");</code> will return the string "Hi there. My name is David.".
+ * <p>
+ * The '{}' pair is called a formatting element. It serves to designate the
+ * location where the arguments need to be inserted within the message pattern.
+ *
+ * @param messagePattern The message pattern which will be parsed and formatted
+ * @param arg1 The first argument to replace the first formatting element
+ * @param arg2 The second argument to replace the second formatting element
+ * @return The formatted message
+ */
+ public static String format(String messagePattern, Object arg1, Object arg2) {
+ int i = 0;
+ int len = messagePattern.length();
+ int j = messagePattern.indexOf(DELIM_START);
+
+ StringBuffer sbuf = new StringBuffer(messagePattern.length() + 50);
+
+ for (int L = 0; L < 2; L++) {
+ j = messagePattern.indexOf(DELIM_START, i);
+
+ if (j == -1 || (j+1 == len)) {
+ // no more variables
+ if (i == 0) { // this is a simple string
+ return messagePattern;
+ } else { // add the tail string which contains no variables and return the result.
+ sbuf.append(messagePattern.substring(i, messagePattern.length()));
+ return sbuf.toString();
+ }
+ } else {
+ char delimStop = messagePattern.charAt(j + 1);
+ if ((delimStop != DELIM_STOP)) {
+ // invalid DELIM_START/DELIM_STOP pair
+ sbuf.append(messagePattern.substring(i, messagePattern.length()));
+ return sbuf.toString();
+ }
+ sbuf.append(messagePattern.substring(i, j));
+ sbuf.append((L == 0) ? arg1 : arg2);
+ i = j + 2;
+ }
+ }
+ // append the characters following the second {} pair.
+ sbuf.append(messagePattern.substring(i, messagePattern.length()));
+ return sbuf.toString();
+ }
+}
diff --git a/src/java/org/slf4j/impl/NOPLogger.java b/src/java/org/slf4j/impl/NOPLogger.java
new file mode 100644
index 0000000..d0c4820
--- /dev/null
+++ b/src/java/org/slf4j/impl/NOPLogger.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ * Copyright (c) 2004-2005 QOS.ch
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j.impl;
+
+import org.slf4j.ULogger;
+
+
+/**
+ * A no operation (NOP) implementation of {@link ULogger}.
+ *
+ * @author Ceki Gülcü
+ */
+public class NOPLogger implements ULogger {
+
+ /**
+ * The unique instance of NOPLogger.
+ */
+ public final static NOPLogger NOP_LOGGER = new NOPLogger();
+
+ /**
+ * There is no point in people creating multiple instances of NullLogger.
+ * Hence, the private access modifier.
+ */
+ private NOPLogger() {
+ }
+
+ /* Always returns false.
+ *
+ * @see org.slf4j.Logger#isDebugEnabled()
+ */
+ public boolean isDebugEnabled() {
+ return false;
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#debug(java.lang.Object)
+ */
+ public void debug(Object msg) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#debug(java.lang.Object, java.lang.Object)
+ */
+ public void debug(Object parameterizedMsg, Object param1) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#debug(java.lang.Object, java.lang.Object, java.lang.Object)
+ */
+ public void debug(String parameterizedMsg, Object param1, Object param2) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#debug(java.lang.Object, java.lang.Throwable)
+ */
+ public void debug(Object msg, Throwable t) {
+ // NOP
+ }
+
+ /* Always returns false.
+ * @see org.slf4j.Logger#isInfoEnabled()
+ */
+ public boolean isInfoEnabled() {
+ // NOP
+ return false;
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#info(java.lang.Object)
+ */
+ public void info(Object msg) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#info(java.lang.Object, java.lang.Object)
+ */
+ public void info(Object parameterizedMsg, Object param1) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#info(java.lang.Object, java.lang.Object, java.lang.Object)
+ */
+ public void info(String parameterizedMsg, Object param1, Object param2) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#info(java.lang.Object, java.lang.Throwable)
+ */
+ public void info(Object msg, Throwable t) {
+ // NOP
+ }
+
+ /* Always returns false.
+ * @see org.slf4j.Logger#isWarnEnabled()
+ */
+ public boolean isWarnEnabled() {
+ return false;
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#warn(java.lang.Object)
+ */
+ public void warn(Object msg) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#warn(java.lang.Object, java.lang.Object)
+ */
+ public void warn(Object parameterizedMsg, Object param1) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#warn(java.lang.Object, java.lang.Object, java.lang.Object)
+ */
+ public void warn(String parameterizedMsg, Object param1, Object param2) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#warn(java.lang.Object, java.lang.Throwable)
+ */
+ public void warn(Object msg, Throwable t) {
+ // NOP
+ }
+
+ /* Always returns false.
+ * @see org.slf4j.Logger#isErrorEnabled()
+ */
+ public boolean isErrorEnabled() {
+ return false;
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#error(java.lang.Object)
+ */
+ public void error(Object msg) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#error(java.lang.Object, java.lang.Object)
+ */
+ public void error(Object parameterizedMsg, Object param1) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#error(java.lang.Object, java.lang.Object, java.lang.Object)
+ */
+ public void error(String parameterizedMsg, Object param1, Object param2) {
+ // NOP
+ }
+
+ /* A NOP implementation.
+ * @see org.slf4j.Logger#error(java.lang.Object, java.lang.Throwable)
+ */
+ public void error(Object msg, Throwable t) {
+ // NOP
+ }
+
+}
diff --git a/src/java/org/slf4j/impl/NOPLoggerFA.java b/src/java/org/slf4j/impl/NOPLoggerFA.java
new file mode 100644
index 0000000..2d321ad
--- /dev/null
+++ b/src/java/org/slf4j/impl/NOPLoggerFA.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ * Copyright (c) 2004-2005 QOS.ch
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j.impl;
+
+import org.slf4j.LoggerFactoryAdapter;
+import org.slf4j.ULogger;
+
+
+/**
+ * NOPLoggerFA is am implementation of {@link LoggerFactoryAdapter}
+ * which always returns the unique instance of NOPLogger.
+ *
+ * @author Ceki Gulcu
+ */
+public class NOPLoggerFA implements LoggerFactoryAdapter {
+
+ public NOPLoggerFA() {
+ // nothing to do
+ }
+
+ public ULogger getLogger(String name) {
+ return NOPLogger.NOP_LOGGER;
+ }
+ public ULogger getLogger(String domainName, String subDomainName) {
+ return NOPLogger.NOP_LOGGER;
+ }
+}
diff --git a/src/java/org/slf4j/impl/SimpleLogger.java b/src/java/org/slf4j/impl/SimpleLogger.java
new file mode 100644
index 0000000..7b8be4a
--- /dev/null
+++ b/src/java/org/slf4j/impl/SimpleLogger.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ * Copyright (c) 2004-2005 QOS.ch
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j.impl;
+
+import org.slf4j.ULogger;
+
+
+/**
+ * A simple implementation that logs messages of level INFO or higher on
+ * the console (<code>System.out<code>).
+ * <p>
+ * The output includes the relative time in milliseconds, thread name, the level,
+ * logger name, and the message followed by the line separator for the host.
+ * In log4j terms it amounts to the "%r [%t] %level %logger - %m%n" pattern.
+ * <pre>
+176 [main] INFO examples.Sort - Populating an array of 2 elements in reverse order.
+225 [main] INFO examples.SortAlgo - Entered the sort method.
+304 [main] INFO SortAlgo.DUMP - Dump of interger array:
+317 [main] INFO SortAlgo.DUMP - Element [0] = 0
+331 [main] INFO SortAlgo.DUMP - Element [1] = 1
+343 [main] INFO examples.Sort - The next log statement should be an error message.
+346 [main] ERROR SortAlgo.DUMP - Tried to dump an uninitialized array.
+ at org.log4j.examples.SortAlgo.dump(SortAlgo.java:58)
+ at org.log4j.examples.Sort.main(Sort.java:64)
+467 [main] INFO examples.Sort - Exiting main method.
+</pre>
+ *
+ * @author Ceki Gülcü
+ */
+public class SimpleLogger implements ULogger {
+
+ String loggerName;
+
+ /**
+ * Mark the time when this class gets loaded into memory.
+ */
+ static private long startTime = System.currentTimeMillis();
+
+ public static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ static private String INFO_STR = "INFO";
+ static private String WARN_STR = "WARN";
+ static private String ERROR_STR = "ERROR";
+
+ /**
+ * Package access allows only {@link SimpleLoggerFA} to instantiate
+ * SimpleLogger instances.
+ */
+ SimpleLogger(String name) {
+ this.loggerName = name;
+ }
+
+ /**
+ * Always returns false.
+ */
+ public boolean isDebugEnabled() {
+ return false;
+ }
+
+ /**
+ * A NOP implementation.
+ */
+ public void debug(Object msg) {
+ // NOP
+ }
+
+ /**
+ * A NOP implementation.
+ */
+ public void debug(Object parameterizedMsg, Object param1) {
+ // NOP
+ }
+
+ /**
+ * A NOP implementation.
+ */
+ public void debug(String parameterizedMsg, Object param1, Object param2) {
+ // NOP
+ }
+
+ /**
+ * A NOP implementation.
+ */
+ public void debug(Object msg, Throwable t) {
+ // NOP
+ }
+
+ /**
+ * This is our internal implementation for logging regular (non-parameterized)
+ * log messages.
+ *
+ * @param level
+ * @param message
+ * @param t
+ */
+ private void log(String level, String message, Throwable t) {
+ StringBuffer buf = new StringBuffer();
+
+ long millis = System.currentTimeMillis();
+ buf.append(millis-startTime);
+
+ buf.append(" [");
+ buf.append(Thread.currentThread().getName());
+ buf.append("] ");
+
+ buf.append(level);
+ buf.append(" ");
+
+ buf.append(loggerName);
+ buf.append(" - ");
+
+ buf.append(message);
+
+ buf.append(LINE_SEPARATOR);
+
+ System.out.print(buf.toString());
+ if(t != null) {
+ t.printStackTrace(System.out);
+ }
+ System.out.flush();
+ }
+ /**
+ * For parameterized messages, first substitute parameters and then log.
+ *
+ * @param level
+ * @param parameterizedMsg
+ * @param param1
+ * @param param2
+ */
+ private void parameterizedLog(String level, Object parameterizedMsg, Object param1, Object param2) {
+ if (parameterizedMsg instanceof String) {
+ String msgStr = (String) parameterizedMsg;
+ msgStr = MessageFormatter.format(msgStr, param1, param2);
+ log(level, msgStr, null);
+ } else {
+ // To be failsafe, we handle the case where 'messagePattern' is not
+ // a String. Unless the user makes a mistake, this should not happen.
+ log(level, parameterizedMsg.toString(), null);
+ }
+ }
+
+ /**
+ * Always returns true.
+ */
+ public boolean isInfoEnabled() {
+ return true;
+ }
+
+ /**
+ * A simple implementation which always logs messages of level INFO according
+ * to the format outlined above.
+ */
+ public void info(Object msg) {
+ log(INFO_STR, msg.toString(), null);
+ }
+
+
+ /**
+ * Perform single parameter substituion before logging the message of level
+ * INFO according to the format outlined above.
+ */
+ public void info(Object parameterizedMsg, Object param1) {
+ parameterizedLog(INFO_STR, parameterizedMsg, param1, null);
+ }
+
+ /**
+ * Perform double parameter substituion before logging the message of level
+ * INFO according to the format outlined above.
+ */
+
+ public void info(String parameterizedMsg, Object param1, Object param2) {
+ parameterizedLog(INFO_STR, parameterizedMsg, param1, param2);
+ }
+
+ /**
+ * Log a message of level INFO, including an exception.
+ */
+ public void info(Object msg, Throwable t) {
+ log(INFO_STR, msg.toString(), t);
+ }
+
+ /**
+ * Always returns true.
+ */
+ public boolean isWarnEnabled() {
+ return true;
+ }
+
+ /**
+ * A simple implementation which always logs messages of level WARN according
+ * to the format outlined above.
+ */
+ public void warn(Object msg) {
+ log(WARN_STR, msg.toString(), null);
+ }
+
+ /**
+ * Perform single parameter substituion before logging the message of level
+ * WARN according to the format outlined above.
+ */
+ public void warn(Object parameterizedMsg, Object param1) {
+ parameterizedLog(WARN_STR, parameterizedMsg, param1, null);
+ }
+
+ /**
+ * Perform double parameter substituion before logging the message of level
+ * WARN according to the format outlined above.
+ */
+ public void warn(String parameterizedMsg, Object param1, Object param2) {
+ parameterizedLog(WARN_STR, parameterizedMsg, param1, param2);
+ }
+
+ /**
+ * Log a message of level WARN, including an exception.
+ */
+ public void warn(Object msg, Throwable t) {
+ log(WARN_STR, msg.toString(), t);
+ }
+
+ /**
+ * Always returns true.
+ */
+ public boolean isErrorEnabled() {
+ return true;
+ }
+
+ /**
+ * A simple implementation which always logs messages of level ERROR acoording
+ * to the format outlined above.
+ */
+ public void error(Object msg) {
+ log(ERROR_STR, msg.toString(), null);
+ }
+
+
+ /**
+ * Perform single parameter substituion before logging the message of level
+ * ERROR according to the format outlined above.
+ */
+ public void error(Object parameterizedMsg, Object param1) {
+ parameterizedLog(ERROR_STR, parameterizedMsg, param1, null);
+ }
+
+ /**
+ * Perform double parameter substituion before logging the message of level
+ * ERROR according to the format outlined above.
+ */
+ public void error(String parameterizedMsg, Object param1, Object param2) {
+ parameterizedLog(ERROR_STR, parameterizedMsg, param1, param2);
+ }
+
+ /**
+ * Log a message of level ERROR, including an exception.
+ */
+ public void error(Object msg, Throwable t) {
+ log(ERROR_STR, msg.toString(), t);
+ }
+
+}
diff --git a/src/java/org/slf4j/impl/SimpleLoggerFA.java b/src/java/org/slf4j/impl/SimpleLoggerFA.java
new file mode 100644
index 0000000..6b04340
--- /dev/null
+++ b/src/java/org/slf4j/impl/SimpleLoggerFA.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2004-2005 SLF4J.ORG
+ * Copyright (c) 2004-2005 QOS.ch
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+ * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ *
+ */
+
+package org.slf4j.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.slf4j.LoggerFactoryAdapter;
+import org.slf4j.ULogger;
+
+
+/**
+ * An implementation of {@link LoggerFactoryAdapter} which always returns
+ * {@link SimpleLogger} instances.
+ *
+ * @author Ceki Gülcü
+ */
+public class SimpleLoggerFA implements LoggerFactoryAdapter {
+
+ Map map;
+
+ public SimpleLoggerFA() {
+ map = new HashMap();
+ }
+
+
+ /**
+ * Return an appropriate {@link SimpleLogger} instance by name. At this time,
+ *
+ */
+ /**
+ * Return an appropriate {@link SimpleLogger} instance.
+ * */
+ public ULogger getLogger(String name) {
+ ULogger ulogger = (ULogger) map.get(name);
+ if(ulogger == null) {
+ ulogger = new SimpleLogger(name);
+ map.put(name, ulogger);
+ }
+ return ulogger;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.slf4j.LoggerFactoryAdapter#getLogger(java.lang.String, java.lang.String)
+ */
+ public ULogger getLogger(String domainName, String subDomainName) {
+ return getLogger(domainName);
+ }
+
+
+}
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..293419b 100644
--- a/src/xdocs/documentation.xml
+++ b/src/xdocs/documentation.xml
@@ -10,12 +10,22 @@
<section name="Official log4j documentation">
- <p>The following documentation is included with the standard log4j
- distribution and also browsable online:</p>
+ <p>With the exception of the complete manual, the following
+ documentation is included with the standard log4j distribution
+ and also browsable online:
+ </p>
<ul>
<p>
- <li><a href="manual.html"><b>short manual</b></a>,
+ <a
+ href="https://www.qos.ch/shop/products/clm_t.jsp"><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="https://www.qos.ch/shop/products/clm_t.jsp"><b>complete manual</b></a> (commercial),
</li>
</p>
@@ -24,6 +34,12 @@
<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>
@@ -50,22 +66,54 @@
<section name="Articles on log4j">
<ul>
- <li><a href="http://www.vipan.com/htdocs/log4jhelp.html">Don't Use System.out.println!
+ <p>
+ <li><a href="http://www.vipan.com/htdocs/log4jhelp.html">Don't Use System.out.println!
Use Log4j</a> by Vipan Singla
- </li>
+ </li>
+ </p>
- <li><a href="http://builder.com.com/article.jhtml?id=u00820020124kev01.htm">
+ <p><li><a href="http://www.onjava.com/pub/a/onjava/2002/08/07/log4j.html?page=1">
+ Build Flexible Logs With log4j</a> by Vikram Goyal
+ </li></p>
+
+ <p><li><a
+ href="http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/log4j/log4j.html">log4j</a>
+ by Ashley J.S Mills, University Of Birmingham</li></p>
+
+ <p><li><a href="http://www.builder.com.com/article.jhtml?id=u00820020124kev01.htm">
Add logging to your Java Applications</a> by Kevin Brown
- </li>
+ </li></p>
- <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>
+ <p><li><a href="http://www.builder.com.com/article.jhtml?id=u00220020724kev01.htm">
+ How does the Java logging API stack up against log4j?</a> by Kevin Brown
+ </li></p>
- <li>
+ <p><li>
<a href="http://www.opensymphony.com/guidelines/logging.jsp">OpenSymphony Logging Primer</a>
- </li>
- </ul>
+ </li></p>
+
+ <p><li>
+ <a href="http://www.jguru.com/faq/Log4j">log4j FAQ</a> at jGuru
+ </li></p>
+
+ <p><li>
+ <a href="http://qos.ch/logging/thinkAgain.html">Think Again</a> by Ceki Gülcü
+
+ </li></p>
+
+ <p><li> <a href="http://qos.ch/logging/sc.html">Supporting the
+ log4j <code>RepositorySelector</code></a> by Ceki
+ Gülcü
+ </li></p>
+
+ <p><li> <a href="http://rei1.m-plify.com/log4j/">Log4j class
+ diagrams</a>, courtesy of David Tonhofer
+ </li>
+ </p>
+
+ <p><li> <a href="http://www.jug-l.org/log4j.html">Advanced
+ Log4j</a> Louisville JUG presentation by Jonathan Cowherd </li></p>
+ </ul>
<p>If you would like your log4j-relateed article to be listed
here, then please send a note to the <a
diff --git a/src/xdocs/download.xml b/src/xdocs/download.xml
index 6f40fb1..c6e4b3c 100644
--- a/src/xdocs/download.xml
+++ b/src/xdocs/download.xml
@@ -9,13 +9,19 @@
<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.8">
+ <p>log4j 1.2.8 is available in <a
+ href="../jakarta-log4j-1.2.8.tar.gz"><b>TAR.GZ</b></a> format
+ or in <a href="../jakarta-log4j-1.2.8.zip"><b>ZIP</b></a>
+ format.
</p>
-
+ <p>As of release 1.2.8 log4j now searches for the file log4j.xml
+ as well as the file log4j.properties during
+ initialization. See the <a href="HISTORY">HISTORY</a> file for
+ the firther 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 +41,16 @@
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. <em>The recommended pattern for extending the
+ <code>Logger</code> class is wrapping. Moreover, we strongly
+ discourage casual users from subclassing the
+ <code>Category</code> or <code>Logger</code> classes. </em>
</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 quite a few of them!
</p>
@@ -57,9 +65,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>
@@ -69,33 +77,26 @@
<!-- ============================================================================== -->
- <dt><a href="http://www.japhy.de/configLog4j"><b>configLog4j</b></a></dt>
+<!-- <dt><a href="http://www.japhy.de/configLog4j"><b>configLog4j</b></a></dt>
<dd>A graphical log4j configuration editor by Tobias
Dezulian.</dd>
-
+-->
<!-- ============================================================================== -->
<dt>
<a
- href="http://support.klopotek.de/log4j/jdbc/index.html"><b>JDBCAppender</b></a>
+ href="http://www.mannhaupt.com/danko/projects/"><b>JDBCAppender</b></a>
+ </dt>
- </dt> <dd>A <code>JDBCAppender</code> by <a
- href="mailto:t.fenner@klopotek.de">Thomas Fenner</a>. Note
- that log4j 1.2 ships with another <code>JDBCAppender</code>
- written by Kevin Steppe.
+ <dd>A powerful <code>JDBCAppender</code> by Danko Mannhaupt
+ who continues the work of Thomas Fenner. You might find
+ this JDBCAppender more suitable then the one that ships with
+ log4j 1.2.
</dd>
<!-- ============================================================================== -->
- <dt><a
- href="http://developer.jini.org/exchange/projects/log"><b>JINI
- logging service</b></a> (registration required)</dt>
-
- <dd>A log4j wrapper for JINI by Jerome Bernard.</dd>
-
- <!-- ============================================================================== -->
-
<dt><a href="http://qos.ch/"><b>log4j<em>ME</em></b></a></dt>
<dd>Log4j<em>ME</em>, or log4j MiniEdition, is based on the
@@ -132,9 +133,9 @@
</dt>
<dd>Another full-featured graphical log viewer. After a merger
- with a service-orinted company and a change in
- business-orientation, the owners of LogFactor5 have decided
- to donate their product to the log4j project.
+ and the subsequent change in business-orientation, the
+ owners of LogFactor5 have decided to donate their product to
+ the log4j project.
</dd>
<!-- ============================================================================== -->
@@ -198,14 +199,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>
@@ -233,7 +244,13 @@
</dd>
<!-- =========================================================================== -->
+
+ <dt><a href="http://sourceforge.net/projects/qmmslog"><b>qmmslog</b></a></dt>
+ <dd>Qmmslog is a port of log4j to the Qt/C++ platform.
+ </dd>
+
+ <!-- =========================================================================== -->
<dt><a
href="http://log4r.sourceforge.net"><b>log4r</b></a></dt>
<dd>A Powerful Logger for Ruby.
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/src/xdocs/stylesheets/project.xml b/src/xdocs/stylesheets/project.xml
index c5640aa..84432aa 100644
--- a/src/xdocs/stylesheets/project.xml
+++ b/src/xdocs/stylesheets/project.xml
@@ -12,6 +12,7 @@
<item name="Download" href="/download.html"/>
<item name="Documentation" href="/documentation.html"/>
<item name="Plan" href="/plan.html"/>
+ <item name="Wiki" href="http://nagoya.apache.org/wiki/apachewiki.cgi?Log4JProjectPages"/>
<item name="Contact us" href="/contactUs.html"/>
<item name="Contributors" href="/contributors.html"/>
<item name="History" href="/history.html"/>
@@ -26,6 +27,7 @@
</menu>
<menu name="Translations">
+ <item name="Korean" href="http://jakarta.apache-korea.org/log4j/index.html"/>
<item name="Japanese" href="http://www.ingrid.org/jajakarta/log4j/"/>
</menu>
</body>
diff --git a/tests/build.xml b/tests/build.xml
index a249bdd..c89dc58 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>
@@ -98,11 +96,11 @@
<!-- ================================================================= -->
<target name="regression" depends="Minimum, Logger, DOM, CustomLevel,
CustomLogger, PatternLayout,
- HierarchyThreshold, SocketServer,
+ HierarchyThreshold, DefaultInit, SocketServer,
XMLLayout, AsyncAppender,
OptionConverter, BoundedFIFO,
- CyclicBuffer, OR, LevelMatchFilter,
- DRFA"/>
+ CyclicBuffer, PatternParser, OR,
+ LevelMatchFilter, DRFA"/>
<!-- ================================================================= -->
<!-- Longer unit tests -->
@@ -169,10 +167,60 @@
</junit>
</target>
+ <target name="DefaultInit" depends="build">
+ <!-- Delete possible cruft from previous runs. -->
+ <delete file="classes/log4j.xml"/>
+ <delete file="classes/log4j.properties"/>
+
+ <junit printsummary="yes" fork="yes" haltonfailure="yes">
+ <classpath refid="tests.classpath"/>
+ <formatter type="plain" usefile="false"/>
+ <test fork="true" name="org.apache.log4j.defaultInit.TestCase1" />
+ </junit>
+
+ <copy file="input/xml/defaultInit.xml" tofile="classes/log4j.xml"/>
+ <junit printsummary="yes" fork="yes" haltonfailure="yes">
+ <classpath refid="tests.classpath"/>
+ <formatter type="plain" usefile="false"/>
+ <test fork="true" name="org.apache.log4j.defaultInit.TestCase2" />
+ </junit>
+ <delete file="classes/log4j.xml"/>
+
+ <!-- test handling of log4j.defaultInitOverride system property -->
+ <copy file="input/xml/defaultInit.xml" tofile="classes/log4j.xml"/>
+ <junit printsummary="yes" fork="yes" haltonfailure="yes">
+ <jvmarg value="-Dlog4j.defaultInitOverride=true"/>
+ <classpath refid="tests.classpath"/>
+ <formatter type="plain" usefile="false"/>
+ <test fork="true" name="org.apache.log4j.defaultInit.TestCase1" />
+ </junit>
+ <delete file="classes/log4j.xml"/>
+
+ <!-- test default initialization from log4j.xml -->
+ <copy file="input/defaultInit3.properties" tofile="classes/log4j.properties"/>
+ <junit printsummary="yes" fork="yes" haltonfailure="yes">
+ <classpath refid="tests.classpath"/>
+ <formatter type="plain" usefile="false"/>
+ <test fork="true" name="org.apache.log4j.defaultInit.TestCase3" />
+ </junit>
+ <delete file="classes/log4j.properties"/>
+
+ <!-- test default initialization from log4j.properties -->
+ <copy file="input/xml/defaultInit.xml" tofile="classes/log4j.xml"/>
+ <copy file="input/defaultInit3.properties" tofile="classes/log4j.properties"/>
+ <junit printsummary="yes" fork="yes" haltonfailure="yes">
+ <classpath refid="tests.classpath"/>
+ <formatter type="plain" usefile="false"/>
+ <test fork="true" name="org.apache.log4j.defaultInit.TestCase4" />
+ </junit>
+ <delete file="classes/log4j.xml"/>
+ <delete file="classes/log4j.properties"/>
+ </target>
+
<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 +260,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 +292,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/defaultInit3.properties b/tests/input/defaultInit3.properties
new file mode 100644
index 0000000..ce38951
--- /dev/null
+++ b/tests/input/defaultInit3.properties
@@ -0,0 +1,7 @@
+
+log4j.rootCategory=DEBUG, D3
+log4j.appender.D3=org.apache.log4j.FileAppender
+log4j.appender.D3.File=output/temp
+log4j.appender.D3.Append=false
+log4j.appender.D3.layout=org.apache.log4j.PatternLayout
+log4j.appender.D3.layout.ConversionPattern=%d [%t] %-5p %.16c - %m%n
\ No newline at end of file
diff --git a/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/socketServer7.properties b/tests/input/socketServer7.properties
new file mode 100644
index 0000000..ee5169d
--- /dev/null
+++ b/tests/input/socketServer7.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{key7} [%t] %c{1} - %m%n
diff --git a/tests/input/socketServer8.properties b/tests/input/socketServer8.properties
new file mode 100644
index 0000000..e88af64
--- /dev/null
+++ b/tests/input/socketServer8.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{key8} [%t] %c{1} - %m%n
diff --git a/tests/input/xml/defaultInit.xml b/tests/input/xml/defaultInit.xml
new file mode 100644
index 0000000..58adbd4
--- /dev/null
+++ b/tests/input/xml/defaultInit.xml
@@ -0,0 +1,17 @@
+<?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="D1" class="org.apache.log4j.ConsoleAppender">
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %c{2} - %m%n"/>
+ </layout>
+ </appender>
+
+ <root>
+ <priority value ="OFF" />
+ <appender-ref ref="D1" />
+ </root>
+
+</log4j:configuration>
diff --git a/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/LoggerTestCase.java b/tests/src/java/org/apache/log4j/LoggerTestCase.java
index d5f4274..6ffaf4f 100644
--- a/tests/src/java/org/apache/log4j/LoggerTestCase.java
+++ b/tests/src/java/org/apache/log4j/LoggerTestCase.java
@@ -73,8 +73,8 @@
a1.setName("testAppender1");
logger.addAppender(a1);
- Enumeration enum = logger.getAllAppenders();
- Appender aHat = (Appender) enum.nextElement();
+ Enumeration enumeration = logger.getAllAppenders();
+ Appender aHat = (Appender) enumeration.nextElement();
assertEquals(a1, aHat);
}
@@ -93,10 +93,10 @@
logger.addAppender(a1);
logger.addAppender(a2);
logger.removeAppender("testAppender2.1");
- Enumeration enum = logger.getAllAppenders();
- Appender aHat = (Appender) enum.nextElement();
+ Enumeration enumeration = logger.getAllAppenders();
+ Appender aHat = (Appender) enumeration.nextElement();
assertEquals(a2, aHat);
- assertTrue(!enum.hasMoreElements());
+ assertTrue(!enumeration.hasMoreElements());
}
/**
@@ -204,7 +204,7 @@
Logger root = Logger.getRootLogger();
root.addAppender(caRoot);
- LoggerRepository h = Category.getDefaultHierarchy();
+ LoggerRepository h = LogManager.getLoggerRepository();
//h.disableDebug();
h.setThreshold((Level) Level.INFO);
assertEquals(caRoot.counter, 0);
@@ -309,7 +309,7 @@
public
void testHierarchy1() {
- Hierarchy h = new Hierarchy(new RootCategory((Level) Level.ERROR));
+ Hierarchy h = new Hierarchy(new RootLogger((Level) Level.ERROR));
Logger a0 = h.getLogger("a");
assertEquals("a", a0.getName());
assertNull(a0.getLevel());
diff --git a/tests/src/java/org/apache/log4j/MyPatternLayout.java b/tests/src/java/org/apache/log4j/MyPatternLayout.java
index ae8b903..c4cd926 100644
--- a/tests/src/java/org/apache/log4j/MyPatternLayout.java
+++ b/tests/src/java/org/apache/log4j/MyPatternLayout.java
@@ -44,9 +44,9 @@
public
static void main(String[] args) {
Layout layout = new MyPatternLayout("[counter=%.10#] - %m%n");
- Category cat = Category.getInstance("some.cat");
- cat.addAppender(new ConsoleAppender(layout, ConsoleAppender.SYSTEM_OUT));
- cat.debug("Hello, log");
- cat.info("Hello again...");
+ Logger logger = Logger.getLogger("some.cat");
+ logger.addAppender(new ConsoleAppender(layout, ConsoleAppender.SYSTEM_OUT));
+ logger.debug("Hello, log");
+ logger.info("Hello again...");
}
}
diff --git a/tests/src/java/org/apache/log4j/StressCategory.java b/tests/src/java/org/apache/log4j/StressCategory.java
index dbce0a0..05a6389 100644
--- a/tests/src/java/org/apache/log4j/StressCategory.java
+++ b/tests/src/java/org/apache/log4j/StressCategory.java
@@ -9,11 +9,11 @@
import org.apache.log4j.Level;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
import java.util.Random;
/*
- Stress test the Category class.
+ Stress test the Logger class.
*/
@@ -25,11 +25,11 @@
Level.ERROR,
Level.FATAL};
- static Level defaultLevel = Category.getRoot().getLevel();
+ static Level defaultLevel = Logger.getRootLogger().getLevel();
static int LENGTH;
static String[] names;
- static Category[] cat;
+ static Logger[] cat;
static CT[] ct;
static Random random = new Random(10);
@@ -53,7 +53,7 @@
for(int i=0; i < LENGTH; i++) {
names[i] = args[i];
}
- cat = new Category[LENGTH];
+ cat = new Logger[LENGTH];
ct = new CT[LENGTH];
@@ -105,7 +105,7 @@
if(ct[i] == null)
cat[i] = null;
else {
- cat[i] = Category.getInstance(ct[i].catstr);
+ cat[i] = Logger.getLogger(ct[i].catstr);
cat[i].setLevel(ct[i].level);
}
}
@@ -183,7 +183,7 @@
boolean checkCorrectness(int i) {
CT localCT = ct[i];
- // Can't perform test if category is not instantiated
+ // Can't perform test if logger is not instantiated
if(localCT == null)
return true;
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/defaultInit/TestCase1.java b/tests/src/java/org/apache/log4j/defaultInit/TestCase1.java
new file mode 100644
index 0000000..b228766
--- /dev/null
+++ b/tests/src/java/org/apache/log4j/defaultInit/TestCase1.java
@@ -0,0 +1,45 @@
+/*
+ * 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.defaultInit;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.framework.Test;
+
+import java.util.Vector;
+
+import org.apache.log4j.*;
+import org.apache.log4j.performance.NullAppender;
+
+public class TestCase1 extends TestCase {
+
+ public TestCase1(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ }
+
+ public void tearDown() {
+ LogManager.shutdown();
+ }
+
+ public void noneTest() {
+ Logger root = Logger.getRootLogger();
+ boolean rootIsConfigured = root.getAllAppenders().hasMoreElements();
+ assertTrue(!rootIsConfigured);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(new TestCase1("noneTest"));
+ return suite;
+ }
+
+}
+
diff --git a/tests/src/java/org/apache/log4j/defaultInit/TestCase2.java b/tests/src/java/org/apache/log4j/defaultInit/TestCase2.java
new file mode 100644
index 0000000..35ed69d
--- /dev/null
+++ b/tests/src/java/org/apache/log4j/defaultInit/TestCase2.java
@@ -0,0 +1,49 @@
+/*
+ * 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.defaultInit;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.framework.Test;
+
+import java.util.Vector;
+import java.util.Enumeration;
+
+import org.apache.log4j.*;
+import org.apache.log4j.performance.NullAppender;
+
+public class TestCase2 extends TestCase {
+
+ public TestCase2(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ }
+
+ public void tearDown() {
+ LogManager.shutdown();
+ }
+
+ public void xmlTest() {
+ Logger root = Logger.getRootLogger();
+ boolean rootIsConfigured = root.getAllAppenders().hasMoreElements();
+ assertTrue(rootIsConfigured);
+ Enumeration e = root.getAllAppenders();
+ Appender appender = (Appender) e.nextElement();
+ assertEquals(appender.getName(), "D1");
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(new TestCase2("xmlTest"));
+ return suite;
+ }
+
+}
+
diff --git a/tests/src/java/org/apache/log4j/defaultInit/TestCase3.java b/tests/src/java/org/apache/log4j/defaultInit/TestCase3.java
new file mode 100644
index 0000000..e61af6d
--- /dev/null
+++ b/tests/src/java/org/apache/log4j/defaultInit/TestCase3.java
@@ -0,0 +1,49 @@
+/*
+ * 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.defaultInit;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.framework.Test;
+
+import java.util.Vector;
+import java.util.Enumeration;
+
+import org.apache.log4j.*;
+import org.apache.log4j.performance.NullAppender;
+
+public class TestCase3 extends TestCase {
+
+ public TestCase3(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ }
+
+ public void tearDown() {
+ LogManager.shutdown();
+ }
+
+ public void propertiesTest() {
+ Logger root = Logger.getRootLogger();
+ boolean rootIsConfigured = root.getAllAppenders().hasMoreElements();
+ assertTrue(rootIsConfigured);
+ Enumeration e = root.getAllAppenders();
+ Appender appender = (Appender) e.nextElement();
+ assertEquals(appender.getName(), "D3");
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(new TestCase3("propertiesTest"));
+ return suite;
+ }
+
+}
+
diff --git a/tests/src/java/org/apache/log4j/defaultInit/TestCase4.java b/tests/src/java/org/apache/log4j/defaultInit/TestCase4.java
new file mode 100644
index 0000000..19126d1
--- /dev/null
+++ b/tests/src/java/org/apache/log4j/defaultInit/TestCase4.java
@@ -0,0 +1,50 @@
+/*
+ * 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.defaultInit;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.framework.Test;
+
+import java.util.Vector;
+import java.util.Enumeration;
+
+import org.apache.log4j.*;
+import org.apache.log4j.performance.NullAppender;
+
+public class TestCase4 extends TestCase {
+
+ public TestCase4(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ }
+
+ public void tearDown() {
+ LogManager.shutdown();
+ }
+
+ public void combinedTest() {
+ Logger root = Logger.getRootLogger();
+ boolean rootIsConfigured = root.getAllAppenders().hasMoreElements();
+ assertTrue(rootIsConfigured);
+ Enumeration e = root.getAllAppenders();
+ Appender appender = (Appender) e.nextElement();
+ assertEquals(appender.getName(), "D1");
+ assertEquals(e.hasMoreElements(), false);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(new TestCase4("combinedTest"));
+ return suite;
+ }
+
+}
+
diff --git a/tests/src/java/org/apache/log4j/helpers/BoundedFIFOTestCase.java b/tests/src/java/org/apache/log4j/helpers/BoundedFIFOTestCase.java
index 2baa672..64a0440 100644
--- a/tests/src/java/org/apache/log4j/helpers/BoundedFIFOTestCase.java
+++ b/tests/src/java/org/apache/log4j/helpers/BoundedFIFOTestCase.java
@@ -15,8 +15,8 @@
package org.apache.log4j.helpers;
import org.apache.log4j.spi.LoggingEvent;
-import org.apache.log4j.Category;
-import org.apache.log4j.Priority;
+import org.apache.log4j.Logger;
+import org.apache.log4j.Level;
import org.apache.log4j.helpers.BoundedFIFO;
@@ -33,7 +33,7 @@
@author Ceki Gülcü
@since 0.9.1 */
public class BoundedFIFOTestCase extends TestCase {
- static Category cat = Category.getInstance("x");
+ static Logger cat = Logger.getLogger("x");
static int MAX = 1000;
@@ -41,7 +41,7 @@
{
for (int i = 0; i < MAX; i++) {
- e[i] = new LoggingEvent("", cat, Priority.DEBUG, "e"+i, null);
+ e[i] = new LoggingEvent("", cat, Level.DEBUG, "e"+i, null);
}
}
diff --git a/tests/src/java/org/apache/log4j/helpers/CyclicBufferTestCase.java b/tests/src/java/org/apache/log4j/helpers/CyclicBufferTestCase.java
index 221e86f..76caa57 100644
--- a/tests/src/java/org/apache/log4j/helpers/CyclicBufferTestCase.java
+++ b/tests/src/java/org/apache/log4j/helpers/CyclicBufferTestCase.java
@@ -15,8 +15,8 @@
package org.apache.log4j.helpers;
import org.apache.log4j.spi.LoggingEvent;
-import org.apache.log4j.Category;
-import org.apache.log4j.Priority;
+import org.apache.log4j.Logger;
+import org.apache.log4j.Level;
import org.apache.log4j.helpers.CyclicBuffer;
import junit.framework.TestCase;
@@ -32,7 +32,7 @@
*/
public class CyclicBufferTestCase extends TestCase {
- static Category cat = Category.getInstance("x");
+ static Logger cat = Logger.getLogger("x");
static int MAX = 1000;
@@ -40,7 +40,7 @@
{
for (int i = 0; i < MAX; i++) {
- e[i] = new LoggingEvent("", cat, Priority.DEBUG, "e"+i, null);
+ e[i] = new LoggingEvent("", cat, Level.DEBUG, "e"+i, null);
}
}
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..4bcfcd7 100644
--- a/tests/src/java/org/apache/log4j/xml/XMLLayoutTestCase.java
+++ b/tests/src/java/org/apache/log4j/xml/XMLLayoutTestCase.java
@@ -58,6 +58,31 @@
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"));
+ }
+
+ public void testNull() throws Exception {
+ XMLLayout xmlLayout = new XMLLayout();
+ root.addAppender(new FileAppender(xmlLayout, TEMP, false));
+ logger.debug("hi");
+ logger.debug(null);
+ Exception e = new Exception((String) null);
+ logger.debug("hi", e);
+ Transformer.transform(TEMP, FILTERED, new Filter[] {new LineNumberFilter(),
+ new XMLTimestampFilter()});
+ assertTrue(Compare.compare(FILTERED, "witness/xmlLayout.null"));
+ }
+
void common() {
int i = -1;
@@ -71,7 +96,7 @@
logger.warn ("Message " + ++i);
root.warn("Message " + i);
-
+
logger.error("Message " + ++i);
root.error("Message " + i);
@@ -84,13 +109,14 @@
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"));
+ suite.addTest(new XMLLayoutTestCase("testNull"));
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>
+
diff --git a/tests/witness/xmlLayout.null b/tests/witness/xmlLayout.null
new file mode 100644
index 0000000..a6b1c7f
--- /dev/null
+++ b/tests/witness/xmlLayout.null
@@ -0,0 +1,26 @@
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[hi]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[]]></log4j:message>
+</log4j:event>
+
+<log4j:event logger="org.apache.log4j.xml.XMLLayoutTestCase" timestamp="XXX" level="DEBUG" thread="main">
+<log4j:message><![CDATA[hi]]></log4j:message>
+<log4j:throwable><![CDATA[java.lang.Exception
+ at org.apache.log4j.xml.XMLLayoutTestCase.testNull(XMLLayoutTestCase.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)
+]]></log4j:throwable>
+</log4j:event>
+