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