ClassLoaderReflectionTest.java revision f3507d0976cb14ba59e0715f22f4c6b7c97cbae8
11e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson/* 21e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * Copyright (C) 2010 The Android Open Source Project 31e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * 41e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 51e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * you may not use this file except in compliance with the License. 61e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * You may obtain a copy of the License at 71e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * 81e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 91e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * 101e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * Unless required by applicable law or agreed to in writing, software 111e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 121e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * See the License for the specific language governing permissions and 141e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * limitations under the License. 151e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson */ 161e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 171e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonpackage libcore.java.lang.reflect; 181e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 191e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.io.File; 201e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.io.IOException; 21f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilsonimport java.lang.reflect.Constructor; 22f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilsonimport java.lang.reflect.Field; 23f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilsonimport java.lang.reflect.Method; 241e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.lang.reflect.ParameterizedType; 251e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.lang.reflect.Type; 26f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilsonimport java.lang.reflect.TypeVariable; 271e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.net.MalformedURLException; 281e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.net.URL; 291e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.net.URLClassLoader; 301e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.util.ArrayList; 311e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.util.Arrays; 321e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.util.List; 33f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilsonimport java.util.concurrent.Callable; 341e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport junit.framework.TestCase; 351e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 36f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson/** 37f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson * This class creates another class loader to load multiple copies of various 38f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson * classes into the VM at once. Then it verifies that reflection resolves the 39f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson * class names using the correct class loader. 40f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson */ 411e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonpublic final class ClassLoaderReflectionTest extends TestCase { 421e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 43f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson /* 44f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson * Each of these class instances points to a different copy of the class 45f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson * than the one in the application class loader! 46f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson */ 47f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> aClass; 48f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> aListClass; 49f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> bClass; 50f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> bStringClass; 51f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> cClass; 52f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> dClass; 53f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> eClass; 54f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> fClass; 55f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 56f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson @Override protected void setUp() throws Exception { 57f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson String prefix = ClassLoaderReflectionTest.class.getName(); 58f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson ClassLoader loader = twoCopiesClassLoader(prefix, getClass().getClassLoader()); 59f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson aClass = loader.loadClass(prefix + "$A"); 60f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson bClass = loader.loadClass(prefix + "$B"); 61f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson cClass = loader.loadClass(prefix + "$C"); 62f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson dClass = loader.loadClass(prefix + "$D"); 63f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson eClass = loader.loadClass(prefix + "$E"); 64f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson fClass = loader.loadClass(prefix + "$F"); 65f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson aListClass = loader.loadClass(prefix + "$AList"); 66f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson bStringClass = loader.loadClass(prefix + "$BString"); 67f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 681e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 691e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson public void testLoadOneClassInTwoClassLoadersSimultaneously() throws Exception { 701e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson assertEquals(aClass.getName(), A.class.getName()); 711e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson assertNotSame(aClass, A.class); 721e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 731e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 74f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testField() throws Exception { 751e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson assertEquals(aClass, aListClass.getDeclaredField("field").getType()); 761e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 771e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 781e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson /** 791e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * http://code.google.com/p/android/issues/detail?id=10111 801e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson */ 81f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testGenericSuperclassParameter() throws Exception { 82f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(aListClass.getGenericSuperclass(), ArrayList.class, aClass); 831e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 841e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 85f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testGenericSuperclassRawType() throws Exception { 86f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(bStringClass.getGenericSuperclass(), bClass, String.class); 87f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 88f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 89f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testTypeParameters() throws Exception { 90f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson TypeVariable<? extends Class<?>>[] typeVariables = cClass.getTypeParameters(); 91f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(2, typeVariables.length); 92f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertTypeVariable(typeVariables[0], "K", String.class); 93f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertTypeVariable(typeVariables[1], "V", aClass); 94f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 95f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 96f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testGenericInterfaces() throws Exception { 97f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Type[] types = eClass.getGenericInterfaces(); 98f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(2, types.length); 99f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson // TODO: this test incorrectly assumes that interfaces will be returned in source order! 100f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(types[0], Callable.class, aClass); 101f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(types[1], dClass, aClass); 102f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 103f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 104f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testFieldGenericType() throws Exception { 105f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Field bString = fClass.getDeclaredField("bString"); 106f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(bString.getGenericType(), bClass, String.class); 107f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Field listA = fClass.getDeclaredField("listA"); 108f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(listA.getGenericType(), List.class, aClass); 109f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 110f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 111f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testConstructorGenericType() throws Exception { 112f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Constructor<?> constructor = fClass.getDeclaredConstructors()[0]; 113f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Type[] parameters = constructor.getGenericParameterTypes(); 114f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(parameters[0], bClass, String.class); 115f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(parameters[1], List.class, aClass); 116f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 117f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 118f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testMethodGenericReturnType() throws Exception { 119f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Method method = fClass.getDeclaredMethod("method", bClass, List.class); 120f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(method.getGenericReturnType(), bClass, String.class); 121f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 122f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 123f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testMethodGenericParameterTypes() throws Exception { 124f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Method method = fClass.getDeclaredMethod("method", bClass, List.class); 125f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Type[] types = method.getGenericParameterTypes(); 126f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(2, types.length); 127f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(types[0], bClass, String.class); 128f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(types[1], List.class, aClass); 1291e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 1301e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 1311e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson static class A {} 132f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson static class B<T> { 133f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson T field; 134f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 135f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson static class C<K extends String, V extends A> {} 136f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson interface D<T> {} 137f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson class E implements Callable<A>, D<A> { 138f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public A call() throws Exception { 139f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson return null; 140f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 141f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 142f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson class F { 143f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson B<String> bString; 144f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson List<A> listA; 145f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson F(B<String> parameter, List<A> anotherParameter) {} 146f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson B<String> method(B<String> parameter, List<A> anotherParameter) { 147f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson return null; 148f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 149f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 1501e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson static class AList extends ArrayList<A> { 1511e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson A field; 1521e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 153f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson static class BString extends B<String> {} 1541e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 1551e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson /** 1561e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * Returns a class loader that permits multiple copies of the same class to 1571e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * be loaded into the same VM at the same time. This loads classes using the 1581e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * same classpath as the application class loader. 1591e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * 1601e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * @param prefix the prefix of classes that can be loaded by both the 1611e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * returned class loader and the application class loader. 1621e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson */ 163f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private ClassLoader twoCopiesClassLoader(final String prefix, ClassLoader parent) 1641e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson throws IOException, InterruptedException { 1651e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 1661e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson /* 1671e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * To load two copies of a given class in the VM, we end up creating two 1681e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * new class loaders: a bridge class loader and a leaf class loader. 1691e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * 1701e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * The bridge class loader is a child of the application class loader. 1711e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * It never loads any classes. All it does is decide when to delegate to 1721e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * the application class loader (which has a copy of everything) and 1731e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * when to fail. 1741e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * 1751e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * The leaf class loader is a child of the bridge class loader. It 1761e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * uses the same classpath as the application class loader. It loads 1771e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * anything that its parent failed on. 1781e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson */ 1791e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 180f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson ClassLoader bridge = new ClassLoader(parent) { 1811e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson @Override protected Class<?> loadClass(String className, boolean resolve) 1821e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson throws ClassNotFoundException { 1831e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson if (className.startsWith(prefix)) { 1841e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson /* throwing will cause the child class loader to load the class. */ 1851e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson throw new ClassNotFoundException(); 1861e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } else { 1871e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson return super.loadClass(className, resolve); 1881e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 1891e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 1901e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson }; 1911e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 1921e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson try { 1931e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson // first try to create a PathClassLoader for a dalvik VM... 1941e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson String classPath = System.getProperty("java.class.path"); 1951e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson return (ClassLoader) Class.forName("dalvik.system.PathClassLoader") 1961e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson .getConstructor(String.class, ClassLoader.class) 1971e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson .newInstance(classPath, bridge); 1981e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } catch (Exception ignored) { 1991e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 2001e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 2011e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson // fall back to a URLClassLoader on a JVM 2021e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson List<URL> classpath = new ArrayList<URL>(); 2031e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson classpath.addAll(classpathToUrls("java.class.path")); 2041e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson classpath.addAll(classpathToUrls("sun.boot.class.path")); 2051e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson return new URLClassLoader(classpath.toArray(new URL[classpath.size()]), bridge); 2061e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 2071e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 2081e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson private List<URL> classpathToUrls(String propertyName) throws MalformedURLException { 2091e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson String classpath = System.getProperty(propertyName); 2101e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson List<URL> result = new ArrayList<URL>(); 2111e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson for (String pathElement : classpath.split(File.pathSeparator)) { 2121e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson result.add(new File(pathElement).toURI().toURL()); 2131e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 2141e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson return result; 2151e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 216f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 217f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private void assertParameterizedType(Type actual, Type raw, Type... args) { 218f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertTrue(actual.toString(), actual instanceof ParameterizedType); 219f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson ParameterizedType parameterizedType = (ParameterizedType) actual; 220f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(raw, parameterizedType.getRawType()); 221f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(Arrays.<Type>asList(args), 222f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Arrays.asList(parameterizedType.getActualTypeArguments())); 223f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 224f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 225f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private void assertTypeVariable(TypeVariable actual, String name, Type... bounds) { 226f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(name, actual.getName()); 227f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(Arrays.<Type>asList(bounds), Arrays.asList(actual.getBounds())); 228f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 2291e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson} 230