001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.logging.tccl.log; 019 020 021 import java.net.URL; 022 023 import junit.framework.Test; 024 import junit.framework.TestCase; 025 026 import org.apache.commons.logging.Log; 027 import org.apache.commons.logging.LogFactory; 028 import org.apache.commons.logging.PathableClassLoader; 029 import org.apache.commons.logging.PathableTestSuite; 030 031 032 /** 033 * Verify that by default the standard LogFactoryImpl class loads a 034 * custom Log implementation via the TCCL. 035 */ 036 037 public class TcclEnabledTestCase extends TestCase { 038 039 public static final String MY_LOG_PKG = 040 "org.apache.commons.logging.tccl.custom"; 041 042 public static final String MY_LOG_IMPL = 043 MY_LOG_PKG + ".MyLog"; 044 045 // ------------------------------------------- JUnit Infrastructure Methods 046 047 /** 048 * Return the tests included in this test suite. 049 */ 050 public static Test suite() throws Exception { 051 Class thisClass = TcclEnabledTestCase.class; 052 053 // Determine the URL to this .class file, so that we can then 054 // append the priority dirs to it. For tidiness, load this 055 // class through a dummy loader though this is not absolutely 056 // necessary... 057 PathableClassLoader dummy = new PathableClassLoader(null); 058 dummy.useExplicitLoader("junit.", Test.class.getClassLoader()); 059 dummy.addLogicalLib("testclasses"); 060 dummy.addLogicalLib("commons-logging"); 061 062 String thisClassPath = thisClass.getName().replace('.', '/') + ".class"; 063 URL baseUrl = dummy.findResource(thisClassPath); 064 065 // Now set up the desired classloader hierarchy. Everything goes into 066 // the parent classpath, but we exclude the custom Log class. 067 // 068 // We then create a tccl classloader that can see the custom 069 // Log class. Therefore if that class can be found, then the 070 // TCCL must have been used to load it. 071 PathableClassLoader emptyLoader = new PathableClassLoader(null); 072 073 PathableClassLoader parentLoader = new PathableClassLoader(null); 074 parentLoader.useExplicitLoader("junit.", Test.class.getClassLoader()); 075 parentLoader.addLogicalLib("commons-logging"); 076 parentLoader.addLogicalLib("testclasses"); 077 // hack to ensure that the testcase classloader can't see 078 // the custom MyLogFactoryImpl 079 parentLoader.useExplicitLoader(MY_LOG_PKG + ".", emptyLoader); 080 081 URL propsEnableUrl = new URL(baseUrl, "props_enable_tccl/"); 082 parentLoader.addURL(propsEnableUrl); 083 084 PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader); 085 tcclLoader.addLogicalLib("testclasses"); 086 087 Class testClass = parentLoader.loadClass(thisClass.getName()); 088 return new PathableTestSuite(testClass, tcclLoader); 089 } 090 091 /** 092 * Set up instance variables required by this test case. 093 */ 094 public void setUp() throws Exception { 095 LogFactory.releaseAll(); 096 } 097 098 /** 099 * Tear down instance variables required by this test case. 100 */ 101 public void tearDown() { 102 LogFactory.releaseAll(); 103 } 104 105 // ----------------------------------------------------------- Test Methods 106 107 /** 108 * Verify that MyLogFactoryImpl is only loadable via the tccl. 109 */ 110 public void testLoader() throws Exception { 111 112 ClassLoader thisClassLoader = this.getClass().getClassLoader(); 113 ClassLoader tcclLoader = Thread.currentThread().getContextClassLoader(); 114 115 // the tccl loader should NOT be the same as the loader that loaded this test class. 116 assertNotSame("tccl not same as test classloader", thisClassLoader, tcclLoader); 117 118 // MyLog should not be loadable via parent loader 119 try { 120 Class clazz = thisClassLoader.loadClass(MY_LOG_IMPL); 121 fail("Unexpectedly able to load MyLog via test class classloader"); 122 assertNotNull(clazz); // silence warnings about unused var 123 } catch(ClassNotFoundException ex) { 124 // ok, expected 125 } 126 127 // MyLog should be loadable via tccl loader 128 try { 129 Class clazz = tcclLoader.loadClass(MY_LOG_IMPL); 130 assertNotNull(clazz); 131 } catch(ClassNotFoundException ex) { 132 fail("Unexpectedly unable to load MyLog via tccl classloader"); 133 } 134 } 135 136 /** 137 * Verify that the custom Log implementation which is only accessable 138 * via the TCCL has successfully been loaded as specified in the config file. 139 * This proves that the TCCL was used to load that class. 140 */ 141 public void testTcclLoading() throws Exception { 142 LogFactory instance = LogFactory.getFactory(); 143 144 assertEquals( 145 "Correct LogFactory loaded", 146 "org.apache.commons.logging.impl.LogFactoryImpl", 147 instance.getClass().getName()); 148 149 Log log = instance.getInstance("test"); 150 assertEquals( 151 "Correct Log loaded", 152 MY_LOG_IMPL, 153 log.getClass().getName()); 154 } 155 }