Moved demonstration away from the main source directory to a holding area. The aim is to clean up the source distribution.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/logging/trunk@355971 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -1,30 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
Contained are JCL Proof Of Concept Demonstrations
|
|
||||||
|
|
||||||
The following jars must be added to this directory:
|
|
||||||
|
|
||||||
Log4j.jar
|
|
||||||
commons-logging.jar
|
|
||||||
commons-logging-api.jar
|
|
||||||
|
|
||||||
Create build directories by typing 'ant clean'
|
|
||||||
Build by typing ant.
|
|
||||||
|
|
||||||
Read the overview in the javadocs created under target/docs.
|
|
||||||
|
|
||||||
When the time comes, run the demonstrations by typing 'ant run'
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
<?xml version='1.0'?>
|
|
||||||
<!-- $Id: overview.html 132718 2004-09-09 20:38:21Z rdonkin $
|
|
||||||
|
|
||||||
Copyright 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.
|
|
||||||
-->
|
|
||||||
<project name='classloader-examplars' default='build'>
|
|
||||||
|
|
||||||
<property name='build.home' value='target'/>
|
|
||||||
<property name='bin.tests' value='${build.home}/test-classes'/>
|
|
||||||
<property name='bin.caller' value='${build.home}/caller-classes'/>
|
|
||||||
<property name='bin.static' value='${build.home}/static-classes'/>
|
|
||||||
<property name='bin.docs' value='${build.home}/docs'/>
|
|
||||||
<property name='source' value='src/java'/>
|
|
||||||
|
|
||||||
<path id="static.classpath">
|
|
||||||
<pathelement location="commons-logging.jar"/>
|
|
||||||
<pathelement location="log4j.jar"/>
|
|
||||||
</path>
|
|
||||||
|
|
||||||
<path id="caller.classpath">
|
|
||||||
<pathelement location="commons-logging.jar"/>
|
|
||||||
<pathelement location="log4j.jar"/>
|
|
||||||
<pathelement location="static.jar"/>
|
|
||||||
</path>
|
|
||||||
|
|
||||||
<path id="tests.classpath">
|
|
||||||
<pathelement location="commons-logging.jar"/>
|
|
||||||
<pathelement location="log4j.jar"/>
|
|
||||||
<pathelement location="static.jar"/>
|
|
||||||
<pathelement location="caller.jar"/>
|
|
||||||
</path>
|
|
||||||
|
|
||||||
<path id="run.classpath">
|
|
||||||
<pathelement location="tests.jar"/>
|
|
||||||
</path>
|
|
||||||
|
|
||||||
|
|
||||||
<target name='init'>
|
|
||||||
<delete dir='${build.home}'/>
|
|
||||||
<mkdir dir='${build.home}'/>
|
|
||||||
<mkdir dir='${bin.tests}'/>
|
|
||||||
<mkdir dir='${bin.caller}'/>
|
|
||||||
<mkdir dir='${bin.static}'/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name='clean'>
|
|
||||||
<delete dir='${build.home}'/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name='build-static'>
|
|
||||||
<javac srcdir="${source}"
|
|
||||||
destdir="${bin.static}"
|
|
||||||
debug="true">
|
|
||||||
<classpath refid="static.classpath"/>
|
|
||||||
<include name='org/apache/commons/logging/proofofconcept/staticlogger/*.java'/>
|
|
||||||
</javac>
|
|
||||||
<jar jarfile="static.jar"
|
|
||||||
basedir="${bin.static}">
|
|
||||||
</jar>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name='build-caller'>
|
|
||||||
<javac srcdir="${source}"
|
|
||||||
destdir="${bin.caller}"
|
|
||||||
debug="true">
|
|
||||||
<classpath refid="caller.classpath"/>
|
|
||||||
<include name='org/apache/commons/logging/proofofconcept/caller/*.java'/>
|
|
||||||
</javac>
|
|
||||||
<jar jarfile="caller.jar"
|
|
||||||
basedir="${bin.caller}">
|
|
||||||
</jar>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
|
|
||||||
<target name='build-tests'>
|
|
||||||
<javac srcdir="${source}"
|
|
||||||
destdir="${bin.tests}"
|
|
||||||
debug="true">
|
|
||||||
<classpath refid="tests.classpath"/>
|
|
||||||
<include name='org/apache/commons/logging/proofofconcept/runner/*.java'/>
|
|
||||||
</javac>
|
|
||||||
<jar jarfile="tests.jar"
|
|
||||||
basedir="${bin.tests}">
|
|
||||||
</jar>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="javadoc">
|
|
||||||
<delete dir='${bin.docs}'/>
|
|
||||||
<mkdir dir="${bin.docs}"/>
|
|
||||||
<javadoc sourcepath="${source}"
|
|
||||||
destdir="${bin.docs}"
|
|
||||||
packagenames="org.apache.commons.logging.proofofconcept.*"
|
|
||||||
author="true"
|
|
||||||
private="true"
|
|
||||||
version="true"
|
|
||||||
overview="${source}/overview.html"
|
|
||||||
doctitle="JCL Proof Of Concept Demonstrations"
|
|
||||||
windowtitle="JCL Proof Of Concept Demonstrations"
|
|
||||||
bottom='Copyright 2005 The Apache Software Foundation or its licensors, as applicable.'>
|
|
||||||
<classpath refid="static.classpath"/>
|
|
||||||
</javadoc>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name='build' depends='init, build-static, build-caller, build-tests, javadoc'>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name='run'>
|
|
||||||
<java classname="org.apache.commons.logging.proofofconcept.runner.ParentFirstRunner" fork="yes" failonerror="true">
|
|
||||||
<classpath refid="run.classpath"/>
|
|
||||||
</java>
|
|
||||||
<java classname="org.apache.commons.logging.proofofconcept.runner.ChildFirstRunner" fork="yes" failonerror="true">
|
|
||||||
<classpath refid="run.classpath"/>
|
|
||||||
</java>
|
|
||||||
</target>
|
|
||||||
</project>
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 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.
|
|
||||||
*/
|
|
||||||
package org.apache.commons.logging.proofofconcept.caller;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the behaviour of calls to logging
|
|
||||||
* and formats the results.
|
|
||||||
* The actual logging calls are execute by {@link SomeObject}.
|
|
||||||
*/
|
|
||||||
public class JCLDemonstrator{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs {@link #runJCL()} and {@link #runStatic()}
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void run() {
|
|
||||||
runJCL();
|
|
||||||
runStatic();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a test that logs to JCL
|
|
||||||
* and outputs the results to <code>System.out</code>.
|
|
||||||
*/
|
|
||||||
public void runJCL() {
|
|
||||||
try {
|
|
||||||
SomeObject someObject = new SomeObject();
|
|
||||||
System.out.println("--------------------");
|
|
||||||
System.out.println("Logging to JCL:");
|
|
||||||
someObject.logToJCL();
|
|
||||||
System.out.println("JCL Logging OK");
|
|
||||||
} catch (Throwable t) {
|
|
||||||
System.out.println("JCL Logging FAILED: " + t.getClass());
|
|
||||||
System.out.println(t.getMessage());
|
|
||||||
System.out.println("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a test that logs to Log4J via static calls
|
|
||||||
* and outputs the results to <code>System.out</code>.
|
|
||||||
*/
|
|
||||||
public void runStatic() {
|
|
||||||
try {
|
|
||||||
SomeObject someObject = new SomeObject();
|
|
||||||
System.out.println("--------------------");
|
|
||||||
System.out.println("Logging to Static:");
|
|
||||||
someObject.logToStaticLog4J();
|
|
||||||
System.out.println("Static Logging: OK");
|
|
||||||
} catch (Throwable t) {
|
|
||||||
System.out.println("Static Logging FAILED: " + t.getClass());
|
|
||||||
System.out.println(t.getMessage());
|
|
||||||
System.out.println("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 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.
|
|
||||||
*/
|
|
||||||
package org.apache.commons.logging.proofofconcept.caller;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.apache.commons.logging.proofofconcept.staticlogger.StaticLog4JLogger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This simulates some application or library code
|
|
||||||
* that uses logging.
|
|
||||||
* This separation allows tests to be run
|
|
||||||
* where this class is defined by either the parent
|
|
||||||
* or the child classloader.
|
|
||||||
*/
|
|
||||||
public class SomeObject {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs a message to <code>Jakarta Commons Logging</code>.
|
|
||||||
*/
|
|
||||||
public void logToJCL() {
|
|
||||||
LogFactory.getLog("a log").info("A message");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs a message to <code>Log4j</code> via a class
|
|
||||||
* which makes a static call.
|
|
||||||
*/
|
|
||||||
public void logToStaticLog4J() {
|
|
||||||
StaticLog4JLogger.info("A message");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<!-- $Id: overview.html 132718 2004-09-09 20:38:21Z rdonkin $
|
|
||||||
|
|
||||||
Copyright 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.
|
|
||||||
-->
|
|
||||||
<body bgcolor="white">
|
|
||||||
<p>Invokes logging
|
|
||||||
and takes the role of calling application code in these demonstrations.
|
|
||||||
This separation allows a greater variety of defining classloaders for
|
|
||||||
the calling application code to be simulated.
|
|
||||||
</p>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 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.
|
|
||||||
*/
|
|
||||||
package org.apache.commons.logging.proofofconcept.runner;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Rather slack) implementation of a child first classloader.
|
|
||||||
* Should be fit for the purpose intended (which is demonstration)
|
|
||||||
* but a more complete and robust implementation should be
|
|
||||||
* preferred for more general purposes.
|
|
||||||
*/
|
|
||||||
public class ChildFirstClassLoader extends URLClassLoader {
|
|
||||||
|
|
||||||
public ChildFirstClassLoader(URL[] urls, ClassLoader parent) {
|
|
||||||
super(urls, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected synchronized Class loadClass(String name, boolean resolve)
|
|
||||||
throws ClassNotFoundException {
|
|
||||||
|
|
||||||
// very basic implementation
|
|
||||||
Class result = findLoadedClass(name);
|
|
||||||
if (result == null) {
|
|
||||||
try {
|
|
||||||
result = findClass(name);
|
|
||||||
if (resolve) {
|
|
||||||
resolveClass(result);
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
result = super.loadClass(name, resolve);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 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.
|
|
||||||
*/
|
|
||||||
package org.apache.commons.logging.proofofconcept.runner;
|
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs child first demonstrations.
|
|
||||||
* @see #main(String[])
|
|
||||||
*/
|
|
||||||
public class ChildFirstRunner extends ClassLoaderRunner {
|
|
||||||
|
|
||||||
|
|
||||||
public ChildFirstRunner() throws MalformedURLException {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void testCase17() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("17", parentUrls, childUrls, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase18() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR + CALLER_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("18", parentUrls, childUrls, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase19() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("19", parentUrls, childUrls, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase20() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR + CALLER_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("20", parentUrls, childUrls, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase21() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("21", parentUrls, childUrls, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase22() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("22", parentUrls, childUrls, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase23() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("23", parentUrls, childUrls, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase24() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("24", parentUrls, childUrls, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void testCase25() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("25", parentUrls, childUrls, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase26() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR + CALLER_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("26", parentUrls, childUrls, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase27() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("27", parentUrls, childUrls, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase28() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR + CALLER_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("28", parentUrls, childUrls, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase29() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("29", parentUrls, childUrls, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase30() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("30", parentUrls, childUrls, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase31() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("31", parentUrls, childUrls, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase32() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("32", parentUrls, childUrls, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs all child first cases.
|
|
||||||
* @param args
|
|
||||||
*/
|
|
||||||
public static void main(String[] args)
|
|
||||||
{
|
|
||||||
ChildFirstRunner runner;
|
|
||||||
try {
|
|
||||||
runner = new ChildFirstRunner();
|
|
||||||
System.out.println("");
|
|
||||||
System.out.println("");
|
|
||||||
System.out.println("Running Child First Cases...");
|
|
||||||
System.out.println("");
|
|
||||||
System.out.println("");
|
|
||||||
runner.testCase17();
|
|
||||||
runner.testCase18();
|
|
||||||
runner.testCase19();
|
|
||||||
runner.testCase20();
|
|
||||||
runner.testCase21();
|
|
||||||
runner.testCase22();
|
|
||||||
runner.testCase23();
|
|
||||||
runner.testCase24();
|
|
||||||
runner.testCase25();
|
|
||||||
runner.testCase26();
|
|
||||||
runner.testCase27();
|
|
||||||
runner.testCase28();
|
|
||||||
runner.testCase29();
|
|
||||||
runner.testCase30();
|
|
||||||
runner.testCase31();
|
|
||||||
runner.testCase32();
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
System.out.println("Cannot find required jars");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 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.
|
|
||||||
*/
|
|
||||||
package org.apache.commons.logging.proofofconcept.runner;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs demonstrations with complex classloader hierarchies
|
|
||||||
* and outputs formatted descriptions of the tests run.
|
|
||||||
*/
|
|
||||||
public class ClassLoaderRunner {
|
|
||||||
|
|
||||||
private static final Class[] EMPTY_CLASSES = {};
|
|
||||||
private static final Object[] EMPTY_OBJECTS = {};
|
|
||||||
private static final URL[] EMPTY_URLS = {};
|
|
||||||
|
|
||||||
public static final int LOG4J_JAR = 1 << 0;
|
|
||||||
public static final int STATIC_JAR = 1 << 1;
|
|
||||||
public static final int JCL_JAR = 1 << 2;
|
|
||||||
public static final int CALLER_JAR = 1 << 3;
|
|
||||||
public static final int API_JAR = 1 << 4;
|
|
||||||
|
|
||||||
private final URL log4jUrl;
|
|
||||||
private final URL staticUrl;
|
|
||||||
private final URL jclUrl;
|
|
||||||
private final URL callerUrl;
|
|
||||||
private final URL apiUrl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads URLs.
|
|
||||||
* @throws MalformedURLException when any of these URLs cannot
|
|
||||||
* be resolved
|
|
||||||
*/
|
|
||||||
public ClassLoaderRunner() throws MalformedURLException {
|
|
||||||
log4jUrl = new URL("file:log4j.jar");
|
|
||||||
staticUrl = new URL("file:static.jar");
|
|
||||||
jclUrl = new URL("file:commons-logging.jar");
|
|
||||||
callerUrl = new URL("file:caller.jar");
|
|
||||||
apiUrl = new URL("file:commons-logging-api.jar");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a demonstration.
|
|
||||||
* @param caseName human name for test (used for output)
|
|
||||||
* @param parentJars bitwise code for jars to be definable
|
|
||||||
* by the parent classloader
|
|
||||||
* @param childJars bitwise code for jars to be definable
|
|
||||||
* by the child classloader
|
|
||||||
* @param setContextClassloader true if the context classloader
|
|
||||||
* should be set to the child classloader,
|
|
||||||
* false preserves the default
|
|
||||||
* @param childFirst true if the child classloader
|
|
||||||
* should delegate only if it cannot define a class,
|
|
||||||
* false otherwise
|
|
||||||
*/
|
|
||||||
public void run(String caseName, int parentJars, int childJars,
|
|
||||||
boolean setContextClassloader, boolean childFirst) {
|
|
||||||
|
|
||||||
System.out.println("");
|
|
||||||
System.out.println("*****************************");
|
|
||||||
System.out.println("");
|
|
||||||
System.out.println("Running case " + caseName + "...");
|
|
||||||
System.out.println("");
|
|
||||||
URL[] parentUrls = urlsForJars(parentJars, "Parent Classloader: ");
|
|
||||||
URL[] childUrls = urlsForJars(childJars, "Child Classloader: ");
|
|
||||||
System.out.println("Child context classloader: " + setContextClassloader);
|
|
||||||
System.out.println("Child first: " + childFirst);
|
|
||||||
System.out.println("");
|
|
||||||
run("org.apache.commons.logging.proofofconcept.caller.JCLDemonstrator",
|
|
||||||
parentUrls, childUrls, setContextClassloader, childFirst);
|
|
||||||
System.out.println("*****************************");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a bitwise jar code into an array of URLs
|
|
||||||
* containing approapriate URLs.
|
|
||||||
* @param jars bitwise jar code
|
|
||||||
* @param humanLoaderName human name for classloader
|
|
||||||
* @return <code>URL</code> array, not null possibly empty
|
|
||||||
*/
|
|
||||||
private URL[] urlsForJars(int jars, String humanLoaderName) {
|
|
||||||
List urls = new ArrayList();;
|
|
||||||
if ((LOG4J_JAR & jars) > 0) {
|
|
||||||
urls.add(log4jUrl);
|
|
||||||
}
|
|
||||||
if ((STATIC_JAR & jars) > 0) {
|
|
||||||
urls.add(staticUrl);
|
|
||||||
}
|
|
||||||
if ((JCL_JAR & jars) > 0) {
|
|
||||||
urls.add(jclUrl);
|
|
||||||
}
|
|
||||||
if ((API_JAR & jars) > 0) {
|
|
||||||
urls.add(apiUrl);
|
|
||||||
}
|
|
||||||
if ((CALLER_JAR & jars) > 0) {
|
|
||||||
urls.add(callerUrl);
|
|
||||||
}
|
|
||||||
System.out.println(humanLoaderName + " " + urls);
|
|
||||||
URL[] results = (URL[]) urls.toArray(EMPTY_URLS);
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a demonstration.
|
|
||||||
* @param testName the human name for this test
|
|
||||||
* @param parentClassloaderUrls the <code>URL</code>'s which should
|
|
||||||
* be definable by the parent classloader, not null
|
|
||||||
* @param childClassloaderUrls the <code>URL</code>'s which should
|
|
||||||
* be definable by the child classloader, not null
|
|
||||||
* @param setContextClassloader true if the context
|
|
||||||
* classloader should be set to the child classloader,
|
|
||||||
* false if the default context classloader should
|
|
||||||
* be maintained
|
|
||||||
* @param childFirst true if the child classloader
|
|
||||||
* should delegate only when it cannot define the class,
|
|
||||||
* false otherwise
|
|
||||||
*/
|
|
||||||
public void run (String testName,
|
|
||||||
URL[] parentClassloaderUrls,
|
|
||||||
URL[] childClassloaderUrls,
|
|
||||||
boolean setContextClassloader,
|
|
||||||
boolean childFirst) {
|
|
||||||
|
|
||||||
URLClassLoader parent = new URLClassLoader(parentClassloaderUrls);
|
|
||||||
URLClassLoader child = null;
|
|
||||||
if (childFirst) {
|
|
||||||
child = new ChildFirstClassLoader(childClassloaderUrls, parent);
|
|
||||||
} else {
|
|
||||||
child = new URLClassLoader(childClassloaderUrls, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setContextClassloader) {
|
|
||||||
Thread.currentThread().setContextClassLoader(child);
|
|
||||||
} else {
|
|
||||||
ClassLoader system = ClassLoader.getSystemClassLoader();
|
|
||||||
Thread.currentThread().setContextClassLoader(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
logDefiningLoaders(child, parent);
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
Class callerClass = child.loadClass(testName);
|
|
||||||
Method runMethod = callerClass.getDeclaredMethod("run", EMPTY_CLASSES);
|
|
||||||
Object caller = callerClass.newInstance();
|
|
||||||
runMethod.invoke(caller, EMPTY_OBJECTS);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("Cannot execute test: " + e.getMessage());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs the classloaders which define important classes
|
|
||||||
* @param child child <code>ClassLoader</code>, not null
|
|
||||||
* @param parent parent <code>ClassLoader</code>, not null
|
|
||||||
*/
|
|
||||||
private void logDefiningLoaders(ClassLoader child, ClassLoader parent)
|
|
||||||
{
|
|
||||||
System.out.println("");
|
|
||||||
logDefiningLoaders(child, parent, "org.apache.commons.logging.LogFactory", "JCL ");
|
|
||||||
logDefiningLoaders(child, parent, "org.apache.log4j.Logger", "Log4j ");
|
|
||||||
logDefiningLoaders(child, parent, "org.apache.commons.logging.proofofconcept.staticlogger.StaticLog4JLogger", "Static Logger");
|
|
||||||
logDefiningLoaders(child, parent, "org.apache.commons.logging.proofofconcept.caller.SomeObject", "Caller ");
|
|
||||||
System.out.println("");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs the classloader which defines the class with the given name whose
|
|
||||||
* loading is initiated by the child classloader.
|
|
||||||
* @param child child <code>ClassLoader</code>, not null
|
|
||||||
* @param parent parent <code>ClassLoader</code>, not null
|
|
||||||
* @param className name of the class to be loaded
|
|
||||||
* @param humanName the human name for the class
|
|
||||||
*/
|
|
||||||
private void logDefiningLoaders(ClassLoader child, ClassLoader parent, String className, String humanName) {
|
|
||||||
try {
|
|
||||||
Class clazz = child.loadClass(className);
|
|
||||||
ClassLoader definingLoader = clazz.getClassLoader();
|
|
||||||
if (definingLoader == null)
|
|
||||||
{
|
|
||||||
System.out.println(humanName + " defined by SYSTEM class loader");
|
|
||||||
}
|
|
||||||
else if (definingLoader.equals(child))
|
|
||||||
{
|
|
||||||
System.out.println(humanName + " defined by CHILD class loader");
|
|
||||||
}
|
|
||||||
else if (definingLoader.equals(parent))
|
|
||||||
{
|
|
||||||
System.out.println(humanName + " defined by PARENT class loader");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
System.out.println(humanName + " defined by OTHER class loader");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println(humanName + " NOT LOADABLE by application classloader");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 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.
|
|
||||||
*/
|
|
||||||
package org.apache.commons.logging.proofofconcept.runner;
|
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs parent first demonstrations.
|
|
||||||
* @see #main(String[])
|
|
||||||
*/
|
|
||||||
public class ParentFirstRunner extends ClassLoaderRunner {
|
|
||||||
|
|
||||||
|
|
||||||
public ParentFirstRunner() throws MalformedURLException {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase1() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("1", parentUrls, childUrls, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase2() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR + CALLER_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("2", parentUrls, childUrls, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase3() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("3", parentUrls, childUrls, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase4() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR + CALLER_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("4", parentUrls, childUrls, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase5() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("5", parentUrls, childUrls, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase6() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("6", parentUrls, childUrls, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase7() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("7", parentUrls, childUrls, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase8() {
|
|
||||||
int parentUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("8", parentUrls, childUrls, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void testCase9() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("9", parentUrls, childUrls, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase10() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR + CALLER_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("10", parentUrls, childUrls, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase11() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("11", parentUrls, childUrls, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase12() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR + CALLER_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("12", parentUrls, childUrls, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase13() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("13", parentUrls, childUrls, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase14() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("14", parentUrls, childUrls, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase15() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
run("15", parentUrls, childUrls, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCase16() {
|
|
||||||
int parentUrls = API_JAR + STATIC_JAR + CALLER_JAR + LOG4J_JAR;
|
|
||||||
int childUrls = JCL_JAR + STATIC_JAR + LOG4J_JAR;
|
|
||||||
run("16", parentUrls, childUrls, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs all parent first cases.
|
|
||||||
* @param args
|
|
||||||
*/
|
|
||||||
public static void main(String[] args)
|
|
||||||
{
|
|
||||||
ParentFirstRunner runner;
|
|
||||||
try {
|
|
||||||
runner = new ParentFirstRunner();
|
|
||||||
|
|
||||||
System.out.println("");
|
|
||||||
System.out.println("");
|
|
||||||
System.out.println("Running Parent First Cases...");
|
|
||||||
System.out.println("");
|
|
||||||
System.out.println("");
|
|
||||||
runner.testCase1();
|
|
||||||
runner.testCase2();
|
|
||||||
runner.testCase3();
|
|
||||||
runner.testCase4();
|
|
||||||
runner.testCase5();
|
|
||||||
runner.testCase6();
|
|
||||||
runner.testCase7();
|
|
||||||
runner.testCase8();
|
|
||||||
runner.testCase9();
|
|
||||||
runner.testCase10();
|
|
||||||
runner.testCase11();
|
|
||||||
runner.testCase12();
|
|
||||||
runner.testCase13();
|
|
||||||
runner.testCase14();
|
|
||||||
runner.testCase15();
|
|
||||||
runner.testCase16();
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
System.out.println("Cannot find required jars");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<!-- $Id: overview.html 132718 2004-09-09 20:38:21Z rdonkin $
|
|
||||||
|
|
||||||
Copyright 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.
|
|
||||||
-->
|
|
||||||
<body bgcolor="white">
|
|
||||||
<p>Runs the demonstrations.</p>
|
|
||||||
<p>
|
|
||||||
Also contained is utility code that efficiently sets up the
|
|
||||||
various classloader hierarchies.
|
|
||||||
</p>
|
|
||||||
</body>
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 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.
|
|
||||||
*/
|
|
||||||
package org.apache.commons.logging.proofofconcept.staticlogger;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This simulates a simple, static binding to Log4J.
|
|
||||||
*/
|
|
||||||
public class StaticLog4JLogger {
|
|
||||||
|
|
||||||
public static void info(String message) {
|
|
||||||
// could have got the logger at the start
|
|
||||||
Logger.getLogger("Whatever").info(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<!-- $Id: overview.html 132718 2004-09-09 20:38:21Z rdonkin $
|
|
||||||
|
|
||||||
Copyright 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.
|
|
||||||
-->
|
|
||||||
<body bgcolor="white">
|
|
||||||
<p>Calls Log4j. Uses a symbolic reference.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
This allows practical demonstrations of the behaviour of code
|
|
||||||
that calls Log4J statically when placed in similar
|
|
||||||
classloader circumstances of JCL.
|
|
||||||
</p>
|
|
||||||
</body>
|
|
||||||
@@ -1,835 +0,0 @@
|
|||||||
<html>
|
|
||||||
<!-- $Id: overview.html 132718 2004-09-09 20:38:21Z rdonkin $
|
|
||||||
|
|
||||||
Copyright 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.
|
|
||||||
-->
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=iso-8859-1">
|
|
||||||
<title>Overview Documentation for JCL Proof Of Concept Demonstrations</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Demonstrates Jakarta Commons Logging (JCL) concepts.</h1>
|
|
||||||
<h3>Introduction</h3>
|
|
||||||
<p>This document contains analysis of various JCL use cases. It works
|
|
||||||
both as an educational document and as a specification (of sorts).
|
|
||||||
It's intended audience are (potential) JCL developers and (potential)
|
|
||||||
expert users. The code that accompanies
|
|
||||||
this document demonstrates the cases analysed in the text.
|
|
||||||
</p>
|
|
||||||
<p>Familiarity with (advanced) class loading
|
|
||||||
concepts and terminology is assumed. Please digest the
|
|
||||||
<a HREF="http://jakarta.apache.org/commons/logging/tech.html">JCL
|
|
||||||
Technology Guide</a> before starting.
|
|
||||||
</p>
|
|
||||||
<p>This approach was inspired by a
|
|
||||||
<a href='http://www.qos.ch/logging/classloader.jsp'>JCL critique</a>
|
|
||||||
written by Ceki Gülcü.
|
|
||||||
</p>
|
|
||||||
<p>These demonstrations focus on discovery in general and discovery
|
|
||||||
of Log4J in particular. Not only is Log4J the most important target
|
|
||||||
but these are some of the most difficult and contentious cases.
|
|
||||||
Lessons learnt from these cases should easily and safely extrapolate
|
|
||||||
to other cases.
|
|
||||||
</p>
|
|
||||||
<p>It is important that this document is as accurate as possible both
|
|
||||||
in facts and analysis. Readers are encouraged to contribute
|
|
||||||
corrections and improvements. Please either:
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li>submit a <A HREF="http://issues.apache.org/bugzilla">bug
|
|
||||||
report</a> for the JCL component</li>
|
|
||||||
<li>or post to the Jakarta Commons Developer <a href="http://jakarta.apache.org/site/mail.html">mailing
|
|
||||||
list</a></li>
|
|
||||||
</p>
|
|
||||||
</ul>
|
|
||||||
<h3>Overview</h3>
|
|
||||||
<p>The basic set up for these demonstrations is intentionally simple.
|
|
||||||
There are no tricks that might obscure a clear view of the concepts.
|
|
||||||
The source code used to run these demonstrations is simple and should
|
|
||||||
be easy to understand.
|
|
||||||
</p>
|
|
||||||
<p>Each demonstration is initiated by a runner. The runner loads the
|
|
||||||
other code components into appropriate ClassLoaders and then calls the caller.
|
|
||||||
</p>
|
|
||||||
<p>The caller is used to simulate a class that needs to log
|
|
||||||
something. It is isolated from the code that runs the demonstration
|
|
||||||
in order to allow a greater variety of ClassLoader situations to be simulated.
|
|
||||||
The calling code is split
|
|
||||||
into one class that presents the formatted results and another that
|
|
||||||
actually performs the calls. Calls are made to JCL and to a static
|
|
||||||
logger.
|
|
||||||
</p>
|
|
||||||
<p>The static logger simply contains a call directly to Log4J. This
|
|
||||||
is useful for comparison.
|
|
||||||
</p>
|
|
||||||
<p>Now would be a good idea to study the javadocs.
|
|
||||||
</p>
|
|
||||||
<p>Results are printed (with a little formatting) to System.out. The
|
|
||||||
run target in the ant build scripts runs all cases. It may be
|
|
||||||
difficult to run these demonstrations from an IDE (a clean system
|
|
||||||
ClassLoader is required).
|
|
||||||
</p>
|
|
||||||
<h4>Conventional And Unconventional Context ClassLoaders</h4>
|
|
||||||
<p>This analysis will start by making a division between conventional
|
|
||||||
context classloaders and unconventional ones. Conventionally, the
|
|
||||||
context classloader for a thread executing code in a particular class
|
|
||||||
should either be the classloader used to load the class, an ancestor
|
|
||||||
of that classloader or a descendent of it. The conventional context
|
|
||||||
classloader cases will focus on context classloaders which obey these
|
|
||||||
rules.
|
|
||||||
</p>
|
|
||||||
<h3>Conventional Classloader Cases</h3>
|
|
||||||
<p>The aim of the set up will be isolate the essentials. Only three
|
|
||||||
classloaders will be considered:
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li>the system classloader,</li>
|
|
||||||
<li>a parent classloader (whose parent
|
|
||||||
is the system classloader) </li>
|
|
||||||
<li>and a child classloader of the parent.</li>
|
|
||||||
</ul>
|
|
||||||
<p>This situation is commonly encountered in containers (where the
|
|
||||||
child classloader is the application classloader). In practical
|
|
||||||
situations, the hierarchy is likely to be contain more classloaders
|
|
||||||
but it should be possible either to extrapolate from these simple
|
|
||||||
cases or reduce the more complex ones to these.
|
|
||||||
</p>
|
|
||||||
<p>The analysis will proceed by considering two cases separately:
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li>parent-first classloading </li>
|
|
||||||
<li>and child-first classloading.</li>
|
|
||||||
</ul>
|
|
||||||
<p>In the parent first cases, when the child classloader initiates
|
|
||||||
loading, it starts by delegating to the parent classloader. Only if
|
|
||||||
this classloader does not define the class will the child classloader
|
|
||||||
attempt to define the class. In the child first cases, the child
|
|
||||||
classloader will begin by attempting to define the class itself. Only
|
|
||||||
when it cannot define a class will it delegate to it's parents.
|
|
||||||
Further discussion of each of these cases will be contained in the
|
|
||||||
appropriate section.
|
|
||||||
</p>
|
|
||||||
<p>The other variable is the setting of the context classloader. In
|
|
||||||
these cases, it will be set to either the system classloader (the
|
|
||||||
default) or the child classloader (the application classloader).
|
|
||||||
Perhaps the cases for setting to the parent classloader
|
|
||||||
should be added (but this would be unusual: conventionally the context
|
|
||||||
classloader should be either unset or set to the application
|
|
||||||
classloader). Contributions of these extra cases would be welcomed.
|
|
||||||
</p>
|
|
||||||
<p>The cases will be presented in a matrix. This contains details of
|
|
||||||
the classloader set ups including which
|
|
||||||
which classes are definable by which loaders and how the context
|
|
||||||
classloader is set. It also contains the results of analysis about
|
|
||||||
the way that both the static logging and JCL (ideally) should behave.
|
|
||||||
</p>
|
|
||||||
<p>For example
|
|
||||||
</p>
|
|
||||||
<table border='1'>
|
|
||||||
<tr>
|
|
||||||
<th>Context ClassLoader</th>
|
|
||||||
<td>System</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Parent</th>
|
|
||||||
<td>JCL+Static</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Child</th>
|
|
||||||
<td>
|
|
||||||
JCL+Static<br/>
|
|
||||||
Log4J<br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Expected Result</th>
|
|
||||||
<td>JCL->java.util<br/>
|
|
||||||
static FAIL
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>This describes a case where the context classloader is unset (and
|
|
||||||
so defaults to the system), the static.jar and commons-logging.jar
|
|
||||||
are definable by the parent classloader, the static.jar,
|
|
||||||
commons-logging.jar and log4j are definable by the child. The
|
|
||||||
caller.jar is also definable by the child classloader. The expected
|
|
||||||
result in this case is that JCL will discover java.util.logging and
|
|
||||||
that logging statically to Log4j will fail.
|
|
||||||
</p>
|
|
||||||
<p>For purposes of reference, an indication is given in those cases
|
|
||||||
that correspond to examples used by Ceki in his critique.
|
|
||||||
</p>
|
|
||||||
<p>Analytical notes explaining how these results were obtained are
|
|
||||||
included below each table. As the cases proceed, the notes will grow
|
|
||||||
more terse.
|
|
||||||
</p>
|
|
||||||
<h4>Parent First ClassLoader Cases</h4>
|
|
||||||
<h5>Log4J Defined By Child, JCL By Parent</h5>
|
|
||||||
<table border='1' width='90%'>
|
|
||||||
<tr>
|
|
||||||
<th>Case</th>
|
|
||||||
<td>1</td>
|
|
||||||
<td>2</td>
|
|
||||||
<td>3</td>
|
|
||||||
<td>4</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Ceki Example</th>
|
|
||||||
<td>-</td>
|
|
||||||
<td>1</td>
|
|
||||||
<td>2A</td>
|
|
||||||
<td>3</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Context ClassLoader</th>
|
|
||||||
<td>System</td>
|
|
||||||
<td>System</td>
|
|
||||||
<td>Child</td>
|
|
||||||
<td>Child</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Parent</th>
|
|
||||||
<td>JCL+Static</td>
|
|
||||||
<td>JCL+Static Caller</td>
|
|
||||||
<td>JCL+Static</td>
|
|
||||||
<td>JCL+Static Caller</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Child</th>
|
|
||||||
<td>
|
|
||||||
JCL+Static<br/>
|
|
||||||
Log4J<br/>
|
|
||||||
Caller</td>
|
|
||||||
<td>
|
|
||||||
JCL+Static<br/>
|
|
||||||
Log4J
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
JCL+Static<br/>
|
|
||||||
Log4J<br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
JCL+Static <br/>
|
|
||||||
Log4J
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Expected Result</th>
|
|
||||||
<td>
|
|
||||||
JCL->java.util<br/>
|
|
||||||
static FAIL
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
JCL->java.util<br/>
|
|
||||||
static FAIL
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
JCL->java.util <br/>
|
|
||||||
static FAIL
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
JCL->java.util<br/>
|
|
||||||
static FAIL
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>One important point to bear in mind when analysing parent-first
|
|
||||||
classloaders is that the presence or absence in the child classloader
|
|
||||||
of classes definable by the parent classloader produces no difference
|
|
||||||
in behaviour: the parent classloader will always load the class in
|
|
||||||
question.
|
|
||||||
</p>
|
|
||||||
<p>In the cases above, Log4J is defined (only) by the child and all
|
|
||||||
JCL classes by the parent classloader. The symbolic references from
|
|
||||||
Log4JLogger to Log4J classes therefore cannot be resolved as Log4j is
|
|
||||||
not definable by the parent classloader. For the same reason, the
|
|
||||||
static call should also always fail.
|
|
||||||
</p>
|
|
||||||
<p>The context classloader can be of no use (whether set or not)
|
|
||||||
since Log4JLogger will always be defined by the parent classloader
|
|
||||||
whether loading is initiated by the child or by the parent loader.
|
|
||||||
</p>
|
|
||||||
<p>Therefore, in these cases, the appropriate behaviour is for JCL to
|
|
||||||
discover that java.util.logging is the only available logging system.
|
|
||||||
</p>
|
|
||||||
<h5>Log4J Defined By Parent, JCL By Parent</h5>
|
|
||||||
<table border='1' width='90%'>
|
|
||||||
<tr>
|
|
||||||
<th>Case</th>
|
|
||||||
<td>5</td>
|
|
||||||
<td>6</td>
|
|
||||||
<td>7</td>
|
|
||||||
<td>8</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Ceki Example</th>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Context ClassLoader</th>
|
|
||||||
<td>System</td>
|
|
||||||
<td>System</td>
|
|
||||||
<td>Child</td>
|
|
||||||
<td>Child</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Parent</th>
|
|
||||||
<td>Log4J <br/>
|
|
||||||
JCL+Static
|
|
||||||
<td>Log4J <br/>
|
|
||||||
JCL+Static <br/>
|
|
||||||
Caller
|
|
||||||
<td>Log4J <br/>
|
|
||||||
JCL+Static
|
|
||||||
</td>
|
|
||||||
<td>Log4J <br/>
|
|
||||||
JCL+Static <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Child</th>
|
|
||||||
<td>JCL+Static<br/>
|
|
||||||
Log4J <br/>
|
|
||||||
Caller <br/>
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static<br/>
|
|
||||||
Log4J <br/>
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J<br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static<br/>
|
|
||||||
Log4J
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Expected Result
|
|
||||||
</th>
|
|
||||||
<td>JCL->log4j <br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>JCL->log4j <br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
JCL->log4j<br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
JCL->log4j<br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>This demonstrates the usual way to fix the problems encountered
|
|
||||||
when Log4J is not definable by the loader that defines JCL: just add
|
|
||||||
the Log4j.jar into the classloader that defines JCL.
|
|
||||||
</p>
|
|
||||||
<p>This is a very simple set of cases with JCL and static being able
|
|
||||||
to resolve the appropriate symbolic references to Log4j directly.
|
|
||||||
Whether the context classloader is set or not in these cases should
|
|
||||||
make no difference.
|
|
||||||
</p>
|
|
||||||
<h5>Log4J Defined By Child, JCL API By Parent, JCL By Child</h5>
|
|
||||||
<table border='1' width='90%'>
|
|
||||||
<tr>
|
|
||||||
<th>Case</th>
|
|
||||||
<td>9</td>
|
|
||||||
<td>10</td>
|
|
||||||
<td>11</td>
|
|
||||||
<td>12</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Ceki Example</th>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Context ClassLoader</th>
|
|
||||||
<td>System</td>
|
|
||||||
<td>System</td>
|
|
||||||
<td>Child</td>
|
|
||||||
<td>Child</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Parent</th>
|
|
||||||
<td>API+Static</td>
|
|
||||||
<td>API+Static <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>API+Static
|
|
||||||
</td>
|
|
||||||
<td>API+Static <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Child</th>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static<br/>
|
|
||||||
Log4J
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Expected Result</th>
|
|
||||||
<td>JCL->java.util<br/>
|
|
||||||
static FAIL
|
|
||||||
</td>
|
|
||||||
<td>JCL->java.util<br/>
|
|
||||||
static FAIL
|
|
||||||
</td>
|
|
||||||
<td>JCL->log4j<br/>
|
|
||||||
static FAIL
|
|
||||||
</td>
|
|
||||||
<td>JCL->log4j <br/>
|
|
||||||
static FAIL</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>These demonstrate variations on the first series of cases where
|
|
||||||
Log4J is defined by the child. The placement of the static jar does
|
|
||||||
not vary (from the previous set) and again is expected to
|
|
||||||
consistently fail.
|
|
||||||
</p>
|
|
||||||
<p>This time the API jar is placed in the parent classloader and the
|
|
||||||
full JCL jar in the child. This means that the symbolic reference
|
|
||||||
from the Log4JLogger class (contained in the full jar but not the
|
|
||||||
API) to Log4J classes can be resolved.
|
|
||||||
</p>
|
|
||||||
<p>In these cases, whether JCL can succeed depends on the context
|
|
||||||
classloader. The delegation model employed by Java ClassLoaders
|
|
||||||
allows child classloaders to know about parents but not vice versa.
|
|
||||||
Therefore, the context classloader is the only means available to
|
|
||||||
attempt to load Log4JLogger. When the context classloader is set to
|
|
||||||
the child, this classloader defines Log4JLogger and Log4J. Therefore,
|
|
||||||
JCL should be able to discover Log4J (only) when the context
|
|
||||||
classloader is set to the child.
|
|
||||||
</p>
|
|
||||||
<h5>Log4J Defined By Parent, JCL API By Parent, JCL By Child</h5>
|
|
||||||
<table border='1' width='90%'>
|
|
||||||
<tr>
|
|
||||||
<th>Case</th>
|
|
||||||
<td>13</td>
|
|
||||||
<td>14</td>
|
|
||||||
<td>15</td>
|
|
||||||
<td>16</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Ceki Example</th>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Context ClassLoader</th>
|
|
||||||
<td>System</td>
|
|
||||||
<td>System</td>
|
|
||||||
<td>Child</td>
|
|
||||||
<td>Child</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Parent</th>
|
|
||||||
<td>Log4J <br/>
|
|
||||||
API+Static
|
|
||||||
</td>
|
|
||||||
<td>Log4J <br/>
|
|
||||||
API+Static <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>Log4J<br/>
|
|
||||||
API+Static
|
|
||||||
</td>
|
|
||||||
<td>Log4J<br/>
|
|
||||||
API+Static<br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Child</th>
|
|
||||||
<td>JCL+Static<br/>
|
|
||||||
Log4J <br/>
|
|
||||||
Caller</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Expected Result</th>
|
|
||||||
<td>JCL->java.util<br/>
|
|
||||||
static OK</td>
|
|
||||||
<td>JCL->java.util<br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>JCL->log4j<br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>JCL->log4j<br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>Trivial variations on the second series. Now API and JCL are
|
|
||||||
definable only by parent and child respectively (as in the last
|
|
||||||
series). When the context classloader is set to system,
|
|
||||||
Log4JLogger cannot be loaded and so java.util.logging is the only viable
|
|
||||||
logger.
|
|
||||||
</p>
|
|
||||||
<h4>Child First ClassLoader Cases</h4>
|
|
||||||
<p>The same classloader configuration can be repeated with (this
|
|
||||||
time) child-first classloading.
|
|
||||||
</p>
|
|
||||||
<h5>Log4J Defined By Child, JCL By Parent</h5>
|
|
||||||
<table border='1' width='90%'>
|
|
||||||
<tr>
|
|
||||||
<th>Case</th>
|
|
||||||
<td>17</td>
|
|
||||||
<td>18</td>
|
|
||||||
<td>19</td>
|
|
||||||
<td>20</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Ceki Example</th>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
<td>5</td>
|
|
||||||
<td>6</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Context ClassLoader</th>
|
|
||||||
<td>System</td>
|
|
||||||
<td>System</td>
|
|
||||||
<td>Child</td>
|
|
||||||
<td>Child</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Parent</th>
|
|
||||||
<td>JCL+Static</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Caller</td>
|
|
||||||
<td>JCL+Static</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Child</th>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Expected Result</th>
|
|
||||||
<td>JCL->Log4j <br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>JCL->java.util <br/>
|
|
||||||
static FAIL
|
|
||||||
</td>
|
|
||||||
<td>JCL->Log4j<br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>JCL->java.util<br/>
|
|
||||||
static FAIL
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>In child-first cases, the classloader which defines the caller
|
|
||||||
plays a more important role. When the caller is defined by the child
|
|
||||||
classloader, both static and JCL should succeed whether the context
|
|
||||||
classloader is set or not.
|
|
||||||
</p>
|
|
||||||
<p>When the caller is defined by the parent classloader, this means
|
|
||||||
that the parent classloader will define the JCL and static classes
|
|
||||||
(rather than the child). Log4J is not defined by the parent loader
|
|
||||||
and so the static call must fail in both cases.
|
|
||||||
</p>
|
|
||||||
<p>With a friendly context classloader, JCL can load an instance of
|
|
||||||
Log4JLogger whose symbolic references to Log4J can be resolved.
|
|
||||||
However, the child classloader which defines this class will resolve
|
|
||||||
the symbolic reference to Log to the class defined by the child
|
|
||||||
classloader rather than the Log class defined by the parent
|
|
||||||
classloader. They are not mutually accessible and so JCL must
|
|
||||||
discover java.util.logging.
|
|
||||||
</p>
|
|
||||||
<h5>Log4J Defined By Parent, JCL By Parent</h5>
|
|
||||||
<table border='1' width='90%'>
|
|
||||||
<tr>
|
|
||||||
<th>Case
|
|
||||||
</th>
|
|
||||||
<td>21</td>
|
|
||||||
<td>22</td>
|
|
||||||
<td>23</td>
|
|
||||||
<td>24</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Ceki Example</th>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Context ClassLoader</th>
|
|
||||||
<td>System</td>
|
|
||||||
<td>System</td>
|
|
||||||
<td>Child</td>
|
|
||||||
<td>Child</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Parent</th>
|
|
||||||
<td>Log4J <br/>
|
|
||||||
JCL+Static
|
|
||||||
</td>
|
|
||||||
<td>Log4J <br/>
|
|
||||||
JCL+Static <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>Log4J <br/>
|
|
||||||
JCL+Static
|
|
||||||
</td>
|
|
||||||
<td>Log4J <br/>
|
|
||||||
JCL+Static <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Child</th>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Expected Result</th>
|
|
||||||
<td>JCL->log4j <br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>JCL->log4j <br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>JCL->log4j <br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>JCL->log4j <br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>Trivial case where jar's are definable by both loaders.
|
|
||||||
</p>
|
|
||||||
<h5>Log4J Defined By Child, JCL API By Parent, JCL By Child</h5>
|
|
||||||
<table border='1' width='90%'>
|
|
||||||
<tr>
|
|
||||||
<th>Case</th>
|
|
||||||
<td>25</td>
|
|
||||||
<td>26</td>
|
|
||||||
<td>27</td>
|
|
||||||
<td>28</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Ceki Example</th>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Context ClassLoader</th>
|
|
||||||
<td>System</td>
|
|
||||||
<td>System</td>
|
|
||||||
<td>Child</td>
|
|
||||||
<td>Child</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Parent</th>
|
|
||||||
<td>API+Static</td>
|
|
||||||
<td>API+Static <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>API+Static</td>
|
|
||||||
<td>API+Static <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Child</th>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Expected Result</th>
|
|
||||||
<td>JCL->log4j <br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>JCL->java.util <br/>
|
|
||||||
static FAIL
|
|
||||||
</td>
|
|
||||||
<td>JCL->log4j <br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>JCL->java.util <br/>
|
|
||||||
static FAIL
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>(As above) to succeed, the static call requires that Log4J is
|
|
||||||
definable by the loader which defines the callers. JCL should
|
|
||||||
discover Log4J in the cases where the static call succeeds.
|
|
||||||
</p>
|
|
||||||
<p>Even with a friendly context classloader, the Log class referenced
|
|
||||||
by the Log4JLogger defined by the child classloader will be
|
|
||||||
inaccessible to the caller (loader by the parent classloader).
|
|
||||||
</p>
|
|
||||||
<h5>Log4J Defined By Parent, JCL API By Parent, JCL By Child</h5>
|
|
||||||
<table border='1' width='90%'>
|
|
||||||
<tr>
|
|
||||||
<th>Case</th>
|
|
||||||
<td>29</td>
|
|
||||||
<td>30</td>
|
|
||||||
<td>31</td>
|
|
||||||
<td>32</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Ceki Example</th>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
<td>-</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Context ClassLoader</th>
|
|
||||||
<td>System</td>
|
|
||||||
<td>System</td>
|
|
||||||
<td>Child</td>
|
|
||||||
<td>Child</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Parent</th>
|
|
||||||
<td>Log4J <br/>
|
|
||||||
API+Static
|
|
||||||
</td>
|
|
||||||
<td>Log4J <br/>
|
|
||||||
API+Static <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>Log4J<br/>
|
|
||||||
API+Static
|
|
||||||
</td>
|
|
||||||
<td>Log4J<br/>
|
|
||||||
API+Static <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Child</th>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J <br/>
|
|
||||||
Caller
|
|
||||||
</td>
|
|
||||||
<td>JCL+Static <br/>
|
|
||||||
Log4J
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Expected Result</th>
|
|
||||||
<td>JCL->log4j <br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>JCL->java.util <br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>JCL->log4j <br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
<td>JCL->java.util <br/>
|
|
||||||
static OK
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>These results at first glance may seem a little confusing. The
|
|
||||||
issue for JCL is that classes needed to log to Log4J are only
|
|
||||||
definable by the child classloader.
|
|
||||||
</p>
|
|
||||||
<p>Even with a friendly context classloader, JCL runs into the same
|
|
||||||
difficulties with accessibility that
|
|
||||||
occurred above.
|
|
||||||
</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Reference in New Issue
Block a user