KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > logging > pathable > ChildFirstTestCase


1 /*
2  * Copyright 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.pathable;
17
18 import java.net.URL JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Arrays JavaDoc;
21 import java.util.Enumeration JavaDoc;
22
23 import junit.framework.Test;
24 import junit.framework.TestCase;
25
26 import org.apache.commons.logging.PathableClassLoader;
27 import org.apache.commons.logging.PathableTestSuite;
28
29 /**
30  * Tests for the PathableTestSuite and PathableClassLoader functionality,
31  * where lookup order for the PathableClassLoader is child-first.
32  * <p>
33  * These tests assume:
34  * <ul>
35  * <li>junit is in system classpath
36  * <li>nothing else is in system classpath
37  * </ul>
38  */

39
40 public class ChildFirstTestCase extends TestCase {
41     
42     /**
43      * Set up a custom classloader hierarchy for this test case.
44      * The hierarchy is:
45      * <ul>
46      * <li> contextloader: child-first.
47      * <li> childloader: child-first, used to load test case.
48      * <li> parentloader: child-first, parent is the bootclassloader.
49      * </ul>
50      */

51     public static Test suite() throws Exception JavaDoc {
52         Class JavaDoc thisClass = ChildFirstTestCase.class;
53         ClassLoader JavaDoc thisClassLoader = thisClass.getClassLoader();
54         
55         // Make the parent a direct child of the bootloader to hide all
56
// other classes in the system classpath
57
PathableClassLoader parent = new PathableClassLoader(null);
58         parent.setParentFirst(false);
59         
60         // Make the junit classes visible as a special case, as junit
61
// won't be able to call this class at all without this. The
62
// junit classes must be visible from the classloader that loaded
63
// this class, so use that as the source for future access to classes
64
// from the junit package.
65
parent.useExplicitLoader("junit.", thisClassLoader);
66         
67         // Make the commons-logging.jar classes visible via the parent
68
parent.addLogicalLib("commons-logging");
69         
70         // Create a child classloader to load the test case through
71
PathableClassLoader child = new PathableClassLoader(parent);
72         child.setParentFirst(false);
73         
74         // Obviously, the child classloader needs to have the test classes
75
// in its path!
76
child.addLogicalLib("testclasses");
77         child.addLogicalLib("commons-logging-adapters");
78         
79         // Create a third classloader to be the context classloader.
80
PathableClassLoader context = new PathableClassLoader(child);
81         context.setParentFirst(false);
82
83         // reload this class via the child classloader
84
Class JavaDoc testClass = child.loadClass(thisClass.getName());
85         
86         // and return our custom TestSuite class
87
return new PathableTestSuite(testClass, context);
88     }
89     
90     /**
91      * Test that the classloader hierarchy is as expected, and that
92      * calling loadClass() on various classloaders works as expected.
93      * Note that for this test case, parent-first classloading is
94      * in effect.
95      */

96     public void testPaths() throws Exception JavaDoc {
97         // the context classloader is not expected to be null
98
ClassLoader JavaDoc contextLoader = Thread.currentThread().getContextClassLoader();
99         assertNotNull("Context classloader is null", contextLoader);
100         assertEquals("Context classloader has unexpected type",
101                 PathableClassLoader.class.getName(),
102                 contextLoader.getClass().getName());
103         
104         // the classloader that loaded this class is obviously not null
105
ClassLoader JavaDoc thisLoader = this.getClass().getClassLoader();
106         assertNotNull("thisLoader is null", thisLoader);
107         assertEquals("thisLoader has unexpected type",
108                 PathableClassLoader.class.getName(),
109                 thisLoader.getClass().getName());
110         
111         // the suite method specified that the context classloader's parent
112
// is the loader that loaded this test case.
113
assertSame("Context classloader is not child of thisLoader",
114                 thisLoader, contextLoader.getParent());
115
116         // thisLoader's parent should be available
117
ClassLoader JavaDoc parentLoader = thisLoader.getParent();
118         assertNotNull("Parent classloader is null", parentLoader);
119         assertEquals("Parent classloader has unexpected type",
120                 PathableClassLoader.class.getName(),
121                 parentLoader.getClass().getName());
122         
123         // parent should have a parent of null
124
assertNull("Parent classloader has non-null parent", parentLoader.getParent());
125
126         // getSystemClassloader is not a PathableClassLoader; it's of a
127
// built-in type. This also verifies that system classloader is none of
128
// (context, child, parent).
129
ClassLoader JavaDoc systemLoader = ClassLoader.getSystemClassLoader();
130         assertNotNull("System classloader is null", systemLoader);
131         assertFalse("System classloader has unexpected type",
132                 PathableClassLoader.class.getName().equals(
133                         systemLoader.getClass().getName()));
134
135         // junit classes should be visible; their classloader is system.
136
// this will of course throw an exception if not found.
137
Class JavaDoc junitTest = contextLoader.loadClass("junit.framework.Test");
138         assertSame("Junit not loaded via systemloader",
139                 systemLoader, junitTest.getClassLoader());
140
141         // jcl api classes should be visible only via the parent
142
Class JavaDoc logClass = contextLoader.loadClass("org.apache.commons.logging.Log");
143         assertSame("Log class not loaded via parent",
144                 logClass.getClassLoader(), parentLoader);
145
146         // jcl adapter classes should be visible via both parent and child. However
147
// as the classloaders are child-first we should see the child one.
148
Class JavaDoc log4jClass = contextLoader.loadClass("org.apache.commons.logging.impl.Log4JLogger");
149         assertSame("Log4JLogger not loaded via child",
150                 log4jClass.getClassLoader(), thisLoader);
151         
152         // test classes should be visible via the child only
153
Class JavaDoc testClass = contextLoader.loadClass("org.apache.commons.logging.PathableTestSuite");
154         assertSame("PathableTestSuite not loaded via child",
155                 testClass.getClassLoader(), thisLoader);
156         
157         // test loading of class that is not available
158
try {
159             Class JavaDoc noSuchClass = contextLoader.loadClass("no.such.class");
160             fail("Class no.such.class is unexpectedly available");
161         } catch(ClassNotFoundException JavaDoc ex) {
162             // ok
163
}
164
165         // String class classloader is null
166
Class JavaDoc stringClass = contextLoader.loadClass("java.lang.String");
167         assertNull("String class classloader is not null!",
168                 stringClass.getClassLoader());
169     }
170     
171     /**
172      * Test that the various flavours of ClassLoader.getResource work as expected.
173      */

174     public void testResource() {
175         URL JavaDoc resource;
176         
177         ClassLoader JavaDoc contextLoader = Thread.currentThread().getContextClassLoader();
178         ClassLoader JavaDoc childLoader = contextLoader.getParent();
179         
180         // getResource where it doesn't exist
181
resource = childLoader.getResource("nosuchfile");
182         assertNull("Non-null URL returned for invalid resource name", resource);
183
184         // getResource where it is accessable only to parent classloader
185
resource = childLoader.getResource("org/apache/commons/logging/Log.class");
186         assertNotNull("Unable to locate Log.class resource", resource);
187         
188         // getResource where it is accessable only to child classloader
189
resource = childLoader.getResource("org/apache/commons/logging/PathableTestSuite.class");
190         assertNotNull("Unable to locate PathableTestSuite.class resource", resource);
191
192         // getResource where it is accessable to both classloaders. The one visible
193
// to the child should be returned. The URL returned will be of form
194
// jar:file:/x/y.jar!path/to/resource. The filename part should include the jarname
195
// of form commons-logging-adapters-nnnn.jar, not commons-logging-nnnn.jar
196
resource = childLoader.getResource("org/apache/commons/logging/impl/Log4JLogger.class");
197         assertNotNull("Unable to locate Log4JLogger.class resource", resource);
198         assertTrue("Incorrect source for Log4JLogger class",
199                 resource.toString().indexOf("/commons-logging-adapters-1.") > 0);
200     }
201     
202     /**
203      * Test that the various flavours of ClassLoader.getResources work as expected.
204      */

205     public void testResources() throws Exception JavaDoc {
206         Enumeration JavaDoc resources;
207         URL JavaDoc[] urls;
208         
209         // verify the classloader hierarchy
210
ClassLoader JavaDoc contextLoader = Thread.currentThread().getContextClassLoader();
211         ClassLoader JavaDoc childLoader = contextLoader.getParent();
212         ClassLoader JavaDoc parentLoader = childLoader.getParent();
213         ClassLoader JavaDoc bootLoader = parentLoader.getParent();
214         assertNull("Unexpected classloader hierarchy", bootLoader);
215         
216         // getResources where no instances exist
217
resources = childLoader.getResources("nosuchfile");
218         urls = toURLArray(resources);
219         assertEquals("Non-null URL returned for invalid resource name", 0, urls.length);
220         
221         // getResources where the resource only exists in the parent
222
resources = childLoader.getResources("org/apache/commons/logging/Log.class");
223         urls = toURLArray(resources);
224         assertEquals("Unexpected number of Log.class resources found", 1, urls.length);
225         
226         // getResources where the resource only exists in the child
227
resources = childLoader.getResources("org/apache/commons/logging/PathableTestSuite.class");
228         urls = toURLArray(resources);
229         assertEquals("Unexpected number of PathableTestSuite.class resources found", 1, urls.length);
230         
231         // getResources where the resource exists in both.
232
// resources should be returned in order (child-resource, parent-resource).
233
//
234
// IMPORTANT: due to the fact that in java 1.4 and earlier method
235
// ClassLoader.getResources is final it isn't possible for PathableClassLoader
236
// to override this. So even when child-first is enabled the resource order
237
// is still (parent-resources, child-resources). This test verifies the expected
238
// behaviour - even though it's not the desired behaviour.
239

240         resources = childLoader.getResources("org/apache/commons/logging/impl/Log4JLogger.class");
241         urls = toURLArray(resources);
242         assertEquals("Unexpected number of Log4JLogger.class resources found", 2, urls.length);
243         
244         // There is no gaurantee about the ordering of results returned from getResources
245
// To make this test portable across JVMs, sort the string to give them a known order
246
String JavaDoc[] urlsToStrings = new String JavaDoc[2];
247         urlsToStrings[0] = urls[0].toString();
248         urlsToStrings[1] = urls[1].toString();
249         Arrays.sort(urlsToStrings);
250         assertTrue("Incorrect source for Log4JLogger class",
251                 urlsToStrings[0].indexOf("/commons-logging-1.") > 0);
252         assertTrue("Incorrect source for Log4JLogger class",
253                 urlsToStrings[1].indexOf("/commons-logging-adapters-1.") > 0);
254     }
255
256     /**
257      * Utility method to convert an enumeration-of-URLs into an array of URLs.
258      */

259     private static URL JavaDoc[] toURLArray(Enumeration JavaDoc e) {
260         ArrayList JavaDoc l = new ArrayList JavaDoc();
261         while (e.hasMoreElements()) {
262             URL JavaDoc u = (URL JavaDoc) e.nextElement();
263             l.add(u);
264         }
265         URL JavaDoc[] tmp = new URL JavaDoc[l.size()];
266         return (URL JavaDoc[]) l.toArray(tmp);
267     }
268
269     /**
270      * Test that getResourceAsStream works.
271      */

272     public void testResourceAsStream() throws Exception JavaDoc {
273         java.io.InputStream JavaDoc is;
274         
275         // verify the classloader hierarchy
276
ClassLoader JavaDoc contextLoader = Thread.currentThread().getContextClassLoader();
277         ClassLoader JavaDoc childLoader = contextLoader.getParent();
278         ClassLoader JavaDoc parentLoader = childLoader.getParent();
279         ClassLoader JavaDoc bootLoader = parentLoader.getParent();
280         assertNull("Unexpected classloader hierarchy", bootLoader);
281         
282         // getResourceAsStream where no instances exist
283
is = childLoader.getResourceAsStream("nosuchfile");
284         assertNull("Invalid resource returned non-null stream", is);
285         
286         // getResourceAsStream where resource does exist
287
is = childLoader.getResourceAsStream("org/apache/commons/logging/Log.class");
288         assertNotNull("Null returned for valid resource", is);
289         is.close();
290         
291         // It would be nice to test parent-first ordering here, but that would require
292
// having a resource with the same name in both the parent and child loaders,
293
// but with different contents. That's a little tricky to set up so we'll
294
// skip that for now.
295
}
296 }
297
Popular Tags