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 exclude VM plugin
27 * @author Jean-Francois Denise
28 * @modules jdk.jlink/jdk.tools.jlink.internal
29 *          jdk.jlink/jdk.tools.jlink.internal.plugins
30 *          jdk.jlink/jdk.tools.jlink.plugin
31 * @run main ExcludeVMPluginTest
32 */
33import java.io.ByteArrayInputStream;
34import java.net.URI;
35import java.nio.file.Path;
36import java.nio.file.Paths;
37import java.util.HashMap;
38import java.util.Map;
39import jdk.tools.jlink.internal.ResourcePoolManager;
40
41import jdk.tools.jlink.internal.plugins.ExcludeVMPlugin;
42import jdk.tools.jlink.plugin.Plugin;
43import jdk.tools.jlink.plugin.ResourcePool;
44import jdk.tools.jlink.plugin.ResourcePoolEntry;
45
46public class ExcludeVMPluginTest {
47
48    private static final String TAG = "# orig in test\n";
49
50    private static final String[] ARCHITECTURES = {"/", "/amd64/", "/i386/", "/arm/",
51        "/aarch64/", "/toto/"};
52
53    private static final String[] CLIENT = {"client/" + jvmlib(),};
54    private static final String[] SERVER = {"server/" + jvmlib()};
55    private static final String[] MINIMAL = {"minimal/" + jvmlib()};
56    private static final String[] ALL = {CLIENT[0], SERVER[0], MINIMAL[0]};
57    private static final String JVM_CFG_ALL = TAG + "-server KNOWN\n-client KNOWN\n-minimal KNOWN\n";
58    private static final String JVM_CFG_CLIENT = TAG + "-client KNOWN\n";
59    private static final String JVM_CFG_SERVER = TAG + "-server KNOWN\n";
60    private static final String JVM_CFG_SERVER_ALIAS_OTHERS = TAG + "-server KNOWN\n-client ALIASED_TO -server\n-minimal ALIASED_TO -server\n";
61    private static final String JVM_CFG_CLIENT_ALIAS_OTHERS = TAG + "-client KNOWN\n-server ALIASED_TO -client\n-minimal ALIASED_TO -client\n";
62    private static final String JVM_CFG_MINIMAL_ALIAS_OTHERS = TAG + "-minimal KNOWN\n-server ALIASED_TO -minimal\n-client ALIASED_TO -minimal\n";
63    private static final String JVM_CFG_MINIMAL = TAG + "-minimal KNOWN\n";
64
65    public static void main(String[] args) throws Exception {
66        new ExcludeVMPluginTest().test();
67    }
68
69    public void test() throws Exception {
70        boolean failed = false;
71
72        try {
73            checkVM("toto", ALL, JVM_CFG_ALL, ALL, JVM_CFG_ALL);
74            failed = true;
75            throw new Exception("Should have failed");
76        } catch (Exception ex) {
77            if (failed) {
78                throw ex;
79            }
80        }
81
82        checkVM("all", ALL, JVM_CFG_ALL, ALL, JVM_CFG_ALL);
83        checkVM("all", CLIENT, JVM_CFG_CLIENT, CLIENT, JVM_CFG_CLIENT);
84        checkVM("all", SERVER, JVM_CFG_SERVER, SERVER, JVM_CFG_SERVER);
85        checkVM("all", MINIMAL, JVM_CFG_MINIMAL, MINIMAL, JVM_CFG_MINIMAL);
86
87        checkVM("server", ALL, JVM_CFG_ALL, SERVER, JVM_CFG_SERVER_ALIAS_OTHERS);
88        checkVM("server", SERVER, JVM_CFG_SERVER, SERVER, JVM_CFG_SERVER);
89        try {
90            checkVM("server", CLIENT, JVM_CFG_CLIENT, SERVER, JVM_CFG_SERVER);
91            failed = true;
92            throw new Exception("Should have failed");
93        } catch (Exception ex) {
94            if (failed) {
95                throw ex;
96            }
97        }
98        try {
99            checkVM("server", MINIMAL, JVM_CFG_MINIMAL, SERVER, JVM_CFG_SERVER);
100            failed = true;
101            throw new Exception("Should have failed");
102        } catch (Exception ex) {
103            if (failed) {
104                throw ex;
105            }
106        }
107
108        checkVM("client", ALL, JVM_CFG_ALL, CLIENT, JVM_CFG_CLIENT_ALIAS_OTHERS);
109        checkVM("client", CLIENT, JVM_CFG_CLIENT, CLIENT, JVM_CFG_CLIENT);
110        try {
111            checkVM("client", SERVER, JVM_CFG_SERVER, CLIENT, JVM_CFG_CLIENT);
112            failed = true;
113            throw new Exception("Should have failed");
114        } catch (Exception ex) {
115            if (failed) {
116                throw ex;
117            }
118        }
119        try {
120            checkVM("client", MINIMAL, JVM_CFG_MINIMAL, CLIENT, JVM_CFG_CLIENT);
121            failed = true;
122            throw new Exception("Should have failed");
123        } catch (Exception ex) {
124            if (failed) {
125                throw ex;
126            }
127        }
128
129        checkVM("minimal", ALL, JVM_CFG_ALL, MINIMAL, JVM_CFG_MINIMAL_ALIAS_OTHERS);
130        checkVM("minimal", MINIMAL, JVM_CFG_MINIMAL, MINIMAL, JVM_CFG_MINIMAL);
131        try {
132            checkVM("minimal", SERVER, JVM_CFG_SERVER, MINIMAL, JVM_CFG_MINIMAL);
133            failed = true;
134            throw new Exception("Should have failed");
135        } catch (Exception ex) {
136            if (failed) {
137                throw ex;
138            }
139        }
140        try {
141            checkVM("minimal", CLIENT, JVM_CFG_CLIENT, MINIMAL, JVM_CFG_MINIMAL);
142            failed = true;
143            throw new Exception("Should have failed");
144        } catch (Exception ex) {
145            if (failed) {
146                throw ex;
147            }
148        }
149
150    }
151
152    public void checkVM(String vm, String[] input, String jvmcfg, String[] expectedOutput, String expectdJvmCfg) throws Exception {
153
154        for (String arch : ARCHITECTURES) {
155            String[] winput = new String[input.length];
156            String[] woutput = new String[expectedOutput.length];
157            for (int i = 0; i < input.length; i++) {
158                winput[i] = "/java.base/lib" + arch + input[i];
159            }
160            for (int i = 0; i < expectedOutput.length; i++) {
161                woutput[i] = "/java.base/lib" + arch + expectedOutput[i];
162            }
163            doCheckVM(vm, winput, jvmcfg, woutput, expectdJvmCfg);
164        }
165    }
166
167    private void doCheckVM(String vm, String[] input, String jvmcfg, String[] expectedOutput, String expectdJvmCfg) throws Exception {
168        // Create a pool with jvm.cfg and the input paths.
169        byte[] jvmcfgContent = jvmcfg.getBytes();
170        ResourcePoolManager poolMgr = new ResourcePoolManager();
171        poolMgr.add(
172            ResourcePoolEntry.create("/java.base/lib/jvm.cfg",
173                ResourcePoolEntry.Type.NATIVE_LIB, jvmcfgContent));
174
175        // java.base/module-info.class is used by exclude vm plugin
176        // to get current osName(). We read it from jrt-fs and add a
177        // ResourcePoolEntry
178        poolMgr.add(
179            ResourcePoolEntry.create("/java.base/module-info.class",
180                ResourcePoolEntry.Type.CLASS_OR_RESOURCE, getJavaBaseModuleInfo()));
181        for (String in : input) {
182            poolMgr.add(ResourcePoolEntry.create(in,
183                    ResourcePoolEntry.Type.NATIVE_LIB, new byte[0]));
184        }
185        ResourcePoolManager outMgr = new ResourcePoolManager();
186
187        Plugin p = new ExcludeVMPlugin();
188        Map<String, String> config = new HashMap<>();
189        if (vm != null) {
190            config.put(ExcludeVMPlugin.NAME, vm);
191        }
192        p.configure(config);
193        ResourcePool out = p.transform(poolMgr.resourcePool(), outMgr.resourcePoolBuilder());
194
195        String newContent = new String(out.findEntry("/java.base/lib/jvm.cfg").get().contentBytes());
196
197        if (!expectdJvmCfg.equals(newContent)) {
198            throw new Exception("Got content " + newContent + " expected " + expectdJvmCfg);
199        }
200
201        // Apart from native resources, we should find jvm.cfg and
202        // java.base/module-info.class. So, we add 2 here to the
203        // expected count!
204        if (out.entryCount() != (expectedOutput.length + 2)) {
205            out.entries().forEach(m -> {
206                System.err.println(m.path());
207            });
208            throw new Exception("Invalid output size " + out.entryCount() + " expected " + (expectedOutput.length + 2));
209        }
210
211        out.entries().forEach(md -> {
212            if (md.path().equals("/java.base/lib/jvm.cfg") ||
213                md.path().equals("/java.base/module-info.class")) {
214                return;
215            }
216            boolean contained = false;
217            for (String o : expectedOutput) {
218                if (md.path().equals(o)) {
219                    contained = true;
220                    break;
221                }
222            }
223            if (!contained) {
224                throw new RuntimeException(md.path() + " not expected");
225            }
226        });
227    }
228
229    // read java.base/module-info.class from jrt-fs
230    private static Path getJavaBaseModuleInfo() {
231        return Paths.get(URI.create("jrt:/modules/java.base/module-info.class"));
232    }
233
234    private static boolean isWindows() {
235        return System.getProperty("os.name").startsWith("Windows");
236    }
237
238    private static boolean isMac() {
239        return System.getProperty("os.name").startsWith("Mac OS");
240    }
241
242    private static String jvmlib() {
243        String lib = "libjvm.so";
244        if (isWindows()) {
245            lib = "jvm.dll";
246        } else if (isMac()) {
247            lib = "libjvm.dylib";
248        }
249        return lib;
250    }
251}
252