// // Copyright (C) 2012 United States Government as represented by the // Administrator of the National Aeronautics and Space Administration // (NASA). All Rights Reserved. // // This software is distributed under the NASA Open Source Agreement // (NOSA), version 1.3. The NOSA has been approved by the Open Source // Initiative. See the file NOSA-1.3-JPF at the top of the distribution // directory tree for the complete NOSA document. // // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. // package gov.nasa.jpf.test.java.net; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import org.junit.Ignore; import org.junit.Test; /** * @author Nastaran Shafiei <nastaran.shafiei@gmail.com> * * test of java.lang.ClassLoader API */ public class URLClassLoaderTest extends LoadUtility { public class TestClassLoader extends URLClassLoader { public TestClassLoader(URL[] urls) { super(urls); } public TestClassLoader(URL[] urls, ClassLoader parent) { super(urls, parent); } public Class<?> findClass(String name) throws ClassNotFoundException { return super.findClass(name); } public Class<?> getLoadedClass(String name) { return findLoadedClass(name); } public Class<?> delegateTofindSystemClass(String cname) throws ClassNotFoundException { return this.findSystemClass(cname); } protected Package[] getPackages() { return super.getPackages(); } protected Package getPackage(String name) { return super.getPackage(name); } } @Test public void testConstructor_NullPointerException() { if (verifyUnhandledException("java.lang.NullPointerException")) { new URLClassLoader(null); } } @Test public void testConstructorEmptyURLs () { if (verifyNoPropertyViolation()) { URLClassLoader cl = new URLClassLoader(new URL[0]); assertNotNull(cl.getParent()); assertEquals(cl.getParent(), ClassLoader.getSystemClassLoader()); } } @Test public void testConstructorParent() { if (verifyNoPropertyViolation()) { URL[] urls = new URL[0]; ClassLoader parent = new TestClassLoader(urls); URLClassLoader cl = new URLClassLoader(urls, parent); assertNotNull(parent.getParent()); assertEquals(parent.getParent(), ClassLoader.getSystemClassLoader()); assertNotNull(cl.getParent()); assertEquals(cl.getParent(), parent); } } @Test public void testLoadClass_NoClassDefFoundError() throws ClassNotFoundException { if (verifyUnhandledException("java.lang.NoClassDefFoundError")) { URL[] urls = new URL[0]; URLClassLoader cl = new URLClassLoader(urls); cl.loadClass("java/lang/Class"); } } @Test public void testLoadClass_ClassNotFoundException() throws ClassNotFoundException { if (verifyUnhandledException("java.lang.ClassNotFoundException")) { URL[] urls = new URL[0]; URLClassLoader cl = new URLClassLoader(urls); cl.loadClass("java.lang.Does_Not_Exist"); } } @Test public void testLoadClass_ClassNotFoundException2() throws ClassNotFoundException { if (verifyUnhandledException("java.lang.ClassNotFoundException")) { URL[] urls = new URL[0]; URLClassLoader cl = new URLClassLoader(urls); cl.loadClass("java.lang.Class.class"); } } @Test public void testSystemLoaderLoadClass() throws ClassNotFoundException { if (verifyNoPropertyViolation()) { URL[] urls = new URL[0]; ClassLoader systemCl = ClassLoader.getSystemClassLoader(); ClassLoader parent = new TestClassLoader(urls); URLClassLoader cl = new URLClassLoader(urls, parent); String cname = "java.lang.Class"; Class<?> c1 = systemCl.loadClass(cname); Class<?> c2 = parent.loadClass(cname); Class<?> c3 = cl.loadClass(cname); assertSame(c1, c2); assertSame(c1, c3); // this test fails on the host VM, cause java.lang.Class is loaded by // bootstrap classloader and therefore c1.getClassLoader() returns null, // but the test passes on JPF. assertSame(c1.getClassLoader(), systemCl); } } @Test public void testFindLoadedClass() throws ClassNotFoundException, MalformedURLException { if (verifyNoPropertyViolation()) { URL[] urls = new URL[0]; TestClassLoader ucl1 = new TestClassLoader(urls); TestClassLoader ucl2 = new TestClassLoader(urls, ucl1); String cname = "java.lang.Class"; Class<?> c = ucl2.loadClass(cname); assertNotNull(c); assertEquals(c.getName(), cname); // systemClassLoader is going to be the defining classloader assertNull(ucl2.getLoadedClass(cname)); assertNull(ucl1.getLoadedClass(cname)); } } @Test public void testNonSystemLoaderLoadClass() throws MalformedURLException, ClassNotFoundException { movePkgOut(); if (verifyNoPropertyViolation()) { // create a url from a dir URL[] urls = { new URL(dirUrl) }; URLClassLoader cl = new URLClassLoader(urls); String cname = pkg + ".Class1"; Class<?> cls = cl.loadClass(cname); assertEquals(cls.getClassLoader(), cl); assertFalse(cls.getClassLoader() == ClassLoader.getSystemClassLoader()); assertEquals(cls.getInterfaces().length, 2); for(Class<?>ifc: cls.getInterfaces()) { assertEquals(cls.getClassLoader(), ifc.getClassLoader()); } // create a url from jar urls[0] = new URL(jarUrl); cl = new URLClassLoader(urls); cls = cl.loadClass(cname); assertEquals(cls.getClassLoader(), cl); assertFalse(cls.getClassLoader() == ClassLoader.getSystemClassLoader()); assertEquals(cls.getInterfaces().length, 2); for(Class<?>ifc: cls.getInterfaces()) { assertEquals(cls.getClassLoader(), ifc.getClassLoader()); } } movePkgBack(); } // @Test public void testFindResource() throws MalformedURLException { movePkgOut(); if (verifyNoPropertyViolation()) { URL[] urls = { new URL(dirUrl) }; URLClassLoader cl = new URLClassLoader(urls); String resClass1 = pkg + "/Class1.class"; URL url = cl.findResource(resClass1); String expectedUrl = dirUrl + "/" + resClass1; assertEquals(url.toString(), expectedUrl); String resInterface1 = pkg + "/Interface1.class"; url = cl.findResource(resInterface1); expectedUrl = dirUrl + "/" + resInterface1; assertEquals(url.toString(), expectedUrl); url = cl.findResource("non_existence_resource"); assertNull(url); url = cl.findResource("java/lang/Class.class"); assertNull(url); // create a url from jar urls[0] = new URL(jarUrl); cl = new URLClassLoader(urls); url = cl.findResource(resClass1); expectedUrl = jarUrl + resClass1; assertEquals(url.toString(), expectedUrl); url = cl.findResource(resInterface1); expectedUrl = jarUrl + resInterface1; assertEquals(url.toString(), expectedUrl); url = cl.findResource("non_existence_resource"); assertNull(url); url = cl.findResource("java/lang/Class.class"); assertNull(url); } movePkgBack(); } // @Test public void testFindResources() throws IOException { movePkgOut(); if (verifyNoPropertyViolation()) { URL[] urls = { new URL(dirUrl), new URL(jarUrl), new URL(jarUrl) }; URLClassLoader cl = new URLClassLoader(urls); String resource = pkg + "/Class1.class"; Enumeration<URL> e = cl.findResources(resource); List<String> urlList = new ArrayList<String>(); while(e.hasMoreElements()) { urlList.add(e.nextElement().toString()); } assertTrue(urlList.contains(jarUrl + resource)); assertTrue(urlList.contains(dirUrl + "/" + resource)); // we added the same url path twice, but findResource return value should only // include one entry for the same resource assertEquals(urlList.size(), 2); e = cl.findResources(null); assertNotNull(e); assertFalse(e.hasMoreElements()); } movePkgBack(); } @Test public void testGetURLs() throws MalformedURLException { if (verifyNoPropertyViolation()) { URL[] urls = new URL[5]; urls[0] = new URL("file://" + "/x/y/z/" ); urls[1] = new URL("file://" + "/a/b/c/" ); urls[2] = new URL("file://" + "/a/b/c/" ); urls[3] = new URL(dirUrl);; urls[4] = new URL(jarUrl); URLClassLoader cl = new URLClassLoader(urls); URL[] clUrls = cl.getURLs(); assertEquals(clUrls.length, urls.length); for (int i=0; i<urls.length; i++) { assertEquals(clUrls[i], urls[i]); } } } @Test public void testNewInstance1() throws MalformedURLException, ClassNotFoundException { movePkgOut(); if (verifyNoPropertyViolation()) { URL[] urls = new URL[1]; urls[0] = new URL(dirUrl); URLClassLoader cl = URLClassLoader.newInstance(urls); Class<?> c = cl.loadClass(pkg + ".Class1"); assertNotNull(c); assertSame(c.getClassLoader(), cl); URL resource = cl.getResource(pkg + "/Interface1.class"); assertNotNull(resource); } movePkgBack(); } @Test public void testNewInstance2() throws MalformedURLException, ClassNotFoundException { movePkgOut(); if (verifyNoPropertyViolation()) { URL[] urls = new URL[1]; urls[0] = new URL(dirUrl); URLClassLoader parent = URLClassLoader.newInstance(urls); URLClassLoader cl = URLClassLoader.newInstance(urls, parent); assertSame(parent, cl.getParent()); Class<?> c = cl.loadClass(pkg + ".Class1"); assertNotNull(c); assertSame(c.getClassLoader(), parent); String resName = pkg + "/Interface1.class"; URL resource = cl.getResource(resName); assertNotNull(resource); resource = cl.getParent().getResource(resName); assertNotNull(resource); } movePkgBack(); } public class Standard extends URLClassLoader { public Standard (URL[] urls) { super(urls); } public Standard(URL[] urls, ClassLoader parent) { super(urls, parent); } } public class Custom extends URLClassLoader { public Custom (URL[] urls) { super(urls); } public Custom(URL[] urls, ClassLoader parent) { super(urls, parent); } protected Class<?> findClass(String name) throws ClassNotFoundException { return super.findClass(name); } public Class<?> loadClass(String name) throws ClassNotFoundException { return super.loadClass(name); } } @Test public void testClassResolution() throws MalformedURLException, ClassNotFoundException { movePkgOut(); if (verifyNoPropertyViolation()) { // create a url from a dir URL[] urls = { new URL(dirUrl) }; String cname = pkg + ".Class1"; String objClass = "java.lang.Object"; Standard cl1 = new Standard(new URL[0]); Standard cl2 = new Standard(urls, cl1); Standard cl3 = new Standard(urls, cl2); Class<?> c = cl3.loadClass(cname); assertEquals(c.getClassLoader(), cl2); c = cl3.loadClass(objClass); assertEquals(c.getClassLoader(), ClassLoader.getSystemClassLoader()); Custom cl4 = new Custom(urls, null); Standard cl5 = new Standard(urls, cl4); c = cl5.loadClass(cname); // delegates to cl4 (Custom) assertEquals(c.getClassLoader(), cl4); Class<?> c4 = cl4.loadClass(cname); assertSame(c, c4); c = cl5.loadClass(objClass); assertEquals(c.getClassLoader(), ClassLoader.getSystemClassLoader()); assertSame(c, cl4.loadClass(objClass)); cl4 = new Custom(urls, cl3); cl5 = new Standard(urls, cl4); c = cl5.loadClass(cname); assertEquals(c.getClassLoader(), cl2); assertSame(c, cl4.loadClass(cname)); c = cl5.loadClass(objClass); assertEquals(c.getClassLoader(), ClassLoader.getSystemClassLoader()); assertSame(c, cl4.loadClass(objClass)); } movePkgBack(); } @Test public void testFindSystemClass() throws MalformedURLException, ClassNotFoundException { movePkgOut(); if (verifyNoPropertyViolation()) { URL[] urls = { new URL(dirUrl) }; TestClassLoader loader = new TestClassLoader(urls); assertNotNull(loader.delegateTofindSystemClass("java.lang.Class")); String cname = pkg + ".Class1"; assertNotNull(loader.loadClass(cname)); try { loader.delegateTofindSystemClass(cname); } catch(ClassNotFoundException e) { } } movePkgBack(); } @Test public void testFindSystemClass_ClassNotFoundException() throws MalformedURLException, ClassNotFoundException { movePkgOut(); if (verifyUnhandledException("java.lang.ClassNotFoundException")) { URL[] urls = { new URL(dirUrl) }; TestClassLoader cl = new TestClassLoader(urls); String cname = pkg + ".Class1"; // this should fail, cause our SystemClassLoader cannot find a non-standard // class that is not on the classpath cl.delegateTofindSystemClass(cname); } movePkgBack(); } @Test public void testGetPackages() throws ClassNotFoundException, MalformedURLException { movePkgOut(); if(verifyNoPropertyViolation()) { URL[] urls = { new URL(dirUrl) }; TestClassLoader cl = new TestClassLoader(urls); Package[] pkgs = cl.getPackages(); boolean java_lang = false; boolean classloader_specific_tests = false; for(int i=0; i<pkgs.length; i++) { if(pkgs[i].getName().equals("java.lang")) { java_lang = true; } else if(pkgs[i].getName().equals("classloader_specific_tests")) { classloader_specific_tests = true; } } assertTrue(java_lang && !classloader_specific_tests); String cname = pkg + ".Class1"; cl.loadClass(cname); pkgs = cl.getPackages(); for(int i=0; i<pkgs.length; i++) { if(pkgs[i].getName().equals("java.lang")) { java_lang = true; } else if(pkgs[i].getName().equals("classloader_specific_tests")) { classloader_specific_tests = true; } } assertTrue(java_lang && classloader_specific_tests); } movePkgBack(); } @Test public void testGetPackage() throws ClassNotFoundException, MalformedURLException { movePkgOut(); if(verifyNoPropertyViolation()) { URL[] urls = { new URL(dirUrl) }; TestClassLoader cl = new TestClassLoader(urls); assertNotNull(cl.getPackage("java.lang")); assertNull(cl.getPackage("non_existing_package")); assertNull(cl.getPackage("classloader_specific_tests")); String cname = pkg + ".Class1"; cl.loadClass(cname); assertNotNull(cl.getPackage("classloader_specific_tests")); } movePkgBack(); } @Test @Ignore // Not working because of changes in JPF_..._URLClassLoader#addURL0__Ljava_lang_String_2__V() // I have to retain the changes for jetty webapp public void testThrownException() throws ClassNotFoundException, MalformedURLException, SecurityException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { movePkgOut(); if(verifyNoPropertyViolation()) { URL[] urls = { new URL(dirUrl) }; TestClassLoader loader = new TestClassLoader(urls); String cname = pkg + ".Class1"; Class<?> c = loader.loadClass(cname); Method m = c.getMethod("causeArithmeticException", new Class<?>[0]); try { m.invoke(null, new Object[0]); fail("Should have thrown java.lang.ArithmeticException: division by zero"); } catch (InvocationTargetException ite) { Throwable cause = ite.getCause(); assertTrue( cause instanceof ArithmeticException && cause.getMessage().equals("division by zero")); } } movePkgBack(); } }