From ae7e0b31575be036c211c93095416bf71bd65a70 Mon Sep 17 00:00:00 2001 From: Robert Burrell Donkin Date: Sun, 11 Dec 2005 16:52:00 +0000 Subject: [PATCH] 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 --- demonstration/README.txt | 30 - demonstration/build.xml | 127 --- .../caller/JCLDemonstrator.java | 69 -- .../proofofconcept/caller/SomeObject.java | 44 - .../proofofconcept/caller/package.html | 24 - .../runner/ChildFirstClassLoader.java | 52 -- .../runner/ChildFirstRunner.java | 165 ---- .../runner/ClassLoaderRunner.java | 222 ----- .../runner/ParentFirstRunner.java | 165 ---- .../proofofconcept/runner/package.html | 23 - .../staticlogger/StaticLog4JLogger.java | 32 - .../proofofconcept/staticlogger/package.html | 25 - demonstration/src/java/overview.html | 835 ------------------ 13 files changed, 1813 deletions(-) delete mode 100644 demonstration/README.txt delete mode 100644 demonstration/build.xml delete mode 100644 demonstration/src/java/org/apache/commons/logging/proofofconcept/caller/JCLDemonstrator.java delete mode 100644 demonstration/src/java/org/apache/commons/logging/proofofconcept/caller/SomeObject.java delete mode 100644 demonstration/src/java/org/apache/commons/logging/proofofconcept/caller/package.html delete mode 100644 demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ChildFirstClassLoader.java delete mode 100644 demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ChildFirstRunner.java delete mode 100644 demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ClassLoaderRunner.java delete mode 100644 demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ParentFirstRunner.java delete mode 100644 demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/package.html delete mode 100644 demonstration/src/java/org/apache/commons/logging/proofofconcept/staticlogger/StaticLog4JLogger.java delete mode 100644 demonstration/src/java/org/apache/commons/logging/proofofconcept/staticlogger/package.html delete mode 100644 demonstration/src/java/overview.html diff --git a/demonstration/README.txt b/demonstration/README.txt deleted file mode 100644 index 723bac6..0000000 --- a/demonstration/README.txt +++ /dev/null @@ -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' \ No newline at end of file diff --git a/demonstration/build.xml b/demonstration/build.xml deleted file mode 100644 index 891b994..0000000 --- a/demonstration/build.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/demonstration/src/java/org/apache/commons/logging/proofofconcept/caller/JCLDemonstrator.java b/demonstration/src/java/org/apache/commons/logging/proofofconcept/caller/JCLDemonstrator.java deleted file mode 100644 index 4047c96..0000000 --- a/demonstration/src/java/org/apache/commons/logging/proofofconcept/caller/JCLDemonstrator.java +++ /dev/null @@ -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 System.out. - */ - 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 System.out. - */ - 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(""); - } - } -} diff --git a/demonstration/src/java/org/apache/commons/logging/proofofconcept/caller/SomeObject.java b/demonstration/src/java/org/apache/commons/logging/proofofconcept/caller/SomeObject.java deleted file mode 100644 index ca0ec93..0000000 --- a/demonstration/src/java/org/apache/commons/logging/proofofconcept/caller/SomeObject.java +++ /dev/null @@ -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 Jakarta Commons Logging. - */ - public void logToJCL() { - LogFactory.getLog("a log").info("A message"); - } - - /** - * Logs a message to Log4j via a class - * which makes a static call. - */ - public void logToStaticLog4J() { - StaticLog4JLogger.info("A message"); - } -} diff --git a/demonstration/src/java/org/apache/commons/logging/proofofconcept/caller/package.html b/demonstration/src/java/org/apache/commons/logging/proofofconcept/caller/package.html deleted file mode 100644 index 54aa603..0000000 --- a/demonstration/src/java/org/apache/commons/logging/proofofconcept/caller/package.html +++ /dev/null @@ -1,24 +0,0 @@ - - -

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

- - diff --git a/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ChildFirstClassLoader.java b/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ChildFirstClassLoader.java deleted file mode 100644 index 2c32552..0000000 --- a/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ChildFirstClassLoader.java +++ /dev/null @@ -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; - } - -} diff --git a/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ChildFirstRunner.java b/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ChildFirstRunner.java deleted file mode 100644 index d69ab9d..0000000 --- a/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ChildFirstRunner.java +++ /dev/null @@ -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(); - } - - } -} diff --git a/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ClassLoaderRunner.java b/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ClassLoaderRunner.java deleted file mode 100644 index a486e39..0000000 --- a/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ClassLoaderRunner.java +++ /dev/null @@ -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 URL 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 URL's which should - * be definable by the parent classloader, not null - * @param childClassloaderUrls the URL'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 ClassLoader, not null - * @param parent parent ClassLoader, 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 ClassLoader, not null - * @param parent parent ClassLoader, 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"); - } - } - -} diff --git a/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ParentFirstRunner.java b/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ParentFirstRunner.java deleted file mode 100644 index 5c102ae..0000000 --- a/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/ParentFirstRunner.java +++ /dev/null @@ -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(); - } - - } -} diff --git a/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/package.html b/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/package.html deleted file mode 100644 index 94723ea..0000000 --- a/demonstration/src/java/org/apache/commons/logging/proofofconcept/runner/package.html +++ /dev/null @@ -1,23 +0,0 @@ - - -

Runs the demonstrations.

-

-Also contained is utility code that efficiently sets up the -various classloader hierarchies. -

- diff --git a/demonstration/src/java/org/apache/commons/logging/proofofconcept/staticlogger/StaticLog4JLogger.java b/demonstration/src/java/org/apache/commons/logging/proofofconcept/staticlogger/StaticLog4JLogger.java deleted file mode 100644 index 8d8b2e8..0000000 --- a/demonstration/src/java/org/apache/commons/logging/proofofconcept/staticlogger/StaticLog4JLogger.java +++ /dev/null @@ -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); - } - -} diff --git a/demonstration/src/java/org/apache/commons/logging/proofofconcept/staticlogger/package.html b/demonstration/src/java/org/apache/commons/logging/proofofconcept/staticlogger/package.html deleted file mode 100644 index 8e081c8..0000000 --- a/demonstration/src/java/org/apache/commons/logging/proofofconcept/staticlogger/package.html +++ /dev/null @@ -1,25 +0,0 @@ - - -

Calls Log4j. Uses a symbolic reference. -

-

-This allows practical demonstrations of the behaviour of code -that calls Log4J statically when placed in similar -classloader circumstances of JCL. -

- diff --git a/demonstration/src/java/overview.html b/demonstration/src/java/overview.html deleted file mode 100644 index 9ae10f0..0000000 --- a/demonstration/src/java/overview.html +++ /dev/null @@ -1,835 +0,0 @@ - - - - - Overview Documentation for JCL Proof Of Concept Demonstrations - - -

Demonstrates Jakarta Commons Logging (JCL) concepts.

-

Introduction

-

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

-

Familiarity with (advanced) class loading -concepts and terminology is assumed. Please digest the -JCL -Technology Guide before starting. -

-

This approach was inspired by a -JCL critique -written by Ceki Gülcü. -

-

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

-

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

- -

Overview

-

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

-

Each demonstration is initiated by a runner. The runner loads the -other code components into appropriate ClassLoaders and then calls the caller. -

-

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

-

The static logger simply contains a call directly to Log4J. This -is useful for comparison. -

-

Now would be a good idea to study the javadocs. -

-

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). -

-

Conventional And Unconventional Context ClassLoaders

-

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

-

Conventional Classloader Cases

-

The aim of the set up will be isolate the essentials. Only three -classloaders will be considered: -

- -

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

-

The analysis will proceed by considering two cases separately: -

- -

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

-

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

-

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

-

For example -

- - - - - - - - - - - - - - - - - -
Context ClassLoaderSystem
ParentJCL+Static
Child - JCL+Static
- Log4J
- Caller -
Expected ResultJCL->java.util
- static FAIL -
-

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

-

For purposes of reference, an indication is given in those cases -that correspond to examples used by Ceki in his critique. -

-

Analytical notes explaining how these results were obtained are -included below each table. As the cases proceed, the notes will grow -more terse. -

-

Parent First ClassLoader Cases

-
Log4J Defined By Child, JCL By Parent
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Case1234
Ceki Example-12A3
Context ClassLoaderSystemSystemChildChild
ParentJCL+StaticJCL+Static CallerJCL+StaticJCL+Static Caller
Child - JCL+Static
- Log4J
- Caller
- JCL+Static
- Log4J -
- JCL+Static
- Log4J
- Caller -
- JCL+Static
- Log4J -
Expected Result - JCL->java.util
- static FAIL -
- JCL->java.util
- static FAIL -
- JCL->java.util
- static FAIL -
- JCL->java.util
- static FAIL -
-

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

-

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

-

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

-

Therefore, in these cases, the appropriate behaviour is for JCL to -discover that java.util.logging is the only available logging system. -

-
Log4J Defined By Parent, JCL By Parent
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Case5678
Ceki Example----
Context ClassLoaderSystemSystemChildChild
ParentLog4J
- JCL+Static -
Log4J
- JCL+Static
- Caller -
Log4J
- JCL+Static -
Log4J
- JCL+Static
- Caller -
ChildJCL+Static
- Log4J
- Caller
-
JCL+Static
- Log4J
-
JCL+Static
- Log4J
- Caller -
JCL+Static
- Log4J -
Expected Result - JCL->log4j
- static OK -
JCL->log4j
- static OK -
- JCL->log4j
- static OK -
- JCL->log4j
- static OK -
-

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

-

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

-
Log4J Defined By Child, JCL API By Parent, JCL By Child
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Case9101112
Ceki Example----
Context ClassLoaderSystemSystemChildChild
ParentAPI+StaticAPI+Static
- Caller -
API+Static - API+Static
- Caller -
ChildJCL+Static
- Log4J
- Caller -
JCL+Static
- Log4J -
JCL+Static
- Log4J
- Caller -
JCL+Static
- Log4J -
Expected ResultJCL->java.util
- static FAIL -
JCL->java.util
- static FAIL -
JCL->log4j
- static FAIL -
JCL->log4j
- static FAIL

-
-

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

-

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

-

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

-
Log4J Defined By Parent, JCL API By Parent, JCL By Child
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Case13141516
Ceki Example----
Context ClassLoaderSystemSystemChildChild
ParentLog4J
- API+Static -
Log4J
- API+Static
- Caller -
Log4J
- API+Static -
Log4J
- API+Static
- Caller -
ChildJCL+Static
- Log4J
- Caller
JCL+Static
- Log4J
JCL+Static
- Log4J
- Caller -
JCL+Static
- Log4J
Expected ResultJCL->java.util
- static OK
JCL->java.util
- static OK -
JCL->log4j
- static OK -
JCL->log4j
- static OK -
-

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

-

Child First ClassLoader Cases

-

The same classloader configuration can be repeated with (this -time) child-first classloading. -

-
Log4J Defined By Child, JCL By Parent
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Case17181920
Ceki Example--56
Context ClassLoaderSystemSystemChildChild
ParentJCL+StaticJCL+Static
- Caller
JCL+StaticJCL+Static
- Caller -
ChildJCL+Static
- Log4J
- Caller -
JCL+Static
- Log4J -
JCL+Static
- Log4J
- Caller -
JCL+Static
- Log4J -
Expected ResultJCL->Log4j
- static OK -
JCL->java.util
- static FAIL -
JCL->Log4j
- static OK -
JCL->java.util
- static FAIL -
-

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

-

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

-

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

-
Log4J Defined By Parent, JCL By Parent
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Case - 21222324
Ceki Example----
Context ClassLoaderSystemSystemChildChild
ParentLog4J
- JCL+Static -
Log4J
- JCL+Static
- Caller -
Log4J
- JCL+Static -
Log4J
- JCL+Static
- Caller -
ChildJCL+Static
- Log4J
- Caller -
JCL+Static
- Log4J -
JCL+Static
- Log4J
- Caller -
JCL+Static
- Log4J -
Expected ResultJCL->log4j
- static OK -
JCL->log4j
- static OK -
JCL->log4j
- static OK -
JCL->log4j
- static OK -
-

Trivial case where jar's are definable by both loaders. -

-
Log4J Defined By Child, JCL API By Parent, JCL By Child
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Case25262728
Ceki Example----
Context ClassLoaderSystemSystemChildChild
ParentAPI+StaticAPI+Static
- Caller -
API+StaticAPI+Static
- Caller -
ChildJCL+Static
- Log4J
- Caller -
JCL+Static
- Log4J -
JCL+Static
- Log4J
- Caller -
JCL+Static
- Log4J -
Expected ResultJCL->log4j
- static OK -
JCL->java.util
- static FAIL -
JCL->log4j
- static OK -
JCL->java.util
- static FAIL -
-

(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. -

-

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). -

-
Log4J Defined By Parent, JCL API By Parent, JCL By Child
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Case29303132
Ceki Example----
Context ClassLoaderSystemSystemChildChild
ParentLog4J
- API+Static -
Log4J
- API+Static
- Caller -
Log4J
- API+Static -
Log4J
- API+Static
- Caller -
ChildJCL+Static
- Log4J
- Caller -
JCL+Static
- Log4J -
JCL+Static
- Log4J
- Caller -
JCL+Static
- Log4J -
Expected ResultJCL->log4j
- static OK -
JCL->java.util
- static OK -
JCL->log4j
- static OK -
JCL->java.util
- static OK -
-

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

-

Even with a friendly context classloader, JCL runs into the same -difficulties with accessibility that -occurred above. -

- -