1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */ 
17  
18  package org.apache.commons.logging.tccl.log;
19  
20  
21  import java.net.URL;
22  
23  import junit.framework.Test;
24  import junit.framework.TestCase;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.apache.commons.logging.PathableClassLoader;
29  import org.apache.commons.logging.PathableTestSuite;
30  
31  
32  /**
33   * Verify that by default the standard LogFactoryImpl class loads a
34   * custom Log implementation via the TCCL. 
35   */
36  
37  public class TcclEnabledTestCase extends TestCase {
38  
39      public static final String MY_LOG_PKG = 
40          "org.apache.commons.logging.tccl.custom";
41  
42      public static final String MY_LOG_IMPL =
43          MY_LOG_PKG + ".MyLog";
44  
45      // ------------------------------------------- JUnit Infrastructure Methods
46  
47      /**
48       * Return the tests included in this test suite.
49       */
50      public static Test suite() throws Exception {
51          Class thisClass = TcclEnabledTestCase.class;
52  
53          // Determine the URL to this .class file, so that we can then
54          // append the priority dirs to it. For tidiness, load this
55          // class through a dummy loader though this is not absolutely
56          // necessary...
57          PathableClassLoader dummy = new PathableClassLoader(null);
58          dummy.useExplicitLoader("junit.", Test.class.getClassLoader());
59          dummy.addLogicalLib("testclasses");
60          dummy.addLogicalLib("commons-logging");
61          
62          String thisClassPath = thisClass.getName().replace('.', '/') + ".class";
63          URL baseUrl = dummy.findResource(thisClassPath);
64  
65          // Now set up the desired classloader hierarchy. Everything goes into
66          // the parent classpath, but we exclude the custom Log class.
67          //
68          // We then create a tccl classloader that can see the custom
69          // Log class. Therefore if that class can be found, then the
70          // TCCL must have been used to load it.
71          PathableClassLoader emptyLoader = new PathableClassLoader(null);
72          
73          PathableClassLoader parentLoader = new PathableClassLoader(null);
74          parentLoader.useExplicitLoader("junit.", Test.class.getClassLoader());
75          parentLoader.addLogicalLib("commons-logging");
76          parentLoader.addLogicalLib("testclasses");
77          // hack to ensure that the testcase classloader can't see
78          // the custom MyLogFactoryImpl
79          parentLoader.useExplicitLoader(MY_LOG_PKG + ".", emptyLoader);
80          
81          URL propsEnableUrl = new URL(baseUrl, "props_enable_tccl/");
82          parentLoader.addURL(propsEnableUrl);
83  
84          PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader);
85          tcclLoader.addLogicalLib("testclasses");
86  
87          Class testClass = parentLoader.loadClass(thisClass.getName());
88          return new PathableTestSuite(testClass, tcclLoader);
89      }
90  
91      /**
92       * Set up instance variables required by this test case.
93       */
94      public void setUp() throws Exception {
95          LogFactory.releaseAll();
96      }
97  
98      /**
99       * 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 }