From 361de486f66d87637e80d526ad8cf5733afe5fc8 Mon Sep 17 00:00:00 2001 From: alanb Date: Mon, 21 Jan 2013 23:21:15 -0500 Subject: [PATCH] 8003256: (profiles) Add support for profile identification Reviewed-by: dholmes, mchung, ksrini --- make/java/version/Makefile | 3 +- makefiles/GensrcMisc.gmk | 13 +- .../classes/sun/misc/Version.java.template | 95 ++++++++-- .../tools/launcher/profiles/VersionCheck.java | 169 ++++++++++++++++++ 4 files changed, 263 insertions(+), 17 deletions(-) create mode 100644 test/tools/launcher/profiles/VersionCheck.java diff --git a/make/java/version/Makefile b/make/java/version/Makefile index 76a16c355..824300ec6 100644 --- a/make/java/version/Makefile +++ b/make/java/version/Makefile @@ -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 @@ $(GENSRCDIR)/sun/misc/Version.java: \ -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 $@ diff --git a/makefiles/GensrcMisc.gmk b/makefiles/GensrcMisc.gmk index 7fdfa3c84..b8b174ee3 100644 --- a/makefiles/GensrcMisc.gmk +++ b/makefiles/GensrcMisc.gmk @@ -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 diff --git a/src/share/classes/sun/misc/Version.java.template b/src/share/classes/sun/misc/Version.java.template index 62babae10..710bf7178 100644 --- a/src/share/classes/sun/misc/Version.java.template +++ b/src/share/classes/sun/misc/Version.java.template @@ -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 @@ public class Version { "@@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 @@ public class Version { 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 @@ public class Version { 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_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(')'); + 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 @@ public class Version { 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. diff --git a/test/tools/launcher/profiles/VersionCheck.java b/test/tools/launcher/profiles/VersionCheck.java new file mode 100644 index 000000000..fc3a5f704 --- /dev/null +++ b/test/tools/launcher/profiles/VersionCheck.java @@ -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."); + } +} -- GitLab