1/* 2 * Copyright (c) 1999, 2019, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package java.lang; 27 28import java.io.PrintStream; 29import java.util.Arrays; 30import java.util.List; 31import java.util.Map; 32import java.util.Optional; 33 34class VersionProps { 35 36 private static final String launcher_name = 37 "@@LAUNCHER_NAME@@"; 38 39 private static final String java_version = 40 "@@VERSION_SHORT@@"; 41 42 private static final String java_version_date = 43 "@@VERSION_DATE@@"; 44 45 // This field is read by HotSpot 46 private static final String java_runtime_name = 47 "@@RUNTIME_NAME@@"; 48 49 // This field is read by HotSpot 50 private static final String java_runtime_version = 51 "@@VERSION_STRING@@"; 52 53 private static final String VERSION_NUMBER = 54 "@@VERSION_NUMBER@@"; 55 56 private static final String VERSION_SPECIFICATION = 57 "@@VERSION_SPECIFICATION@@"; 58 59 private static final String VERSION_BUILD = 60 "@@VERSION_BUILD@@"; 61 62 private static final String VERSION_PRE = 63 "@@VERSION_PRE@@"; 64 65 private static final String VERSION_OPT = 66 "@@VERSION_OPT@@"; 67 68 private static final boolean isLTS = 69 "@@VERSION_OPT@@".startsWith("LTS"); 70 71 private static final String CLASSFILE_MAJOR_MINOR = 72 "@@VERSION_CLASSFILE_MAJOR@@.@@VERSION_CLASSFILE_MINOR@@"; 73 74 private static final String VENDOR = 75 "@@VENDOR@@"; 76 77 private static final String VENDOR_URL = 78 "@@VENDOR_URL@@"; 79 80 // The remaining VENDOR_* fields must not be final, 81 // so that they can be redefined by jlink plugins 82 83 // This field is read by HotSpot 84 private static String VENDOR_VERSION = 85 "@@VENDOR_VERSION_STRING@@"; 86 87 private static String VENDOR_URL_BUG = 88 "@@VENDOR_URL_BUG@@"; 89 90 // This field is read by HotSpot 91 private static String VENDOR_URL_VM_BUG = 92 "@@VENDOR_URL_VM_BUG@@"; 93 94 /** 95 * Initialize system properties using build provided values. 96 * 97 * @param props Map instance in which to insert the properties 98 */ 99 public static void init(Map<String, String> props) { 100 props.put("java.version", java_version); 101 props.put("java.version.date", java_version_date); 102 props.put("java.runtime.version", java_runtime_version); 103 props.put("java.runtime.name", java_runtime_name); 104 if (!VENDOR_VERSION.isEmpty()) 105 props.put("java.vendor.version", VENDOR_VERSION); 106 107 props.put("java.class.version", CLASSFILE_MAJOR_MINOR); 108 109 props.put("java.specification.version", VERSION_SPECIFICATION); 110 props.put("java.specification.name", "Java Platform API Specification"); 111 props.put("java.specification.vendor", "Oracle Corporation"); 112 113 props.put("java.vendor", VENDOR); 114 props.put("java.vendor.url", VENDOR_URL); 115 props.put("java.vendor.url.bug", VENDOR_URL_BUG); 116 } 117 118 private static int parseVersionNumber(String version, int prevIndex, int index) { 119 if (index - prevIndex > 1 && 120 Character.digit(version.charAt(prevIndex), 10) <= 0) 121 throw new IllegalArgumentException("Leading zeros not supported (" + 122 version.substring(prevIndex, index) + ")"); 123 return Integer.parseInt(version, prevIndex, index, 10); 124 } 125 126 // This method is reflectively used by regression tests. 127 static List<Integer> parseVersionNumbers(String version) { 128 // Let's find the size of an array required to hold $VNUM components 129 int size = 0; 130 int prevIndex = 0; 131 do { 132 prevIndex = version.indexOf('.', prevIndex) + 1; 133 size++; 134 } while (prevIndex > 0); 135 Integer[] verNumbers = new Integer[size]; 136 137 // Fill in the array with $VNUM components 138 int n = 0; 139 prevIndex = 0; 140 int index = version.indexOf('.'); 141 while (index > -1) { 142 verNumbers[n] = parseVersionNumber(version, prevIndex, index); 143 prevIndex = index + 1; // Skip the period 144 index = version.indexOf('.', prevIndex); 145 n++; 146 } 147 verNumbers[n] = parseVersionNumber(version, prevIndex, version.length()); 148 149 if (verNumbers[0] == 0 || verNumbers[n] == 0) 150 throw new IllegalArgumentException("Leading/trailing zeros not allowed (" + 151 Arrays.toString(verNumbers) + ")"); 152 153 return List.of(verNumbers); 154 } 155 156 static List<Integer> versionNumbers() { 157 return parseVersionNumbers(VERSION_NUMBER); 158 } 159 160 static Optional<String> pre() { 161 return optionalOf(VERSION_PRE); 162 } 163 164 static Optional<Integer> build() { 165 return VERSION_BUILD.isEmpty() ? 166 Optional.empty() : 167 Optional.of(Integer.parseInt(VERSION_BUILD)); 168 } 169 170 static Optional<String> optional() { 171 return optionalOf(VERSION_OPT); 172 } 173 174 // Treat empty strings as value not being present 175 private static Optional<String> optionalOf(String value) { 176 if (!value.isEmpty()) { 177 return Optional.of(value); 178 } else { 179 return Optional.empty(); 180 } 181 } 182 183 /** 184 * In case you were wondering this method is called by java -version. 185 */ 186 public static void print(boolean err) { 187 print(err, false); 188 } 189 190 /** 191 * This is the same as print except that it adds an extra line-feed 192 * at the end, typically used by the -showversion in the launcher 193 */ 194 public static void println(boolean err) { 195 print(err, true); 196 } 197 198 /** 199 * Print version info. 200 */ 201 private static void print(boolean err, boolean newln) { 202 PrintStream ps = err ? System.err : System.out; 203 204 /* First line: platform version. */ 205 if (err) { 206 ps.println(launcher_name + " version \"" + java_version + "\"" 207 + " " + java_version_date 208 + (isLTS ? " LTS" : "")); 209 } else { 210 /* Use a format more in line with GNU conventions */ 211 ps.println(launcher_name + " " + java_version 212 + " " + java_version_date 213 + (isLTS ? " LTS" : "")); 214 } 215 216 /* Second line: runtime version (ie, libraries). */ 217 String jdk_debug_level = System.getProperty("jdk.debug", "release"); 218 if ("release".equals(jdk_debug_level)) { 219 /* Do not show debug level "release" builds */ 220 jdk_debug_level = ""; 221 } else { 222 jdk_debug_level = jdk_debug_level + " "; 223 } 224 225 String vendor_version = (VENDOR_VERSION.isEmpty() 226 ? "" : " " + VENDOR_VERSION); 227 228 ps.println(java_runtime_name + vendor_version 229 + " (" + jdk_debug_level + "build " + java_runtime_version + ")"); 230 231 /* Third line: JVM information. */ 232 String java_vm_name = System.getProperty("java.vm.name"); 233 String java_vm_version = System.getProperty("java.vm.version"); 234 String java_vm_info = System.getProperty("java.vm.info"); 235 ps.println(java_vm_name + vendor_version 236 + " (" + jdk_debug_level + "build " + java_vm_version + ", " 237 + java_vm_info + ")"); 238 239 } 240 241} 242