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