/* * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.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 <tt>/usr/share/lib/xml/dtd/servicetag.dtd</tt>. * <p> * A valid {@code ServiceTag} instance must comply to the service tag schema * and contain the following fields: * <ul> * <li>{@link #getInstanceURN <tt>instance_urn</tt>}</li> * <li>{@link #getProductName <tt>product_name</tt>}</li> * <li>{@link #getProductVersion <tt>product_version</tt>}</li> * <li>{@link #getProductURN <tt>product_urn</tt>}</li> * <li>{@link #getProductParent <tt>product_parent</tt>}</li> * <li>{@link #getProductParentURN <tt>product_parent_urn</tt>}</li> * <li>{@link #getProductDefinedInstanceID <tt>product_defined_inst_id</tt>}</li> * <li>{@link #getProductVendor <tt>product_vendor</tt>}</li> * <li>{@link #getPlatformArch <tt>platform_arch</tt>}</li> * <li>{@link #getContainer <tt>container</tt>}</li> * <li>{@link #getSource <tt>source</tt>}</li> * <li>{@link #getInstallerUID <tt>installer_uid</tt>}</li> * <li>{@link #getTimestamp <tt>timestamp</tt>}</li> * </ul> * * The <tt>instance_urn</tt> 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 <tt>installer_uid</tt> and * <tt>timestamp</tt> are set when a {@code ServiceTag} object * is added to a {@link RegistrationData} object, or {@link Registry * system service tag registry}. * * @see <a href="https://sunconnection.sun.com/FAQ/sc_faq.html">Service Tags FAQ</a> */ 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 <tt>instance_urn</tt>. * * @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 <tt>instance_urn</tt>. * * @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: * <blockquote> * "<tt>urn:st:<32-char {@link java.util.UUID uuid}></tt>" * </blockquote> * @return a URN. */ public static String generateInstanceURN() { return Util.generateURN(); } /** * Returns the uniform resource name of this service tag instance. * * @return the <tt>instance_urn</tt> 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 * <tt>instance_urn</tt> is the same as the * <tt>instance_urn</tt> 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. * <p> * 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, * <blockquote> * <tt>NetBeans IDE 6.0 with JDK 6 Update 5 Bundle</tt> * </blockquote> * in a NetBeans/JDK bundle. * <p> * 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); } }