1 /* 2 * Copyright (c) 1999, 2018, 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 26 package java.lang; 27 28 import java.io.PrintStream; 29 import java.util.Arrays; 30 import java.util.List; 31 import java.util.Optional; 32 import java.util.Properties; 33 34 class 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 private static final String java_runtime_name = 46 "@@RUNTIME_NAME@@"; 47 48 private static final String java_runtime_version = 49 "@@VERSION_STRING@@"; 50 51 private static final String VERSION_NUMBER = 52 "@@VERSION_NUMBER@@"; 53 54 private static final String VERSION_BUILD = 55 "@@VERSION_BUILD@@"; 56 57 private static final String VERSION_PRE = 58 "@@VERSION_PRE@@"; 59 60 private static final String VERSION_OPT = 61 "@@VERSION_OPT@@"; 62 63 private static final boolean isLTS = 64 "@@VERSION_OPT@@".startsWith("LTS"); 65 66 private static final String CLASSFILE_MAJOR_MINOR = 67 "@@VERSION_CLASSFILE_MAJOR@@.@@VERSION_CLASSFILE_MINOR@@"; 68 69 private static final String VENDOR_VERSION_STRING = 70 "@@VENDOR_VERSION_STRING@@"; 71 72 private static final String vendor_version = 73 (VENDOR_VERSION_STRING.length() > 0 74 ? " " + VENDOR_VERSION_STRING : ""); 75 76 private static final String VENDOR = 77 "@@VENDOR@@"; 78 79 private static final String VENDOR_URL = 80 "@@VENDOR_URL@@"; 81 82 private static final String VENDOR_URL_BUG = 83 "@@VENDOR_URL_BUG@@"; 84 85 /** 86 * Initialize system properties using build provided values. 87 * 88 * @param props Properties instance in which to insert the properties 89 */ 90 public static void init(Properties props) { 91 props.setProperty("java.version", java_version); 92 props.setProperty("java.version.date", java_version_date); 93 props.setProperty("java.runtime.version", java_runtime_version); 94 props.setProperty("java.runtime.name", java_runtime_name); 95 if (VENDOR_VERSION_STRING.length() > 0) 96 props.setProperty("java.vendor.version", VENDOR_VERSION_STRING); 97 98 props.setProperty("java.class.version", CLASSFILE_MAJOR_MINOR); 99 100 props.setProperty("java.specification.version", VERSION_NUMBER); 101 props.setProperty("java.specification.name", "Java Platform API Specification"); 102 props.setProperty("java.specification.vendor", "Oracle Corporation"); 103 104 if (!VENDOR.isEmpty()) { 105 props.setProperty("java.vendor", VENDOR); 106 } 107 if (!VENDOR_URL.isEmpty()) { 108 props.setProperty("java.vendor.url", VENDOR_URL); 109 } 110 if (!VENDOR_URL_BUG.isEmpty()) { 111 props.setProperty("java.vendor.url.bug", VENDOR_URL_BUG); 112 } 113 } 114 115 private static int parseVersionNumber(String version, int prevIndex, int index) { 116 if (index - prevIndex > 1 && 117 Character.digit(version.charAt(prevIndex), 10) <= 0) 118 throw new IllegalArgumentException("Leading zeros not supported (" + 119 version.substring(prevIndex, index) + ")"); 120 return Integer.parseInt(version, prevIndex, index, 10); 121 } 122 123 // This method is reflectively used by regression tests. 124 static List<Integer> parseVersionNumbers(String version) { 125 // Let's find the size of an array required to hold $VNUM components 126 int size = 0; 127 int prevIndex = 0; 128 do { 129 prevIndex = version.indexOf('.', prevIndex) + 1; 130 size++; 131 } while (prevIndex > 0); 132 Integer[] verNumbers = new Integer[size]; 133 134 // Fill in the array with $VNUM components 135 int n = 0; 136 prevIndex = 0; 137 int index = version.indexOf('.'); 138 while (index > -1) { 139 verNumbers[n] = parseVersionNumber(version, prevIndex, index); 140 prevIndex = index + 1; // Skip the period 141 index = version.indexOf('.', prevIndex); 142 n++; 143 } 144 verNumbers[n] = parseVersionNumber(version, prevIndex, version.length()); 145 146 if (verNumbers[0] == 0 || verNumbers[n] == 0) 147 throw new IllegalArgumentException("Leading/trailing zeros not allowed (" + 148 Arrays.toString(verNumbers) + ")"); 149 150 return List.of(verNumbers); 151 } 152 153 static List<Integer> versionNumbers() { 154 return parseVersionNumbers(VERSION_NUMBER); 155 } 156 157 static Optional<String> pre() { 158 return optionalOf(VERSION_PRE); 159 } 160 161 static Optional<Integer> build() { 162 return VERSION_BUILD.isEmpty() ? 163 Optional.empty() : 164 Optional.of(Integer.parseInt(VERSION_BUILD)); 165 } 166 167 static Optional<String> optional() { 168 return optionalOf(VERSION_OPT); 169 } 170 171 // Treat empty strings as value not being present 172 private static Optional<String> optionalOf(String value) { 173 if (!value.isEmpty()) { 174 return Optional.of(value); 175 } else { 176 return Optional.empty(); 177 } 178 } 179 180 /** 181 * In case you were wondering this method is called by java -version. 182 */ 183 public static void print(boolean err) { 184 print(err, false); 185 } 186 187 /** 188 * This is the same as print except that it adds an extra line-feed 189 * at the end, typically used by the -showversion in the launcher 190 */ 191 public static void println(boolean err) { 192 print(err, true); 193 } 194 195 /** 196 * Print version info. 197 */ 198 private static void print(boolean err, boolean newln) { 199 PrintStream ps = err ? System.err : System.out; 200 201 /* First line: platform version. */ 202 if (err) { 203 ps.println(launcher_name + " version \"" + java_version + "\"" 204 + " " + java_version_date 205 + (isLTS ? " LTS" : "")); 206 } else { 207 /* Use a format more in line with GNU conventions */ 208 ps.println(launcher_name + " " + java_version 209 + " " + java_version_date 210 + (isLTS ? " LTS" : "")); 211 } 212 213 /* Second line: runtime version (ie, libraries). */ 214 String jdk_debug_level = System.getProperty("jdk.debug", "release"); 215 if ("release".equals(jdk_debug_level)) { 216 /* Do not show debug level "release" builds */ 217 jdk_debug_level = ""; 218 } else { 219 jdk_debug_level = jdk_debug_level + " "; 220 } 221 222 ps.println(java_runtime_name + vendor_version 223 + " (" + jdk_debug_level + "build " + java_runtime_version + ")"); 224 225 /* Third line: JVM information. */ 226 String java_vm_name = System.getProperty("java.vm.name"); 227 String java_vm_version = System.getProperty("java.vm.version"); 228 String java_vm_info = System.getProperty("java.vm.info"); 229 ps.println(java_vm_name + vendor_version 230 + " (" + jdk_debug_level + "build " + java_vm_version + ", " 231 + java_vm_info + ")"); 232 233 } 234 235 }