KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > logging > LoadTestCase


1 /*
2  * Copyright 2001-2005 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 package org.apache.commons.logging;
17
18 import junit.framework.TestCase;
19
20 /**
21  * testcase to emulate container and application isolated from container
22  * @author baliuka
23  * @version $Id: LoadTestCase.java 369709 2006-01-17 07:52:41Z skitching $
24  */

25 public class LoadTestCase extends TestCase{
26     //TODO: need some way to add service provider packages
27
static private String JavaDoc LOG_PCKG[] = {"org.apache.commons.logging",
28                                         "org.apache.commons.logging.impl"};
29     
30     /**
31      * A custom classloader which "duplicates" logging classes available
32      * in the parent classloader into itself.
33      * <p>
34      * When asked to load a class that is in one of the LOG_PCKG packages,
35      * it loads the class itself (child-first). This class doesn't need
36      * to be set up with a classpath, as it simply uses the same classpath
37      * as the classloader that loaded it.
38      */

39     static class AppClassLoader extends ClassLoader JavaDoc{
40         
41         java.util.Map JavaDoc classes = new java.util.HashMap JavaDoc();
42         
43         AppClassLoader(ClassLoader JavaDoc parent){
44             super(parent);
45         }
46         
47         private Class JavaDoc def(String JavaDoc name)throws ClassNotFoundException JavaDoc{
48             
49             Class JavaDoc result = (Class JavaDoc)classes.get(name);
50             if(result != null){
51                 return result;
52             }
53             
54             try{
55                 
56                 ClassLoader JavaDoc cl = this.getClass().getClassLoader();
57                 String JavaDoc classFileName = name.replace('.','/') + ".class";
58                 java.io.InputStream JavaDoc is = cl.getResourceAsStream(classFileName);
59                 java.io.ByteArrayOutputStream JavaDoc out = new java.io.ByteArrayOutputStream JavaDoc();
60                 
61                 while(is.available() > 0){
62                     out.write(is.read());
63                 }
64                 
65                 byte data [] = out.toByteArray();
66                 
67                 result = super.defineClass(name, data, 0, data.length );
68                 classes.put(name,result);
69                 
70                 return result;
71                 
72             }catch(java.io.IOException JavaDoc ioe){
73                 
74                 throw new ClassNotFoundException JavaDoc( name + " caused by "
75                 + ioe.getMessage() );
76             }
77             
78             
79         }
80         
81         // not very trivial to emulate we must implement "findClass",
82
// but it will delegete to junit class loder first
83
public Class JavaDoc loadClass(String JavaDoc name)throws ClassNotFoundException JavaDoc{
84             
85             //isolates all logging classes, application in the same classloader too.
86
//filters exeptions to simlify handling in test
87
for(int i = 0; i < LOG_PCKG.length; i++ ){
88                 if( name.startsWith( LOG_PCKG[i] ) &&
89                 name.indexOf("Exception") == -1 ){
90                     return def(name);
91                 }
92             }
93             return super.loadClass(name);
94         }
95         
96     }
97     
98
99     /**
100      * Call the static setAllowFlawedContext method on the specified class
101      * (expected to be a UserClass loaded via a custom classloader), passing
102      * it the specified state parameter.
103      */

104     private void setAllowFlawedContext(Class JavaDoc c, String JavaDoc state) throws Exception JavaDoc {
105         Class JavaDoc[] params = {String JavaDoc.class};
106         java.lang.reflect.Method JavaDoc m = c.getDeclaredMethod("setAllowFlawedContext", params);
107         m.invoke(null, new Object JavaDoc[] {state});
108     }
109
110     /**
111      * Test what happens when we play various classloader tricks like those
112      * that happen in web and j2ee containers.
113      * <p>
114      * Note that this test assumes that commons-logging.jar and log4j.jar
115      * are available via the system classpath.
116      */

117     public void testInContainer()throws Exception JavaDoc{
118         
119         //problem can be in this step (broken app container or missconfiguration)
120
//1. Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
121
//2. Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
122
// we expect this :
123
// 1. Thread.currentThread().setContextClassLoader(appLoader);
124
// 2. Thread.currentThread().setContextClassLoader(null);
125

126         // Context classloader is same as class calling into log
127
Class JavaDoc cls = reload();
128         Thread.currentThread().setContextClassLoader(cls.getClassLoader());
129         execute(cls);
130         
131         // Context classloader is the "bootclassloader". This is technically
132
// bad, but LogFactoryImpl.ALLOW_FLAWED_CONTEXT defaults to true so
133
// this test should pass.
134
cls = reload();
135         Thread.currentThread().setContextClassLoader(null);
136         execute(cls);
137         
138         // Context classloader is the "bootclassloader". This is same as above
139
// except that ALLOW_FLAWED_CONTEXT is set to false; an error should
140
// now be reported.
141
cls = reload();
142         Thread.currentThread().setContextClassLoader(null);
143         try {
144             setAllowFlawedContext(cls, "false");
145             execute(cls);
146             fail("Logging config succeeded when context classloader was null!");
147         } catch(LogConfigurationException ex) {
148             // expected; the boot classloader doesn't *have* JCL available
149
}
150         
151         // Context classloader is the system classloader.
152
//
153
// This is expected to cause problems, as LogFactoryImpl will attempt
154
// to use the system classloader to load the Log4JLogger class, which
155
// will then be unable to cast that object to the Log interface loaded
156
// via the child classloader. However as ALLOW_FLAWED_CONTEXT defaults
157
// to true this test should pass.
158
cls = reload();
159         Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
160         execute(cls);
161         
162         // Context classloader is the system classloader. This is the same
163
// as above except that ALLOW_FLAWED_CONTEXT is set to false; an error
164
// should now be reported.
165
cls = reload();
166         Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
167         try {
168             setAllowFlawedContext(cls, "false");
169             execute(cls);
170             fail("Error: somehow downcast a Logger loaded via system classloader"
171                     + " to the Log interface loaded via a custom classloader");
172         } catch(LogConfigurationException ex) {
173             // expected
174
}
175     }
176
177     /**
178      * Load class UserClass via a temporary classloader which is a child of
179      * the classloader used to load this test class.
180      */

181     private Class JavaDoc reload()throws Exception JavaDoc{
182         
183         Class JavaDoc testObjCls = null;
184         
185         AppClassLoader appLoader = new AppClassLoader(
186                 this.getClass().getClassLoader());
187         try{
188             
189             testObjCls = appLoader.loadClass(UserClass.class.getName());
190             
191         }catch(ClassNotFoundException JavaDoc cnfe){
192             throw cnfe;
193         }catch(Throwable JavaDoc t){
194             t.printStackTrace();
195             fail("AppClassLoader failed ");
196         }
197         
198         assertTrue( "app isolated" ,testObjCls.getClassLoader() == appLoader );
199         
200         
201         return testObjCls;
202         
203         
204     }
205     
206     
207     private void execute(Class JavaDoc cls)throws Exception JavaDoc{
208             
209             cls.newInstance();
210         
211     }
212     
213     
214     public static void main(String JavaDoc[] args){
215         String JavaDoc[] testCaseName = { LoadTestCase.class.getName() };
216         junit.textui.TestRunner.main(testCaseName);
217     }
218     
219     public void setUp() {
220         // save state before test starts so we can restore it when test ends
221
origContextClassLoader = Thread.currentThread().getContextClassLoader();
222     }
223     
224     public void tearDown() {
225         // restore original state so a test can't stuff up later tests.
226
Thread.currentThread().setContextClassLoader(origContextClassLoader);
227     }
228     
229     private ClassLoader JavaDoc origContextClassLoader;
230 }
231
Popular Tags