From 0c96edbc0a480538989a6b663ea41c8c3f69c604 Mon Sep 17 00:00:00 2001 From: mchung Date: Thu, 2 Oct 2008 16:50:41 -0700 Subject: 6581243: Service Tag and Product Registration Support in JDK 7 Summary: Include service tag creation and product registration support in JDK Reviewed-by: ksrini --- make/com/sun/Makefile | 2 +- make/com/sun/servicetag/Makefile | 80 ++ .../classes/com/sun/servicetag/BrowserSupport.java | 199 +++++ .../classes/com/sun/servicetag/Installer.java | 965 +++++++++++++++++++++ .../com/sun/servicetag/LinuxSystemEnvironment.java | 193 +++++ .../com/sun/servicetag/RegistrationData.java | 475 ++++++++++ .../com/sun/servicetag/RegistrationDocument.java | 368 ++++++++ src/share/classes/com/sun/servicetag/Registry.java | 552 ++++++++++++ .../classes/com/sun/servicetag/ServiceTag.java | 634 ++++++++++++++ .../com/sun/servicetag/SolarisServiceTag.java | 62 ++ .../sun/servicetag/SolarisSystemEnvironment.java | 158 ++++ .../classes/com/sun/servicetag/SunConnection.java | 299 +++++++ .../com/sun/servicetag/SystemEnvironment.java | 338 ++++++++ .../servicetag/UnauthorizedAccessException.java | 53 ++ src/share/classes/com/sun/servicetag/Util.java | 336 +++++++ .../sun/servicetag/WindowsSystemEnvironment.java | 144 +++ src/share/classes/com/sun/servicetag/package.html | 71 ++ .../com/sun/servicetag/resources/Putback-Notes.txt | 25 + .../resources/javase_5_swordfish.properties | 29 + .../resources/javase_6_swordfish.properties | 29 + .../resources/javase_7_swordfish.properties | 29 + .../com/sun/servicetag/resources/jdk_header.png | Bin 0 -> 19005 bytes .../servicetag/resources/product_registration.xsd | 301 +++++++ .../com/sun/servicetag/resources/register.html | 105 +++ .../com/sun/servicetag/resources/register_ja.html | 91 ++ .../sun/servicetag/resources/register_zh_CN.html | 92 ++ test/com/sun/servicetag/DeleteServiceTag.java | 129 +++ test/com/sun/servicetag/DuplicateNotFound.java | 97 +++ test/com/sun/servicetag/FindServiceTags.java | 133 +++ test/com/sun/servicetag/InstanceUrnCheck.java | 76 ++ .../sun/servicetag/InvalidRegistrationData.java | 65 ++ test/com/sun/servicetag/InvalidServiceTag.java | 96 ++ test/com/sun/servicetag/JavaServiceTagTest.java | 176 ++++ test/com/sun/servicetag/JavaServiceTagTest1.java | 240 +++++ test/com/sun/servicetag/NewRegistrationData.java | 105 +++ test/com/sun/servicetag/SvcTagClient.java | 200 +++++ test/com/sun/servicetag/SystemRegistryTest.java | 131 +++ test/com/sun/servicetag/TestLoadFromXML.java | 69 ++ test/com/sun/servicetag/UpdateServiceTagTest.java | 109 +++ test/com/sun/servicetag/Util.java | 250 ++++++ test/com/sun/servicetag/ValidRegistrationData.java | 112 +++ test/com/sun/servicetag/environ.properties | 9 + test/com/sun/servicetag/missing-environ-field.xml | 45 + test/com/sun/servicetag/newer-registry-version.xml | 32 + test/com/sun/servicetag/registration.xml | 61 ++ test/com/sun/servicetag/servicetag1.properties | 13 + test/com/sun/servicetag/servicetag2.properties | 13 + test/com/sun/servicetag/servicetag3.properties | 13 + test/com/sun/servicetag/servicetag4.properties | 13 + test/com/sun/servicetag/servicetag5.properties | 13 + 50 files changed, 7829 insertions(+), 1 deletion(-) create mode 100644 make/com/sun/servicetag/Makefile create mode 100644 src/share/classes/com/sun/servicetag/BrowserSupport.java create mode 100644 src/share/classes/com/sun/servicetag/Installer.java create mode 100644 src/share/classes/com/sun/servicetag/LinuxSystemEnvironment.java create mode 100644 src/share/classes/com/sun/servicetag/RegistrationData.java create mode 100644 src/share/classes/com/sun/servicetag/RegistrationDocument.java create mode 100644 src/share/classes/com/sun/servicetag/Registry.java create mode 100644 src/share/classes/com/sun/servicetag/ServiceTag.java create mode 100644 src/share/classes/com/sun/servicetag/SolarisServiceTag.java create mode 100644 src/share/classes/com/sun/servicetag/SolarisSystemEnvironment.java create mode 100644 src/share/classes/com/sun/servicetag/SunConnection.java create mode 100644 src/share/classes/com/sun/servicetag/SystemEnvironment.java create mode 100644 src/share/classes/com/sun/servicetag/UnauthorizedAccessException.java create mode 100644 src/share/classes/com/sun/servicetag/Util.java create mode 100644 src/share/classes/com/sun/servicetag/WindowsSystemEnvironment.java create mode 100644 src/share/classes/com/sun/servicetag/package.html create mode 100644 src/share/classes/com/sun/servicetag/resources/Putback-Notes.txt create mode 100644 src/share/classes/com/sun/servicetag/resources/javase_5_swordfish.properties create mode 100644 src/share/classes/com/sun/servicetag/resources/javase_6_swordfish.properties create mode 100644 src/share/classes/com/sun/servicetag/resources/javase_7_swordfish.properties create mode 100644 src/share/classes/com/sun/servicetag/resources/jdk_header.png create mode 100644 src/share/classes/com/sun/servicetag/resources/product_registration.xsd create mode 100644 src/share/classes/com/sun/servicetag/resources/register.html create mode 100644 src/share/classes/com/sun/servicetag/resources/register_ja.html create mode 100644 src/share/classes/com/sun/servicetag/resources/register_zh_CN.html create mode 100644 test/com/sun/servicetag/DeleteServiceTag.java create mode 100644 test/com/sun/servicetag/DuplicateNotFound.java create mode 100644 test/com/sun/servicetag/FindServiceTags.java create mode 100644 test/com/sun/servicetag/InstanceUrnCheck.java create mode 100644 test/com/sun/servicetag/InvalidRegistrationData.java create mode 100644 test/com/sun/servicetag/InvalidServiceTag.java create mode 100644 test/com/sun/servicetag/JavaServiceTagTest.java create mode 100644 test/com/sun/servicetag/JavaServiceTagTest1.java create mode 100644 test/com/sun/servicetag/NewRegistrationData.java create mode 100644 test/com/sun/servicetag/SvcTagClient.java create mode 100644 test/com/sun/servicetag/SystemRegistryTest.java create mode 100644 test/com/sun/servicetag/TestLoadFromXML.java create mode 100644 test/com/sun/servicetag/UpdateServiceTagTest.java create mode 100644 test/com/sun/servicetag/Util.java create mode 100644 test/com/sun/servicetag/ValidRegistrationData.java create mode 100644 test/com/sun/servicetag/environ.properties create mode 100644 test/com/sun/servicetag/missing-environ-field.xml create mode 100644 test/com/sun/servicetag/newer-registry-version.xml create mode 100644 test/com/sun/servicetag/registration.xml create mode 100644 test/com/sun/servicetag/servicetag1.properties create mode 100644 test/com/sun/servicetag/servicetag2.properties create mode 100644 test/com/sun/servicetag/servicetag3.properties create mode 100644 test/com/sun/servicetag/servicetag4.properties create mode 100644 test/com/sun/servicetag/servicetag5.properties diff --git a/make/com/sun/Makefile b/make/com/sun/Makefile index 0328f120d..188e73670 100644 --- a/make/com/sun/Makefile +++ b/make/com/sun/Makefile @@ -41,7 +41,7 @@ endif # Omit mirror since it's built with the apt tool. SUBDIRS = $(SCRIPT_SUBDIR) image security crypto/provider jndi jmx \ java inputmethods org xml rowset net/httpserver net/ssl demo \ - tools jarsigner tracing + tools jarsigner tracing servicetag all build clean clobber:: $(SUBDIRS-loop) diff --git a/make/com/sun/servicetag/Makefile b/make/com/sun/servicetag/Makefile new file mode 100644 index 000000000..e7914e827 --- /dev/null +++ b/make/com/sun/servicetag/Makefile @@ -0,0 +1,80 @@ +# Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. + +BUILDDIR = ../../.. +PACKAGE = com.sun.servicetag +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +# +# Files to compile +# +AUTO_FILES_JAVA_DIRS = com/sun/servicetag + +# +# Rules +# +include $(BUILDDIR)/common/Classes.gmk + +SERVICETAG_LIBDIR = $(LIBDIR)/servicetag +SERVICETAG_RESOURCES_DIR = $(CLASSDESTDIR)/com/sun/servicetag/resources +FILES_copy = $(SERVICETAG_RESOURCES_DIR)/product_registration.xsd \ + $(SERVICETAG_RESOURCES_DIR)/register.html \ + $(SERVICETAG_RESOURCES_DIR)/register_ja.html \ + $(SERVICETAG_RESOURCES_DIR)/register_zh_CN.html \ + $(SERVICETAG_LIBDIR)/jdk_header.png + +# Add all properties files to the FILES_copy list +SWORDFISH_properties := $(shell \ + $(CD) $(SHARE_SRC)/classes/com/sun/servicetag/resources; \ + $(FIND) . -name 'javase_*_swordfish.properties' -print ; \ + ) +FILES_copy += $(shell \ + for f in $(SWORDFISH_properties) ; do \ + echo $(SERVICETAG_RESOURCES_DIR)/$$f ; \ + done \ +) + + +# +#OTHER_JAVACFLAGS += -Xlint:unchecked + +build: install-servicetag-lib copy-files + +copy-files: $(FILES_copy) + +$(CLASSBINDIR)/%: $(SHARE_SRC)/classes/% + $(install-file) + +$(SERVICETAG_LIBDIR)/jdk_header.png: $(SHARE_SRC)/classes/com/sun/servicetag/resources/jdk_header.png + $(install-file) + $(CHMOD) 444 $@ + +install-servicetag-lib: + @$(RM) -rf $(SERVICETAG_LIBDIR) + $(MKDIR) $(SERVICETAG_LIBDIR) + +clean clobber:: + @$(RM) $(FILES_copy) + +.PHONY: copy-files diff --git a/src/share/classes/com/sun/servicetag/BrowserSupport.java b/src/share/classes/com/sun/servicetag/BrowserSupport.java new file mode 100644 index 000000000..c77769bfc --- /dev/null +++ b/src/share/classes/com/sun/servicetag/BrowserSupport.java @@ -0,0 +1,199 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.io.IOException; +import java.net.URI; + +/** + * BrowserSupport class. + * + * The implementation of the com.sun.servicetag API needs to be + * compiled with JDK 5 as well since the consumer of this API + * may require to support JDK 5 (e.g. NetBeans). + * + * The Desktop.browse() method can be backported in this class + * if needed. The current implementation only supports JDK 6. + */ +class BrowserSupport { + private static boolean isBrowseSupported = false; + private static Method browseMethod = null; + private static Object desktop = null; + private static volatile Boolean result = false; + + + private static void initX() { + if (desktop != null) { + return; + } + boolean supported = false; + Method browseM = null; + Object desktopObj = null; + try { + // Determine if java.awt.Desktop is supported + Class desktopCls = Class.forName("java.awt.Desktop", true, null); + Method getDesktopM = desktopCls.getMethod("getDesktop"); + browseM = desktopCls.getMethod("browse", URI.class); + + Class actionCls = Class.forName("java.awt.Desktop$Action", true, null); + final Method isDesktopSupportedMethod = desktopCls.getMethod("isDesktopSupported"); + Method isSupportedMethod = desktopCls.getMethod("isSupported", actionCls); + Field browseField = actionCls.getField("BROWSE"); + // isDesktopSupported calls getDefaultToolkit which can block + // infinitely, see 6636099 for details, to workaround we call + // in a thread and time it out, noting that the issue is specific + // to X11, it does not hurt for Windows. + Thread xthread = new Thread() { + public void run() { + try { + // support only if Desktop.isDesktopSupported() and + // Desktop.isSupported(Desktop.Action.BROWSE) return true. + result = (Boolean) isDesktopSupportedMethod.invoke(null); + } catch (IllegalAccessException e) { + // should never reach here + InternalError x = + new InternalError("Desktop.getDesktop() method not found"); + x.initCause(e); + } catch (InvocationTargetException e) { + // browser not supported + if (Util.isVerbose()) { + e.printStackTrace(); + } + } + } + }; + // set it to daemon, so that the vm will exit. + xthread.setDaemon(true); + xthread.start(); + try { + xthread.join(5 * 1000); + } catch (InterruptedException ie) { + // ignore the exception + } + if (result.booleanValue()) { + desktopObj = getDesktopM.invoke(null); + result = (Boolean) isSupportedMethod.invoke(desktopObj, browseField.get(null)); + supported = result.booleanValue(); + } + } catch (ClassNotFoundException e) { + // browser not supported + if (Util.isVerbose()) { + e.printStackTrace(); + } + } catch (NoSuchMethodException e) { + // browser not supported + if (Util.isVerbose()) { + e.printStackTrace(); + } + } catch (NoSuchFieldException e) { + // browser not supported + if (Util.isVerbose()) { + e.printStackTrace(); + } + } catch (IllegalAccessException e) { + // should never reach here + InternalError x = + new InternalError("Desktop.getDesktop() method not found"); + x.initCause(e); + throw x; + } catch (InvocationTargetException e) { + // browser not supported + if (Util.isVerbose()) { + e.printStackTrace(); + } + } + isBrowseSupported = supported; + browseMethod = browseM; + desktop = desktopObj; + } + + static boolean isSupported() { + initX(); + return isBrowseSupported; + } + + /** + * Launches the default browser to display a {@code URI}. + * If the default browser is not able to handle the specified + * {@code URI}, the application registered for handling + * {@code URIs} of the specified type is invoked. The application + * is determined from the protocol and path of the {@code URI}, as + * defined by the {@code URI} class. + *

+ * This method calls the Desktop.getDesktop().browse() method. + *

+ * @param uri the URI to be displayed in the user default browser + * + * @throws NullPointerException if {@code uri} is {@code null} + * @throws UnsupportedOperationException if the current platform + * does not support the {@link Desktop.Action#BROWSE} action + * @throws IOException if the user default browser is not found, + * or it fails to be launched, or the default handler application + * failed to be launched + * @throws IllegalArgumentException if the necessary permissions + * are not available and the URI can not be converted to a {@code URL} + */ + static void browse(URI uri) throws IOException { + if (uri == null) { + throw new NullPointerException("null uri"); + } + if (!isSupported()) { + throw new UnsupportedOperationException("Browse operation is not supported"); + } + + // Call Desktop.browse() method + try { + if (Util.isVerbose()) { + System.out.println("desktop: " + desktop + ":browsing..." + uri); + } + browseMethod.invoke(desktop, uri); + } catch (IllegalAccessException e) { + // should never reach here + InternalError x = + new InternalError("Desktop.getDesktop() method not found"); + x.initCause(e); + throw x; + } catch (InvocationTargetException e) { + Throwable x = e.getCause(); + if (x != null) { + if (x instanceof UnsupportedOperationException) { + throw (UnsupportedOperationException) x; + } else if (x instanceof IllegalArgumentException) { + throw (IllegalArgumentException) x; + } else if (x instanceof IOException) { + throw (IOException) x; + } else if (x instanceof SecurityException) { + throw (SecurityException) x; + } else { + // ignore + } + } + } + } +} diff --git a/src/share/classes/com/sun/servicetag/Installer.java b/src/share/classes/com/sun/servicetag/Installer.java new file mode 100644 index 000000000..0cda7afe3 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/Installer.java @@ -0,0 +1,965 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +import java.io.*; +import java.util.HashSet; +import java.util.Locale; +import java.util.Properties; +import java.util.Set; +import java.util.List; +import java.util.ArrayList; +import static com.sun.servicetag.Util.*; + +/** + * Service Tag Installer for Java SE. + */ +public class Installer { + // System properties for testing + private static String SVCTAG_DIR_PATH = + "servicetag.dir.path"; + private static String SVCTAG_ENABLE_REGISTRATION = + "servicetag.registration.enabled"; + private final static String SUN_VENDOR = "Sun Microsystems"; + private final static String REGISTRATION_XML = "registration.xml"; + private final static String SERVICE_TAG_FILE = "servicetag"; + private final static String REGISTRATION_HTML_NAME = "register"; + + private final static Locale[] knownSupportedLocales = + new Locale[] { Locale.ENGLISH, + Locale.JAPANESE, + Locale.SIMPLIFIED_CHINESE}; + + private final static String javaHome = System.getProperty("java.home"); + private static File svcTagDir; + private static File serviceTagFile; + private static File regXmlFile; + private static RegistrationData registration; + private static boolean supportRegistration; + private static String registerHtmlParent; + private static Set supportedLocales = new HashSet(); + private static Properties swordfishProps = null; + private static String[] jreArchs = null; + static { + String dir = System.getProperty(SVCTAG_DIR_PATH); + if (dir == null) { + svcTagDir = new File(getJrePath(), "lib" + File.separator + SERVICE_TAG_FILE); + } else { + svcTagDir = new File(dir); + } + serviceTagFile = new File(svcTagDir, SERVICE_TAG_FILE); + regXmlFile = new File(svcTagDir, REGISTRATION_XML); + if (System.getProperty(SVCTAG_ENABLE_REGISTRATION) == null) { + supportRegistration = isJdk(); + } else { + supportRegistration = true; + } + } + + private Installer() { + } + + // Implementation of ServiceTag.getJavaServiceTag(String) method + static ServiceTag getJavaServiceTag(String source) throws IOException { + if (!System.getProperty("java.vendor").startsWith(SUN_VENDOR)) { + // Products bundling this implementation may run on + // Mac OS which is not a Sun JDK + return null; + } + boolean cleanup = false; + try { + // Check if we have the swordfish entries for this JRE version + if (loadSwordfishEntries() == null) { + return null; + } + + ServiceTag st = getJavaServiceTag(); + // Check if the service tag created by this bundle owner + if (st != null && st.getSource().equals(source)) { + // Install the system service tag if supported + // stclient may be installed after the service tag creation + if (Registry.isSupported()) { + installSystemServiceTag(); + } + return st; + } + + // in case any exception thrown during the cleanup + cleanup = true; + + // re-create a new one for this bundle owner + // first delete the registration data + deleteRegistrationData(); + cleanup = false; + + // create service tag and generate new register.html pages + return createServiceTag(source); + } finally { + if (cleanup) { + if (regXmlFile.exists()) { + regXmlFile.delete(); + } + if (serviceTagFile.exists()) { + serviceTagFile.delete(); + } + } + } + } + + /** + * Returns the Java SE registration data located in + * the /lib/servicetag/registration.xml by default. + * + * @throws IllegalArgumentException if the registration data + * is of invalid format. + */ + private static synchronized RegistrationData getRegistrationData() + throws IOException { + if (registration != null) { + return registration; + } + if (regXmlFile.exists()) { + BufferedInputStream in = null; + try { + in = new BufferedInputStream(new FileInputStream(regXmlFile)); + registration = RegistrationData.loadFromXML(in); + } catch (IllegalArgumentException ex) { + System.err.println("Error: Bad registration data \"" + + regXmlFile + "\":" + ex.getMessage()); + throw ex; + } finally { + if (in != null) { + in.close(); + } + } + } else { + registration = new RegistrationData(); + } + return registration; + } + + /** + * Write the registration data to the registration.xml file. + * + * The offline registration page has to be regenerated with + * the new registration data. + * + * @throws java.io.IOException + */ + private static synchronized void writeRegistrationXml() + throws IOException { + if (!svcTagDir.exists()) { + // This check is for NetBeans or other products that + // bundles this com.sun.servicetag implementation for + // pre-6u5 release. + if (!svcTagDir.mkdir()) { + throw new IOException("Failed to create directory: " + svcTagDir); + } + } + + // regenerate the new offline registration page + deleteRegistrationHtmlPage(); + getRegistrationHtmlPage(); + + BufferedOutputStream out = null; + try { + out = new BufferedOutputStream(new FileOutputStream(regXmlFile)); + getRegistrationData().storeToXML(out); + } catch (IllegalArgumentException ex) { + System.err.println("Error: Bad registration data \"" + + regXmlFile + "\":" + ex.getMessage()); + throw ex; + } finally { + if (out != null) { + out.close(); + } + } + } + + /** + * Returns the instance urn(s) stored in the servicetag file + * or empty set if file not exists. + */ + private static Set getInstalledURNs() throws IOException { + Set urnSet = new HashSet(); + if (serviceTagFile.exists()) { + BufferedReader in = null; + try { + in = new BufferedReader(new FileReader(serviceTagFile)); + String urn; + while ((urn = in.readLine()) != null) { + urn = urn.trim(); + if (urn.length() > 0) { + urnSet.add(urn); + } + } + } finally { + if (in != null) { + in.close(); + } + } + } + return urnSet; + } + + /** + * Return the Java SE service tag(s) if it exists. + * Typically only one Java SE service tag but it could have two for + * Solaris 32-bit and 64-bit on the same install directory. + * + * @return the service tag(s) for Java SE + */ + private static ServiceTag[] getJavaServiceTagArray() throws IOException { + RegistrationData regData = getRegistrationData(); + Set svcTags = regData.getServiceTags(); + Set result = new HashSet(); + + Properties props = loadSwordfishEntries(); + String jdkUrn = props.getProperty("servicetag.jdk.urn"); + String jreUrn = props.getProperty("servicetag.jre.urn"); + for (ServiceTag st : svcTags) { + if (st.getProductURN().equals(jdkUrn) || + st.getProductURN().equals(jreUrn)) { + result.add(st); + } + } + return result.toArray(new ServiceTag[0]); + } + + /** + * Returns the Java SE service tag for this running platform; + * or null if not exist. + * This method will return the 64-bit service tag if the JDK + * supports both 32-bit and 64-bit if already created. + */ + private static ServiceTag getJavaServiceTag() throws IOException { + String definedId = getProductDefinedId(); + for (ServiceTag st : getJavaServiceTagArray()) { + if (st.getProductDefinedInstanceID().equals(definedId)) { + return st; + } + } + return null; + } + + /** + * Create a service tag for Java SE and install in the system + * service tag registry if supported. + * + * A registration data /lib/servicetag/registration.xml + * will be created to storeToXML the XML entry for Java SE service tag. + * If the system supports service tags, this method will install + * the Java SE service tag in the system service tag registry and + * its instance_urn will be stored to /lib/servicetag/servicetag. + * + * If /lib/servicetag/registration.xml exists but is not installed + * in the system service tag registry (i.e. servicetag doesn't exist), + * this method will install it as described above. + * + * If the system supports service tag, stclient will be used + * to create the Java SE service tag. + * + * A Solaris 32-bit and 64-bit JDK will be installed in the same + * directory but the registration.xml will have 2 service tags. + * The servicetag file will also contain 2 instance_urns for that case. + */ + private static ServiceTag createServiceTag(String svcTagSource) + throws IOException { + // determine if a new service tag is needed to be created + ServiceTag newSvcTag = null; + if (getJavaServiceTag() == null) { + newSvcTag = newServiceTag(svcTagSource); + } + + // Add the new service tag in the registration data + if (newSvcTag != null) { + RegistrationData regData = getRegistrationData(); + + // Add the service tag to the registration data in JDK/JRE + newSvcTag = regData.addServiceTag(newSvcTag); + + // add if there is a service tag for the OS + ServiceTag osTag = SolarisServiceTag.getServiceTag(); + if (osTag != null && regData.getServiceTag(osTag.getInstanceURN()) == null) { + regData.addServiceTag(osTag); + } + // write to the registration.xml + writeRegistrationXml(); + } + + // Install the system service tag if supported + if (Registry.isSupported()) { + installSystemServiceTag(); + } + return newSvcTag; + } + + private static void installSystemServiceTag() throws IOException { + // only install the service tag in the registry if + // it has permission to write the servicetag file. + if ((!serviceTagFile.exists() && !svcTagDir.canWrite()) || + (serviceTagFile.exists() && !serviceTagFile.canWrite())) { + return; + } + + Set urns = getInstalledURNs(); + ServiceTag[] javaSvcTags = getJavaServiceTagArray(); + if (urns.size() < javaSvcTags.length) { + for (ServiceTag st : javaSvcTags) { + // Add the service tag in the system service tag registry + // if not installed + String instanceURN = st.getInstanceURN(); + if (!urns.contains(instanceURN)) { + Registry.getSystemRegistry().addServiceTag(st); + } + } + } + writeInstalledUrns(); + } + + private static ServiceTag newServiceTag(String svcTagSource) throws IOException { + // Load the swoRDFish information for the service tag creation + Properties props = loadSwordfishEntries(); + + // Determine the product URN and name + String productURN; + String productName; + + if (isJdk()) { + // /jre exists which implies it's a JDK + productURN = props.getProperty("servicetag.jdk.urn"); + productName = props.getProperty("servicetag.jdk.name"); + } else { + // Otherwise, it's a JRE + productURN = props.getProperty("servicetag.jre.urn"); + productName = props.getProperty("servicetag.jre.name"); + } + + return ServiceTag.newInstance(ServiceTag.generateInstanceURN(), + productName, + System.getProperty("java.version"), + productURN, + props.getProperty("servicetag.parent.name"), + props.getProperty("servicetag.parent.urn"), + getProductDefinedId(), + SUN_VENDOR, + System.getProperty("os.arch"), + getZoneName(), + svcTagSource); + } + + /** + * Delete the registration data, the offline registration pages and + * the service tags in the system service tag registry if installed. + * + * The registration.xml and servicetag file will be removed. + */ + private static synchronized void deleteRegistrationData() + throws IOException { + try { + // delete the offline registration page + deleteRegistrationHtmlPage(); + + // Remove the service tag from the system ST registry if exists + Set urns = getInstalledURNs(); + if (urns.size() > 0 && Registry.isSupported()) { + for (String u : urns) { + Registry.getSystemRegistry().removeServiceTag(u); + } + } + registration = null; + } finally { + // Delete the registration.xml and servicetag files if exists + if (regXmlFile.exists()) { + if (!regXmlFile.delete()) { + throw new IOException("Failed to delete " + regXmlFile); + } + } + if (serviceTagFile.exists()) { + if (!serviceTagFile.delete()) { + throw new IOException("Failed to delete " + serviceTagFile); + } + } + } + } + + /** + * Updates the registration data to contain one single service tag + * for the running Java runtime. + */ + private static synchronized void updateRegistrationData(String svcTagSource) + throws IOException { + RegistrationData regData = getRegistrationData(); + ServiceTag curSvcTag = newServiceTag(svcTagSource); + + ServiceTag[] javaSvcTags = getJavaServiceTagArray(); + Set urns = getInstalledURNs(); + for (ServiceTag st : javaSvcTags) { + if (!st.getProductDefinedInstanceID().equals(curSvcTag.getProductDefinedInstanceID())) { + String instanceURN = st.getInstanceURN(); + regData.removeServiceTag(instanceURN); + + // remove it from the system service tag registry if exists + if (urns.contains(instanceURN) && Registry.isSupported()) { + Registry.getSystemRegistry().removeServiceTag(instanceURN); + } + } + } + writeRegistrationXml(); + writeInstalledUrns(); + } + + private static void writeInstalledUrns() throws IOException { + // if the Registry is not supported, + // remove the servicetag file + if (!Registry.isSupported() && serviceTagFile.exists()) { + serviceTagFile.delete(); + return; + } + + PrintWriter out = null; + try { + out = new PrintWriter(serviceTagFile); + + ServiceTag[] javaSvcTags = getJavaServiceTagArray(); + for (ServiceTag st : javaSvcTags) { + // Write the instance_run to the servicetag file + String instanceURN = st.getInstanceURN(); + out.println(instanceURN); + } + } finally { + if (out != null) { + out.close(); + } + } + } + + /** + * Load the values associated with the swoRDFish metadata entries + * for Java SE. The swoRDFish metadata entries are different for + * different release. + * + * @param version Version of Java SE + */ + private static synchronized Properties loadSwordfishEntries() throws IOException { + if (swordfishProps != null) { + return swordfishProps; + } + + // The version string for Java SE 6 is 1.6.0 + // We just need the minor number in the version string + int version = Util.getJdkVersion(); + + String filename = "/com/sun/servicetag/resources/javase_" + + version + "_swordfish.properties"; + InputStream in = Installer.class.getClass().getResourceAsStream(filename); + if (in == null) { + return null; + } + swordfishProps = new Properties(); + try { + swordfishProps.load(in); + } finally { + in.close(); + } + return swordfishProps; + } + + /** + * Returns the product defined instance ID for Java SE. + * It is a list of comma-separated name/value pairs: + * "id= []*" + * "dir=" + * + * where is the full version string of the JRE, + * is the architecture that the runtime supports + * (i.e. "sparc", "sparcv9", "i386", "amd64" (ISA list)) + * + * For Solaris, it can be dual mode that can support both + * 32-bit and 64-bit. the "id" will be set to + * "1.6.0_03-b02 sparc sparcv9" + * + * The "dir" property is included in the service tag to enable + * the Service Tag software to determine if a service tag for + * Java SE is invalid and perform appropriate service tag + * cleanup if necessary. See RFE# 6574781 Service Tags Enhancement. + * + */ + private static String getProductDefinedId() { + StringBuilder definedId = new StringBuilder(); + definedId.append("id="); + definedId.append(System.getProperty("java.runtime.version")); + + String[] archs = getJreArchs(); + for (String name : archs) { + definedId.append(" " + name); + } + + String location = ",dir=" + javaHome; + if ((definedId.length() + location.length()) < 256) { + definedId.append(",dir="); + definedId.append(javaHome); + } else { + // if it exceeds the limit, we will not include the location + if (isVerbose()) { + System.err.println("Warning: Product defined instance ID exceeds the field limit:"); + } + } + + return definedId.toString(); + } + + /** + * Returns the architectures that the runtime supports + * (i.e. "sparc", "sparcv9", "i386", "amd64" (ISA list)) + * The directory name where libjava.so is located. + * + * On Windows, returns the "os.arch" system property value. + */ + private synchronized static String[] getJreArchs() { + if (jreArchs != null) { + return jreArchs; + } + + Set archs = new HashSet(); + + String os = System.getProperty("os.name"); + if (os.equals("SunOS") || os.equals("Linux")) { + // Traverse the directories under /lib. + // If /lib//libjava.so exists, add + // to the product defined ID + File dir = new File(getJrePath() + File.separator + "lib"); + if (dir.isDirectory()) { + String[] children = dir.list(); + for (String name : children) { + File f = new File(dir, name + File.separator + "libjava.so"); + if (f.exists()) { + archs.add(name); + } + } + } + } else { + // Windows - append the os.arch + archs.add(System.getProperty("os.arch")); + } + jreArchs = archs.toArray(new String[0]); + return jreArchs; + } + + /** + * Return the zonename if zone is supported; otherwise, return + * "global". + */ + private static String getZoneName() throws IOException { + String zonename = "global"; + + String command = "/usr/bin/zonename"; + File f = new File(command); + // com.sun.servicetag package has to be compiled with JDK 5 as well + // JDK 5 doesn't support the File.canExecute() method. + // Risk not checking isExecute() for the zonename command is very low. + if (f.exists()) { + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + if (p.exitValue() == 0) { + zonename = output.trim(); + } + + } + return zonename; + } + + private synchronized static String getRegisterHtmlParent() throws IOException { + if (registerHtmlParent == null) { + File htmlDir; // register.html is put under the JDK directory + if (getJrePath().endsWith(File.separator + "jre")) { + htmlDir = new File(getJrePath(), ".."); + } else { + // j2se non-image build + htmlDir = new File(getJrePath()); + } + + // initialize the supported locales + initSupportedLocales(htmlDir); + + // Determine the location of the offline registration page + String path = System.getProperty(SVCTAG_DIR_PATH); + if (path == null) { + // Default is /register.html + registerHtmlParent = htmlDir.getCanonicalPath(); + } else { + File f = new File(path); + registerHtmlParent = f.getCanonicalPath(); + if (!f.isDirectory()) { + throw new InternalError("Path " + path + " set in \"" + + SVCTAG_DIR_PATH + "\" property is not a directory"); + } + } + } + return registerHtmlParent; + } + + /** + * Returns the File object of the offline registration page localized + * for the default locale in the JDK directory. + */ + static synchronized File getRegistrationHtmlPage() throws IOException { + if (!supportRegistration) { + // No register.html page generated if JRE + return null; + } + + String parent = getRegisterHtmlParent(); + + // check if the offline registration page is already generated + File f = new File(parent, REGISTRATION_HTML_NAME + ".html"); + if (!f.exists()) { + // Generate the localized version of the offline registration Page + generateRegisterHtml(parent); + } + + String name = REGISTRATION_HTML_NAME; + Locale locale = getDefaultLocale(); + if (!locale.equals(Locale.ENGLISH) && supportedLocales.contains(locale)) { + // if the locale is not English and is supported by JDK + // set to the appropriate offline registration page; + // otherwise,set to register.html. + name = REGISTRATION_HTML_NAME + "_" + locale.toString(); + } + File htmlFile = new File(parent, name + ".html"); + if (isVerbose()) { + System.out.print("Offline registration page: " + htmlFile); + System.out.println((htmlFile.exists() ? + "" : " not exist. Use register.html")); + } + if (htmlFile.exists()) { + return htmlFile; + } else { + return new File(parent, + REGISTRATION_HTML_NAME + ".html"); + } + } + + private static Locale getDefaultLocale() { + List candidateLocales = getCandidateLocales(Locale.getDefault()); + for (Locale l : candidateLocales) { + if (supportedLocales.contains(l)) { + return l; + } + } + return Locale.getDefault(); + } + + private static List getCandidateLocales(Locale locale) { + String language = locale.getLanguage(); + String country = locale.getCountry(); + String variant = locale.getVariant(); + + List locales = new ArrayList(3); + if (variant.length() > 0) { + locales.add(locale); + } + if (country.length() > 0) { + locales.add((locales.size() == 0) ? + locale : new Locale(language, country, "")); + } + if (language.length() > 0) { + locales.add((locales.size() == 0) ? + locale : new Locale(language, "", "")); + } + return locales; + } + + // Remove the offline registration pages + private static void deleteRegistrationHtmlPage() throws IOException { + String parent = getRegisterHtmlParent(); + if (parent == null) { + return; + } + + for (Locale locale : supportedLocales) { + String name = REGISTRATION_HTML_NAME; + if (!locale.equals(Locale.ENGLISH)) { + name += "_" + locale.toString(); + } + File f = new File(parent, name + ".html"); + if (f.exists()) { + if (!f.delete()) { + throw new IOException("Failed to delete " + f); + } + } + } + } + + private static void initSupportedLocales(File jdkDir) { + if (supportedLocales.isEmpty()) { + // initialize with the known supported locales + for (Locale l : knownSupportedLocales) { + supportedLocales.add(l); + } + } + + // Determine unknown supported locales if any + // by finding the localized version of README.html + // This prepares if a new locale in JDK is supported in + // e.g. in the OpenSource world + FilenameFilter ff = new FilenameFilter() { + public boolean accept(File dir, String name) { + String fname = name.toLowerCase(); + if (fname.startsWith("readme") && fname.endsWith(".html")) { + return true; + } + return false; + } + }; + + String[] readmes = jdkDir.list(ff); + for (String name : readmes) { + String basename = name.substring(0, name.length() - ".html".length()); + String[] ss = basename.split("_"); + switch (ss.length) { + case 1: + // English version + break; + case 2: + supportedLocales.add(new Locale(ss[1])); + break; + case 3: + supportedLocales.add(new Locale(ss[1], ss[2])); + break; + default: + // ignore + break; + } + } + if (isVerbose()) { + System.out.println("Supported locales: "); + for (Locale l : supportedLocales) { + System.out.println(l); + } + } + } + + private static final String JDK_HEADER_PNG_KEY = "@@JDK_HEADER_PNG@@"; + private static final String JDK_VERSION_KEY = "@@JDK_VERSION@@"; + private static final String REGISTRATION_URL_KEY = "@@REGISTRATION_URL@@"; + private static final String REGISTRATION_PAYLOAD_KEY = "@@REGISTRATION_PAYLOAD@@"; + + @SuppressWarnings("unchecked") + private static void generateRegisterHtml(String parent) throws IOException { + int version = Util.getJdkVersion(); + int update = Util.getUpdateVersion(); + String jdkVersion = "Version " + version; + if (update > 0) { + // product name is not translated + jdkVersion += " Update " + update; + } + RegistrationData regData = getRegistrationData(); + // Make sure it uses the canonical path before getting the URI. + File img = new File(svcTagDir.getCanonicalPath(), "jdk_header.png"); + String headerImageSrc = img.toURI().toString(); + + // Format the registration data in one single line + StringBuilder payload = new StringBuilder(); + String xml = regData.toString().replaceAll("\"", "%22"); + BufferedReader reader = new BufferedReader(new StringReader(xml)); + try { + String line = null; + while ((line = reader.readLine()) != null) { + payload.append(line.trim()); + } + } finally { + reader.close(); + } + + String resourceFilename = "/com/sun/servicetag/resources/register"; + for (Locale locale : supportedLocales) { + String name = REGISTRATION_HTML_NAME; + String resource = resourceFilename; + if (!locale.equals(Locale.ENGLISH)) { + name += "_" + locale.toString(); + resource += "_" + locale.toString(); + } + File f = new File(parent, name + ".html"); + InputStream in = null; + BufferedReader br = null; + PrintWriter pw = null; + String registerURL = SunConnection. + getRegistrationURL(regData.getRegistrationURN(), + locale, + String.valueOf(version)).toString(); + try { + in = Installer.class.getClass().getResourceAsStream(resource + ".html"); + if (in == null) { + // if the resource file is missing + if (isVerbose()) { + System.out.println("Missing resouce file: " + resource + ".html"); + } + continue; + } + if (isVerbose()) { + System.out.println("Generating " + f + " from " + resource + ".html"); + } + + br = new BufferedReader(new InputStreamReader(in, "UTF-8")); + pw = new PrintWriter(f, "UTF-8"); + String line = null; + while ((line = br.readLine()) != null) { + String output = line; + if (line.contains(JDK_VERSION_KEY)) { + output = line.replace(JDK_VERSION_KEY, jdkVersion); + } else if (line.contains(JDK_HEADER_PNG_KEY)) { + output = line.replace(JDK_HEADER_PNG_KEY, headerImageSrc); + } else if (line.contains(REGISTRATION_URL_KEY)) { + output = line.replace(REGISTRATION_URL_KEY, registerURL); + } else if (line.contains(REGISTRATION_PAYLOAD_KEY)) { + output = line.replace(REGISTRATION_PAYLOAD_KEY, payload.toString()); + } + pw.println(output); + } + f.setReadOnly(); + pw.flush(); + } finally { + if (pw != null) { + pw.close(); + } + if (in != null) { + in.close(); + } + if (br!= null) { + br.close(); + } + } + } + } + + private static final int MAX_SOURCE_LEN = 63; + + /** + * A utility class to create a service tag for Java SE. + *

+ * Usage:
+ *

+ * <JAVA_HOME>/bin/java com.sun.servicetag.Installer + *
+ *

+ */ + public static void main(String[] args) { + String source = "Manual "; + String runtimeName = System.getProperty("java.runtime.name"); + if (runtimeName.startsWith("OpenJDK")) { + source = "OpenJDK "; + } + source += System.getProperty("java.runtime.version"); + if (source.length() > MAX_SOURCE_LEN) { + source = source.substring(0, MAX_SOURCE_LEN); + } + + // Parse the options (arguments starting with "-" ) + boolean delete = false; + boolean update = false; + boolean register = false; + int count = 0; + while (count < args.length) { + String arg = args[count]; + if (arg.trim().length() == 0) { + // skip empty arguments + count++; + continue; + } + + if (arg.equals("-source")) { + source = args[++count]; + } else if (arg.equals("-delete")) { + delete = true; + } else if (arg.equals("-register")) { + register = true; + } else { + usage(); + return; + } + count++; + } + try { + if (delete) { + deleteRegistrationData(); + } else { + ServiceTag[] javaSvcTags = getJavaServiceTagArray(); + String[] archs = getJreArchs(); + if (javaSvcTags.length > archs.length) { + // 64-bit has been uninstalled + // so remove the service tag + updateRegistrationData(source); + } else { + // create the service tag + createServiceTag(source); + } + } + + if (register) { + // Registration is only supported by JDK + // For testing purpose, override with a "servicetag.enable.registration" property + + RegistrationData regData = getRegistrationData(); + if (supportRegistration && !regData.getServiceTags().isEmpty()) { + SunConnection.register(regData, + getDefaultLocale(), + String.valueOf(Util.getJdkVersion())); + } + } + System.exit(0); + } catch (IOException e) { + System.err.println("I/O Error: " + e.getMessage()); + if (isVerbose()) { + e.printStackTrace(); + } + } catch (IllegalArgumentException ex) { + if (isVerbose()) { + ex.printStackTrace(); + } + } catch (Exception e) { + System.err.println("Error: " + e.getMessage()); + if (isVerbose()) { + e.printStackTrace(); + } + } + System.exit(1); + } + + private static void usage() { + System.out.println("Usage:"); + System.out.print(" " + Installer.class.getName()); + System.out.println(" [-delete|-source |-register]"); + System.out.println(" to create a service tag for the Java platform"); + System.out.println(""); + System.out.println("Internal Options:"); + System.out.println(" -source: to specify the source of the service tag to be created"); + System.out.println(" -delete: to delete the service tag "); + System.out.println(" -register: to register the JDK"); + System.out.println(" -help: to print this help message"); + } +} diff --git a/src/share/classes/com/sun/servicetag/LinuxSystemEnvironment.java b/src/share/classes/com/sun/servicetag/LinuxSystemEnvironment.java new file mode 100644 index 000000000..e78c2f4cc --- /dev/null +++ b/src/share/classes/com/sun/servicetag/LinuxSystemEnvironment.java @@ -0,0 +1,193 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +// This class is a copy of the com.sun.scn.servicetags.LinuxSystemEnvironment +// class from the Sun Connection source. +// +// The Service Tags team maintains the latest version of the implementation +// for system environment data collection. JDK will include a copy of +// the most recent released version for a JDK release. We rename +// the package to com.sun.servicetag so that the Sun Connection +// product always uses the latest version from the com.sun.scn.servicetags +// package. JDK and users of the com.sun.servicetag API +// (e.g. NetBeans and SunStudio) will use the version in JDK. +// +// So we keep this class in src/share/classes instead of src//classes. + +import java.io.*; + +/** + * Linux implementation of the SystemEnvironment class. + */ +class LinuxSystemEnvironment extends SystemEnvironment { + LinuxSystemEnvironment() { + setHostId(getLinuxHostId()); + setSystemModel(getCommandOutput("/bin/uname", "-i")); + setSystemManufacturer(getLinuxSystemManufacturer()); + setCpuManufacturer(getLinuxCpuManufacturer()); + setSerialNumber(getLinuxSN()); + } + private String dmiInfo = null; + + private static final int SN = 1; + private static final int SYS = 2; + private static final int CPU = 3; + + private String getLinuxHostId() { + String output = getCommandOutput("/usr/bin/hostid"); + // trim off the leading 0x + if (output.startsWith("0x")) { + output = output.substring(2); + } + return output; + } + + /** + * Tries to obtain and return the cpu manufacturer. + * @return The cpu manufacturer (an empty string if not found or an error occurred) + */ + private String getLinuxCpuManufacturer() { + String tmp = getLinuxPSNInfo(CPU); + if (tmp.length() > 0) { + return tmp; + } + + String contents = getFileContent("/proc/cpuinfo"); + for (String line : contents.split("\n")) { + if (line.contains("vendor_id")) { + String[] ss = line.split(":", 2); + if (ss.length > 1) { + return ss[1].trim(); + } + } + } + + // returns an empty string if it can't be found or an error happened + return getLinuxDMIInfo("dmi type 4", "manufacturer"); + } + + + /** + * Tries to obtain and return the system manufacturer. + * @return The system manufacturer (an empty string if not found or an error occurred) + */ + private String getLinuxSystemManufacturer() { + String tmp = getLinuxPSNInfo(SYS); + if (tmp.length() > 0) { + return tmp; + } + + // returns an empty string if it can't be found or an error happened + return getLinuxDMIInfo("dmi type 1", "manufacturer"); + } + + /** + * Tries to obtain and return the serial number of the system. + * @return The serial number (an empty string if not found or an error occurred) + */ + private String getLinuxSN() { + String tmp = getLinuxPSNInfo(SN); + if (tmp.length() > 0) { + return tmp; + } + + // returns an empty string if it can't be found or an error happened + return getLinuxDMIInfo("dmi type 1", "serial number"); + } + + private String getLinuxPSNInfo(int target) { + // try to read from the psn file if it exists + String contents = getFileContent("/var/run/psn"); + String[] ss = contents.split("\n"); + if (target <= ss.length) { + return ss[target-1]; + } + + // default case is to return "" + return ""; + } + + // reads from dmidecode with the given type and target + // returns an empty string if nothing was found or an error occurred + // + // Sample output segment: + // Handle 0x0001 + // DMI type 1, 25 bytes. + // System Information + // Manufacturer: System manufacturer + // Product Name: System Product Name + // Version: System Version + // Serial Number: System Serial Number + // UUID: 3091D719-B25B-D911-959D-6D1B12C7686E + // Wake-up Type: Power Switch + + private synchronized String getLinuxDMIInfo(String dmiType, String target) { + // only try to get dmidecode information once, after that, we can + // reuse the output + if (dmiInfo == null) { + Thread dmidecodeThread = new Thread() { + public void run() { + dmiInfo = getCommandOutput("/usr/sbin/dmidecode"); + } + }; + dmidecodeThread.start(); + + try { + dmidecodeThread.join(2000); + if (dmidecodeThread.isAlive()) { + dmidecodeThread.interrupt(); + dmiInfo = ""; + } + } catch (InterruptedException ie) { + dmidecodeThread.interrupt(); + } + } + + if (dmiInfo.length() == 0) { + return ""; + } + boolean dmiFlag = false; + for (String s : dmiInfo.split("\n")) { + String line = s.toLowerCase(); + if (dmiFlag) { + if (line.contains(target)) { + String key = target + ":"; + int indx = line.indexOf(key) + key.length(); + if (line.contains(key) && indx < line.length()) { + return line.substring(indx).trim(); + } + String[] ss = line.split(":"); + return ss[ss.length-1]; + } + } else if (line.contains(dmiType)) { + dmiFlag = true; + } + } + return ""; + } + +} diff --git a/src/share/classes/com/sun/servicetag/RegistrationData.java b/src/share/classes/com/sun/servicetag/RegistrationData.java new file mode 100644 index 000000000..1ed3abab7 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/RegistrationData.java @@ -0,0 +1,475 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +import java.io.*; +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import static com.sun.servicetag.RegistrationDocument.*; + +/** + * A {@code RegistrationData} object is a container of one or more + * {@link #getServiceTags service tags} that identify the + * components for product registration. + * Each {@code RegistrationData} object has a {@link #getRegistrationURN + * uniform resource name} (URN) as its identifier. + * + * It also has an environment map with + * the following elements: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
hostnameHostname of the systeme.g. woody
hostIdHost ID of the systeme.g. 83abc1ab
osNameOperating system name e.g. SunOS
osVersionOperating system version e.g. 5.10
osArchitectureOperating system architecture e.g. sparc
systemModelSystem model e.g. SUNW,Sun-Fire-V440
systemManufacturerSystem manufacturer e.g. Sun Microsystems
cpuManufacturerCPU manufacturer e.g. Sun Microsystems
serialNumberSystem serial number e.g. BEL078932
+ *
+ * The hostname and osName element must have a non-empty value. + * If an element is not available on a system and their value will be + * empty. + *

+ * + * Registration XML Schema + *

+ * A {@code RegistrationData} object can be {@link #loadFromXML loaded} from + * and {@link #storeToXML stored} into an XML file in the format described + * by the + * + * registration data schema. The registration data schema is defined by the + * Service Tags Technology. + *

+ * Typically the registration data is constructed at installation time + * and stored in an XML file for later service tag lookup or registration. + * + *

+ * Example Usage + *

+ * The examples below show how the {@code RegistrationData} can be + * used for product registration. + * Exception handling is not shown in these examples for clarity. + *

    + *
  1. This example shows how the JDK creates a JDK service tag, installs it + * in the system service tag registry and adds it to the registration data. + *
    + *
    + *   // create a service tag object with an instance_urn
    + *   ServiceTag st = ServiceTag.newInstance(ServiceTag.generateInstanceURN(),
    + *                                          ....);
    + *   // Adds to the system service tag registry if supported
    + *   if (Registry.isSupported()) {
    + *       Registry.getSystemRegistry().addServiceTag(st);
    + *   }
    + *
    + *   // add to the registration data
    + *   RegistrationData registration  = new RegistrationData();
    + *   registration.addServiceTag(st);
    + * 
    + *
  2. + *
  3. At this point, the registration data is ready to + * send to Sun Connection for registration. This example shows how to register + * the JDK via the Registration Relay Service. + *

    + * There are several registration services for Sun Connection. For example, + * the + * Registration Relay Service is a web application interface that + * processes the registration data payload sent via HTTP post + * and hosts the registration user interface for a specified + * registration URL. Refer to the + * Registration Relay Service Specification for details. + *

    + *

    + *   // Open the connection to the URL of the registration service
    + *   HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
    + *   con.setDoInput(true);
    + *   con.setDoOutput(true);
    + *   con.setUseCaches(false);
    + *   con.setAllowUserInteraction(false);
    + *   con.setRequestMethod("POST");
    + *   con.setRequestProperty("Content-Type", "text/xml;charset=\"utf-8\"");
    + *   con.connect();
    + *
    + *   // send the registration data to the registration service
    + *   OutputStream out = con.getOutputStream();
    + *   registration.storeToXML(out);
    + *   out.close();
    + * 
    + *
  4. + *
  5. This example shows how to store the registration data in an XML file. + * for later service tag lookup or registration. + *
    + *
    + *   BufferedOutputStream out = new BufferedOutputStream(
    + *       new FileOutputStream(""<JAVA_HOME>/lib/servicetag/registration.xml"));
    + *   registration.storeToXML(out);
    + *   out.close();
    + * 
    + *
  6. + *
  7. This example shows how to install service tags that are in the + * registration data in the system service tag registry when determined + * to be available. The system service tag registry might not have existed + * when the registration data was constructed. + *
    + *
    + *   if (Registry.isSupported()) {
    + *       Set<ServiceTag> svctags = registration.getServiceTags();
    + *       for (ServiceTag st : svctags) {
    + *           Registry.getSystemRegistry().addServiceTag(st);
    + *       }
    + *   }
    + * 
    + *
  8. + *
+ * + * @see Sun Connection Inventory Channel + */ +public class RegistrationData { + private final Map environment = initEnvironment(); + private final Map svcTagMap = + new LinkedHashMap(); + private final String urn; + + /** + * Creates a {@code RegistrationData} object with a generated + * {@link #getRegistrationURN registration URN}. + * The following keys in the {@link #getEnvironmentMap environment map} + * will be initialized for the configuration of the + * running system: + *
+ * hostname, osName, osVersion and + * osArchitecture + *
+ * and the value of other keys may be empty. + */ + public RegistrationData() { + this(Util.generateURN()); + SystemEnvironment sysEnv = SystemEnvironment.getSystemEnvironment(); + setEnvironment(ST_NODE_HOSTNAME, sysEnv.getHostname()); + setEnvironment(ST_NODE_HOST_ID, sysEnv.getHostId()); + setEnvironment(ST_NODE_OS_NAME, sysEnv.getOsName()); + setEnvironment(ST_NODE_OS_VERSION, sysEnv.getOsVersion()); + setEnvironment(ST_NODE_OS_ARCH, sysEnv.getOsArchitecture()); + setEnvironment(ST_NODE_SYSTEM_MODEL, sysEnv.getSystemModel()); + setEnvironment(ST_NODE_SYSTEM_MANUFACTURER, sysEnv.getSystemManufacturer()); + setEnvironment(ST_NODE_CPU_MANUFACTURER, sysEnv.getCpuManufacturer()); + setEnvironment(ST_NODE_SERIAL_NUMBER, sysEnv.getSerialNumber()); + } + + // package private + RegistrationData(String urn) { + this.urn = urn; + } + + private Map initEnvironment() { + Map map = new LinkedHashMap(); + map.put(ST_NODE_HOSTNAME, ""); + map.put(ST_NODE_HOST_ID, ""); + map.put(ST_NODE_OS_NAME, ""); + map.put(ST_NODE_OS_VERSION, ""); + map.put(ST_NODE_OS_ARCH, ""); + map.put(ST_NODE_SYSTEM_MODEL, ""); + map.put(ST_NODE_SYSTEM_MANUFACTURER, ""); + map.put(ST_NODE_CPU_MANUFACTURER, ""); + map.put(ST_NODE_SERIAL_NUMBER, ""); + return map; + } + + /** + * Returns the uniform resource name of this registration data + * in this format: + * urn:st:<32-char {@link java.util.UUID uuid}> + * + * @return the URN of this registration data. + */ + public String getRegistrationURN() { + return urn; + } + + /** + * Returns a map containing the environment information for this + * registration data. See the set of keys + * in the environment map. Subsequent update to the environment + * map via the {@link #setEnvironment setEnvironment} method will not be reflected + * in the returned map. + * + * @return an environment map for this registration data. + */ + public Map getEnvironmentMap() { + return new LinkedHashMap(environment); + } + + /** + * Sets an element of the specified {@code name} in the environment map + * with the given {@code value}. + * + * @throws IllegalArgumentException if {@code name} is not a valid key + * in the environment map, or {@code value} is not valid. + */ + public void setEnvironment(String name, String value) { + if (name == null) { + throw new NullPointerException("name is null"); + } + if (value == null) { + throw new NullPointerException("value is null"); + } + if (environment.containsKey(name)) { + if (name.equals(ST_NODE_HOSTNAME) || name.equals(ST_NODE_OS_NAME)) { + if (value.length() == 0) { + throw new IllegalArgumentException("\"" + + name + "\" requires non-empty value."); + } + } + environment.put(name, value); + } else { + throw new IllegalArgumentException("\"" + + name + "\" is not an environment element."); + } + } + + /** + * Returns all service tags in this registration data. + * + * @return a {@link Set Set} of the service tags + * in this registration data. + */ + public Set getServiceTags() { + return new HashSet(svcTagMap.values()); + } + + /** + * Adds a service tag to this registration data. + * If the given service tag has an empty instance_urn, + * this method will generate a URN and place it in the copy + * of the service tag in this registration data. + * This method will return the {@code ServiceTag} object + * added to this registration data. + * + * @param st {@code ServiceTag} object to be added. + * @return a {@code ServiceTag} object added to this registration data. + * + * @throws IllegalArgumentException if + * a service tag of the same {@link ServiceTag#getInstanceURN + * instance_urn} already exists in the registry. + */ + public synchronized ServiceTag addServiceTag(ServiceTag st) { + ServiceTag svcTag = ServiceTag.newInstanceWithUrnTimestamp(st); + + String instanceURN = svcTag.getInstanceURN(); + if (svcTagMap.containsKey(instanceURN)) { + throw new IllegalArgumentException("Instance_urn = " + instanceURN + + " already exists in the registration data."); + } else { + svcTagMap.put(instanceURN, svcTag); + } + return svcTag; + } + + /** + * Returns a service tag of the given instance_urn in this registration + * data. + * + * @param instanceURN the instance_urn of the service tag + * @return the {@code ServiceTag} object of the given instance_urn + * if exists; otherwise return {@code null}. + */ + public synchronized ServiceTag getServiceTag(String instanceURN) { + if (instanceURN == null) { + throw new NullPointerException("instanceURN is null"); + } + return svcTagMap.get(instanceURN); + } + + /** + * Removes a service tag of the given instance_urn from this + * registration data. + * + * @param instanceURN the instance_urn of + * the service tag to be removed. + * + * @return the removed {@code ServiceTag} object; + * or {@code null} if the service tag does not exist in this + * registration data. + */ + public synchronized ServiceTag removeServiceTag(String instanceURN) { + if (instanceURN == null) { + throw new NullPointerException("instanceURN is null"); + } + + ServiceTag svcTag = null; + if (svcTagMap.containsKey(instanceURN)) { + svcTag = svcTagMap.remove(instanceURN); + } + return svcTag; + } + + /** + * Updates the product_defined_instance_id in the service tag + * of the given instance_urn in this registration data. + * + * @param instanceURN the instance_urn of the service tag to be updated. + * @param productDefinedInstanceID the value of the + * product_defined_instance_id to be set. + * + * @return the updated {@code ServiceTag} object; + * or {@code null} if the service tag does not exist in this + * registration data. + */ + public synchronized ServiceTag updateServiceTag(String instanceURN, + String productDefinedInstanceID) { + ServiceTag svcTag = getServiceTag(instanceURN); + if (svcTag == null) { + return null; + } + + svcTag = ServiceTag.newInstanceWithUrnTimestamp(svcTag); + // update the product defined instance ID field + svcTag.setProductDefinedInstanceID(productDefinedInstanceID); + svcTagMap.put(instanceURN, svcTag); + return svcTag; + } + + /** + * Reads the registration data from the XML document on the + * specified input stream. The XML document must be + * in the format described by the + * registration data schema. + * The specified stream is closed after this method returns. + * + * @param in the input stream from which to read the XML document. + * @return a {@code RegistrationData} object read from the input + * stream. + * + * @throws IllegalArgumentException if the input stream + * contains an invalid registration data. + * + * @throws IOException if an error occurred when reading from the input stream. + */ + public static RegistrationData loadFromXML(InputStream in) throws IOException { + try { + return RegistrationDocument.load(in); + } finally { + in.close(); + } + } + + /** + * Writes the registration data to the specified output stream + * in the format described by the + * registration data schema with "UTF-8" encoding. + * The specified stream remains open after this method returns. + * + * @param os the output stream on which to write the XML document. + * + * @throws IOException if an error occurred when writing to the output stream. + */ + public void storeToXML(OutputStream os) throws IOException { + RegistrationDocument.store(os, this); + os.flush(); + } + + /** + * Returns a newly allocated byte array containing the registration + * data in XML format. + * + * @return a newly allocated byte array containing the registration + * data in XML format. + */ + public byte[] toXML() { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + storeToXML(out); + return out.toByteArray(); + } catch (IOException e) { + // should not reach here + return new byte[0]; + } + } + + /** + * Returns a string representation of this registration data in XML + * format. + * + * @return a string representation of this registration data in XML + * format. + */ + @Override + public String toString() { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + storeToXML(out); + return out.toString("UTF-8"); + } catch (IOException e) { + // should not reach here + return "Error creating the return string."; + } + } +} diff --git a/src/share/classes/com/sun/servicetag/RegistrationDocument.java b/src/share/classes/com/sun/servicetag/RegistrationDocument.java new file mode 100644 index 000000000..34d5127b7 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/RegistrationDocument.java @@ -0,0 +1,368 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +import java.io.*; +import java.net.URL; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; +import org.xml.sax.InputSource; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +// For write operation +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +/** + * XML Support Class for Product Registration. + */ +class RegistrationDocument { + + private static final String REGISTRATION_DATA_SCHEMA = + "/com/sun/servicetag/resources/product_registration.xsd"; + private static final String REGISTRATION_DATA_VERSION = "1.0"; + private static final String SERVICE_TAG_VERSION = "1.0"; + final static String ST_NODE_REGISTRATION_DATA = "registration_data"; + final static String ST_ATTR_REGISTRATION_VERSION = "version"; + final static String ST_NODE_ENVIRONMENT = "environment"; + final static String ST_NODE_HOSTNAME = "hostname"; + final static String ST_NODE_HOST_ID = "hostId"; + final static String ST_NODE_OS_NAME = "osName"; + final static String ST_NODE_OS_VERSION = "osVersion"; + final static String ST_NODE_OS_ARCH = "osArchitecture"; + final static String ST_NODE_SYSTEM_MODEL = "systemModel"; + final static String ST_NODE_SYSTEM_MANUFACTURER = "systemManufacturer"; + final static String ST_NODE_CPU_MANUFACTURER = "cpuManufacturer"; + final static String ST_NODE_SERIAL_NUMBER = "serialNumber"; + final static String ST_NODE_REGISTRY = "registry"; + final static String ST_ATTR_REGISTRY_URN = "urn"; + final static String ST_ATTR_REGISTRY_VERSION = "version"; + final static String ST_NODE_SERVICE_TAG = "service_tag"; + final static String ST_NODE_INSTANCE_URN = "instance_urn"; + final static String ST_NODE_PRODUCT_NAME = "product_name"; + final static String ST_NODE_PRODUCT_VERSION = "product_version"; + final static String ST_NODE_PRODUCT_URN = "product_urn"; + final static String ST_NODE_PRODUCT_PARENT_URN = "product_parent_urn"; + final static String ST_NODE_PRODUCT_PARENT = "product_parent"; + final static String ST_NODE_PRODUCT_DEFINED_INST_ID = "product_defined_inst_id"; + final static String ST_NODE_PRODUCT_VENDOR = "product_vendor"; + final static String ST_NODE_PLATFORM_ARCH = "platform_arch"; + final static String ST_NODE_TIMESTAMP = "timestamp"; + final static String ST_NODE_CONTAINER = "container"; + final static String ST_NODE_SOURCE = "source"; + final static String ST_NODE_INSTALLER_UID = "installer_uid"; + + static RegistrationData load(InputStream in) throws IOException { + Document document = initializeDocument(in); + + // Gets the registration URN + Element root = getRegistrationDataRoot(document); + Element registryRoot = + getSingletonElementFromRoot(root, ST_NODE_REGISTRY); + String urn = registryRoot.getAttribute(ST_ATTR_REGISTRY_URN); + + // Construct a new RegistrationData object from the DOM tree + // Initialize the environment map and service tags + RegistrationData regData = new RegistrationData(urn); + addServiceTags(registryRoot, regData); + + Element envRoot = getSingletonElementFromRoot(root, ST_NODE_ENVIRONMENT); + buildEnvironmentMap(envRoot, regData); + return regData; + } + + static void store(OutputStream os, RegistrationData registration) + throws IOException { + // create a new document with the root node + Document document = initializeDocument(); + + // create the nodes for the environment map and the service tags + // in the registration data + addEnvironmentNodes(document, + registration.getEnvironmentMap()); + addServiceTagRegistry(document, + registration.getRegistrationURN(), + registration.getServiceTags()); + transform(document, os); + } + + // initialize a document from an input stream + private static Document initializeDocument(InputStream in) throws IOException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + try { + // XML schema for validation + SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + URL xsdUrl = RegistrationDocument.class.getResource(REGISTRATION_DATA_SCHEMA); + Schema schema = sf.newSchema(xsdUrl); + Validator validator = schema.newValidator(); + + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(new InputSource(in)); + validator.validate(new DOMSource(doc)); + return doc; + } catch (SAXException sxe) { + IllegalArgumentException e = new IllegalArgumentException("Error generated in parsing"); + e.initCause(sxe); + throw e; + } catch (ParserConfigurationException pce) { + // Parser with specific options can't be built + // should not reach here + InternalError x = new InternalError("Error in creating the new document"); + x.initCause(pce); + throw x; + } + } + + // initialize a new document for the registration data + private static Document initializeDocument() throws IOException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.newDocument(); + + // initialize the document with the registration_data root + Element root = doc.createElement(ST_NODE_REGISTRATION_DATA); + doc.appendChild(root); + root.setAttribute(ST_ATTR_REGISTRATION_VERSION, REGISTRATION_DATA_VERSION); + + return doc; + } catch (ParserConfigurationException pce) { + // Parser with specified options can't be built + // should not reach here + InternalError x = new InternalError("Error in creating the new document"); + x.initCause(pce); + throw x; + } + } + + // Transform the current DOM tree with the given output stream. + private static void transform(Document document, OutputStream os) { + try { + // Use a Transformer for output + TransformerFactory tFactory = TransformerFactory.newInstance(); + tFactory.setAttribute("indent-number", new Integer(3)); + + Transformer transformer = tFactory.newTransformer(); + + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.STANDALONE, "yes"); + transformer.transform(new DOMSource(document), + new StreamResult(new BufferedWriter(new OutputStreamWriter(os, "UTF-8")))); + } catch (UnsupportedEncodingException ue) { + // Should not reach here + InternalError x = new InternalError("Error generated during transformation"); + x.initCause(ue); + throw x; + } catch (TransformerConfigurationException tce) { + // Error generated by the parser + // Should not reach here + InternalError x = new InternalError("Error in creating the new document"); + x.initCause(tce); + throw x; + } catch (TransformerException te) { + // Error generated by the transformer + InternalError x = new InternalError("Error generated during transformation"); + x.initCause(te); + throw x; + } + } + + private static void addServiceTagRegistry(Document document, + String registryURN, + Set svcTags) { + // add service tag registry node and its attributes + Element reg = document.createElement(ST_NODE_REGISTRY); + reg.setAttribute(ST_ATTR_REGISTRY_URN, registryURN); + reg.setAttribute(ST_ATTR_REGISTRY_VERSION, SERVICE_TAG_VERSION); + + Element root = getRegistrationDataRoot(document); + root.appendChild(reg); + + // adds the elements for the service tags + for (ServiceTag st : svcTags) { + addServiceTagElement(document, reg, st); + } + } + + private static void addServiceTagElement(Document document, + Element registryRoot, + ServiceTag st) { + Element svcTag = document.createElement(ST_NODE_SERVICE_TAG); + registryRoot.appendChild(svcTag); + addChildElement(document, svcTag, + ST_NODE_INSTANCE_URN, st.getInstanceURN()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_NAME, st.getProductName()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_VERSION, st.getProductVersion()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_URN, st.getProductURN()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_PARENT_URN, st.getProductParentURN()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_PARENT, st.getProductParent()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_DEFINED_INST_ID, + st.getProductDefinedInstanceID()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_VENDOR, st.getProductVendor()); + addChildElement(document, svcTag, + ST_NODE_PLATFORM_ARCH, st.getPlatformArch()); + addChildElement(document, svcTag, + ST_NODE_TIMESTAMP, Util.formatTimestamp(st.getTimestamp())); + addChildElement(document, svcTag, + ST_NODE_CONTAINER, st.getContainer()); + addChildElement(document, svcTag, + ST_NODE_SOURCE, st.getSource()); + addChildElement(document, svcTag, + ST_NODE_INSTALLER_UID, + String.valueOf(st.getInstallerUID())); + } + + private static void addChildElement(Document document, Element root, + String element, String text) { + Element node = document.createElement(element); + node.appendChild(document.createTextNode(text)); + root.appendChild(node); + } + + // Constructs service tags from the document + private static void addServiceTags(Element registryRoot, + RegistrationData registration) { + NodeList children = registryRoot.getElementsByTagName(ST_NODE_SERVICE_TAG); + int length = (children == null ? 0 : children.getLength()); + for (int i = 0; i < length; i++) { + Element svcTagElement = (Element) children.item(i); + ServiceTag st = getServiceTag(svcTagElement); + registration.addServiceTag(st); + } + } + + // build environment map from the document + private static void buildEnvironmentMap(Element envRoot, + RegistrationData registration) { + registration.setEnvironment(ST_NODE_HOSTNAME, getTextValue(envRoot, ST_NODE_HOSTNAME)); + registration.setEnvironment(ST_NODE_HOST_ID, getTextValue(envRoot, ST_NODE_HOST_ID)); + registration.setEnvironment(ST_NODE_OS_NAME, getTextValue(envRoot, ST_NODE_OS_NAME)); + registration.setEnvironment(ST_NODE_OS_VERSION, getTextValue(envRoot, ST_NODE_OS_VERSION)); + registration.setEnvironment(ST_NODE_OS_ARCH, getTextValue(envRoot, ST_NODE_OS_ARCH)); + registration.setEnvironment(ST_NODE_SYSTEM_MODEL, getTextValue(envRoot, ST_NODE_SYSTEM_MODEL)); + registration.setEnvironment(ST_NODE_SYSTEM_MANUFACTURER, getTextValue(envRoot, ST_NODE_SYSTEM_MANUFACTURER)); + registration.setEnvironment(ST_NODE_CPU_MANUFACTURER, getTextValue(envRoot, ST_NODE_CPU_MANUFACTURER)); + registration.setEnvironment(ST_NODE_SERIAL_NUMBER, getTextValue(envRoot, ST_NODE_SERIAL_NUMBER)); + } + + // add the nodes representing the environment map in the document + private static void addEnvironmentNodes(Document document, + Map envMap) { + Element root = getRegistrationDataRoot(document); + Element env = document.createElement(ST_NODE_ENVIRONMENT); + root.appendChild(env); + Set> keys = envMap.entrySet(); + for (Map.Entry entry : keys) { + addChildElement(document, env, entry.getKey(), entry.getValue()); + } + } + + private static Element getRegistrationDataRoot(Document doc) { + Element root = doc.getDocumentElement(); + if (!root.getNodeName().equals(ST_NODE_REGISTRATION_DATA)) { + throw new IllegalArgumentException("Not a " + + ST_NODE_REGISTRATION_DATA + + " node \"" + root.getNodeName() + "\""); + } + return root; + } + + private static Element getSingletonElementFromRoot(Element root, String name) { + NodeList children = root.getElementsByTagName(name); + int length = (children == null ? 0 : children.getLength()); + if (length != 1) { + throw new IllegalArgumentException("Invalid number of " + name + + " nodes = " + length); + } + Element e = (Element) children.item(0); + if (!e.getNodeName().equals(name)) { + throw new IllegalArgumentException("Not a " + name + + " node \"" + e.getNodeName() + "\""); + } + return e; + } + + // Constructs one ServiceTag instance from a service tag element root + private static ServiceTag getServiceTag(Element svcTagElement) { + return new ServiceTag( + getTextValue(svcTagElement, ST_NODE_INSTANCE_URN), + getTextValue(svcTagElement, ST_NODE_PRODUCT_NAME), + getTextValue(svcTagElement, ST_NODE_PRODUCT_VERSION), + getTextValue(svcTagElement, ST_NODE_PRODUCT_URN), + getTextValue(svcTagElement, ST_NODE_PRODUCT_PARENT), + getTextValue(svcTagElement, ST_NODE_PRODUCT_PARENT_URN), + getTextValue(svcTagElement, ST_NODE_PRODUCT_DEFINED_INST_ID), + getTextValue(svcTagElement, ST_NODE_PRODUCT_VENDOR), + getTextValue(svcTagElement, ST_NODE_PLATFORM_ARCH), + getTextValue(svcTagElement, ST_NODE_CONTAINER), + getTextValue(svcTagElement, ST_NODE_SOURCE), + Util.getIntValue(getTextValue(svcTagElement, ST_NODE_INSTALLER_UID)), + Util.parseTimestamp(getTextValue(svcTagElement, ST_NODE_TIMESTAMP)) + ); + } + + private static String getTextValue(Element e, String tagName) { + String value = ""; + NodeList nl = e.getElementsByTagName(tagName); + if (nl != null && nl.getLength() > 0) { + Element el = (Element) nl.item(0); + Node node = el.getFirstChild(); + if (node != null) { + value = node.getNodeValue(); + } + } + return value; + } +} diff --git a/src/share/classes/com/sun/servicetag/Registry.java b/src/share/classes/com/sun/servicetag/Registry.java new file mode 100644 index 000000000..aaf382ac4 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/Registry.java @@ -0,0 +1,552 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +import java.io.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; + +import static com.sun.servicetag.Util.*; +import static com.sun.servicetag.RegistrationDocument.*; + +/** + * A service tag registry is a XML-based registry containing + * the list of {@link ServiceTag service tags} installed in the system. + * The {@code Registry} class provides interfaces + * to add, remove, update, and get a service tag from a service tag + * registry. + * This {@code Registry} class may not be supported + * on all systems. The {@link #isSupported} method + * can be called to determine if it is supported. + *

+ * A registry may implement restrictions to only allow certain users + * to {@link #updateServiceTag update} and + * to {@link #removeServiceTag remove} a service tag record. Typically, + * only the owner of the service tag, the owner of the registry + * and superuser are authorized to update or remove a service tag in + * the registry. + * + * @see + * Service Tag User Guide + */ +public class Registry { + + private static final String STCLIENT_SOLARIS = "/usr/bin/stclient"; + private static final String STCLIENT_LINUX = "/opt/sun/servicetag/bin/stclient"; + // stclient exit value (see sthelper.h) + private static final int ST_ERR_NOT_AUTH = 245; + private static final int ST_ERR_REC_NOT_FOUND = 225; + + // The stclient output has to be an exported interface + private static final String INSTANCE_URN_DESC = "Product instance URN="; + private static boolean initialized = false; + private static boolean supportsHelperClass = true; // default + private static File stclient = null; + private static String stclientPath = null; + private static Registry registry = new Registry(); + + // System properties for testing + private static String SVCTAG_STCLIENT_CMD = "servicetag.stclient.cmd"; + private static String SVCTAG_STHELPER_SUPPORTED = "servicetag.sthelper.supported"; + + private Registry() { + } + + private synchronized static String getSTclient() { + if (!initialized) { + // the system property always overrides the default setting + if (System.getProperty(SVCTAG_STHELPER_SUPPORTED) != null) { + supportsHelperClass = Boolean.getBoolean(SVCTAG_STHELPER_SUPPORTED); + } + + // This is only used for testing + stclientPath = System.getProperty(SVCTAG_STCLIENT_CMD); + if (stclientPath != null) { + return stclientPath; + } + + // Initialization to determine the platform's stclient pathname + String os = System.getProperty("os.name"); + if (os.equals("SunOS")) { + stclient = new File(STCLIENT_SOLARIS); + } else if (os.equals("Linux")) { + stclient = new File(STCLIENT_LINUX); + } else if (os.startsWith("Windows")) { + stclient = getWindowsStClientFile(); + } else { + if (isVerbose()) { + System.out.println("Running on non-Sun JDK"); + } + } + initialized = true; + } + + // com.sun.servicetag package has to be compiled with JDK 5 as well + // JDK 5 doesn't support the File.canExecute() method. + // Risk not checking isExecute() for the stclient command is very low. + + if (stclientPath == null && stclient != null && stclient.exists()) { + stclientPath = stclient.getAbsolutePath(); + } + return stclientPath; + } + + /** + * Returns the system service tag registry. The {@code Registry} class + * may not be supported on some platforms; use the {@link #isSupported} + * method to determine if it is supported. + * + * @return the {@code Registry} object for the system service tag registry. + * + * @throws UnsupportedOperationException if the {@code Registry} class is + * not supported. + */ + public static Registry getSystemRegistry() { + if (isSupported()) { + return registry; + } else { + throw new UnsupportedOperationException("Registry class is not supported"); + } + } + + /** + * Returns {@code true} if the {@code Registry} class is supported on this system. + * + * @return {@code true} if the {@code Registry} class is supported; + * otherwise, return {@code false}. + */ + public static boolean isSupported() { + return (getSTclient() != null && supportsHelperClass); + } + + private static List getCommandList() { + // Set up the arguments to call stclient + List command = new ArrayList(); + if (System.getProperty(SVCTAG_STCLIENT_CMD) != null) { + // This is for jtreg testing use. This will be set to something + // like: + // $JAVA_HOME/bin/java -cp $TEST_DIR \ + // -Dstclient.registry.path=$TEST_DIR/registry.xml \ + // SvcTagClient + // + // On Windows, the JAVA_HOME and TEST_DIR path could contain + // space e.g. c:\Program Files\Java\jdk1.6.0_05\bin\java. + // The SVCTAG_STCLIENT_CMD must be set with a list of + // space-separated parameters. If a parameter contains spaces, + // it must be quoted with '"'. + + String cmd = getSTclient(); + int len = cmd.length(); + int i = 0; + while (i < len) { + char separator = ' '; + if (cmd.charAt(i) == '"') { + separator = '"'; + i++; + } + // look for the separator or matched the closing '"' + int j; + for (j = i+1; j < len; j++) { + if (cmd.charAt(j) == separator) { + break; + } + } + + if (i == j-1) { + // add an empty parameter + command.add("\"\""); + } else { + // double quotes and space are not included + command.add(cmd.substring(i,j)); + } + + // skip spaces + for (i = j+1; i < len; i++) { + if (!Character.isSpaceChar(cmd.charAt(i))) { + break; + } + } + } + if (isVerbose()) { + System.out.println("Command list:"); + for (String s : command) { + System.out.println(s); + } + } + } else { + command.add(getSTclient()); + } + return command; + } + + // Returns null if the service tag record not found; + // or throw UnauthorizedAccessException or IOException + // based on the exitValue. + private static ServiceTag checkReturnError(int exitValue, + String output, + ServiceTag st) throws IOException { + switch (exitValue) { + case ST_ERR_REC_NOT_FOUND: + return null; + case ST_ERR_NOT_AUTH: + if (st != null) { + throw new UnauthorizedAccessException( + "Not authorized to access " + st.getInstanceURN() + + " installer_uid=" + st.getInstallerUID()); + } else { + throw new UnauthorizedAccessException( + "Not authorized:" + output); + } + default: + throw new IOException("stclient exits with error" + + " (" + exitValue + ")\n" + output); + } + } + + /** + * Adds a service tag to this registry. + * If the given service tag has an empty instance_urn, + * this helper class will generate a URN and place it in the + * copy of the service tag in this registry. + * This method will return the {@code ServiceTag} representing + * the service tag entry to this registry. + * + * @param st {@code ServiceTag} object + * @return a {@code ServiceTag} object representing the service tag + * entry to this registry. + * + * @throws IllegalArgumentException if a service tag of the same + * instance_urn already exists in this registry. + * + * @throws java.io.IOException if an I/O error occurs in this operation. + */ + public ServiceTag addServiceTag(ServiceTag st) throws IOException { + List command = getCommandList(); + command.add("-a"); + if (st.getInstanceURN().length() > 0) { + ServiceTag sysSvcTag = getServiceTag(st.getInstanceURN()); + if (sysSvcTag != null) { + throw new IllegalArgumentException("Instance_urn = " + + st.getInstanceURN() + " already exists"); + } + command.add("-i"); + command.add(st.getInstanceURN()); + } + command.add("-p"); + command.add(st.getProductName()); + command.add("-e"); + command.add(st.getProductVersion()); + command.add("-t"); + command.add(st.getProductURN()); + if (st.getProductParentURN().length() > 0) { + command.add("-F"); + command.add(st.getProductParentURN()); + } + command.add("-P"); + command.add(st.getProductParent()); + if (st.getProductDefinedInstanceID().length() > 0) { + command.add("-I"); + command.add(st.getProductDefinedInstanceID()); + } + command.add("-m"); + command.add(st.getProductVendor()); + command.add("-A"); + command.add(st.getPlatformArch()); + command.add("-z"); + command.add(st.getContainer()); + command.add("-S"); + command.add(st.getSource()); + + BufferedReader in = null; + try { + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + if (isVerbose()) { + System.out.println("Output from stclient -a command:"); + System.out.println(output); + } + String urn = ""; + if (p.exitValue() == 0) { + // Obtain the instance urn from the stclient output + in = new BufferedReader(new StringReader(output)); + String line = null; + while ((line = in.readLine()) != null) { + line = line.trim(); + if (line.startsWith(INSTANCE_URN_DESC)) { + urn = line.substring(INSTANCE_URN_DESC.length()); + break; + } + } + if (urn.length() == 0) { + throw new IOException("Error in creating service tag:\n" + + output); + } + return getServiceTag(urn); + } else { + return checkReturnError(p.exitValue(), output, st); + } + } finally { + if (in != null) { + in.close(); + } + } + } + + /** + * Removes a service tag of the given instance_urn from this + * registry. + * + * @param instanceURN the instance_urn of the service tag + * to be removed. + * + * @return the {@code ServiceTag} object removed from this registry; + * or {@code null} if the service tag does not exist in this registry. + * + * @throws UnauthorizedAccessException if the user is not authorized to + * remove the service tag of the given instance_urn + * from this registry. + * + * @throws java.io.IOException if an I/O error occurs in this operation. + */ + public ServiceTag removeServiceTag(String instanceURN) throws IOException { + ServiceTag st = getServiceTag(instanceURN); + if (st == null) { + return null; + } + + List command = getCommandList(); + command.add("-d"); + command.add("-i"); + command.add(instanceURN); + + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + if (isVerbose()) { + System.out.println("Output from stclient -d command:"); + System.out.println(output); + } + if (p.exitValue() == 0) { + return st; + } else { + return checkReturnError(p.exitValue(), output, st); + } + } + + /** + * Updates the product_defined_instance_id in the service tag + * of the specified instance_urn in this registry. + * + * @param instanceURN the instance_urn of the service tag to be updated. + * @param productDefinedInstanceID the value of the + * product_defined_instance_id to be set. + * + * @return the updated {@code ServiceTag} object; + * or {@code null} if the service tag does not exist in this + * registry. + * + * @throws UnauthorizedAccessException if the user is not authorized to + * update the service tag from this registry. + * + * @throws IOException if an I/O error occurs in this operation. + */ + public ServiceTag updateServiceTag(String instanceURN, + String productDefinedInstanceID) + throws IOException { + ServiceTag svcTag = getServiceTag(instanceURN); + if (svcTag == null) { + return null; + } + + List command = getCommandList(); + command.add("-u"); + command.add("-i"); + command.add(instanceURN); + command.add("-I"); + if (productDefinedInstanceID.length() > 0) { + command.add(productDefinedInstanceID); + } else { + command.add("\"\""); + } + + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + if (isVerbose()) { + System.out.println("Output from stclient -u command:"); + System.out.println(output); + } + + if (p.exitValue() == 0) { + return getServiceTag(instanceURN); + } else { + return checkReturnError(p.exitValue(), output, svcTag); + } + } + + /** + * Returns a {@code ServiceTag} object of the given instance_urn + * in this registry. + * + * @param instanceURN the instance_urn of the service tag + * @return a {@code ServiceTag} object of the given instance_urn + * in this registry; or {@code null} if not found. + * + * @throws java.io.IOException if an I/O error occurs in this operation. + */ + public ServiceTag getServiceTag(String instanceURN) throws IOException { + if (instanceURN == null) { + throw new NullPointerException("instanceURN is null"); + } + + List command = getCommandList(); + command.add("-g"); + command.add("-i"); + command.add(instanceURN); + + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + if (isVerbose()) { + System.out.println("Output from stclient -g command:"); + System.out.println(output); + } + if (p.exitValue() == 0) { + return parseServiceTag(output); + } else { + return checkReturnError(p.exitValue(), output, null); + } + } + + private ServiceTag parseServiceTag(String output) throws IOException { + BufferedReader in = null; + try { + Properties props = new Properties(); + // parse the service tag output from stclient + in = new BufferedReader(new StringReader(output)); + String line = null; + while ((line = in.readLine()) != null) { + if ((line = line.trim()).length() > 0) { + String[] ss = line.trim().split("=", 2); + if (ss.length == 2) { + props.setProperty(ss[0].trim(), ss[1].trim()); + } else { + props.setProperty(ss[0].trim(), ""); + } + } + } + + String urn = props.getProperty(ST_NODE_INSTANCE_URN); + String productName = props.getProperty(ST_NODE_PRODUCT_NAME); + String productVersion = props.getProperty(ST_NODE_PRODUCT_VERSION); + String productURN = props.getProperty(ST_NODE_PRODUCT_URN); + String productParent = props.getProperty(ST_NODE_PRODUCT_PARENT); + String productParentURN = props.getProperty(ST_NODE_PRODUCT_PARENT_URN); + String productDefinedInstanceID = + props.getProperty(ST_NODE_PRODUCT_DEFINED_INST_ID); + String productVendor = props.getProperty(ST_NODE_PRODUCT_VENDOR); + String platformArch = props.getProperty(ST_NODE_PLATFORM_ARCH); + String container = props.getProperty(ST_NODE_CONTAINER); + String source = props.getProperty(ST_NODE_SOURCE); + int installerUID = + Util.getIntValue(props.getProperty(ST_NODE_INSTALLER_UID)); + Date timestamp = + Util.parseTimestamp(props.getProperty(ST_NODE_TIMESTAMP)); + + return new ServiceTag(urn, + productName, + productVersion, + productURN, + productParent, + productParentURN, + productDefinedInstanceID, + productVendor, + platformArch, + container, + source, + installerUID, + timestamp); + } finally { + if (in != null) { + in.close(); + } + } + + } + + /** + * Returns the service tags of the specified + * product_urn in this registry. + * + * @param productURN the product_urn to look up + * @return a {@code Set} of {@code ServiceTag} objects + * of the specified product_urn in this registry. + * + * @throws java.io.IOException if an I/O error occurs in this operation. + */ + public Set findServiceTags(String productURN) throws IOException { + if (productURN == null) { + throw new NullPointerException("productURN is null"); + } + + List command = getCommandList(); + command.add("-f"); + command.add("-t"); + command.add(productURN); + + BufferedReader in = null; + try { + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + + Set instances = new HashSet(); + if (p.exitValue() == 0) { + // parse the service tag output from stclient + in = new BufferedReader(new StringReader(output)); + String line = null; + while ((line = in.readLine()) != null) { + String s = line.trim(); + if (s.startsWith("urn:st:")) { + instances.add(getServiceTag(s)); + } + } + } else { + checkReturnError(p.exitValue(), output, null); + } + return instances; + } finally { + if (in != null) { + in.close(); + } + } + } +} diff --git a/src/share/classes/com/sun/servicetag/ServiceTag.java b/src/share/classes/com/sun/servicetag/ServiceTag.java new file mode 100644 index 000000000..dd4ce3e98 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/ServiceTag.java @@ -0,0 +1,634 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +import java.util.Date; +import java.io.IOException; +import static com.sun.servicetag.RegistrationDocument.*; + +/** + * A service tag is an XML-based data structure that identifies a product or + * a component on a system. The service tag schema is defined by the + * Service Tags Technology. The location of the DTD file is platform dependent. + * On Solaris, see /usr/share/lib/xml/dtd/servicetag.dtd. + *

+ * A valid {@code ServiceTag} instance must comply to the service tag schema + * and contain the following fields: + *

    + *
  • {@link #getInstanceURN instance_urn}
  • + *
  • {@link #getProductName product_name}
  • + *
  • {@link #getProductVersion product_version}
  • + *
  • {@link #getProductURN product_urn}
  • + *
  • {@link #getProductParent product_parent}
  • + *
  • {@link #getProductParentURN product_parent_urn}
  • + *
  • {@link #getProductDefinedInstanceID product_defined_inst_id}
  • + *
  • {@link #getProductVendor product_vendor}
  • + *
  • {@link #getPlatformArch platform_arch}
  • + *
  • {@link #getContainer container}
  • + *
  • {@link #getSource source}
  • + *
  • {@link #getInstallerUID installer_uid}
  • + *
  • {@link #getTimestamp timestamp}
  • + *
+ * + * The instance_urn can be specified when a {@code ServiceTag} + * object is created, or it can be generated when it is added to + * a {@link RegistrationData} object, or {@link Registry + * system service tag registry}. The installer_uid and + * timestamp are set when a {@code ServiceTag} object + * is added to a {@link RegistrationData} object, or {@link Registry + * system service tag registry}. + * + * @see Service Tags FAQ + */ +public class ServiceTag { + + private String instanceURN; + private String productName; + private String productVersion; + private String productURN; + private String productParent; + private String productParentURN; + private String productDefinedInstanceID; + private String productVendor; + private String platformArch; + private String container; + private String source; + private int installerUID; + private Date timestamp; + + // Service Tag Field Lengths (defined in sthelper.h) + // Since the constants defined in sthelper.h includes the null-terminated + // character, so minus 1 from the sthelper.h defined values. + private final int MAX_URN_LEN = 256 - 1; + private final int MAX_PRODUCT_NAME_LEN = 256 - 1; + private final int MAX_PRODUCT_VERSION_LEN = 64 - 1; + private final int MAX_PRODUCT_PARENT_LEN = 256 - 1; + private final int MAX_PRODUCT_VENDOR_LEN = 64 - 1; + private final int MAX_PLATFORM_ARCH_LEN = 64 - 1; + private final int MAX_CONTAINER_LEN = 64 - 1; + private final int MAX_SOURCE_LEN = 64 - 1; + + // private constructors + private ServiceTag() { + } + // package private + ServiceTag(String instanceURN, + String productName, + String productVersion, + String productURN, + String productParent, + String productParentURN, + String productDefinedInstanceID, + String productVendor, + String platformArch, + String container, + String source, + int installerUID, + Date timestamp) { + setInstanceURN(instanceURN); + setProductName(productName); + setProductVersion(productVersion); + setProductURN(productURN); + setProductParentURN(productParentURN); + setProductParent(productParent); + setProductDefinedInstanceID(productDefinedInstanceID); + setProductVendor(productVendor); + setPlatformArch(platformArch); + setContainer(container); + setSource(source); + setInstallerUID(installerUID); + setTimestamp(timestamp); + } + + /** + * Creates a service tag object with no instance_urn. + * + * @param productName the name of the product. + * @param productVersion the version of the product. + * @param productURN the uniform resource name of the product + * @param productParent the name of the product's parent. + * @param productParentURN the uniform resource name of the product's parent. + * @param productDefinedInstanceID the instance identifier. + * @param productVendor the vendor of the product. + * @param platformArch the operating system architecture. + * @param container the container of the product. + * @param source the source of the product. + * + * @throws IllegalArgumentException if any value of the input fields + * does not conform to the service tag XML schema. + */ + public static ServiceTag newInstance(String productName, + String productVersion, + String productURN, + String productParent, + String productParentURN, + String productDefinedInstanceID, + String productVendor, + String platformArch, + String container, + String source) { + return new ServiceTag("", /* empty instance_urn */ + productName, + productVersion, + productURN, + productParent, + productParentURN, + productDefinedInstanceID, + productVendor, + platformArch, + container, + source, + -1, + null); + } + + /** + * Creates a service tag object with a specified instance_urn. + * + * @param instanceURN the uniform resource name of this instance. + * @param productName the name of the product. + * @param productVersion the version of the product. + * @param productURN the uniform resource name of the product + * @param productParent the name of the product's parent. + * @param productParentURN the uniform resource name of the product's parent. + * @param productDefinedInstanceID the instance identifier. + * @param productVendor the vendor of the product. + * @param platformArch the operating system architecture. + * @param container the container of the product. + * @param source the source of the product. + * + * @throws IllegalArgumentException if any value of the input fields + * does not conform to the service tag XML schema. + */ + public static ServiceTag newInstance(String instanceURN, + String productName, + String productVersion, + String productURN, + String productParent, + String productParentURN, + String productDefinedInstanceID, + String productVendor, + String platformArch, + String container, + String source) { + return new ServiceTag(instanceURN, + productName, + productVersion, + productURN, + productParent, + productParentURN, + productDefinedInstanceID, + productVendor, + platformArch, + container, + source, + -1, + null); + } + + // Creates a copy of the ServiceTag instance + // with instance_urn and timestamp initialized + static ServiceTag newInstanceWithUrnTimestamp(ServiceTag st) { + String instanceURN = + (st.getInstanceURN().length() == 0 ? Util.generateURN() : + st.getInstanceURN()); + ServiceTag svcTag = new ServiceTag(instanceURN, + st.getProductName(), + st.getProductVersion(), + st.getProductURN(), + st.getProductParent(), + st.getProductParentURN(), + st.getProductDefinedInstanceID(), + st.getProductVendor(), + st.getPlatformArch(), + st.getContainer(), + st.getSource(), + st.getInstallerUID(), + new Date()); + return svcTag; + } + + /** + * Returns a uniform resource name (URN) in this format: + *
+ * "urn:st:<32-char {@link java.util.UUID uuid}>" + *
+ * @return a URN. + */ + public static String generateInstanceURN() { + return Util.generateURN(); + } + + /** + * Returns the uniform resource name of this service tag instance. + * + * @return the instance_urn of this service tag. + */ + public String getInstanceURN() { + return instanceURN; + } + + /** + * Returns the name of the product. + * + * @return the product name. + */ + public String getProductName() { + return productName; + } + + /** + * Returns the version of the product. + * + * @return the product version. + */ + public String getProductVersion() { + return productVersion; + } + + /** + * Returns the uniform resource name of the product. + * + * @return the product URN. + */ + public String getProductURN() { + return productURN; + } + + /** + * Returns the uniform resource name of the product's parent. + * + * @return the product's parent URN. + */ + public String getProductParentURN() { + return productParentURN; + } + + /** + * Returns the name of the product's parent. + * + * @return the product's parent name. + */ + public String getProductParent() { + return productParent; + } + + /** + * Returns the identifier defined for this product instance. + * + * @return the identifier defined for this product instance. + */ + public String getProductDefinedInstanceID() { + return productDefinedInstanceID; + } + + /** + * Returns the vendor of the product. + * + * @return the product vendor. + */ + public String getProductVendor() { + return productVendor; + } + + /** + * Returns the platform architecture on which the product + * is running on. + * + * @return the platform architecture on which the product is running on. + */ + public String getPlatformArch() { + return platformArch; + } + + /** + * Returns the timestamp. This timestamp is set when this service tag + * is added to or updated in a {@code RegistrationData} object or + * the system service tag registry. + * This method may return {@code null}. + * + * @return timestamp when this service tag + * is added to or updated in a {@code RegistrationData} object or + * the system service tag registry, or {@code null}. + */ + public Date getTimestamp() { + if (timestamp != null) { + return (Date) timestamp.clone(); + } else { + return null; + } + } + + + /** + * Returns the container of the product. + * + * @return the container of the product. + */ + public String getContainer() { + return container; + } + + /** + * Returns the source of this service tag. + * + * @return source of this service tag. + */ + public String getSource() { + return source; + } + + /** + * Returns the UID. The UID is set when this service tag + * is added to or updated in the system service tag registry. + * This is platform dependent whose default value is {@code -1}. + * When this service tag is added to a {@code RegistrationData}, + * the UID is not set. + * + * @return the UID of whom this service tag + * is added to or updated in the system service tag registry, + * or {@code -1}. + */ + public int getInstallerUID() { + return installerUID; + } + + // The following setter methods are used to validate the + // input field when constructing a ServiceTag instance + + private void setInstanceURN(String instanceURN) { + if (instanceURN == null) { + throw new NullPointerException("Parameter instanceURN cannot be null"); + } + if (instanceURN.length() > MAX_URN_LEN) { + throw new IllegalArgumentException("instanceURN \"" + instanceURN + + "\" exceeds maximum length " + MAX_URN_LEN); + } + this.instanceURN = instanceURN; + } + + private void setProductName(String productName) { + if (productName == null) { + throw new NullPointerException("Parameter productName cannot be null"); + } + if (productName.length() == 0) { + throw new IllegalArgumentException("product name cannot be empty"); + } + if (productName.length() > MAX_PRODUCT_NAME_LEN) { + throw new IllegalArgumentException("productName \"" + productName + + "\" exceeds maximum length " + MAX_PRODUCT_NAME_LEN); + } + this.productName = productName; + } + + private void setProductVersion(String productVersion) { + if (productVersion == null) { + throw new NullPointerException("Parameter productVersion cannot be null"); + } + + if (productVersion.length() == 0) { + throw new IllegalArgumentException("product version cannot be empty"); + } + if (productVersion.length() > MAX_PRODUCT_VERSION_LEN) { + throw new IllegalArgumentException("productVersion \"" + + productVersion + "\" exceeds maximum length " + + MAX_PRODUCT_VERSION_LEN); + } + this.productVersion = productVersion; + } + + private void setProductURN(String productURN) { + if (productURN == null) { + throw new NullPointerException("Parameter productURN cannot be null"); + } + if (productURN.length() == 0) { + throw new IllegalArgumentException("product URN cannot be empty"); + } + if (productURN.length() > MAX_URN_LEN) { + throw new IllegalArgumentException("productURN \"" + productURN + + "\" exceeds maximum length " + MAX_URN_LEN); + } + this.productURN = productURN; + } + + private void setProductParentURN(String productParentURN) { + if (productParentURN == null) { + throw new NullPointerException("Parameter productParentURN cannot be null"); + } + // optional field - can be empty + if (productParentURN.length() > MAX_URN_LEN) { + throw new IllegalArgumentException("productParentURN \"" + + productParentURN + "\" exceeds maximum length " + + MAX_URN_LEN); + } + this.productParentURN = productParentURN; + } + + private void setProductParent(String productParent) { + if (productParent == null) { + throw new NullPointerException("Parameter productParent cannot be null"); + } + if (productParent.length() == 0) { + throw new IllegalArgumentException("product parent cannot be empty"); + } + if (productParent.length() > MAX_PRODUCT_PARENT_LEN) { + throw new IllegalArgumentException("productParent \"" + + productParent + "\" exceeds maximum length " + + MAX_PRODUCT_PARENT_LEN); + } + this.productParent = productParent; + } + + void setProductDefinedInstanceID(String productDefinedInstanceID) { + if (productDefinedInstanceID == null) { + throw new NullPointerException("Parameter productDefinedInstanceID cannot be null"); + } + if (productDefinedInstanceID.length() > MAX_URN_LEN) { + throw new IllegalArgumentException("productDefinedInstanceID \"" + + productDefinedInstanceID + "\" exceeds maximum length " + + MAX_URN_LEN); + } + // optional field - can be empty + this.productDefinedInstanceID = productDefinedInstanceID; + } + + private void setProductVendor(String productVendor) { + if (productVendor == null) { + throw new NullPointerException("Parameter productVendor cannot be null"); + } + if (productVendor.length() == 0) { + throw new IllegalArgumentException("product vendor cannot be empty"); + } + if (productVendor.length() > MAX_PRODUCT_VENDOR_LEN) { + throw new IllegalArgumentException("productVendor \"" + + productVendor + "\" exceeds maximum length " + + MAX_PRODUCT_VENDOR_LEN); + } + this.productVendor = productVendor; + } + + private void setPlatformArch(String platformArch) { + if (platformArch == null) { + throw new NullPointerException("Parameter platformArch cannot be null"); + } + if (platformArch.length() == 0) { + throw new IllegalArgumentException("platform architecture cannot be empty"); + } + if (platformArch.length() > MAX_PLATFORM_ARCH_LEN) { + throw new IllegalArgumentException("platformArch \"" + + platformArch + "\" exceeds maximum length " + + MAX_PLATFORM_ARCH_LEN); + } + this.platformArch = platformArch; + } + + private void setTimestamp(Date timestamp) { + // can be null + this.timestamp = timestamp; + } + + private void setContainer(String container) { + if (container == null) { + throw new NullPointerException("Parameter container cannot be null"); + } + if (container.length() == 0) { + throw new IllegalArgumentException("container cannot be empty"); + } + if (container.length() > MAX_CONTAINER_LEN) { + throw new IllegalArgumentException("container \"" + + container + "\" exceeds maximum length " + + MAX_CONTAINER_LEN); + } + this.container = container; + } + + private void setSource(String source) { + if (source == null) { + throw new NullPointerException("Parameter source cannot be null"); + } + if (source.length() == 0) { + throw new IllegalArgumentException("source cannot be empty"); + } + if (source.length() > MAX_SOURCE_LEN) { + throw new IllegalArgumentException("source \"" + source + + "\" exceeds maximum length " + MAX_SOURCE_LEN); + } + this.source = source; + } + + private void setInstallerUID(int installerUID) { + this.installerUID = installerUID; + } + + /** + * Compares this service tag to the specified object. + * The result is {@code true} if and only if the argument is + * not {@code null} and is a {@code ServiceTag} object whose + * instance_urn is the same as the + * instance_urn of this service tag. + * + * @return {@code true} if this service tag is the same as + * the specified object. + */ + @Override + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof ServiceTag)) { + return false; + } + ServiceTag st = (ServiceTag) obj; + if (st == this) { + return true; + } + return st.getInstanceURN().equals(getInstanceURN()); + } + + /** + * Returns the hash code value for this service tag. + * @return the hash code value for this service tag. + */ + @Override + public int hashCode() { + int hash = 7; + hash = 19 * hash + (this.instanceURN != null ? this.instanceURN.hashCode() : 0); + return hash; + } + + /** + * Returns the string representation of this service tag. + * The format is implementation specific. + * + * @return the string representation of this service tag. + */ + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(ST_NODE_INSTANCE_URN).append("=").append(instanceURN).append("\n"); + sb.append(ST_NODE_PRODUCT_NAME).append("=").append(productName).append("\n"); + sb.append(ST_NODE_PRODUCT_VERSION).append("=").append(productVersion).append("\n"); + sb.append(ST_NODE_PRODUCT_URN).append("=").append(productURN).append("\n"); + sb.append(ST_NODE_PRODUCT_PARENT_URN).append("=").append(productParentURN).append("\n"); + sb.append(ST_NODE_PRODUCT_PARENT).append("=").append(productParent).append("\n"); + sb.append(ST_NODE_PRODUCT_DEFINED_INST_ID).append("=").append(productDefinedInstanceID).append("\n"); + sb.append(ST_NODE_PRODUCT_VENDOR).append("=").append(productVendor).append("\n"); + sb.append(ST_NODE_PLATFORM_ARCH).append("=").append(platformArch).append("\n"); + sb.append(ST_NODE_TIMESTAMP).append("=").append(Util.formatTimestamp(timestamp)).append("\n"); + sb.append(ST_NODE_CONTAINER).append("=").append(container).append("\n"); + sb.append(ST_NODE_SOURCE).append("=").append(source).append("\n"); + sb.append(ST_NODE_INSTALLER_UID).append("=").append(String.valueOf(installerUID)).append("\n"); + return sb.toString(); + } + + + /** + * Returns the {@link ServiceTag} instance for the running Java + * platform. The {@link ServiceTag#setSource source} field + * of the {@code ServiceTag} will be set to the given {@code source}. + * This method will return {@code null} if there is no service tag + * for the running Java platform. + *

+ * This method is designed for Sun software that bundles the JDK + * or the JRE to use. It is recommended that the {@code source} + * string contains information about the bundling software + * such as the name and the version of the software bundle, + * for example, + *

+ * NetBeans IDE 6.0 with JDK 6 Update 5 Bundle + *
+ * in a NetBeans/JDK bundle. + *

+ * At the first time to call this method the application + * is required to have the write permission to the installed + * directory of this running JDK or JRE instance. + * + * @param source the source that bundles the JDK or the JRE. + * @return a {@code ServiceTag} object for the Java platform, + * or {@code null} if not supported. + * @throws IOException if an error occurs in this operation. + */ + public static ServiceTag getJavaServiceTag(String source) throws IOException { + return Installer.getJavaServiceTag(source); + } + +} diff --git a/src/share/classes/com/sun/servicetag/SolarisServiceTag.java b/src/share/classes/com/sun/servicetag/SolarisServiceTag.java new file mode 100644 index 000000000..d637c2304 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/SolarisServiceTag.java @@ -0,0 +1,62 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +import java.io.IOException; +import java.util.Set; + +/** + * Utility class to obtain the service tag for the Solaris Operating System. + */ +class SolarisServiceTag { + private final static String[] SolarisProductURNs = new String[] { + "urn:uuid:a7a38948-2bd5-11d6-98ce-9d3ac1c0cfd7", /* Solaris 8 */ + "urn:uuid:4f82caac-36f3-11d6-866b-85f428ef944e", /* Solaris 9 */ + "urn:uuid:a19de03b-48bc-11d9-9607-080020a9ed93", /* Solaris 9 sparc */ + "urn:uuid:4c35c45b-4955-11d9-9607-080020a9ed93", /* Solaris 9 x86 */ + "urn:uuid:5005588c-36f3-11d6-9cec-fc96f718e113", /* Solaris 10 */ + "urn:uuid:6df19e63-7ef5-11db-a4bd-080020a9ed93" /* Solaris 11 */ + }; + + /** + * Returns null if not found. + * + * There is only one service tag for the operating system. + */ + static ServiceTag getServiceTag() throws IOException { + if (Registry.isSupported()) { + Registry streg = Registry.getSystemRegistry(); + for (String parentURN : SolarisProductURNs) { + Set instances = streg.findServiceTags(parentURN); + for (ServiceTag st : instances) { + // there should have only one service tag for the OS + return st; + } + } + } + return null; + } +} diff --git a/src/share/classes/com/sun/servicetag/SolarisSystemEnvironment.java b/src/share/classes/com/sun/servicetag/SolarisSystemEnvironment.java new file mode 100644 index 000000000..f9f10684f --- /dev/null +++ b/src/share/classes/com/sun/servicetag/SolarisSystemEnvironment.java @@ -0,0 +1,158 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +// This class is a copy of the com.sun.scn.servicetags.SolarisSystemEnvironment +// class from the Sun Connection source. +// +// The Service Tags team maintains the latest version of the implementation +// for system environment data collection. JDK will include a copy of +// the most recent released version for a JDK release. We rename +// the package to com.sun.servicetag so that the Sun Connection +// product always uses the latest version from the com.sun.scn.servicetags +// package. JDK and users of the com.sun.servicetag API +// (e.g. NetBeans and SunStudio) will use the version in JDK. +// +// So we keep this class in src/share/classes instead of src//classes. + +import java.io.*; + +/** + * Solaris implementation of the SystemEnvironment class. + */ +class SolarisSystemEnvironment extends SystemEnvironment { + SolarisSystemEnvironment() { + setHostId(getCommandOutput("/usr/bin/hostid")); + setSystemModel(getCommandOutput("/usr/bin/uname", "-i")); + setSystemManufacturer(getSolarisSystemManufacturer()); + setCpuManufacturer(getSolarisCpuManufacturer()); + setSerialNumber(getSolarisSN()); + } + + /** + * Tries to obtain the cpu manufacturer. + * @return The cpu manufacturer (an empty string if not found or an error occurred) + */ + private String getSolarisCpuManufacturer() { + // not fully accurate, this could be another manufacturer (fujitsu for example) + if ("sparc".equalsIgnoreCase(System.getProperty("os.arch"))) { + return "Sun Microsystems, Inc"; + } + + // if we're here, then we'll try smbios (type 3) + return getSmbiosData("3", "Manufacturer: "); + } + + /** + * Tries to obtain the system manufacturer. + * @return The system manufacturer (an empty string if not found or an error occurred) + */ + private String getSolarisSystemManufacturer() { + // not fully accurate, this could be another manufacturer (fujitsu for example) + if ("sparc".equalsIgnoreCase(System.getProperty("os.arch"))) { + return "Sun Microsystems, Inc"; + } + + // if we're here, then we'll try smbios (type 1) + return getSmbiosData("1", "Manufacturer: "); + } + + /** + * Tries to obtain the serial number. + * @return The serial number (empty string if not found or an error occurred) + */ + private String getSolarisSN() { + // try to read from the psn file if it exists + String tmp = getFileContent("/var/run/psn"); + if (tmp.length() > 0) { + return tmp.trim(); + } + + // if we're here, then we'll try sneep + String tmpSN = getSneepSN(); + if (tmpSN.length() > 0) { + return tmpSN; + } + + // if we're here, then we'll try smbios (type 1) + tmpSN = getSmbiosData("1", "Serial Number: "); + if (tmpSN.length() > 0) { + return tmpSN; + } + + // if we're here, then we'll try smbios (type 3) + tmpSN = getSmbiosData("3", "Serial Number: "); + if (tmpSN.length() > 0) { + return tmpSN; + } + + // give up and return + return ""; + } + + // Sample smbios output segment: + // ID SIZE TYPE + // 1 150 SMB_TYPE_SYSTEM (system information) + // + // Manufacturer: Sun Microsystems + // Product: Sun Fire X4600 + // Version: To Be Filled By O.E.M. + // Serial Number: 00:14:4F:45:0C:2A + private String getSmbiosData(String type, String target) { + String output = getCommandOutput("/usr/sbin/smbios", "-t", type); + for (String s : output.split("\n")) { + if (s.contains(target)) { + int indx = s.indexOf(target) + target.length(); + if (indx < s.length()) { + String tmp = s.substring(indx).trim(); + String lowerCaseStr = tmp.toLowerCase(); + if (!lowerCaseStr.startsWith("not available") + && !lowerCaseStr.startsWith("to be filled by o.e.m")) { + return tmp; + } + } + } + } + + return ""; + } + + private String getSneepSN() { + String basedir = getCommandOutput("pkgparam","SUNWsneep","BASEDIR"); + File f = new File(basedir + "/bin/sneep"); + if (f.exists()) { + String sneepSN = getCommandOutput(basedir + "/bin/sneep"); + if (sneepSN.equalsIgnoreCase("unknown")) { + return ""; + } else { + return sneepSN; + } + } else { + return ""; + } + } + +} diff --git a/src/share/classes/com/sun/servicetag/SunConnection.java b/src/share/classes/com/sun/servicetag/SunConnection.java new file mode 100644 index 000000000..8bcddbe97 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/SunConnection.java @@ -0,0 +1,299 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +import java.io.*; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.io.OutputStreamWriter; +import java.util.Locale; +import javax.net.ssl.HttpsURLConnection; + +/** + * Sun Connection Class for Product Registration. + * + * Registration Web Application Interface + * 1) POST the product registry to the output stream of the registration + * relay service. + * 2) Open the webapp URL from a browser with the following parameters: + * registry-urn + * product=jdk + * locale= + * version= + * + * @see https://sn-tools.central.sun.com/twiki/pub/ServiceTags/RegistrationRelayService/ + * + */ +class SunConnection { + + private static String JDK_REGISTRATION_URL = "https://inventory.sun.com/"; + private static String SANDBOX_TESTING_URL = "https://inventory-beta.sun.com/"; + private static String REGISTRATION_WEB_PATH = "RegistrationWeb/register"; + + // System properties for testing + private static String SVCTAG_REGISTER_TESTING = "servicetag.register.testing"; + private static String SVCTAG_REGISTRATION_URL = "servicetag.registration.url"; + private static String SVCTAG_CONNECTION_TIMEOUT = "servicetag.connection.timeout"; + + private SunConnection() { + } + + /** + * Returns a URL for JDK registration interfacing with the Sun Connection + * registration relay service in this form: + * /?product=jdk&locale= + * + * The can be overridden by an environment + * variable or a system property. + * + * 1) "servicetag.register.testing" system property to switch to the + * Sun Connection registration sandbox testing. + * 2) "servicetag.registration.url" system property to override + * the URL + * 3) Default production URL + * + */ + static URL getRegistrationURL(String registrationURN, Locale locale, String version) { + String url = System.getProperty(SVCTAG_REGISTRATION_URL); + if (url == null) { + if (System.getProperty(SVCTAG_REGISTER_TESTING) != null) { + url = SANDBOX_TESTING_URL; + } else { + url = JDK_REGISTRATION_URL; + } + } + url += REGISTRATION_WEB_PATH; + + // trim whitespaces + url = url.trim(); + if (url.length() == 0) { + throw new InternalError("Empty registration url set"); + } + + // Add the registry_urn in the URL's query + String registerURL = rewriteURL(url, registrationURN, locale, version); + try { + return new URL(registerURL); + } catch (MalformedURLException ex) { + // should never reach here + InternalError x = + new InternalError(ex.getMessage()); + x.initCause(ex); + throw x; + } + } + + private static String rewriteURL(String url, String registryURN, Locale locale, String version) { + StringBuilder sb = new StringBuilder(url.trim()); + int len = sb.length(); + if (sb.charAt(len-1) != '/') { + sb.append('/'); + } + sb.append(registryURN); + sb.append("?"); + sb.append("product=jdk"); + sb.append("&"); + sb.append("locale=").append(locale.toString()); + sb.append("&"); + sb.append("version=").append(version); + return sb.toString(); + } + + /** + * Registers all products in the given product registry. If it fails + * to post the service tag registry, open the browser with the offline + * registration page. + * + * @param regData registration data to be posted to the Sun Connection + * for registration. + * @param locale Locale + * @param version JDK version + * + * @throws IOException if I/O error occurs in this operation + */ + public static void register(RegistrationData regData, + Locale locale, + String version) throws IOException { + // Gets the URL for SunConnection registration relay service + URL url = getRegistrationURL(regData.getRegistrationURN(), + locale, + version); + + // Post the Product Registry to Sun Connection + boolean succeed = postRegistrationData(url, regData); + if (succeed) { + // service tags posted successfully + // now prompt for registration + openBrowser(url); + } else { + // open browser with the offline registration page + openOfflineRegisterPage(); + } + } + + /** + * Opens a browser for JDK product registration. + * @param url Registration Webapp URL + */ + private static void openBrowser(URL url) throws IOException { + if (!BrowserSupport.isSupported()) { + if (Util.isVerbose()) { + System.out.println("Browser is not supported"); + } + return; + } + + try { + BrowserSupport.browse(url.toURI()); + } catch (URISyntaxException ex) { + InternalError x = new InternalError("Error in registering: " + ex.getMessage()); + x.initCause(ex); + throw x; + } catch (IllegalArgumentException ex) { + if (Util.isVerbose()) { + ex.printStackTrace(); + } + } catch (UnsupportedOperationException ex) { + // ignore if not supported + if (Util.isVerbose()) { + ex.printStackTrace(); + } + } + } + + /** + * POST service tag registry to Sun Connection + * @param loc the URL of the webapp to handle the POST request + * @param streg the Service Tag registry + * @return true if posting succeeds; otherwise, false. + */ + private static boolean postRegistrationData(URL url, + RegistrationData registration) { + try { + HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); + con.setDoInput(true); + con.setDoOutput(true); + con.setUseCaches(false); + con.setAllowUserInteraction(false); + + // default 10 seconds timeout + String timeout = System.getProperty(SVCTAG_CONNECTION_TIMEOUT, "10"); + con.setConnectTimeout(Util.getIntValue(timeout) * 1000); + + if (Util.isVerbose()) { + System.out.println("Connecting to post registration data at " + url); + } + + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type", "text/xml;charset=\"utf-8\""); + con.connect(); + + OutputStream out = con.getOutputStream(); + registration.storeToXML(out); + out.flush(); + out.close(); + + int returnCode = con.getResponseCode(); + if (Util.isVerbose()) { + System.out.println("POST return status = " + returnCode); + printReturnData(con, returnCode); + } + return (returnCode == HttpURLConnection.HTTP_OK); + } catch (MalformedURLException me) { + // should never reach here + InternalError x = new InternalError("Error in registering: " + me.getMessage()); + x.initCause(me); + throw x; + } catch (Exception ioe) { + // SocketTimeoutException, IOException or UnknownHostException + if (Util.isVerbose()) { + ioe.printStackTrace(); + } + return false; + } + } + + /** + * Opens the offline registratioin page in the browser. + * + */ + private static void openOfflineRegisterPage() + throws IOException { + if (!BrowserSupport.isSupported()) { + if (Util.isVerbose()) { + System.out.println("Browser is not supported"); + } + return; + } + + File registerPage = Installer.getRegistrationHtmlPage(); + try { + BrowserSupport.browse(registerPage.toURI()); + } catch (FileNotFoundException ex) { + // should never reach here + InternalError x = + new InternalError("Error in launching " + registerPage + ": " + ex.getMessage()); + x.initCause(ex); + throw x; + } catch (IllegalArgumentException ex) { + if (Util.isVerbose()) { + ex.printStackTrace(); + } + } catch (UnsupportedOperationException ex) { + // ignore if not supported + if (Util.isVerbose()) { + ex.printStackTrace(); + } + } + } + + private static void printReturnData(HttpURLConnection con, int returnCode) + throws IOException { + BufferedReader reader = null; + try { + if (returnCode < 400) { + reader = new BufferedReader( + new InputStreamReader(con.getInputStream())); + } else { + reader = new BufferedReader( + new InputStreamReader(con.getErrorStream())); + } + StringBuilder sb = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + sb.append(line).append("\n"); + } + System.out.println("Response is : "); + System.out.println(sb.toString()); + } finally { + if (reader != null) { + reader.close(); + } + } + } +} diff --git a/src/share/classes/com/sun/servicetag/SystemEnvironment.java b/src/share/classes/com/sun/servicetag/SystemEnvironment.java new file mode 100644 index 000000000..af0281fd3 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/SystemEnvironment.java @@ -0,0 +1,338 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +// This class is a copy of the com.sun.scn.servicetags.SystemEnvironment +// class from the Sun Connection source. +// +// The Service Tags team maintains the latest version of the implementation +// for system environment data collection. JDK will include a copy of +// the most recent released version for a JDK release. We rename +// the package to com.sun.servicetag so that the Sun Connection +// product always uses the latest version from the com.sun.scn.servicetags +// package. JDK and users of the com.sun.servicetag API +// (e.g. NetBeans and SunStudio) will use the version in JDK. + +import java.io.*; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * SystemEnvironment class collects the environment data with the + * best effort from the underlying platform. + */ +public class SystemEnvironment { + private String hostname; + private String hostId; + private String osName; + private String osVersion; + private String osArchitecture; + private String systemModel; + private String systemManufacturer; + private String cpuManufacturer; + private String serialNumber; + private static SystemEnvironment sysEnv = null; + + public static synchronized SystemEnvironment getSystemEnvironment() { + if (sysEnv == null) { + String os = System.getProperty("os.name"); + if (os.equals("SunOS")) { + sysEnv = new SolarisSystemEnvironment(); + } else if (os.equals("Linux")) { + sysEnv = new LinuxSystemEnvironment(); + } else if (os.startsWith("Windows")) { + sysEnv = new WindowsSystemEnvironment(); + } else { + sysEnv = new SystemEnvironment(); + } + } + return sysEnv; + } + + // package-private + SystemEnvironment() { + try { + this.hostname = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException ex) { + this.hostname = "Unknown host"; + } + this.hostId = ""; + this.osName = System.getProperty("os.name"); + this.osVersion = System.getProperty("os.version"); + this.osArchitecture = System.getProperty("os.arch"); + this.systemModel = ""; + this.systemManufacturer = ""; + this.cpuManufacturer = ""; + this.serialNumber = ""; + } + + + /** + * Sets the hostname. + * @param hostname The hostname to set. + */ + public void setHostname(String hostname) { + this.hostname = hostname; + } + + /** + * Sets the OS name. + * @param osName The osName to set. + */ + public void setOsName(String osName) { + this.osName = osName; + } + + /** + * Sets the OS version. + * @param osVersion The osVersion to set. + */ + public void setOsVersion(String osVersion) { + this.osVersion = osVersion; + } + + /** + * Sets the OS architecture. + * @param osArchitecture The osArchitecture to set. + */ + public void setOsArchitecture(String osArchitecture) { + this.osArchitecture = osArchitecture; + } + + /** + * Sets the system model. + * @param systemModel The systemModel to set. + */ + public void setSystemModel(String systemModel) { + this.systemModel = systemModel; + } + + /** + * Sets the system manufacturer. + * @param systemManufacturer The systemManufacturer to set. + */ + public void setSystemManufacturer(String systemManufacturer) { + this.systemManufacturer = systemManufacturer; + } + + /** + * Sets the cpu manufacturer. + * @param cpuManufacturer The cpuManufacturer to set. + */ + public void setCpuManufacturer(String cpuManufacturer) { + this.cpuManufacturer = cpuManufacturer; + } + + /** + * Sets the serial number. + * @param serialNumber The serialNumber to set. + */ + public void setSerialNumber(String serialNumber) { + this.serialNumber = serialNumber; + } + + /** + * Sets the hostid. Truncates to a max length of 16 chars. + * @param hostId The hostid to set. + */ + public void setHostId(String hostId) { + if (hostId == null || hostId.equals("null")) { + hostId = ""; + } + if (hostId.length() > 16) { + hostId = hostId.substring(0,16); + } + this.hostId = hostId; + } + + /** + * Returns the hostname. + * @return The hostname. + */ + public String getHostname() { + return hostname; + } + + /** + * Returns the osName. + * @return The osName. + */ + public String getOsName() { + return osName; + } + + /** + * Returns the osVersion. + * @return The osVersion. + */ + public String getOsVersion() { + return osVersion; + } + + /** + * Returns the osArchitecture. + * @return The osArchitecture. + */ + public String getOsArchitecture() { + return osArchitecture; + } + + /** + * Returns the systemModel. + * @return The systemModel. + */ + public String getSystemModel() { + return systemModel; + } + + /** + * Returns the systemManufacturer. + * @return The systemManufacturer. + */ + public String getSystemManufacturer() { + return systemManufacturer; + } + + /** + * Returns the serialNumber. + * @return The serialNumber. + */ + public String getSerialNumber() { + return serialNumber; + } + + /** + * Returns the hostId. + * @return The hostId. + */ + public String getHostId() { + return hostId; + } + + /** + * Returns the cpuManufacturer. + * @return The cpuManufacturer. + */ + public String getCpuManufacturer() { + return cpuManufacturer; + } + + protected String getCommandOutput(String... command) { + StringBuilder sb = new StringBuilder(); + BufferedReader br = null; + Process p = null; + try { + ProcessBuilder pb = new ProcessBuilder(command); + p = pb.start(); + p.waitFor(); + + if (p.exitValue() == 0) { + br = new BufferedReader(new InputStreamReader(p.getInputStream())); + String line = null; + while ((line = br.readLine()) != null) { + line = line.trim(); + if (line.length() > 0) { + if (sb.length() > 0) { + sb.append("\n"); + } + sb.append(line); + } + } + } + return sb.toString(); + } catch (InterruptedException ie) { + // in case the command hangs + if (p != null) { + p.destroy(); + } + return ""; + } catch (Exception e) { + // ignore exception + return ""; + } finally { + if (p != null) { + try { + p.getErrorStream().close(); + } catch (IOException e) { + // ignore + } + try { + p.getInputStream().close(); + } catch (IOException e) { + // ignore + } + try { + p.getOutputStream().close(); + } catch (IOException e) { + // ignore + } + p = null; + } + if (br != null) { + try { + br.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + protected String getFileContent(String filename) { + File f = new File(filename); + if (!f.exists()) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + BufferedReader br = null; + try { + br = new BufferedReader(new FileReader(f)); + String line = null; + while ((line = br.readLine()) != null) { + line = line.trim(); + if (line.length() > 0) { + if (sb.length() > 0) { + sb.append("\n"); + } + sb.append(line); + } + } + return sb.toString(); + } catch (Exception e) { + // ignore exception + return ""; + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException e) { + // ignore + } + } + } + } +} diff --git a/src/share/classes/com/sun/servicetag/UnauthorizedAccessException.java b/src/share/classes/com/sun/servicetag/UnauthorizedAccessException.java new file mode 100644 index 000000000..0b5b35ea6 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/UnauthorizedAccessException.java @@ -0,0 +1,53 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +/** + * Thrown if the user is not authorized to + * {@link Registry#updateServiceTag update} or + * {@link Registry#removeServiceTag remove} + * a service tag from a {@link Registry}. + */ +public class UnauthorizedAccessException extends RuntimeException { + + /** + * Constructs an UnauthorizedAccessException object + * without detail message. + */ + public UnauthorizedAccessException() { + } + + + /** + * Constructs an UnauthorizedAccessException object + * with the specified detail message. + * + * @param msg the detail message. + */ + public UnauthorizedAccessException(String msg) { + super(msg); + } +} diff --git a/src/share/classes/com/sun/servicetag/Util.java b/src/share/classes/com/sun/servicetag/Util.java new file mode 100644 index 000000000..9e32111a2 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/Util.java @@ -0,0 +1,336 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +import java.io.*; +import java.util.Date; +import java.text.SimpleDateFormat; +import java.text.ParseException; +import java.util.TimeZone; +import java.util.UUID; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +// Utility class for com.sun.servicetag package +class Util { + private static boolean verbose = (System.getProperty("servicetag.verbose") != null); + private static String jrepath = null; + private static final String REGKEY_TAIL = + "microsoft\\windows\\currentversion\\app paths\\stclient.exe"; + private static final String STCLIENT_TAIL = "sun\\servicetag\\stclient.exe"; + private static final String WIN32_STCLIENT = + "c:\\Program Files (x86)\\" + STCLIENT_TAIL; + + // for debugging and tracing + static boolean isVerbose() { + return verbose; + } + + /** + * Gets the pathname of JRE in the running platform + * This can be a JDK or JRE. + */ + static synchronized String getJrePath() { + if (jrepath == null) { + // Determine the JRE path by checking the existence of + // /jre/lib and /lib. + String javaHome = System.getProperty("java.home"); + jrepath = javaHome + File.separator + "jre"; + File f = new File(jrepath, "lib"); + if (!f.exists()) { + // java.home usually points to the JRE path + jrepath = javaHome; + } + } + return jrepath; + } + + /** + * Tests if the running platform is a JDK. + */ + static boolean isJdk() { + // /jre exists which implies it's a JDK + return getJrePath().endsWith(File.separator + "jre"); + } + + /** + * Generates the URN string of "urn:st" namespace + */ + static String generateURN() { + return "urn:st:" + UUID.randomUUID().toString(); + } + + static int getIntValue(String value) { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("\"" + value + "\"" + + " expected to be an integer"); + } + } + + /** + * Formats the Date into a timestamp string in YYYY-MM-dd HH:mm:ss GMT. + * @param timestamp Date + * @return a string representation of the timestamp + * in the YYYY-MM-dd HH:mm:ss GMT format. + */ + static String formatTimestamp(Date timestamp) { + if (timestamp == null) { + return "[No timestamp]"; + } + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); + df.setTimeZone(TimeZone.getTimeZone("GMT")); + return df.format(timestamp); + } + + /** + * Parses a timestamp string in YYYY-MM-dd HH:mm:ss GMT format. + * @param timestamp Timestamp in the YYYY-MM-dd HH:mm:ss GMT format. + * @return Date + */ + static Date parseTimestamp(String timestamp) { + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); + df.setTimeZone(TimeZone.getTimeZone("GMT")); + try { + return df.parse(timestamp); + } catch (ParseException e) { + // should not reach here + e.printStackTrace(); + return new Date(); + } + } + + static String commandOutput(Process p) throws IOException { + Reader r = null; + Reader err = null; + try { + r = new InputStreamReader(p.getInputStream()); + err = new InputStreamReader(p.getErrorStream()); + String output = commandOutput(r); + String errorMsg = commandOutput(err); + p.waitFor(); + return output + errorMsg.trim(); + } catch (InterruptedException e) { + if (isVerbose()) { + e.printStackTrace(); + } + return e.getMessage(); + } finally { + if (r != null) { + r.close(); + } + if (err != null) { + err.close(); + } + } + } + + static String commandOutput(Reader r) throws IOException { + StringBuilder sb = new StringBuilder(); + int c; + while ((c = r.read()) > 0) { + if (c != '\r') { + sb.append((char) c); + } + } + return sb.toString(); + } + + static int getJdkVersion() { + parseVersion(); + return jdkVersion; + } + + static int getUpdateVersion() { + parseVersion(); + return jdkUpdate; + } + + private static int jdkVersion = 0; + private static int jdkUpdate = 0; + private static synchronized void parseVersion() { + if (jdkVersion > 0) { + return; + } + + // parse java.runtime.version + // valid format of the version string is: + // n.n.n[_uu[c]][-]-bxx + String cs = System.getProperty("java.runtime.version"); + if (cs.length() >= 5 && + Character.isDigit(cs.charAt(0)) && cs.charAt(1) == '.' && + Character.isDigit(cs.charAt(2)) && cs.charAt(3) == '.' && + Character.isDigit(cs.charAt(4))) { + jdkVersion = Character.digit(cs.charAt(2), 10); + cs = cs.substring(5, cs.length()); + if (cs.charAt(0) == '_' && cs.length() >= 3 && + Character.isDigit(cs.charAt(1)) && + Character.isDigit(cs.charAt(2))) { + int nextChar = 3; + try { + String uu = cs.substring(1, 3); + jdkUpdate = Integer.valueOf(uu).intValue(); + } catch (NumberFormatException e) { + // not conforming to the naming convention + return; + } + } + } else { + throw new InternalError("Invalid java.runtime.version" + cs); + } + } + + /** + * Returns this java string as a null-terminated byte array + */ + private static byte[] stringToByteArray(String str) { + return (str + "\u0000").getBytes(); + } + + /** + * Converts a null-terminated byte array to java string + */ + private static String byteArrayToString(byte[] array) { + return new String(array, 0, array.length -1); + } + + /** + * Gets the stclient path using a well known location from + * the Windows platform Registry, ensuring the path returned + * by the registry is really the one we are looking for, + * otherwise it will return null. + */ + private static File getWindowsStClientFile(boolean wow64) { + File out = null; + String regKey = (wow64 == true) + ? "software\\Wow6432Node\\" + REGKEY_TAIL + : "software\\" + REGKEY_TAIL; + String keyName = "" ; // use the default key + String path = getRegistryKey(regKey, keyName); + if (path != null + && (new File(path)).exists() + && path.toLowerCase().endsWith(STCLIENT_TAIL.toLowerCase())) { + out = new File(path); + } + if (isVerbose()) { + System.out.println("stclient=" + out); + } + return out; + } + + /** + * Finds a stclient in 32 and 64 bit environments, first by querying + * the windows registry, if not then get the well known paths for + * 64bit see http://support.microsoft.com/kb/896459 + */ + + static File getWindowsStClientFile() { + File stclient = null; + if (System.getProperty("os.arch").equals("x86")) { + // try to get the default entry + stclient = getWindowsStClientFile(false); + if (stclient != null) { + return stclient; + } + } else { // we are on 64-bit system + // try the wow64 area + stclient = getWindowsStClientFile(true); + if (stclient != null) { + return stclient; + } + // try the default hard coded path, maybe wow64 registry is missing + stclient = new File(WIN32_STCLIENT); + if (stclient.canExecute()) { + if (isVerbose()) { + System.out.println("stclient(default)=" + stclient); + } + return stclient; + } + } + if (isVerbose()) { + System.out.println("stclient not found"); + } + return null; + } + + /** + * This uses reflection to access a private java windows registry + * interface, any changes to that Class must be appropriately adjusted. + * Returns a null if unsuccessful. + */ + private static String getRegistryKey(String regKey, String keyName) { + String out = null; + try { + Class clazz = Class.forName("java.util.prefs.WindowsPreferences"); + + // Get the registry methods + Method winRegOpenKeyM = clazz.getDeclaredMethod("WindowsRegOpenKey", + int.class, byte[].class, int.class); + winRegOpenKeyM.setAccessible(true); + + Method winRegCloseKeyM = clazz.getDeclaredMethod("WindowsRegCloseKey", + int.class); + winRegCloseKeyM.setAccessible(true); + + Method winRegQueryValueM = clazz.getDeclaredMethod("WindowsRegQueryValueEx", + int.class, byte[].class); + winRegQueryValueM.setAccessible(true); + + // Get all the constants we need + int HKLM = getValueFromStaticField("HKEY_LOCAL_MACHINE", clazz); + int KEY_READ = getValueFromStaticField("KEY_READ", clazz); + int ERROR_CODE = getValueFromStaticField("ERROR_CODE", clazz); + int NATIVE_HANDLE = getValueFromStaticField("NATIVE_HANDLE", clazz); + int ERROR_SUCCESS = getValueFromStaticField("ERROR_SUCCESS", clazz); + + // Convert keys + byte[] reg = stringToByteArray(regKey); + byte[] key = stringToByteArray(keyName); + + // Open the registry + int[] result = (int[]) winRegOpenKeyM.invoke(null, HKLM, reg, KEY_READ); + + if (result[ERROR_CODE] == ERROR_SUCCESS) { + byte[] stvalue = (byte[]) winRegQueryValueM.invoke(null, + result[NATIVE_HANDLE], key); + out = byteArrayToString(stvalue); + winRegCloseKeyM.invoke(null, result[NATIVE_HANDLE]); + } + } catch (Exception ex) { + if (isVerbose()) { + ex.printStackTrace(); + } + } + return out; + } + + private static int getValueFromStaticField(String fldName, Class klass) throws Exception { + Field f = klass.getDeclaredField(fldName); + f.setAccessible(true); + return f.getInt(null); + } +} diff --git a/src/share/classes/com/sun/servicetag/WindowsSystemEnvironment.java b/src/share/classes/com/sun/servicetag/WindowsSystemEnvironment.java new file mode 100644 index 000000000..1fff0ea7d --- /dev/null +++ b/src/share/classes/com/sun/servicetag/WindowsSystemEnvironment.java @@ -0,0 +1,144 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.servicetag; + +// This class is a copy of the com.sun.scn.servicetags.WindowsSystemEnvironment +// class from the Sun Connection source. +// +// The Service Tags team maintains the latest version of the implementation +// for system environment data collection. JDK will include a copy of +// the most recent released version for a JDK release. We rename +// the package to com.sun.servicetag so that the Sun Connection +// product always uses the latest version from the com.sun.scn.servicetags +// package. JDK and users of the com.sun.servicetag API +// (e.g. NetBeans and SunStudio) will use the version in JDK. +// +// So we keep this class in src/share/classes instead of src//classes. + +import java.io.*; +import java.util.ArrayList; +import java.util.List; + +/** + * Windows implementation of the SystemEnvironment class. + */ +class WindowsSystemEnvironment extends SystemEnvironment { + WindowsSystemEnvironment() { + super(); + + // run a call to make sure things are initialized + // ignore the first call result as the system may + // give inconsistent data on the first invocation ever + getWmicResult("computersystem", "get", "model"); + + setSystemModel(getWmicResult("computersystem", "get", "model")); + setSystemManufacturer(getWmicResult("computersystem", "get", "manufacturer")); + setSerialNumber(getWmicResult("bios", "get", "serialnumber")); + + String cpuMfr = getWmicResult("cpu", "get", "manufacturer"); + // this isn't as good an option, but if we couldn't get anything + // from wmic, try the processor_identifier + if (cpuMfr.length() == 0) { + String procId = System.getenv("processor_identifer"); + if (procId != null) { + String[] s = procId.split(","); + cpuMfr = s[s.length - 1].trim(); + } + } + setCpuManufacturer(cpuMfr); + + // try to remove the temp file that gets created from running wmic cmds + try { + // look in the current working directory + File f = new File("TempWmicBatchFile.bat"); + if (f.exists()) { + f.delete(); + } + } catch (Exception e) { + // ignore the exception + } + } + + + /** + * This method invokes wmic outside of the normal environment + * collection routines. + * + * An initial call to wmic can be costly in terms of time. + * + * + * Details of why the first call is costly can be found at: + * + * http://support.microsoft.com/kb/290216/en-us + * + * "When you run the Wmic.exe utility for the first time, the utility + * compiles its .mof files into the repository. To save time during + * Windows installation, this operation takes place as necessary." + * + */ + private String getWmicResult(String alias, String verb, String property) { + String res = ""; + BufferedReader in = null; + try { + ProcessBuilder pb = new ProcessBuilder("cmd", "/C", "WMIC", alias, verb, property); + Process p = pb.start(); + // need this for executing windows commands (at least + // needed for executing wmic command) + BufferedWriter bw = new BufferedWriter( + new OutputStreamWriter(p.getOutputStream())); + bw.write(13); + bw.flush(); + bw.close(); + + p.waitFor(); + if (p.exitValue() == 0) { + in = new BufferedReader(new InputStreamReader(p.getInputStream())); + String line = null; + while ((line = in.readLine()) != null) { + line = line.trim(); + if (line.length() == 0) { + continue; + } + res = line; + } + // return the *last* line read + return res; + } + + } catch (Exception e) { + // ignore the exception + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + // ignore + } + } + } + return res.trim(); + } +} diff --git a/src/share/classes/com/sun/servicetag/package.html b/src/share/classes/com/sun/servicetag/package.html new file mode 100644 index 000000000..b5a07701c --- /dev/null +++ b/src/share/classes/com/sun/servicetag/package.html @@ -0,0 +1,71 @@ +CTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> + + + + + + + +This package contains classes that allow the creation +and manipulation of service tags. +This com.sun.servicetag package is intended for +Sun internal use only. +

+

+
Service Tag
+
A service tag is an XML-based data structure that contains identifying +information about an instance of a product or component on a system. +
+
+
+
Service Tag Registry
+
A service tag registry is a XML-based registry that contains +the service tags of all the tagged components on a system. The +service tag registry is present on systems that have the +Service Tags software installed. +
+
+
+
Registration Data
+
A registration data is a container of one or more +service tags that identify the +components for product registration and will be used to interface +with the Sun Connection registration services. +
+
+ +This package contains the methods to create service tags, set up the +registration data for product registration, add service tags to and +remove them from the system service tag registry. +

+All methods defined in this package will throw {@code NullPointerException} +if {@code null} is passed in any input parameter unless it is stated otherwise. +In addition, they are multi-thread safe. + + + + diff --git a/src/share/classes/com/sun/servicetag/resources/Putback-Notes.txt b/src/share/classes/com/sun/servicetag/resources/Putback-Notes.txt new file mode 100644 index 000000000..70e8cffbd --- /dev/null +++ b/src/share/classes/com/sun/servicetag/resources/Putback-Notes.txt @@ -0,0 +1,25 @@ +README for auto-generating of the offline registration page. + +1. register.html is defined by the xDesign team. + +2. Before putback in the workspace, we need to modify the + register.html to contain the following: + + (a) replace the pathname of the jdk_header.png image to + + + (b) replace the product name from: + Java Development Kit Version 6 Update 5 (e.g.) + to: + Java Development Kit @@JDK_VERSION@@ + + (c) replace the form action for the "Register My JDK" button with: + +

+ + (d) Add this input in the form for posting data after + the line: + + + +3. The jdk_header.png is located under /lib/servicetag directory. diff --git a/src/share/classes/com/sun/servicetag/resources/javase_5_swordfish.properties b/src/share/classes/com/sun/servicetag/resources/javase_5_swordfish.properties new file mode 100644 index 000000000..8b58c32f0 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/resources/javase_5_swordfish.properties @@ -0,0 +1,29 @@ +# Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. + +servicetag.jdk.urn = urn:uuid:d5bed446-05f2-42ed-ba0a-153105a52413 +servicetag.jdk.name = J2SE 5.0 Development Kit +servicetag.jre.urn = urn:uuid:5c6686aa-fd05-46a6-ba3e-700e2d5f7043 +servicetag.jre.name = J2SE 5.0 Runtime Environment +servicetag.parent.urn = urn:uuid:f3c20172-557a-11d7-93d0-d6a41ea318df +servicetag.parent.name = Java 2 Platform, Standard Edition 5.0 diff --git a/src/share/classes/com/sun/servicetag/resources/javase_6_swordfish.properties b/src/share/classes/com/sun/servicetag/resources/javase_6_swordfish.properties new file mode 100644 index 000000000..982c9666c --- /dev/null +++ b/src/share/classes/com/sun/servicetag/resources/javase_6_swordfish.properties @@ -0,0 +1,29 @@ +# Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. + +servicetag.jdk.urn = urn:uuid:b58ef9a8-5ae8-11db-a023-080020a9ed93 +servicetag.jdk.name = Java SE 6 Development Kit +servicetag.jre.urn = urn:uuid:92d1de8c-1e59-42c6-a280-1c379526bcbc +servicetag.jre.name = Java SE 6 Runtime Environment +servicetag.parent.urn = urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3 +servicetag.parent.name = Java Platform Standard Edition 6 (Java SE 6) diff --git a/src/share/classes/com/sun/servicetag/resources/javase_7_swordfish.properties b/src/share/classes/com/sun/servicetag/resources/javase_7_swordfish.properties new file mode 100644 index 000000000..45eebd2d3 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/resources/javase_7_swordfish.properties @@ -0,0 +1,29 @@ +# Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. + +servicetag.jdk.urn = JSEZ9-007-ZZZZ +servicetag.jdk.name = Java SE 7 Development Kit +servicetag.jre.urn = JSERE-007-ZZZZ +servicetag.jre.name = Java SE 7 Runtime Environment +servicetag.parent.urn = urn:uuid:dc1704fe-264f-11dc-9482-080020a9ed93 +servicetag.parent.name = Java Platform Standard Edition 7 (Java SE 7) diff --git a/src/share/classes/com/sun/servicetag/resources/jdk_header.png b/src/share/classes/com/sun/servicetag/resources/jdk_header.png new file mode 100644 index 000000000..011cfd4cd Binary files /dev/null and b/src/share/classes/com/sun/servicetag/resources/jdk_header.png differ diff --git a/src/share/classes/com/sun/servicetag/resources/product_registration.xsd b/src/share/classes/com/sun/servicetag/resources/product_registration.xsd new file mode 100644 index 000000000..43d27455b --- /dev/null +++ b/src/share/classes/com/sun/servicetag/resources/product_registration.xsd @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/share/classes/com/sun/servicetag/resources/register.html b/src/share/classes/com/sun/servicetag/resources/register.html new file mode 100644 index 000000000..23e9d717a --- /dev/null +++ b/src/share/classes/com/sun/servicetag/resources/register.html @@ -0,0 +1,105 @@ + + + + +Register your JDK + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  +
 

Thank you for installing the + Java Development Kit @@JDK_VERSION@@ + from Sun Microsystems.

+

Registering your product will give you the following benefits:

+
    +
  • Notification of new versions, patches, and updates
  • +
  • Special offers on Sun developer products, services and training
  • +
  • Access to early releases and documentation
  • +
+

Product registration is FREE, quick and easy!

+
+

All you need is a Sun Developer Network or other Sun Online account. If you don't already have one, you will be prompted to create one.

+ + + + + +
+ + + + You need to be connected to the Internet to register this Sun product.
+
+
  +

Sun Microsystems, Inc. respects your privacy. + We will use your personal information for communications + and management of your Sun Online Account, the services + and applications you access using your Sun Online Account, + and the products and systems you register with your Sun Online Account.

+

For more information on the data that will be collected as + part of the registration process and how it will be managed
+ see http://java.sun.com/javase/registration/JDKRegistrationPrivacy.html.
+
+ For more information on Sun's Privacy Policy see http://www.sun.com/privacy/ or contact privacy@sun.com.

  
  
+ + diff --git a/src/share/classes/com/sun/servicetag/resources/register_ja.html b/src/share/classes/com/sun/servicetag/resources/register_ja.html new file mode 100644 index 000000000..56ee84f54 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/resources/register_ja.html @@ -0,0 +1,91 @@ + + + + +JDK 製品登録 + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
 

Sun Microsystems の Java Development Kit @@JDK_VERSION@@ をインストールしていただき、ありがとうございます。

+

製品登録をすると、次のような特典を受けることができます。

+
    +
  • 最新のバージョン、パッチ、および更新についての通知
  • +
  • Sun の開発者向け製品、サービス、およびトレーニングの特別販売
  • +
  • アーリーリリースおよびドキュメントへのアクセス
  • +
+

製品登録は無料であり、迅速で簡単です。

+
+

必要になるのは、Sun 開発者向けネットワークアカウントまたはその他の Sun オンラインアカウントだけです。 まだアカウントがない場合は、アカウントの作成が求められます。

+ + + + + +
+ + +
この Sun 製品を登録するには、インターネットに接続している必要があります。
+
+
  +

Sun Microsystems, Inc. は、お客様のプライバシーを尊重します。 お客様の個人情報は、お客様の Sun オンラインアカウント、お客様が Sun オンラインアカウントを使用してアクセスするサービスとアプリケーション、およびお客様が Sun オンラインアカウントで登録する製品とシステムの通信と管理に使用します。

+

登録の際に収集されるデータや、それらがどのように管理されるかについての詳細は、
http://java.sun.com/javase/ja/registration/JDKRegistrationPrivacy.html を参照してください。

Sun のプライバシーポリシーについての詳細は、http://jp.sun.com/privacy/ を参照するか、お問い合わせフォームからお問い合わせください。

  
  
+ + diff --git a/src/share/classes/com/sun/servicetag/resources/register_zh_CN.html b/src/share/classes/com/sun/servicetag/resources/register_zh_CN.html new file mode 100644 index 000000000..c47929fb7 --- /dev/null +++ b/src/share/classes/com/sun/servicetag/resources/register_zh_CN.html @@ -0,0 +1,92 @@ + + + + +注册您的 JDK + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
 

感谢您安装 Sun Microsystems 的 Java Development Kit @@JDK_VERSION@@

+

注册产品后您将获得如下增值服务:

+
    +
  • 获得新版本、修补程序和更新的通知服务
  • +
  • 获得有关 Sun 开发者产品、服务和培训的优惠
  • +
  • 获得对早期版本和文档的访问权限
  • +
+

产品注册是免费的,即快速又轻松!

+
+

您需要具有 Sun 开发者网络或其他 Sun 联机帐户。如果您没有,系统将提示您创建一个。

+ + + + + +
+ + +
您需要连接到 Internet 来注册此 Sun 产品。
+
+
  +

Sun Microsystems, Inc. 尊重您的隐私。我们会将您的个人信息用于通信和 Sun 联机帐户的管理、Sun 联机帐户访问的服务和应用程序以及用于使用 Sun 联机帐户注册的产品和系统。

+

有关注册过程中收集的数据以及这些数据的管理方式的更多信息,
请访问 http://java.sun.com/javase/registration/JDKRegistrationPrivacy.html

有关 Sun 隐私政策的更多信息,请访问 http://www.sun.com/privacy/ 或与 privacy@sun.com 联系。

  
  
+ + diff --git a/test/com/sun/servicetag/DeleteServiceTag.java b/test/com/sun/servicetag/DeleteServiceTag.java new file mode 100644 index 000000000..6dda06b61 --- /dev/null +++ b/test/com/sun/servicetag/DeleteServiceTag.java @@ -0,0 +1,129 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6622366 + * @summary Basic Test for deleting a service tag in a product registration + * @author Mandy Chung + * + * @run build DeleteServiceTag Util + * @run main DeleteServiceTag + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +public class DeleteServiceTag { + private static RegistrationData registration; + private static File regFile; + private static Map stMap = + new LinkedHashMap(); + private static String[] files = new String[] { + "servicetag1.properties", + "servicetag2.properties", + "servicetag3.properties" + }; + + public static void main(String[] argv) throws Exception { + String registrationDir = System.getProperty("test.classes"); + String servicetagDir = System.getProperty("test.src"); + + File original = new File(servicetagDir, "registration.xml"); + regFile = new File(registrationDir, "registration.xml"); + copyRegistrationXML(original, regFile); + + // loads all the service tags + for (String f : files) { + File stfile = new File(servicetagDir, f); + ServiceTag svcTag = Util.newServiceTag(stfile); + stMap.put(svcTag.getInstanceURN(), svcTag); + } + + // load the registration data with all service tags + BufferedInputStream in = new BufferedInputStream(new FileInputStream(regFile)); + registration = RegistrationData.loadFromXML(in); + + if (stMap.size() != files.length) { + throw new RuntimeException("Invalid service tag count= " + + stMap.size() + " expected=" + files.length); + } + // check the service tags + Util.checkRegistrationData(regFile.getCanonicalPath(), stMap); + + // delete a service tag + deleteServiceTag(servicetagDir, files[0]); + + System.out.println("Test passed: service tags deleted."); + } + + private static void copyRegistrationXML(File from, File to) throws IOException { + + to.delete(); + BufferedReader reader = new BufferedReader(new FileReader(from)); + PrintWriter writer = new PrintWriter(to); + try { + String line = null; + while ((line = reader.readLine()) != null) { + writer.println(line); + } + writer.flush(); + } finally { + writer.close(); + } + } + + private static void deleteServiceTag(String parent, String filename) throws Exception { + File f = new File(parent, filename); + ServiceTag svcTag = Util.newServiceTag(f); + + ServiceTag st = registration.removeServiceTag(svcTag.getInstanceURN()); + if (st == null) { + throw new RuntimeException("RegistrationData.remove method" + + " returns null"); + } + if (!Util.matches(st, svcTag)) { + throw new RuntimeException("ServiceTag added in the registration " + + " doesn't match."); + } + // check the service tags before storing the updated data + Util.checkRegistrationData(regFile.getCanonicalPath(), stMap); + + ServiceTag st1 = registration.getServiceTag(svcTag.getInstanceURN()); + if (st1 != null) { + throw new RuntimeException("RegistrationData.get method returns " + + "non-null."); + } + // Now remove the service tag from the map and store to the XML file + stMap.remove(svcTag.getInstanceURN()); + BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(regFile)); + try { + registration.storeToXML(out); + } finally { + out.close(); + } + } +} diff --git a/test/com/sun/servicetag/DuplicateNotFound.java b/test/com/sun/servicetag/DuplicateNotFound.java new file mode 100644 index 000000000..d84352085 --- /dev/null +++ b/test/com/sun/servicetag/DuplicateNotFound.java @@ -0,0 +1,97 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6622366 + * @summary Basic Test for RegistrationData.removeServiceTag and + * updateServiceTag. + * @author Mandy Chung + * + * @run build DuplicateNotFound Util + * @run main DuplicateNotFound + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +public class DuplicateNotFound { + private static String servicetagDir = System.getProperty("test.src"); + private static String[] files = new String[] { + "servicetag1.properties", + "servicetag2.properties", + "servicetag3.properties" + }; + + private static RegistrationData registration = new RegistrationData(); + + public static void main(String[] argv) throws Exception { + ServiceTag svcTag; + registration.addServiceTag(loadServiceTag(files[0])); + registration.addServiceTag(loadServiceTag(files[1])); + testDuplicate(files[0]); + testDuplicate(files[1]); + testNotFound(files[2]); + } + + private static void testDuplicate(String filename) throws Exception { + boolean dup = false; + try { + registration.addServiceTag(loadServiceTag(filename)); + } catch (IllegalArgumentException e) { + dup = true; + } + if (!dup) { + throw new RuntimeException(filename + + " added successfully but expected to be a duplicated."); + } + } + private static void testNotFound(String filename) throws Exception { + ServiceTag st = loadServiceTag(filename); + ServiceTag svctag = registration.getServiceTag(st.getInstanceURN()); + if (svctag != null) { + throw new RuntimeException(st.getInstanceURN() + + " exists but expected not found"); + } + + svctag = registration.removeServiceTag(st.getInstanceURN()); + if (svctag != null) { + throw new RuntimeException(st.getInstanceURN() + + " exists but expected not found"); + } + + svctag = registration.updateServiceTag(st.getInstanceURN(), "testing"); + if (svctag != null) { + throw new RuntimeException(st.getInstanceURN() + + " updated successfully but expected not found."); + } + } + + private static ServiceTag loadServiceTag(String filename) throws Exception { + File f = new File(servicetagDir, filename); + return Util.newServiceTag(f); + } +} diff --git a/test/com/sun/servicetag/FindServiceTags.java b/test/com/sun/servicetag/FindServiceTags.java new file mode 100644 index 000000000..e9bc09479 --- /dev/null +++ b/test/com/sun/servicetag/FindServiceTags.java @@ -0,0 +1,133 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6622366 + * @summary Basic Test for Registry.findServiceTags() + * @author Mandy Chung + * + * @run build FindServiceTags SvcTagClient Util + * @run main FindServiceTags + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +// This test creates a few service tags in the Registry. +// Check if the findServiceTags method returns the expected ones. +public class FindServiceTags { + private static String registryDir = System.getProperty("test.classes"); + private static String servicetagDir = System.getProperty("test.src"); + private static String[] files = new String[] { + "servicetag1.properties", + "servicetag2.properties", + "servicetag3.properties", + "servicetag4.properties", + "servicetag5.properties" + }; + + private static Registry registry; + private static Set set = new HashSet(); + private static Set productUrns = new HashSet(); + private static int expectedUrnCount = 3; + + public static void main(String[] argv) throws Exception { + registry = Util.getSvcTagClientRegistry(); + + for (String filename : files) { + File f = new File(servicetagDir, filename); + ServiceTag svcTag = Util.newServiceTag(f); + ServiceTag st = registry.addServiceTag(svcTag); + + set.add(st); + productUrns.add(st.getProductURN()); + } + if (productUrns.size() != expectedUrnCount) { + throw new RuntimeException("Unexpected number of product URNs = " + + productUrns.size() + " expected " + expectedUrnCount); + } + if (set.size() != files.length) { + throw new RuntimeException("Unexpected number of service tags = " + + set.size() + " expected " + files.length); + } + String purn = null; + for (String urn : productUrns) { + if (purn == null) { + // save the first product_urn for later use + purn = urn; + } + findServiceTags(urn); + } + + // remove all service tags of purn + Set tags = registry.findServiceTags(purn); + for (ServiceTag st : tags) { + System.out.println("Removing service tag " + st.getInstanceURN()); + registry.removeServiceTag(st.getInstanceURN()); + } + tags = registry.findServiceTags(purn); + if (tags.size() != 0) { + throw new RuntimeException("Unexpected service tag count = " + + tags.size()); + } + + System.out.println("Test passed."); + } + + private static void findServiceTags(String productUrn) throws Exception { + Set found = registry.findServiceTags(productUrn); + Set matched = new HashSet(); + System.out.println("Finding service tags of product_urn=" + + productUrn); + for (ServiceTag st : set) { + if (st.getProductURN().equals(productUrn)) { + System.out.println(st.getInstanceURN()); + matched.add(st); + } + } + if (found.size() != matched.size()) { + throw new RuntimeException("Unmatched service tag count = " + + found.size() + " expected " + matched.size()); + } + + for (ServiceTag st0 : found) { + ServiceTag st = null; + for (ServiceTag st1 : matched) { + if (Util.matches(st0, st1)) { + st = st1; + break; + } + } + if (st == null) { + System.out.println("product_urn=" + st0.getProductURN()); + System.out.println("instance_urn=" + st0.getInstanceURN() ); + throw new RuntimeException(st0.getInstanceURN() + + " not expected in the returned list"); + } + } + } +} diff --git a/test/com/sun/servicetag/InstanceUrnCheck.java b/test/com/sun/servicetag/InstanceUrnCheck.java new file mode 100644 index 000000000..b0736dd59 --- /dev/null +++ b/test/com/sun/servicetag/InstanceUrnCheck.java @@ -0,0 +1,76 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6622366 + * @summary Basic Test for checking instance_urn + * @author Mandy Chung + * + * @run build InstanceUrnCheck Util + * @run main InstanceUrnCheck + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +public class InstanceUrnCheck { + private static String servicetagDir = System.getProperty("test.src"); + private static String[] files = new String[] { + "servicetag1.properties", + "servicetag2.properties", + "servicetag3.properties" + }; + private static RegistrationData registration = new RegistrationData(); + + public static void main(String[] argv) throws Exception { + for (String f : files) { + addServiceTag(f); + } + } + + private static void addServiceTag(String filename) throws Exception { + File f = new File(servicetagDir, filename); + ServiceTag svcTag = Util.newServiceTag(f, true /* no instance_urn */); + ServiceTag st = registration.addServiceTag(svcTag); + if (!Util.matchesNoInstanceUrn(svcTag, st)) { + throw new RuntimeException("ServiceTag " + + " doesn't match."); + } + System.out.println("New service tag instance_urn=" + st.getInstanceURN()); + if (!st.getInstanceURN().startsWith("urn:st:")) { + throw new RuntimeException("Invalid generated instance_urn " + + st.getInstanceURN()); + } + if (st.getInstallerUID() != -1) { + throw new RuntimeException("Invalid installer_uid " + + st.getInstallerUID()); + } + if (st.getTimestamp() == null) { + throw new RuntimeException("null timestamp "); + } + } +} diff --git a/test/com/sun/servicetag/InvalidRegistrationData.java b/test/com/sun/servicetag/InvalidRegistrationData.java new file mode 100644 index 000000000..b68f5ee04 --- /dev/null +++ b/test/com/sun/servicetag/InvalidRegistrationData.java @@ -0,0 +1,65 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6622366 + * @summary Basic Test for invalid product registry + * @author Mandy Chung + * + * @run build InvalidRegistrationData + * @run main InvalidRegistrationData + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +public class InvalidRegistrationData { + public static void main(String[] argv) throws Exception { + String servicetagDir = System.getProperty("test.src"); + + checkRegistrationData(servicetagDir, "missing-environ-field.xml"); + checkRegistrationData(servicetagDir, "newer-registry-version.xml"); + } + + private static void checkRegistrationData(String parent, String filename) + throws Exception { + boolean thrown = false; + File f = new File(parent, filename); + BufferedInputStream in = new BufferedInputStream(new FileInputStream(f)); + try { + RegistrationData regData = RegistrationData.loadFromXML(in); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage() + " thrown expected"); + thrown = true; + } + + if (!thrown) { + throw new RuntimeException("ERROR: No IllegalArgumentException thrown"); + } + } + +} diff --git a/test/com/sun/servicetag/InvalidServiceTag.java b/test/com/sun/servicetag/InvalidServiceTag.java new file mode 100644 index 000000000..70b406a50 --- /dev/null +++ b/test/com/sun/servicetag/InvalidServiceTag.java @@ -0,0 +1,96 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6622366 + * @summary Basic Test for ServiceTag.newServiceTag() to test invalid fields. + * @author Mandy Chung + * + * @run build InvalidServiceTag + * @run main InvalidServiceTag + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +public class InvalidServiceTag { + private final static int MAX_CONTAINER_LEN = 64 - 1; + public static void main(String[] argv) throws Exception { + // all fields valid + ServiceTag st1 = ServiceTag.newInstance("product name", + "product version", + "product urn", + "product parent", + "product parent urn", + "product defined instance ID", + "product vendor", + "platform arch", + "container", + "source"); + // empty optional field + ServiceTag st2 = ServiceTag.newInstance("product name", + "product version", + "product urn", + "product parent", + "", + "", + "product vendor", + "platform arch", + "container", + "source"); + // Invalid - empty required field + setInvalidContainer(""); + // Invalid - required field exceeds max length. + StringBuilder sb = new StringBuilder(); + for (int i = 0; i <= MAX_CONTAINER_LEN; i++) { + sb.append('x'); + } + setInvalidContainer(sb.toString()); + System.out.println("Test passed."); + } + private static void setInvalidContainer(String container) { + boolean exceptionThrown = false; + try { + ServiceTag st2 = ServiceTag.newInstance("product name", + "product version", + "product urn", + "product parent", + "product parent urn", + "product defined instance ID", + "product vendor", + "platform arch", + container, + "source"); + } catch (IllegalArgumentException iae) { + iae.printStackTrace(); + exceptionThrown = true; + } + if (!exceptionThrown) { + throw new RuntimeException("IllegalArgumentException not thrown"); + } + } +} diff --git a/test/com/sun/servicetag/JavaServiceTagTest.java b/test/com/sun/servicetag/JavaServiceTagTest.java new file mode 100644 index 000000000..1647f0119 --- /dev/null +++ b/test/com/sun/servicetag/JavaServiceTagTest.java @@ -0,0 +1,176 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6622366 + * @summary Basic Test for ServiceTag.getJavaServiceTag() + * Disable creating the service tag in the system registry. + * Verify the existence of registration.xml file and the + * content of the service tag. + * @author Mandy Chung + * + * @run build JavaServiceTagTest + * @run main JavaServiceTagTest + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +public class JavaServiceTagTest { + public static void main(String[] argv) throws Exception { + String registrationDir = System.getProperty("test.classes"); + + // disable calling to stclient + System.setProperty("servicetag.sthelper.supported", "false"); + + if (Registry.isSupported()) { + throw new RuntimeException("Registry.isSupported() should " + + "return false"); + } + // For debugging + // System.setProperty("servicetag.verbose", ""); + + // cleanup the registration.xml and servicetag file in the test directory + System.setProperty("servicetag.dir.path", registrationDir); + File regFile = new File(registrationDir, "registration.xml"); + regFile.delete(); + File svcTagFile = new File(registrationDir, "servicetag"); + svcTagFile.delete(); + + ServiceTag svctag = ServiceTag.getJavaServiceTag("JavaServiceTagTest"); + checkServiceTag(svctag); + + if (svcTagFile.exists()) { + throw new RuntimeException(svcTagFile + " should not exist."); + } + + // registration.xml should be created + if (!regFile.exists()) { + throw new RuntimeException(regFile + " not created."); + } + BufferedInputStream in = new BufferedInputStream(new FileInputStream(regFile)); + RegistrationData registration = RegistrationData.loadFromXML(in); + Set c = registration.getServiceTags(); + if (c.size() != 1) { + throw new RuntimeException(regFile + " has " + c.size() + + " service tags. Expected 1."); + } + ServiceTag st = registration.getServiceTag(svctag.getInstanceURN()); + if (!Util.matches(st, svctag)) { + throw new RuntimeException("ServiceTag " + + " doesn't match."); + } + } + + private static void checkServiceTag(ServiceTag st) throws IOException { + Properties props = loadSwordfishEntries(); + if (st.getProductURN(). + equals(props.getProperty("servicetag.jdk.urn"))) { + if (!st.getProductName(). + equals(props.getProperty("servicetag.jdk.name"))) { + throw new RuntimeException("Product URN and name don't match."); + } + } else if (st.getProductURN(). + equals(props.getProperty("servicetag.jre.urn"))) { + if (!st.getProductName(). + equals(props.getProperty("servicetag.jre.name"))) { + throw new RuntimeException("Product URN and name don't match."); + } + } else { + throw new RuntimeException("Unexpected product_urn: " + + st.getProductURN()); + } + if (!st.getProductVersion(). + equals(System.getProperty("java.version"))) { + throw new RuntimeException("Unexpected product_version: " + + st.getProductVersion()); + } + if (!st.getProductParent(). + equals(props.getProperty("servicetag.parent.name"))) { + throw new RuntimeException("Unexpected product_parent: " + + st.getProductParent()); + } + if (!st.getProductParentURN(). + equals(props.getProperty("servicetag.parent.urn"))) { + throw new RuntimeException("Unexpected product_parent_urn: " + + st.getProductParentURN()); + } + if (!st.getPlatformArch(). + equals(System.getProperty("os.arch"))) { + throw new RuntimeException("Unexpected platform_arch: " + + st.getPlatformArch()); + } + if (!st.getProductVendor(). + equals("Sun Microsystems")) { + throw new RuntimeException("Unexpected product_vendor: " + + st.getProductVendor()); + } + if (!st.getSource(). + equals("JavaServiceTagTest")) { + throw new RuntimeException("Unexpected source: " + + st.getSource()); + } + String[] ss = st.getProductDefinedInstanceID().split(","); + boolean id = false; + boolean dir = false; + for (String s : ss) { + String[] values = s.split("="); + if (values[0].equals("id")) { + id = true; + String[] sss = values[1].split(" "); + if (!sss[0].equals(System.getProperty("java.runtime.version"))) { + throw new RuntimeException("Unexpected version in id: " + + sss[0]); + } + if (sss.length < 2) { + throw new RuntimeException("Unexpected id=" + values[1]); + } + } else if (values[0].equals("dir")) { + dir = true; + } + } + if (!id || !dir) { + throw new RuntimeException("Unexpected product_defined_instance_id: " + + st.getProductDefinedInstanceID()); + } + } + + private static Properties loadSwordfishEntries() + throws IOException { + int version = sun.misc.Version.jdkMinorVersion(); + String filename = "/com/sun/servicetag/resources/javase_" + + version + "_swordfish.properties"; + InputStream in = Installer.class.getClass().getResourceAsStream(filename); + Properties props = new Properties(); + try { + props.load(in); + } finally { + in.close(); + } + return props; + } +} diff --git a/test/com/sun/servicetag/JavaServiceTagTest1.java b/test/com/sun/servicetag/JavaServiceTagTest1.java new file mode 100644 index 000000000..3d5a8789b --- /dev/null +++ b/test/com/sun/servicetag/JavaServiceTagTest1.java @@ -0,0 +1,240 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6622366 + * @summary Basic Test for ServiceTag.getJavaServiceTag(String) + * to verify that the registration.xml and servicetag files + * are both created correctly. + * @author Mandy Chung + * + * @run build JavaServiceTagTest1 + * @run main JavaServiceTagTest1 + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +public class JavaServiceTagTest1 { + private static String registrationDir = System.getProperty("test.classes"); + private static String servicetagDir = System.getProperty("test.src"); + private static File regFile; + private static File svcTagFile; + private static Registry registry; + public static void main(String[] argv) throws Exception { + // cleanup the registration.xml and servicetag file in the test directory + System.setProperty("servicetag.dir.path", registrationDir); + regFile = new File(registrationDir, "registration.xml"); + regFile.delete(); + + svcTagFile = new File(registrationDir, "servicetag"); + svcTagFile.delete(); + + registry = Util.getSvcTagClientRegistry(); + + // verify that only one service tag is created + ServiceTag st1 = testJavaServiceTag("Test1"); + + // getJavaServiceTag method should create a new service tag + // and delete the old one + ServiceTag st2 = testJavaServiceTag("Test2"); + if (registry.getServiceTag(st1.getInstanceURN()) != null) { + throw new RuntimeException("instance_urn: " + st1.getInstanceURN() + + " exists but expected to be removed"); + } + + // expected to have different instance_urn + if (st1.getInstanceURN().equals(st2.getInstanceURN())) { + throw new RuntimeException("instance_urn: " + st1.getInstanceURN() + + " == " + st2.getInstanceURN()); + } + + // Delete the service tag from the Registry and the servicetag file + if (registry.removeServiceTag(st2.getInstanceURN()) == null) { + throw new RuntimeException("Failed to remove " + + st1.getInstanceURN() + " from the registry"); + } + svcTagFile.delete(); + + // call the getJavaServiceTag(String) method again + // should create the servicetag file. + ServiceTag st3 = testJavaServiceTag("Test2"); + if (!Util.matches(st2, st3)) { + System.out.println(st2); + System.out.println(st3); + throw new RuntimeException("Test Failed: Expected to be the same"); + } + + } + + private static ServiceTag testJavaServiceTag(String source) throws Exception { + ServiceTag svctag = ServiceTag.getJavaServiceTag(source); + checkServiceTag(svctag, source); + + // verify if registration.xml is created + if (!regFile.exists()) { + throw new RuntimeException(regFile + " not created."); + } + + // verify the registration.xml content is the expected service tag + BufferedInputStream in = new BufferedInputStream(new FileInputStream(regFile)); + RegistrationData registration = RegistrationData.loadFromXML(in); + Set c = registration.getServiceTags(); + if (c.size() != 1) { + throw new RuntimeException(regFile + " has " + c.size() + + " service tags. Expected 1."); + } + ServiceTag st = registration.getServiceTag(svctag.getInstanceURN()); + if (!Util.matches(st, svctag)) { + throw new RuntimeException("RegistrationData ServiceTag " + + " doesn't match."); + } + + // verify the service tag added in the registry + st = registry.getServiceTag(svctag.getInstanceURN()); + if (!Util.matches(st, svctag)) { + throw new RuntimeException("Registry ServiceTag " + + " doesn't match."); + } + + // verify if servicetag file is created + if (!svcTagFile.exists()) { + throw new RuntimeException(svcTagFile + " not created."); + } + + // verify that the servicetag file only contains one instance_urn + BufferedReader reader = new BufferedReader(new FileReader(svcTagFile)); + int count = 0; + try { + String line; + while ((line = reader.readLine()) != null) { + if (line.equals(svctag.getInstanceURN())) { + count++; + } else { + throw new RuntimeException("servicetag contains " + + " unexpected instance_urn " + line); + } + } + } finally { + reader.close(); + } + if (count != 1) { + throw new RuntimeException("servicetag contains unexpected " + + "number of instance_urn = " + count); + } + return svctag; + } + + private static void checkServiceTag(ServiceTag st, String source) + throws IOException { + Properties props = loadSwordfishEntries(); + if (st.getProductURN(). + equals(props.getProperty("servicetag.jdk.urn"))) { + if (!st.getProductName(). + equals(props.getProperty("servicetag.jdk.name"))) { + throw new RuntimeException("Product URN and name don't match."); + } + } else if (st.getProductURN(). + equals(props.getProperty("servicetag.jre.urn"))) { + if (!st.getProductName(). + equals(props.getProperty("servicetag.jre.name"))) { + throw new RuntimeException("Product URN and name don't match."); + } + } else { + throw new RuntimeException("Unexpected product_urn: " + + st.getProductURN()); + } + if (!st.getProductVersion(). + equals(System.getProperty("java.version"))) { + throw new RuntimeException("Unexpected product_version: " + + st.getProductVersion()); + } + if (!st.getProductParent(). + equals(props.getProperty("servicetag.parent.name"))) { + throw new RuntimeException("Unexpected product_parent: " + + st.getProductParent()); + } + if (!st.getProductParentURN(). + equals(props.getProperty("servicetag.parent.urn"))) { + throw new RuntimeException("Unexpected product_parent_urn: " + + st.getProductParentURN()); + } + if (!st.getPlatformArch(). + equals(System.getProperty("os.arch"))) { + throw new RuntimeException("Unexpected platform_arch: " + + st.getPlatformArch()); + } + if (!st.getProductVendor(). + equals("Sun Microsystems")) { + throw new RuntimeException("Unexpected product_vendor: " + + st.getProductVendor()); + } + if (!st.getSource(). + equals(source)) { + throw new RuntimeException("Unexpected source: " + + st.getSource() + " expected: " + source); + } + String[] ss = st.getProductDefinedInstanceID().split(","); + boolean id = false; + boolean dir = false; + for (String s : ss) { + String[] values = s.split("="); + if (values[0].equals("id")) { + id = true; + String[] sss = values[1].split(" "); + if (!sss[0].equals(System.getProperty("java.runtime.version"))) { + throw new RuntimeException("Unexpected version in id: " + + sss[0]); + } + if (sss.length < 2) { + throw new RuntimeException("Unexpected id=" + values[1]); + } + } else if (values[0].equals("dir")) { + dir = true; + } + } + if (!id || !dir) { + throw new RuntimeException("Unexpected product_defined_instance_id: " + + st.getProductDefinedInstanceID()); + } + } + + private static Properties loadSwordfishEntries() + throws IOException { + int version = sun.misc.Version.jdkMinorVersion(); + String filename = "/com/sun/servicetag/resources/javase_" + + version + "_swordfish.properties"; + InputStream in = Installer.class.getClass().getResourceAsStream(filename); + Properties props = new Properties(); + try { + props.load(in); + } finally { + in.close(); + } + return props; + } +} diff --git a/test/com/sun/servicetag/NewRegistrationData.java b/test/com/sun/servicetag/NewRegistrationData.java new file mode 100644 index 000000000..4a91e578e --- /dev/null +++ b/test/com/sun/servicetag/NewRegistrationData.java @@ -0,0 +1,105 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6622366 + * @summary Basic Test for Registration Data + * @author Mandy Chung + * + * @run build NewRegistrationData Util + * @run main NewRegistrationData + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +public class NewRegistrationData { + private static RegistrationData regData; + private static Map stMap = new LinkedHashMap(); + private static String[] files = new String[] { + "servicetag1.properties", + "servicetag2.properties", + "servicetag3.properties" + }; + + public static void main(String[] argv) throws Exception { + String regDataDir = System.getProperty("test.classes"); + String servicetagDir = System.getProperty("test.src"); + + File reg = new File(regDataDir, "registration.xml"); + // Make sure a brand new file is created + reg.delete(); + + regData = new RegistrationData(); + if (regData.getRegistrationURN().isEmpty()) { + throw new RuntimeException("Empty registration urn"); + } + + int count = 0; + for (String f : files) { + addServiceTag(servicetagDir, f, ++count); + } + + // check if the registration data contains all service tags + Set c = regData.getServiceTags(); + for (ServiceTag st : c) { + if (!Util.matches(st, regData.getServiceTag(st.getInstanceURN()))) { + throw new RuntimeException("ServiceTag added in the regData " + + " doesn't match."); + } + } + + // store the service tag to a file + BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(reg)); + try { + regData.storeToXML(out); + } finally { + out.close(); + } + + Util.checkRegistrationData(reg.getCanonicalPath(), stMap); + System.out.println("Test passed: " + count + " service tags added"); + } + + private static void addServiceTag(String parent, String filename, int count) throws Exception { + File f = new File(parent, filename); + ServiceTag svcTag = Util.newServiceTag(f); + regData.addServiceTag(svcTag); + stMap.put(svcTag.getInstanceURN(), svcTag); + + Set c = regData.getServiceTags(); + if (c.size() != count) { + throw new RuntimeException("Invalid service tag count= " + + c.size() + " expected=" + count); + } + ServiceTag st = regData.getServiceTag(svcTag.getInstanceURN()); + if (!Util.matches(st, svcTag)) { + throw new RuntimeException("ServiceTag added in the regData " + + " doesn't match."); + } + } +} diff --git a/test/com/sun/servicetag/SvcTagClient.java b/test/com/sun/servicetag/SvcTagClient.java new file mode 100644 index 000000000..c63d1deee --- /dev/null +++ b/test/com/sun/servicetag/SvcTagClient.java @@ -0,0 +1,200 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @bug 6622366 + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +/** + * A utility class simulating stclient for testing purpose. + */ +public class SvcTagClient { + private static File xmlFile; + private static RegistrationData registration; + private static String instanceURN; + private static String productName; + private static String productVersion; + private static String productURN; + private static String productParent; + private static String productParentURN = ""; // optional + private static String productDefinedInstanceID = ""; //optional + private static String productVendor; + private static String platformArch; + private static String container; + private static String source; + + // stclient exit value + private static final int ST_ERR_REC_NOT_FOUND = 225; + + public static void main(String[] args) throws Exception { + String path = System.getProperty("stclient.registry.path"); + if (path == null) { + System.err.println("stclient registry path missing"); + System.exit(-1); + } + xmlFile = new File(path); + if (xmlFile.exists()) { + BufferedInputStream in = new BufferedInputStream(new FileInputStream(xmlFile)); + registration = RegistrationData.loadFromXML(in); + } else { + registration = new RegistrationData(); + } + boolean add = false; + boolean delete = false; + boolean update = false; + boolean get = false; + boolean find = false; + + int count = 0; + while (count < args.length) { + String arg = args[count]; + if (!arg.startsWith("-")) { + System.err.println("Invalid option:" + arg); + System.exit(-1); + } + if (arg.equals("-a")) { + add = true; + } else if (arg.equals("-d")) { + delete = true; + } else if (arg.equals("-u")) { + update = true; + } else if (arg.equals("-g")) { + get = true; + } else if (arg.equals("-f")) { + find = true; + productURN = ""; + } else if (arg.equals("-t")) { + productURN = args[++count]; + } else if (arg.equals("-i")) { + instanceURN = args[++count]; + } else if (arg.equals("-p")) { + productName = args[++count]; + } else if (arg.equals("-e")) { + productVersion = args[++count]; + } else if (arg.equals("-t")) { + productURN = args[++count]; + } else if (arg.equals("-F")) { + productParentURN = args[++count]; + } else if (arg.equals("-P")) { + productParent = args[++count]; + } else if (arg.equals("-I")) { + productDefinedInstanceID = args[++count]; + } else if (arg.equals("-m")) { + productVendor = args[++count]; + } else if (arg.equals("-A")) { + platformArch = args[++count]; + } else if (arg.equals("-z")) { + container = args[++count]; + } else if (arg.equals("-S")) { + source = args[++count]; + } else { + System.err.println("Invalid option:" + arg); + System.exit(-1); + } + count++; + } + + if (add) { + addServiceTag(); + } else if (delete) { + deleteServiceTag(); + } else if (update) { + updateServiceTag(); + } else if (get) { + getServiceTag(); + } else if (find) { + findServiceTags(); + } else { + System.err.println("Error"); + System.exit(-1); + } + updateXmlFile(); + } + private static String OUTPUT = "Product instance URN="; + + private static void addServiceTag() { + if (instanceURN == null) { + instanceURN = ServiceTag.generateInstanceURN(); + } + ServiceTag st = ServiceTag.newInstance(instanceURN, + productName, + productVersion, + productURN, + productParent, + productParentURN, + productDefinedInstanceID, + productVendor, + platformArch, + container, + source); + registration.addServiceTag(st); + System.out.println(OUTPUT + st.getInstanceURN()); + } + + private static void deleteServiceTag() { + registration.removeServiceTag(instanceURN); + System.out.println("instance_urn=" + instanceURN + " deleted"); + } + + private static void updateServiceTag() { + registration.updateServiceTag(instanceURN, productDefinedInstanceID); + System.out.println("instance_urn=" + instanceURN + " updated"); + } + + private static void getServiceTag() { + ServiceTag st = registration.getServiceTag(instanceURN); + if (st == null) { + System.err.println("instance_urn=" + instanceURN + " not found"); + System.exit(ST_ERR_REC_NOT_FOUND); + } else { + System.out.println(st); + } + } + + private static void findServiceTags() { + Set set = registration.getServiceTags(); + for (ServiceTag st : set) { + if (st.getProductURN().equals(productURN)) { + System.out.println(st.getInstanceURN()); + } + } + if (set.size() == 0) { + System.out.println("No records found"); + System.exit(ST_ERR_REC_NOT_FOUND); + } + } + private static void updateXmlFile() throws IOException { + BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(xmlFile)); + try { + registration.storeToXML(out); + } finally { + out.close(); + } + } +} diff --git a/test/com/sun/servicetag/SystemRegistryTest.java b/test/com/sun/servicetag/SystemRegistryTest.java new file mode 100644 index 000000000..0cabcedfc --- /dev/null +++ b/test/com/sun/servicetag/SystemRegistryTest.java @@ -0,0 +1,131 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6622366 + * @summary Basic Test for registry class + * by replacing stclient with SvcTagClient utility + * @author Mandy Chung + * + * @run build SvcTagClient SystemRegistryTest Util + * @run main SystemRegistryTest + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +public class SystemRegistryTest { + private static String registryDir = System.getProperty("test.classes"); + private static String servicetagDir = System.getProperty("test.src"); + private static List list = new ArrayList(); + private static String[] files = new String[] { + "servicetag1.properties", + "servicetag2.properties", + "servicetag3.properties" + }; + + private static Registry registry; + public static void main(String[] argv) throws Exception { + registry = Util.getSvcTagClientRegistry(); + + for (String filename : files) { + File f = new File(servicetagDir, filename); + ServiceTag svcTag = Util.newServiceTag(f); + ServiceTag st = registry.addServiceTag(svcTag); + list.add(st); + System.out.println(st); + } + + testDuplicate(list.get(0)); + testNotFound(); + + // remove a service tag + String urn = list.get(0).getInstanceURN(); + ServiceTag svcTag = registry.removeServiceTag(urn); + if (!Util.matches(svcTag, list.get(0))) { + throw new RuntimeException(urn + + " deleted but does not match."); + } + + // get a service tag + svcTag = list.get(1); + urn = svcTag.getInstanceURN(); + ServiceTag st = registry.getServiceTag(urn); + if (!Util.matches(svcTag, st)) { + throw new RuntimeException(urn + + " returned from getServiceTag but does not match."); + } + // update the service tag + registry.updateServiceTag(urn, "My new defined ID"); + st = registry.getServiceTag(urn); + if (Util.matches(svcTag, st)) { + throw new RuntimeException(urn + + " updated but expected to be different."); + } + + if (!st.getProductDefinedInstanceID().equals("My new defined ID")) { + throw new RuntimeException("Invalid product_defined_instance_id " + + st.getProductDefinedInstanceID()); + } + if (st.getInstallerUID() != -1) { + throw new RuntimeException("Invalid installer_uid " + + st.getInstallerUID()); + } + if (st.getTimestamp().equals(svcTag.getTimestamp())) { + throw new RuntimeException("Timestamp " + + st.getTimestamp() + " == " + svcTag.getTimestamp()); + } + + } + private static void testDuplicate(ServiceTag st) throws IOException { + boolean dup = false; + try { + registry.addServiceTag(st); + } catch (IllegalArgumentException e) { + dup = true; + } + if (!dup) { + throw new RuntimeException(st.getInstanceURN() + + " added successfully but expected to be a duplicated."); + } + } + + private static void testNotFound() throws Exception { + String instanceURN = "urn:st:721cf98a-f4d7-6231-bb1d-f2f5aa903ef7"; + ServiceTag svctag = registry.removeServiceTag(instanceURN); + if (svctag != null) { + throw new RuntimeException(instanceURN + + " exists but expected not found"); + } + + svctag = registry.updateServiceTag(instanceURN, "testing"); + if (svctag != null) { + throw new RuntimeException(instanceURN + + " exists but expected not found"); + } + } +} diff --git a/test/com/sun/servicetag/TestLoadFromXML.java b/test/com/sun/servicetag/TestLoadFromXML.java new file mode 100644 index 000000000..dcc19f355 --- /dev/null +++ b/test/com/sun/servicetag/TestLoadFromXML.java @@ -0,0 +1,69 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6622366 + * @summary Basic Test for RegistrationData.loadFromXML + * @author Mandy Chung + * + * @run build TestLoadFromXML + * @run main TestLoadFromXML + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +public class TestLoadFromXML { + public static void main(String[] argv) throws Exception { + String registrationDir = System.getProperty("test.classes"); + String servicetagDir = System.getProperty("test.src"); + + File inFile = new File(servicetagDir, "registration.xml"); + File outFile = new File(registrationDir, "out.xml"); + BufferedInputStream in = new BufferedInputStream(new FileInputStream(inFile)); + RegistrationData regData = RegistrationData.loadFromXML(in); + boolean closed = false; + try { + in.read(); + } catch (IOException e) { + // expect the InputStream is closed + closed = true; + System.out.println("*** Expected IOException ***"); + e.printStackTrace(); + } + if (!closed) { + throw new RuntimeException("InputStream not closed after " + + "RegistrationData.loadFromXML() call"); + } + + BufferedOutputStream out = + new BufferedOutputStream(new FileOutputStream(outFile)); + regData.storeToXML(out); + // should be able to write to the OutputStream + out.write(0); + } +} diff --git a/test/com/sun/servicetag/UpdateServiceTagTest.java b/test/com/sun/servicetag/UpdateServiceTagTest.java new file mode 100644 index 000000000..1d61f3f96 --- /dev/null +++ b/test/com/sun/servicetag/UpdateServiceTagTest.java @@ -0,0 +1,109 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6622366 + * @summary Basic Test for RegistrationData.updateServiceTag + * @author Mandy Chung + * + * @run build UpdateServiceTagTest Util + * @run main UpdateServiceTagTest + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +public class UpdateServiceTagTest { + private static String servicetagDir = System.getProperty("test.src"); + private static String[] files = new String[] { + "servicetag1.properties", + "servicetag2.properties", + "servicetag3.properties" + }; + private static RegistrationData registration = new RegistrationData(); + private static Set set = new HashSet(); + + public static void main(String[] argv) throws Exception { + for (String f : files) { + ServiceTag st = addServiceTag(f); + set.add(st); + } + Thread.sleep(1000); + for (ServiceTag st : set) { + updateServiceTag(st); + } + } + + private static ServiceTag addServiceTag(String filename) throws Exception { + File f = new File(servicetagDir, filename); + ServiceTag svcTag = Util.newServiceTag(f, true /* no instance_urn */); + ServiceTag st = registration.addServiceTag(svcTag); + if (!Util.matchesNoInstanceUrn(svcTag, st)) { + throw new RuntimeException("ServiceTag " + + " doesn't match."); + } + String urn = st.getInstanceURN(); + if (!urn.startsWith("urn:st:")) { + throw new RuntimeException("Invalid generated instance_urn " + + urn); + } + if (st.getInstallerUID() != -1) { + throw new RuntimeException("Invalid installer_uid " + + st.getInstallerUID()); + } + if (st.getTimestamp() == null) { + throw new RuntimeException("null timestamp "); + } + return st; + } + + private static String newID = "New product defined instance ID"; + private static void updateServiceTag(ServiceTag svcTag) throws Exception { + // update the service tag + String urn = svcTag.getInstanceURN(); + registration.updateServiceTag(urn, newID); + + // get the updated service tag + ServiceTag st = registration.getServiceTag(urn); + if (Util.matches(svcTag, st)) { + throw new RuntimeException("ServiceTag " + + " should not match."); + } + if (!st.getProductDefinedInstanceID().equals(newID)) { + throw new RuntimeException("Invalid product_defined_instance_id " + + st.getProductDefinedInstanceID()); + } + if (st.getInstallerUID() != -1) { + throw new RuntimeException("Invalid installer_uid " + + st.getInstallerUID()); + } + if (st.getTimestamp().equals(svcTag.getTimestamp())) { + throw new RuntimeException("Timestamp " + + st.getTimestamp() + " == " + svcTag.getTimestamp()); + } + } +} diff --git a/test/com/sun/servicetag/Util.java b/test/com/sun/servicetag/Util.java new file mode 100644 index 000000000..367486dba --- /dev/null +++ b/test/com/sun/servicetag/Util.java @@ -0,0 +1,250 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @bug 6622366 + * @summary Utility class used by other jtreg tests + */ + +import com.sun.servicetag.RegistrationData; +import com.sun.servicetag.ServiceTag; +import com.sun.servicetag.Registry; + +import java.util.Set; +import java.util.Date; +import java.util.Map; +import java.util.Properties; +import java.util.TimeZone; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.io.*; + +public class Util { + public static ServiceTag newServiceTag(File f) + throws FileNotFoundException, IOException, NumberFormatException { + return newServiceTag(f, false /* with instance_urn */); + } + + public static ServiceTag newServiceTag(File f, boolean noInstanceURN) + throws FileNotFoundException, IOException, NumberFormatException { + Properties props = new Properties(); + FileReader reader = new FileReader(f); + try { + props.load(reader); + } finally { + reader.close(); + } + if (noInstanceURN) { + return ServiceTag.newInstance( + props.getProperty("product_name"), + props.getProperty("product_version"), + props.getProperty("product_urn"), + props.getProperty("product_parent"), + props.getProperty("product_parent_urn"), + props.getProperty("product_defined_inst_id"), + props.getProperty("product_vendor"), + props.getProperty("platform_arch"), + props.getProperty("container"), + props.getProperty("source")); + } else { + return ServiceTag.newInstance( + props.getProperty("instance_urn"), + props.getProperty("product_name"), + props.getProperty("product_version"), + props.getProperty("product_urn"), + props.getProperty("product_parent"), + props.getProperty("product_parent_urn"), + props.getProperty("product_defined_inst_id"), + props.getProperty("product_vendor"), + props.getProperty("platform_arch"), + props.getProperty("container"), + props.getProperty("source")); + } + } + + public static boolean matches(ServiceTag st1, ServiceTag st2) { + if (!st1.getInstanceURN().equals(st2.getInstanceURN())) { + System.out.println("instance_urn: " + st1.getInstanceURN() + + " != " + st2.getInstanceURN()); + return false; + } + return matchesNoInstanceUrn(st1, st2); + } + + public static boolean matchesNoInstanceUrn(ServiceTag st1, ServiceTag st2) { + if (!st1.getProductName().equals(st2.getProductName())) { + System.out.println("product_name: " + st1.getProductName() + + " != " + st2.getProductName()); + return false; + } + + if (!st1.getProductVersion().equals(st2.getProductVersion())) { + System.out.println("product_version: " + st1.getProductVersion() + + " != " + st2.getProductVersion()); + return false; + } + if (!st1.getProductURN().equals(st2.getProductURN())) { + System.out.println("product_urn: " + st1.getProductURN() + + " != " + st2.getProductURN()); + return false; + } + if (!st1.getProductParentURN().equals(st2.getProductParentURN())) { + System.out.println("product_parent_urn: " + st1.getProductParentURN() + + " != " + st2.getProductParentURN()); + return false; + } + if (!st1.getProductParent().equals(st2.getProductParent())) { + System.out.println("product_parent: " + st1.getProductParent() + + " != " + st2.getProductParent()); + return false; + } + if (!st1.getProductDefinedInstanceID().equals(st2.getProductDefinedInstanceID())) { + System.out.println("product_defined_inst_id: " + + st1.getProductDefinedInstanceID() + + " != " + st2.getProductDefinedInstanceID()); + return false; + } + if (!st1.getProductVendor().equals(st2.getProductVendor())) { + System.out.println("product_vendor: " + st1.getProductVendor() + + " != " + st2.getProductVendor()); + return false; + } + if (!st1.getPlatformArch().equals(st2.getPlatformArch())) { + System.out.println("platform_arch: " + st1.getPlatformArch() + + " != " + st2.getPlatformArch()); + return false; + } + if (!st1.getContainer().equals(st2.getContainer())) { + System.out.println("container: " + st1.getContainer() + + " != " + st2.getContainer()); + return false; + } + if (!st1.getSource().equals(st2.getSource())) { + System.out.println("source: " + st1.getSource() + + " != " + st2.getSource()); + return false; + } + return true; + } + + public static void checkRegistrationData(String regFile, + Map stMap) + throws IOException { + BufferedInputStream in = new BufferedInputStream(new FileInputStream(regFile)); + RegistrationData registration = RegistrationData.loadFromXML(in); + Set svcTags = registration.getServiceTags(); + if (svcTags.size() != stMap.size()) { + throw new RuntimeException("Invalid service tag count= " + + svcTags.size() + " expected=" + stMap.size()); + } + for (ServiceTag st : svcTags) { + ServiceTag st1 = stMap.get(st.getInstanceURN()); + if (!matches(st, st1)) { + throw new RuntimeException("ServiceTag in the registry " + + "does not match the one in the map"); + } + } + } + + + /** + * Formats the Date into a timestamp string in YYYY-MM-dd HH:mm:ss GMT. + * @param timestamp Date + * @return a string representation of the timestamp in the YYYY-MM-dd HH:mm:ss GMT format. + */ + static String formatTimestamp(Date timestamp) { + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); + df.setTimeZone(TimeZone.getTimeZone("GMT")); + return df.format(timestamp); + } + + /** + * Parses a timestamp string in YYYY-MM-dd HH:mm:ss GMT format. + * @param timestamp Timestamp in the YYYY-MM-dd HH:mm:ss GMT format. + * @return Date + */ + static Date parseTimestamp(String timestamp) { + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); + df.setTimeZone(TimeZone.getTimeZone("GMT")); + try { + return df.parse(timestamp); + } catch (ParseException e) { + // should not reach here + e.printStackTrace(); + return new Date(); + } + } + + /** + * Returns the command simulating stclient behavior. + */ + static String getSvcClientCommand(String stclientRegistry) { + String regDir = System.getProperty("test.classes"); + + StringBuilder sb = new StringBuilder(); + // wrap each argument to the command with double quotes + sb.append("\""); + sb.append(System.getProperty("java.home")); + sb.append(File.separator).append("bin"); + sb.append(File.separator).append("java"); + sb.append("\""); + sb.append(" -cp "); + sb.append("\"").append(regDir).append("\""); + sb.append(" \"-Dstclient.registry.path="); + sb.append(stclientRegistry).append("\""); + sb.append(" SvcTagClient"); + return sb.toString(); + } + + private static Registry registry = null; + /** + * Returns the Registry processed by SvcTagClient that simulates + * stclient. + */ + static synchronized Registry getSvcTagClientRegistry() throws IOException { + if (registry != null) { + return registry; + } + + // System.setProperty("servicetag.verbose", "true"); + // enable the helper class + System.setProperty("servicetag.sthelper.supported", "true"); + + // clean up registry.xml + String regDir = System.getProperty("test.classes"); + File registryFile = new File(regDir, "registry.xml"); + if (registryFile.exists()) { + registryFile.delete(); + } + + String stclientCmd = Util.getSvcClientCommand(registryFile.getCanonicalPath()); + System.out.println("stclient cmd: " + stclientCmd); + System.setProperty("servicetag.stclient.cmd", stclientCmd); + + // get the Registry object after the system properties are set + registry = Registry.getSystemRegistry(); + return registry; + } +} diff --git a/test/com/sun/servicetag/ValidRegistrationData.java b/test/com/sun/servicetag/ValidRegistrationData.java new file mode 100644 index 000000000..ec6929398 --- /dev/null +++ b/test/com/sun/servicetag/ValidRegistrationData.java @@ -0,0 +1,112 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6622366 + * @summary Basic Test for reading a valid registration + * @author Mandy Chung + * + * @run build ValidRegistrationData + * @run main ValidRegistrationData + */ + +import com.sun.servicetag.*; +import java.io.*; +import java.util.*; + +public class ValidRegistrationData { + private static String registrationDir = System.getProperty("test.classes"); + private static String servicetagDir = System.getProperty("test.src"); + private static RegistrationData registration; + private static Map stMap = + new LinkedHashMap(); + private static String[] files = new String[] { + "servicetag1.properties", + "servicetag2.properties", + "servicetag3.properties" + }; + private static String URN = "urn:st:9543ffaa-a4f1-4f77-b2d1-f561922d4e4a"; + + public static void main(String[] argv) throws Exception { + File f = new File(servicetagDir, "registration.xml"); + + // load the registration data with all service tags + BufferedInputStream in = new BufferedInputStream(new FileInputStream(f)); + registration = RegistrationData.loadFromXML(in); + if (!registration.getRegistrationURN().equals(URN)){ + throw new RuntimeException("Invalid URN=" + + registration.getRegistrationURN()); + } + Map environMap = registration.getEnvironmentMap(); + checkEnvironmentMap(environMap); + + // set environment + setInvalidEnvironment("hostname", ""); + setInvalidEnvironment("osName", ""); + setInvalidEnvironment("invalid", ""); + } + + private static void checkEnvironmentMap(Map envMap) + throws Exception { + Properties props = new Properties(); + File f = new File(servicetagDir, "environ.properties"); + FileReader reader = new FileReader(f); + try { + props.load(reader); + } finally { + reader.close(); + } + for (Map.Entry entry : envMap.entrySet()) { + String name = entry.getKey(); + String value = entry.getValue(); + String expected = props.getProperty(name); + if (expected == null || !value.equals(expected)) { + throw new RuntimeException("Invalid environment " + + name + "=" + value); + } + props.remove(name); + } + if (!props.isEmpty()) { + System.out.println("Environment missing: "); + for (String s : props.stringPropertyNames()) { + System.out.println(" " + s + "=" + props.getProperty(s)); + } + throw new RuntimeException("Invalid environment read"); + } + } + private static void setInvalidEnvironment(String name, String value) { + boolean invalid = false; + try { + registration.setEnvironment(name, value); + } catch (IllegalArgumentException e) { + invalid = true; + } + if (!invalid) { + throw new RuntimeException(name + "=" + value + + " set but expected to fail."); + } + } +} diff --git a/test/com/sun/servicetag/environ.properties b/test/com/sun/servicetag/environ.properties new file mode 100644 index 000000000..0881061b0 --- /dev/null +++ b/test/com/sun/servicetag/environ.properties @@ -0,0 +1,9 @@ +hostname=ko +hostId=83abc1ab +osName=SunOS +osVersion=5.10 +osArchitecture=sparc +systemModel=Sun-Fire-V440 +systemManufacturer=Sun Microsystems +cpuManufacturer=Sun Microsystems +serialNumber=BEL078932 diff --git a/test/com/sun/servicetag/missing-environ-field.xml b/test/com/sun/servicetag/missing-environ-field.xml new file mode 100644 index 000000000..727288dd1 --- /dev/null +++ b/test/com/sun/servicetag/missing-environ-field.xml @@ -0,0 +1,45 @@ + + + +ko + +SunOS +5.10 +sparc + + + + + + +urn:st:9efff93a-767c-4714-fcfa-c48988293110 +Java SE 6 Runtime Environment +1.6.0-internal +urn:uuid:92d1de8c-1e59-42c6-a280-1c379526bcbc +urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3 +Java Platform Standard Edition 6 (Java SE 6) +id=1.6.0-internal-b00 sparc,dir=/myjdk/solaris-sparc +Sun Microsystems +sparc +2007-11-12 06:15:11 GMT +global +servicetag1.properties +121937 + + +urn:st:0e9712bf-4832-e315-8e40-c4b17ffac9a9 +Java SE 6 Development Kit +1.6.0 +urn:uuid:b58ef9a8-5ae8-11db-a023-080020a9ed93 +urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3 +Java Platform Standard Edition 6 (Java SE 6) +id=1.6.0_05-b01 sparc,dir=/myjdk/solaris-i586 +Sun Microsystems +i386 +2007-11-12 06:15:11 GMT +global +servicetag2.properties +121937 + + + diff --git a/test/com/sun/servicetag/newer-registry-version.xml b/test/com/sun/servicetag/newer-registry-version.xml new file mode 100644 index 000000000..9ee68ac0a --- /dev/null +++ b/test/com/sun/servicetag/newer-registry-version.xml @@ -0,0 +1,32 @@ + + + +ko + +SunOS +5.10 +sparc + + + + + + + +urn:st:9efff93a-767c-4714-fcfa-c48988293110 +Java SE 6 Runtime Environment +1.6.0-internal +urn:uuid:92d1de8c-1e59-42c6-a280-1c379526bcbc +urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3 +Java Platform Standard Edition 6 (Java SE 6) +id=1.6.0-internal-b00 sparc,dir=/myjdk/solaris-sparc +Sun Microsystems +sparc +2007-11-13 00:49:01 GMT +global +servicetag1.properties +121937 + + + + diff --git a/test/com/sun/servicetag/registration.xml b/test/com/sun/servicetag/registration.xml new file mode 100644 index 000000000..e7a431a0f --- /dev/null +++ b/test/com/sun/servicetag/registration.xml @@ -0,0 +1,61 @@ + + + +ko +83abc1ab +SunOS +5.10 +sparc +Sun-Fire-V440 +Sun Microsystems +Sun Microsystems +BEL078932 + + + +urn:st:9efff93a-767c-4714-fcfa-c48988293110 +Java SE 6 Runtime Environment +1.6.0-internal +urn:uuid:92d1de8c-1e59-42c6-a280-1c379526bcbc +urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3 +Java Platform Standard Edition 6 (Java SE 6) +id=1.6.0-internal-b00 sparc,dir=/myjdk/solaris-sparc +Sun Microsystems +sparc +2007-11-13 00:49:01 GMT +global +servicetag1.properties +121937 + + +urn:st:0e9712bf-4832-e315-8e40-c4b17ffac9a9 +Java SE 6 Development Kit +1.6.0 +urn:uuid:b58ef9a8-5ae8-11db-a023-080020a9ed93 +urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3 +Java Platform Standard Edition 6 (Java SE 6) +id=1.6.0_05-b01 i386,dir=/myjdk/solaris-i586 +Sun Microsystems +i386 +2007-11-13 00:49:01 GMT +global +servicetag2.properties +121937 + + +urn:st:8a6ff75e-21a4-c8d7-bbda-de2c971bd67d +Solaris 10 Operating System +10 +urn:uuid:5005588c-36f3-11d6-9cec-fc96f718e113 +urn:uuid:596ffcfa-63d5-11d7-9886-ac816a682f92 +Solaris Operating System + +Sun Microsystems +sparc +2007-11-13 00:49:01 GMT +global +servicetag3.properties +212883 + + + diff --git a/test/com/sun/servicetag/servicetag1.properties b/test/com/sun/servicetag/servicetag1.properties new file mode 100644 index 000000000..3a1e8acc3 --- /dev/null +++ b/test/com/sun/servicetag/servicetag1.properties @@ -0,0 +1,13 @@ +instance_urn=urn:st:9efff93a-767c-4714-fcfa-c48988293110 +product_name=Java SE 6 Runtime Environment +product_version=1.6.0-internal +product_urn=urn:uuid:92d1de8c-1e59-42c6-a280-1c379526bcbc +product_parent_urn=urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3 +product_parent=Java Platform Standard Edition 6 (Java SE 6) +product_defined_inst_id=id=1.6.0-internal-b00 sparc,dir=/myjdk/solaris-sparc +product_vendor=Sun Microsystems +platform_arch=sparc +timestamp=2007-11-12 05:19:40 GMT +container=global +source=servicetag1.properties +installer_uid=121937 diff --git a/test/com/sun/servicetag/servicetag2.properties b/test/com/sun/servicetag/servicetag2.properties new file mode 100644 index 000000000..d5dbe14f8 --- /dev/null +++ b/test/com/sun/servicetag/servicetag2.properties @@ -0,0 +1,13 @@ +instance_urn=urn:st:0e9712bf-4832-e315-8e40-c4b17ffac9a9 +product_name=Java SE 6 Development Kit +product_version=1.6.0 +product_urn=urn:uuid:b58ef9a8-5ae8-11db-a023-080020a9ed93 +product_parent_urn=urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3 +product_parent=Java Platform Standard Edition 6 (Java SE 6) +product_defined_inst_id=id=1.6.0_05-b01 i386,dir=/myjdk/solaris-i586 +product_vendor=Sun Microsystems +platform_arch=i386 +timestamp=2007-11-12 06:12:21 GMT +container=global +source=servicetag2.properties +installer_uid=121937 diff --git a/test/com/sun/servicetag/servicetag3.properties b/test/com/sun/servicetag/servicetag3.properties new file mode 100644 index 000000000..6ca5dc79d --- /dev/null +++ b/test/com/sun/servicetag/servicetag3.properties @@ -0,0 +1,13 @@ +instance_urn=urn:st:8a6ff75e-21a4-c8d7-bbda-de2c971bd67d +product_name=Solaris 10 Operating System +product_version=10 +product_urn=urn:uuid:5005588c-36f3-11d6-9cec-fc96f718e113 +product_parent_urn=urn:uuid:596ffcfa-63d5-11d7-9886-ac816a682f92 +product_parent=Solaris Operating System +product_defined_inst_id= +product_vendor=Sun Microsystems +platform_arch=sparc +timestamp=2007-06-20 22:07:11 GMT +container=global +source=servicetag3.properties +installer_uid=212883 diff --git a/test/com/sun/servicetag/servicetag4.properties b/test/com/sun/servicetag/servicetag4.properties new file mode 100644 index 000000000..ba7c3c526 --- /dev/null +++ b/test/com/sun/servicetag/servicetag4.properties @@ -0,0 +1,13 @@ +instance_urn=urn:st:b8171b45-a087-47b3-92c8-f2d9fb34e8c2 +product_name=Java SE 6 Runtime Environment +product_version=1.6.0_05 +product_urn=urn:uuid:92d1de8c-1e59-42c6-a280-1c379526bcbc +product_parent_urn=urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3 +product_parent=Java Platform Standard Edition 6 (Java SE 6) +product_defined_inst_id=id=1.6.0_05-b01 amd64,dir=/myjdk/linux-amd64 +product_vendor=Sun Microsystems +platform_arch=x64 +timestamp=2007-12-12 05:19:40 GMT +container=global +source=servicetag4.properties +installer_uid=121937 diff --git a/test/com/sun/servicetag/servicetag5.properties b/test/com/sun/servicetag/servicetag5.properties new file mode 100644 index 000000000..84e44c324 --- /dev/null +++ b/test/com/sun/servicetag/servicetag5.properties @@ -0,0 +1,13 @@ +instance_urn=urn:st:1d4269a1-71e3-4e44-bc8f-3793da7928ed +product_name=Java SE 6 Runtime Environment +product_version=1.6.0_06 +product_urn=urn:uuid:92d1de8c-1e59-42c6-a280-1c379526bcbc +product_parent_urn=urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3 +product_parent=Java Platform Standard Edition 6 (Java SE 6) +product_defined_inst_id=id=1.6.0_06-b06 i386,dir=/w/mchung/bundles/jdk1.6.0_05/jre +product_vendor=Sun Microsystems +platform_arch=x86 +timestamp=2007-11-29 17:59:42 GMT +container=global +source=servicetag5.properties +installer_uid=-1 -- cgit v1.2.3 From ce4a9015d3fc73ee6da23097c59a6795ec329c16 Mon Sep 17 00:00:00 2001 From: jjh Date: Thu, 2 Oct 2008 18:23:23 -0700 Subject: 6751643: ThreadReference.ownedMonitors() can return null Summary: Make a local copy of the cache so it doesn't get modified by a racy resume Reviewed-by: dcubed, swamyv --- .../com/sun/tools/jdi/ThreadReferenceImpl.java | 114 +++++---- test/com/sun/jdi/SimulResumerTest.java | 278 +++++++++++++++++++++ 2 files changed, 350 insertions(+), 42 deletions(-) create mode 100644 test/com/sun/jdi/SimulResumerTest.java diff --git a/src/share/classes/com/sun/tools/jdi/ThreadReferenceImpl.java b/src/share/classes/com/sun/tools/jdi/ThreadReferenceImpl.java index 7af01561e..0f18120f1 100644 --- a/src/share/classes/com/sun/tools/jdi/ThreadReferenceImpl.java +++ b/src/share/classes/com/sun/tools/jdi/ThreadReferenceImpl.java @@ -61,7 +61,8 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl private ThreadGroupReference threadGroup; // This is cached only while this one thread is suspended. Each time - // the thread is resumed, we clear this and start with a fresh one. + // the thread is resumed, we abandon the current cache object and + // create a new intialized one. private static class LocalCache { JDWP.ThreadReference.Status status = null; List frames = null; @@ -74,6 +75,28 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl boolean triedCurrentContended = false; } + /* + * The localCache instance var is set by resetLocalCache to an initialized + * object as shown above. This occurs when the ThreadReference + * object is created, and when the mirrored thread is resumed. + * The fields are then filled in by the relevant methods as they + * are called. A problem can occur if resetLocalCache is called + * (ie, a resume() is executed) at certain points in the execution + * of some of these methods - see 6751643. To avoid this, each + * method that wants to use this cache must make a local copy of + * this variable and use that. This means that each invocation of + * these methods will use a copy of the cache object that was in + * effect at the point that the copy was made; if a racy resume + * occurs, it won't affect the method's local copy. This means that + * the values returned by these calls may not match the state of + * the debuggee at the time the caller gets the values. EG, + * frameCount() is called and comes up with 5 frames. But before + * it returns this, a resume of the debuggee thread is executed in a + * different debugger thread. The thread is resumed and running at + * the time that the value 5 is returned. Or even worse, the thread + * could be suspended again and have a different number of frames, eg, 24, + * but this call will still return 5. + */ private LocalCache localCache; private void resetLocalCache() { @@ -129,8 +152,9 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl } /** - * Note that we only cache the name string while suspended because - * it can change via Thread.setName arbitrarily + * Note that we only cache the name string while the entire VM is suspended + * because the name can change via Thread.setName arbitrarily while this + * thread is running. */ public String name() { String name = null; @@ -240,19 +264,20 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl } private JDWP.ThreadReference.Status jdwpStatus() { - JDWP.ThreadReference.Status myStatus = localCache.status; + LocalCache snapshot = localCache; + JDWP.ThreadReference.Status myStatus = snapshot.status; try { if (myStatus == null) { myStatus = JDWP.ThreadReference.Status.process(vm, this); if ((myStatus.suspendStatus & SUSPEND_STATUS_SUSPENDED) != 0) { // thread is suspended, we can cache the status. - localCache.status = myStatus; + snapshot.status = myStatus; } } } catch (JDWPException exc) { throw exc.toJDIException(); } - return myStatus; + return myStatus; } public int status() { @@ -304,9 +329,10 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl } public int frameCount() throws IncompatibleThreadStateException { + LocalCache snapshot = localCache; try { - if (localCache.frameCount == -1) { - localCache.frameCount = JDWP.ThreadReference.FrameCount + if (snapshot.frameCount == -1) { + snapshot.frameCount = JDWP.ThreadReference.FrameCount .process(vm, this).frameCount; } } catch (JDWPException exc) { @@ -318,7 +344,7 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl throw exc.toJDIException(); } } - return localCache.frameCount; + return snapshot.frameCount; } public List frames() throws IncompatibleThreadStateException { @@ -335,22 +361,22 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl * local is known to be non-null. Should only be called from * a sync method. */ - private boolean isSubrange(LocalCache localCache, + private boolean isSubrange(LocalCache snapshot, int start, int length) { - if (start < localCache.framesStart) { + if (start < snapshot.framesStart) { return false; } if (length == -1) { - return (localCache.framesLength == -1); + return (snapshot.framesLength == -1); } - if (localCache.framesLength == -1) { - if ((start + length) > (localCache.framesStart + - localCache.frames.size())) { + if (snapshot.framesLength == -1) { + if ((start + length) > (snapshot.framesStart + + snapshot.frames.size())) { throw new IndexOutOfBoundsException(); } return true; } - return ((start + length) <= (localCache.framesStart + localCache.framesLength)); + return ((start + length) <= (snapshot.framesStart + snapshot.framesLength)); } public List frames(int start, int length) @@ -371,14 +397,14 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl // Lock must be held while creating stack frames so if that two threads // do this at the same time, one won't clobber the subset created by the other. - + LocalCache snapshot = localCache; try { - if (localCache.frames == null || !isSubrange(localCache, start, length)) { + if (snapshot.frames == null || !isSubrange(snapshot, start, length)) { JDWP.ThreadReference.Frames.Frame[] jdwpFrames = JDWP.ThreadReference.Frames. process(vm, this, start, length).frames; int count = jdwpFrames.length; - localCache.frames = new ArrayList(count); + snapshot.frames = new ArrayList(count); for (int i = 0; i ownedMonitors() throws IncompatibleThreadStateException { + LocalCache snapshot = localCache; try { - if (localCache.ownedMonitors == null) { - localCache.ownedMonitors = Arrays.asList( + if (snapshot.ownedMonitors == null) { + snapshot.ownedMonitors = Arrays.asList( (ObjectReference[])JDWP.ThreadReference.OwnedMonitors. process(vm, this).owned); if ((vm.traceFlags & vm.TRACE_OBJREFS) != 0) { vm.printTrace(description() + " temporarily caching owned monitors"+ - " (count = " + localCache.ownedMonitors.size() + ")"); + " (count = " + snapshot.ownedMonitors.size() + ")"); } } } catch (JDWPException exc) { @@ -435,54 +462,57 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl throw exc.toJDIException(); } } - return localCache.ownedMonitors; + return snapshot.ownedMonitors; } public ObjectReference currentContendedMonitor() throws IncompatibleThreadStateException { + LocalCache snapshot = localCache; try { - if (localCache.contendedMonitor == null && - !localCache.triedCurrentContended) { - localCache.contendedMonitor = JDWP.ThreadReference.CurrentContendedMonitor. + if (snapshot.contendedMonitor == null && + !snapshot.triedCurrentContended) { + snapshot.contendedMonitor = JDWP.ThreadReference.CurrentContendedMonitor. process(vm, this).monitor; - localCache.triedCurrentContended = true; - if ((localCache.contendedMonitor != null) && + snapshot.triedCurrentContended = true; + if ((snapshot.contendedMonitor != null) && ((vm.traceFlags & vm.TRACE_OBJREFS) != 0)) { vm.printTrace(description() + " temporarily caching contended monitor"+ - " (id = " + localCache.contendedMonitor.uniqueID() + ")"); + " (id = " + snapshot.contendedMonitor.uniqueID() + ")"); } } } catch (JDWPException exc) { switch (exc.errorCode()) { + case JDWP.Error.THREAD_NOT_SUSPENDED: case JDWP.Error.INVALID_THREAD: /* zombie */ throw new IncompatibleThreadStateException(); default: throw exc.toJDIException(); } } - return localCache.contendedMonitor; + return snapshot.contendedMonitor; } public List ownedMonitorsAndFrames() throws IncompatibleThreadStateException { + LocalCache snapshot = localCache; try { - if (localCache.ownedMonitorsInfo == null) { + if (snapshot.ownedMonitorsInfo == null) { JDWP.ThreadReference.OwnedMonitorsStackDepthInfo.monitor[] minfo; minfo = JDWP.ThreadReference.OwnedMonitorsStackDepthInfo.process(vm, this).owned; - localCache.ownedMonitorsInfo = new ArrayList(minfo.length); + snapshot.ownedMonitorsInfo = new ArrayList(minfo.length); for (int i=0; i < minfo.length; i++) { JDWP.ThreadReference.OwnedMonitorsStackDepthInfo.monitor mi = minfo[i]; MonitorInfo mon = new MonitorInfoImpl(vm, minfo[i].monitor, this, minfo[i].stack_depth); - localCache.ownedMonitorsInfo.add(mon); + snapshot.ownedMonitorsInfo.add(mon); } if ((vm.traceFlags & vm.TRACE_OBJREFS) != 0) { vm.printTrace(description() + " temporarily caching owned monitors"+ - " (count = " + localCache.ownedMonitorsInfo.size() + ")"); + " (count = " + snapshot.ownedMonitorsInfo.size() + ")"); } } @@ -495,7 +525,7 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl throw exc.toJDIException(); } } - return localCache.ownedMonitorsInfo; + return snapshot.ownedMonitorsInfo; } public void popFrames(StackFrame frame) throws IncompatibleThreadStateException { diff --git a/test/com/sun/jdi/SimulResumerTest.java b/test/com/sun/jdi/SimulResumerTest.java new file mode 100644 index 000000000..cf7568e8b --- /dev/null +++ b/test/com/sun/jdi/SimulResumerTest.java @@ -0,0 +1,278 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6751643 + * @summary ThreadReference.ownedMonitors() can return null + * + * @author jjh + * + * @run build TestScaffold VMConnection TargetListener TargetAdapter + * @run compile -g SimulResumerTest.java + * @run main SimulResumerTest + */ +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; + +/* + * This debuggee basically runs two threads each of + * which loop, hitting a bkpt in each iteration. + * + */ +class SimulResumerTarg extends Thread { + static boolean one = false; + static String name1 = "Thread 1"; + static String name2 = "Thread 2"; + static int count = 10000; + public static void main(String[] args) { + System.out.println("Howdy!"); + SimulResumerTarg t1 = new SimulResumerTarg(name1); + SimulResumerTarg t2 = new SimulResumerTarg(name2); + + t1.start(); + t2.start(); + } + + public SimulResumerTarg(String name) { + super(name); + } + + public void run() { + if (getName().equals(name1)) { + run1(); + } else { + run2(); + } + } + + public void bkpt1(int i) { + synchronized(name1) { + yield(); + } + } + + public void run1() { + int i = 0; + while (i < count) { + i++; + bkpt1(i); + } + } + + public void bkpt2(int i) { + synchronized(name2) { + yield(); + } + } + + public void run2() { + int i = 0; + while (i < count) { + i++; + bkpt2(i); + } + } +} + +/********** test program **********/ + +public class SimulResumerTest extends TestScaffold { + ReferenceType targetClass; + ThreadReference mainThread; + BreakpointRequest request1; + BreakpointRequest request2; + static volatile int bkpts = 0; + static int iters = 0; + Thread resumerThread; + static int waitTime = 100; + ThreadReference debuggeeThread1 = null; + ThreadReference debuggeeThread2 = null; + + SimulResumerTest (String args[]) { + super(args); + } + + public static void main(String[] args) throws Exception { + new SimulResumerTest(args).startTests(); + } + + /* BreakpointEvent handler */ + + public void breakpointReached(BreakpointEvent event) { + // save ThreadRefs for the two debuggee threads + ThreadReference thr = event.thread(); + if (bkpts == 0) { + resumerThread.start(); + debuggeeThread1 = thr; + System.out.println("thr1 = " + debuggeeThread1); + } + + if (debuggeeThread2 == null && thr != debuggeeThread1) { + debuggeeThread2 = thr; + System.out.println("thr2 = " + debuggeeThread2); + } + + synchronized("abc") { + bkpts++; + } + /** + if (bkpts >= SimulResumerTarg.count * 2) { + resumerThread.interrupt(); + } + *****/ + + } + + /********** test core **********/ + + void check(ThreadReference thr) { + // This calls each ThreadReference method that could fail due to the bug + // that occurs if a resume is done while a call to the method is in process. + String kind = ""; + if (thr != null) { + try { + kind = "ownedMonitors()"; + System.out.println("kind = " + kind); + if (thr.ownedMonitors() == null) { + failure("failure: ownedMonitors = null"); + } + + kind = "ownedMonitorsAndFrames()"; + System.out.println("kind = " + kind); + if (thr.ownedMonitorsAndFrames() == null) { + failure("failure: ownedMonitorsAndFrames = null"); + } + + kind = "currentContendedMonitor()"; + System.out.println("kind = " + kind); + thr.currentContendedMonitor(); + // no failure return value here; could cause an NPE + + kind = "frames()"; + System.out.println("kind = " + kind); + List frames = thr.frames(); + // no failure return value here; could cause an NPE + + int nframes = frames.size(); + if (nframes > 0) { + // hmm, how could it ever be 0? + kind = "frames(0, size - 1)"; + System.out.println("kind = " + kind); + thr.frames(0, frames.size() - 1); + } + + kind = "frameCount()"; + System.out.println("kind = " + kind); + if (thr.frameCount() == -1) { + failure("failure: frameCount = -1"); + } + + kind = "name()"; + System.out.println("kind = " + kind); + if (thr.name() == null) { + failure("failure: name = null"); + } + + kind = "status()"; + System.out.println("kind = " + kind); + if (thr.status() < 0) { + failure("failure: status < 0"); + } + + } catch (IncompatibleThreadStateException ee) { + // ignore + } catch (VMDisconnectedException ee) { + // This is how we stop. The debuggee runs to completion + // and we get this exception. + throw ee; + } catch (Exception ee) { + failure("failure: Got exception from " + kind + ": " + ee ); + } + } + } + + protected void runTests() throws Exception { + /* + * Get to the top of main() + * to determine targetClass and mainThread + */ + BreakpointEvent bpe = startToMain("SimulResumerTarg"); + targetClass = bpe.location().declaringType(); + mainThread = bpe.thread(); + EventRequestManager erm = vm().eventRequestManager(); + final Thread mainThread = Thread.currentThread(); + + /* + * Set event requests + */ + Location loc1 = findMethod(targetClass, "bkpt1", "(I)V").location(); + Location loc2 = findMethod(targetClass, "bkpt2", "(I)V").location(); + request1 = erm.createBreakpointRequest(loc1); + request2 = erm.createBreakpointRequest(loc2); + request1.enable(); + request2.enable(); + + /* + * This thread will be started when we get the first bkpt. + */ + resumerThread = new Thread("test resumer") { + public void run() { + while (true) { + iters++; + System.out.println("bkpts = " + bkpts + ", iters = " + iters); + try { + Thread.sleep(waitTime); + check(debuggeeThread1); + check(debuggeeThread2); + } catch (InterruptedException ee) { + // If the test completes, this occurs. + println("resumer Interrupted"); + break; + } catch (VMDisconnectedException ee) { + println("VMDisconnectedException"); + break; + } + } + } + }; + + /* + * resume the target, listening for events + */ + listenUntilVMDisconnect(); + resumerThread.interrupt(); + /* + * deal with results of test + * if anything has called failure("foo") testFailed will be true + */ + if (!testFailed) { + println("SimulResumerTest: passed; bkpts = " + bkpts + ", iters = " + iters); + } else { + throw new Exception("SimulResumerTest: failed; bkpts = " + bkpts + ", iters = " + iters); + } + } +} -- cgit v1.2.3 From 030ef2c637ac58c8d792ab47b4c4e12033a45465 Mon Sep 17 00:00:00 2001 From: ksrini Date: Wed, 1 Oct 2008 09:04:42 -0700 Subject: 4459600: java -jar fails to run Main-Class if classname followed by whitespace. Summary: Fixed whitespace trimming in the manifest as well as post review comments on CR: 6742159 Reviewed-by: darcy, dholmes --- src/share/classes/sun/launcher/LauncherHelper.java | 15 ++++----------- test/tools/launcher/Arrrghs.java | 18 +++++++++++++----- test/tools/launcher/TestHelper.java | 21 ++++++++++----------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/share/classes/sun/launcher/LauncherHelper.java b/src/share/classes/sun/launcher/LauncherHelper.java index 96ad48446..8cca710da 100644 --- a/src/share/classes/sun/launcher/LauncherHelper.java +++ b/src/share/classes/sun/launcher/LauncherHelper.java @@ -151,7 +151,7 @@ public enum LauncherHelper { throw new IOException("no main mainifest attributes, in " + jarname); } - return mainAttrs.getValue(MAIN_CLASS); + return mainAttrs.getValue(MAIN_CLASS).trim(); } finally { if (jarFile != null) { jarFile.close(); @@ -207,10 +207,9 @@ public enum LauncherHelper { throw new RuntimeException("Main method not found in " + classname); } /* - * Usually the getMethod (above) will choose the correct method, based - * on its modifiers and parameter types, the only check required is the - * getReturnType check as getMethod does not check for this, all the - * other modifier tests are redundant, and are simply here for safety. + * getMethod (above) will choose the correct method, based + * on its name and parameter type, however, we still have to + * ensure that the method is static and returns a void. */ int mod = method.getModifiers(); if (!Modifier.isStatic(mod)) { @@ -219,12 +218,6 @@ public enum LauncherHelper { throw new RuntimeException("Main method is not static in class " + classname); } - if (!Modifier.isPublic(mod)) { - ostream.println(getLocalizedMessage("java.launcher.cls.error2", - "public", classname)); - throw new RuntimeException("Main method is not public in class " + - classname); - } Class rType = method.getReturnType(); if (!rType.isPrimitive() || !rType.getName().equals("void")) { ostream.println(getLocalizedMessage("java.launcher.cls.error3", diff --git a/test/tools/launcher/Arrrghs.java b/test/tools/launcher/Arrrghs.java index 6b14abe50..df9e993a1 100644 --- a/test/tools/launcher/Arrrghs.java +++ b/test/tools/launcher/Arrrghs.java @@ -24,7 +24,7 @@ /** * @test * @compile -XDignore.symbol.file Arrrghs.java TestHelper.java - * @bug 5030233 6214916 6356475 6571029 6684582 + * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 * @run main Arrrghs * @summary Argument parsing validation. */ @@ -232,7 +232,8 @@ public class Arrrghs { TestHelper.TestResult tr = null; // a missing class - TestHelper.createJar(new File("some.jar"), new File("Foo"), (String[])null); + TestHelper.createJar("MIA", new File("some.jar"), new File("Foo"), + (String[])null); tr = TestHelper.doExec(TestHelper.javaCmd, "-jar", "some.jar"); tr.contains("MIA"); System.out.println(tr); @@ -276,13 +277,13 @@ public class Arrrghs { // incorrect method type - non-static TestHelper.createJar(new File("some.jar"), new File("Foo"), - "public void main(Object[] args){}"); + "public void main(String[] args){}"); tr = TestHelper.doExec(TestHelper.javaCmd, "-jar", "some.jar"); - tr.contains("Error: Main method not found in class Foo"); + tr.contains("Error: Main method is not static in class Foo"); System.out.println(tr); // use classpath to check tr = TestHelper.doExec(TestHelper.javaCmd, "-cp", "some.jar", "Foo"); - tr.contains("Error: Main method not found in class Foo"); + tr.contains("Error: Main method is not static in class Foo"); System.out.println(tr); // amongst a potpourri of kindred main methods, is the right one chosen ? @@ -300,6 +301,13 @@ public class Arrrghs { tr = TestHelper.doExec(TestHelper.javaCmd, "-cp", "some.jar", "Foo"); tr.contains("THE_CHOSEN_ONE"); System.out.println(tr); + + // test for extraneous whitespace in the Main-Class attribute + TestHelper.createJar(" Foo ", new File("some.jar"), new File("Foo"), + "public static void main(String... args){}"); + tr = TestHelper.doExec(TestHelper.javaCmd, "-jar", "some.jar"); + tr.checkPositive(); + System.out.println(tr); } /** diff --git a/test/tools/launcher/TestHelper.java b/test/tools/launcher/TestHelper.java index bd9009dc5..fb63114b6 100644 --- a/test/tools/launcher/TestHelper.java +++ b/test/tools/launcher/TestHelper.java @@ -72,8 +72,8 @@ public enum TestHelper { } /* - * A generic jar file creator which creates the java file, compiles it - * and jar's it up for use. + * A convenience method to create a java file, compile and jar it up, using + * the sole class file name in the jar, as the Main-Class attribute value. */ static void createJar(File jarName, File mainClass, String... mainDefs) throws FileNotFoundException { @@ -81,11 +81,13 @@ public enum TestHelper { } /* - * A method which takes manifest entry to specify a specific manifest - * Main-Class name. + * A generic jar file creator to create a java file, compile it + * and jar it up, a specific Main-Class entry name in the + * manifest can be specified or a null to use the sole class file name + * as the Main-Class attribute value. */ - static void createJar(String mEntry, File jarName, File mainClass, String... mainDefs) - throws FileNotFoundException { + static void createJar(String mEntry, File jarName, File mainClass, + String... mainDefs) throws FileNotFoundException { if (jarName.exists()) { jarName.delete(); } @@ -105,10 +107,7 @@ public enum TestHelper { if (compiler.run(null, null, null, compileArgs) != 0) { throw new RuntimeException("compilation failed " + mainClass + ".java"); } - - if (mEntry == null && mainDefs == null) { - mEntry = "MIA"; - } else { + if (mEntry == null) { mEntry = mainClass.getName(); } String jarArgs[] = { @@ -125,7 +124,7 @@ public enum TestHelper { } /* - * A method which executes a java cmd and returs the results in a container + * A method which executes a java cmd and returns the results in a container */ static TestResult doExec(String...cmds) { String cmdStr = ""; -- cgit v1.2.3