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.logfactory;
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.LogFactory;
027    import org.apache.commons.logging.PathableClassLoader;
028    import org.apache.commons.logging.PathableTestSuite;
029    
030    
031    /**
032     * Verify that by default a custom LogFactoryImpl is loaded from the
033     * tccl classloader.
034     */
035    
036    public class TcclEnabledTestCase extends TestCase {
037    
038        // ------------------------------------------- JUnit Infrastructure Methods
039    
040    
041        /**
042         * Return the tests included in this test suite.
043         */
044        public static Test suite() throws Exception {
045            Class thisClass = TcclEnabledTestCase.class;
046    
047            // Determine the URL to this .class file, so that we can then
048            // append the priority dirs to it. For tidiness, load this
049            // class through a dummy loader though this is not absolutely
050            // necessary...
051            PathableClassLoader dummy = new PathableClassLoader(null);
052            dummy.useExplicitLoader("junit.", Test.class.getClassLoader());
053            dummy.addLogicalLib("testclasses");
054            dummy.addLogicalLib("commons-logging");
055            
056            String thisClassPath = thisClass.getName().replace('.', '/') + ".class";
057            URL baseUrl = dummy.findResource(thisClassPath);
058    
059            // Now set up the desired classloader hierarchy. Everything goes into
060            // the parent classpath, but we exclude the custom LogFactoryImpl
061            // class.
062            //
063            // We then create a tccl classloader that can see the custom
064            // LogFactory class. Therefore if that class can be found, then the
065            // TCCL must have been used to load it.
066            PathableClassLoader emptyLoader = new PathableClassLoader(null);
067            
068            PathableClassLoader parentLoader = new PathableClassLoader(null);
069            parentLoader.useExplicitLoader("junit.", Test.class.getClassLoader());
070            parentLoader.addLogicalLib("commons-logging");
071            parentLoader.addLogicalLib("testclasses");
072            // hack to ensure that the testcase classloader can't see
073            // the cust MyLogFactoryImpl
074            parentLoader.useExplicitLoader(
075                "org.apache.commons.logging.tccl.custom.", emptyLoader);
076            
077            URL propsEnableUrl = new URL(baseUrl, "props_enable_tccl/");
078            parentLoader.addURL(propsEnableUrl);
079    
080            PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader);
081            tcclLoader.addLogicalLib("testclasses");
082    
083            Class testClass = parentLoader.loadClass(thisClass.getName());
084            return new PathableTestSuite(testClass, tcclLoader);
085        }
086    
087        /**
088         * Set up instance variables required by this test case.
089         */
090        public void setUp() throws Exception {
091            LogFactory.releaseAll();
092        }
093    
094        /**
095         * Tear down instance variables required by this test case.
096         */
097        public void tearDown() {
098            LogFactory.releaseAll();
099        }
100    
101        // ----------------------------------------------------------- Test Methods
102    
103        /**
104         * Verify that MyLogFactoryImpl is only loadable via the tccl.
105         */
106        public void testLoader() throws Exception {
107            
108            ClassLoader thisClassLoader = this.getClass().getClassLoader();
109            ClassLoader tcclLoader = Thread.currentThread().getContextClassLoader();
110    
111            // the tccl loader should NOT be the same as the loader that loaded this test class.
112            assertNotSame("tccl not same as test classloader", thisClassLoader, tcclLoader);
113    
114            // MyLogFactoryImpl should not be loadable via parent loader
115            try {
116                Class clazz = thisClassLoader.loadClass(
117                    "org.apache.commons.logging.tccl.custom.MyLogFactoryImpl");
118                fail("Unexpectedly able to load MyLogFactoryImpl via test class classloader");
119                assertNotNull(clazz); // silence warning about unused var
120            } catch(ClassNotFoundException ex) {
121                // ok, expected
122            }
123            
124            // MyLogFactoryImpl should be loadable via tccl loader
125            try {
126                Class clazz = tcclLoader.loadClass(
127                    "org.apache.commons.logging.tccl.custom.MyLogFactoryImpl");
128                assertNotNull(clazz);
129            } catch(ClassNotFoundException ex) {
130                fail("Unexpectedly unable to load MyLogFactoryImpl via tccl classloader");
131            }
132        }
133    
134        /**
135         * Verify that the custom LogFactory implementation which is only accessable
136         * via the TCCL has successfully been loaded as specified in the config file.
137         * This proves that the TCCL was used to load that class.
138         */
139        public void testTcclLoading() throws Exception {
140            LogFactory instance = LogFactory.getFactory();
141            
142            assertEquals(
143                "Correct LogFactory loaded", 
144                "org.apache.commons.logging.tccl.custom.MyLogFactoryImpl",
145                instance.getClass().getName());
146        }
147    }