8003256: (profiles) Add support for profile identification
Reviewed-by: dholmes, mchung, ksrini
--- a/jdk/make/java/version/Makefile Mon Jan 21 23:20:42 2013 -0500
+++ b/jdk/make/java/version/Makefile Mon Jan 21 23:21:15 2013 -0500
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@
-e 's/@@java_version@@/$(RELEASE)/g' \
-e 's/@@java_runtime_version@@/$(FULL_VERSION)/g' \
-e 's/@@java_runtime_name@@/$(RUNTIME_NAME)/g' \
+ -e 's/@@java_profile_name@@//g' \
$< > $@.temp
@$(MV) $@.temp $@
--- a/jdk/makefiles/GensrcMisc.gmk Mon Jan 21 23:20:42 2013 -0500
+++ b/jdk/makefiles/GensrcMisc.gmk Mon Jan 21 23:21:15 2013 -0500
@@ -23,24 +23,29 @@
# questions.
#
+include ProfileNames.gmk
+
##########################################################################################
# Install the launcher name, release version string, full version
# string and the runtime name into the Version.java file.
# To be printed by java -version
-$(JDK_OUTPUTDIR)/gensrc/sun/misc/Version.java: \
- $(JDK_TOPDIR)/src/share/classes/sun/misc/Version.java.template
+$(JDK_OUTPUTDIR)/gensrc/sun/misc/Version.java \
+$(PROFILE_VERSION_JAVA_TARGETS): \
+ $(JDK_TOPDIR)/src/share/classes/sun/misc/Version.java.template
$(MKDIR) -p $(@D)
$(RM) $@ $@.tmp
- $(ECHO) $(LOG_INFO) Generating sun/misc/Version.java
+ $(ECHO) Generating sun/misc/Version.java $(call profile_version_name, $@)
$(SED) -e 's/@@launcher_name@@/$(LAUNCHER_NAME)/g' \
-e 's/@@java_version@@/$(RELEASE)/g' \
-e 's/@@java_runtime_version@@/$(FULL_VERSION)/g' \
-e 's/@@java_runtime_name@@/$(RUNTIME_NAME)/g' \
+ -e 's/@@java_profile_name@@/$(call profile_version_name, $@)/g' \
$< > $@.tmp
$(MV) $@.tmp $@
-GENSRC_MISC += $(JDK_OUTPUTDIR)/gensrc/sun/misc/Version.java
+GENSRC_MISC += $(JDK_OUTPUTDIR)/gensrc/sun/misc/Version.java \
+ $(PROFILE_VERSION_JAVA_TARGETS)
##########################################################################################
# Version file for jconsole
--- a/jdk/src/share/classes/sun/misc/Version.java.template Mon Jan 21 23:20:42 2013 -0500
+++ b/jdk/src/share/classes/sun/misc/Version.java.template Mon Jan 21 23:21:15 2013 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,8 +36,11 @@
"@@java_version@@";
private static final String java_runtime_name =
- "@@java_runtime_name@@";
-
+ "@@java_runtime_name@@";
+
+ private static final String java_profile_name =
+ "@@java_profile_name@@";
+
private static final String java_runtime_version =
"@@java_runtime_version@@";
@@ -49,6 +52,8 @@
System.setProperty("java.version", java_version);
System.setProperty("java.runtime.version", java_runtime_version);
System.setProperty("java.runtime.name", java_runtime_name);
+ if (java_profile_name.length() > 0)
+ System.setProperty("java.runtime.profile", java_profile_name);
}
private static boolean versionsInitialized = false;
@@ -90,23 +95,28 @@
boolean isHeadless = false;
/* Report that we're running headless if the property is true */
- String headless = System.getProperty("java.awt.headless");
- if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) {
+ String headless = System.getProperty("java.awt.headless");
+ if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) {
isHeadless = true;
- }
+ }
/* First line: platform version. */
ps.println(launcher_name + " version \"" + java_version + "\"");
/* Second line: runtime version (ie, libraries). */
- ps.print(java_runtime_name + " (build " + java_runtime_version);
+ ps.print(java_runtime_name + " (build " + java_runtime_version);
- if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) {
- // embedded builds report headless state
- ps.print(", headless");
- }
- ps.println(')');
+ if (java_profile_name.length() > 0) {
+ // profile name
+ ps.print(", profile " + java_profile_name);
+ }
+
+ if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) {
+ // embedded builds report headless state
+ ps.print(", headless");
+ }
+ ps.println(')');
/* Third line: JVM information. */
String java_vm_name = System.getProperty("java.vm.name");
@@ -332,6 +342,67 @@
private static native boolean getJvmVersionInfo();
private static native void getJdkVersionInfo();
+ // Possible runtime profiles, ordered from small to large
+ private final static String[] PROFILES = { "compact1", "compact2", "compact3" };
+
+ /**
+ * Returns the name of the profile that this runtime implements. The empty
+ * string is returned for the full Java Runtime.
+ */
+ public static String profileName() {
+ return java_profile_name;
+ }
+
+ /**
+ * Indicates if this runtime implements the full Java Runtime.
+ */
+ public static boolean isFullJre() {
+ return java_profile_name.length() == 0;
+ }
+
+ // cached index of this profile's name in PROFILES (1-based)
+ private static int thisRuntimeIndex;
+
+ /**
+ * Indicates if this runtime supports the given profile. Profile names are
+ * case sensitive.
+ *
+ * @return {@code true} if the given profile is supported
+ */
+ public static boolean supportsProfile(String requiredProfile) {
+ int x = thisRuntimeIndex - 1;
+ if (x < 0) {
+ String profile = profileName();
+ if (profile.length() > 0) {
+ x = 0;
+ while (x < PROFILES.length) {
+ if (PROFILES[x].equals(profile))
+ break;
+ x++;
+ }
+ if (x >= PROFILES.length)
+ throw new InternalError(profile + " not known to sun.misc.Version");
+
+ // okay if another thread has already set it
+ thisRuntimeIndex = x + 1;
+ }
+ // else we are a full JRE
+ }
+
+ int y = 0;
+ while (y < PROFILES.length) {
+ if (PROFILES[y].equals(requiredProfile))
+ break;
+ y++;
+ }
+ if (y >= PROFILES.length) {
+ // profile not found so caller has requested something that is not defined
+ return false;
+ }
+
+ return x < 0 || x >= y;
+ }
+
}
// Help Emacs a little because this file doesn't end in .java.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/profiles/VersionCheck.java Mon Jan 21 23:21:15 2013 -0500
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8003256
+ * @compile -XDignore.symbol.file VersionCheck.java
+ * @run main VersionCheck
+ * @summary Tests that "java -version" includes the name of the profile and that
+ * it matches the name in the release file
+ */
+
+import java.nio.file.*;
+import java.io.*;
+import java.util.Properties;
+
+public class VersionCheck {
+
+ static final String JAVA_HOME = System.getProperty("java.home");
+ static final String OS_NAME = System.getProperty("os.name");
+ static final String OS_ARCH = System.getProperty("os.arch");
+
+ static final String JAVA_CMD =
+ OS_NAME.startsWith("Windows") ? "java.exe" : "java";
+
+ static final boolean NEED_D64 =
+ OS_NAME.equals("SunOS") &&
+ (OS_ARCH.equals("sparcv9") || OS_ARCH.equals("amd64"));
+
+ /**
+ * Returns {@code true} if the given class is present.
+ */
+ static boolean isPresent(String cn) {
+ try {
+ Class.forName(cn);
+ return true;
+ } catch (ClassNotFoundException ignore) {
+ return false;
+ }
+ }
+
+ /**
+ * Determines the profile by checking whether specific classes are present.
+ * Returns the empty string if this runtime does not appear to be a profile
+ * of Java SE.
+ */
+ static String probeProfile() {
+ if (isPresent("java.awt.Window"))
+ return "";
+ if (isPresent("java.lang.management.ManagementFactory"))
+ return "compact3";
+ if (isPresent("java.sql.DriverManager"))
+ return "compact2";
+ return "compact1";
+ }
+
+ /**
+ * Execs java with the given parameters. The method blocks until the
+ * process terminates. Returns a {@code ByteArrayOutputStream} with any
+ * stdout or stderr from the process.
+ */
+ static ByteArrayOutputStream execJava(String... args)
+ throws IOException
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(Paths.get(JAVA_HOME, "bin", JAVA_CMD).toString());
+ if (NEED_D64)
+ sb.append(" -d64");
+ for (String arg: args) {
+ sb.append(' ');
+ sb.append(arg);
+ }
+ String[] cmd = sb.toString().split(" ");
+ ProcessBuilder pb = new ProcessBuilder(cmd);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buf = new byte[1024];
+ int n;
+ do {
+ n = p.getInputStream().read(buf);
+ if (n > 0)
+ baos.write(buf, 0, n);
+ } while (n > 0);
+ try {
+ int exitCode = p.waitFor();
+ if (exitCode != 0)
+ throw new RuntimeException("Exit code: " + exitCode);
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Should not happen");
+ }
+ return baos;
+ }
+
+ public static void main(String[] args) throws IOException {
+ String reported = sun.misc.Version.profileName();
+ String probed = probeProfile();
+ if (!reported.equals(probed)) {
+ throw new RuntimeException("sun.misc.Version reports: " + reported
+ + ", but probing reports: " + probed);
+ }
+
+ String profile = probed;
+ boolean isFullJre = (profile.length() == 0);
+
+ // check that java -version includes "profile compactN"
+ String expected = "profile " + profile;
+ System.out.println("Checking java -version ...");
+ ByteArrayOutputStream baos = execJava("-version");
+ ByteArrayInputStream bain = new ByteArrayInputStream(baos.toByteArray());
+ BufferedReader reader = new BufferedReader(new InputStreamReader(bain));
+ boolean found = false;
+ String line;
+ while ((line = reader.readLine()) != null) {
+ if (line.contains(expected)) {
+ found = true;
+ break;
+ }
+ }
+ if (found && isFullJre)
+ throw new RuntimeException(expected + " found in java -version output");
+ if (!found && !isFullJre)
+ throw new RuntimeException("java -version did not include " + expected);
+
+ // check that the profile name matches the release file
+ System.out.println("Checking release file ...");
+ Properties props = new Properties();
+
+ Path home = Paths.get(JAVA_HOME);
+ if (home.getFileName().toString().equals("jre"))
+ home = home.getParent();
+ Path release = home.resolve("release");
+ try (InputStream in = Files.newInputStream(release)) {
+ props.load(in);
+ }
+ String value = props.getProperty("JAVA_PROFILE");
+ if (isFullJre) {
+ if (value != null)
+ throw new RuntimeException("JAVA_PROFILE should not be present");
+ } else {
+ if (value == null)
+ throw new RuntimeException("JAVA_PROFILE not present in release file");
+ if (!value.equals("\"" + profile + "\""))
+ throw new RuntimeException("Unexpected value of JAVA_PROFILE: " + value);
+ }
+
+ System.out.println("Test passed.");
+ }
+}