View Javadoc
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.logfactory;
19  
20  import java.net.URL;
21  
22  import junit.framework.Test;
23  import junit.framework.TestCase;
24  
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.commons.logging.PathableClassLoader;
27  import org.apache.commons.logging.PathableTestSuite;
28  
29  /**
30   * Verifies that by default a custom LogFactoryImpl is loaded from the
31   * TCCL class loader.
32   */
33  public class TcclEnabledTestCase extends TestCase {
34  
35      /**
36       * Return the tests included in this test suite.
37       */
38      public static Test suite() throws Exception {
39          final Class<TcclEnabledTestCase> thisClass = TcclEnabledTestCase.class;
40  
41          // Determine the URL to this .class file, so that we can then
42          // append the priority dirs to it. For tidiness, load this
43          // class through a dummy loader though this is not absolutely
44          // necessary...
45          final PathableClassLoader dummy = new PathableClassLoader(null);
46          dummy.useExplicitLoader("junit.", Test.class.getClassLoader());
47          dummy.addLogicalLib("testclasses");
48          dummy.addLogicalLib("commons-logging");
49  
50          final String thisClassPath = thisClass.getName().replace('.', '/') + ".class";
51          final URL baseUrl = dummy.findResource(thisClassPath);
52  
53          // Now set up the desired class loader hierarchy. Everything goes into
54          // the parent classpath, but we exclude the custom LogFactoryImpl
55          // class.
56          //
57          // We then create a tccl class loader that can see the custom
58          // LogFactory class. Therefore if that class can be found, then the
59          // TCCL must have been used to load it.
60          final PathableClassLoader emptyLoader = new PathableClassLoader(null);
61  
62          final PathableClassLoader parentLoader = new PathableClassLoader(null);
63          parentLoader.useExplicitLoader("junit.", Test.class.getClassLoader());
64          parentLoader.addLogicalLib("commons-logging");
65          parentLoader.addLogicalLib("testclasses");
66          // hack to ensure that the test class loader can't see
67          // the cust MyLogFactoryImpl
68          parentLoader.useExplicitLoader(
69              "org.apache.commons.logging.tccl.custom.", emptyLoader);
70  
71          final URL propsEnableUrl = new URL(baseUrl, "props_enable_tccl/");
72          parentLoader.addURL(propsEnableUrl);
73  
74          final PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader);
75          tcclLoader.addLogicalLib("testclasses");
76  
77          final Class<?> testClass = parentLoader.loadClass(thisClass.getName());
78          return new PathableTestSuite(testClass, tcclLoader);
79      }
80  
81      /**
82       * Sets up instance variables required by this test case.
83       */
84      @Override
85      public void setUp() throws Exception {
86          LogFactory.releaseAll();
87      }
88  
89      /**
90       * Tears down instance variables required by this test case.
91       */
92      @Override
93      public void tearDown() {
94          LogFactory.releaseAll();
95      }
96  
97      /**
98       * Verifies that MyLogFactoryImpl is only loadable via the tccl.
99       */
100     public void testLoader() throws Exception {
101 
102         final ClassLoader thisClassLoader = this.getClass().getClassLoader();
103         final ClassLoader tcclLoader = Thread.currentThread().getContextClassLoader();
104 
105         // the TCCL loader should NOT be the same as the loader that loaded this test class.
106         assertNotSame("tccl not same as test class loader", thisClassLoader, tcclLoader);
107 
108         // MyLogFactoryImpl should not be loadable via parent loader
109         try {
110             final Class<?> clazz = thisClassLoader.loadClass(
111                 "org.apache.commons.logging.tccl.custom.MyLogFactoryImpl");
112             fail("Unexpectedly able to load MyLogFactoryImpl via test class class loader");
113             assertNotNull(clazz); // silence warning about unused var
114         } catch (final ClassNotFoundException ex) {
115             // OK, expected
116         }
117 
118         // MyLogFactoryImpl should be loadable via TCCL loader
119         try {
120             final Class<?> clazz = tcclLoader.loadClass(
121                 "org.apache.commons.logging.tccl.custom.MyLogFactoryImpl");
122             assertNotNull(clazz);
123         } catch (final ClassNotFoundException ex) {
124             fail("Unexpectedly unable to load MyLogFactoryImpl via TCCL class loader");
125         }
126     }
127 
128     /**
129      * Verify that the custom LogFactory implementation which is only accessible
130      * via the TCCL has successfully been loaded as specified in the config file.
131      * This proves that the TCCL was used to load that class.
132      */
133     public void testTcclLoading() throws Exception {
134         final LogFactory instance = LogFactory.getFactory();
135 
136         assertEquals(
137             "Correct LogFactory loaded",
138             "org.apache.commons.logging.tccl.custom.MyLogFactoryImpl",
139             instance.getClass().getName());
140     }
141 }