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.LogConfigurationException;
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 LogFactoryImpl is loaded from the tccl classloader.
34   */
35  
36  public class TcclDisabledTestCase 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 = TcclDisabledTestCase.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 MyLog
78          parentLoader.useExplicitLoader(MY_LOG_PKG + ".", emptyLoader);
79          
80          URL propsEnableUrl = new URL(baseUrl, "props_disable_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 MyLog 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 NOT been loaded. Because this is only accessable via the
136      * TCCL, and we've use a commons-logging.properties that disables TCCL loading,
137      * we should see the default Log rather than the custom one.
138      */
139     public void testTcclLoading() throws Exception {
140         LogFactory instance = LogFactory.getFactory();
141         assertEquals(
142                 "Correct LogFactory loaded", 
143                 "org.apache.commons.logging.impl.LogFactoryImpl",
144                 instance.getClass().getName());
145 
146         try {
147             Log log = instance.getLog("test");
148             fail("Unexpectedly succeeded in loading a custom Log class"
149                 + " that is only accessable via the tccl.");
150         } catch(LogConfigurationException ex) {
151             // ok, expected
152             int index = ex.getMessage().indexOf(MY_LOG_IMPL);
153             assertTrue("MyLog not found", index >= 0);
154         }
155     }
156 }