GetSystemPackage.java revision 15491:6f390eafc676
1/*
2 * Copyright (c) 2014, 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 * @bug 8060130
27 * @library /lib/testlibrary
28 * @build package2.Class2 GetSystemPackage jdk.testlibrary.*
29 * @summary Test if getSystemPackage() return consistent values for cases
30 *          where a manifest is provided or not and ensure only jars on
31 *          bootclasspath gets resolved via Package.getSystemPackage
32 * @run main GetSystemPackage
33 */
34
35import java.io.File;
36import java.io.FileInputStream;
37import java.io.FileNotFoundException;
38import java.io.FileOutputStream;
39import java.io.IOException;
40import java.util.jar.Attributes;
41import java.util.jar.JarEntry;
42import java.util.jar.JarOutputStream;
43import java.util.jar.Manifest;
44import jdk.testlibrary.ProcessTools;
45
46public class GetSystemPackage {
47
48    static final String testClassesDir = System.getProperty("test.classes", ".");
49    static final File tmpFolder = new File(testClassesDir);
50    static final String manifestTitle = "Special JAR";
51
52    public static void main(String ... args) throws Exception {
53        if (args.length == 0) {
54            buildJarsAndInitiateSystemPackageTest();
55            return;
56        }
57        switch (args[0]) {
58            case "system-manifest":
59                verifyPackage(true, true);
60                break;
61            case "system-no-manifest":
62                verifyPackage(false, true);
63                break;
64            case "non-system-manifest":
65                verifyPackage(true, false);
66                break;
67            case "non-system-no-manifest":
68            default:
69                verifyPackage(false, false);
70                break;
71        }
72    }
73
74    private static void buildJarsAndInitiateSystemPackageTest()
75            throws Exception
76    {
77        Manifest m = new Manifest();
78        // not setting MANIFEST_VERSION prevents META-INF/MANIFEST.MF from
79        // getting written
80        m.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
81        m.getMainAttributes().put(Attributes.Name.SPECIFICATION_TITLE,
82                                  manifestTitle);
83
84        buildJar("manifest.jar", m);
85        buildJar("no-manifest.jar", null);
86
87        runSubProcess("System package with manifest improperly resolved.",
88                "-Xbootclasspath/a:" + testClassesDir + "/manifest.jar",
89                "GetSystemPackage", "system-manifest");
90
91        runSubProcess("System package from directory improperly resolved.",
92                "-Xbootclasspath/a:" + testClassesDir, "GetSystemPackage",
93                "system-no-manifest");
94
95        runSubProcess("System package with no manifest improperly resolved",
96                "-Xbootclasspath/a:" + testClassesDir + "/no-manifest.jar",
97                "GetSystemPackage", "system-no-manifest");
98
99        runSubProcess("Classpath package with manifest improperly resolved",
100                "-cp", testClassesDir + "/manifest.jar", "GetSystemPackage",
101                "non-system-manifest");
102
103        runSubProcess("Classpath package with no manifest improperly resolved",
104                "-cp", testClassesDir + "/no-manifest.jar", "GetSystemPackage",
105                "non-system-no-manifest");
106
107    }
108
109    private static void buildJar(String name, Manifest man) throws Exception {
110        JarBuilder jar = new JarBuilder(tmpFolder, name, man);
111        jar.addClassFile("package2/Class2.class",
112                testClassesDir + "/package2/Class2.class");
113        jar.addClassFile("GetSystemPackage.class",
114                testClassesDir + "/GetSystemPackage.class");
115        jar.build();
116    }
117
118    private static void runSubProcess(String messageOnError, String ... args)
119            throws Exception
120    {
121        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
122        int res = pb.directory(tmpFolder).inheritIO().start().waitFor();
123        if (res != 0) {
124            throw new RuntimeException(messageOnError);
125        }
126    }
127
128    private static void verifyPackage(boolean hasManifest,
129                                      boolean isSystemPackage)
130            throws Exception
131    {
132        Class<?> c = Class.forName("package2.Class2");
133        Package pkg = c.getPackage();
134        if (pkg == null || pkg != Package.getPackage("package2") ||
135                !"package2".equals(pkg.getName())) {
136            fail("package2 not found via Package.getPackage()");
137        }
138
139        String specificationTitle = pkg.getSpecificationTitle();
140        if (!"package2".equals(pkg.getName())) {
141            fail("Invalid package for Class2");
142        }
143
144        if (hasManifest && (specificationTitle == null
145                || !manifestTitle.equals(specificationTitle))) {
146            fail("Invalid manifest for package " + pkg.getName());
147        }
148        if (!hasManifest && specificationTitle != null) {
149            fail("Invalid manifest for package " + pkg.getName() + ": was " +
150                    specificationTitle + " expected: null");
151        }
152
153        ClassLoader ld = c.getClassLoader();
154        Package systemPkg = ld != null ? null : Package.getPackage("package2");
155
156        if (findPackage("java.lang") == null) {
157            fail("java.lang not found via Package.getPackages()");
158        }
159        Package foundPackage = findPackage("package2");
160        if (isSystemPackage) {
161            if (systemPkg == null) {
162                fail("System package could not be found via getSystemPackage");
163            }
164            if (foundPackage != systemPkg || systemPkg != pkg) {
165                fail("Inconsistent package found via Package.getPackages()");
166            }
167        } else {
168            if (systemPkg != null) {
169                fail("Non-system package could be found via getSystemPackage");
170            }
171            if (foundPackage == null) {
172                fail("Non-system package not found via Package.getPackages()");
173            }
174        }
175    }
176
177    private static Package findPackage(String name) {
178        Package[] packages = Package.getPackages();
179        for (Package p : packages) {
180            if (p.getName().equals(name)) {
181                return p;
182            }
183        }
184        return null;
185    }
186
187    private static void fail(String message) {
188        throw new RuntimeException(message);
189    }
190}
191
192/*
193 * Helper class for building jar files
194 */
195class JarBuilder {
196
197    private JarOutputStream os;
198
199    public JarBuilder(File tmpFolder, String jarName, Manifest manifest)
200            throws FileNotFoundException, IOException
201    {
202        File jarFile = new File(tmpFolder, jarName);
203        if (manifest != null) {
204            this.os = new JarOutputStream(new FileOutputStream(jarFile),
205                                          manifest);
206        } else {
207            this.os = new JarOutputStream(new FileOutputStream(jarFile));
208        }
209    }
210
211    public void addClassFile(String pathFromRoot, String file)
212            throws IOException
213    {
214        byte[] buf = new byte[1024];
215        try (FileInputStream in = new FileInputStream(file)) {
216            JarEntry entry = new JarEntry(pathFromRoot);
217            os.putNextEntry(entry);
218            int len;
219            while ((len = in.read(buf)) > 0) {
220                os.write(buf, 0, len);
221            }
222            os.closeEntry();
223        }
224    }
225
226    public void build() throws IOException {
227        os.close();
228    }
229}
230