1 /*
  2  * Copyright (c) 2013, 2021, 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 package jdk.test.lib;
 25 
 26 import java.io.FileNotFoundException;
 27 import java.io.IOException;
 28 import java.nio.file.Files;
 29 import java.nio.file.Path;
 30 import java.nio.file.Paths;
 31 import java.security.AccessController;
 32 import java.security.PrivilegedAction;
 33 import java.util.concurrent.TimeUnit;
 34 import java.util.regex.Pattern;
 35 
 36 public class Platform {
 37     public  static final String vmName      = privilegedGetProperty("java.vm.name");
 38     public  static final String vmInfo      = privilegedGetProperty("java.vm.info");
 39     private static final String osVersion   = privilegedGetProperty("os.version");
 40     private static       int osVersionMajor = -1;
 41     private static       int osVersionMinor = -1;
 42     private static final String osName      = privilegedGetProperty("os.name");
 43     private static final String dataModel   = privilegedGetProperty("sun.arch.data.model");
 44     private static final String vmVersion   = privilegedGetProperty("java.vm.version");
 45     private static final String jdkDebug    = privilegedGetProperty("jdk.debug");
 46     private static final String osArch      = privilegedGetProperty("os.arch");
 47     private static final String userName    = privilegedGetProperty("user.name");
 48     private static final String compiler    = privilegedGetProperty("sun.management.compiler");
 49     private static final String testJdk     = privilegedGetProperty("test.jdk");
 50 
 51     @SuppressWarnings("removal")
 52     private static String privilegedGetProperty(String key) {
 53         return AccessController.doPrivileged((
 54                 PrivilegedAction<String>) () -> System.getProperty(key));
 55     }
 56 
 57     public static boolean isClient() {
 58         return vmName.endsWith(" Client VM");
 59     }
 60 
 61     public static boolean isServer() {
 62         return vmName.endsWith(" Server VM");
 63     }
 64 
 65     public static boolean isZero() {
 66         return vmName.endsWith(" Zero VM");
 67     }
 68 
 69     public static boolean isMinimal() {
 70         return vmName.endsWith(" Minimal VM");
 71     }
 72 
 73     public static boolean isEmbedded() {
 74         return vmName.contains("Embedded");
 75     }
 76 
 77     public static boolean isEmulatedClient() {
 78         return vmInfo.contains(" emulated-client");
 79     }
 80 
 81     public static boolean isTieredSupported() {
 82         return (compiler != null) && compiler.contains("Tiered Compilers");
 83     }
 84 
 85     public static boolean isInt() {
 86         return vmInfo.contains("interpreted");
 87     }
 88 
 89     public static boolean isMixed() {
 90         return vmInfo.contains("mixed");
 91     }
 92 
 93     public static boolean isComp() {
 94         return vmInfo.contains("compiled");
 95     }
 96 
 97     public static boolean is32bit() {
 98         return dataModel.equals("32");
 99     }
100 
101     public static boolean is64bit() {
102         return dataModel.equals("64");
103     }
104 
105     public static boolean isAix() {
106         return isOs("aix");
107     }
108 
109     public static boolean isLinux() {
110         return isOs("linux");
111     }
112 
113     public static boolean isBusybox(String tool) {
114         try {
115             Path toolpath = Paths.get(tool);
116             return !isWindows()
117                     && Files.isSymbolicLink(toolpath)
118                     && Paths.get("/bin/busybox")
119                         .equals(Files.readSymbolicLink(toolpath));
120         } catch (IOException ignore) {
121             return false;
122         }
123     }
124 
125     public static boolean isOSX() {
126         return isOs("mac");
127     }
128 
129     public static boolean isWindows() {
130         return isOs("win");
131     }
132 
133     private static boolean isOs(String osname) {
134         return osName.toLowerCase().startsWith(osname.toLowerCase());
135     }
136 
137     public static String getOsName() {
138         return osName;
139     }
140 
141     // Os version support.
142     private static void init_version() {
143         String[] osVersionTokens = osVersion.split("\\.");
144         try {
145             if (osVersionTokens.length > 0) {
146                 osVersionMajor = Integer.parseInt(osVersionTokens[0]);
147                 if (osVersionTokens.length > 1) {
148                     osVersionMinor = Integer.parseInt(osVersionTokens[1]);
149                 }
150             }
151         } catch (NumberFormatException e) {
152             osVersionMajor = osVersionMinor = 0;
153         }
154     }
155 
156     public static String getOsVersion() {
157         return osVersion;
158     }
159 
160     // Returns major version number from os.version system property.
161     // E.g. 3 on SLES 11.3 (for the linux kernel version).
162     public static int getOsVersionMajor() {
163         if (osVersionMajor == -1) init_version();
164         return osVersionMajor;
165     }
166 
167     // Returns minor version number from os.version system property.
168     // E.g. 0 on SLES 11.3 (for the linux kernel version).
169     public static int getOsVersionMinor() {
170         if (osVersionMinor == -1) init_version();
171         return osVersionMinor;
172     }
173 
174     public static boolean isDebugBuild() {
175         return (jdkDebug.toLowerCase().contains("debug"));
176     }
177 
178     public static boolean isSlowDebugBuild() {
179         return (jdkDebug.toLowerCase().equals("slowdebug"));
180     }
181 
182     public static boolean isFastDebugBuild() {
183         return (jdkDebug.toLowerCase().equals("fastdebug"));
184     }
185 
186     public static String getVMVersion() {
187         return vmVersion;
188     }
189 
190     public static boolean isAArch64() {
191         return isArch("aarch64");
192     }
193 
194     public static boolean isARM() {
195         return isArch("arm.*");
196     }
197 
198     public static boolean isRiscv64() {
199         return isArch("riscv64");
200     }
201 
202     public static boolean isPPC() {
203         return isArch("ppc.*");
204     }
205 
206     // Returns true for IBM z System running linux.
207     public static boolean isS390x() {
208         return isArch("s390.*") || isArch("s/390.*") || isArch("zArch_64");
209     }
210 
211     public static boolean isX64() {
212         // On OSX it's 'x86_64' and on other (Linux and Windows) platforms it's 'amd64'
213         return isArch("(amd64)|(x86_64)");
214     }
215 
216     public static boolean isX86() {
217         // On Linux it's 'i386', Windows 'x86' without '_64' suffix.
218         return isArch("(i386)|(x86(?!_64))");
219     }
220 
221     public static String getOsArch() {
222         return osArch;
223     }
224 
225     public static boolean isRoot() {
226         return userName.equals("root");
227     }
228 
229     /**
230      * Return a boolean for whether SA and jhsdb are ported/available
231      * on this platform.
232      */
233     public static boolean hasSA() {
234         if (isZero()) {
235             return false; // SA is not enabled.
236         }
237         if (isAix()) {
238             return false; // SA not implemented.
239         } else if (isLinux()) {
240             if (isS390x() || isARM()) {
241                 return false; // SA not implemented.
242             }
243         }
244         // Other platforms expected to work:
245         return true;
246     }
247 
248     /**
249      * Return true if the test JDK is signed, otherwise false. Only valid on OSX.
250      */
251     public static boolean isSignedOSX() throws IOException {
252         // We only care about signed binaries for 10.14 and later (actually 10.14.5, but
253         // for simplicity we'll also include earlier 10.14 versions).
254         if (getOsVersionMajor() == 10 && getOsVersionMinor() < 14) {
255             return false; // assume not signed
256         }
257 
258         // Find the path to the java binary.
259         String jdkPath = System.getProperty("java.home");
260         Path javaPath = Paths.get(jdkPath + "/bin/java");
261         String javaFileName = javaPath.toAbsolutePath().toString();
262         if (Files.notExists(javaPath)) {
263             throw new FileNotFoundException("Could not find file " + javaFileName);
264         }
265 
266         // Run codesign on the java binary.
267         ProcessBuilder pb = new ProcessBuilder("codesign", "-d", "-v", javaFileName);
268         pb.redirectError(ProcessBuilder.Redirect.DISCARD);
269         pb.redirectOutput(ProcessBuilder.Redirect.DISCARD);
270         Process codesignProcess = pb.start();
271         try {
272             if (codesignProcess.waitFor(10, TimeUnit.SECONDS) == false) {
273                 System.err.println("Timed out waiting for the codesign process to complete. Assuming not signed.");
274                 codesignProcess.destroyForcibly();
275                 return false; // assume not signed
276             }
277         } catch (InterruptedException e) {
278             throw new RuntimeException(e);
279         }
280 
281         // Check codesign result to see if java binary is signed. Here are the
282         // exit code meanings:
283         //    0: signed
284         //    1: not signed
285         //    2: invalid arguments
286         //    3: only has meaning with the -R argument.
287         // So we should always get 0 or 1 as an exit value.
288         if (codesignProcess.exitValue() == 0) {
289             System.out.println("Target JDK is signed. Some tests may be skipped.");
290             return true; // signed
291         } else if (codesignProcess.exitValue() == 1) {
292             System.out.println("Target JDK is not signed.");
293             return false; // not signed
294         } else {
295             System.err.println("Executing codesign failed. Assuming unsigned: " +
296                                codesignProcess.exitValue());
297             return false; // not signed
298         }
299     }
300 
301     private static boolean isArch(String archnameRE) {
302         return Pattern.compile(archnameRE, Pattern.CASE_INSENSITIVE)
303                       .matcher(osArch)
304                       .matches();
305     }
306 
307     /**
308      * Returns file extension of shared library, e.g. "so" on linux, "dll" on windows.
309      * @return file extension
310      */
311     public static String sharedLibraryExt() {
312         if (isWindows()) {
313             return "dll";
314         } else if (isOSX()) {
315             return "dylib";
316         } else {
317             return "so";
318         }
319     }
320 
321     /*
322      * Returns name of system variable containing paths to shared native libraries.
323      */
324     public static String sharedLibraryPathVariableName() {
325         if (isWindows()) {
326             return "PATH";
327         } else if (isOSX()) {
328             return "DYLD_LIBRARY_PATH";
329         } else if (isAix()) {
330             return "LIBPATH";
331         } else {
332             return "LD_LIBRARY_PATH";
333         }
334     }
335 
336     /**
337      * Returns absolute path to directory containing shared libraries in the tested JDK.
338      */
339     public static Path libDir() {
340         return libDir(Paths.get(testJdk)).toAbsolutePath();
341     }
342 
343     /**
344      * Resolves a given path, to a JDK image, to the directory containing shared libraries.
345      *
346      * @param image the path to a JDK image
347      * @return the resolved path to the directory containing shared libraries
348      */
349     public static Path libDir(Path image) {
350         if (Platform.isWindows()) {
351             return image.resolve("bin");
352         } else {
353             return image.resolve("lib");
354         }
355     }
356 
357     /**
358      * Returns absolute path to directory containing JVM shared library.
359      */
360     public static Path jvmLibDir() {
361         return libDir().resolve(variant());
362     }
363 
364     private static String variant() {
365         if (Platform.isServer()) {
366             return "server";
367         } else if (Platform.isClient()) {
368             return "client";
369         } else if (Platform.isMinimal()) {
370             return "minimal";
371         } else if (Platform.isZero()) {
372             return "zero";
373         } else {
374             throw new Error("TESTBUG: unsupported vm variant");
375         }
376     }
377 
378 
379     public static boolean isDefaultCDSArchiveSupported() {
380         return (is64bit()  &&
381                 isServer() &&
382                 (isLinux()   ||
383                  isOSX()     ||
384                  isWindows()) &&
385                 !isZero()    &&
386                 !isMinimal() &&
387                 !isARM());
388     }
389 
390     /*
391      * This should match the #if condition in ClassListParser::load_class_from_source().
392      */
393     public static boolean areCustomLoadersSupportedForCDS() {
394         return (is64bit() && (isLinux() || isOSX()));
395     }
396 }