1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
27 static private String 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{
40
41 java.util.Map classes = new java.util.HashMap();
42
43 AppClassLoader(ClassLoader parent){
44 super(parent);
45 }
46
47 private Class def(String name)throws ClassNotFoundException{
48
49 Class result = (Class)classes.get(name);
50 if(result != null){
51 return result;
52 }
53
54 try{
55
56 ClassLoader cl = this.getClass().getClassLoader();
57 String classFileName = name.replace('.','/') + ".class";
58 java.io.InputStream is = cl.getResourceAsStream(classFileName);
59 java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
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 ioe){
73
74 throw new ClassNotFoundException( name + " caused by "
75 + ioe.getMessage() );
76 }
77
78
79 }
80
81
82
83 public Class loadClass(String name)throws ClassNotFoundException{
84
85
86
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 c, String state) throws Exception {
105 Class[] params = {String.class};
106 java.lang.reflect.Method m = c.getDeclaredMethod("setAllowFlawedContext", params);
107 m.invoke(null, new Object[] {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{
118
119
120
121
122
123
124
125
126
127 Class cls = reload();
128 Thread.currentThread().setContextClassLoader(cls.getClassLoader());
129 execute(cls);
130
131
132
133
134 cls = reload();
135 Thread.currentThread().setContextClassLoader(null);
136 execute(cls);
137
138
139
140
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
149 }
150
151
152
153
154
155
156
157
158 cls = reload();
159 Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
160 execute(cls);
161
162
163
164
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
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 reload()throws Exception{
182
183 Class 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 cnfe){
192 throw cnfe;
193 }catch(Throwable 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 cls)throws Exception{
208
209 cls.newInstance();
210
211 }
212
213
214 public static void main(String[] args){
215 String[] testCaseName = { LoadTestCase.class.getName() };
216 junit.textui.TestRunner.main(testCaseName);
217 }
218
219 public void setUp() {
220
221 origContextClassLoader = Thread.currentThread().getContextClassLoader();
222 }
223
224 public void tearDown() {
225
226 Thread.currentThread().setContextClassLoader(origContextClassLoader);
227 }
228
229 private ClassLoader origContextClassLoader;
230 }