1 /*
   2  * Copyright (c) 1999, 2016, 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.ArrayList;
  30 import java.util.List;
  31 import java.util.Optional;
  32 
  33 class VersionProps {
  34 
  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_runtime_name =
  43         "@@RUNTIME_NAME@@";
  44 
  45     private static final String java_runtime_version =
  46         "@@VERSION_STRING@@";
  47 
  48     private static final String VERSION_NUMBER =
  49         "@@VERSION_NUMBER@@";
  50 
  51     private static final String VERSION_BUILD =
  52         "@@VERSION_BUILD@@";
  53 
  54     private static final String VERSION_PRE =
  55         "@@VERSION_PRE@@";
  56 
  57     private static final String VERSION_OPT =
  58         "@@VERSION_OPT@@";
  59 
  60     static {
  61         init();
  62     }
  63 
  64     public static void init() {
  65         System.setProperty("java.version", java_version);
  66         System.setProperty("java.runtime.version", java_runtime_version);
  67         System.setProperty("java.runtime.name", java_runtime_name);
  68     }
  69 
  70     private static void check(String s, int prevIndex, int index) {
  71         if (index - prevIndex > 1 &&
  72             Character.digit(s.charAt(prevIndex), 10) <= 0)
  73             throw new IllegalArgumentException("Leading zeros not supported (" +
  74                     s.substring(prevIndex, index) + ")");
  75     }
  76 
  77     // This method is reflectively regression tested from
  78     // test/java/lang/Runtime/Version/VersionProps.java
  79     // If you rename or remove this method, please update the test accordingly.
  80     static List<Integer> parseVersionNumbers(String versionNumber) {
  81         List<Integer> versionNumbers = new ArrayList<>(4);
  82         int prevIndex = 0;
  83         int index = versionNumber.indexOf('.');
  84         while (index > 0) {
  85             check(versionNumber, prevIndex, index);
  86             versionNumbers.add(
  87                     Integer.parseInt(versionNumber, prevIndex, index, 10));
  88             prevIndex = index + 1; // Skip the period
  89             index = versionNumber.indexOf('.', prevIndex);
  90         }
  91         check(versionNumber, prevIndex, versionNumber.length());
  92         versionNumbers.add(Integer.parseInt(versionNumber,
  93                 prevIndex, versionNumber.length(), 10));
  94 
  95         if (versionNumbers.get(0) == 0 || versionNumbers.get(versionNumbers.size() - 1) == 0)
  96             throw new IllegalArgumentException("Leading or trailing zeros not supported (" +
  97                     versionNumbers + ")");
  98 
  99         return versionNumbers;
 100     }
 101 
 102     static List<Integer> versionNumbers() {
 103         return parseVersionNumbers(VERSION_NUMBER);
 104     }
 105 
 106     static Optional<String> pre() {
 107         return optionalOf(VERSION_PRE);
 108     }
 109 
 110     static Optional<Integer> build() {
 111         return VERSION_BUILD.isEmpty() ?
 112                 Optional.empty() :
 113                 Optional.of(Integer.parseInt(VERSION_BUILD));
 114     }
 115 
 116     static Optional<String> optional() {
 117         return optionalOf(VERSION_OPT);
 118     }
 119 
 120     // Treat empty strings as value not being present
 121     private static Optional<String> optionalOf(String value) {
 122         if (!value.isEmpty()) {
 123             return Optional.of(value);
 124         } else {
 125             return Optional.empty();
 126         }
 127     }
 128 
 129     /**
 130      * In case you were wondering this method is called by java -version.
 131      * Sad that it prints to stderr; would be nicer if default printed on
 132      * stdout.
 133      */
 134     public static void print() {
 135         print(System.err);
 136     }
 137 
 138     /**
 139      * This is the same as print except that it adds an extra line-feed
 140      * at the end, typically used by the -showversion in the launcher
 141      */
 142     public static void println() {
 143         print(System.err);
 144         System.err.println();
 145     }
 146 
 147     /**
 148      * Give a stream, it will print version info on it.
 149      */
 150     public static void print(PrintStream ps) {
 151         boolean isHeadless = false;
 152 
 153         /* Report that we're running headless if the property is true */
 154         String headless = System.getProperty("java.awt.headless");
 155         if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) {
 156             isHeadless = true;
 157         }
 158 
 159         /* First line: platform version. */
 160         ps.println(launcher_name + " version \"" + java_version + "\"");
 161 
 162         /* Second line: runtime version (ie, libraries). */
 163 
 164         String jdk_debug_level = System.getProperty("jdk.debug", "release");
 165         /* Debug level is not printed for "release" builds */
 166         if ("release".equals(jdk_debug_level)) {
 167             jdk_debug_level = "";
 168         } else {
 169             jdk_debug_level = jdk_debug_level + " ";
 170         }
 171 
 172         ps.print(java_runtime_name + " (" + jdk_debug_level + "build " + java_runtime_version);
 173 
 174         if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) {
 175             // embedded builds report headless state
 176             ps.print(", headless");
 177         }
 178         ps.println(')');
 179 
 180         /* Third line: JVM information. */
 181         String java_vm_name    = System.getProperty("java.vm.name");
 182         String java_vm_version = System.getProperty("java.vm.version");
 183         String java_vm_info    = System.getProperty("java.vm.info");
 184         ps.println(java_vm_name + " (" + jdk_debug_level + "build " + java_vm_version + ", " +
 185                    java_vm_info + ")");
 186     }
 187 
 188 }