1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 package sun.misc;
28 import java.io.PrintStream;
29 
30 public class Version {
31     // Android-changed: launcher_name, java_version,
32     // java_runtime_name and java_runtime_version.
33     private static final String launcher_name = "";
34     private static final String java_version = AndroidHardcodedSystemProperties.JAVA_VERSION;
35     private static final String java_runtime_name = "Android Runtime";
36     private static final String java_runtime_version = "0.9";
37 
38     // Called by java.lang.System.<clinit>
initSystemProperties()39     public static void initSystemProperties() {
40         System.setUnchangeableSystemProperty("java.version", java_version);
41         System.setUnchangeableSystemProperty("java.runtime.version", java_runtime_version);
42         System.setUnchangeableSystemProperty("java.runtime.name", java_runtime_name);
43     }
44 
45     private static boolean versionsInitialized = false;
46     private static int jvm_major_version = 0;
47     private static int jvm_minor_version = 0;
48     private static int jvm_micro_version = 0;
49     private static int jvm_update_version = 0;
50     private static int jvm_build_number = 0;
51     private static String jvm_special_version = null;
52     private static int jdk_major_version = 0;
53     private static int jdk_minor_version = 0;
54     private static int jdk_micro_version = 0;
55     private static int jdk_update_version = 0;
56     private static int jdk_build_number = 0;
57     private static String jdk_special_version = null;
58 
59     /**
60      * In case you were wondering this method is called by java -version.
61      * Sad that it prints to stderr; would be nicer if default printed on
62      * stdout.
63      */
print()64     public static void print() {
65         print(System.err);
66     }
67 
68     /**
69      * This is the same as print except that it adds an extra line-feed
70      * at the end, typically used by the -showversion in the launcher
71      */
println()72     public static void println() {
73         print(System.err);
74         System.err.println();
75     }
76 
77     /**
78      * Give a stream, it will print version info on it.
79      */
print(PrintStream ps)80     public static void print(PrintStream ps) {
81         boolean isHeadless = false;
82 
83         /* Report that we're running headless if the property is true */
84 	String headless = System.getProperty("java.awt.headless");
85 	if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) {
86             isHeadless = true;
87 	}
88 
89         /* First line: platform version. */
90         ps.println(launcher_name + " version \"" + java_version + "\"");
91 
92         /* Second line: runtime version (ie, libraries). */
93 
94 	ps.print(java_runtime_name + " (build " + java_runtime_version);
95 
96 	if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) {
97 	    // embedded builds report headless state
98 	    ps.print(", headless");
99 	}
100 	ps.println(')');
101 
102         /* Third line: JVM information. */
103         String java_vm_name    = System.getProperty("java.vm.name");
104         String java_vm_version = System.getProperty("java.vm.version");
105         String java_vm_info    = System.getProperty("java.vm.info");
106         ps.println(java_vm_name + " (build " + java_vm_version + ", " +
107                    java_vm_info + ")");
108     }
109 
110 
111     /**
112      * Returns the major version of the running JVM if it's 1.6 or newer
113      * or any RE VM build. It will return 0 if it's an internal 1.5 or
114      * 1.4.x build.
115      *
116      * @since 1.6
117      */
jvmMajorVersion()118     public static synchronized int jvmMajorVersion() {
119         if (!versionsInitialized) {
120             initVersions();
121         }
122         return jvm_major_version;
123     }
124 
125     /**
126      * Returns the minor version of the running JVM if it's 1.6 or newer
127      * or any RE VM build. It will return 0 if it's an internal 1.5 or
128      * 1.4.x build.
129      * @since 1.6
130      */
jvmMinorVersion()131     public static synchronized int jvmMinorVersion() {
132         if (!versionsInitialized) {
133             initVersions();
134         }
135         return jvm_minor_version;
136     }
137 
138 
139     /**
140      * Returns the micro version of the running JVM if it's 1.6 or newer
141      * or any RE VM build. It will return 0 if it's an internal 1.5 or
142      * 1.4.x build.
143      * @since 1.6
144      */
jvmMicroVersion()145     public static synchronized int jvmMicroVersion() {
146         if (!versionsInitialized) {
147             initVersions();
148         }
149         return jvm_micro_version;
150     }
151 
152     /**
153      * Returns the update release version of the running JVM if it's
154      * a RE build. It will return 0 if it's an internal build.
155      * @since 1.6
156      */
jvmUpdateVersion()157     public static synchronized int jvmUpdateVersion() {
158         if (!versionsInitialized) {
159             initVersions();
160         }
161         return jvm_update_version;
162     }
163 
jvmSpecialVersion()164     public static synchronized String jvmSpecialVersion() {
165         if (!versionsInitialized) {
166             initVersions();
167         }
168         if (jvm_special_version == null) {
169             jvm_special_version = getJvmSpecialVersion();
170         }
171         return jvm_special_version;
172     }
getJvmSpecialVersion()173     public static native String getJvmSpecialVersion();
174 
175     /**
176      * Returns the build number of the running JVM if it's a RE build
177      * It will return 0 if it's an internal build.
178      * @since 1.6
179      */
jvmBuildNumber()180     public static synchronized int jvmBuildNumber() {
181         if (!versionsInitialized) {
182             initVersions();
183         }
184         return jvm_build_number;
185     }
186 
187     /**
188      * Returns the major version of the running JDK.
189      *
190      * @since 1.6
191      */
jdkMajorVersion()192     public static synchronized int jdkMajorVersion() {
193         if (!versionsInitialized) {
194             initVersions();
195         }
196         return jdk_major_version;
197     }
198 
199     /**
200      * Returns the minor version of the running JDK.
201      * @since 1.6
202      */
jdkMinorVersion()203     public static synchronized int jdkMinorVersion() {
204         if (!versionsInitialized) {
205             initVersions();
206         }
207         return jdk_minor_version;
208     }
209 
210     /**
211      * Returns the micro version of the running JDK.
212      * @since 1.6
213      */
jdkMicroVersion()214     public static synchronized int jdkMicroVersion() {
215         if (!versionsInitialized) {
216             initVersions();
217         }
218         return jdk_micro_version;
219     }
220 
221     /**
222      * Returns the update release version of the running JDK if it's
223      * a RE build. It will return 0 if it's an internal build.
224      * @since 1.6
225      */
jdkUpdateVersion()226     public static synchronized int jdkUpdateVersion() {
227         if (!versionsInitialized) {
228             initVersions();
229         }
230         return jdk_update_version;
231     }
232 
jdkSpecialVersion()233     public static synchronized String jdkSpecialVersion() {
234         if (!versionsInitialized) {
235             initVersions();
236         }
237         if (jdk_special_version == null) {
238             jdk_special_version = getJdkSpecialVersion();
239         }
240         return jdk_special_version;
241     }
getJdkSpecialVersion()242     public static native String getJdkSpecialVersion();
243 
244     /**
245      * Returns the build number of the running JDK if it's a RE build
246      * It will return 0 if it's an internal build.
247      * @since 1.6
248      */
jdkBuildNumber()249     public static synchronized int jdkBuildNumber() {
250         if (!versionsInitialized) {
251             initVersions();
252         }
253         return jdk_build_number;
254     }
255 
256     // true if JVM exports the version info including the capabilities
257     private static boolean jvmVersionInfoAvailable;
initVersions()258     private static synchronized void initVersions() {
259         if (versionsInitialized) {
260             return;
261         }
262         jvmVersionInfoAvailable = getJvmVersionInfo();
263         if (!jvmVersionInfoAvailable) {
264             // parse java.vm.version for older JVM before the
265             // new JVM_GetVersionInfo is added.
266             // valid format of the version string is:
267             // n.n.n[_uu[c]][-<identifer>]-bxx
268             CharSequence cs = System.getProperty("java.vm.version");
269             if (cs.length() >= 5 &&
270                 Character.isDigit(cs.charAt(0)) && cs.charAt(1) == '.' &&
271                 Character.isDigit(cs.charAt(2)) && cs.charAt(3) == '.' &&
272                 Character.isDigit(cs.charAt(4))) {
273                 jvm_major_version = Character.digit(cs.charAt(0), 10);
274                 jvm_minor_version = Character.digit(cs.charAt(2), 10);
275                 jvm_micro_version = Character.digit(cs.charAt(4), 10);
276                 cs = cs.subSequence(5, cs.length());
277                 if (cs.charAt(0) == '_' && cs.length() >= 3 &&
278                     Character.isDigit(cs.charAt(1)) &&
279                     Character.isDigit(cs.charAt(2))) {
280                     int nextChar = 3;
281                     try {
282                         String uu = cs.subSequence(1, 3).toString();
283                         jvm_update_version = Integer.parseInt(uu);
284                         if (cs.length() >= 4) {
285                             char c = cs.charAt(3);
286                             if (c >= 'a' && c <= 'z') {
287                                 jvm_special_version = Character.toString(c);
288                                 nextChar++;
289                             }
290                         }
291                     } catch (NumberFormatException e) {
292                         // not conforming to the naming convention
293                         return;
294                     }
295                     cs = cs.subSequence(nextChar, cs.length());
296                 }
297                 if (cs.charAt(0) == '-') {
298                     // skip the first character
299                     // valid format: <identifier>-bxx or bxx
300                     // non-product VM will have -debug|-release appended
301                     cs = cs.subSequence(1, cs.length());
302                     String[] res = cs.toString().split("-");
303                     for (String s : res) {
304                         if (s.charAt(0) == 'b' && s.length() == 3 &&
305                             Character.isDigit(s.charAt(1)) &&
306                             Character.isDigit(s.charAt(2))) {
307                             jvm_build_number =
308                                 Integer.parseInt(s.substring(1, 3));
309                             break;
310                         }
311                     }
312                 }
313             }
314         }
315         getJdkVersionInfo();
316         versionsInitialized = true;
317     }
318 
319     // Gets the JVM version info if available and sets the jvm_*_version fields
320     // and its capabilities.
321     //
322     // Return false if not available which implies an old VM (Tiger or before).
getJvmVersionInfo()323     private static native boolean getJvmVersionInfo();
getJdkVersionInfo()324     private static native void getJdkVersionInfo();
325 
326 }
327 
328 // Help Emacs a little because this file doesn't end in .java.
329 //
330 // Local Variables: ***
331 // mode: java ***
332 // End: ***
333