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