KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > kernel > config > MultiParentClassLoaderTest


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 package org.apache.geronimo.kernel.config;
18
19 import java.io.File JavaDoc;
20 import java.io.Serializable JavaDoc;
21 import java.io.InputStream JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.net.URLClassLoader JavaDoc;
25 import java.net.URL JavaDoc;
26 import java.util.jar.JarFile JavaDoc;
27 import java.util.jar.JarOutputStream JavaDoc;
28 import java.util.jar.JarEntry JavaDoc;
29 import java.util.Enumeration JavaDoc;
30
31 import junit.framework.TestCase;
32 import net.sf.cglib.proxy.Enhancer;
33 import net.sf.cglib.proxy.NoOp;
34 import net.sf.cglib.core.NamingPolicy;
35 import net.sf.cglib.core.Predicate;
36 import net.sf.cglib.core.DefaultGeneratorStrategy;
37 import org.apache.geronimo.kernel.repository.Artifact;
38
39 /**
40  * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
41  */

42 public class MultiParentClassLoaderTest extends TestCase {
43     private static final String JavaDoc CLASS_NAME = "TestClass";
44     private static final String JavaDoc ENTRY_NAME = "foo";
45     private static final String JavaDoc ENTRY_VALUE = "bar";
46     private File JavaDoc[] files;
47     private static final String JavaDoc NON_EXISTANT_RESOURCE = "non-existant-resource";
48     private static final String JavaDoc NON_EXISTANT_CLASS = "NonExistant.class";
49     private URLClassLoader JavaDoc[] parents;
50     private MultiParentClassLoader classLoader;
51     private static final Artifact NAME = new Artifact("test", "fake", "1.0", "car");
52
53     /**
54      * Verify that the test jars are valid
55      * @throws Exception
56      */

57     public void testTestJars() throws Exception JavaDoc {
58         for (int i = 0; i < files.length; i++) {
59             File JavaDoc file = files[i];
60             JarFile JavaDoc jarFile = new JarFile JavaDoc(files[i]);
61             String JavaDoc urlString = "jar:" + file.toURL() + "!/" + ENTRY_NAME;
62             URL JavaDoc url = new URL JavaDoc(files[i].toURL(), urlString);
63             assertStreamContains(ENTRY_VALUE + i, url.openStream());
64             jarFile.close();
65
66             URLClassLoader JavaDoc urlClassLoader = new URLClassLoader JavaDoc(new URL JavaDoc[] { file.toURL() } );
67             // clazz shared by all
68
Class JavaDoc clazz = urlClassLoader.loadClass(CLASS_NAME);
69             assertNotNull(clazz);
70             assertTrue(clazz instanceof Serializable JavaDoc);
71
72             // clazz specific to this jar
73
clazz = urlClassLoader.loadClass(CLASS_NAME + i);
74             assertNotNull(clazz);
75             assertTrue(clazz instanceof Serializable JavaDoc);
76
77             // resource shared by all jars
78
InputStream JavaDoc in = urlClassLoader.getResourceAsStream(ENTRY_NAME );
79             assertStreamContains("Should have found value from parent " + i, ENTRY_VALUE + i, in);
80             in.close();
81             
82             // resource specific to this jar
83
in = urlClassLoader.getResourceAsStream(ENTRY_NAME + i);
84             assertStreamContains("Should have found value from parent " + i, ENTRY_VALUE + i + ENTRY_VALUE, in);
85             in.close();
86         }
87     }
88
89     /**
90      * Verify the get name method returns the name provided to the constructor.
91      */

92     public void testGetName() {
93         assertEquals(NAME, classLoader.getId());
94     }
95
96     /**
97      * Verufy that the getParents method returns a different array from the one passed to the constructor and that the
98      * parents are in the same order.
99      */

100     public void testGetParents() {
101         ClassLoader JavaDoc[] actualParents = classLoader.getParents();
102         assertNotSame(parents, actualParents);
103         assertEquals(parents.length, actualParents.length);
104         for (int i = 0; i < actualParents.length; i++) {
105             assertEquals(parents[i], actualParents[i]);
106         }
107     }
108
109     /**
110      * Test loadClass loads in preference of the parents, in order, and then the local urls.
111      * @throws Exception if a problem occurs
112      */

113     public void testLoadClass() throws Exception JavaDoc {
114         // load class specific to my class loader
115
Class JavaDoc clazz = classLoader.loadClass(CLASS_NAME + 33);
116         assertNotNull(clazz);
117         assertTrue(clazz instanceof Serializable JavaDoc);
118         assertEquals(classLoader, clazz.getClassLoader());
119
120         // load class specific to each parent class loader
121
for (int i = 0; i < parents.length; i++) {
122             URLClassLoader JavaDoc parent = parents[i];
123             clazz = classLoader.loadClass(CLASS_NAME + i);
124             assertNotNull(clazz);
125             assertTrue(clazz instanceof Serializable JavaDoc);
126             assertEquals(parent, clazz.getClassLoader());
127         }
128
129         // class shared by all class loaders
130
clazz = classLoader.loadClass(CLASS_NAME);
131         assertNotNull(clazz);
132         assertTrue(clazz instanceof Serializable JavaDoc);
133         assertEquals(parents[0], clazz.getClassLoader());
134     }
135
136     public void testInverseClassLoading() throws Exception JavaDoc {
137         File JavaDoc parentJar = createJarFile(0);
138         ClassLoader JavaDoc parentCl = new URLClassLoader JavaDoc(new URL JavaDoc[]{parentJar.toURL()});
139         File JavaDoc myJar = createJarFile(1);
140         ClassLoader JavaDoc cl = new MultiParentClassLoader(NAME, new URL JavaDoc[]{myJar.toURL()}, parentCl);
141         Class JavaDoc clazz = cl.loadClass(CLASS_NAME);
142         assertSame(parentCl, clazz.getClassLoader());
143
144         cl = new MultiParentClassLoader(NAME, new URL JavaDoc[]{myJar.toURL()}, parentCl, true, new String JavaDoc[0], new String JavaDoc[0]);
145         clazz = cl.loadClass(CLASS_NAME);
146         assertSame(cl, clazz.getClassLoader());
147     }
148
149     public void testHiddenClasses() throws Exception JavaDoc {
150         File JavaDoc parentJar = createJarFile(0);
151         ClassLoader JavaDoc parentCl = new URLClassLoader JavaDoc(new URL JavaDoc[]{parentJar.toURL()});
152         File JavaDoc myJar = createJarFile(1);
153         ClassLoader JavaDoc cl = new MultiParentClassLoader(NAME, new URL JavaDoc[]{myJar.toURL()}, parentCl);
154         Class JavaDoc clazz = cl.loadClass(CLASS_NAME);
155         assertSame(parentCl, clazz.getClassLoader());
156
157         cl = new MultiParentClassLoader(NAME, new URL JavaDoc[]{myJar.toURL()}, parentCl, false, new String JavaDoc[] {CLASS_NAME}, new String JavaDoc[0]);
158         clazz = cl.loadClass(CLASS_NAME);
159         assertSame(cl, clazz.getClassLoader());
160     }
161
162     public void testNonOverridableClasses() throws Exception JavaDoc {
163         File JavaDoc parentJar = createJarFile(0);
164         ClassLoader JavaDoc parentCl = new URLClassLoader JavaDoc(new URL JavaDoc[]{parentJar.toURL()});
165         File JavaDoc myJar = createJarFile(1);
166         ClassLoader JavaDoc cl = new MultiParentClassLoader(NAME, new URL JavaDoc[]{myJar.toURL()}, parentCl);
167         Class JavaDoc clazz = cl.loadClass(CLASS_NAME);
168         assertSame(parentCl, clazz.getClassLoader());
169
170         cl = new MultiParentClassLoader(NAME, new URL JavaDoc[]{myJar.toURL()}, parentCl, true, new String JavaDoc[0], new String JavaDoc[] {CLASS_NAME});
171         clazz = cl.loadClass(CLASS_NAME);
172         assertSame(parentCl, clazz.getClassLoader());
173     }
174
175     /**
176      * Test that an attempt to load a non-existant class causes a ClassNotFoundException.
177      */

178     public void testLoadNonExistantClass() {
179         try {
180             classLoader.loadClass(NON_EXISTANT_CLASS);
181             fail("loadClass should have thrown a ClassNotFoundException");
182         } catch (ClassNotFoundException JavaDoc e) {
183             // expected
184
}
185     }
186
187     /**
188      * Test getResourceAsStream loads in preference of the parents, in order, and then the local urls.
189      * @throws Exception if a problem occurs
190      */

191     public void testGetResourceAsStream() throws Exception JavaDoc {
192         InputStream JavaDoc in = classLoader.getResourceAsStream(ENTRY_NAME + 33);
193         assertStreamContains("Should have found value from my file", ENTRY_VALUE + 33 + ENTRY_VALUE, in);
194         in.close();
195
196         for (int i = 0; i < parents.length; i++) {
197             in = classLoader.getResourceAsStream(ENTRY_NAME + i);
198             assertStreamContains("Should have found value from parent " + i, ENTRY_VALUE + i + ENTRY_VALUE, in);
199             in.close();
200         }
201
202         in = classLoader.getResourceAsStream(ENTRY_NAME);
203         assertStreamContains("Should have found value from first parent", ENTRY_VALUE + 0, in);
204         in.close();
205     }
206
207     /**
208      * Test getResourceAsStream returns null when attempt is made to loade a non-existant resource.
209      */

210     public void testGetNonExistantResourceAsStream() throws Exception JavaDoc {
211         InputStream JavaDoc in = classLoader.getResourceAsStream(NON_EXISTANT_RESOURCE);
212         assertNull(in);
213     }
214
215     /**
216      * Test getResource loads in preference of the parents, in order, and then the local urls.
217      * @throws Exception if a problem occurs
218      */

219     public void testGetResource() throws Exception JavaDoc {
220         URL JavaDoc resource = classLoader.getResource(ENTRY_NAME + 33);
221         assertURLContains("Should have found value from my file", ENTRY_VALUE + 33 + ENTRY_VALUE, resource);
222
223         for (int i = 0; i < parents.length; i++) {
224             resource = classLoader.getResource(ENTRY_NAME + i);
225             assertURLContains("Should have found value from parent " + i, ENTRY_VALUE + i + ENTRY_VALUE, resource);
226         }
227
228         resource = classLoader.getResource(ENTRY_NAME);
229         assertURLContains("Should have found value from first parent", ENTRY_VALUE + 0, resource);
230     }
231
232     /**
233      * Test getResource returns null when attempt is made to loade a non-existant resource.
234      */

235     public void testGetNonExistantResource() throws Exception JavaDoc {
236         URL JavaDoc resource = classLoader.getResource(NON_EXISTANT_RESOURCE);
237         assertNull(resource);
238     }
239
240     /**
241      * Test getResource returns an enumeration in preference of the parents, in order, and then the local urls.
242      * @throws Exception if a problem occurs
243      */

244     public void testGetResources() throws Exception JavaDoc {
245         Enumeration JavaDoc resources = classLoader.getResources(ENTRY_NAME);
246         assertNotNull(resources);
247         assertTrue(resources.hasMoreElements());
248
249         // there should be one entry for each parent
250
for (int i = 0; i < parents.length; i++) {
251             URL JavaDoc resource = (URL JavaDoc) resources.nextElement();
252             assertURLContains("Should have found value from parent " + i, ENTRY_VALUE + i, resource);
253         }
254
255         // and one entry from my url
256
assertTrue(resources.hasMoreElements());
257         URL JavaDoc resource = (URL JavaDoc) resources.nextElement();
258         assertURLContains("Should have found value from my file", ENTRY_VALUE + 33, resource);
259     }
260
261     /**
262      * Test getResources returns an empty enumeration when attempt is made to loade a non-existant resource.
263      */

264     public void testGetNonExistantResources() throws Exception JavaDoc {
265         Enumeration JavaDoc resources = classLoader.getResources(NON_EXISTANT_RESOURCE);
266         assertNotNull(resources);
267         assertFalse(resources.hasMoreElements());
268     }
269
270     private void assertStreamContains(String JavaDoc expectedValue, InputStream JavaDoc in) throws IOException JavaDoc {
271         assertStreamContains(null, expectedValue, in);
272     }
273
274     private void assertStreamContains(String JavaDoc message, String JavaDoc expectedValue, InputStream JavaDoc in) throws IOException JavaDoc {
275         String JavaDoc entryValue;
276         try {
277             StringBuffer JavaDoc stringBuffer = new StringBuffer JavaDoc();
278             byte[] bytes = new byte[4000];
279             for (int count = in.read(bytes); count != -1; count = in.read(bytes)) {
280                 stringBuffer.append(new String JavaDoc(bytes, 0, count));
281             }
282             entryValue = stringBuffer.toString();
283         } finally {
284             in.close();
285         }
286         assertEquals(message, expectedValue, entryValue);
287     }
288
289     private void assertURLContains(String JavaDoc message, String JavaDoc expectedValue, URL JavaDoc resource) throws IOException JavaDoc {
290         InputStream JavaDoc in;
291         assertNotNull(resource);
292         in = resource.openStream();
293         assertStreamContains(message, expectedValue, in);
294     }
295
296     private static void assertFileExists(File JavaDoc file) {
297         assertTrue("File should exist: " + file, file.canRead());
298     }
299
300     protected void setUp() throws Exception JavaDoc {
301         super.setUp();
302         files = new File JavaDoc[3];
303         for (int i = 0; i < files.length; i++) {
304             files[i] = createJarFile(i);
305         }
306
307         parents = new URLClassLoader JavaDoc[3];
308         for (int i = 0; i < parents.length; i++) {
309             parents[i] = new URLClassLoader JavaDoc(new URL JavaDoc[]{files[i].toURL()});
310         }
311
312         File JavaDoc myFile = createJarFile(33);
313         classLoader = new MultiParentClassLoader(NAME, new URL JavaDoc[]{myFile.toURL()}, parents);
314     }
315
316     private static File JavaDoc createJarFile(int i) throws IOException JavaDoc {
317         File JavaDoc file = File.createTempFile("test-" + i + "-", ".jar");
318
319         FileOutputStream JavaDoc out = new FileOutputStream JavaDoc(file);
320         JarOutputStream JavaDoc jarOut = new JarOutputStream JavaDoc(out);
321
322         // common class shared by everyone
323
jarOut.putNextEntry(new JarEntry JavaDoc(CLASS_NAME + ".class"));
324         jarOut.write(createClass(CLASS_NAME));
325
326         // class only available in this jar
327
jarOut.putNextEntry(new JarEntry JavaDoc(CLASS_NAME + i + ".class"));
328         jarOut.write(createClass(CLASS_NAME + i));
329
330         // common resource shared by everyone
331
jarOut.putNextEntry(new JarEntry JavaDoc(ENTRY_NAME));
332         jarOut.write((ENTRY_VALUE + i).getBytes());
333
334         // resource only available in this jar
335
jarOut.putNextEntry(new JarEntry JavaDoc(ENTRY_NAME + i));
336         jarOut.write((ENTRY_VALUE + i + ENTRY_VALUE).getBytes());
337
338         jarOut.close();
339         out.close();
340
341         assertFileExists(file);
342         return file;
343     }
344
345     private static byte[] createClass(final String JavaDoc name) {
346         Enhancer enhancer = new Enhancer();
347         enhancer.setNamingPolicy(new NamingPolicy() {
348             public String JavaDoc getClassName(String JavaDoc prefix, String JavaDoc source, Object JavaDoc key, Predicate names) {
349                 return name;
350             }
351         });
352         enhancer.setClassLoader(new URLClassLoader JavaDoc(new URL JavaDoc[0]));
353         enhancer.setSuperclass(Object JavaDoc.class);
354         enhancer.setInterfaces(new Class JavaDoc[]{Serializable JavaDoc.class});
355         enhancer.setCallbackTypes(new Class JavaDoc[]{NoOp.class});
356         enhancer.setUseFactory(false);
357         ByteCode byteCode = new ByteCode();
358         enhancer.setStrategy(byteCode);
359         enhancer.createClass();
360
361         return byteCode.getByteCode();
362     }
363
364     protected void tearDown() throws Exception JavaDoc {
365         for (int i = 0; i < files.length; i++) {
366             files[i].delete();
367 // assertFileNotExists(files[i]);
368
}
369         super.tearDown();
370     }
371
372     private static class ByteCode extends DefaultGeneratorStrategy {
373         private byte[] byteCode;
374
375         public byte[] transform(byte[] byteCode) {
376             this.byteCode = byteCode;
377             return byteCode;
378         }
379
380         public byte[] getByteCode() {
381             return byteCode;
382         }
383     }
384 }
Popular Tags