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  
21  import java.net.URL;
22  
23  import junit.framework.Test;
24  import junit.framework.TestCase;
25  
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 a commons-logging.properties file can prevent a custom
33   * LogFactoryImpl being loaded from the tccl classloader.
34   */
35  
36  public class TcclDisabledTestCase extends TestCase {
37  
38      public static final String MY_LOG_FACTORY_PKG = 
39          "org.apache.commons.logging.tccl.custom";
40  
41      public static final String MY_LOG_FACTORY_IMPL =
42          MY_LOG_FACTORY_PKG + ".MyLogFactoryImpl";
43  
44      // ------------------------------------------- JUnit Infrastructure Methods
45  
46  
47      /**
48       * Return the tests included in this test suite.
49       */
50      public static Test suite() throws Exception {
51          Class thisClass = TcclDisabledTestCase.class;
52  
53          // Determine the URL to this .class file, so that we can then
54          // append the priority dirs to it. For tidiness, load this
55          // class through a dummy loader though this is not absolutely
56          // necessary...
57          PathableClassLoader dummy = new PathableClassLoader(null);
58          dummy.useExplicitLoader("junit.", Test.class.getClassLoader());
59          dummy.addLogicalLib("testclasses");
60          dummy.addLogicalLib("commons-logging");
61          
62          String thisClassPath = thisClass.getName().replace('.', '/') + ".class";
63          URL baseUrl = dummy.findResource(thisClassPath);
64  
65          // Now set up the desired classloader hierarchy. Everything goes into
66          // the parent classpath, but we exclude the custom LogFactoryImpl
67          // class.
68          //
69          // We then create a tccl classloader that can see the custom
70          // LogFactory class. Therefore if that class can be found, then the
71          // TCCL must have been used to load it.
72          PathableClassLoader emptyLoader = new PathableClassLoader(null);
73          
74          PathableClassLoader parentLoader = new PathableClassLoader(null);
75          parentLoader.useExplicitLoader("junit.", Test.class.getClassLoader());
76          parentLoader.addLogicalLib("commons-logging");
77          parentLoader.addLogicalLib("testclasses");
78          // hack to ensure that the testcase classloader can't see
79          // the custom MyLogFactoryImpl
80          parentLoader.useExplicitLoader(
81              MY_LOG_FACTORY_PKG + ".", emptyLoader);
82          
83          URL propsEnableUrl = new URL(baseUrl, "props_disable_tccl/");
84          parentLoader.addURL(propsEnableUrl);
85  
86          PathableClassLoader tcclLoader = new PathableClassLoader(parentLoader);
87          tcclLoader.addLogicalLib("testclasses");
88  
89          Class testClass = parentLoader.loadClass(thisClass.getName());
90          return new PathableTestSuite(testClass, tcclLoader);
91      }
92  
93      /**
94       * Set up instance variables required by this test case.
95       */
96      public void setUp() throws Exception {
97          LogFactory.releaseAll();
98      }
99  
100     /**
101      * Tear down instance variables required by this test case.
102      */
103     public void tearDown() {
104         LogFactory.releaseAll();
105     }
106 
107     // ----------------------------------------------------------- Test Methods
108 
109     /**
110      * Verify that MyLogFactoryImpl is only loadable via the tccl.
111      */
112     public void testLoader() throws Exception {
113         
114         ClassLoader thisClassLoader = this.getClass().getClassLoader();
115         ClassLoader tcclLoader = Thread.currentThread().getContextClassLoader();
116 
117         // the tccl loader should NOT be the same as the loader that loaded this test class.
118         assertNotSame("tccl not same as test classloader", thisClassLoader, tcclLoader);
119 
120         // MyLogFactoryImpl should not be loadable via parent loader
121         try {
122             Class clazz = thisClassLoader.loadClass(MY_LOG_FACTORY_IMPL);
123             fail("Unexpectedly able to load MyLogFactoryImpl via test class classloader");
124             assertNotNull(clazz); // silence warning about unused var
125         } catch(ClassNotFoundException ex) {
126             // ok, expected
127         }
128         
129         // MyLogFactoryImpl should be loadable via tccl loader
130         try {
131             Class clazz = tcclLoader.loadClass(MY_LOG_FACTORY_IMPL);
132             assertNotNull(clazz);
133         } catch(ClassNotFoundException ex) {
134             fail("Unexpectedly unable to load MyLogFactoryImpl via tccl classloader");
135         }
136     }
137 
138     /**
139      * Verify that the custom LogFactory implementation which is only accessable
140      * via the TCCL has NOT been loaded. Because this is only accessable via the
141      * TCCL, and we've use a commons-logging.properties that disables TCCL loading,
142      * we should see the default LogFactoryImpl rather than the custom one.
143      */
144     public void testTcclLoading() throws Exception {
145         try {
146             LogFactory instance = LogFactory.getFactory();
147             fail("Unexpectedly succeeded in loading custom factory, though TCCL disabled.");
148             assertNotNull(instance); // silence warning about unused var
149         } catch(org.apache.commons.logging.LogConfigurationException ex) {
150             // ok, custom MyLogFactoryImpl as specified in props_disable_tccl
151             // could not be found.
152             int index = ex.getMessage().indexOf(MY_LOG_FACTORY_IMPL);
153             assertTrue("MylogFactoryImpl not found", index >= 0);
154         }
155     }
156 }