/* * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 8060130 * @library /lib/testlibrary * @build package2.Class2 GetSystemPackage jdk.testlibrary.* * @summary Test if getSystemPackage() return consistent values for cases * where a manifest is provided or not and ensure only jars on * bootclasspath gets resolved via Package.getSystemPackage * @run main GetSystemPackage */ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import jdk.testlibrary.ProcessTools; public class GetSystemPackage { static final String testClassesDir = System.getProperty("test.classes", "."); static final File tmpFolder = new File(testClassesDir); static final String manifestTitle = "Special JAR"; public static void main(String ... args) throws Exception { if (args.length == 0) { buildJarsAndInitiateSystemPackageTest(); return; } switch (args[0]) { case "system-manifest": verifyPackage(true, true); break; case "system-no-manifest": verifyPackage(false, true); break; case "non-system-manifest": verifyPackage(true, false); break; case "non-system-no-manifest": default: verifyPackage(false, false); break; } } private static void buildJarsAndInitiateSystemPackageTest() throws Exception { Manifest m = new Manifest(); // not setting MANIFEST_VERSION prevents META-INF/MANIFEST.MF from // getting written m.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); m.getMainAttributes().put(Attributes.Name.SPECIFICATION_TITLE, manifestTitle); buildJar("manifest.jar", m); buildJar("no-manifest.jar", null); runSubProcess("System package with manifest improperly resolved.", "-Xbootclasspath/p:" + testClassesDir + "/manifest.jar", "GetSystemPackage", "system-manifest"); runSubProcess("System package from directory improperly resolved.", "-Xbootclasspath/p:" + testClassesDir, "GetSystemPackage", "system-no-manifest"); runSubProcess("System package with no manifest improperly resolved", "-Xbootclasspath/p:" + testClassesDir + "/no-manifest.jar", "GetSystemPackage", "system-no-manifest"); runSubProcess("Classpath package with manifest improperly resolved", "-cp", testClassesDir + "/manifest.jar", "GetSystemPackage", "non-system-manifest"); runSubProcess("Classpath package with no manifest improperly resolved", "-cp", testClassesDir + "/no-manifest.jar", "GetSystemPackage", "non-system-no-manifest"); } private static void buildJar(String name, Manifest man) throws Exception { JarBuilder jar = new JarBuilder(tmpFolder, name, man); jar.addClassFile("package2/Class2.class", testClassesDir + "/package2/Class2.class"); jar.addClassFile("GetSystemPackage.class", testClassesDir + "/GetSystemPackage.class"); jar.addClassFile("GetSystemPackageClassLoader.class", testClassesDir + "/GetSystemPackageClassLoader.class"); jar.build(); } private static void runSubProcess(String messageOnError, String ... args) throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args); int res = pb.directory(tmpFolder).inheritIO().start().waitFor(); if (res != 0) { throw new RuntimeException(messageOnError); } } private static void verifyPackage(boolean hasManifest, boolean isSystemPackage) throws Exception { Class c = Class.forName("package2.Class2"); Package pkg = c.getPackage(); if (pkg == null || pkg != Package.getPackage("package2") || !"package2".equals(pkg.getName())) { fail("package2 not found via Package.getPackage()"); } String specificationTitle = pkg.getSpecificationTitle(); if (!"package2".equals(pkg.getName())) { fail("Invalid package for Class2"); } if (hasManifest && (specificationTitle == null || !manifestTitle.equals(specificationTitle))) { fail("Invalid manifest for package " + pkg.getName()); } if (!hasManifest && specificationTitle != null) { fail("Invalid manifest for package " + pkg.getName() + ": was " + specificationTitle + " expected: null"); } // force the use of a classloader with no parent, then retrieve the // package in a way that bypasses the classloader pkg maps GetSystemPackageClassLoader classLoader = new GetSystemPackageClassLoader(); Package systemPkg = classLoader.getSystemPackage("package2"); if (findPackage("java.lang") == null) { fail("java.lang not found via Package.getPackages()"); } Package foundPackage = findPackage("package2"); if (isSystemPackage) { if (systemPkg == null) { fail("System package could not be found via getSystemPackage"); } if (foundPackage != systemPkg || systemPkg != pkg) { fail("Inconsistent package found via Package.getPackages()"); } } else { if (systemPkg != null) { fail("Non-system package could be found via getSystemPackage"); } if (foundPackage == null) { fail("Non-system package not found via Package.getPackages()"); } } } private static Package findPackage(String name) { Package[] packages = Package.getPackages(); for (Package p : packages) { System.out.println(p); if (p.getName().equals(name)) { return p; } } return null; } private static void fail(String message) { throw new RuntimeException(message); } } /* * This classloader bypasses the system classloader to give as direct access * to Package.getSystemPackage() as possible */ class GetSystemPackageClassLoader extends ClassLoader { public GetSystemPackageClassLoader() { super(null); } public Package getSystemPackage(String name) { return super.getPackage(name); } } /* * Helper class for building jar files */ class JarBuilder { private JarOutputStream os; public JarBuilder(File tmpFolder, String jarName, Manifest manifest) throws FileNotFoundException, IOException { File jarFile = new File(tmpFolder, jarName); if (manifest != null) { this.os = new JarOutputStream(new FileOutputStream(jarFile), manifest); } else { this.os = new JarOutputStream(new FileOutputStream(jarFile)); } } public void addClassFile(String pathFromRoot, String file) throws IOException { byte[] buf = new byte[1024]; try (FileInputStream in = new FileInputStream(file)) { JarEntry entry = new JarEntry(pathFromRoot); os.putNextEntry(entry); int len; while ((len = in.read(buf)) > 0) { os.write(buf, 0, len); } os.closeEntry(); } } public void build() throws IOException { os.close(); } }