jdk/test/java/lang/ClassLoader/GetSystemPackage.java
changeset 27348 1614e0fd2b9b
child 32230 2f44d6cdc380
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/ClassLoader/GetSystemPackage.java	Thu Nov 06 00:06:26 2014 +0100
@@ -0,0 +1,249 @@
+/*
+ * 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();
+    }
+}