/* * Copyright (c) 1999, 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.lang.Exception; import java.lang.InterruptedException; import java.lang.Package; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.lang.Process; import java.lang.ProcessBuilder; import java.lang.RuntimeException; import java.lang.String; 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); JarBuilder manifestJar = new JarBuilder(tmpFolder, "manifest.jar", m); manifestJar.addClassFile("package2/Class2.class", testClassesDir + "/package2/Class2.class"); manifestJar.addClassFile("GetSystemPackage.class", testClassesDir + "/GetSystemPackage.class"); manifestJar.addClassFile("GetSystemPackageClassLoader.class", testClassesDir + "/GetSystemPackageClassLoader.class"); manifestJar.build(); JarBuilder noManifestJar = new JarBuilder(tmpFolder, "no-manifest.jar", null); noManifestJar.addClassFile("package2/Class2.class", testClassesDir + "/package2/Class2.class"); noManifestJar.addClassFile("GetSystemPackage.class", testClassesDir + "/GetSystemPackage.class"); noManifestJar.addClassFile("GetSystemPackageClassLoader.class", testClassesDir + "/GetSystemPackageClassLoader.class"); noManifestJar.build(); runSubProcess("Package of a system package with manifest setup could not be resolved.", "-Xbootclasspath/p:" + testClassesDir + "/manifest.jar", "GetSystemPackage", "system-manifest"); runSubProcess("System package from bootclasspath directory could not be resolved.", "-Xbootclasspath/p:" + testClassesDir, "GetSystemPackage", "system-no-manifest"); runSubProcess("System package from JAR without manifest could not be resolved.", "-Xbootclasspath/p:" + testClassesDir + "/no-manifest.jar", "GetSystemPackage", "system-no-manifest"); runSubProcess("Package not on bootclasspath could be resolved via system classpath.", "-cp", testClassesDir + "/manifest.jar", "GetSystemPackage", "non-system-manifest"); runSubProcess("Package with no manifest not on bootclasspath could be resolved via system classpath.", "-cp", testClassesDir + "/no-manifest.jar", "GetSystemPackage", "non-system-no-manifest"); } 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"); // force the use of a classloader with no parent, bypassing classpath Package pkg = c.getPackage(); GetSystemPackageClassLoader classLoader = new GetSystemPackageClassLoader(); if (isSystemPackage) { pkg = classLoader.getSystemPackage("package2"); if (pkg == null) { throw new Exception("System package could not be found via Package.getSystemPackage"); } } else if (classLoader.getSystemPackage("package2") != null) { throw new Exception("Non-system package could be found via Package.getSystemPackage"); } String specificationTitle = pkg.getSpecificationTitle(); if (!"package2".equals(pkg.getName())) { throw new Exception("Invalid package for Class2"); } if (hasManifest && (specificationTitle == null || !manifestTitle.equals(specificationTitle))) { throw new Exception("Invalid manifest for package " + pkg.getName() + ": was " + specificationTitle + " expected: Special JAR"); } if (!hasManifest && specificationTitle != null) { throw new Exception("Invalid manifest for package " + pkg.getName() + ": was " + specificationTitle + " expected: null"); } } } /* * 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(); } }