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 props.setProperty("java.vendor", VENDOR); 105 props.setProperty("java.vendor.url", VENDOR_URL); 106 props.setProperty("java.vendor.url.bug", VENDOR_URL_BUG); 107 } 108 109 private static int parseVersionNumber(String version, int prevIndex, int index) { 110 if (index - prevIndex > 1 && 111 Character.digit(version.charAt(prevIndex), 10) <= 0) 112 throw new IllegalArgumentException("Leading zeros not supported (" + 113 version.substring(prevIndex, index) + ")"); 114 return Integer.parseInt(version, prevIndex, index, 10); 115 } 116 117 // This method is reflectively used by regression tests. 118 static List<Integer> parseVersionNumbers(String version) { 119 // Let's find the size of an array required to hold $VNUM components 120 int size = 0; 121 int prevIndex = 0; 122 do { 123 prevIndex = version.indexOf('.', prevIndex) + 1; 124 size++; 125 } while (prevIndex > 0); 126 Integer[] verNumbers = new Integer[size]; 127 128 // Fill in the array with $VNUM components 129 int n = 0; 130 prevIndex = 0; 131 int index = version.indexOf('.'); 132 while (index > -1) { 133 verNumbers[n] = parseVersionNumber(version, prevIndex, index); 134 prevIndex = index + 1; // Skip the period 135 index = version.indexOf('.', prevIndex); 136 n++; 137 } 138 verNumbers[n] = parseVersionNumber(version, prevIndex, version.length()); 139 140 if (verNumbers[0] == 0 || verNumbers[n] == 0) 141 throw new IllegalArgumentException("Leading/trailing zeros not allowed (" + 142 Arrays.toString(verNumbers) + ")"); 143 144 return List.of(verNumbers); 145 } 146 147 static List<Integer> versionNumbers() { 148 return parseVersionNumbers(VERSION_NUMBER); 149 } 150 151 static Optional<String> pre() { 152 return optionalOf(VERSION_PRE); 153 } 154 155 static Optional<Integer> build() { 156 return VERSION_BUILD.isEmpty() ? 157 Optional.empty() : 158 Optional.of(Integer.parseInt(VERSION_BUILD)); 159 } 160 161 static Optional<String> optional() { 162 return optionalOf(VERSION_OPT); 163 } 164 165 // Treat empty strings as value not being present 166 private static Optional<String> optionalOf(String value) { 167 if (!value.isEmpty()) { 168 return Optional.of(value); 169 } else { 170 return Optional.empty(); 171 } 172 } 173 174 /** 175 * In case you were wondering this method is called by java -version. 176 */ 177 public static void print(boolean err) { 178 print(err, false); 179 } 180 181 /** 182 * This is the same as print except that it adds an extra line-feed 183 * at the end, typically used by the -showversion in the launcher 184 */ 185 public static void println(boolean err) { 186 print(err, true); 187 } 188 189 /** 190 * Print version info. 191 */ 192 private static void print(boolean err, boolean newln) { 193 PrintStream ps = err ? System.err : System.out; 194 195 /* First line: platform version. */ 196 if (err) { 197 ps.println(launcher_name + " version \"" + java_version + "\"" 198 + " " + java_version_date 199 + (isLTS ? " LTS" : "")); 200 } else { 201 /* Use a format more in line with GNU conventions */ 202 ps.println(launcher_name + " " + java_version 203 + " " + java_version_date 204 + (isLTS ? " LTS" : "")); 205 } 206 207 /* Second line: runtime version (ie, libraries). */ 208 String jdk_debug_level = System.getProperty("jdk.debug", "release"); 209 if ("release".equals(jdk_debug_level)) { 210 /* Do not show debug level "release" builds */ 211 jdk_debug_level = ""; 212 } else { 213 jdk_debug_level = jdk_debug_level + " "; 214 } 215 216 ps.println(java_runtime_name + vendor_version 217 + " (" + jdk_debug_level + "build " + java_runtime_version + ")"); 218 219 /* Third line: JVM information. */ 220 String java_vm_name = System.getProperty("java.vm.name"); 221 String java_vm_version = System.getProperty("java.vm.version"); 222 String java_vm_info = System.getProperty("java.vm.info"); 223 ps.println(java_vm_name + vendor_version 224 + " (" + jdk_debug_level + "build " + java_vm_version + ", " 225 + java_vm_info + ")"); 226 227 } 228 229 }