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