Moved optional distribution into contrib.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/logging/trunk@356008 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
15
build.xml
15
build.xml
@@ -108,7 +108,6 @@
|
||||
<property name="core.jar.name" value="commons-${component.name}-${component.version}.jar"/>
|
||||
<property name="api.jar.name" value="commons-${component.name}-api-${component.version}.jar"/>
|
||||
<property name="adapters.jar.name" value="commons-${component.name}-adapters-${component.version}.jar"/>
|
||||
<property name="optional.jar.name" value="commons-${component.name}-optional-${component.version}.jar"/>
|
||||
|
||||
<!-- ========== Compiler Defaults ========================================= -->
|
||||
|
||||
@@ -571,20 +570,6 @@ limitations under the License.-->'>
|
||||
<include name="${adapters.jar.name}"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<!--
|
||||
- Now build the optional jar in subdir "optional" and copy that into
|
||||
- the dist directory too.
|
||||
-->
|
||||
<ant antfile='build.xml' target='dist' dir='${optional.home}' inheritAll="false" />
|
||||
<copy todir="${dist.home}">
|
||||
<fileset dir='${optional.dist.home}'>
|
||||
<include name='*.jar'/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy todir="${dist.home}/docs-optional">
|
||||
<fileset dir='${optional.dist.home}/docs'/>
|
||||
</copy>
|
||||
|
||||
<!--
|
||||
- And copy the source too; we don't have separate source and binary distributions
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
# Copyright 2001-2004 The Apache Software Foundation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# log4j.jar - log4j classes (see http://jakarta.apache.org/log4j)
|
||||
log4j.jar=/java/log4j/log4j.jar
|
||||
|
||||
# Used for testing against older 1.2.x Log4J versions
|
||||
log4j12.jar=/java/log4j/log4j-1.2.7.jar
|
||||
|
||||
# logkit.jar - Avalon LogKit classes (see http://jakarta.apache.org/avalon)
|
||||
logkit.jar=/java/logkit/logkit.jar
|
||||
|
||||
# Avalon framework - used for wrapper for avalon framework logger
|
||||
avalon-framework.jar=../../Avalon-4.1.4/avalon-framework-4.1.4.jar
|
||||
|
||||
#
|
||||
# if you want to run the test cases, junit needs to be in the classpath.
|
||||
# the build.xml uses a default value so you might not need to set this property.
|
||||
#
|
||||
# junit.jar=../../jakarta-velocity/build/lib/junit-3.7.jar
|
||||
|
||||
# Maven properties (for web site build)
|
||||
# Those committers using agents may like to use
|
||||
#maven.username=rdonkin
|
||||
#logging.cvs=lserver:rdonkin@cvs.apache.org:/home/cvs
|
||||
@@ -1,268 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright 2004 The Apache Software Foundation.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
|
||||
<project name="Logging" default="compile" basedir=".">
|
||||
|
||||
<!--
|
||||
"Logging" component of the Jakarta Commons Subproject
|
||||
$Id$
|
||||
-->
|
||||
|
||||
|
||||
<!-- ========== Initialize Properties ===================================== -->
|
||||
|
||||
<property file="build.properties"/> <!-- Distribution local -->
|
||||
<property file="../build.properties"/> <!-- Component local -->
|
||||
<property file="../../build.properties"/> <!-- Commons local -->
|
||||
<property file="${user.home}/build.properties"/> <!-- User local -->
|
||||
|
||||
<!-- ========== External Dependencies ===================================== -->
|
||||
|
||||
<!-- The directories corresponding to your necessary dependencies -->
|
||||
<property name="junit.home" value="/usr/local/junit3.5"/>
|
||||
<property name="jakarta.home" value="../../.."/>
|
||||
|
||||
<!-- ========== Component Declarations ==================================== -->
|
||||
|
||||
|
||||
<!-- The name of this component -->
|
||||
<property name="component.name" value="logging-optional"/>
|
||||
|
||||
<!-- The primary package name of this component -->
|
||||
<property name="component.package" value="org.apache.commons.logging"/>
|
||||
|
||||
<!-- The title of this component -->
|
||||
<property name="component.title" value="Logging Wrapper Library (Optional Implementations)"/>
|
||||
|
||||
<!-- The current version number of this component -->
|
||||
<property name="component.version" value="1.1-dev"/>
|
||||
|
||||
<!-- The base directory for compilation targets -->
|
||||
<property name="build.home" value="${basedir}/target"/>
|
||||
|
||||
<!-- The base directory for component configuration files -->
|
||||
<property name="conf.home" value="src/conf"/>
|
||||
|
||||
<!-- The base directory for distribution targets -->
|
||||
<property name="dist.home" value="dist"/>
|
||||
|
||||
<!-- The base directory for component sources -->
|
||||
<property name="source.home" value="src/java"/>
|
||||
|
||||
<!-- The base directory for unit test sources -->
|
||||
<property name="test.home" value="src/test"/>
|
||||
|
||||
<!-- jar name -->
|
||||
<property name="optional.jar.name" value="commons-${component.name}-${component.version}.jar"/>
|
||||
|
||||
|
||||
<!-- ========== Derived Values ============================================ -->
|
||||
|
||||
|
||||
<!-- The locations of necessary jar files -->
|
||||
<property name="junit.jar" value="${junit.home}/junit.jar"/>
|
||||
<property name="commons-logging-core.jar" value="../dist/commons-logging-${component.version}.jar"/>
|
||||
|
||||
<!-- ========== Compiler Defaults ========================================= -->
|
||||
|
||||
|
||||
<!-- Should Java compilations set the 'debug' compiler option? -->
|
||||
<property name="compile.debug" value="true"/>
|
||||
|
||||
<!-- Should Java compilations set the 'deprecation' compiler option? -->
|
||||
<property name="compile.deprecation" value="false"/>
|
||||
|
||||
<!-- Should Java compilations set the 'optimize' compiler option? -->
|
||||
<property name="compile.optimize" value="false"/>
|
||||
|
||||
<!-- Construct compile classpath -->
|
||||
<path id="compile.classpath">
|
||||
<pathelement location="${build.home}/classes"/>
|
||||
<pathelement location="${junit.jar}"/>
|
||||
<pathelement location="${commons-logging-core.jar}"/>
|
||||
<pathelement location="${log4j12.jar}"/>
|
||||
</path>
|
||||
|
||||
|
||||
<!-- ========== Test Execution Defaults =================================== -->
|
||||
|
||||
|
||||
<!-- Construct unit test classpath (generic tests) -->
|
||||
<path id="test.classpath">
|
||||
<pathelement location="${build.home}/classes"/>
|
||||
<pathelement location="${build.home}/tests"/>
|
||||
<pathelement location="${junit.jar}"/>
|
||||
<pathelement location="${conf.home}"/>
|
||||
<pathelement location="${commons-logging-core.jar}"/>
|
||||
<pathelement location="${log4j12.jar}"/>
|
||||
</path>
|
||||
|
||||
<!-- Should all tests fail if one does? -->
|
||||
<property name="test.failonerror" value="true"/>
|
||||
|
||||
<!-- The test runner to execute -->
|
||||
<property name="test.runner" value="junit.textui.TestRunner"/>
|
||||
<property name="test.entry" value="org.apache.commons.logging.TestAll"/>
|
||||
<property name="test.wrapper" value="org.apache.commons.logging.Wrapper"/>
|
||||
|
||||
<!-- ========== Executable Targets ======================================== -->
|
||||
|
||||
|
||||
<target name="init"
|
||||
description="Initialize and evaluate conditionals">
|
||||
<echo message="-------- ${component.title} ${component.version} --------"/>
|
||||
<filter token="name" value="${component.name}"/>
|
||||
<filter token="package" value="${component.package}"/>
|
||||
<filter token="version" value="${component.version}"/>
|
||||
</target>
|
||||
|
||||
<target name="prepare" depends="init"
|
||||
description="Prepare build directory">
|
||||
|
||||
<echo>
|
||||
Preparing build directory...
|
||||
</echo>
|
||||
<mkdir dir="${build.home}"/>
|
||||
<mkdir dir="${build.home}/conf"/>
|
||||
<mkdir dir="${build.home}/classes"/>
|
||||
<mkdir dir="${build.home}/docs"/>
|
||||
<mkdir dir="${build.home}/docs/api"/>
|
||||
<mkdir dir="${build.home}/tests"/>
|
||||
</target>
|
||||
|
||||
<target name="static" depends="prepare"
|
||||
description="Copy static files to build directory">
|
||||
<tstamp/>
|
||||
<copy todir="${build.home}/conf" filtering="on">
|
||||
<fileset dir="${conf.home}" includes="*.MF"/>
|
||||
<fileset dir="${conf.home}" includes="*.properties"/>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="compile" depends="static" >
|
||||
|
||||
<javac srcdir="${source.home}"
|
||||
destdir="${build.home}/classes"
|
||||
debug="${compile.debug}"
|
||||
deprecation="${compile.deprecation}"
|
||||
optimize="${compile.optimize}">
|
||||
<classpath refid="compile.classpath"/>
|
||||
</javac>
|
||||
|
||||
<copy todir="${build.home}/classes" filtering="on">
|
||||
<fileset dir="${source.home}" excludes="**/*.java"/>
|
||||
</copy>
|
||||
<mkdir dir="${build.home}/classes/META-INF"/>
|
||||
<copy file="../LICENSE.txt"
|
||||
todir="${build.home}/classes/META-INF"/>
|
||||
<copy file="../NOTICE.txt"
|
||||
todir="${build.home}/classes/META-INF"/>
|
||||
|
||||
<jar jarfile="${build.home}/${optional.jar.name}"
|
||||
basedir="${build.home}/classes"
|
||||
manifest="${build.home}/conf/MANIFEST.MF">
|
||||
<include name="org/apache/commons/logging/**" />
|
||||
<include name="META-INF/LICENSE.txt"/>
|
||||
<include name="META-INF/NOTICE.txt"/>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="compile.tests" depends="compile"
|
||||
description="Compile unit test cases">
|
||||
<javac srcdir="${test.home}"
|
||||
destdir="${build.home}/tests"
|
||||
debug="${compile.debug}"
|
||||
deprecation="${compile.deprecation}"
|
||||
optimize="${compile.optimize}">
|
||||
<classpath refid="test.classpath"/>
|
||||
</javac>
|
||||
|
||||
<copy todir="${build.home}/tests" filtering="on">
|
||||
<fileset dir="${test.home}" excludes="**/*.java"/>
|
||||
</copy>
|
||||
|
||||
<jar jarfile="${build.home}/commons-${component.name}-tests.jar"
|
||||
basedir="${build.home}/tests"
|
||||
manifest="${build.home}/conf/MANIFEST.MF">
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="clean"
|
||||
description="Clean build and distribution directories">
|
||||
<delete dir="${build.home}"/>
|
||||
<delete dir="${dist.home}"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="all" depends="clean,compile"
|
||||
description="Clean and compile all components"/>
|
||||
|
||||
|
||||
<target name="javadoc" depends="compile"
|
||||
description="Create component Javadoc documentation">
|
||||
<mkdir dir="${dist.home}"/>
|
||||
<mkdir dir="${dist.home}/docs"/>
|
||||
<mkdir dir="${dist.home}/docs/api"/>
|
||||
<javadoc sourcepath="${source.home}"
|
||||
destdir="${dist.home}/docs/api"
|
||||
overview="${source.home}/overview.html"
|
||||
packagenames="org.apache.commons.*"
|
||||
author="true"
|
||||
private="true"
|
||||
version="true"
|
||||
doctitle="<h1>${component.title} (Version ${component.version})</h1>"
|
||||
windowtitle="${component.title} (Version ${component.version})"
|
||||
bottom='Copyright 2002-2004 The Apache Software Foundation.<!--
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.-->'>
|
||||
<classpath refid="test.classpath"/>
|
||||
</javadoc>
|
||||
</target>
|
||||
|
||||
<target name='dist' depends='compile, javadoc'>
|
||||
<copy file='${build.home}/${optional.jar.name}' todir='${dist.home}'/>
|
||||
</target>
|
||||
|
||||
<!-- ========== Unit Test Targets ========================================= -->
|
||||
|
||||
|
||||
<target name="test"
|
||||
description="Run all unit test cases" depends='compile.tests'>
|
||||
<java classname="${test.runner}" fork="yes"
|
||||
failonerror="${test.failonerror}">
|
||||
<arg value="${test.entry}"/>
|
||||
<classpath refid="test.classpath"/>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright 2004 The Apache Software Foundation.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<project>
|
||||
<pomVersion>3</pomVersion>
|
||||
|
||||
<name>Logging</name>
|
||||
<id>commons-logging-optional</id>
|
||||
<currentVersion>1.1-SNAPSHOT</currentVersion>
|
||||
<inceptionYear>2001</inceptionYear>
|
||||
<shortDescription>Commons Logging (Optional Implementations)</shortDescription>
|
||||
<description>
|
||||
Commons Logging is a thin adapter allowing configurable bridging to other,
|
||||
well known logging systems. This package contains non-core implementations.
|
||||
</description>
|
||||
<logo>/images/logo.png</logo>
|
||||
|
||||
<url>http://jakarta.apache.org/commons/logging/optional</url>
|
||||
<package>org.apache.commons.logging</package>
|
||||
|
||||
<organization>
|
||||
<name>The Apache Software Foundation</name>
|
||||
<url>http://jakarta.apache.org</url>
|
||||
<logo>http://jakarta.apache.org/images/original-jakarta-logo.gif</logo>
|
||||
</organization>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>/LICENSE.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<gumpRepositoryId>jakarta</gumpRepositoryId>
|
||||
<issueTrackingUrl>http://issues.apache.org/bugzilla/</issueTrackingUrl>
|
||||
<siteAddress>jakarta.apache.org</siteAddress>
|
||||
<siteDirectory>/www/jakarta.apache.org/commons/logging/optional</siteDirectory>
|
||||
<distributionDirectory>/www/jakarta.apache.org/builds/jakarta-commons/logging/optional/</distributionDirectory>
|
||||
|
||||
<repository>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/jakarta/commons/proper/logging/trunk</connection>
|
||||
<url>http://svn.apache.org/repos/asf/jakarta/commons/proper/logging/trunk</url>
|
||||
</repository>
|
||||
|
||||
<mailingLists>
|
||||
<mailingList>
|
||||
<name>Commons Dev List</name>
|
||||
<subscribe>commons-dev-subscribe@jakarta.apache.org</subscribe>
|
||||
<unsubscribe>commons-dev-unsubscribe@jakarta.apache.org</unsubscribe>
|
||||
<archive>http://mail-archives.apache.org/eyebrowse/SummarizeList?listName=commons-dev@jakarta.apache.org</archive>
|
||||
</mailingList>
|
||||
<mailingList>
|
||||
<name>Commons User List</name>
|
||||
<subscribe>commons-user-subscribe@jakarta.apache.org</subscribe>
|
||||
<unsubscribe>commons-user-unsubscribe@jakarta.apache.org</unsubscribe>
|
||||
<archive>http://mail-archives.apache.org/eyebrowse/SummarizeList?listName=commons-user@jakarta.apache.org</archive>
|
||||
</mailingList>
|
||||
</mailingLists>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Morgan Delagrange</name>
|
||||
<id>morgand</id>
|
||||
<email>morgand at apache dot org</email>
|
||||
<organization>Apache</organization>
|
||||
<roles><role>Java Developer</role></roles>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Rodney Waldhoff</name>
|
||||
<id>rwaldhoff</id>
|
||||
<email>rwaldhoff at apache org</email>
|
||||
<organization>Apache Software Foundation</organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Craig McClanahan</name>
|
||||
<id>craigmcc</id>
|
||||
<email>craigmcc at apache org</email>
|
||||
<organization>Apache Software Foundation</organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Scott Sanders</name>
|
||||
<id>sanders</id>
|
||||
<email>sanders at apache dot org</email>
|
||||
<organization>Apache Software Foundation</organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Robert Burrell Donkin</name>
|
||||
<id>rdonkin</id>
|
||||
<email>rdonkin at apache dot org</email>
|
||||
<organization>Apache Software Foundation</organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Peter Donald</name>
|
||||
<id>donaldp</id>
|
||||
<email>donaldp at apache dot org</email>
|
||||
<organization></organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Costin Manolache</name>
|
||||
<id>costin</id>
|
||||
<email>costin at apache dot org</email>
|
||||
<organization>Apache Software Foundation</organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Richard Sitze</name>
|
||||
<id>rsitze</id>
|
||||
<email>rsitze at apache dot org</email>
|
||||
<organization>Apache Software Foundation</organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Juozas Baliuka</name>
|
||||
<id>baliuka</id>
|
||||
<email>baliuka@apache.org</email>
|
||||
<organization></organization>
|
||||
<roles>
|
||||
<role>Java Developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<id>junit</id>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<id>commons-logging</id>
|
||||
<version>1.0.4</version>
|
||||
<url>http://jakarta.apache.org/commons/logging.html</url>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<id>log4j</id>
|
||||
<version>1.1.3</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<nagEmailAddress>commons-dev@jakarta.apache.org</nagEmailAddress>
|
||||
<sourceDirectory>src/java</sourceDirectory>
|
||||
<unitTestSourceDirectory>src/test</unitTestSourceDirectory>
|
||||
</build>
|
||||
|
||||
<reports>
|
||||
<report>maven-javadoc-plugin</report>
|
||||
<report>maven-jdepend-plugin</report>
|
||||
<report>maven-jxr-plugin</report>
|
||||
</reports>
|
||||
|
||||
</project>
|
||||
@@ -1,5 +0,0 @@
|
||||
Extension-Name: org.apache.commons.logging-optional
|
||||
Specification-Vendor: Apache Software Foundation
|
||||
Specification-Version: 1.0
|
||||
Implementation-Vendor: Apache Software Foundation
|
||||
Implementation-Version: 1.0.5
|
||||
@@ -1,223 +0,0 @@
|
||||
/*
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.apache.commons.logging.impl;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.log4j.Category;
|
||||
import org.apache.log4j.Priority;
|
||||
|
||||
/**
|
||||
* <p>Implementation of <code>Log</code> that maps directly to a Log4J
|
||||
* <strong>Category</strong>. Initial configuration of the corresponding
|
||||
* Category instances should be done in the usual manner, as outlined in
|
||||
* the Log4J documentation.</p>
|
||||
*
|
||||
* @deprecated Use <code>Log4JLogger</code> instead.
|
||||
*
|
||||
* @author <a href="mailto:sanders@apache.org">Scott Sanders</a>
|
||||
* @author Rod Waldhoff
|
||||
* @author Robert Burrell Donkin
|
||||
* @version $Id$
|
||||
*/
|
||||
public final class Log4JCategoryLog implements Log {
|
||||
|
||||
|
||||
// ------------------------------------------------------------- Attributes
|
||||
|
||||
/** The fully qualified name of the Log4JCategoryLog class. */
|
||||
private static final String FQCN = Log4JCategoryLog.class.getName();
|
||||
|
||||
/** Log to this category */
|
||||
private Category category = null;
|
||||
|
||||
|
||||
// ------------------------------------------------------------ Constructor
|
||||
|
||||
public Log4JCategoryLog() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base constructor.
|
||||
*/
|
||||
public Log4JCategoryLog(String name) {
|
||||
this.category=Category.getInstance(name);
|
||||
}
|
||||
|
||||
/** For use with a log4j factory.
|
||||
*/
|
||||
public Log4JCategoryLog(Category category ) {
|
||||
this.category=category;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------- Implmentation
|
||||
|
||||
|
||||
/**
|
||||
* Log a message to the Log4j Category with <code>TRACE</code> priority.
|
||||
* Currently logs to <code>DEBUG</code> level in Log4J.
|
||||
*/
|
||||
public void trace(Object message) {
|
||||
category.log(FQCN, Priority.DEBUG, message, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log an error to the Log4j Category with <code>TRACE</code> priority.
|
||||
* Currently logs to <code>DEBUG</code> level in Log4J.
|
||||
*/
|
||||
public void trace(Object message, Throwable t) {
|
||||
category.log(FQCN, Priority.DEBUG, message, t );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log a message to the Log4j Category with <code>DEBUG</code> priority.
|
||||
*/
|
||||
public void debug(Object message) {
|
||||
category.log(FQCN, Priority.DEBUG, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an error to the Log4j Category with <code>DEBUG</code> priority.
|
||||
*/
|
||||
public void debug(Object message, Throwable t) {
|
||||
category.log(FQCN, Priority.DEBUG, message, t );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log a message to the Log4j Category with <code>INFO</code> priority.
|
||||
*/
|
||||
public void info(Object message) {
|
||||
category.log(FQCN, Priority.INFO, message, null );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log an error to the Log4j Category with <code>INFO</code> priority.
|
||||
*/
|
||||
public void info(Object message, Throwable t) {
|
||||
category.log(FQCN, Priority.INFO, message, t );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log a message to the Log4j Category with <code>WARN</code> priority.
|
||||
*/
|
||||
public void warn(Object message) {
|
||||
category.log(FQCN, Priority.WARN, message, null );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log an error to the Log4j Category with <code>WARN</code> priority.
|
||||
*/
|
||||
public void warn(Object message, Throwable t) {
|
||||
category.log(FQCN, Priority.WARN, message, t );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log a message to the Log4j Category with <code>ERROR</code> priority.
|
||||
*/
|
||||
public void error(Object message) {
|
||||
category.log(FQCN, Priority.ERROR, message, null );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log an error to the Log4j Category with <code>ERROR</code> priority.
|
||||
*/
|
||||
public void error(Object message, Throwable t) {
|
||||
category.log(FQCN, Priority.ERROR, message, t );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log a message to the Log4j Category with <code>FATAL</code> priority.
|
||||
*/
|
||||
public void fatal(Object message) {
|
||||
category.log(FQCN, Priority.FATAL, message, null );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log an error to the Log4j Category with <code>FATAL</code> priority.
|
||||
*/
|
||||
public void fatal(Object message, Throwable t) {
|
||||
category.log(FQCN, Priority.FATAL, message, t );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the native Category instance we are using.
|
||||
*/
|
||||
public Category getCategory() {
|
||||
return (this.category);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the Log4j Category used is enabled for <code>DEBUG</code> priority.
|
||||
*/
|
||||
public boolean isDebugEnabled() {
|
||||
return category.isDebugEnabled();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the Log4j Category used is enabled for <code>ERROR</code> priority.
|
||||
*/
|
||||
public boolean isErrorEnabled() {
|
||||
return category.isEnabledFor(Priority.ERROR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the Log4j Category used is enabled for <code>FATAL</code> priority.
|
||||
*/
|
||||
public boolean isFatalEnabled() {
|
||||
return category.isEnabledFor(Priority.FATAL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the Log4j Category used is enabled for <code>INFO</code> priority.
|
||||
*/
|
||||
public boolean isInfoEnabled() {
|
||||
return category.isInfoEnabled();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the Log4j Category used is enabled for <code>TRACE</code> priority.
|
||||
* For Log4J, this returns the value of <code>isDebugEnabled()</code>
|
||||
*/
|
||||
public boolean isTraceEnabled() {
|
||||
return category.isDebugEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the Log4j Category used is enabled for <code>WARN</code> priority.
|
||||
*/
|
||||
public boolean isWarnEnabled() {
|
||||
return category.isEnabledFor(Priority.WARN);
|
||||
}
|
||||
}
|
||||
@@ -1,432 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.apache.commons.logging.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
/**
|
||||
* <p>Memory implementation of Log that keeps all log message as
|
||||
* entries in memory. The class is designed to be used in unit tests.
|
||||
* The default log level is TRACE.</p>
|
||||
* <p>The code borrows heavily from the SimpleLog class.</p>
|
||||
* @author Jörg Schaible
|
||||
* @version $Id$
|
||||
*/
|
||||
public class MemoryLog implements Log {
|
||||
|
||||
// ------------------------------------------------------- Class Attributes
|
||||
|
||||
/**
|
||||
* A class for a log entry.
|
||||
*/
|
||||
public static class Entry {
|
||||
|
||||
private final Date date;
|
||||
private final String name;
|
||||
private final int level;
|
||||
private final Object message;
|
||||
private final Throwable throwable;
|
||||
|
||||
/**
|
||||
* Construct a log entry.
|
||||
* @param name the logger's name
|
||||
* @param level the log level
|
||||
* @param message the message to log
|
||||
* @param t the throwable attending the log
|
||||
*/
|
||||
private Entry(String name, int level, Object message, Throwable t) {
|
||||
this.date = new Date();
|
||||
this.name = name;
|
||||
this.level = level;
|
||||
this.message = message;
|
||||
this.throwable = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the logging date.
|
||||
*/
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the logger's name.
|
||||
*/
|
||||
public String getLogName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the log message.
|
||||
*/
|
||||
public Object getMessage() {
|
||||
return message;
|
||||
}
|
||||
/**
|
||||
* @return Returns the attendent {@link java.lang.Throwable} of the log or null.
|
||||
*/
|
||||
public Throwable getThrowable() {
|
||||
return throwable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the log level.
|
||||
*/
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
}
|
||||
|
||||
/** The list with all log entries. */
|
||||
private static final List logEntries = Collections.synchronizedList(new ArrayList());
|
||||
|
||||
|
||||
// ---------------------------------------------------- Log Level Constants
|
||||
|
||||
/** "Trace" level logging. */
|
||||
public static final int LOG_LEVEL_TRACE = 1;
|
||||
/** "Debug" level logging. */
|
||||
public static final int LOG_LEVEL_DEBUG = 2;
|
||||
/** "Info" level logging. */
|
||||
public static final int LOG_LEVEL_INFO = 3;
|
||||
/** "Warn" level logging. */
|
||||
public static final int LOG_LEVEL_WARN = 4;
|
||||
/** "Error" level logging. */
|
||||
public static final int LOG_LEVEL_ERROR = 5;
|
||||
/** "Fatal" level logging. */
|
||||
public static final int LOG_LEVEL_FATAL = 6;
|
||||
|
||||
/** Enable all logging levels */
|
||||
public static final int LOG_LEVEL_ALL = (LOG_LEVEL_TRACE - 1);
|
||||
|
||||
/** Enable no logging levels */
|
||||
public static final int LOG_LEVEL_OFF = (LOG_LEVEL_FATAL + 1);
|
||||
|
||||
|
||||
// ------------------------------------------------------------- Attributes
|
||||
|
||||
/** The name of this simple log instance */
|
||||
protected String logName = null;
|
||||
/** The current log level */
|
||||
protected int currentLogLevel;
|
||||
|
||||
|
||||
// ------------------------------------------------------------ Constructor
|
||||
|
||||
/**
|
||||
* Construct a simple log with given name.
|
||||
*
|
||||
* @param name log name
|
||||
*/
|
||||
public MemoryLog(String name) {
|
||||
|
||||
logName = name;
|
||||
|
||||
// Set initial log level
|
||||
setLevel(MemoryLog.LOG_LEVEL_TRACE);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------- Properties
|
||||
|
||||
/**
|
||||
* <p> Set logging level. </p>
|
||||
*
|
||||
* @param currentLogLevel new logging level
|
||||
*/
|
||||
public void setLevel(int currentLogLevel) {
|
||||
|
||||
this.currentLogLevel = currentLogLevel;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Returns the logging level.
|
||||
*/
|
||||
public int getLevel() {
|
||||
|
||||
return currentLogLevel;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------- Logging Methods
|
||||
|
||||
|
||||
/**
|
||||
* <p> Do the actual logging.
|
||||
* This method assembles the message
|
||||
* and then calls <code>write()</code> to cause it to be written.</p>
|
||||
*
|
||||
* @param type One of the LOG_LEVEL_XXX constants defining the log level
|
||||
* @param message The message itself (typically a String)
|
||||
* @param t The exception whose stack trace should be logged
|
||||
*/
|
||||
protected void log(int type, Object message, Throwable t) {
|
||||
|
||||
if(isLevelEnabled(type)) {
|
||||
Entry entry = new Entry(logName, type, message, t);
|
||||
logEntries.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param logLevel is this level enabled?
|
||||
* @return Returns true if the current level is enabled.
|
||||
*/
|
||||
protected boolean isLevelEnabled(int logLevel) {
|
||||
// log level are numerically ordered so can use simple numeric
|
||||
// comparison
|
||||
return (logLevel >= currentLogLevel);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Returns the log entries.
|
||||
*/
|
||||
public static List getLogEntries() {
|
||||
return Collections.unmodifiableList(logEntries);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reset the MemoryLog and clear the log entries.
|
||||
*/
|
||||
public static void reset() {
|
||||
logEntries.clear();
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------- Log Implementation
|
||||
|
||||
|
||||
/**
|
||||
* <p> Log a message with debug log level.</p>
|
||||
*/
|
||||
public final void debug(Object message) {
|
||||
|
||||
if (isLevelEnabled(MemoryLog.LOG_LEVEL_DEBUG)) {
|
||||
log(MemoryLog.LOG_LEVEL_DEBUG, message, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Log an error with debug log level.</p>
|
||||
*/
|
||||
public final void debug(Object message, Throwable t) {
|
||||
|
||||
if (isLevelEnabled(MemoryLog.LOG_LEVEL_DEBUG)) {
|
||||
log(MemoryLog.LOG_LEVEL_DEBUG, message, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Log a message with trace log level.</p>
|
||||
*/
|
||||
public final void trace(Object message) {
|
||||
|
||||
if (isLevelEnabled(MemoryLog.LOG_LEVEL_TRACE)) {
|
||||
log(MemoryLog.LOG_LEVEL_TRACE, message, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Log an error with trace log level.</p>
|
||||
*/
|
||||
public final void trace(Object message, Throwable t) {
|
||||
|
||||
if (isLevelEnabled(MemoryLog.LOG_LEVEL_TRACE)) {
|
||||
log(MemoryLog.LOG_LEVEL_TRACE, message, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Log a message with info log level.</p>
|
||||
*/
|
||||
public final void info(Object message) {
|
||||
|
||||
if (isLevelEnabled(MemoryLog.LOG_LEVEL_INFO)) {
|
||||
log(MemoryLog.LOG_LEVEL_INFO,message,null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Log an error with info log level.</p>
|
||||
*/
|
||||
public final void info(Object message, Throwable t) {
|
||||
|
||||
if (isLevelEnabled(MemoryLog.LOG_LEVEL_INFO)) {
|
||||
log(MemoryLog.LOG_LEVEL_INFO, message, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Log a message with warn log level.</p>
|
||||
*/
|
||||
public final void warn(Object message) {
|
||||
|
||||
if (isLevelEnabled(MemoryLog.LOG_LEVEL_WARN)) {
|
||||
log(MemoryLog.LOG_LEVEL_WARN, message, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Log an error with warn log level.</p>
|
||||
*/
|
||||
public final void warn(Object message, Throwable t) {
|
||||
|
||||
if (isLevelEnabled(MemoryLog.LOG_LEVEL_WARN)) {
|
||||
log(MemoryLog.LOG_LEVEL_WARN, message, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Log a message with error log level.</p>
|
||||
*/
|
||||
public final void error(Object message) {
|
||||
|
||||
if (isLevelEnabled(MemoryLog.LOG_LEVEL_ERROR)) {
|
||||
log(MemoryLog.LOG_LEVEL_ERROR, message, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Log an error with error log level.</p>
|
||||
*/
|
||||
public final void error(Object message, Throwable t) {
|
||||
|
||||
if (isLevelEnabled(MemoryLog.LOG_LEVEL_ERROR)) {
|
||||
log(MemoryLog.LOG_LEVEL_ERROR, message, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Log a message with fatal log level.</p>
|
||||
*/
|
||||
public final void fatal(Object message) {
|
||||
|
||||
if (isLevelEnabled(MemoryLog.LOG_LEVEL_FATAL)) {
|
||||
log(MemoryLog.LOG_LEVEL_FATAL, message, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Log an error with fatal log level.</p>
|
||||
*/
|
||||
public final void fatal(Object message, Throwable t) {
|
||||
|
||||
if (isLevelEnabled(MemoryLog.LOG_LEVEL_FATAL)) {
|
||||
log(MemoryLog.LOG_LEVEL_FATAL, message, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Are debug messages currently enabled? </p>
|
||||
*
|
||||
* <p> This allows expensive operations such as <code>String</code>
|
||||
* concatenation to be avoided when the message will be ignored by the
|
||||
* logger. </p>
|
||||
*/
|
||||
public final boolean isDebugEnabled() {
|
||||
|
||||
return isLevelEnabled(MemoryLog.LOG_LEVEL_DEBUG);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Are error messages currently enabled? </p>
|
||||
*
|
||||
* <p> This allows expensive operations such as <code>String</code>
|
||||
* concatenation to be avoided when the message will be ignored by the
|
||||
* logger. </p>
|
||||
*/
|
||||
public final boolean isErrorEnabled() {
|
||||
|
||||
return isLevelEnabled(MemoryLog.LOG_LEVEL_ERROR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Are fatal messages currently enabled? </p>
|
||||
*
|
||||
* <p> This allows expensive operations such as <code>String</code>
|
||||
* concatenation to be avoided when the message will be ignored by the
|
||||
* logger. </p>
|
||||
*/
|
||||
public final boolean isFatalEnabled() {
|
||||
|
||||
return isLevelEnabled(MemoryLog.LOG_LEVEL_FATAL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Are info messages currently enabled? </p>
|
||||
*
|
||||
* <p> This allows expensive operations such as <code>String</code>
|
||||
* concatenation to be avoided when the message will be ignored by the
|
||||
* logger. </p>
|
||||
*/
|
||||
public final boolean isInfoEnabled() {
|
||||
|
||||
return isLevelEnabled(MemoryLog.LOG_LEVEL_INFO);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Are trace messages currently enabled? </p>
|
||||
*
|
||||
* <p> This allows expensive operations such as <code>String</code>
|
||||
* concatenation to be avoided when the message will be ignored by the
|
||||
* logger. </p>
|
||||
*/
|
||||
public final boolean isTraceEnabled() {
|
||||
|
||||
return isLevelEnabled(MemoryLog.LOG_LEVEL_TRACE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Are warn messages currently enabled? </p>
|
||||
*
|
||||
* <p> This allows expensive operations such as <code>String</code>
|
||||
* concatenation to be avoided when the message will be ignored by the
|
||||
* logger. </p>
|
||||
*/
|
||||
public final boolean isWarnEnabled() {
|
||||
|
||||
return isLevelEnabled(MemoryLog.LOG_LEVEL_WARN);
|
||||
}
|
||||
}
|
||||
@@ -1,488 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.apache.commons.logging.impl;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* <p>Implementation of <code>Hashtable</code> that uses <code>WeakReference</code>'s
|
||||
* to hold its keys thus allowing them to be reclaimed by the garbage collector.
|
||||
* The associated values are retained using strong references.</p>
|
||||
*
|
||||
* <p>This class follows the symantics of <code>Hashtable</code> as closely as
|
||||
* possible. It therefore does not accept null values or keys.</p>
|
||||
*
|
||||
* <p><strong>Note:</strong>
|
||||
* This is <em>not</em> intended to be a general purpose hash table replacement.
|
||||
* This implementation is also tuned towards a particular purpose: for use as a replacement
|
||||
* for <code>Hashtable</code> in <code>LogFactory</code>. This application requires
|
||||
* good liveliness for <code>get</code> and <code>put</code>. Various tradeoffs
|
||||
* have been made with this in mind.
|
||||
* </p>
|
||||
* <p>
|
||||
* <strong>Usage:</strong> typical use case is as a drop-in replacement
|
||||
* for the <code>Hashtable</code> used in <code>LogFactory</code> for J2EE enviroments
|
||||
* running 1.3+ JVMs. Use of this class <i>in most cases</i> (see below) will
|
||||
* allow classloaders to be collected by the garbage collector without the need
|
||||
* to call {@link org.apache.commons.logging.LogFactory#release(ClassLoader) LogFactory.release(ClassLoader)}.
|
||||
* </p>
|
||||
*
|
||||
* <p><code>org.apache.commons.logging.LogFactory</code> looks to see whether this
|
||||
* class is present in the classpath, and if so then uses it to store
|
||||
* references to the <code>LogFactory</code> implementationd it loads
|
||||
* (rather than using a standard Hashtable instance).
|
||||
* Having this class used instead of <code>Hashtable</code> solves
|
||||
* certain issues related to dynamic reloading of applications in J2EE-style
|
||||
* environments. However this class requires java 1.3 or later (due to its use
|
||||
* of <code>java.lang.ref.WeakReference</code> and associates) and therefore cannot be
|
||||
* included in the main logging distribution which supports JVMs prior to 1.3.
|
||||
* And by the way, this extends <code>Hashtable</code> rather than <code>HashMap</code>
|
||||
* for backwards compatibility reasons. See the documentation
|
||||
* for method <code>LogFactory.createFactoryStore</code> for more details.</p>
|
||||
*
|
||||
* <p>The reason all this is necessary is due to a issue which
|
||||
* arises during hot deploy in a J2EE-like containers.
|
||||
* Each component running in the container owns one or more classloaders; when
|
||||
* the component loads a LogFactory instance via the component classloader
|
||||
* a reference to it gets stored in the static LogFactory.factories member,
|
||||
* keyed by the component's classloader so different components don't
|
||||
* stomp on each other. When the component is later unloaded, the container
|
||||
* sets the component's classloader to null with the intent that all the
|
||||
* component's classes get garbage-collected. However there's still a
|
||||
* reference to the component's classloader from the "global" <code>LogFactory</code>'s
|
||||
* factories member! If <code>LogFactory.release()</code> is called whenever component
|
||||
* is unloaded (as happens in some famous containers), the classloaders will be correctly
|
||||
* garbage collected.
|
||||
* However, holding the classloader references weakly ensures that the classloader
|
||||
* will be garbage collected without programmatic intervention.
|
||||
* Unfortunately, weak references are
|
||||
* only available in java 1.3+, so this code only uses <code>WeakHashtable</code> if the
|
||||
* class has explicitly been made available on the classpath.</p>
|
||||
*
|
||||
* <p>
|
||||
* Because the presence of this class in the classpath ensures proper
|
||||
* unload of components without the need to call method
|
||||
* {@link org.apache.commons.logging.LogFactory#release(ClassLoader) LogFactory.release ClassLoader)},
|
||||
* it is recommended that this class be deployed along with the standard
|
||||
* commons-logging.jar file when using commons-logging in J2EE
|
||||
* environments (which will presumably be running on Java 1.3 or later).
|
||||
* There are no know ill effects from using this class.</p>
|
||||
*
|
||||
* <p>
|
||||
* <strong>Limitations:</strong>
|
||||
* There is still one (unusual) scenario in which a component will not
|
||||
* be correctly unloaded without an explicit release. Though weak references
|
||||
* are used for its keys, it is necessary to use
|
||||
* strong references for its values.</p>
|
||||
*
|
||||
* <p> If the abstract class <code>LogFactory</code> is
|
||||
* loaded by the container classloader but a subclass of
|
||||
* <code>LogFactory</code> [LogFactory1] is loaded by the component's
|
||||
* classloader and an instance stored in the static map associated with the
|
||||
* base LogFactory class, then there is a strong reference from the LogFactory
|
||||
* class to the LogFactory1 instance (as normal) and a strong reference from
|
||||
* the LogFactory1 instance to the component classloader via
|
||||
* <code>getClass().getClassLoader()</code>. This chain of references will prevent
|
||||
* collection of the child classloader.</p>
|
||||
*
|
||||
* <p>
|
||||
* Such a situation occurs when the commons-logging.jar is
|
||||
* loaded by a parent classloader (e.g. a server level classloader in a
|
||||
* servlet container) and a custom <code>LogFactory</code> implementation is
|
||||
* loaded by a child classloader (e.g. a web app classloader).</p>
|
||||
*
|
||||
* <p>To avoid this scenario, ensure
|
||||
* that any custom LogFactory subclass is loaded by the same classloader as
|
||||
* the base <code>LogFactory</code>. Creating custom LogFactory subclasses is,
|
||||
* however, rare. The standard LogFactoryImpl class should be sufficient
|
||||
* for most or all users.</p>
|
||||
*
|
||||
*
|
||||
* @author Brian Stansberry
|
||||
*/
|
||||
public final class WeakHashtable extends Hashtable {
|
||||
|
||||
/**
|
||||
* The maximum number of times put() or remove() can be called before
|
||||
* the map will be purged of all cleared entries.
|
||||
*/
|
||||
private static final int MAX_CHANGES_BEFORE_PURGE = 100;
|
||||
|
||||
/**
|
||||
* The maximum number of times put() or remove() can be called before
|
||||
* the map will be purged of one cleared entry.
|
||||
*/
|
||||
private static final int PARTIAL_PURGE_COUNT = 10;
|
||||
|
||||
/* ReferenceQueue we check for gc'd keys */
|
||||
private ReferenceQueue queue = new ReferenceQueue();
|
||||
/* Counter used to control how often we purge gc'd entries */
|
||||
private int changeCount = 0;
|
||||
|
||||
/**
|
||||
* Constructs a WeakHashtable with the Hashtable default
|
||||
* capacity and load factor.
|
||||
*/
|
||||
public WeakHashtable() {}
|
||||
|
||||
|
||||
/**
|
||||
*@see Hashtable
|
||||
*/
|
||||
public boolean containsKey(Object key) {
|
||||
// purge should not be required
|
||||
Referenced referenced = new Referenced(key);
|
||||
return super.containsKey(referenced);
|
||||
}
|
||||
|
||||
/**
|
||||
*@see Hashtable
|
||||
*/
|
||||
public Enumeration elements() {
|
||||
purge();
|
||||
return super.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
*@see Hashtable
|
||||
*/
|
||||
public Set entrySet() {
|
||||
purge();
|
||||
Set referencedEntries = super.entrySet();
|
||||
Set unreferencedEntries = new HashSet();
|
||||
for (Iterator it=referencedEntries.iterator(); it.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
Referenced referencedKey = (Referenced) entry.getKey();
|
||||
Object key = referencedKey.getValue();
|
||||
Object value = entry.getValue();
|
||||
if (key != null) {
|
||||
Entry dereferencedEntry = new Entry(key, value);
|
||||
unreferencedEntries.add(dereferencedEntry);
|
||||
}
|
||||
}
|
||||
return unreferencedEntries;
|
||||
}
|
||||
|
||||
/**
|
||||
*@see Hashtable
|
||||
*/
|
||||
public Object get(Object key) {
|
||||
// for performance reasons, no purge
|
||||
Referenced referenceKey = new Referenced(key);
|
||||
return super.get(referenceKey);
|
||||
}
|
||||
|
||||
/**
|
||||
*@see Hashtable
|
||||
*/
|
||||
public Enumeration keys() {
|
||||
purge();
|
||||
final Enumeration enumer = super.keys();
|
||||
return new Enumeration() {
|
||||
public boolean hasMoreElements() {
|
||||
return enumer.hasMoreElements();
|
||||
}
|
||||
public Object nextElement() {
|
||||
Referenced nextReference = (Referenced) enumer.nextElement();
|
||||
return nextReference.getValue();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*@see Hashtable
|
||||
*/
|
||||
public Set keySet() {
|
||||
purge();
|
||||
Set referencedKeys = super.keySet();
|
||||
Set unreferencedKeys = new HashSet();
|
||||
for (Iterator it=referencedKeys.iterator(); it.hasNext();) {
|
||||
Referenced referenceKey = (Referenced) it.next();
|
||||
Object keyValue = referenceKey.getValue();
|
||||
if (keyValue != null) {
|
||||
unreferencedKeys.add(keyValue);
|
||||
}
|
||||
}
|
||||
return unreferencedKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
*@see Hashtable
|
||||
*/
|
||||
public Object put(Object key, Object value) {
|
||||
// check for nulls, ensuring symantics match superclass
|
||||
if (key == null) {
|
||||
throw new NullPointerException("Null keys are not allowed");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("Null values are not allowed");
|
||||
}
|
||||
|
||||
// for performance reasons, only purge every
|
||||
// MAX_CHANGES_BEFORE_PURGE times
|
||||
if (changeCount++ > MAX_CHANGES_BEFORE_PURGE) {
|
||||
purge();
|
||||
changeCount = 0;
|
||||
}
|
||||
// do a partial purge more often
|
||||
else if ((changeCount % PARTIAL_PURGE_COUNT) == 0) {
|
||||
purgeOne();
|
||||
}
|
||||
|
||||
Object result = null;
|
||||
Referenced keyRef = new Referenced(key, queue);
|
||||
return super.put(keyRef, value);
|
||||
}
|
||||
|
||||
/**
|
||||
*@see Hashtable
|
||||
*/
|
||||
public void putAll(Map t) {
|
||||
if (t != null) {
|
||||
Set entrySet = t.entrySet();
|
||||
for (Iterator it=entrySet.iterator(); it.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*@see Hashtable
|
||||
*/
|
||||
public Collection values() {
|
||||
purge();
|
||||
return super.values();
|
||||
}
|
||||
|
||||
/**
|
||||
*@see Hashtable
|
||||
*/
|
||||
public Object remove(Object key) {
|
||||
// for performance reasons, only purge every
|
||||
// MAX_CHANGES_BEFORE_PURGE times
|
||||
if (changeCount++ > MAX_CHANGES_BEFORE_PURGE) {
|
||||
purge();
|
||||
changeCount = 0;
|
||||
}
|
||||
// do a partial purge more often
|
||||
else if ((changeCount % PARTIAL_PURGE_COUNT) == 0) {
|
||||
purgeOne();
|
||||
}
|
||||
return super.remove(new Referenced(key));
|
||||
}
|
||||
|
||||
/**
|
||||
*@see Hashtable
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
purge();
|
||||
return super.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
*@see Hashtable
|
||||
*/
|
||||
public int size() {
|
||||
purge();
|
||||
return super.size();
|
||||
}
|
||||
|
||||
/**
|
||||
*@see Hashtable
|
||||
*/
|
||||
public String toString() {
|
||||
purge();
|
||||
return super.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Hashtable
|
||||
*/
|
||||
protected void rehash() {
|
||||
// purge here to save the effort of rehashing dead entries
|
||||
purge();
|
||||
super.rehash();
|
||||
}
|
||||
|
||||
/**
|
||||
* Purges all entries whose wrapped keys
|
||||
* have been garbage collected.
|
||||
*/
|
||||
private void purge() {
|
||||
synchronized (queue) {
|
||||
WeakKey key;
|
||||
while ((key = (WeakKey) queue.poll()) != null) {
|
||||
super.remove(key.getReferenced());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Purges one entry whose wrapped key
|
||||
* has been garbage collected.
|
||||
*/
|
||||
private void purgeOne() {
|
||||
|
||||
synchronized (queue) {
|
||||
WeakKey key = (WeakKey) queue.poll();
|
||||
if (key != null) {
|
||||
super.remove(key.getReferenced());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Entry implementation */
|
||||
private final static class Entry implements Map.Entry {
|
||||
|
||||
private final Object key;
|
||||
private final Object value;
|
||||
|
||||
private Entry(Object key, Object value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
boolean result = false;
|
||||
if (o != null && o instanceof Map.Entry) {
|
||||
Map.Entry entry = (Map.Entry) o;
|
||||
result = (getKey()==null ?
|
||||
entry.getKey() == null :
|
||||
getKey().equals(entry.getKey()))
|
||||
&&
|
||||
(getValue()==null ?
|
||||
entry.getValue() == null :
|
||||
getValue().equals(entry.getValue()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
|
||||
return (getKey()==null ? 0 : getKey().hashCode()) ^
|
||||
(getValue()==null ? 0 : getValue().hashCode());
|
||||
}
|
||||
|
||||
public Object setValue(Object value) {
|
||||
throw new UnsupportedOperationException("Entry.setValue is not supported.");
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Object getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Wrapper giving correct symantics for equals and hashcode */
|
||||
private final static class Referenced {
|
||||
|
||||
private final WeakReference reference;
|
||||
private final int hashCode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws NullPointerException if referant is <code>null</code>
|
||||
*/
|
||||
private Referenced(Object referant) {
|
||||
reference = new WeakReference(referant);
|
||||
// Calc a permanent hashCode so calls to Hashtable.remove()
|
||||
// work if the WeakReference has been cleared
|
||||
hashCode = referant.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws NullPointerException if key is <code>null</code>
|
||||
*/
|
||||
private Referenced(Object key, ReferenceQueue queue) {
|
||||
reference = new WeakKey(key, queue, this);
|
||||
// Calc a permanent hashCode so calls to Hashtable.remove()
|
||||
// work if the WeakReference has been cleared
|
||||
hashCode = key.hashCode();
|
||||
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
private Object getValue() {
|
||||
return reference.get();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
boolean result = false;
|
||||
if (o instanceof Referenced) {
|
||||
Referenced otherKey = (Referenced) o;
|
||||
Object thisKeyValue = getValue();
|
||||
Object otherKeyValue = otherKey.getValue();
|
||||
if (thisKeyValue == null) {
|
||||
result = (otherKeyValue == null);
|
||||
|
||||
// Since our hashcode was calculated from the original
|
||||
// non-null referant, the above check breaks the
|
||||
// hashcode/equals contract, as two cleared Referenced
|
||||
// objects could test equal but have different hashcodes.
|
||||
// We can reduce (not eliminate) the chance of this
|
||||
// happening by comparing hashcodes.
|
||||
if (result == true) {
|
||||
result = (this.hashCode() == otherKey.hashCode());
|
||||
}
|
||||
// In any case, as our c'tor does not allow null referants
|
||||
// and Hashtable does not do equality checks between
|
||||
// existing keys, normal hashtable operations should never
|
||||
// result in an equals comparison between null referants
|
||||
}
|
||||
else
|
||||
{
|
||||
result = thisKeyValue.equals(otherKeyValue);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* WeakReference subclass that holds a hard reference to an
|
||||
* associated <code>value</code> and also makes accessible
|
||||
* the Referenced object holding it.
|
||||
*/
|
||||
private final static class WeakKey extends WeakReference {
|
||||
|
||||
private final Referenced referenced;
|
||||
|
||||
private WeakKey(Object key,
|
||||
ReferenceQueue queue,
|
||||
Referenced referenced) {
|
||||
super(key, queue);
|
||||
this.referenced = referenced;
|
||||
}
|
||||
|
||||
private Referenced getReferenced() {
|
||||
return referenced;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<!--
|
||||
|
||||
Copyright 2001-2005 The Apache Software Foundation.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Overview Documentation for COMMONS-LOGGING (OPTIONAL)</title>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
<p>Contains optional additions to JCL.</p>
|
||||
|
||||
<p>Contained are classes which are not considered appropriate
|
||||
to distribute as part of JCL main distribution.
|
||||
Some classes are JVM dependent.
|
||||
Others are targetted at uncommon use cases.
|
||||
Utility code is also appropriate.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.logging;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface implemented by SubDeploymentClass. The LogFactoryTest's
|
||||
* IsolatedClassLoader will delegate loading of this interface to the
|
||||
* test runner's classloader, so the test can interact with
|
||||
* SubDeploymentClass via this interface.
|
||||
*
|
||||
* @author bstansberry
|
||||
*
|
||||
* @see LogFactoryTest
|
||||
*/
|
||||
public interface IFactoryCreator {
|
||||
|
||||
WeakReference getWeakFactory();
|
||||
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.apache.commons.logging;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.commons.logging.impl.LogFactoryImpl;
|
||||
import org.apache.commons.logging.impl.WeakHashtable;
|
||||
|
||||
public class LogFactoryTest extends TestCase {
|
||||
|
||||
|
||||
/** Maximum number of iterations before our test fails */
|
||||
private static final int MAX_GC_ITERATIONS = 50;
|
||||
|
||||
private ClassLoader origLoader = null;
|
||||
private String origFactoryProperty = null;
|
||||
|
||||
public LogFactoryTest(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
public void testLogFactoryType() {
|
||||
assertTrue(LogFactory.factories instanceof WeakHashtable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that LogFactories are not removed from the map
|
||||
* if their creating ClassLoader is still alive.
|
||||
*/
|
||||
public void testHoldFactories() throws Exception
|
||||
{
|
||||
// 1) Basic test
|
||||
|
||||
// Get a weak reference to the factory using the classloader.
|
||||
// When this reference is cleared we know the factory has been
|
||||
// cleared from LogFactory.factories as well
|
||||
WeakReference weakFactory = loadFactoryFromContextClassLoader();
|
||||
// Run the gc, confirming that the factory
|
||||
// is not dropped from the map even though there are
|
||||
// no other references to it
|
||||
checkRelease(weakFactory, true);
|
||||
|
||||
// 2) Test using an isolated classloader a la a web app
|
||||
|
||||
// Create a classloader that isolates commons-logging
|
||||
ClassLoader childLoader = new IsolatedClassLoader(origLoader);
|
||||
Thread.currentThread().setContextClassLoader(childLoader);
|
||||
weakFactory = loadFactoryFromContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(origLoader);
|
||||
// At this point we still have a reference to childLoader,
|
||||
// so the factory should not be cleared
|
||||
|
||||
checkRelease(weakFactory, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a ClassLoader is eventually removed from the map
|
||||
* after all hard references to it are removed.
|
||||
*/
|
||||
public void testReleaseClassLoader() throws Exception
|
||||
{
|
||||
// 1) Test of a child classloader that follows the Java2
|
||||
// delegation model (e.g. an EJB module classloader)
|
||||
|
||||
// Create a classloader that delegates to its parent
|
||||
ClassLoader childLoader = new ClassLoader() {};
|
||||
// Get a weak reference to the factory using the classloader.
|
||||
// When this reference is cleared we know the factory has been
|
||||
// cleared from LogFactory.factories as well
|
||||
Thread.currentThread().setContextClassLoader(childLoader);
|
||||
loadFactoryFromContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(origLoader);
|
||||
|
||||
// Get a WeakReference to the child loader so we know when it
|
||||
// has been gc'ed
|
||||
WeakReference weakLoader = new WeakReference(childLoader);
|
||||
// Remove any hard reference to the childLoader or the factory creator
|
||||
childLoader = null;
|
||||
|
||||
// Run the gc, confirming that childLoader is dropped from the map
|
||||
checkRelease(weakLoader, false);
|
||||
|
||||
// 2) Test using an isolated classloader a la a web app
|
||||
|
||||
childLoader = new IsolatedClassLoader(origLoader);
|
||||
Thread.currentThread().setContextClassLoader(childLoader);
|
||||
loadFactoryFromContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(origLoader);
|
||||
weakLoader = new WeakReference(childLoader);
|
||||
childLoader = null; // somewhat equivalent to undeploying a webapp
|
||||
|
||||
checkRelease(weakLoader, false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeatedly run the gc, checking whether the given WeakReference
|
||||
* is not cleared and failing or succeeding based on
|
||||
* parameter <code>failOnRelease</code>.
|
||||
*/
|
||||
private void checkRelease(WeakReference reference, boolean failOnRelease) {
|
||||
|
||||
int iterations = 0;
|
||||
int bytz = 2;
|
||||
while(true) {
|
||||
System.gc();
|
||||
if(iterations++ > MAX_GC_ITERATIONS){
|
||||
if (failOnRelease) {
|
||||
break;
|
||||
}
|
||||
fail("Max iterations reached before reference released.");
|
||||
}
|
||||
|
||||
if(reference.get() == null) {
|
||||
if (failOnRelease) {
|
||||
fail("reference released");
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// create garbage:
|
||||
byte[] b;
|
||||
try {
|
||||
b = new byte[bytz];
|
||||
bytz = bytz * 2;
|
||||
}
|
||||
catch (OutOfMemoryError oom) {
|
||||
// Doing this is probably a no-no, but it seems to work ;-)
|
||||
b = null;
|
||||
System.gc();
|
||||
if (failOnRelease) {
|
||||
break;
|
||||
}
|
||||
fail("OutOfMemory before reference released.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
// Preserve the original classloader and factory implementation
|
||||
// class so we can restore them when we are done
|
||||
origLoader = Thread.currentThread().getContextClassLoader();
|
||||
origFactoryProperty = System.getProperty(LogFactory.FACTORY_PROPERTY);
|
||||
|
||||
// Ensure we use LogFactoryImpl as our factory
|
||||
System.setProperty(LogFactory.FACTORY_PROPERTY,
|
||||
LogFactoryImpl.class.getName());
|
||||
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
// Set the classloader back to whatever it originally was
|
||||
Thread.currentThread().setContextClassLoader(origLoader);
|
||||
|
||||
// Set the factory implementation class back to
|
||||
// whatever it originally was
|
||||
if (origFactoryProperty != null) {
|
||||
System.setProperty(LogFactory.FACTORY_PROPERTY,
|
||||
origFactoryProperty);
|
||||
}
|
||||
else {
|
||||
System.getProperties().remove(LogFactory.FACTORY_PROPERTY);
|
||||
}
|
||||
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private static WeakReference loadFactoryFromContextClassLoader()
|
||||
throws Exception {
|
||||
ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
Class clazz = loader.loadClass(SubDeploymentClass.class.getName());
|
||||
IFactoryCreator creator = (IFactoryCreator) clazz.newInstance();
|
||||
return creator.getWeakFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* A ClassLoader that mimics the operation of a web app classloader
|
||||
* by not delegating some calls to its parent.
|
||||
*
|
||||
* In this case it does not delegate loading commons-logging classes,
|
||||
* acting as if commons-logging were in WEB-INF/lib. However, it does
|
||||
* delegate loading of IFactoryCreator, thus allowing this class to
|
||||
* interact with SubDeploymentClass via IFactoryCreator.
|
||||
*/
|
||||
private static final class IsolatedClassLoader extends ClassLoader {
|
||||
|
||||
private IsolatedClassLoader(ClassLoader parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
protected synchronized Class loadClass(String name, boolean resolve)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
if (name != null && name.startsWith("org.apache.commons.logging")
|
||||
&& "org.apache.commons.logging.IFactoryCreator".equals(name) == false) {
|
||||
// First, check if the class has already been loaded
|
||||
Class c = findClass(name);
|
||||
|
||||
if (resolve) {
|
||||
resolveClass(c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
else {
|
||||
return super.loadClass(name, resolve);
|
||||
}
|
||||
}
|
||||
|
||||
protected Class findClass(String name) throws ClassNotFoundException {
|
||||
if (name != null && name.startsWith("org.apache.commons.logging")
|
||||
&& "org.apache.commons.logging.IFactoryCreator".equals(name) == false) {
|
||||
try {
|
||||
InputStream is = getResourceAsStream( name.replace('.','/').concat(".class"));
|
||||
byte[] bytes = new byte[1024];
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
|
||||
int read;
|
||||
while ((read = is.read(bytes)) > -1) {
|
||||
baos.write(bytes, 0, read);
|
||||
}
|
||||
bytes = baos.toByteArray();
|
||||
return this.defineClass(name, bytes, 0, bytes.length);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new ClassNotFoundException("cannot find " + name, e);
|
||||
} catch (IOException e) {
|
||||
throw new ClassNotFoundException("cannot read " + name, e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return super.findClass(name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.logging;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Class that mocks a user class deployed in a sub-deployment that
|
||||
* interacts with LogFactory.
|
||||
*
|
||||
* @author bstansberry
|
||||
*
|
||||
* @see LogFactoryTest
|
||||
*/
|
||||
public class SubDeploymentClass implements IFactoryCreator {
|
||||
|
||||
private WeakReference weakFactory = null;
|
||||
|
||||
public SubDeploymentClass() {
|
||||
LogFactory factory = LogFactory.getFactory();
|
||||
weakFactory = new WeakReference(factory);
|
||||
}
|
||||
|
||||
public WeakReference getWeakFactory() {
|
||||
return weakFactory;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.apache.commons.logging;
|
||||
|
||||
import junit.framework.*;
|
||||
import org.apache.commons.logging.impl.MemoryLogTest;
|
||||
import org.apache.commons.logging.impl.WeakHashtableTest;
|
||||
|
||||
/**
|
||||
* <p> The build script calls just one <code>TestSuite</code> - this one!
|
||||
* All tests should be written into separate <code>TestSuite</code>'s
|
||||
* and added to this. Don't clutter this class with implementations. </p>
|
||||
*
|
||||
* @version $Revision$
|
||||
*/
|
||||
public class TestAll extends TestCase {
|
||||
|
||||
public TestAll(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite();
|
||||
|
||||
suite.addTest(MemoryLogTest.suite());
|
||||
suite.addTestSuite(WeakHashtableTest.class);
|
||||
suite.addTestSuite(LogFactoryTest.class);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
/**
|
||||
* This allows the tests to run as a standalone application.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
String[] testCaseName = { TestAll.class.getName() };
|
||||
junit.textui.TestRunner.main(testCaseName);
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.logging.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.impl.MemoryLog;
|
||||
|
||||
import junit.framework.*;
|
||||
|
||||
/**
|
||||
* Test the MemoryLog.
|
||||
* @author Jörg Schaible
|
||||
*/
|
||||
public class MemoryLogTest
|
||||
extends TestCase {
|
||||
|
||||
public MemoryLogTest(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
MemoryLog.reset();
|
||||
}
|
||||
|
||||
public Log getLogObject()
|
||||
{
|
||||
return (Log) new MemoryLog(this.getClass().getName());
|
||||
}
|
||||
|
||||
public final void testGetLogEntries()
|
||||
{
|
||||
MemoryLog log = (MemoryLog)getLogObject();
|
||||
log.setLevel(MemoryLog.LOG_LEVEL_DEBUG);
|
||||
log.trace("trace");
|
||||
log.debug("debug");
|
||||
log.info("info");
|
||||
log.warn("warn");
|
||||
log.error("error", new RuntimeException("error"));
|
||||
log.fatal("fatal", new RuntimeException("fatal"));
|
||||
List list = MemoryLog.getLogEntries();
|
||||
assertEquals(5, list.size());
|
||||
assertEquals("debug",((MemoryLog.Entry)list.get(0)).getMessage());
|
||||
assertEquals("info",((MemoryLog.Entry)list.get(1)).getMessage());
|
||||
assertEquals("warn",((MemoryLog.Entry)list.get(2)).getMessage());
|
||||
assertEquals("error",((MemoryLog.Entry)list.get(3)).getMessage());
|
||||
assertEquals("error",((MemoryLog.Entry)list.get(3)).getThrowable().getMessage());
|
||||
assertEquals("fatal",((MemoryLog.Entry)list.get(4)).getMessage());
|
||||
assertEquals("fatal",((MemoryLog.Entry)list.get(4)).getThrowable().getMessage());
|
||||
MemoryLog.reset();
|
||||
assertEquals(0, MemoryLog.getLogEntries().size());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(MemoryLogTest.suite());
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite();
|
||||
|
||||
suite.addTestSuite(MemoryLogTest.class);
|
||||
|
||||
return suite;
|
||||
}
|
||||
}
|
||||
@@ -1,249 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.apache.commons.logging.impl;
|
||||
|
||||
import java.lang.ref.*;
|
||||
import junit.framework.*;
|
||||
import java.util.*;
|
||||
|
||||
public class WeakHashtableTest extends TestCase {
|
||||
|
||||
|
||||
/** Maximum number of iterations before our test fails */
|
||||
private static final int MAX_GC_ITERATIONS = 50;
|
||||
|
||||
private WeakHashtable weakHashtable;
|
||||
private Long keyOne;
|
||||
private Long keyTwo;
|
||||
private Long keyThree;
|
||||
private Long valueOne;
|
||||
private Long valueTwo;
|
||||
private Long valueThree;
|
||||
|
||||
public WeakHashtableTest(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
weakHashtable = new WeakHashtable();
|
||||
|
||||
keyOne = new Long(1);
|
||||
keyTwo = new Long(2);
|
||||
keyThree = new Long(3);
|
||||
valueOne = new Long(100);
|
||||
valueTwo = new Long(200);
|
||||
valueThree = new Long(300);
|
||||
|
||||
weakHashtable.put(keyOne, valueOne);
|
||||
weakHashtable.put(keyTwo, valueTwo);
|
||||
weakHashtable.put(keyThree, valueThree);
|
||||
}
|
||||
|
||||
/** Tests public boolean contains(ObjectÊvalue) */
|
||||
public void testContains() throws Exception {
|
||||
assertFalse(weakHashtable.contains(new Long(1)));
|
||||
assertFalse(weakHashtable.contains(new Long(2)));
|
||||
assertFalse(weakHashtable.contains(new Long(3)));
|
||||
assertTrue(weakHashtable.contains(new Long(100)));
|
||||
assertTrue(weakHashtable.contains(new Long(200)));
|
||||
assertTrue(weakHashtable.contains(new Long(300)));
|
||||
assertFalse(weakHashtable.contains(new Long(400)));
|
||||
}
|
||||
|
||||
/** Tests public boolean containsKey(ObjectÊkey) */
|
||||
public void testContainsKey() throws Exception {
|
||||
assertTrue(weakHashtable.containsKey(new Long(1)));
|
||||
assertTrue(weakHashtable.containsKey(new Long(2)));
|
||||
assertTrue(weakHashtable.containsKey(new Long(3)));
|
||||
assertFalse(weakHashtable.containsKey(new Long(100)));
|
||||
assertFalse(weakHashtable.containsKey(new Long(200)));
|
||||
assertFalse(weakHashtable.containsKey(new Long(300)));
|
||||
assertFalse(weakHashtable.containsKey(new Long(400)));
|
||||
}
|
||||
|
||||
/** Tests public boolean containsValue(ObjectÊvalue) */
|
||||
public void testContainsValue() throws Exception {
|
||||
assertFalse(weakHashtable.containsValue(new Long(1)));
|
||||
assertFalse(weakHashtable.containsValue(new Long(2)));
|
||||
assertFalse(weakHashtable.containsValue(new Long(3)));
|
||||
assertTrue(weakHashtable.containsValue(new Long(100)));
|
||||
assertTrue(weakHashtable.containsValue(new Long(200)));
|
||||
assertTrue(weakHashtable.containsValue(new Long(300)));
|
||||
assertFalse(weakHashtable.containsValue(new Long(400)));
|
||||
}
|
||||
|
||||
/** Tests public Enumeration elements() */
|
||||
public void testElements() throws Exception {
|
||||
ArrayList elements = new ArrayList();
|
||||
for (Enumeration e = weakHashtable.elements(); e.hasMoreElements();) {
|
||||
elements.add(e.nextElement());
|
||||
}
|
||||
assertEquals(3, elements.size());
|
||||
assertTrue(elements.contains(valueOne));
|
||||
assertTrue(elements.contains(valueTwo));
|
||||
assertTrue(elements.contains(valueThree));
|
||||
}
|
||||
|
||||
/** Tests public Set entrySet() */
|
||||
public void testEntrySet() throws Exception {
|
||||
Set entrySet = weakHashtable.entrySet();
|
||||
for (Iterator it = entrySet.iterator(); it.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
Object key = entry.getKey();
|
||||
if (keyOne.equals(key)) {
|
||||
assertEquals(valueOne, entry.getValue());
|
||||
} else if (keyTwo.equals(key)) {
|
||||
assertEquals(valueTwo, entry.getValue());
|
||||
} else if (keyThree.equals(key)) {
|
||||
assertEquals(valueThree, entry.getValue());
|
||||
} else {
|
||||
fail("Unexpected key");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Tests public Object get(ObjectÊkey) */
|
||||
public void testGet() throws Exception {
|
||||
assertEquals(valueOne, weakHashtable.get(keyOne));
|
||||
assertEquals(valueTwo, weakHashtable.get(keyTwo));
|
||||
assertEquals(valueThree, weakHashtable.get(keyThree));
|
||||
assertNull(weakHashtable.get(new Long(50)));
|
||||
}
|
||||
|
||||
/** Tests public Enumeration keys() */
|
||||
public void testKeys() throws Exception {
|
||||
ArrayList keys = new ArrayList();
|
||||
for (Enumeration e = weakHashtable.keys(); e.hasMoreElements();) {
|
||||
keys.add(e.nextElement());
|
||||
}
|
||||
assertEquals(3, keys.size());
|
||||
assertTrue(keys.contains(keyOne));
|
||||
assertTrue(keys.contains(keyTwo));
|
||||
assertTrue(keys.contains(keyThree));
|
||||
}
|
||||
|
||||
/** Tests public Set keySet() */
|
||||
public void testKeySet() throws Exception {
|
||||
Set keySet = weakHashtable.keySet();
|
||||
assertEquals(3, keySet.size());
|
||||
assertTrue(keySet.contains(keyOne));
|
||||
assertTrue(keySet.contains(keyTwo));
|
||||
assertTrue(keySet.contains(keyThree));
|
||||
}
|
||||
|
||||
/** Tests public Object put(ObjectÊkey, ObjectÊvalue) */
|
||||
public void testPut() throws Exception {
|
||||
Long anotherKey = new Long(2004);
|
||||
weakHashtable.put(anotherKey, new Long(1066));
|
||||
|
||||
assertEquals(new Long(1066), weakHashtable.get(anotherKey));
|
||||
|
||||
// Test compliance with the hashtable API re nulls
|
||||
Exception caught = null;
|
||||
try {
|
||||
weakHashtable.put(null, new Object());
|
||||
}
|
||||
catch (Exception e) {
|
||||
caught = e;
|
||||
}
|
||||
assertNotNull("did not throw an exception adding a null key", caught);
|
||||
caught = null;
|
||||
try {
|
||||
weakHashtable.put(new Object(), null);
|
||||
}
|
||||
catch (Exception e) {
|
||||
caught = e;
|
||||
}
|
||||
assertNotNull("did not throw an exception adding a null value", caught);
|
||||
}
|
||||
|
||||
/** Tests public void putAll(MapÊt) */
|
||||
public void testPutAll() throws Exception {
|
||||
Map newValues = new HashMap();
|
||||
Long newKey = new Long(1066);
|
||||
Long newValue = new Long(1415);
|
||||
newValues.put(newKey, newValue);
|
||||
Long anotherNewKey = new Long(1645);
|
||||
Long anotherNewValue = new Long(1815);
|
||||
newValues.put(anotherNewKey, anotherNewValue);
|
||||
weakHashtable.putAll(newValues);
|
||||
|
||||
assertEquals(5, weakHashtable.size());
|
||||
assertEquals(newValue, weakHashtable.get(newKey));
|
||||
assertEquals(anotherNewValue, weakHashtable.get(anotherNewKey));
|
||||
}
|
||||
|
||||
/** Tests public Object remove(ObjectÊkey) */
|
||||
public void testRemove() throws Exception {
|
||||
weakHashtable.remove(keyOne);
|
||||
assertEquals(2, weakHashtable.size());
|
||||
assertNull(weakHashtable.get(keyOne));
|
||||
}
|
||||
|
||||
/** Tests public Collection values() */
|
||||
public void testValues() throws Exception {
|
||||
Collection values = weakHashtable.values();
|
||||
assertEquals(3, values.size());
|
||||
assertTrue(values.contains(valueOne));
|
||||
assertTrue(values.contains(valueTwo));
|
||||
assertTrue(values.contains(valueThree));
|
||||
}
|
||||
|
||||
public void testRelease() throws Exception {
|
||||
assertNotNull(weakHashtable.get(new Long(1)));
|
||||
ReferenceQueue testQueue = new ReferenceQueue();
|
||||
WeakReference weakKeyOne = new WeakReference(keyOne, testQueue);
|
||||
|
||||
// lose our references
|
||||
keyOne = null;
|
||||
keyTwo = null;
|
||||
keyThree = null;
|
||||
valueOne = null;
|
||||
valueTwo = null;
|
||||
valueThree = null;
|
||||
|
||||
int iterations = 0;
|
||||
int bytz = 2;
|
||||
while(true) {
|
||||
System.gc();
|
||||
if(iterations++ > MAX_GC_ITERATIONS){
|
||||
fail("Max iterations reached before resource released.");
|
||||
}
|
||||
|
||||
if(weakHashtable.get(new Long(1)) == null) {
|
||||
break;
|
||||
|
||||
} else {
|
||||
// create garbage:
|
||||
byte[] b = new byte[bytz];
|
||||
bytz = bytz * 2;
|
||||
}
|
||||
}
|
||||
|
||||
// some JVMs seem to take a little time to put references on
|
||||
// the reference queue once the reference has been collected
|
||||
// need to think about whether this is enough to justify
|
||||
// stepping through the collection each time...
|
||||
while(testQueue.poll() == null) {}
|
||||
|
||||
// Test that the released objects are not taking space in the table
|
||||
assertEquals("underlying table not emptied", 0, weakHashtable.size());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user