You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by ce...@apache.org on 2003/01/09 11:57:11 UTC
cvs commit: jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/witness confParsing.1 hello min.1 min.2 shallow.1
ceki 2003/01/09 02:57:11
Added: log4jMini build.xml
log4jMini/docs .cvsignore index.html overview.html
log4jMini/src/java/org/apache/log4j Appender.java
AppenderSkeleton.java Category.java
CategoryKey.java FileAppender.java Hierarchy.java
Layout.java NDC.java PatternLayout.java
Priority.java PropertyConfigurator.java
ProvisionNode.java StressCategory.java
WriterAppender.java package.html
log4jMini/src/java/org/apache/log4j/examples .cvsignore
Makefile Sort.java SortAlgo.java Trivial.java
sort1.lcf sort2.lcf sort3.lcf
log4jMini/src/java/org/apache/log4j/helpers
FormattingInfo.java LogLog.java
OptionConverter.java PatternConverter.java
PatternParser.java
log4jMini/src/java/org/apache/log4j/spi LoggingEvent.java
OptionHandler.java RootCategory.java
log4jMini/src/java/org/apache/log4j/test .cvsignore
.functions ConfigurationFileParsing.java Hello.java
Min.java Shallow.java confParsing hello min shallow
log4jMini/src/java/org/apache/log4j/test/witness
confParsing.1 hello min.1 min.2 shallow.1
Log:
Added log4jMini to CVS repository as requested on the developers list.
Revision Changes Path
1.1 jakarta-log4j/log4jMini/build.xml
Index: build.xml
===================================================================
<project name="log4jMini" default="build" basedir="." >
<property name="version" value="1.2alpha"/>
<!-- The base directory relative to which most targets are built -->
<property name="base" value="."/>
<!-- The directory where source files are stored. -->
<property name="java.source.dir" value="src/java/"/>
<!-- The directory where the package-list file is found, ./ or -->
<!-- build/ -->
<property name="packaging.dir" value="build"/>
<!-- Destination for compiled files -->
<property name="javac.dest" value="dist/classes"/>
<!-- Destination for generated jar files -->
<property name="jar.dest" value="${basedir}"/>
<!-- The jar file that the jar task will generate -->
<property name="log4jMini.jar" value="log4jMini-${version}.jar"/>
<!-- Destination for documentation files generated or not -->
<property name="docs" value="docs"/>
<!-- Destination for javadoc generated files -->
<property name="javadoc.dest" value="docs/api"/>
<!-- The stem where most log4j source code is located. -->
<property name="stem" value="org/apache/log4j"/>
<!-- Some targets needs a more precise stem. -->
<property name="BSTEM" value="${java.source.dir}/${stem}"/>
<!-- Original manifest.mf file before filtering. -->
<property name="manifest.src" value="build/manifest.mf"/>
<!-- Directory where release images go. -->
<property name="dist.images" value="dist/images"/>
<!-- Directory for temporary files. -->
<property name="dist.tmp" value="dist/tmp"/>
<!-- Construct compile classpath -->
<path id="compile.classpath">
<pathelement location="${build.home}/classes"/>
</path>
<target name="junitCheck">
<available classname="junit.framework.TestCase" property="junit-present"/>
</target>
<target name="junit" depends="junitCheck" if="junit-present">
<echo message="JUnit is present."/>
</target>
<!-- ================================================================= -->
<!-- Initialize variables -->
<!-- NOTE: all directories are relative to jakarta-log4j/ -->
<!-- ================================================================= -->
<target name="init">
<tstamp />
</target>
<target name="build" depends="init">
<mkdir dir="${javac.dest}" />
<javac srcdir="${java.source.dir}"
destdir="${javac.dest}"
includes="${stem}/**/*.java, ${stem}/xml/XMLLayout.java,"
excludes="**/examples/**, ${stem}/StressCategory.java"
deprecation="${deprecation}"
debug="on">
<classpath refid="compile.classpath"/>
</javac>
</target>
<!-- ================================================================= -->
<!-- Remove all generated (compiled) class files. -->
<!-- ================================================================= -->
<target name="clean" depends="init">
<delete dir="${javac.dest}/" />
</target>
<!-- ================================================================= -->
<!-- Create log4jMini.jar, excluding tests and other odds and ends. -->
<!-- ================================================================= -->
<target name="jar" depends="build">
<delete>
<fileset dir="${jar.dest}">
<include name="${log4j.jar}"/>
</fileset>
</delete>
<jar jarfile="${jar.dest}/${log4j.jar}" basedir="${javac.dest}"
includes="${stem}/*.class,
${stem}/helpers/*.class,
${stem}/spi/*.class,
${stem}/or/*.class,
${stem}/config/PropertySetter.class
${stem}/config/PropertySetterException.class"
excludes="**/UnitTest**,
**/examples/**,
**/selectors/*.class,
**/servlet/*.class">
<manifest>
<attribute name="Manifest-version" value="1.0"/>
<section name="org/apache/log4j/">
<attribute name="Implementation-Title" value="log4jMini"/>
<attribute name="Implementation-Version" value="${version}"/>
<attribute name="Implementation-Vendor" value="Apache Software Foundation"/>
</section>
</manifest>
</jar>
</target>
<!-- ================================================================= -->
<!-- This target builds the javadoc files. -->
<!-- ================================================================= -->
<target name="javadoc" depends="init">
<mkdir dir="${javadoc.dest}" />
<javadoc sourcepath="${java.source.dir}"
destdir="${javadoc.dest}"
packagenames="org.apache.log4j,
org.apache.log4j.helpers,
org.apache.log4j.spi"
version="true"
protected="true"
author="true"
use="true"
overview="${docs}/overview.html"
doctitle="log4j MicroEdition version ${version}<br>API Specification"
windowtitle="Log4jME Version ${version}"
header="<b>Log4jME ${version}</b>"
bottom="Please <a href=http://lists.sourceforge.net/mailman/listinfo/log4j-announce><b>notify me</b></a> about new log4j releases. <hr>">
<link offline="true"
href="http://java.sun.com/products/jdk/1.2/docs/api"
packageListLoc="${packaging.dir}"/>
</javadoc>
</target>
<!-- ================================================================= -->
<!-- Build a complete distribution. Results go to ${dist.images} -->
<!-- ================================================================= -->
<target name="dist" depends="init, clean, jar">
<delete verbose="true">
<fileset dir=".">
<patternset>
<include name="**/*.bak"/>
<include name="dist/velocity.log"/>
<include name="${BSTEM}/**/temp*"/>
<include name="${BSTEM}/performance/test"/>
<include name="${BSTEM}/test/current.*"/>
<include name="${BSTEM}/test/current.*"/>
<include name="${BSTEM}/examples/test"/>
<include name="${BSTEM}/test/logging.*"/>
<include name="${BSTEM}/test/log4j.properties"/>
<include name="{$BSTEM}/test/socket.lcf"/>
<include name="${BSTEM}/test/file"/>
<include name="${BSTEM}/test/output.*"/>
<include name="${jar.dest}/manifest.mf"/>
<include name="${javac.dest}/*.class"/>
</patternset>
</fileset>
</delete>
<mkdir dir="${dist.images}" />
<mkdir dir="${dist.tmp}/log4jME-${version}" />
<copy todir="${dist.tmp}/log4jME-${version}">
<fileset dir="${base}"
includes="make/**,
src/**,
docs/**,
Makefile,
build/*, build.bat, build.sh,
build/lib/*.jar,
manifest.mf,
INSTALL,
LICENSE.txt,
dist/lib/*.jar,
org/**,
dist/classes/**"
excludes="make/make.loc,
**/*.bak, **/goEnv.bat,
**/.#*"/>
</copy>
<fixcrlf srcdir="${dist.tmp}/log4jME-${version}"
includes="build.sh" cr="remove"/>
<fixcrlf srcdir="${dist.tmp}/log4jME-${version}"
includes="build.bat" cr="add"/>
<chmod dir="${dist.tmp}/log4jME-${version}"
includes="build.sh" perm="+x"/>
<tar tarfile="${dist.images}/log4jME-${version}.tar"
basedir="${dist.tmp}"
includes="log4jME-${version}/**" />
<gzip src="${dist.images}/log4jME-${version}.tar"
zipfile="${dist.images}/log4jME-${version}.tar.gz" />
<zip zipfile="${dist.images}/log4jME-${version}.zip"
basedir="${dist.tmp}"
includes="log4jME-${version}/**" />
<delete dir="${dist.tmp}" />
</target>
</project>
1.1 jakarta-log4j/log4jMini/docs/.cvsignore
Index: .cvsignore
===================================================================
api
1.1 jakarta-log4j/log4jMini/docs/index.html
Index: index.html
===================================================================
<HTML>
<BODY>
<p>Log4jME, or log4j MicroEdition is based on nearly the same code as
<a href="http://jakarta.apache.org/log4j">log4j</a>. However, as the
name indicates the micro-edition is much smaller. It offers the same
client interface such that code compiled for log4jME is 100%
compatible with log4j standard edition. You can choose to upgrade to
log4j standard edition at any time by replacing
<code>log4jME.jar</code> with <code>log4j.jar</code> in your
classpath.
<p>Download log4jME version 1.0beta1 including full source code, class
files and documentation in <a
href="../log4jME-1.0b1.tar.gz"><b>TAR.GZ</b></a> format or in <a
href="../log4jME-1.0b1.zip"><b>ZIP</b></a> format.
<p>You may also browse log4jME <a
href="api/index.html">documentation</a>.
</BODY>
</HTML>
1.1 jakarta-log4j/log4jMini/docs/overview.html
Index: overview.html
===================================================================
<html>
<head>
<title>Log4jME</title>
</head>
<body>
<p>Log4jME, or log4j MicroEdition is based on nearly the same code as
<a href="http://jakarta.apache.org/log4j">log4j</a>. However, as the
name indicates the micro-edition is much smaller. It offers the same
client interface such that code compiled for log4jME is 100%
compatible with log4j standard edition. You can choose to upgrade to
log4j standard edition at any time by replacing
<code>log4jME.jar</code> with <code>log4j.jar</code> in your
classpath.
<p>The features of log4jME are
<ul>
<li><b>Same client interface</b>
<p>The <code>org.apache.log4j.Category</code> shipped with log4jME has
the same interface except support for <code>ResourceBundles</code>,
custom category factories and object renderers.
<p><li><b>Smaller org.apache.log4j.FileAppender</b>
<p>Log4jME contains a modified
<code>org.apache.log4jFileAppender</code> which supports logging to
files and output streams including <code>Systemout</code> and
<code>System.err</code>.
<p><li><b>Smaller org.apache.log4j.PatternLayout</b>
<p>Log4jME contains a modified
<code>org.apache.log4j.PatternLayout</code> which supports the a
limited set of conversion characters namely,
<code>%p</code>,
<code>%t</code>,
<code>%r</code>,
<code>%c</code>,
<code>%m</code>,
<code>%n</code>
as well as literals. In particular, the <code>%d</code> ans
<code>%x</code> conversion characters are not supported.
<p><li><b>Smaller org.apache.log4j.PropertyConfigurator</b>
<p>Log4jME contains a modified
<code>org.apache.log4j.PropertyConfigurator</code> which supports the
same configuration syntax as the <code>PropertyConfigurator</code> in
the standard edition except support for category factories and
renderers.
</ul>
<p>The micro edition does nor offer the same number of appenders and
layouts as in the standard edition. The <code>DOMConfigurator</code>
is also not supported.
</body> </html>
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/Appender.java
Index: Appender.java
===================================================================
package org.apache.log4j;
import org.apache.log4j.spi.LoggingEvent;
/**
Implement this interface for your own strategies for printing log
statements.
@author Ceki Gülcü
*/
public interface Appender {
/**
Release any resources allocated within the appender such as file
handles, network connections, etc.
<p>It is a programming error to append to a closed appender.
@since 0.8.4
*/
public
void close();
/**
Log in Appender specific way. */
public
void doAppend(LoggingEvent event);
/**
Get the name of this appender. The name uniquely identifies the
appender. */
public
String getName();
/**
Set the {@link Layout} for this appender.
@since 0.8.1
*/
public
void setLayout(Layout layout);
/**
Returns this appenders layout.
@since 1.1
*/
public
Layout getLayout();
/**
Set the name of this appender. The name is used by other
components to identify this appender.
@since 0.8.1
*/
public
void setName(String name);
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/AppenderSkeleton.java
Index: AppenderSkeleton.java
===================================================================
package org.apache.log4j;
import org.apache.log4j.Layout;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.OptionHandler;
import org.apache.log4j.helpers.LogLog;
/**
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
implementation has its own layout. */
protected Layout layout;
/** Appenders are named. */
protected String name;
/**
There is no priority threshold filtering by default. */
protected Priority threshold;
/**
Is this appender closed?
*/
protected boolean closed = false;
boolean firstTime = true;
/**
A string constant used in naming the option for setting the
threshold for the appender. See also {@link #setThreshold
setThreshold} method. Current value of this string constant is
<b>Threshold</b>.
<p>Note that all option keys are case sensitive.
*/
public static final String THRESHOLD_OPTION = "Threshold";
/**
Derived appenders should override this method if option structure
requires it. */
public
void activateOptions() {
}
/**
Subclasses of <code>AppenderSkeleton</code> should implement this
method to perform actual logging. See also {@link #doAppend
AppenderSkeleton.doAppend} method.
@since 0.9.0
*/
abstract
protected
void append(LoggingEvent event);
/**
Finalize this appender by calling the imlenentation's
<code>close</code> method.
@since 0.8.4
*/
public
void finalize() {
// An appender might be closed then garbage collected. There is no
// point in closing twice.
if(this.closed)
return;
close();
}
/**
Prints the message and the stack trace of the exception on
<code>System.err</code>. */
public
void error(String message, Exception e) {
if(firstTime) {
LogLog.error(message, e);
firstTime = false;
}
}
/**
Print a the error message passed as parameter on
<code>System.err</code>.
*/
public
void error(String message) {
error(message, null);
}
/**
Returns the layout of this appender. The value may be null.
*/
public
Layout getLayout() {
return layout;
}
/**
Returns the name of this FileAppender.
*/
public
final
String getName() {
return this.name;
}
/**
Returns the string array {{@link #THRESHOLD_OPTION}}.
<p>Configurable Appenders must override this method to return the
additional options they accept. */
public
String[] getOptionStrings() {
return new String[] {THRESHOLD_OPTION};
}
/**
Returns this appenders threshold priority. See the {@link
#setThreshold} method for the meaning of this option.
@since 1.1 */
public
Priority getThreshold() {
return threshold;
}
/**
Check whether the message priority is below the appender's
threshold. If there is no threshold set, then the return value is
always <code>true</code>.
*/
public
boolean isAsSevereAsThreshold(Priority priority) {
return ((threshold == null) || priority.isGreaterOrEqual(threshold));
}
/**
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) {
if(closed) {
LogLog.warn("Appender ["+name+"] is closed.");
}
if(!isAsSevereAsThreshold(event.priority)) {
return;
}
this.append(event);
}
/**
Set the layout for this appender. Note that some appenders have
their own (fixed) layouts or do not use one.
*/
public
void setLayout(Layout layout) {
this.layout = layout;
}
/**
Set the name of this Appender.
*/
public
void setName(String name) {
this.name = name;
}
/**
Configurable Appenders should override this method if they admit
additional options.
All classes derived from {@link AppenderSkeleton} admit the
<b>Threshold</b> option, that is the value of the string constant
{@link #THRESHOLD_OPTION}.
See {@link #setThreshold} method for the meaning of this option.
*/
public
void setOption(String key, String value) {
if(key.equalsIgnoreCase(THRESHOLD_OPTION)) {
threshold = Priority.toPriority(value);
}
}
/**
Set the threshold priority. All log events with lower priority
than the threshold priority are ignored by the appender.
<p>In configuration files this option is specified by setting the
value of the <b>Threshold</b> option to a priority
string, such as "DEBUG", "INFO" and so on.
@since 0.8.3 */
public
void setThreshold(Priority threshold) {
this.threshold = threshold;
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/Category.java
Index: Category.java
===================================================================
/*
* 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. */
// Contibutors: Alex Blewitt <Al...@ioshq.com>
// Markus Oestreicher <oe...@zurich.ibm.com>
// Frank Hoering <fh...@zurich.ibm.com>
// Nelson Minar <ne...@media.mit.edu>
// Jim Cakalic <ji...@na.biomerieux.com>
// Avy Sharell <as...@club-internet.fr>
// Ciaran Treanor <ci...@xelector.com>
// Jeff Turner <je...@socialchange.net.au>
// Michael Horwitz <MH...@siemens.co.za>
// Calvin Chan <ca...@hic.gov.au>
// Aaron Greenhouse <aa...@cs.cmu.edu>
// Beat Meier <bm...@infovia.com.ar>
package org.apache.log4j;
import org.apache.log4j.Priority;
import org.apache.log4j.spi.RootCategory;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.helpers.LogLog;
import java.util.Enumeration;
import java.util.Vector;
import java.util.MissingResourceException;
import java.text.MessageFormat;
import java.util.ResourceBundle;
import java.net.URL;
import java.net.MalformedURLException;
/**
This is the central class in the log4j package. One of the
distintive features of log4j are hierarchical categories and their
evaluation.
<p>See the <a href="../../../../manual.html">user manual</a> for an
introduction on this class.
@author Ceki Gülcü
@author Anders Kristensen */
public class Category {
/**
The hierarchy where categories are attached to by default.
*/
static
public
final Hierarchy defaultHierarchy = new Hierarchy(new
RootCategory(Priority.DEBUG));
/**
The name of this category.
*/
protected String name;
/**
The assigned priority of this category. The
<code>priority</code> variable need not be assined a value in
which case it is inherited form the hierarchy. */
volatile protected Priority priority;
/**
The parent of this category. All categories have at least one
ancestor which is the root category. */
volatile protected Category parent;
// Categories need to know what Hierarchy they are in
protected Hierarchy hierarchy;
/** Array of appenders. */
protected Vector appenderList;
/** Additivity is set to true by default, that is children inherit
the appenders of their ancestors by default. If this variable is
set to <code>false</code> then the appenders found in the
ancestors of this category are not used. However, the children
of this category will inherit its appenders, unless the children
have their additivity flag set to <code>false</code> too. See
the user manual for more details. */
protected boolean additive = true;
/**
This constructor created a new <code>Category</code> instance and
sets its name.
<p>It is intended to be used by sub-classes only. You should not
create categories directly.
@param name The name of the category.
*/
protected
Category(String name) {
this.name = name;
}
/**
Add <code>newAppender</code> to the list of appenders of this
Category instance.
<p>If <code>newAppender</code> is already in the list of
appenders, then it won't be added again.
*/
synchronized
public
void addAppender(Appender newAppender) {
// Null values for newAppender parameter are strictly forbidden.
if(newAppender == null)
return;
if(appenderList == null) {
appenderList = new Vector(1);
}
if(!appenderList.contains(newAppender))
appenderList.addElement(newAppender);
}
public
int appendLoopOnAppenders(LoggingEvent event) {
int size = 0;
Appender appender;
if(appenderList != null) {
size = appenderList.size();
for(int i = 0; i < size; i++) {
appender = (Appender) appenderList.elementAt(i);
appender.doAppend(event);
}
}
return size;
}
/**
Call the appenders in the hierrachy starting at
<code>this</code>. If no appenders could be found, emit a
warning.
<p>This method calls all the appenders inherited from the
hierarchy circumventing any evaluation of whether to log or not
to log the particular log request.
@param LoggingEvent the event to log. */
public
void callAppenders(LoggingEvent event) {
int writes = 0;
for(Category c = this; c != null; c=c.parent) {
// Protected against simultaneous call to addAppender, removeAppender,...
synchronized(c) {
if(c.appenderList != null) {
writes += c.appendLoopOnAppenders(event);
}
if(!c.additive) {
break;
}
}
}
// No appenders in hierarchy, warn user only once.
if(!hierarchy.emittedNoAppenderWarning && writes == 0) {
LogLog.error("No appenders could be found for category (" +
this.getName() + ").");
LogLog.error("Please initialize the log4j system properly.");
hierarchy.emittedNoAppenderWarning = true;
}
}
/**
Log a message object with the {@link Priority#DEBUG DEBUG} priority.
<p>This method first checks if this category is <code>DEBUG</code>
enabled by comparing the priority of this category with the {@link
Priority#DEBUG DEBUG} priority. If this category is
<code>DEBUG</code> enabled, then it invokes all the registered
appenders in this category and also higher in the hierarchy
depending on the value of the additivity flag.
<p><b>WARNING</b> Note that passing a {@link Throwable} to this
method will print the name of the <code>Throwable</code> but no
stack trace. To print a stack trace use the {@link #debug(Object,
Throwable)} form instead.
@param message the message object to log. */
public
void debug(Object message) {
if(hierarchy.enableInt > Priority.DEBUG_INT)
return;
if(Priority.DEBUG.isGreaterOrEqual(this.getChainedPriority())) {
forcedLog(Priority.DEBUG, message, null);
}
}
/**
Log a message object with the <code>DEBUG</code> priority including
the stack trace of the {@link Throwable} <code>t</code> passed as
parameter.
<p>See {@link #debug(Object)} form for more detailed information.
@param message the message object to log.
@param t the exception to log, including its stack trace. */
public
void debug(Object message, Throwable t) {
if(hierarchy.enableInt > Priority.DEBUG_INT)
return;
if(Priority.DEBUG.isGreaterOrEqual(this.getChainedPriority()))
forcedLog(Priority.DEBUG, message, t);
}
/**
Log a message object with the {@link Priority#ERROR ERROR} priority.
<p>This method first checks if this category is <code>ERROR</code>
enabled by comparing the priority of this category with {@link
Priority#ERROR ERROR} priority. If this category is
<code>DEBUG</code> enabled, then it invokes all the registered
appenders in this category and also higher in the hierarchy
depending on the value of the additivity flag.
<p><b>WARNING</b> Note that passing a {@link Throwable} to this
method will print the name of the <code>Throwable</code> but no
stack trace. To print a stack trace use the {@link #error(Object,
Throwable)} form instead.
@param message the message object to log */
public
void error(Object message) {
if(hierarchy.enableInt > Priority.ERROR_INT)
return;
if(Priority.ERROR.isGreaterOrEqual(this.getChainedPriority()))
forcedLog(Priority.ERROR, message, null);
}
/**
Log a message object with the <code>ERROR</code> priority including
the stack trace of the {@link Throwable} <code>t</code> passed as
parameter.
<p>See {@link #error(Object)} form for more detailed information.
@param message the message object to log.
@param t the exception to log, including its stack trace. */
public
void error(Object message, Throwable t) {
if(hierarchy.enableInt > Priority.ERROR_INT)
return;
if(Priority.ERROR.isGreaterOrEqual(this.getChainedPriority()))
forcedLog(Priority.ERROR, message, t);
}
/**
Log a message object with the {@link Priority#FATAL FATAL} priority.
<p>This method first checks if this category is <code>FATAL</code>
enabled by comparing the priority of this category with {@link
Priority#FATAL FATAL} priority. If this category is
<code>DEBUG</code> enabled, then it invokes all the registered
appenders in this category and also higher in the hierarchy
depending on the value of the additivity flag.
<p><b>WARNING</b> Note that passing a {@link Throwable} to this
method will print the name of the Throwable but no stack trace. To
print a stack trace use the {@link #fatal(Object, Throwable)} form
instead.
@param message the message object to log */
public
void fatal(Object message) {
if(hierarchy.enableInt > Priority.FATAL_INT)
return;
if(Priority.FATAL.isGreaterOrEqual(this.getChainedPriority()))
forcedLog(Priority.FATAL, message, null);
}
/**
Log a message object with the <code>FATAL</code> priority including
the stack trace of the {@link Throwable} <code>t</code> passed as
parameter.
<p>See {@link #fatal(Object)} for more detailed information.
@param message the message object to log.
@param t the exception to log, including its stack trace. */
public
void fatal(Object message, Throwable t) {
if(hierarchy.enableInt > Priority.FATAL_INT)
return;
if(Priority.FATAL.isGreaterOrEqual(this.getChainedPriority()))
forcedLog(Priority.FATAL, message, t);
}
/**
This method creates a new logging event and logs the event
without further checks. */
protected
void forcedLog(Priority priority, Object message, Throwable t) {
callAppenders(new LoggingEvent(this, priority, message, t));
}
/**
Get the additivity flag for this Category instance.
*/
public
boolean getAdditivity() {
return additive;
}
/**
Starting from this category, search the category hierarchy for a
non-null priority and return it. Otherwise, return the priority of the
root category.
<p>The Category class is designed so that this method executes as
quickly as possible.
*/
public
Priority getChainedPriority() {
for(Category c = this; c != null; c=c.parent) {
if(c.priority != null)
return c.priority;
}
return null; // If reached will cause an NullPointerException.
}
/**
Return the the {@link Hierarchy} where this <code>Category</code> instance is
attached.
@since 1.1 */
public
Hierarchy getHierarchy() {
return hierarchy;
}
/**
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 priority but inherit
it from the hierarchy. This is one of the central features of
log4j.
@param name The name of the category to retrieve. */
public
static
Category getInstance(String name) {
return defaultHierarchy.getInstance(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.
@since 1.0 */
public
static
Category getInstance(Class clazz) {
return getInstance(clazz.getName());
}
/**
Return the category name. */
public
final
String getName() {
return name;
}
/**
Returns the assigned {@link Priority}, if any, for this Category.
@return Priority - the assigned Priority, can be <code>null</code>.
*/
final
public
Priority getPriority() {
return this.priority;
}
/**
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".
*/
final
public
static
Category getRoot() {
return defaultHierarchy.getRoot();
}
/**
Log a message object with the {@link Priority#INFO INFO} priority.
<p>This method first checks if this category is <code>INFO</code>
enabled by comparing the priority of this category with {@link
Priority#INFO INFO} priority. If this category is
<code>DEBUG</code> enabled, then it invokes all the registered
appenders in this category and also higher in the hierarchy
depending on the value of the additivity flag.
<p><b>WARNING</b> Note that passing a {@link Throwable} to this
method will print the name of the Throwable but no stack trace. To
print a stack trace use the {@link #info(Object, Throwable)} form
instead.
@param message the message object to log */
public
void info(Object message) {
if(hierarchy.enableInt > Priority.INFO_INT)
return;
if(Priority.INFO.isGreaterOrEqual(this.getChainedPriority()))
forcedLog(Priority.INFO, message, null);
}
/**
Log a message object with the <code>INFO</code> priority including
the stack trace of the {@link Throwable} <code>t</code> passed as
parameter.
<p>See {@link #info(Object)} for more detailed information.
@param message the message object to log.
@param t the exception to log, including its stack trace. */
public
void info(Object message, Throwable t) {
if(hierarchy.enableInt > Priority.INFO_INT)
return;
if(Priority.INFO.isGreaterOrEqual(this.getChainedPriority()))
forcedLog(Priority.INFO, message, t);
}
/**
* Check whether this category is enabled for the <code>DEBUG</code>
* priority.
*
* <p> This function is intended to lessen the computational cost of
* disabled log debug statements.
*
* <p> For some <code>cat</code> Category object, when you write,
* <pre>
* cat.debug("This is entry number: " + i );
* </pre>
*
* <p>You incur the cost constructing the message, concatenatiion in
* this case, regardless of whether the message is logged or not.
*
* <p>If you are worried about speed, then you should write
* <pre>
* if(cat.isDebugEnabled()) {
* cat.debug("This is entry number: " + i );
* }
* </pre>
*
* <p>This way you will not incur the cost of parameter
* construction if debugging is disabled for <code>cat</code>. On
* the other hand, if the <code>cat</code> is debug enabled, you
* will incur the cost of evaluating whether the category is debug
* enabled twice. Once in <code>isDebugEnabled</code> and once in
* the <code>debug</code>. This is an insignificant overhead
* since evaluating a category takes about 1%% of the time it
* takes to actually log.
*
* @return boolean - <code>true</code> if this category is debug
* enabled, <code>false</code> otherwise.
* */
public
boolean isDebugEnabled() {
if(hierarchy.enableInt > Priority.DEBUG_INT)
return false;
return Priority.DEBUG.isGreaterOrEqual(this.getChainedPriority());
}
/**
Check whether this category is enabled for a given {@link
Priority} passed as parameter.
See also {@link #isDebugEnabled}.
@return boolean True if this category is enabled for <code>priority</code>.
*/
public
boolean isEnabledFor(Priority priority) {
if(hierarchy.enableInt > priority.level)
return false;
return priority.isGreaterOrEqual(this.getChainedPriority());
}
/**
Check whether this category is enabled for the info priority.
See also {@link #isDebugEnabled}.
@return boolean - <code>true</code> if this category is enabled
for priority info, <code>false</code> otherwise.
*/
public
boolean isInfoEnabled() {
if(hierarchy.enableInt > Priority.INFO_INT)
return false;
return Priority.INFO.isGreaterOrEqual(this.getChainedPriority());
}
/**
Remove all previously added appenders from this Category
instance.
<p>This is useful when re-reading configuration information.
*/
synchronized
public
void removeAllAppenders() {
if(appenderList != null) {
int len = appenderList.size();
for(int i = 0; i < len; i++) {
Appender a = (Appender) appenderList.elementAt(i);
a.close();
}
appenderList.removeAllElements();
appenderList = null;
}
}
/**
Remove the appender passed as parameter form the list of appenders.
@since 0.8.2
*/
synchronized
public
void removeAppender(Appender appender) {
if(appender == null || appenderList == null)
return;
appenderList.removeElement(appender);
}
/**
Remove the appender with the name passed as parameter form the
list of appenders.
@since 0.8.2 */
synchronized
public
void removeAppender(String name) {
if(name == null || appenderList == null) return;
int size = appenderList.size();
for(int i = 0; i < size; i++) {
if(name.equals(((Appender)appenderList.elementAt(i)).getName())) {
appenderList.removeElementAt(i);
break;
}
}
}
/**
Set the additivity flag for this Category instance.
@since 0.8.1
*/
public
void setAdditivity(boolean additive) {
this.additive = additive;
}
/**
Only the Hiearchy class can set the hiearchy of a
category. Default package access is MANDATORY here. */
final
void setHierarchy(Hierarchy hierarchy) {
this.hierarchy = hierarchy;
}
/**
Set the priority of this Category.
<p>Null values are admitted.
*/
public
void setPriority(Priority priority) {
this.priority = priority;
}
/**
Log a message object with the {@link Priority#WARN WARN} priority.
<p>This method first checks if this category is <code>WARN</code>
enabled by comparing the priority of this category with {@link
Priority#WARN WARN} priority. If this category is
<code>DEBUG</code> enabled, then it invokes all the registered
appenders in this category and also higher in the hierarchy
depending on the value of the additivity flag.
<p><b>WARNING</b> Note that passing a {@link Throwable} to this
method will print the name of the Throwable but no stack trace. To
print a stack trace use the {@link #warn(Object, Throwable)} form
instead. <p>
@param message the message object to log. */
public
void warn(Object message) {
if(hierarchy.enableInt > Priority.WARN_INT)
return;
if(Priority.WARN.isGreaterOrEqual(this.getChainedPriority()))
forcedLog(Priority.WARN, message, null);
}
/**
Log a message with the <code>WARN</code> priority including the
stack trace of the {@link Throwable} <code>t</code> passed as
parameter.
<p>See {@link #warn(Object)} for more detailed information.
@param message the message object to log.
@param t the exception to log, including its stack trace. */
public
void warn(Object message, Throwable t) {
if(hierarchy.enableInt > Priority.WARN_INT)
return;
if(Priority.WARN.isGreaterOrEqual(this.getChainedPriority()))
forcedLog(Priority.WARN, message, t);
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/CategoryKey.java
Index: CategoryKey.java
===================================================================
/*
* 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;
/**
CategoryKey is heavily used internally to accelerate hash table searches.
@author Ceki Gülcü
*/
class CategoryKey {
String name;
int hashCache;
CategoryKey(String name) {
this.name = name.intern();
hashCache = name.hashCode();
}
final
public
int hashCode() {
return hashCache;
}
final
public
boolean equals(Object rArg) {
if(this == rArg)
return true;
if(rArg != null && CategoryKey.class == rArg.getClass())
return name == ((CategoryKey)rArg ).name;
else
return false;
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/FileAppender.java
Index: FileAppender.java
===================================================================
/*
* 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. */
package org.apache.log4j;
import java.io.IOException;
import java.io.Writer;
import java.io.FileWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.helpers.LogLog;
// Contibutors: Jens Uwe Pipka <je...@gmx.de>
/**
FileAppender appends log events to the console, to a file, to a
{@link java.io.Writer} or an {@link java.io.OutputStream} depending
on the user's choice.
@author Ceki Gülcü
*/
public class FileAppender extends AppenderSkeleton {
/**
A string constant used in naming the option for setting the
output file. Current value of this string constant is
<b>File</b>.
<p>Note that all option keys are case sensitive.
*/
public static final String FILE_OPTION = "File";
/**
A string constant used in naming the option that determines whether
the output file will be truncated or appended to. Current value
of this string constant is <b>Append</b>.
<p>Note that all option keys are case sensitive.
*/
public static final String APPEND_OPTION = "Append";
/** 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.
*/
protected boolean fileAppend = true;
/**
The name of the log file. */
protected String fileName = null;
protected Writer w;
/**
Is the QuietWriter ours or was it created and passed by the user?
*/
protected boolean wIsOurs = false;
/**
The default constructor does no longer set a default layout nor a
default output target. */
public
FileAppender() {
}
/**
Instantiate a FileAppender and set the output destination to
<code>writer</code>.
<p>The <code>writer</code> must have been opened by the user. */
public
FileAppender(Layout layout, OutputStream os) {
this(layout, new OutputStreamWriter(os));
}
/**
Instantiate a FileAppender and set the output destination to
<code>writer</code>.
<p>The <code>writer</code> must have been opened by the user. */
public
FileAppender(Layout layout, Writer writer) {
this.layout = layout;
this.setWriter(writer);
}
/**
Instantiate a FileAppender and open the file designated by
<code>filename</code>. The opened filename will become the ouput
destination for this appender.
<p>If the <code>append</code> parameter is true, the file will be
appended to. Otherwise, the file desginated by
<code>filename</code> will be truncated before being opened.
*/
public
FileAppender(Layout layout, String filename, boolean append)
throws IOException {
this.layout = layout;
this.setFile(filename, append);
}
/**
Instantiate a FileAppender and open the file designated by
<code>filename</code>. The opened filename will become the output
destination for this appender.
<p>The file will be appended to. */
public
FileAppender(Layout layout, String filename) throws IOException {
this(layout, filename, true);
}
/**
If the a value for {@link #FILE_OPTION} is non-null, then {@link
#setFile} is called with the values of {@link #FILE_OPTION} and
{@link #APPEND_OPTION}.
@since 0.8.1 */
public
void activateOptions() {
if(fileName != null) {
try {
setFile(fileName, fileAppend);
}
catch(java.io.IOException e) {
error("setFile("+fileName+","+fileAppend+") call failed.", e);
}
}
}
/**
This method called by {@link AppenderSkeleton#doAppend}
method.
<p>If the output stream exists an is writable then write a log
statement to the output stream. Otherwise, write a single warning
message to <code>System.err</code>.
<p>The format of the output will depend on this appender's
layout.
*/
public
void append(LoggingEvent event) {
// Reminder: the nesting of calls is:
//
// doAppend()
// - check threshold
// - filter
// - append();
// - checkEntryConditions();
// - subAppend();
if(!checkEntryConditions()) {
return;
}
subAppend(event);
}
/**
This method determines if there is a sense in attempting to append.
<p>It checks whether there is a set output target and also if
there is a set layout. If these checks fail, then the boolean
value <code>false</code> is returned. */
protected
boolean checkEntryConditions() {
if(this.w == null) {
error("No output target set for \""+ name+"\".");
return false;
}
if(this.layout == null) {
error("No layout set for \""+ name+"\".");
return false;
}
return true;
}
/**
Will close the stream opened by a previos {@link #setFile}
call. If the writer is owned by the user it remains untouched.
@see #setFile
@see #setWriter
@since 0.8.4
*/
public
void close() {
this.closed = true;
reset();
}
/**
Close this.writer if opened by setFile or FileAppend(filename..)
*/
protected
void closeWriterIfOurs() {
if(this.wIsOurs && this.w != null) {
try {
this.w.close();
}
catch(java.io.IOException e) {
LogLog.error("Could not close output stream " + w, e);
}
}
}
/**
Retuns the option names for this component, namely the string
array {{@link #FILE_OPTION}, {@link #APPEND_OPTION}} in addition
to the options of its super class {@link AppenderSkeleton}. */
public
String[] getOptionStrings() {
return new String[] {THRESHOLD_OPTION, FILE_OPTION, APPEND_OPTION};
}
/**
<p>Sets and <i>opens</i> the file where the log output will
go. The specified file must be writable.
<p>If there was already an opened stream opened through this
method, then the previous stream is closed first. If the stream
was opened by the user and passed to {@link #setWriter
setWriter}, then the previous stream remains
untouched. It is the users responsability to close it.
@param fileName The path to the log file.
@param boolean If true will append to fileName. Otherwise will
truncate fileName. */
public
synchronized
void setFile(String fileName, boolean append) throws IOException {
reset();
this.w = new FileWriter(fileName, append);
this.fileName = fileName;
this.wIsOurs = true;
}
/**
<p>Sets and <i>opens</i> the file where the log output will
go. The specified file must be writable.
<p>The open mode (append/truncate) will depend on the value of
FileAppend option. If undefined, append mode is used.
@param fileName The name of the log file.
*/
public
void setFile(String fileName) throws IOException {
this.setFile(fileName, fileAppend);
}
/**
Set FileAppender specific options.
The recognized options are <b>File</b> and <b>Append</b>,
i.e. the values of the string constants {@link #FILE_OPTION} and
respectively {@link #APPEND_OPTION}. The options of the super
class {@link AppenderSkeleton} are also recognized.
<p>The <b>File</b> option takes a string value which should be
one of the strings "System.out" or "System.err" or the name of a
file.
<p>If the option is set to "System.out" or "System.err" the
output will go to the corresponding stream. Otherwise, if the
option is set to the name of a file, then the file will be opened
and output will go there.
<p>The <b>Append</b> option takes a boolean value. It is set to
<code>true</code> by default. If true, then <code>File</code>
will be opened in append mode by {@link #setFile setFile} (see
above). Otherwise, {@link #setFile setFile} will open
<code>File</code> in truncate mode.
<p>Note: Actual opening of the file is made when {@link
#activateOptions} is called, not when the options are set.
@since 0.8.1 */
public
void setOption(String key, String value) {
if(value == null) return;
super.setOption(key, value);
if(key.equalsIgnoreCase(FILE_OPTION)) {
// Trim spaces from both ends. The users probably does not want
// trailing spaces in file names.
value = value.trim();
if(value.equalsIgnoreCase("System.out"))
setWriter(new OutputStreamWriter(System.out));
else if(value.equalsIgnoreCase("System.err"))
setWriter(new OutputStreamWriter(System.err));
else {
fileName = value;
}
} else if (key.equalsIgnoreCase(APPEND_OPTION)) {
fileAppend = OptionConverter.toBoolean(value, fileAppend);
}
}
/**
<p>Sets the Writer where the log output will go. The
specified Writer must be opened by the user and be
writable.
<p>If there was already an opened stream opened through the {@link
#setFile setFile} method, then the previous stream is closed
first. If the stream was opened by the user and passed to this
method, then the previous stream remains untouched. It is the
user's responsability to close it.
<p><b>WARNING:</b> Logging to an unopened Writer will fail.
<p>
@param Writer An already opened Writer.
@return Writer The previously attached Writer.
*/
public
synchronized
void setWriter(Writer writer) {
reset();
this.w = writer;
this.wIsOurs = false;
}
/**
Actual writing occurs here.
<p>Most sub-classes of <code>FileAppender</code> will need to
override this method.
@since 0.9.0 */
protected
void subAppend(LoggingEvent event) {
this.write(this.layout.format(event));
if(layout.ignoresThrowable()) {
String s = event.getThrowableStr();
if (s != null) {
write(s);
}
}
try {
w.flush();
} catch(IOException e) {
error("Failed to flush", e);
}
}
/**
The FileAppender requires a layout. Hence, this method returns
<code>true</code>.
@since 0.8.4 */
public
boolean requiresLayout() {
return true;
}
protected
void reset() {
closeWriterIfOurs();
this.fileName = null;
this.w = null;
}
public
void write(String string) {
try {
w.write(string);
} catch(IOException e) {
error("Failed to writing", e);
}
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/Hierarchy.java
Index: Hierarchy.java
===================================================================
/*
* 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. */
// WARNING This class MUST not have references to the Category or
// WARNING RootCategory classes in its static initiliazation neither
// WARNING directly nor indirectly.
// Contributors:
// Luke Blanshard <lu...@quiq.com>
// Mario Schomburg - IBM Global Services/Germany
// Anders Kristensen
// Igor Poteryaev
package org.apache.log4j;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Vector;
import org.apache.log4j.spi.RootCategory;
import org.apache.log4j.Appender;
import org.apache.log4j.helpers.LogLog;
/**
This class is specialized in retrieving categories by name and
also maintaining the category hierarchy.
<p><em>The casual user should not have to deal with this class
directly.</em> In fact, up until version 0.9.0, this class had
default package access.
<p>The structure of the category hierarchy is maintained by the
{@link #getInstance} method. The hierarchy is such that children
link to their parent but parents do not have any pointers to their
children. Moreover, categories can be instantiated in any order, in
particular descendant before ancestor.
<p>In case a descendant is created before a particular ancestor,
then it creates a provision node for the ancestor and adds itself
to the provision node. Other descendants of the same ancestor add
themselves to the previously created provision node.
@author Ceki Gülcü
*/
public class Hierarchy {
Hashtable ht;
Category root;
int enableInt;
Priority enable;
boolean emittedNoAppenderWarning = false;
boolean emittedNoResourceBundleWarning = false;
/**
Create a new Category hierarchy.
@param root The root of the new hierarchy.
*/
public
Hierarchy(Category root) {
ht = new Hashtable();
this.root = root;
// Enable all priority levels by default.
enable(Priority.ALL);
this.root.setHierarchy(this);
}
/**
Enable all logging priorities for this hierarchy. This is the
default.
*/
public
void enableAll() {
enable(Priority.ALL);
}
public
void enable(Priority p) {
if(p != null) {
enableInt = p.level;
enable = p;
}
}
/**
Returns the string representation of the internal
<code>enable</code> state.
@since 1.2
*/
public
Priority getEnable() {
return enable;
}
/**
Return a new category instance named as the first parameter using
<code>factory</code>.
<p>If a category of that name already exists, then it will be
returned. Otherwise, a new category will be instantiated by the
<code>factory</code> parameter and linked with its existing
ancestors as well as children.
@param name The name of the category to retrieve.
@param factory The factory that will make the new category instance.
*/
public
Category getInstance(String name) {
//System.out.println("getInstance("+name+") called.");
CategoryKey key = new CategoryKey(name);
// Synchronize to prevent write conflicts. Read conflicts (in
// getChainedPriority method) are possible only if variable
// assignments are non-atomic.
Category category;
synchronized(ht) {
Object o = ht.get(key);
if(o == null) {
category = new Category(name);
category.setHierarchy(this);
ht.put(key, category);
updateParents(category);
return category;
} else if(o instanceof Category) {
return (Category) o;
} else if (o instanceof ProvisionNode) {
category = new Category(name);
category.setHierarchy(this);
ht.put(key, category);
updateChildren((ProvisionNode) o, category);
updateParents(category);
return category;
}
else {
// It should be impossible to arrive here
return null; // but let's keep the compiler happy.
}
}
}
/**
Get the root of this hierarchy.
@since 0.9.0
*/
public
Category getRoot() {
return root;
}
/**
This method loops through all the *potential* parents of
'cat'. There 3 possible cases:
1) No entry for the potential parent of 'cat' exists
We create a ProvisionNode for this potential parent and insert
'cat' in that provision node.
2) There entry is of type Category for the potential parent.
The entry is 'cat's nearest existing parent. We update cat's
parent field with this entry. We also break from the loop
because updating our parent's parent is our parent's
responsibility.
3) There entry is of type ProvisionNode for this potential parent.
We add 'cat' to the list of children for this potential parent.
*/
final
private
void updateParents(Category cat) {
String name = cat.name;
int length = name.length();
boolean parentFound = false;
//System.out.println("UpdateParents called for " + name);
// if name = "w.x.y.z", loop thourgh "w.x.y", "w.x" and "w", but not "w.x.y.z"
for(int i = name.lastIndexOf('.', length-1); i >= 0;
i = name.lastIndexOf('.', i-1)) {
String substr = name.substring(0, i);
//System.out.println("Updating parent : " + substr);
CategoryKey key = new CategoryKey(substr); // simple constructor
Object o = ht.get(key);
// Create a provision node for a future parent.
if(o == null) {
//System.out.println("No parent "+substr+" found. Creating ProvisionNode.");
ProvisionNode pn = new ProvisionNode(cat);
ht.put(key, pn);
} else if(o instanceof Category) {
parentFound = true;
cat.parent = (Category) o;
//System.out.println("Linking " + cat.name + " -> " + ((Category) o).name);
break; // no need to update the ancestors of the closest ancestor
} else if(o instanceof ProvisionNode) {
((ProvisionNode) o).addElement(cat);
} else {
Exception e = new IllegalStateException("unexpected object type " +
o.getClass() + " in ht.");
e.printStackTrace();
}
}
// If we could not find any existing parents, then link with root.
if(!parentFound)
cat.parent = root;
}
/**
We update the links for all the children that placed themselves
in the provision node 'pn'. The second argument 'cat' is a
reference for the newly created Category, parent of all the
children in 'pn'
We loop on all the children 'c' in 'pn':
If the child 'c' has been already linked to a child of
'cat' then there is no need to update 'c'.
Otherwise, we set cat's parent field to c's parent and set
c's parent field to cat.
*/
final
private
void updateChildren(ProvisionNode pn, Category cat) {
//System.out.println("updateChildren called for " + cat.name);
final int last = pn.size();
for(int i = 0; i < last; i++) {
Category c = (Category) pn.elementAt(i);
//System.out.println("Updating child " +p.name);
// Unless this child already points to a correct (lower) parent,
// make cat.parent point to c.parent and c.parent to cat.
if(!c.parent.name.startsWith(cat.name)) {
cat.parent = c.parent;
c.parent = cat;
}
}
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/Layout.java
Index: Layout.java
===================================================================
/*
* 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;
import org.apache.log4j.spi.OptionHandler;
import org.apache.log4j.spi.LoggingEvent;
/**
Extend this abstract class to create your own log layout format.
@author Ceki Gülcü
*/
public abstract class Layout implements OptionHandler {
// Note that the line.separator property can be looked up even by
// applets.
public final static String LINE_SEP = System.getProperty("line.separator");
public final static int LINE_SEP_LEN = LINE_SEP.length();
/**
Implement this method to create your own layout format.
*/
abstract
public
String format(LoggingEvent event);
/**
If the layout handles the throwable object contained within
{@link LoggingEvent}, then the layout should return
<code>false</code>. Otherwise, if the layout ignores throwable
object, then the layout should return <code>true</code>.
@since 1.0 */
abstract
public
boolean ignoresThrowable();
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/NDC.java
Index: NDC.java
===================================================================
/*
* 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.
*/
// Contributors: Dan Milstein
// Ray Millard
package org.apache.log4j;
import java.util.Hashtable;
import java.util.Stack;
import java.util.Enumeration;
import java.util.Vector;
import org.apache.log4j.helpers.LogLog;
/**
The NDC class implements <i>nested diagnostic contexts</i> as
defined by Neil Harrison in the article "Patterns for Logging
Diagnostic Messages" part of the book "<i>Pattern Languages of
Program Design 3</i>" edited by Martin et al.
<p>A Nested Diagnostic Context, or NDC in short, is an instrument
to distinguish interleaved log output from different sources. Log
output is typically interleaved when a server handles multiple
clients near-simultaneously.
<p>Interleaved log output can still be meaningful if each log entry
from different contexts had a distinctive stamp. This is where NDCs
come into play.
<p><em><b>Note that NDCs are managed on a per thread
basis</b></em>. NDC operations such as {@link #push push}, {@link
#pop}, {@link #clear}, {@link #getDepth} and {@link #setMaxDepth}
affect the NDC of the <em>current</em> thread only. NDCs of other
threads remain unaffected.
<p>For example, a servlet can build a per client request NDC
consisting the clients host name and other information contained in
the the request. <em>Cookies</em> are another source of distinctive
information. To build an NDC one uses the {@link #push push}
operation. Simply put,
<p><ul>
<li>Contexts can be nested.
<p><li>When entering a context, call <code>NDC.push</code>. As a
side effect, if there is no nested diagnostic context for the
current thread, this method will create it.
<p><li>When leaving a context, call <code>NDC.pop</code>.
<p><li><b>When exiting a thread make sure to call {@link #remove
NDC.remove()}</b>.
</ul>
<p>There is no penalty for forgetting to match each
<code>push</code> operation with a corresponding <code>pop</code>,
except the obvious mismatch between the real application context
and the context set in the NDC.
<p>If configured to do so, {@link PatternLayout} and {@link
TTCCLayout} instances automatically retrieve the nested diagnostic
context for the current thread without any user intervention.
Hence, even if a servlet is serving multiple clients
simultaneously, the logs emanating from the same code (belonging to
the same category) can still be distinguished because each client
request will have a different NDC tag.
<p>Heavy duty systems should call the {@link #remove} method when
leaving the run method of a thread. This ensures that the memory
used by the thread can be freed by the Java garbage
collector. There is a mechanism to lazily remove references to dead
threads. In practice, this means that you can be a little sloppy
and sometimes forget to call {@link #remove} before exiting a
thread.
<p>A thread may inherit the nested diagnostic context of another
(possibly parent) thread using the {@link #inherit inherit}
method. A thread may obtain a copy of its NDC with the {@link
#cloneStack cloneStack} method and pass the reference to any other
thread, in particular to a child.
@author Ceki Gülcü
@since 0.7.0
*/
public class NDC {
// The synchronized keyword is not used in this class. This may seem
// dangerous, especially since the class will be used by
// multiple-threads. In particular, all threads share the same
// hashtable (the "ht" variable). This is OK since java hashtables
// are thread safe. Same goes for Stacks.
// More importantly, when inheriting diagnostic contexts the child
// thread is handed a clone of the parent's NDC. It follows that
// each thread has its own NDC (i.e. stack).
static Hashtable ht = new Hashtable();
static int pushCounter = 0; // the number of times push has been called
// after the latest call to lazyRemove
// The number of times we allow push to be called before we call lazyRemove
// 5 is a relatively small number. As such, lazyRemove is not called too
// frequently. We thus avoid the cost of creating an Enumeration too often.
// The higher this number, the longer is the avarage period for which all
// logging calls in all threads are blocked.
static final int REAP_THRESHOLD = 5;
// No instances allowed.
private NDC() {}
/**
Clear any nested diagnostic information if any. This method is
useful in cases where the same thread can be potentially used
over and over in different unrelated contexts.
<p>This method is equivalent to calling the {@link #setMaxDepth}
method with a zero <code>maxDepth</code> argument.
@since 0.8.4c */
public
static
void clear() {
Stack stack = (Stack) ht.get(Thread.currentThread());
if(stack != null)
stack.setSize(0);
}
/**
Clone the diagnostic context for the current thread.
<p>Internally a diagnostic context is represented as a stack. A
given thread can supply the stack (i.e. diagnostic context) to a
child thread so that the child can inherit the parent thread's
diagnostic context.
<p>The child thread uses the {@link #inherit inherit} method to
inherit the parent's diagnostic context.
@return Stack A clone of the current thread's diagnostic context.
*/
public
static
Stack cloneStack() {
Object o = ht.get(Thread.currentThread());
if(o == null)
return null;
else {
Stack stack = (Stack) o;
return (Stack) stack.clone();
}
}
/**
Inherit the diagnostic context of another thread.
<p>The parent thread can obtain a reference to its diagnostic
context using the {@link #cloneStack} method. It should
communicate this information to its child so that it may inherit
the parent's diagnostic context.
<p>The parent's diagnostic context is cloned before being
inherited. In other words, once inherited, the two diagnostic
contexts can be managed independently.
<p>In java, a child thread cannot obtain a reference to its
parent, unless it is directly handed the reference. Consequently,
there is no client-transparent way of inheriting diagnostic
contexts. Do you know any solution to this problem?
@param stack The diagnostic context of the parent thread.
*/
public
static
void inherit(Stack stack) {
if(stack != null)
ht.put(Thread.currentThread(), stack);
}
/**
<font color="#FF4040"><b>Never use this method directly, use the {@link
org.apache.log4j.spi.LoggingEvent#getNDC} method instead.</b></font>
*/
static
public
String get() {
Stack s = (Stack) ht.get(Thread.currentThread());
if(s != null && !s.isEmpty())
return ((DiagnosticContext) s.peek()).fullMessage;
else
return null;
}
/**
Get the current nesting depth of this diagnostic context.
@see #setMaxDepth
@since 0.7.5
*/
public
static
int getDepth() {
Stack stack = (Stack) ht.get(Thread.currentThread());
if(stack == null)
return 0;
else
return stack.size();
}
private
static
void lazyRemove() {
// The synchronization on ht is necessary to prevent JDK 1.2.x from
// throwing ConcurrentModificationExceptions at us. This sucks BIG-TIME.
// One solution is to write our own hashtable implementation.
Vector v;
synchronized(ht) {
// Avoid calling clean-up too often.
if(++pushCounter <= REAP_THRESHOLD) {
return; // We release the lock ASAP.
} else {
pushCounter = 0; // OK let's do some work.
}
int misses = 0;
v = new Vector();
Enumeration enum = 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();
if(t.isAlive()) {
misses++;
} else {
misses = 0;
v.addElement(t);
}
}
} // synchronized
int size = v.size();
for(int i = 0; i < size; i++) {
Thread t = (Thread) v.elementAt(i);
LogLog.debug("Lazy NDC removal for thread [" + t.getName() + "] ("+
ht.size() + ").");
ht.remove(t);
}
}
/**
Clients should call this method before leaving a diagnostic
context.
<p>The returned value is the value that was pushed last. If no
context is available, then the empty string "" is returned.
@return String The innermost diagnostic context.
*/
public
static
String pop() {
Thread key = Thread.currentThread();
Stack stack = (Stack) ht.get(key);
if(stack != null && !stack.isEmpty())
return ((DiagnosticContext) stack.pop()).message;
else
return "";
}
/**
Looks at the last diagnostic context at the top of this NDC
without removing it.
<p>The returned value is the value that was pushed last. If no
context is available, then the empty string "" is returned.
@return String The innermost diagnostic context.
*/
public
static
String peek() {
Thread key = Thread.currentThread();
Stack stack = (Stack) ht.get(key);
if(stack != null && !stack.isEmpty())
return ((DiagnosticContext) stack.peek()).message;
else
return "";
}
/**
Push new diagnostic context information for the current thread.
<p>The contents of the <code>message</code> parameter is
determined solely by the client.
@param message The new diagnostic context information. */
public
static
void push(String message) {
Thread key = Thread.currentThread();
Stack stack = (Stack) ht.get(key);
if(stack == null) {
DiagnosticContext dc = new DiagnosticContext(message, null);
stack = new Stack();
ht.put(key, stack);
stack.push(dc);
} else if (stack.isEmpty()) {
DiagnosticContext dc = new DiagnosticContext(message, null);
stack.push(dc);
} else {
DiagnosticContext parent = (DiagnosticContext) stack.peek();
stack.push(new DiagnosticContext(message, parent));
}
}
/**
Remove the diagnostic context for this thread.
<p>Each thread that created a diagnostic context by calling
{@link #push} should call this method before exiting. Otherwise,
the memory used by the <b>thread</b> cannot be reclaimed by the
VM.
<p>As this is such an important problem in heavy duty systems and
because it is difficult to always guarantee that the remove
method is called before exiting a thread, this method has been
augmented to lazily remove references to dead threads. In
practice, this means that you can be a little sloppy and
occasionally forget to call {@link #remove} before exiting a
thread. However, you must call <code>remove</code> sometime. If
you never call it, then your application is sure to run out of
memory.
*/
static
public
void remove() {
ht.remove(Thread.currentThread());
// Lazily remove dead-thread references in ht.
lazyRemove();
}
/**
Set maximum depth of this diagnostic context. If the current
depth is smaller or equal to <code>maxDepth</code>, then no
action is taken.
<p>This method is a convenient alternative to multiple {@link
#pop} calls. Moreover, it is often the case that at the end of
complex call sequences, the depth of the NDC is
unpredictable. The <code>setMaxDepth</code> method circumvents
this problem.
<p>For example, the combination
<pre>
void foo() {
int depth = NDC.getDepth();
... complex sequence of calls
NDC.setMaxDepth(depth);
}
</pre>
ensures that between the entry and exit of foo the depth of the
diagnostic stack is conserved.
@see #getDepth
@since 0.7.5 */
static
public
void setMaxDepth(int maxDepth) {
Stack stack = (Stack) ht.get(Thread.currentThread());
if(stack != null && maxDepth < stack.size())
stack.setSize(maxDepth);
}
// =====================================================================
private static class DiagnosticContext {
String fullMessage;
String message;
DiagnosticContext(String message, DiagnosticContext parent) {
this.message = message;
if(parent != null) {
fullMessage = parent.fullMessage + ' ' + message;
} else {
fullMessage = message;
}
}
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/PatternLayout.java
Index: PatternLayout.java
===================================================================
/*
* 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 file.
*/
package org.apache.log4j;
import org.apache.log4j.Category;
import org.apache.log4j.Priority;
import org.apache.log4j.Layout;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.NDC;
import org.apache.log4j.helpers.PatternParser;
import org.apache.log4j.helpers.PatternConverter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.Vector;
import java.text.FieldPosition;
// Contributors: Nelson Minar <ne...@monkey.org>
// Anders Kristensen <ak...@dynamicsoft.com>
/**
A flexible layout configurable with pattern string.
<p>The goal of this class is to {@link #format format} a {@link
LoggingEvent} and return the results as a String. The results
depend on the <em>conversion pattern</em>.
<p>The conversion pattern is closely related to the conversion
pattern of the printf function in C. A conversion pattern is
composed of literal text and format control expressions called
<em>conversion specifiers</em>.
<p><i>You are free to insert any literal text within the conversion
pattern.</i>
<p>Each conversion specifier starts with a percent sign (%) and is
followed by optional <em>format modifiers</em> and a <em>conversion
character</em>. The conversion character specifies the type of
data, e.g. category, priority, date, thread name. The format
modifiers control such things as field width, padding, left and
right justification. The following is a simple example.
<p>Let the conversion pattern be <b>"%-5p [%t]: %m%n"</b> and assume
that the log4j environment was set to use a PatternLayout. Then the
statements
<pre>
Category root = Category.getRoot();
root.debug("Message 1");
root.warn("Message 2");
</pre>
would yield the output
<pre>
DEBUG [main]: Message 1
WARN [main]: Message 2
</pre>
<p>Note that there is no explicit separator between text and
conversion specifiers. The pattern parser knows when it has reached
the end of a conversion specifier when it reads a conversion
character. In the example above the conversion specifier
<b>%-5p</b> means the priority of the logging event should be left
justified to a width of five characters.
The recognized conversion characters are
<p>
<table border="1" CELLPADDING="8">
<th>Conversion Character</th>
<th>Effect</th>
<tr>
<td align=center><b>c</b></td>
<td>Used to output the category of the logging event. The
category conversion specifier can be optionally followed by
<em>precision specifier</em>, that is a decimal constant in
brackets.
<p>If a precision specifier is given, then only the corresponding
number of right most components of the category name will be
printed. By default the category name is printed in full.
<p>For example, for the category name "a.b.c" the pattern
<b>%c{2}</b> will output "b.c".
</td>
</tr>
<tr>
<td align=center><b>C</b></td>
<td>Used to output the fully qualified class name of the caller
issuing the logging request. This conversion specifier
can be optionally followed by <em>precision specifier</em>, that
is a decimal constant in brackets.
<p>If a precision specifier is given, then only the corresponding
number of right most components of the class name will be
printed. By default the class name is output in fully qualified form.
<p>For example, for the class name "org.apache.xyz.SomeClass", the
pattern <b>%C{1}</b> will output "SomeClass".
<p><b>WARNING</b> Generating the caller class information is
slow. Thus, it's use should be avoided unless execution speed is
not an issue.
</td>
</tr>
<tr>
<td align=center><b>F</b></td>
<td>Used to output the file name where the logging request was
issued.
<p><b>WARNING</b> Generating caller location information is
extremely slow. It's use should be avoided unless execution speed
is not an issue.
</tr>
<tr>
<td align=center><b>l</b></td>
<td>Used to output location information of the caller which generated
the logging event.
<p>The location information depends on the JVM implementation but
usually consists of the fully qualified name of the calling
method followed by the callers source the file name and line
number between parentheses.
<p>The location information can be very useful. However, it's
generation is <em>extremely</em> slow. It's use should be avoided
unless execution speed is not an issue.
</td>
</tr>
<tr>
<td align=center><b>L</b></td>
<td>Used to output the line number from where the logging request
was issued.
<p><b>WARNING</b> Generating caller location information is
extremely slow. It's use should be avoided unless execution speed
is not an issue.
</tr>
<tr>
<td align=center><b>m</b></td>
<td>Used to output the application supplied message associated with
the logging event.</td>
</tr>
<tr>
<td align=center><b>M</b></td>
<td>Used to output the method name where the logging request was
issued.
<p><b>WARNING</b> Generating caller location information is
extremely slow. It's use should be avoided unless execution speed
is not an issue.
</tr>
<tr>
<td align=center><b>n</b></td>
<td>Outputs the platform dependent line separator character or
characters.
<p>This conversion character offers practically the same
performance as using non-portable line separator strings such as
"\n", or "\r\n". Thus, it is the preferred way of specifying a
line separator.
</tr>
<tr>
<td align=center><b>p</b></td>
<td>Used to output the priority of the logging event.</td>
</tr>
<tr>
<td align=center><b>r</b></td>
<td>Used to output the number of milliseconds elapsed since the start
of the application until the creation of the logging event.</td>
</tr>
<tr>
<td align=center><b>t</b></td>
<td>Used to output the name of the thread that generated the
logging event.</td>
</tr>
<tr>
<td align=center><b>x</b></td>
<td>Used to output the NDC (nested diagnostic context) associated
with the thread that generated the logging event.
</td>
</tr>
<tr>
<td align=center><b>%</b></td>
<td>The sequence %% outputs a single percent sign.
</td>
</tr>
</table>
<p>By default the relevant information is output as is. However,
with the aid of format modifiers it is possible to change the
minimum field width, the maximum field width and justification.
<p>The optional format modifier is placed between the percent sign
and the conversion character.
<p>The first optional format modifier is the <em>left justification
flag</em> which is just the minus (-) character. Then comes the
optional <em>minimum field width</em> modifier. This is a decimal
constant that represents the minimum number of characters to
output. If the data item requires fewer characters, it is padded on
either the left or the right until the minimum width is
reached. The default is to pad on the left (right justify) but you
can specify right padding with the left justification flag. The
padding character is space. If the data item is larger than the
minimum field width, the field is expanded to accommodate the
data. The value is never truncated.
<p>This behavior can be changed using the <em>maximum field
width</em> modifier which is designated by a period followed by a
decimal constant. If the data item is longer than the maximum
field, then the extra characters are removed from the
<em>beginning</em> of the data item and not from the end. For
example, it the maximum field width is eight and the data item is
ten characters long, then the first two characters of the data item
are dropped. This behavior deviates from the printf function in C
where truncation is done from the end.
<p>Below are various format modifier examples for the category
conversion specifier.
<p>
<TABLE BORDER=1 CELLPADDING=8>
<th>Format modifier
<th>left justify
<th>minimum width
<th>maximum width
<th>comment
<tr>
<td align=center>%20c</td>
<td align=center>false</td>
<td align=center>20</td>
<td align=center>none</td>
<td>Left pad with spaces if the category name is less than 20
characters long.
<tr> <td align=center>%-20c</td> <td align=center>true</td> <td
align=center>20</td> <td align=center>none</td> <td>Right pad with
spaces if the category name is less than 20 characters long.
<tr>
<td align=center>%.30c</td>
<td align=center>NA</td>
<td align=center>none</td>
<td align=center>30</td>
<td>Truncate from the beginning if the category name is longer than 30
characters.
<tr>
<td align=center>%20.30c</td>
<td align=center>false</td>
<td align=center>20</td>
<td align=center>30</td>
<td>Left pad with spaces if the category name is shorter than 20
characters. However, if category name is longer than 30 characters,
then truncate from the beginning.
<tr>
<td align=center>%-20.30c</td>
<td align=center>true</td>
<td align=center>20</td>
<td align=center>30</td>
<td>Right pad with spaces if the category name is shorter than 20
characters. However, if category name is longer than 30 characters,
then truncate from the beginning.
</table>
<p>Below are some examples of conversion patterns.
<dl>
<p><dt><b>%r [%t] %-5p %c %x - %m\n</b>
<p><dd>This is essentially the TTCC layout.
<p><dt><b>%-6r [%15.15t] %-5p %30.30c %x - %m\n</b>
<p><dd>Similar to the TTCC layout except that the relative time is
right padded if less than 6 digits, thread name is right padded if
less than 15 characters and truncated if longer and the category
name is left padded if shorter than 30 characters and truncated if
longer.
</dl>
<p>The above text is largely inspired from Peter A. Darnell and
Philip E. Margolis' highly recommended book "C -- a Software
Engineering Approach", ISBN 0-387-97389-3.
@author <a href="mailto:cakalijp@Maritz.com">James P. Cakalic</a>
@author Ceki Gülcü
@since 0.8.2 */
public class PatternLayout extends Layout {
/**
A string constant used in naming the option for setting the
layout pattern. Current value of this string constant is
<b>ConversionPattern</b>.
<p>Note that the search for all option keys is case sensitive.
*/
final static public String CONVERSION_PATTERN_OPTION = "ConversionPattern";
/** Default pattern string for log output. Currently set to the
string <b>"%m%n"</b> which just prints the application supplied
message. */
public final static String DEFAULT_CONVERSION_PATTERN ="%m%n";
protected final int BUF_SIZE = 256;
protected final int MAX_CAPACITY = 1024;
// output buffer appended to when format() is invoked
private StringBuffer sbuf = new StringBuffer(BUF_SIZE);
private String pattern;
private PatternConverter head;
private String timezone;
/**
Constructs a PatternLayout using the DEFAULT_LAYOUT_PATTERN.
The default pattern just produces the application supplied message.
*/
public PatternLayout() {
this(DEFAULT_CONVERSION_PATTERN);
}
/**
Constructs a PatternLayout using the supplied conversion pattern.
*/
public PatternLayout(String pattern) {
this.pattern = pattern;
head = new PatternParser((pattern == null) ? DEFAULT_CONVERSION_PATTERN :
pattern).parse();
}
/**
Set the <b>ConversionPattern</b> option. This is the string which
controls formatting and consists of a mix of literal content and
conversion specifiers.
*/
public
void setConversionPattern(String conversionPattern) {
pattern = conversionPattern;
head = new PatternParser(conversionPattern).parse();
}
/**
Returns the value of the <b>ConversionPattern</b> option.
*/
public
String getConversionPattern() {
return pattern;
}
/**
Does not do anything as options become effective immediately. See
{@link #setOption} method. */
public
void activateOptions() {
// nothing to do.
}
/**
Returns the the array of option strings that {@link
PatternLayout} recognizes. The only recognized option string is
the value of {@link #CONVERSION_PATTERN_OPTION}.
*/
public
String[] getOptionStrings() {
return new String[] {CONVERSION_PATTERN_OPTION};
}
/**
The PatternLayout does not handle the throwable contained within
{@link LoggingEvent LoggingEvents}. Thus, it returns
<code>true</code>.
@since 0.8.4 */
public
boolean ignoresThrowable() {
return true;
}
/**
Returns PatternParser used to parse the conversion string. Subclasses
may override this to return a subclass of PatternParser which recognize
custom conversion characters.
@since 0.9.0
*/
//protected PatternParser createPatternParser(String pattern) {
//return new PatternParser(pattern);
//}
/**
Produces a formatted string as specified by the conversion pattern.
*/
public String format(LoggingEvent event) {
// Reset working stringbuffer
if(sbuf.capacity() > MAX_CAPACITY) {
sbuf = new StringBuffer(BUF_SIZE);
} else {
sbuf.setLength(0);
}
PatternConverter c = head;
while(c != null) {
c.format(sbuf, event);
c = c.next;
}
return sbuf.toString();
}
/**
The PatternLayout specific options are:
<p>
<dl>
<dt><b>ConversionPattern</b>
<p><dd>The value determines the conversion pattern used.
</dl>
*/
public
void setOption(String option, String value) {
if(value == null)
return;
if(option.equalsIgnoreCase(CONVERSION_PATTERN_OPTION)) {
head = new PatternParser(value).parse();
}
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/Priority.java
Index: Priority.java
===================================================================
package org.apache.log4j;
/**
Defines the minimum set of priorities recognized by the system,
that is {@link #FATAL}, {@link #ERROR}, {@link #WARN}, {@link
#INFO} and {@link #DEBUG}.
<p>The <code>Priority</code> class may be subclassed to define a larger
priority set.
@author Ceki Gülcü
*/
public class Priority {
int level;
String levelStr;
public final static int OFF_INT = Integer.MAX_VALUE;
public final static int FATAL_INT = 50000;
public final static int ERROR_INT = 40000;
public final static int WARN_INT = 30000;
public final static int INFO_INT = 20000;
public final static int DEBUG_INT = 10000;
public final static int ALL_INT = Integer.MIN_VALUE;
/**
The <code>OFF</code> is used to turn off logging.
*/
final static public Priority OFF = new Priority(OFF_INT, "OFF");
/**
The <code>FATAL</code> priority designates very severe error
events that will presumably lead the application to abort.
*/
final static public Priority FATAL = new Priority(FATAL_INT, "FATAL");
/**
The <code>ERROR</code> priority designates error events that
might still allow the application to continue running. */
final static public Priority ERROR = new Priority(ERROR_INT, "ERROR");
/**
The <code>WARN</code> priority designates potentially harmful situations.
*/
final static public Priority WARN = new Priority(WARN_INT, "WARN");
/**
The <code>INFO</code> priority designates informational messages
that highlight the progress of the application at coarse-grained
level. */
final static public Priority INFO = new Priority(INFO_INT, "INFO");
/**
The <code>DEBUG</code> priority designates fine-grained
informational events that are most useful to debug an
application. */
final static public Priority DEBUG = new Priority(DEBUG_INT, "DEBUG");
/**
The <code>ALL</code> is used to turn on all logging.
*/
final static public Priority ALL = new Priority(ALL_INT, "ALL");
/**
Instantiate a priority object.
*/
protected
Priority(int level, String levelStr) {
this.level = level;
this.levelStr = levelStr;
}
/**
Returns the string representation of this priority.
*/
final
public
String toString() {
return levelStr;
}
/**
Returns the integer representation of this priority.
*/
public
final
int toInt() {
return level;
}
/**
Returns <code>true</code> if this priority has a higher or equal
priority than the priority passed as argument, <code>false</code>
otherwise.
<p>You should think twice before overriding the default
implementation of <code>isGreaterOrEqual</code> method.
*/
public
boolean isGreaterOrEqual(Priority r) {
return level >= r.level;
}
/**
Convert the string passed as argument to a priority. If the
conversion fails, then this method returns {@link #DEBUG}.
*/
public
static
Priority toPriority(String sArg) {
return toPriority(sArg, Priority.DEBUG);
}
/**
Convert an integer passed as argument to a priority. If the
conversion fails, then this method returns {@link #DEBUG}.
*/
public
static
Priority toPriority(int val) {
return toPriority(val, Priority.DEBUG);
}
/**
Convert an integer passed as argument to a priority. If the
conversion fails, then this method returns the specified default.
*/
public
static
Priority toPriority(int val, Priority defaultPriority) {
switch(val) {
case ALL_INT: return ALL;
case DEBUG_INT: return DEBUG;
case INFO_INT: return INFO;
case WARN_INT: return WARN;
case ERROR_INT: return ERROR;
case FATAL_INT: return FATAL;
case OFF_INT: return OFF;
default: return defaultPriority;
}
}
/**
Convert the string passed as argument to a priority. If the
conversion fails, then this method returns the value of
<code>defaultPriority</code>.
*/
public
static
Priority toPriority(String sArg, Priority defaultPriority) {
if(sArg == null)
return defaultPriority;
String s = sArg.toUpperCase();
if(s.equals("ALL")) return Priority.ALL;
if(s.equals("DEBUG")) return Priority.DEBUG;
if(s.equals("INFO")) return Priority.INFO;
if(s.equals("WARN")) return Priority.WARN;
if(s.equals("ERROR")) return Priority.ERROR;
if(s.equals("FATAL")) return Priority.FATAL;
if(s.equals("OFF")) return Priority.OFF;
return defaultPriority;
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/PropertyConfigurator.java
Index: PropertyConfigurator.java
===================================================================
/*
* 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. */
// Contibutors: "Luke Blanshard" <Lu...@quiq.com>
// "Mark DONSZELMANN" <Ma...@cern.ch>
// Anders Kristensen <ak...@dynamicsoft.com>
package org.apache.log4j;
import org.apache.log4j.Category;
import org.apache.log4j.Priority;
import org.apache.log4j.spi.OptionHandler;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.helpers.OptionConverter;
import java.util.NoSuchElementException;
import java.util.Enumeration;
import java.util.Properties;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.StringTokenizer;
import java.util.Hashtable;
/**
Allows the log4j configuration from an external file. See
<b>{@link #doConfigure(String, Hierarchy)}</b> for the expected
format.
<p>It is sometimes useful to see how log4j is reading configuration
files. You can enable log4j internal logging by defining the
<b>log4j.debug</b> variable.
<P>At the initialization of the Category class, the file
<b>log4j.properties</b> will be searched from the search path used
to load classes. If the file can be found, then it will be fed to
the {@link PropertyConfigurator#configure(java.net.URL)} method.
@author Ceki Gülcü
@since log4jME 1.0
*/
public class PropertyConfigurator {
/**
Used internally to keep track of configured appenders.
*/
protected Hashtable registry = new Hashtable(11);
static final String CATEGORY_PREFIX = "log4j.category.";
static final String ADDITIVITY_PREFIX = "log4j.additivity.";
static final String ROOT_CATEGORY_PREFIX = "log4j.rootCategory";
static final String APPENDER_PREFIX = "log4j.appender.";
static final String CATEGORY_FACTORY_KEY = "log4j.categoryFactory";
static final private String INHERITED = "inherited";
static final private String INTERNAL_ROOT_NAME = "root";
/**
Read configuration from a file. The existing configuration is not
cleared nor reset.
<p>The configuration file consists of staments in the format
<code>key=value</code>.
<h3>Appender configuration</h3>
<p>Appender configuration syntax is:
<pre>
# For appender named <i>appenderName</i>, set its class.
# Note: The appender name can contain dots.
log4j.appender.appenderName=fully.qualified.name.of.appender.class
# Set appender specific options.
log4j.appender.appenderName.option1=value1
...
log4j.appender.appenderName.optionN=valueN
</pre>
For each named appender you can configure its {@link Layout}. The
syntax for configuring an appender's layout is:
<pre>
log.appender.appenderName.layout=fully.qualified.name.of.layout.class
log.appender.appenderName.layout.option1=value1
....
log.appender.appenderName.layout.optionN=valueN
</pre>
<h3>Configuring categories</h3>
<p>The syntax for configuring the root category is:
<pre>
log4j.rootCategory=[FATAL|ERROR|WARN|INFO|DEBUG], appenderName, appenderName, ...
</pre>
<p>This syntax means that one of the strings values ERROR, WARN,
INFO or DEBUG can be supplied followed by appender names separated
by commas.
<p>If one of the optional priority values ERROR, WARN, INFO or
DEBUG is given, the root priority is set to the corresponding
priority. If no priority value is specified, then the root
priority remains untouched.
<p>The root category can be assigned multiple appenders.
<p>Each <i>appenderName</i> (seperated by commas) will be added to
the root category. The named appender is defined using the
appender syntax defined above.
<p>For non-root categories the syntax is almost the same:
<pre>
log4j.category.category_name=[INHERITED|FATAL|ERROR|WARN|INFO|DEBUG], appenderName, appenderName, ...
</pre>
<p>Thus, one of the usual priority values FATAL, ERROR, WARN,
INFO, or DEBUG can be optionally specified. For any any of these
values the named category is assigned the corresponding
priority. In addition however, the value INHERITED can be
optionally specified which means that named category should
inherit its priority from the category hierarchy.
<p>If no priority value is supplied, then the priority of the
named category remains untouched.
<p>By default categories inherit their priority from the
hierarchy. However, if you set the priority of a category and
later decide that that category should inherit its priority, then
you should specify INHERITED as the value for the priority value.
<p>Similar to the root category syntax, each <i>appenderName</i>
(seperated by commas) will be attached to the named category.
<p>See the <a href="../../manual.html#additivity">appender
additivity rule</a> in the user manual for the meaning of the
<code>additivity</code> flag.
<h3>Example</h3>
<p>An example configuration is given below. Other configuration
file examples are given in {@link org.apache.log4j.examples.Sort}
class documentation.
<pre>
# Set options for appender named "A1".
# Appender "A1" will be a FileAppender
log4j.appender.A1=org.apache.log4j.FileAppender
# It will send its output to System.out
log4j.appender.A1.File=System.out
# A1's layout is a PatternLayout, using the conversion pattern
# <b>%-4r %-5p %c{2} - %m%n</b>. Thus, the log output will
# include the relative time since the start of the application in
# milliseconds, followed by the priority of the log request,
# followed by the two rightmost components of the category name
# and finally the message itself.
# Refer to the documentation of {@link PatternLayout} for further information
# on the syntax of the ConversionPattern key.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %c{2} - %m%n
# Set options for appender named "A2"
# A2 should be a <code>FileAppender</code> printing to the
# file <code>temp</code>.
log4j.appender.A2=org.apache.log4j.FileAppender
log4j.appender.A2.File=temp
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%-4r %-5p %c - %m%n
# Root category set to DEBUG using the A2 appender defined above.
log4j.rootCategory=DEBUG, A2
# Category definions:
# The SECURITY category inherits is priority from root. However, it's output
# will go to A1 appender defined above. It's additivity is non-cumulative.
log4j.category.SECURITY=INHERIT, A1
log4j.additivity.SECURITY=false
# Only warnings or above will be logged for the category "SECURITY.access".
# Output will go to A1.
log4j.category.SECURITY.access=WARN
# The category "class.of.the.day" inherits its priority from the
# category hierrarchy. Output will go to the appender's of the root
# category, A2 in this case.
log4j.category.class.of.the.day=INHERIT
</pre>
<p>Refer to the <b>setOption</b> method in each Appender and
Layout for class specific options.
<p>Use the <code>#</code> or <code>!</code> characters at the
beginning of a line for comments.
<p>
@param configFileName The name of the configuration file where the
configuration information is stored.
*/
public
void doConfigure(String configFileName, Hierarchy hierarchy) {
Properties props = new Properties();
try {
FileInputStream istream = new FileInputStream(configFileName);
props.load(istream);
istream.close();
}
catch (IOException e) {
LogLog.error("Could not read config file [" + configFileName+
"].", e);
LogLog.error("Ignoring config file [" + configFileName+"].");
return;
}
// If we reach here, then the config file is alright.
doConfigure(props, hierarchy);
}
/**
*/
static
public
void configure(String configFilename) {
new PropertyConfigurator().doConfigure(configFilename,
Category.defaultHierarchy);
}
/**
Read configuration options from url <code>configURL</code>.
@since 0.8.2
*/
public
static
void configure(java.net.URL configURL) {
new PropertyConfigurator().doConfigure(configURL, Category.defaultHierarchy);
}
/**
Read configuration options from <code>properties</code>.
See {@link #doConfigure(String, Hierarchy)} for the expected format.
*/
static
public
void configure(Properties properties) {
new PropertyConfigurator().doConfigure(properties, Category.defaultHierarchy);
}
/**
Read configuration options from <code>properties</code>.
See {@link #doConfigure(String, Hierarchy)} for the expected format.
*/
public
void doConfigure(Properties properties, Hierarchy hierarchy) {
String value = properties.getProperty(LogLog.DEBUG_KEY);
if(value != null) {
LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true));
}
configureRootCategory(properties, hierarchy);
parseCats(properties, hierarchy);
// We don't want to hold references to appenders preventing their
// garbage collection.
registry.clear();
}
/**
Read configuration options from url <code>configURL</code>.
*/
public
void doConfigure(java.net.URL configURL, Hierarchy hierarchy) {
Properties props = new Properties();
LogLog.debug("Reading URL " + configURL);
try {
props.load(configURL.openStream());
}
catch (java.io.IOException e) {
LogLog.error("Could not read config file [" + configURL
+ "].", e);
LogLog.error("Ignoring config file [" + configURL +"].");
return;
}
doConfigure(props, hierarchy);
}
// -------------------------------------------------------------------------------
// Internal stuff
// -------------------------------------------------------------------------------
void configureOptionHandler(OptionHandler oh, String prefix,
Properties props) {
String[] options = oh.getOptionStrings();
if(options == null)
return;
String value;
for(int i = 0; i < options.length; i++) {
value = props.getProperty(prefix + options[i]);
LogLog.debug(
"Option " + options[i] + "=[" + (value == null? "null" : value)+"].");
// Some option handlers assume that null value are not passed to them.
// So don't remove this check
if(value != null) {
oh.setOption(options[i], value);
}
}
oh.activateOptions();
}
void configureRootCategory(Properties props, Hierarchy hierarchy) {
String value = props.getProperty(ROOT_CATEGORY_PREFIX);
if(value == null)
LogLog.debug("Could not find root category information. Is this OK?");
else {
Category root = hierarchy.getRoot();
synchronized(root) {
parseCategory(props, root, ROOT_CATEGORY_PREFIX, INTERNAL_ROOT_NAME,
value);
}
}
}
/**
Parse non-root elements, such non-root categories and renderers.
*/
protected
void parseCats(Properties props, Hierarchy hierarchy) {
Enumeration enum = props.propertyNames();
while(enum.hasMoreElements()) {
String key = (String) enum.nextElement();
if(key.startsWith(CATEGORY_PREFIX)) {
String categoryName = key.substring(CATEGORY_PREFIX.length());
String value = props.getProperty(key);
Category cat = hierarchy.getInstance(categoryName);
synchronized(cat) {
parseCategory(props, cat, key, categoryName, value);
parseAdditivityForCategory(props, cat, categoryName);
}
}
}
}
/**
Parse the additivity option for a non-root category.
*/
void parseAdditivityForCategory(Properties props, Category cat,
String categoryName) {
String value = props.getProperty(ADDITIVITY_PREFIX + categoryName);
LogLog.debug("Handling "+ADDITIVITY_PREFIX + categoryName+"=["+value+"]");
// touch additivity only if necessary
if((value != null) && (!value.equals(""))) {
boolean additivity = OptionConverter.toBoolean(value, true);
LogLog.debug("Setting additivity for \""+categoryName+"\" to "+
additivity);
cat.setAdditivity(additivity);
}
}
/**
This method must work for the root category as well.
*/
void parseCategory(Properties props, Category cat, String optionKey,
String catName, String value) {
LogLog.debug("Parsing for [" +catName +"] with value=[" + value+"].");
// We must skip over ',' but not white space
StringTokenizer st = new StringTokenizer(value, ",");
// If value is not in the form ", appender.." or "", then we should set
// the priority of the category.
if(!(value.startsWith(",") || value.equals(""))) {
// just to be on the safe side...
if(!st.hasMoreTokens())
return;
String priorityStr = st.nextToken();
LogLog.debug("Priority token is [" + priorityStr + "].");
// If the priority value is inherited, set category priority value to
// null. We also check that the user has not specified inherited for the
// root category.
if(priorityStr.equalsIgnoreCase(INHERITED) && !catName.equals(INTERNAL_ROOT_NAME))
cat.setPriority(null);
else
cat.setPriority(Priority.toPriority(priorityStr));
LogLog.debug("Category " + catName + " set to " + cat.getPriority());
}
// Remove all existing appenders. They will be reconstructed below.
cat.removeAllAppenders();
Appender appender;
String appenderName;
while(st.hasMoreTokens()) {
appenderName = st.nextToken().trim();
if(appenderName == null || appenderName.equals(","))
continue;
LogLog.debug("Parsing appender named \"" + appenderName +"\".");
appender = parseAppender(props, appenderName);
if(appender != null) {
cat.addAppender(appender);
}
}
}
Appender parseAppender(Properties props, String appenderName) {
Appender appender = registryGet(appenderName);
if((appender != null)) {
LogLog.debug("Appender \"" + appenderName + "\" was already parsed.");
return appender;
}
// Appender was not previously initialized.
String prefix = APPENDER_PREFIX + appenderName;
String layoutPrefix = prefix + ".layout";
appender = (Appender) OptionConverter.instantiateByKey(props, prefix,
org.apache.log4j.Appender.class,
null);
if(appender == null) {
LogLog.error(
"Could not instantiate appender named \"" + appenderName+"\".");
return null;
}
appender.setName(appenderName);
if(appender instanceof OptionHandler) {
configureOptionHandler((OptionHandler) appender, prefix + ".", props);
LogLog.debug("Parsed \"" + appenderName +"\" options.");
Layout layout = (Layout) OptionConverter.instantiateByKey(props,
layoutPrefix,
Layout.class,
null);
if(layout != null) {
appender.setLayout(layout);
LogLog.debug("Parsing layout options for \"" + appenderName +"\".");
configureOptionHandler(layout, layoutPrefix + ".", props);
LogLog.debug("End of parsing for \"" + appenderName +"\".");
}
}
registryPut(appender);
return appender;
}
void registryPut(Appender appender) {
registry.put(appender.getName(), appender);
}
Appender registryGet(String name) {
return (Appender) registry.get(name);
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/ProvisionNode.java
Index: ProvisionNode.java
===================================================================
/*
* 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;
import java.util.Vector;
class ProvisionNode extends Vector {
ProvisionNode(Category cat) {
super();
this.addElement(cat);
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/StressCategory.java
Index: StressCategory.java
===================================================================
/*
* 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;
import org.apache.log4j.Priority;
import org.apache.log4j.Category;
import java.util.Random;
/*
Stress test the Category class.
*/
class StressCategory {
static Priority[] priority = new Priority[] {Priority.DEBUG,
Priority.INFO,
Priority.WARN,
Priority.ERROR,
Priority.FATAL};
static Priority defaultPriority = Category.getRoot().getPriority();
static int LENGTH;
static String[] names;
static Category[] cat;
static CT[] ct;
static Random random = new Random(10);
public static void main(String[] args) {
LENGTH = args.length;
if(LENGTH == 0) {
System.err.println( "Usage: java " + StressCategory.class.getName() +
" name1 ... nameN\n.");
System.exit(1);
}
if(LENGTH >= 7) {
System.err.println(
"This stress test suffers from combinatorial explosion.\n"+
"Invoking with seven arguments takes about 90 minutes even on fast machines");
}
names = new String[LENGTH];
for(int i=0; i < LENGTH; i++) {
names[i] = args[i];
}
cat = new Category[LENGTH];
ct = new CT[LENGTH];
permute(0);
// If did not exit, then passed all tests.
}
// Loop through all permutations of names[].
// On each possible permutation call createLoop
static
void permute(int n) {
if(n == LENGTH)
createLoop(0);
else
for(int i = n; i < LENGTH; i++) {
swap(names, n, i);
permute(n+1);
swap(names, n, i);
}
}
static
void swap(String[] names, int i, int j) {
String t = names[i];
names[i] = names[j];
names[j] = t;
}
public
static
void permutationDump() {
System.out.print("Current permutation is - ");
for(int i = 0; i < LENGTH; i++) {
System.out.print(names[i] + " ");
}
System.out.println();
}
// Loop through all possible 3^n combinations of not instantiating,
// instantiating and setting/not setting a priority.
static
void createLoop(int n) {
if(n == LENGTH) {
//System.out.println("..............Creating cat[]...........");
for(int i = 0; i < LENGTH; i++) {
if(ct[i] == null)
cat[i] = null;
else {
cat[i] = Category.getInstance(ct[i].catstr);
cat[i].setPriority(ct[i].priority);
}
}
test();
// Clear hash table for next round
Category.defaultHierarchy.clear();
}
else {
ct[n] = null;
createLoop(n+1);
ct[n] = new CT(names[n], null);
createLoop(n+1);
int r = random.nextInt(); if(r < 0) r = -r;
ct[n] = new CT(names[n], priority[r%5]);
createLoop(n+1);
}
}
static
void test() {
//System.out.println("++++++++++++TEST called+++++++++++++");
//permutationDump();
//catDump();
for(int i = 0; i < LENGTH; i++) {
if(!checkCorrectness(i)) {
System.out.println("Failed stress test.");
permutationDump();
//Hierarchy._default.fullDump();
ctDump();
catDump();
System.exit(1);
}
}
}
static
void ctDump() {
for(int j = 0; j < LENGTH; j++) {
if(ct[j] != null)
System.out.println("ct [" + j + "] = ("+ct[j].catstr+"," +
ct[j].priority + ")");
else
System.out.println("ct [" + j + "] = undefined");
}
}
static
void catDump() {
for(int j = 0; j < LENGTH; j++) {
if(cat[j] != null)
System.out.println("cat[" + j + "] = (" + cat[j].name + "," +
cat[j].getPriority() + ")");
else
System.out.println("cat[" + j + "] = undefined");
}
}
// static
//void provisionNodesDump() {
//for (Enumeration e = CategoryFactory.ht.keys(); e.hasMoreElements() ;) {
// CategoryKey key = (CategoryKey) e.nextElement();
// Object c = CategoryFactory.ht.get(key);
// if(c instanceof ProvisionNode)
//((ProvisionNode) c).dump(key.name);
//}
//}
static
boolean checkCorrectness(int i) {
CT localCT = ct[i];
// Can't perform test if category is not instantiated
if(localCT == null)
return true;
// find expected priority
Priority expected = getExpectedPrioriy(localCT);
Priority purported = cat[i].getChainedPriority();
if(expected != purported) {
System.out.println("Expected priority for " + localCT.catstr + " is " +
expected);
System.out.println("Purported priority for "+ cat[i].name + " is "+purported);
return false;
}
return true;
}
static
Priority getExpectedPrioriy(CT ctParam) {
Priority priority = ctParam.priority;
if(priority != null)
return priority;
String catstr = ctParam.catstr;
for(int i = catstr.lastIndexOf('.', catstr.length()-1); i >= 0;
i = catstr.lastIndexOf('.', i-1)) {
String substr = catstr.substring(0, i);
// find the priority of ct corresponding to substr
for(int j = 0; j < LENGTH; j++) {
if(ct[j] != null && substr.equals(ct[j].catstr)) {
Priority p = ct[j].priority;
if(p != null)
return p;
}
}
}
return defaultPriority;
}
static class CT {
public String catstr;
public Priority priority;
CT(String catstr, Priority priority) {
this.catstr = catstr;
this.priority = priority;
}
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/WriterAppender.java
Index: WriterAppender.java
===================================================================
/*
* 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;
import java.io.IOException;
import java.io.Writer;
import java.io.FileWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.helpers.LogLog;
// Contibutors: Jens Uwe Pipka <je...@gmx.de>
/**
WriterAppender appends log events to a {@link java.io.Writer} or an
{@link java.io.OutputStream} depending on the user's choice.
@author Ceki Gülcü
@since 1.1 */
public class WriterAppender extends AppenderSkeleton {
/**
This is the {@link QuietWriter quietWriter} where we will write
to.
*/
protected Writer w;
/**
This default constructor does nothing. */
public
WriterAppender() {
}
/**
Instantiate a WriterAppender and set the output destination to a
new {@link OutputStreamWriter} initialized with <code>os</code>
as its {@link OutputStream}. */
//public
//WriterAppender(Layout layout, OutputStream os) {
//this(layout, new OutputStreamWriter(os));
//}
/**
Instantiate a WriterAppender and set the output destination to
<code>writer</code>.
<p>The <code>writer</code> must have been previously opened by
the user. */
public
WriterAppender(Layout layout, Writer writer) {
this.layout = layout;
this.setWriter(writer);
}
public
void write(String string) {
try {
w.write(string);
} catch(IOException e) {
error("Failed to writing", e);
}
}
/**
Does nothing.
*/
public
void activateOptions() {
}
/**
This method is called by the {@link AppenderSkeleton#doAppend}
method.
<p>If the output stream exists and is writable then write a log
statement to the output stream. Otherwise, write a single warning
message to <code>System.err</code>.
<p>The format of the output will depend on this appender's
layout.
*/
public
void append(LoggingEvent event) {
// Reminder: the nesting of calls is:
//
// doAppend()
// - check threshold
// - filter
// - append();
// - checkEntryConditions();
// - subAppend();
if(!checkEntryConditions()) {
return;
}
write(this.layout.format(event));
if(layout.ignoresThrowable()) {
String s = event.getThrowableStr();
if (s != null) {
write(s);
}
}
try {
w.flush();
} catch(IOException e) {
error("Failed to flush", e);
}
}
/**
This method determines if there is a sense in attempting to append.
<p>It checks whether there is a set output target and also if
there is a set layout. If these checks fail, then the boolean
value <code>false</code> is returned. */
protected
boolean checkEntryConditions() {
if(this.closed) {
return false;
}
if(this.w == null) {
error("No Writer for ["+name+"]");
return false;
}
if(this.layout == null) {
error("No layout for ["+ name+"]");
return false;
}
return true;
}
/**
Close this appender instance. The underlying stream or writer is
also closed.
<p>Closed appenders cannot be reused.
@see #setWriter
@since 0.8.4 */
public
synchronized
void close() {
if(this.closed)
return;
this.closed = true;
closeWriter();
this.w = null;
}
/**
Close the underlying {@link java.io.Writer}.
*/
protected
void closeWriter() {
if(w != null) {
try {
w.close();
} catch(IOException e) {
LogLog.error("Failed closing", e);
}
}
}
/**
<p>Sets the Writer where the log output will go. The
specified Writer must be opened by the user and be
writable.
<p>The <code>java.io.Writer</code> will be closed when the
appender instance is closed.
<p><b>WARNING:</b> Logging to an unopened Writer will fail.
<p>
@param Writer An already opened Writer. */
public
synchronized
void setWriter(Writer writer) {
closeWriter();
this.w = null;
this.w = writer;
}
/**
Clear internal references to the writer and other variables.
Subclasses can override this method for an alternate closing
behavior. */
//protected
//void reset() {
//closeWriter();
//this.w = null;
//}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/package.html
Index: package.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html> <head>
<title></title>
</head>
<body>
<p>The main package of log4j.
<hr>
</body> </html>
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/.cvsignore
Index: .cvsignore
===================================================================
doc-files
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/Makefile
Index: Makefile
===================================================================
PKG_DIR :=org/apache/log4j/examples
DEPTH :=../../../../../..
JSOURCES:=SortAlgo.java Sort.java
# include master-rule file
include $(DEPTH)/make/make.inc
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/Sort.java
Index: Sort.java
===================================================================
package org.apache.log4j.examples;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.Category;
import org.apache.log4j.Priority;
/**
Example code for log4j to viewed in conjunction with the {@link
org.apache.log4j.examples.SortAlgo SortAlgo} class.
<p>This program expects a configuration file name as its first
argument, and the size of the array to sort as the second and last
argument. See its <b><a href="doc-files/Sort.java">source
code</a></b> for more details.
<p>Play around with different values in the configuration file and
watch the changing behavior.
<p>Example configuration files <a
href="doc-files/sort1.lcf">sort1.lcf</a>,
<a href="doc-files/sort2.lcf">sort2.lcf</a>,
<a href="doc-files/sort3.lcf">sort3.lcf</a> and
<a href="doc-files/sort4.lcf">sort4.lcf</a> are supplied with the
package.
<p>If you are interested in logging performance, then have look at
the {@link org.apache.log4j.performance.Logging} class.
@author Ceki Gülcü */
public class Sort {
static Category CAT = Category.getInstance(Sort.class.getName());
public static void main(String[] args) {
if(args.length != 2) {
usage("Incorrect number of parameters.");
}
int arraySize = -1;
try {
arraySize = Integer.valueOf(args[1]).intValue();
if(arraySize <= 0)
usage("Negative array size.");
}
catch(java.lang.NumberFormatException e) {
usage("Could not number format ["+args[1]+"].");
}
Sort.init(args[0]);
int[] intArray = new int[arraySize];
CAT.info("Populating an array of " + arraySize + " elements in" +
" reverse order.");
for(int i = arraySize -1 ; i >= 0; i--) {
intArray[i] = arraySize - i - 1;
}
SortAlgo sa1 = new SortAlgo(intArray);
sa1.bubbleSort();
sa1.dump();
// We intentionally initilize sa2 with null.
SortAlgo sa2 = new SortAlgo(null);
CAT.info("The next log statement should be an error message.");
sa2.dump();
CAT.info("Exiting main method.");
}
static
void usage(String errMsg) {
System.err.println(errMsg);
System.err.println("\nUsage: java org.apache.log4j.examples.Sort " +
"configFile ARRAY_SIZE\n"+
"where configFile is a configuration file\n"+
" ARRAY_SIZE is a positive integer.\n");
System.exit(1);
}
static
void init(String configFile) {
PropertyConfigurator.configure(configFile);
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/SortAlgo.java
Index: SortAlgo.java
===================================================================
package org.apache.log4j.examples;
import org.apache.log4j.Category;
import org.apache.log4j.NDC;
/**
Example code for log4j to viewed in conjunction with the {@link
org.apache.log4j.examples.Sort Sort} class.
<p>SortAlgo uses the bubble sort algorithm to sort an integer
array. See also its <b><a href="doc-files/SortAlgo.java">source
code</a></b>.
@author Ceki Gülcü
*/
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");
int[] intArray;
SortAlgo(int[] intArray) {
this.intArray = intArray;
}
void bubbleSort() {
CAT.info( "Entered the sort method.");
for(int i = intArray.length -1; i >= 0 ; i--) {
NDC.push("i=" + i);
OUTER.debug("in outer loop.");
for(int j = 0; j < i; j++) {
NDC.push("j=" + j);
// It is poor practice to ship code with log staments in tight loops.
// We do it anyway in this example.
INNER.debug( "in inner loop.");
if(intArray[j] > intArray[j+1])
swap(j, j+1);
NDC.pop();
}
NDC.pop();
}
}
void dump() {
if(! (this.intArray instanceof int[])) {
DUMP.error( "Tried to dump an uninitialized array.");
return;
}
DUMP.info( "Dump of integer array:");
for(int i = 0; i < this.intArray.length; i++) {
DUMP.info( "Element [" + i + "]=" + this.intArray[i]);
}
}
void swap(int l, int r) {
// It is poor practice to ship code with log staments in tight
// loops or code called potentially millions of times.
SWAP.debug( "Swapping intArray["+l+"]=" + intArray[l] +
" and intArray["+r+"]=" + intArray[r]);
int temp = this.intArray[l];
this.intArray[l] = this.intArray[r];
this.intArray[r] = temp;
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/Trivial.java
Index: Trivial.java
===================================================================
package org.apache.log4j.examples;
import org.apache.log4j.Category;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.NDC;
/**
View the <a href="doc-files/Trivial.java">source code</a> of this a
trivial usage example. Running <code>java
org.apache.log4j.examples.Trivial</code> should output something
similar to:
<pre>
0 INFO [main] org.apache.log4j.examples.Trivial (Client #45890) - Awake awake. Put on thy strength.
15 DEBUG [main] org.apache.log4j.examples.Trivial (Client #45890 DB) - Now king David was old.
278 INFO [main] org.apache.log4j.examples.Trivial$InnerTrivial (Client #45890) - Entered foo.
293 INFO [main] org.apache.log4j.examples.Trivial (Client #45890) - Exiting Trivial.
</pre>
<p> The increasing numbers at the beginning of each line are the
times elapsed since the start of the program. The string between
the parentheses is the nested diagnostic context.
<p>See {@link Sort} and {@link SortAlgo} for sligtly more elaborate
examples.
<p>Note thent class files for the example code is not included in
any of the distributed log4j jar files. You will have to add the
directory <code>/dir-where-you-unpacked-log4j/classes</code> to
your classpath before trying out the examples.
*/
public class Trivial {
static Category cat = Category.getInstance(Trivial.class.getName());
public static void main(String[] args) {
BasicConfigurator.configure();
NDC.push("Client #45890");
cat.info("Awake awake. Put on thy strength.");
Trivial.foo();
InnerTrivial.foo();
cat.info("Exiting Trivial.");
}
static
void foo() {
NDC.push("DB");
cat.debug("Now king David was old.");
NDC.pop();
}
static class InnerTrivial {
static Category cat = Category.getInstance(InnerTrivial.class.getName());
static
void foo() {
cat.info("Entered foo.");
}
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/sort1.lcf
Index: sort1.lcf
===================================================================
# An example log4j configuration file that outputs to System.out.
# The output info consists of relative time, priority, thread name,
# category name, nested diagnostic context, the and the message in
# that order.
# 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 do not have a default
# priority. in which case the priority is inherited from the
# hierarchy.
log4j.rootCategory=, A1
# A1 is set to be a ConsoleAppender which outputs to System.out.
log4j.appender.A1=org.apache.log4j.FileAppender
log4j.appender.A1.File=System.out
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
# The conversion pattern uses format specifiers. You might want to
# change the pattern an watch the output layout change.
log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
# In this example, we are not really interested in INNER loop or SWAP
# messages. Try changing the priorities of these categories.
# log4j.category.org.apache.log4j.examples.SortAlgo.INNER=WARN
# log4j.category.org.apache.log4j.examples.SortAlgo.SWAP=WARN
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/sort2.lcf
Index: sort2.lcf
===================================================================
# An example log4j configuration file that outputs both to System.out
# and a file named 'test'.
log4j.rootCategory=, A1, A2
# A1 is set to be FileAppender sending its output to System.out
log4j.appender.A1=org.apache.log4j.FileAppender
log4j.appender.A1.File=System.out
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
# The conversion pattern consists of date in ISO8601 format, priority,
# thread name, category name truncated to its rightmost two components
# and left justified to 17 characters, location information consisting
# of file name (padded to 13 characters) and line number, nested
# diagnostic context, the and the application supplied message
log4j.appender.A1.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n
# Appender A2 writes to the file "test".
log4j.appender.A2=org.apache.log4j.FileAppender
log4j.appender.A2.File=test
# Truncate 'test' if it aleady exists.
log4j.appender.A2.Append=false
# Appender A2 uses the PatternLayout.
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%-5r %-5p [%t] %c{2} - %m%n
# In this example, we are not interested in INNER loop or SWAP
# messages. You might try to set INNER and SWAP to DEBUG for more
# verbose output.
log4j.category.org.apache.log4j.examples.SortAlgo.INNER=INFO
log4j.category.org.apache.log4j.examples.SortAlgo.SWAP=INFO
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/sort3.lcf
Index: sort3.lcf
===================================================================
# Attach appender A1 to root. Set root priority to Prority.DEBUG.
log4j.rootCategory=DEBUG, A1
# A1 is set to be a FileAppender sending its output to
# System.out. However, only error messages and above will be printed
# since the threshold is set to Priority.ERROR.
# The fact that the root priority is set to Prority.DEBUG only
# influences log requests made to the root category. It has no
# influence on the appenders attached to root.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.Threshold=ERROR
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%p [%t] %c{2} (%M:%L) - %m%n
# Set the priority of the category named "org.apache.log4j.examples" to
# Priority.INFO, attach appender A2.
log4j.category.org.apache.log4j.examples=INFO, A2
# Appender A2 writes to the file "test" in user's home.
log4j.appender.A2=org.apache.log4j.FileAppender
log4j.appender.A2.File=${user.home}/test
# Truncate 'test' if it aleady exists.
log4j.appender.A2.Append=false
# Appender A2 uses the PatternLayout.
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%5r %-5p [%t] %c{2} - %m%n
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/helpers/FormattingInfo.java
Index: FormattingInfo.java
===================================================================
/*
* 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.
*/
package org.apache.log4j.helpers;
/**
FormattingInfo instances contain the information obtained when parsing
formatting modifiers in conversion modifiers.
@author <a href=mailto:jim_cakalic@na.biomerieux.com>Jim Cakalic</a>
@author Ceki Gülcü
@since 0.8.2
*/
public class FormattingInfo {
int min = -1;
int max = 0x7FFFFFFF;
boolean leftAlign = false;
void reset() {
min = -1;
max = 0x7FFFFFFF;
leftAlign = false;
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/helpers/LogLog.java
Index: LogLog.java
===================================================================
/*
* 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;
/**
This class used to output log statements from within the log4j package.
<p>Log4j components cannot make log4j logging calls. However, it is
sometimes useful for the user to learn about what log4j is
doing. You can enable log4j internal logging by defining the
<b>log4j.configDebug</b> variable.
<p>All log4j internal debug calls go to <code>System.out</code>
where as internal error messages are sent to
<code>System.err</code>. All internal messages are prepended with
the string "log4j: ".
@since 0.8.2
@author Ceki Gülcü
*/
public class LogLog {
/**
Defining this value makes log4j print log4j-internal debug
statements to <code>System.out</code>.
<p> The value of this string is <b>log4j.debug</b>.
<p>Note that the search for all option names is case sensitive. */
public static final String DEBUG_KEY="log4j.debug";
protected static boolean debugEnabled = false;
/**
In quietMode not even errors generate any output.
*/
private static boolean quietMode = false;
private static final String PREFIX = "log4j: ";
private static final String ERR_PREFIX = "log4j:ERROR ";
private static final String WARN_PREFIX = "log4j:WARN ";
static {
String key = getSystemProperty(DEBUG_KEY, null);
if(key != null) {
debugEnabled = OptionConverter.toBoolean(key, true);
}
}
/**
Allows to enable/disable log4j internal logging.
*/
static
public
void setInternalDebugging(boolean enabled) {
debugEnabled = enabled;
}
/**
This method is used to output log4j internal debug
statements. Output goes to <code>System.out</code>.
*/
public
static
void debug(String msg) {
debug(msg, null);
}
/**
This method is used to output log4j internal debug
statements. Output goes to <code>System.out</code>.
*/
public
static
void debug(String msg, Throwable t) {
if(debugEnabled && !quietMode) {
System.out.println(PREFIX+msg);
if(t != null)
t.printStackTrace(System.out);
}
}
/**
This method is used to output log4j internal error
statements. There is no way to disable error statements.
Output goes to <code>System.err</code>.
*/
public
static
void error(String msg) {
error(msg, null);
}
/**
This method is used to output log4j internal error
statements. There is no way to disable error statements.
Output goes to <code>System.err</code>.
*/
public
static
void error(String msg, Throwable t) {
if(quietMode)
return;
System.err.println(ERR_PREFIX+msg);
if(t != null) {
t.printStackTrace();
}
}
public
static
String getSystemProperty(String key, String def) {
try {
return System.getProperty(key, def);
} catch(Throwable e) {
return def;
}
}
/**
In quite mode no LogLog generates strictly no output, not even
for errors.
@param quietMode A true for not
*/
public
static
void setQuietMode(boolean quietMode) {
LogLog.quietMode = quietMode;
}
/**
This method is used to output log4j internal warning
statements. There is no way to disable warning statements.
Output goes to <code>System.err</code>. */
public
static
void warn(String msg) {
warn(msg, null);
}
/**
This method is used to output log4j internal warnings. There is
no way to disable warning statements. Output goes to
<code>System.err</code>. */
public
static
void warn(String msg, Throwable t) {
if(quietMode)
return;
System.err.println(WARN_PREFIX+msg);
if(t != null) {
t.printStackTrace();
}
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/helpers/OptionConverter.java
Index: OptionConverter.java
===================================================================
/*
* 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 java.util.Properties;
public class OptionConverter {
public
static
boolean toBoolean(String value, boolean defaultVal) {
if(value == null)
return defaultVal;
String trimmedVal = value.trim();
if("true".equalsIgnoreCase(trimmedVal))
return true;
if("false".equalsIgnoreCase(trimmedVal))
return false;
return defaultVal;
}
public
static
Object instantiateByKey(Properties props, String key, Class superClass,
Object defaultValue) {
// Get the value of the property in string form
String className = props.getProperty(key);
if(className == null) {
LogLog.error("Could not find value for " + key);
return defaultValue;
}
// Trim className to avoid trailing spaces that cause problems.
return OptionConverter.instantiateByClassName(className.trim(), superClass,
defaultValue);
}
/**
Instantiate an object given a class name. Check that the
<code>className</code> is a subclass of <code>superClass</code>.
*/
public
static
Object instantiateByClassName(String className, Class superClass,
Object defaultValue) {
if(className != null) {
try {
Class classObj = Class.forName(className);
if(!superClass.isAssignableFrom(classObj))
LogLog.error("A \""+className+"\" object is not assignable to a \""+
superClass.getName() + "\" object.");
return classObj.newInstance();
}
catch (Exception e) {
LogLog.error("Could not instantiate class [" + className + "].", e);
}
}
return defaultValue;
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/helpers/PatternConverter.java
Index: PatternConverter.java
===================================================================
/*
* 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.
*/
package org.apache.log4j.helpers;
import org.apache.log4j.spi.LoggingEvent;
/**
<p>PatternConverter is an abtract class that provides the
formatting functionality that derived classes need.
<p>Conversion specifiers in a conversion patterns are parsed to
individual PatternConverters. Each of which is responsible for
converting a logging event in a converter specific manner.
@author <a href="mailto:cakalijp@Maritz.com">James P. Cakalic</a>
@author Ceki Gülcü
@since 0.8.2
*/
public abstract class PatternConverter {
public PatternConverter next;
int min = -1;
int max = 0x7FFFFFFF;
boolean leftAlign = false;
protected
PatternConverter() { }
protected
PatternConverter(FormattingInfo fi) {
min = fi.min;
max = fi.max;
leftAlign = fi.leftAlign;
}
/**
Derived pattern converters must override this method in order to
convert conversion specifiers in the correct way.
*/
abstract
protected
String convert(LoggingEvent event);
/**
A template method for formatting in a converter specific way.
*/
public
void format(StringBuffer sbuf, LoggingEvent e) {
String s = convert(e);
if(s == null) {
if(0 < min)
spacePad(sbuf, min);
return;
}
int len = s.length();
if(len > max)
sbuf.append(s.substring(len-max));
else if(len < min) {
if(leftAlign) {
sbuf.append(s);
spacePad(sbuf, min-len);
}
else {
spacePad(sbuf, min-len);
sbuf.append(s);
}
}
else
sbuf.append(s);
}
static String[] SPACES = {" ", " ", " ", " " }; //1,2,4,8 spaces
/**
Fast space padding method.
*/
public
void spacePad(StringBuffer sbuf, int length) {
while(length >= 8) {
sbuf.append(SPACES[3]);
length -= 8;
}
for(int i = 2; i >= 0; i--) {
if((length & (1<<i)) != 0) {
sbuf.append(SPACES[i]);
}
}
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/helpers/PatternParser.java
Index: PatternParser.java
===================================================================
package org.apache.log4j.helpers;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.Layout;
import org.apache.log4j.NDC;
import org.apache.log4j.spi.LoggingEvent;
import java.text.DateFormat;
import java.util.Date;
// Contributors: Nelson Minar <(n...@monkey.org>
// Igor E. Poteryaev <ja...@mail.ru>
// Reinhard Deschler <re...@web.de>
/**
Most of the work of the {@link org.apache.log4j.PatternLayout} class
is delegated to the PatternParser class.
@author <a href=mailto:"cakalijp@Maritz.com">James P. Cakalic</a>
@author Ceki Gülcü
@author Anders Kristensen
@since 0.8.2
*/
public class PatternParser {
private static final char ESCAPE_CHAR = '%';
private static final int LITERAL_STATE = 0;
private static final int CONVERTER_STATE = 1;
private static final int MINUS_STATE = 2;
private static final int DOT_STATE = 3;
private static final int MIN_STATE = 4;
private static final int MAX_STATE = 5;
static final int RELATIVE_TIME_CONVERTER = 2000;
static final int THREAD_CONVERTER = 2001;
static final int PRIORITY_CONVERTER = 2002;
//static final int NDC_CONVERTER = 2003;
static final int MESSAGE_CONVERTER = 2004;
int state;
protected StringBuffer currentLiteral = new StringBuffer(32);
protected int patternLength;
protected int i;
PatternConverter head;
PatternConverter tail;
protected FormattingInfo formattingInfo = new FormattingInfo();
protected String pattern;
public
PatternParser(String pattern) {
this.pattern = pattern;
patternLength = pattern.length();
state = LITERAL_STATE;
}
private
void addToList(PatternConverter pc) {
if(head == null) {
head = tail = pc;
} else {
tail.next = pc;
tail = pc;
}
}
private
String extractOption() {
if((i < patternLength) && (pattern.charAt(i) == '{')) {
int end = pattern.indexOf('}', i);
if (end > i) {
String r = pattern.substring(i + 1, end);
i = end+1;
return r;
}
}
return null;
}
/**
The option is expected to be in decimal and positive. In case of
error, zero is returned. */
private
int extractPrecisionOption() {
String opt = extractOption();
int r = 0;
if(opt != null) {
try {
r = Integer.parseInt(opt);
if(r <= 0) {
LogLog.error(opt + " <= 0");
r = 0;
}
}
catch (NumberFormatException e) {
LogLog.error(opt+" invalid", e);
}
}
return r;
}
public
PatternConverter parse() {
char c;
i = 0;
while(i < patternLength) {
c = pattern.charAt(i++);
switch(state) {
case LITERAL_STATE:
// In literal state, the last char is always a literal.
if(i == patternLength) {
currentLiteral.append(c);
continue;
}
if(c == ESCAPE_CHAR) {
// peek at the next char.
switch(pattern.charAt(i)) {
case ESCAPE_CHAR:
currentLiteral.append(c);
i++; // move pointer
break;
case 'n':
currentLiteral.append(Layout.LINE_SEP);
i++; // move pointer
break;
default:
if(currentLiteral.length() != 0) {
addToList(new LiteralPatternConverter(
currentLiteral.toString()));
//LogLog.debug("Parsed LITERAL converter: \""
// +currentLiteral+"\".");
}
currentLiteral.setLength(0);
currentLiteral.append(c); // append %
state = CONVERTER_STATE;
formattingInfo.reset();
}
}
else {
currentLiteral.append(c);
}
break;
case CONVERTER_STATE:
currentLiteral.append(c);
switch(c) {
case '-':
formattingInfo.leftAlign = true;
break;
case '.':
state = DOT_STATE;
break;
default:
if(c >= '0' && c <= '9') {
formattingInfo.min = c - '0';
state = MIN_STATE;
}
else
finalizeConverter(c);
} // switch
break;
case MIN_STATE:
currentLiteral.append(c);
if(c >= '0' && c <= '9')
formattingInfo.min = formattingInfo.min*10 + (c - '0');
else if(c == '.')
state = DOT_STATE;
else {
finalizeConverter(c);
}
break;
case DOT_STATE:
currentLiteral.append(c);
if(c >= '0' && c <= '9') {
formattingInfo.max = c - '0';
state = MAX_STATE;
}
else {
LogLog.error("["+c+"] at pos "+i+" not a digit");
state = LITERAL_STATE;
}
break;
case MAX_STATE:
currentLiteral.append(c);
if(c >= '0' && c <= '9')
formattingInfo.max = formattingInfo.max*10 + (c - '0');
else {
finalizeConverter(c);
state = LITERAL_STATE;
}
break;
} // switch
} // while
if(currentLiteral.length() != 0) {
addToList(new LiteralPatternConverter(currentLiteral.toString()));
//LogLog.debug("Parsed LITERAL converter: \""+currentLiteral+"\".");
}
return head;
}
protected
void finalizeConverter(char c) {
PatternConverter pc = null;
switch(c) {
case 'c':
pc = new CategoryPatternConverter(formattingInfo,
extractPrecisionOption());
//LogLog.debug("CATEGORY converter.");
//formattingInfo.dump();
currentLiteral.setLength(0);
break;
case 'm':
pc = new BasicPatternConverter(formattingInfo, MESSAGE_CONVERTER);
//LogLog.debug("MESSAGE converter.");
//formattingInfo.dump();
currentLiteral.setLength(0);
break;
case 'p':
pc = new BasicPatternConverter(formattingInfo, PRIORITY_CONVERTER);
//LogLog.debug("PRIORITY converter.");
//formattingInfo.dump();
currentLiteral.setLength(0);
break;
case 'r':
pc = new BasicPatternConverter(formattingInfo,
RELATIVE_TIME_CONVERTER);
//LogLog.debug("RELATIVE time converter.");
//formattingInfo.dump();
currentLiteral.setLength(0);
break;
case 't':
pc = new BasicPatternConverter(formattingInfo, THREAD_CONVERTER);
//LogLog.debug("THREAD converter.");
//formattingInfo.dump();
currentLiteral.setLength(0);
break;
/*case 'u':
if(i < patternLength) {
char cNext = pattern.charAt(i);
if(cNext >= '0' && cNext <= '9') {
pc = new UserFieldPatternConverter(formattingInfo, cNext - '0');
LogLog.debug("USER converter ["+cNext+"].");
formattingInfo.dump();
currentLiteral.setLength(0);
i++;
}
else
LogLog.error("Unexpected char" +cNext+" at position "+i);
}
break;*/
//case 'x':
//pc = new BasicPatternConverter(formattingInfo, NDC_CONVERTER);
//currentLiteral.setLength(0);
//break;
default:
LogLog.error("Unexpected ["+c+"] at "+i+" in ConvPattern");
pc = new LiteralPatternConverter(currentLiteral.toString());
currentLiteral.setLength(0);
}
addConverter(pc);
}
protected
void addConverter(PatternConverter pc) {
currentLiteral.setLength(0);
// Add the pattern converter to the list.
addToList(pc);
// Next pattern is assumed to be a literal.
state = LITERAL_STATE;
// Reset formatting info
formattingInfo.reset();
}
// ---------------------------------------------------------------------
// PatternConverters
// ---------------------------------------------------------------------
private static class BasicPatternConverter extends PatternConverter {
int type;
BasicPatternConverter(FormattingInfo formattingInfo, int type) {
super(formattingInfo);
this.type = type;
}
public
String convert(LoggingEvent event) {
switch(type) {
case RELATIVE_TIME_CONVERTER:
return (Long.toString(event.timeStamp - LoggingEvent.getStartTime()));
case THREAD_CONVERTER:
return event.getThreadName();
case PRIORITY_CONVERTER:
return event.priority.toString();
//case NDC_CONVERTER:
//return event.getNDC();
case MESSAGE_CONVERTER: {
return event.message;
}
default: return null;
}
}
}
private static class LiteralPatternConverter extends PatternConverter {
private String literal;
LiteralPatternConverter(String value) {
literal = value;
}
public
final
void format(StringBuffer sbuf, LoggingEvent event) {
sbuf.append(literal);
}
public
String convert(LoggingEvent event) {
return literal;
}
}
private static class CategoryPatternConverter extends PatternConverter {
int precision;
CategoryPatternConverter(FormattingInfo formattingInfo, int precision) {
super(formattingInfo);
this.precision = precision;
}
//String getFullyQualifiedName(LoggingEvent event) {
//return
//}
public
String convert(LoggingEvent event) {
String n = event.categoryName;
if(precision <= 0)
return n;
else {
int len = n.length();
// We substract 1 from 'len' when assigning to 'end' to avoid out of
// bounds exception in return r.substring(end+1, len). This can happen if
// precision is 1 and the category name ends with a dot.
int end = len -1 ;
for(int i = precision; i > 0; i--) {
end = n.lastIndexOf('.', end-1);
if(end == -1)
return n;
}
return n.substring(end+1, len);
}
}
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/spi/LoggingEvent.java
Index: LoggingEvent.java
===================================================================
/*
* 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.spi;
import org.apache.log4j.Category;
import org.apache.log4j.Priority;
import org.apache.log4j.NDC;
import org.apache.log4j.helpers.LogLog;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.util.Hashtable;
// Contributors: Nelson Minar <ne...@monkey.org>
// Wolf Siberski
// Anders Kristensen <ak...@dynamicsoft.com>
/**
The internal representation of logging events. When an affirmative
decision is made to log then a <code>LoggingEvent</code> instance
is created. This instance is passed around to the different log4j
components.
<p>This class is of concern to those wishing to extend log4j.
@author Ceki Gülcü
@author James P. Cakalic
@since 0.8.2 */
public class LoggingEvent {
private static long startTime = System.currentTimeMillis();
/** The category of the logging event. The category field is not
serialized for performance reasons.
<p>It is set by the LoggingEvent constructor or set by a remote
entity after deserialization. */
transient public Category category;
/** The category name. */
public final String categoryName;
/** Priority of logging event. Priority cannot be serializable
because it is a flyweight. Due to its special seralization it
cannot be declared final either. */
transient public Priority priority;
/** The nested diagnostic context (NDC) of logging event. */
//private String ndc;
/** 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. */
private boolean ndcLookupRequired = true;
/** The application supplied message of logging event. */
transient public String message;
/** The name of thread in which this logging event was generated. */
private String threadName;
/** The throwable associated with this logging event.
This is field is transient because not all exception are
serializable. More importantly, the stack information does not
survive serialization.
*/
transient public Throwable throwable;
/** This variable collects the info on a throwable. This variable
will be shipped to
*/
public String throwableStr;
/** The number of milliseconds elapsed from 1/1/1970 until logging event
was created. */
public final long timeStamp;
/**
Instantiate a LoggingEvent from the supplied parameters.
<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 priority The priority of this event.
@param message The message of this event.
@param throwable The throwable of this event. */
public LoggingEvent(Category category, Priority priority, Object message,
Throwable throwable) {
this.category = category;
this.categoryName = category.getName();
this.priority = priority;
this.message = message.toString();
this.throwable = throwable;
timeStamp = System.currentTimeMillis();
}
/**
Return the message for this logging event.
<p>Before serialization, the returned object is the message
passed by the user to generate the logging event. After
serialization, the returned value equals the String form of the
message possibly after object rendering.
@since 1.1 */
public
Object getMessage() {
return message;
}
//public
//String getMessageStr() {
//return message.toString();
//}
//public
//String getNDC() {
// if(ndcLookupRequired) {
// ndcLookupRequired = false;
// ndc = NDC.get();
// }
// return ndc;
//}
/**
Returns the time when the application started, in milliseconds
elapsed since 01.01.1970. */
public
static
long getStartTime() {
return startTime;
}
public
String getThreadName() {
if(threadName == null)
threadName = (Thread.currentThread()).getName();
return threadName;
}
/**
Returns the throwable information contained within this
event. May be <code>null</code> if there is no such information.
*/
public
String getThrowableStr() {
if(throwable == null) {
return null;
}
if(throwableStr == null ) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
throwable.printStackTrace(pw);
throwableStr = sw.toString();
}
return throwableStr;
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/spi/OptionHandler.java
Index: OptionHandler.java
===================================================================
package org.apache.log4j.spi;
import org.apache.log4j.FileAppender;
/**
A string based interface to configure package components.
@author Ceki Gülcü
*/
public interface OptionHandler {
/**
Activate the options that were previously set with calls to option
setters.
<p>This allows to defer activiation of the options until all
options have been set. This is required for components which have
related options that remain ambigous until all are set.
*/
public
void activateOptions();
public
String[] getOptionStrings();
public
void setOption(String key, String value);
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/spi/RootCategory.java
Index: RootCategory.java
===================================================================
package org.apache.log4j.spi;
import org.apache.log4j.Category;
import org.apache.log4j.Priority;
import org.apache.log4j.helpers.LogLog;
/**
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 #getChainedPriority} method always returns the value of the
priority field without walking the hierarchy.
@author Ceki Gülcü
*/
final public class RootCategory extends Category {
/**
The root category names itself as "root". However, the root
category cannot be retrieved by name.
*/
public
RootCategory(Priority priority) {
super("root");
setPriority(priority);
}
/**
Return the assigned priority value without walking the category
hierarchy.
*/
final
public
Priority getChainedPriority() {
return priority;
}
/**
Setting a null value to the priority of the root category may have catastrophic
results. We prevent this here.
@since 0.8.3 */
final
public
void setPriority(Priority priority) {
if(priority == null) {
LogLog.error("null priority disallowed", new Throwable());
}
else {
this.priority = priority;
}
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/.cvsignore
Index: .cvsignore
===================================================================
test*
current.reg*
logging.lcf
socket.lcf
temp*
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/.functions
Index: .functions
===================================================================
# Constants
TEMP=temp
OUTPUT=current.reg
LCF=logging.lcf
# +=============================================+
# Strip the filename, retain the directory only.|
# +=============================================+
function getShellScriptDirectory {
local dir
dir=${0%/*}
if [ "$dir" = "." ]
then
dir=$(pwd)
elif [ "${dir#/}" = "$dir" ] # dir does not start with a /
then
dir=$(pwd)/$dir
fi
echo $dir
}
# +=============================================
# Compensate for ZRL idiosyncrasy
# +=============================================
function setPERL {
if [ -z "$PERL" ]
then
PERL=perl
fi
}
# +============================================
# Print a message and exit.
# +============================================
function die {
echo $1
exit 1
}
# ==============================================
# Delete the file if exists
# ==============================================
function deleteFile {
if [ -e $1 ]; then
echo "Deleting file [$1]."
rm $1
fi
}
# ----------------------------------------------------------------------
function check() {
if ! cmp -s $1 $2
then
echo "The output of current code DIFFERS from witness."
exit 1;
fi
}
# =============================================
# Echo to $LCF
# =============================================
function lecho {
# The quotes ensure that spaces in arguments are preserved.
echo "$*" >> $LCF
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/ConfigurationFileParsing.java
Index: ConfigurationFileParsing.java
===================================================================
/*
* 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.test;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.Category;
public class ConfigurationFileParsing {
static Category log = Category.getInstance(ConfigurationFileParsing.class);
public
static
void main(String argv[]) {
if(argv.length == 1) {
PropertyConfigurator.configure(argv[0]);
Category root = Category.getRoot();
root.debug("Message 1");
log.info("Message 2");
root.warn("Message 3");
log.error("Message 4");
}
else {
Usage("Wrong number of arguments.");
}
}
static
void Usage(String msg) {
System.err.println(msg);
System.err.println("Usage: java "+ConfigurationFileParsing.class.getName()
+ " fileName");
System.exit(1);
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/Hello.java
Index: Hello.java
===================================================================
/*
* 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.test;
import org.apache.log4j.*;
import org.apache.log4j.helpers.LogLog;
/**
Very simple log4j usage example.
@author Ceki Gülcü
*/
public class Hello {
static Category log = Category.getInstance(Hello.class);
public
static
void main(String argv[]) {
Category root = Category.getRoot();
Layout layout = new PatternLayout("%p [%t] %c - %m%n");
try {
root.addAppender(new FileAppender(layout, System.out));
} catch(Exception e) {
LogLog.warn("Could not open file appender.");
}
log.debug("Hello world.");
log.info("What a beatiful day.");
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/Min.java
Index: Min.java
===================================================================
package org.apache.log4j.test;
import org.apache.log4j.*;
import org.apache.log4j.helpers.LogLog;
import java.io.IOException;
/**
This class tests the functionality of the Category class and the
different layouts.
@author Ceki Gülcü
*/
public class Min {
public
static
void main(String argv[]) {
if(argv.length == 1) {
ProgramInit(argv[0]);
}
else {
Usage("Wrong number of arguments.");
}
test1();
}
static
void Usage(String msg) {
System.err.println(msg);
System.err.println( "Usage: java org.apache.log4j.test.Min format");
System.exit(1);
}
/**
Program wide initialization method.
*/
static
void ProgramInit(String format) {
try {
Layout layout = new PatternLayout(format);
Appender appender = new FileAppender(layout, System.out);
Category.getRoot().addAppender(appender);
} catch(Exception e) {
LogLog.error("Could not initialize log4j.");
}
}
static
void test1() {
int i = 0;
// In the lines below, the category names are chosen as an aid in
// remembering their priority values. In general, the category
// names should have no bearing to priority values.
Category ERR = Category.getInstance("ERR");
ERR.setPriority(Priority.ERROR);
Category INF = Category.getInstance("INF");
INF.setPriority(Priority.INFO);
Category INF_ERR = Category.getInstance("INF.ERR");
INF_ERR.setPriority(Priority.ERROR);
Category DEB = Category.getInstance("DEB");
DEB.setPriority(Priority.DEBUG);
// Note: categories with undefined priority
Category INF_UNDEF = Category.getInstance("INF.UNDEF");
Category INF_ERR_UNDEF = Category.getInstance("INF.ERR.UNDEF");
Category UNDEF = Category.getInstance("UNDEF");
// These should all log.----------------------------
ERR.fatal("Message " + i); i++; //0
ERR.error("Message " + i); i++;
ERR.info("Message " + i);
ERR.debug("Message " + i);
INF.fatal("Message " + i); i++; // 2
INF.error( "Message " + i); i++;
INF.warn ( "Message " + i); i++;
INF.info ( "Message " + i); i++;
INF_UNDEF.fatal( "Message " + i); i++; //6
INF_UNDEF.error( "Message " + i); i++;
INF_UNDEF.warn ( "Message " + i); i++;
INF_UNDEF.info ( "Message " + i); i++;
INF_UNDEF.debug ( "Message " + i);
INF_ERR.fatal( "Message " + i); i++; // 10
INF_ERR.error( "Message " + i); i++;
INF_ERR_UNDEF.fatal( "Message " + i); i++;
INF_ERR_UNDEF.error( "Message " + i); i++;
DEB.fatal( "Message " + i); i++; //14
DEB.error( "Message " + i); i++;
DEB.warn ( "Message " + i); i++;
DEB.info ( "Message " + i); i++;
DEB.debug( "Message " + i); i++;
// defaultPriority=DEBUG
UNDEF.error("Message " + i); i++;
UNDEF.warn ("Message " + i); i++;
UNDEF.info ("Message " + i); i++;
UNDEF.debug("Message " + i, new Exception("Just testing")); i++;
// -------------------------------------------------
// The following should not log
ERR.warn("Message " + i); i++;
ERR.info("Message " + i); i++;
ERR.debug("Message " + i); i++;
INF.debug("Message " + i); i++;
INF_UNDEF.debug("Message " + i); i++;
INF_ERR.warn("Message " + i); i++;
INF_ERR.info("Message " + i); i++;
INF_ERR.debug("Message " + i); i++;
INF_ERR_UNDEF.warn("Message " + i); i++;
INF_ERR_UNDEF.info("Message " + i); i++;
INF_ERR_UNDEF.debug("Message " + i); i++;
// -------------------------------------------------
INF.info("Messages should bear numbers 0 through 22.");
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/Shallow.java
Index: Shallow.java
===================================================================
package org.apache.log4j.test;
import org.apache.log4j.*;
import org.apache.log4j.helpers.LogLog;
import java.io.IOException;
import java.util.Enumeration;
/**
This class is a shallow test of the various appenders and
layouts. It also tests their reading of the configuration file.
@author Ceki Gülcü
*/
public class Shallow {
static Category cat = Category.getInstance(Shallow.class);
public
static
void main(String argv[]) {
if(argv.length == 2)
init(argv[0], argv[1]);
else
usage("Wrong number of arguments.");
test();
}
static
void usage(String msg) {
System.err.println(msg);
System.err.println( "Usage: java "+ Shallow.class.getName()+" file format");
System.exit(1);
}
static
void init(String file, String format) {
Category root = Category.getRoot();
Layout layout = new PatternLayout(format);
try {
root.addAppender(new FileAppender(layout, file));
} catch(Exception e) {
LogLog.warn("Could not open file ["+file+"].");
}
}
static
void test() {
int i = -1;
Category root = Category.getRoot();
cat.debug("Message " + ++i);
root.debug("Message " + i);
cat.info ("Message " + ++i);
cat.warn ("Message " + ++i);
cat.error("Message " + ++i);
Exception e = new Exception("Just testing");
cat.debug("Message " + ++i, e);
root.info("Message " + ++i, e);
cat.warn("Message " + ++i, e);
root.error("Message " + ++i, e);
}
}
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/confParsing
Index: confParsing
===================================================================
#!/bin/bash
# Read the .functions file
. .functions
declare -i start=$1
setPERL
# =========================================================================
# This script runs ConfigurationFileParsing java program with args1 and 2.
# It has the side effect of aggregating the following arguments to one
# file called $TEMP.
# It runs a perl filter to remove date, line and other variable
# information from the output.
# =========================================================================
function testConfigurationParsing {
configFile=$1;
options=$2; shift; shift;
echo -n " ConfigurationParsing test $TEST - "
java $D_FLAG org.apache.log4j.test.ConfigurationFileParsing $configFile
if [ -n "$*" ]; then
cat $* $TEMP >> $TEMP.x
mv $TEMP.x $TEMP
fi
$PERL filter.pl $TEMP $OUTPUT ConfigurationFileParsing $options
if [ $? != 0 ]; then
echo "The output is not in expected format. See the file [$OUTPUT]."
exit 1
fi
check witness/confParsing.$TEST $OUTPUT; echo " OK"
}
# =========================================================================
# Just run ConfigurationFileParsing and direct the output to STDOUT or
# STDERR.
# =========================================================================
function testConfigurationParsingII {
conf=$1;
target=$2
case $target in
OUT )
java $D_FLAG org.apache.log4j.test.ConfigurationFileParsing $conf>$TEMP
;;
ERR )
java $D_FLAG org.apache.log4j.test.ConfigurationFileParsing $conf>& $TEMP
;;
esac
check witness/confParsing.$TEST $TEMP; echo " OK"
}
# ======================================================
declare -i TEST
TEST=1;
if [ $TEST -ge $start ]; then
D_FLAG=""
echo "log4j.rootCategory= , testAppender" > $LCF
lecho "log4j.debug="
lecho "log4j.appender.testAppender=org.apache.log4j.FileAppender"
lecho "log4j.appender.testAppender.File=$TEMP"
lecho "log4j.appender.testAppender.Append= false "
lecho "log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout"
lecho "log4j.appender.testAppender.layout.ConversionPattern=%-5p [%t] %c{2} - %m%n"
testConfigurationParsing $LCF NONE
fi
TEST=2;
if [ $TEST -ge $start ]; then
D_FLAG=""
echo "log4j.rootCategory= DEBUG , testAppender" > $LCF
lecho "log4j.debug=false"
lecho "log4j.appender.testAppender=org.apache.log4j.FileAppender"
# Note the spaces
lecho "log4j.appender.testAppender.File=System.out "
lecho "log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout "
lecho "log4j.appender.testAppender.layout.ConversionPattern=[%t] %p - %m%n"
echo -n " ConfigurationParsing test $TEST - "
testConfigurationParsingII $LCF OUT
fi
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/hello
Index: hello
===================================================================
#!/bin/bash
# A regression test to check the option reading code and print formats.
# Read the .functions file
. .functions
deleteFile $OUTPUT
echo -n "Hello test $TEST - "
java org.apache.log4j.test.Hello > $OUTPUT
check witness/hello $OUTPUT; echo "OK"
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/min
Index: min
===================================================================
#!/bin/bash
# A regression test to check the option reading code and print formats.
# Read the .functions file
. .functions
# If set, allows to skip tests
declare -i start=$1
# ----------------------------------------------------------------------
function testMin {
filter="$1"
format="$2"
echo -n "Min test $TEST - "
runMin "$format"
$PERL filter.pl $TEMP $OUTPUT Min $filter
if [ $? != 0 ]; then
echo "The output is not in expected format. See the file [$OUTPUT]."
exit 1
fi
check witness/min.$TEST $OUTPUT; echo "OK"
}
# ----------------------------------------------------------------------
function runMin {
format="$1"
file="$2"
#java -Dlog4j.configDebug org.apache.log4j.test.Shallow $confFile
java org.apache.log4j.test.Min "$format" > $TEMP
}
# ===============================================================
setPERL
declare -i TEST
deleteFile $TEMP
TEST=1
if [ $TEST -ge $start ]; then
testMin NONE "%5p %c [%t] - %m%n"
fi
TEST=2
if [ $TEST -ge $start ]; then
testMin RELATIVE "%r [%t] %p - %m%n"
fi
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/shallow
Index: shallow
===================================================================
#!/bin/bash
# A regression test to check the option reading code and print formats.
# Read the .functions file
. .functions
# If set, allows to skip tests
declare -i start=$1
# ----------------------------------------------------------------------
function testShallow {
file="$1"
filter="$2"
format="$3"
echo -n "Shallow test $TEST - "
runShallow "$format" $file
$PERL filter.pl $TEMP $OUTPUT Shallow $filter
if [ $? != 0 ]; then
echo "The output is not in expected format. See the file [$OUTPUT]."
exit 1
fi
check witness/shallow.$TEST $OUTPUT; echo "OK"
}
# ----------------------------------------------------------------------
function runShallow {
format="$1"
file="$2"
#java -Dlog4j.configDebug org.apache.log4j.test.Shallow $confFile
java org.apache.log4j.test.Shallow "$file" "$format"
}
# ===============================================================
setPERL
declare -i TEST
deleteFile $TEMP
TEST=1
if [ $TEST -ge $start ]; then
testShallow $TEMP NONE "%p %c - %m%n"
fi
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/witness/confParsing.1
Index: confParsing.1
===================================================================
DEBUG [main] root - Message 1
INFO [main] test.ConfigurationFileParsing - Message 2
WARN [main] root - Message 3
ERROR [main] test.ConfigurationFileParsing - Message 4
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/witness/hello
Index: hello
===================================================================
DEBUG [main] org.apache.log4j.test.Hello - Hello world.
INFO [main] org.apache.log4j.test.Hello - What a beatiful day.
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/witness/min.1
Index: min.1
===================================================================
FATAL ERR [main] - Message 0
ERROR ERR [main] - Message 1
FATAL INF [main] - Message 2
ERROR INF [main] - Message 3
WARN INF [main] - Message 4
INFO INF [main] - Message 5
FATAL INF.UNDEF [main] - Message 6
ERROR INF.UNDEF [main] - Message 7
WARN INF.UNDEF [main] - Message 8
INFO INF.UNDEF [main] - Message 9
FATAL INF.ERR [main] - Message 10
ERROR INF.ERR [main] - Message 11
FATAL INF.ERR.UNDEF [main] - Message 12
ERROR INF.ERR.UNDEF [main] - Message 13
FATAL DEB [main] - Message 14
ERROR DEB [main] - Message 15
WARN DEB [main] - Message 16
INFO DEB [main] - Message 17
DEBUG DEB [main] - Message 18
ERROR UNDEF [main] - Message 19
WARN UNDEF [main] - Message 20
INFO UNDEF [main] - Message 21
DEBUG UNDEF [main] - Message 22
java.lang.Exception: Just testing
at org.apache.log4j.test.Min.test1(Min.java)
at org.apache.log4j.test.Min.main(Min.java)
INFO INF [main] - Messages should bear numbers 0 through 22.
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/witness/min.2
Index: min.2
===================================================================
[main] FATAL - Message 0
[main] ERROR - Message 1
[main] FATAL - Message 2
[main] ERROR - Message 3
[main] WARN - Message 4
[main] INFO - Message 5
[main] FATAL - Message 6
[main] ERROR - Message 7
[main] WARN - Message 8
[main] INFO - Message 9
[main] FATAL - Message 10
[main] ERROR - Message 11
[main] FATAL - Message 12
[main] ERROR - Message 13
[main] FATAL - Message 14
[main] ERROR - Message 15
[main] WARN - Message 16
[main] INFO - Message 17
[main] DEBUG - Message 18
[main] ERROR - Message 19
[main] WARN - Message 20
[main] INFO - Message 21
[main] DEBUG - Message 22
java.lang.Exception: Just testing
at org.apache.log4j.test.Min.test1(Min.java)
at org.apache.log4j.test.Min.main(Min.java)
[main] INFO - Messages should bear numbers 0 through 22.
1.1 jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/witness/shallow.1
Index: shallow.1
===================================================================
DEBUG org.apache.log4j.test.Shallow - Message 0
DEBUG root - Message 0
INFO org.apache.log4j.test.Shallow - Message 1
WARN org.apache.log4j.test.Shallow - Message 2
ERROR org.apache.log4j.test.Shallow - Message 3
DEBUG org.apache.log4j.test.Shallow - Message 4
java.lang.Exception: Just testing
at org.apache.log4j.test.Shallow.test(Shallow.java)
at org.apache.log4j.test.Shallow.main(Shallow.java)
INFO root - Message 5
java.lang.Exception: Just testing
at org.apache.log4j.test.Shallow.test(Shallow.java)
at org.apache.log4j.test.Shallow.main(Shallow.java)
WARN org.apache.log4j.test.Shallow - Message 6
java.lang.Exception: Just testing
at org.apache.log4j.test.Shallow.test(Shallow.java)
at org.apache.log4j.test.Shallow.main(Shallow.java)
ERROR root - Message 7
java.lang.Exception: Just testing
at org.apache.log4j.test.Shallow.test(Shallow.java)
at org.apache.log4j.test.Shallow.main(Shallow.java)
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>