blob: 99f5623d14597a585ddee94507bdb24220814038 [file] [log] [blame]
/*
* 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.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.
* <a name="EnvMap"></a>
* It also has an <i>environment map</i> with
* the following elements:
* <blockquote>
* <table border=0>
* <tr>
* <td><tt>hostname</tt></td>
* <td>Hostname of the system</td>
* <td>e.g. woody</td>
* </tr>
* <tr>
* <td><tt>hostId</tt></td>
* <td>Host ID of the system</td>
* <td>e.g. 83abc1ab</td>
* </tr>
* <tr>
* <td><tt>osName</tt></td>
* <td>Operating system name</td>
* <td> e.g. SunOS</td>
* </tr>
* <tr>
* <td><tt>osVersion</tt></td>
* <td>Operating system version</td>
* <td> e.g. 5.10</td>
* </tr>
* <tr>
* <td><tt>osArchitecture</tt></td>
* <td>Operating system architecture</td>
* <td> e.g. sparc</td>
* </tr>
* <tr>
* <td><tt>systemModel</tt></td>
* <td>System model</td>
* <td> e.g. SUNW,Sun-Fire-V440</td>
* </tr>
* <tr>
* <td><tt>systemManufacturer</tt></td>
* <td>System manufacturer</td>
* <td> e.g. Sun Microsystems</td>
* </tr>
* <tr>
* <td><tt>cpuManufacturer</tt></td>
* <td>CPU manufacturer</td>
* <td> e.g. Sun Microsystems</td>
* </tr>
* <tr>
* <td><tt>serialNumber</tt></td>
* <td>System serial number</td>
* <td> e.g. BEL078932</td>
* </tr>
* </table>
* </blockquote>
* The <tt>hostname</tt> and <tt>osName</tt> element must have a non-empty value.
* If an element is not available on a system and their value will be
* empty.
* <p>
* <a name="XMLSchema">
* <b>Registration XML Schema</b></a>
* <p>
* A {@code RegistrationData} object can be {@link #loadFromXML loaded} from
* and {@link #storeToXML stored} into an XML file in the format described
* by the
* <a href="https://sn-tools.central.sun.com/twiki/pub/ServiceTags/RegistrationRelayService/product_registration.xsd">
* registration data schema</a>. The registration data schema is defined by the
* Service Tags Technology.
* <p>
* Typically the registration data is constructed at installation time
* and stored in an XML file for later service tag lookup or registration.
*
* <p>
* <b>Example Usage</b>
* <p>
* The examples below show how the {@code RegistrationData} can be
* used for product registration.
* Exception handling is not shown in these examples for clarity.
* <ol>
* <li>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.
* <br>
* <blockquote><pre>
* // 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);
* </pre></blockquote>
* </li>
* <li>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 <i>Registration Relay Service</i>.
* <p>
* There are several registration services for Sun Connection. For example,
* the <a href="https://sn-tools.central.sun.com/twiki/bin/view/ServiceTags/RegistrationRelayService">
* Registration Relay Service</a> 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.
* <p>
* <blockquote><pre>
* // 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();
* </pre></blockquote>
* </li>
* <li>This example shows how to store the registration data in an XML file.
* for later service tag lookup or registration.
* <br>
* <blockquote><pre>
* BufferedOutputStream out = new BufferedOutputStream(
* new FileOutputStream(""&lt;JAVA_HOME&gt;/lib/servicetag/registration.xml"));
* registration.storeToXML(out);
* out.close();
* </pre></blockquote>
* </li>
* <li>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.
* <br>
* <blockquote><pre>
* if (Registry.isSupported()) {
* Set&lt;ServiceTag&gt; svctags = registration.getServiceTags();
* for (ServiceTag st : svctags) {
* Registry.getSystemRegistry().addServiceTag(st);
* }
* }
* </pre></blockquote>
* </li>
* </ol>
*
* @see <a href="https://sunconnection.sun.com/inventory">Sun Connection Inventory Channel</a>
*/
public class RegistrationData {
private final Map<String, String> environment = initEnvironment();
private final Map<String, ServiceTag> svcTagMap =
new LinkedHashMap<String, ServiceTag>();
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:
* <blockquote>
* <tt>hostname</tt>, <tt>osName</tt>, <tt>osVersion</tt> and
* <tt>osArchitecture</tt>
* </blockquote>
* 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<String, String> initEnvironment() {
Map<String, String> map = new LinkedHashMap<String, String>();
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:
* <tt>urn:st:&lt;32-char {@link java.util.UUID uuid}&gt;</tt>
*
* @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 <a href="#EnvMap">keys</a>
* 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<String, String> getEnvironmentMap() {
return new LinkedHashMap<String,String>(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<ServiceTag> getServiceTags() {
return new HashSet<ServiceTag>(svcTagMap.values());
}
/**
* Adds a service tag to this registration data.
* If the given service tag has an empty <tt>instance_urn</tt>,
* 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
* <tt>instance_urn</tt>} 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 <tt>instance_urn</tt> in this registration
* data.
*
* @param instanceURN the <tt>instance_urn</tt> of the service tag
* @return the {@code ServiceTag} object of the given <tt>instance_urn</tt>
* 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 <tt>instance_urn</tt> from this
* registration data.
*
* @param instanceURN the <tt>instance_urn</tt> 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 <tt>product_defined_instance_id</tt> in the service tag
* of the given <tt>instance_urn</tt> in this registration data.
*
* @param instanceURN the <tt>instance_urn</tt> of the service tag to be updated.
* @param productDefinedInstanceID the value of the
* <tt>product_defined_instance_id</tt> 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 <a href="#XMLSchema">
* registration data schema</a>.
* 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 <a href="#XMLSchema">
* registration data schema</a> 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.";
}
}
}