1   /*
2    * Copyright 2006 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */ 
16  
17  package org.apache.commons.logging.tccl.log;
18  
19  
20  import java.net.URL;
21  
22  import junit.framework.Test;
23  import junit.framework.TestCase;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.commons.logging.PathableClassLoader;
28  import org.apache.commons.logging.PathableTestSuite;
29  
30  
31  /***
32   * Verify that by default the standard LogFactoryImpl class loads a
33   * custom Log implementation via the TCCL. 
34   */
35  
36  public class TcclEnabledTestCase extends TestCase {
37  
38      public static final String MY_LOG_PKG = 
39          "org.apache.commons.logging.tccl.custom";
40  
41      public static final String MY_LOG_IMPL =
42          MY_LOG_PKG + ".MyLog";
43  
44      // ------------------------------------------- JUnit Infrastructure Methods
45  
46      /***
47       * Return the tests included in this test suite.
48       */
49      public static Test suite() throws Exception {
50          Class thisClass = TcclEnabledTestCase.class;
51  
52          // Determine the URL to this .class file, so that we can then
53          // append the priority dirs to it. For tidiness, load this
54          // class through a dummy loader though this is not absolutely
55          // necessary...
56          PathableClassLoader dummy = new PathableClassLoader(null);
57          dummy.useSystemLoader("junit.");
58          dummy.addLogicalLib("testclasses");
59          dummy.addLogicalLib("commons-logging");
60          
61          String thisClassPath = thisClass.getName().replace('.', '/') + ".class";
62          URL baseUrl = dummy.findResource(thisClassPath);
63  
64          // Now set up the desired classloader hierarchy. Everything goes into
65          // the parent classpath, but we exclude the custom Log class.
66          //
67          // We then create a tccl classloader that can see the custom
68          // Log class. Therefore if that class can be found, then the
69          // TCCL must have been used to load it.
70          PathableClassLoader emptyLoader = new PathableClassLoader(null);
71          
72          PathableClassLoader parentLoader = new PathableClassLoader(null);
73          parentLoader.useSystemLoader("junit.");
74          parentLoader.addLogicalLib("commons-logging");
75          parentLoader.addLogicalLib("testclasses");
76          // hack to ensure that the testcase classloader can't see
77          // the custom MyLogFactoryImpl
78          parentLoader.useExplicitLoader(MY_LOG_PKG + ".", emptyLoader);
79          
80          URL propsEnableUrl = new URL(baseUrl, "props_enable_tccl/");
81          parentLoader.addURL(propsEnableUrl);
82  
83          PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader);
84          tcclLoader.addLogicalLib("testclasses");
85  
86          Class testClass = parentLoader.loadClass(thisClass.getName());
87          return new PathableTestSuite(testClass, tcclLoader);
88      }
89  
90      /***
91       * Set up instance variables required by this test case.
92       */
93      public void setUp() throws Exception {
94          LogFactory.releaseAll();
95      }
96  
97      /***
98       * Tear down instance variables required by this test case.
99       */
100     public void tearDown() {
101         LogFactory.releaseAll();
102     }
103 
104     // ----------------------------------------------------------- Test Methods
105 
106     /***
107      * Verify that MyLogFactoryImpl is only loadable via the tccl.
108      */
109     public void testLoader() throws Exception {
110         
111         ClassLoader thisClassLoader = this.getClass().getClassLoader();
112         ClassLoader tcclLoader = Thread.currentThread().getContextClassLoader();
113         
114         // the tccl loader should NOT be the same as the loader that loaded this test class.
115         assertNotSame("tccl not same as test classloader", thisClassLoader, tcclLoader);
116 
117         // MyLog should not be loadable via parent loader
118         try {
119             Class clazz = thisClassLoader.loadClass(MY_LOG_IMPL);
120             fail("Unexpectedly able to load MyLog via test class classloader");
121         } catch(ClassNotFoundException ex) {
122             // ok, expected
123         }
124         
125         // MyLog should be loadable via tccl loader
126         try {
127             Class clazz = tcclLoader.loadClass(MY_LOG_IMPL);
128         } catch(ClassNotFoundException ex) {
129             fail("Unexpectedly unable to load MyLog via tccl classloader");
130         }
131     }
132 
133     /***
134      * Verify that the custom Log implementation which is only accessable
135      * via the TCCL has successfully been loaded as specified in the config file.
136      * This proves that the TCCL was used to load that class.
137      */
138     public void testTcclLoading() throws Exception {
139         LogFactory instance = LogFactory.getFactory();
140         
141         assertEquals(
142             "Correct LogFactory loaded", 
143             "org.apache.commons.logging.impl.LogFactoryImpl",
144             instance.getClass().getName());
145 
146         Log log = instance.getLog("test");
147         assertEquals(
148             "Correct Log loaded",
149             MY_LOG_IMPL,
150             log.getClass().getName());
151     }
152 }