1
0

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:
Robert Burrell Donkin
2005-12-11 20:29:58 +00:00
parent ae7e0b3157
commit d215df346d
15 changed files with 0 additions and 2394 deletions

View File

@@ -108,7 +108,6 @@
<property name="core.jar.name" value="commons-${component.name}-${component.version}.jar"/> <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="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="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 ========================================= --> <!-- ========== Compiler Defaults ========================================= -->
@@ -572,20 +571,6 @@ limitations under the License.--&gt;'>
</fileset> </fileset>
</copy> </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 - And copy the source too; we don't have separate source and binary distributions
- for logging; the source is so small there's little point. - for logging; the source is so small there's little point.

View File

@@ -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

View File

@@ -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="&lt;h1&gt;${component.title} (Version ${component.version})&lt;/h1&gt;"
windowtitle="${component.title} (Version ${component.version})"
bottom='Copyright 2002-2004 The Apache Software Foundation.&lt;!--
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.--&gt;'>
<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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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&ouml;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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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>

View File

@@ -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();
}

View File

@@ -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);
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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&ouml;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;
}
}

View File

@@ -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());
}
}