1 17 package org.apache.geronimo.kernel.config; 18 19 import java.io.File ; 20 import java.io.Serializable ; 21 import java.io.InputStream ; 22 import java.io.IOException ; 23 import java.io.FileOutputStream ; 24 import java.net.URLClassLoader ; 25 import java.net.URL ; 26 import java.util.jar.JarFile ; 27 import java.util.jar.JarOutputStream ; 28 import java.util.jar.JarEntry ; 29 import java.util.Enumeration ; 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 42 public class MultiParentClassLoaderTest extends TestCase { 43 private static final String CLASS_NAME = "TestClass"; 44 private static final String ENTRY_NAME = "foo"; 45 private static final String ENTRY_VALUE = "bar"; 46 private File [] files; 47 private static final String NON_EXISTANT_RESOURCE = "non-existant-resource"; 48 private static final String NON_EXISTANT_CLASS = "NonExistant.class"; 49 private URLClassLoader [] parents; 50 private MultiParentClassLoader classLoader; 51 private static final Artifact NAME = new Artifact("test", "fake", "1.0", "car"); 52 53 57 public void testTestJars() throws Exception { 58 for (int i = 0; i < files.length; i++) { 59 File file = files[i]; 60 JarFile jarFile = new JarFile (files[i]); 61 String urlString = "jar:" + file.toURL() + "!/" + ENTRY_NAME; 62 URL url = new URL (files[i].toURL(), urlString); 63 assertStreamContains(ENTRY_VALUE + i, url.openStream()); 64 jarFile.close(); 65 66 URLClassLoader urlClassLoader = new URLClassLoader (new URL [] { file.toURL() } ); 67 Class clazz = urlClassLoader.loadClass(CLASS_NAME); 69 assertNotNull(clazz); 70 assertTrue(clazz instanceof Serializable ); 71 72 clazz = urlClassLoader.loadClass(CLASS_NAME + i); 74 assertNotNull(clazz); 75 assertTrue(clazz instanceof Serializable ); 76 77 InputStream in = urlClassLoader.getResourceAsStream(ENTRY_NAME ); 79 assertStreamContains("Should have found value from parent " + i, ENTRY_VALUE + i, in); 80 in.close(); 81 82 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 92 public void testGetName() { 93 assertEquals(NAME, classLoader.getId()); 94 } 95 96 100 public void testGetParents() { 101 ClassLoader [] 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 113 public void testLoadClass() throws Exception { 114 Class clazz = classLoader.loadClass(CLASS_NAME + 33); 116 assertNotNull(clazz); 117 assertTrue(clazz instanceof Serializable ); 118 assertEquals(classLoader, clazz.getClassLoader()); 119 120 for (int i = 0; i < parents.length; i++) { 122 URLClassLoader parent = parents[i]; 123 clazz = classLoader.loadClass(CLASS_NAME + i); 124 assertNotNull(clazz); 125 assertTrue(clazz instanceof Serializable ); 126 assertEquals(parent, clazz.getClassLoader()); 127 } 128 129 clazz = classLoader.loadClass(CLASS_NAME); 131 assertNotNull(clazz); 132 assertTrue(clazz instanceof Serializable ); 133 assertEquals(parents[0], clazz.getClassLoader()); 134 } 135 136 public void testInverseClassLoading() throws Exception { 137 File parentJar = createJarFile(0); 138 ClassLoader parentCl = new URLClassLoader (new URL []{parentJar.toURL()}); 139 File myJar = createJarFile(1); 140 ClassLoader cl = new MultiParentClassLoader(NAME, new URL []{myJar.toURL()}, parentCl); 141 Class clazz = cl.loadClass(CLASS_NAME); 142 assertSame(parentCl, clazz.getClassLoader()); 143 144 cl = new MultiParentClassLoader(NAME, new URL []{myJar.toURL()}, parentCl, true, new String [0], new String [0]); 145 clazz = cl.loadClass(CLASS_NAME); 146 assertSame(cl, clazz.getClassLoader()); 147 } 148 149 public void testHiddenClasses() throws Exception { 150 File parentJar = createJarFile(0); 151 ClassLoader parentCl = new URLClassLoader (new URL []{parentJar.toURL()}); 152 File myJar = createJarFile(1); 153 ClassLoader cl = new MultiParentClassLoader(NAME, new URL []{myJar.toURL()}, parentCl); 154 Class clazz = cl.loadClass(CLASS_NAME); 155 assertSame(parentCl, clazz.getClassLoader()); 156 157 cl = new MultiParentClassLoader(NAME, new URL []{myJar.toURL()}, parentCl, false, new String [] {CLASS_NAME}, new String [0]); 158 clazz = cl.loadClass(CLASS_NAME); 159 assertSame(cl, clazz.getClassLoader()); 160 } 161 162 public void testNonOverridableClasses() throws Exception { 163 File parentJar = createJarFile(0); 164 ClassLoader parentCl = new URLClassLoader (new URL []{parentJar.toURL()}); 165 File myJar = createJarFile(1); 166 ClassLoader cl = new MultiParentClassLoader(NAME, new URL []{myJar.toURL()}, parentCl); 167 Class clazz = cl.loadClass(CLASS_NAME); 168 assertSame(parentCl, clazz.getClassLoader()); 169 170 cl = new MultiParentClassLoader(NAME, new URL []{myJar.toURL()}, parentCl, true, new String [0], new String [] {CLASS_NAME}); 171 clazz = cl.loadClass(CLASS_NAME); 172 assertSame(parentCl, clazz.getClassLoader()); 173 } 174 175 178 public void testLoadNonExistantClass() { 179 try { 180 classLoader.loadClass(NON_EXISTANT_CLASS); 181 fail("loadClass should have thrown a ClassNotFoundException"); 182 } catch (ClassNotFoundException e) { 183 } 185 } 186 187 191 public void testGetResourceAsStream() throws Exception { 192 InputStream 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 210 public void testGetNonExistantResourceAsStream() throws Exception { 211 InputStream in = classLoader.getResourceAsStream(NON_EXISTANT_RESOURCE); 212 assertNull(in); 213 } 214 215 219 public void testGetResource() throws Exception { 220 URL 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 235 public void testGetNonExistantResource() throws Exception { 236 URL resource = classLoader.getResource(NON_EXISTANT_RESOURCE); 237 assertNull(resource); 238 } 239 240 244 public void testGetResources() throws Exception { 245 Enumeration resources = classLoader.getResources(ENTRY_NAME); 246 assertNotNull(resources); 247 assertTrue(resources.hasMoreElements()); 248 249 for (int i = 0; i < parents.length; i++) { 251 URL resource = (URL ) resources.nextElement(); 252 assertURLContains("Should have found value from parent " + i, ENTRY_VALUE + i, resource); 253 } 254 255 assertTrue(resources.hasMoreElements()); 257 URL resource = (URL ) resources.nextElement(); 258 assertURLContains("Should have found value from my file", ENTRY_VALUE + 33, resource); 259 } 260 261 264 public void testGetNonExistantResources() throws Exception { 265 Enumeration resources = classLoader.getResources(NON_EXISTANT_RESOURCE); 266 assertNotNull(resources); 267 assertFalse(resources.hasMoreElements()); 268 } 269 270 private void assertStreamContains(String expectedValue, InputStream in) throws IOException { 271 assertStreamContains(null, expectedValue, in); 272 } 273 274 private void assertStreamContains(String message, String expectedValue, InputStream in) throws IOException { 275 String entryValue; 276 try { 277 StringBuffer stringBuffer = new StringBuffer (); 278 byte[] bytes = new byte[4000]; 279 for (int count = in.read(bytes); count != -1; count = in.read(bytes)) { 280 stringBuffer.append(new String (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 message, String expectedValue, URL resource) throws IOException { 290 InputStream in; 291 assertNotNull(resource); 292 in = resource.openStream(); 293 assertStreamContains(message, expectedValue, in); 294 } 295 296 private static void assertFileExists(File file) { 297 assertTrue("File should exist: " + file, file.canRead()); 298 } 299 300 protected void setUp() throws Exception { 301 super.setUp(); 302 files = new File [3]; 303 for (int i = 0; i < files.length; i++) { 304 files[i] = createJarFile(i); 305 } 306 307 parents = new URLClassLoader [3]; 308 for (int i = 0; i < parents.length; i++) { 309 parents[i] = new URLClassLoader (new URL []{files[i].toURL()}); 310 } 311 312 File myFile = createJarFile(33); 313 classLoader = new MultiParentClassLoader(NAME, new URL []{myFile.toURL()}, parents); 314 } 315 316 private static File createJarFile(int i) throws IOException { 317 File file = File.createTempFile("test-" + i + "-", ".jar"); 318 319 FileOutputStream out = new FileOutputStream (file); 320 JarOutputStream jarOut = new JarOutputStream (out); 321 322 jarOut.putNextEntry(new JarEntry (CLASS_NAME + ".class")); 324 jarOut.write(createClass(CLASS_NAME)); 325 326 jarOut.putNextEntry(new JarEntry (CLASS_NAME + i + ".class")); 328 jarOut.write(createClass(CLASS_NAME + i)); 329 330 jarOut.putNextEntry(new JarEntry (ENTRY_NAME)); 332 jarOut.write((ENTRY_VALUE + i).getBytes()); 333 334 jarOut.putNextEntry(new JarEntry (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 name) { 346 Enhancer enhancer = new Enhancer(); 347 enhancer.setNamingPolicy(new NamingPolicy() { 348 public String getClassName(String prefix, String source, Object key, Predicate names) { 349 return name; 350 } 351 }); 352 enhancer.setClassLoader(new URLClassLoader (new URL [0])); 353 enhancer.setSuperclass(Object .class); 354 enhancer.setInterfaces(new Class []{Serializable .class}); 355 enhancer.setCallbackTypes(new Class []{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 { 365 for (int i = 0; i < files.length; i++) { 366 files[i].delete(); 367 } 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 |