1/* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* 25 * @test 26 * @summary Test Package object is local to each ClassLoader. 27 * There can be one Package object of "foo" name defined by 28 * different class loader. 29 * @compile Foo.java 30 * @run testng GetPackages 31 */ 32 33import java.io.IOException; 34import java.io.UncheckedIOException; 35import java.nio.file.Files; 36import java.nio.file.Path; 37import java.nio.file.Paths; 38import java.util.Arrays; 39import java.lang.reflect.*; 40 41import org.testng.annotations.DataProvider; 42import org.testng.annotations.Test; 43import static org.testng.Assert.*; 44 45public class GetPackages { 46 final TestClassLoader loader; 47 final Class<?> fooClass; 48 /* 49 * Each TestClassLoader defines a "foo.Foo" class which has a unique 50 * Package object of "foo" regardless whether its ancestor class loader 51 * defines a package "foo" or not. 52 */ 53 GetPackages(TestClassLoader loader) throws ClassNotFoundException { 54 this.loader = loader; 55 this.fooClass = loader.loadClass("foo.Foo"); 56 } 57 58 /* 59 * Check package "foo" defined locally in the TestClassLoader 60 * as well as its ancestors. 61 */ 62 void checkPackage() throws ClassNotFoundException { 63 // Name of an unnamed package is empty string 64 assertEquals(this.getClass().getPackage().getName(), ""); 65 66 assertEquals(fooClass.getClassLoader(), loader); 67 68 Package p = loader.getDefinedPackage("foo"); 69 assertEquals(p.getName(), "foo"); 70 assertEquals(p, loader.getPackage("foo")); 71 72 if (loader.getParent() != null) { 73 Package p2 = ((TestClassLoader)loader.getParent()).getDefinedPackage("foo"); 74 assertTrue(p != p2); 75 } 76 77 long count = Arrays.stream(loader.getDefinedPackages()) 78 .map(Package::getName) 79 .filter(pn -> pn.equals("foo")) 80 .count(); 81 assertEquals(count, 1); 82 } 83 84 /* 85 * Check the number of package "foo" defined to this class loader and 86 * its ancestors 87 */ 88 Package[] getPackagesFromLoader() { 89 return loader.packagesInClassLoaderChain(); 90 } 91 92 /* 93 * Package.getPackages is caller-sensitve. Call through Foo class 94 * to find all Packages visible to this TestClassLoader and its ancestors 95 */ 96 Package[] getPackagesFromFoo() throws Exception { 97 Method m = fooClass.getMethod("getPackages"); 98 return (Package[])m.invoke(null); 99 } 100 101 private static long numFooPackages(Package[] pkgs) throws Exception { 102 return Arrays.stream(pkgs) 103 .filter(p -> p.getName().equals("foo")) 104 .count(); 105 } 106 107 @DataProvider(name = "loaders") 108 public static Object[][] testLoaders() { 109 TestClassLoader loader1 = new TestClassLoader(null); 110 TestClassLoader loader2 = new TestClassLoader(loader1); 111 TestClassLoader loader3 = new TestClassLoader(loader2); 112 113 // Verify the number of expected Package object of "foo" visible 114 // to the class loader 115 return new Object[][] { 116 { loader1, 1 }, 117 { loader2, 2 }, 118 { loader3, 3 } 119 }; 120 } 121 122 @Test(dataProvider = "loaders") 123 public static void test(TestClassLoader loader, long expected) throws Exception { 124 GetPackages test = new GetPackages(loader); 125 // check package "foo" existence 126 test.checkPackage(); 127 128 assertEquals(numFooPackages(test.getPackagesFromLoader()), expected); 129 assertEquals(numFooPackages(test.getPackagesFromFoo()), expected); 130 } 131} 132 133class TestClassLoader extends ClassLoader { 134 public TestClassLoader() { 135 super(); 136 } 137 138 public TestClassLoader(ClassLoader parent) { 139 super(parent); 140 } 141 142 public Package getPackage(String pn) { 143 return super.getPackage(pn); 144 } 145 146 public Package[] packagesInClassLoaderChain() { 147 return super.getPackages(); 148 } 149 150 @Override 151 protected Class<?> findClass(String name) throws ClassNotFoundException { 152 Path p = Paths.get(System.getProperty("test.classes", ".")); 153 154 try { 155 byte[] bb = Files.readAllBytes(p.resolve("foo/Foo.class")); 156 return defineClass(name, bb, 0, bb.length); 157 } catch (IOException e) { 158 throw new UncheckedIOException(e); 159 } 160 } 161 @Override 162 protected Class<?> loadClass(String cn, boolean resolve) throws ClassNotFoundException { 163 if (!cn.equals("foo.Foo")) 164 return super.loadClass(cn, resolve); 165 return findClass(cn); 166 } 167} 168