jdk/src/share/classes/com/sun/servicetag/RegistrationData.java
changeset 16761 ba1a9ec11f5a
parent 16760 d3a094bca83f
parent 16575 d7ad0dfaa411
child 16762 61af58122ded
equal deleted inserted replaced
16760:d3a094bca83f 16761:ba1a9ec11f5a
     1 /*
       
     2  * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package com.sun.servicetag;
       
    27 
       
    28 import java.io.*;
       
    29 import java.net.UnknownHostException;
       
    30 import java.util.Collection;
       
    31 import java.util.Collections;
       
    32 import java.util.HashSet;
       
    33 import java.util.LinkedHashMap;
       
    34 import java.util.Map;
       
    35 import java.util.Set;
       
    36 
       
    37 import static com.sun.servicetag.RegistrationDocument.*;
       
    38 
       
    39 /**
       
    40  * A {@code RegistrationData} object is a container of one or more
       
    41  * {@link #getServiceTags service tags} that identify the
       
    42  * components for product registration.
       
    43  * Each {@code RegistrationData} object has a {@link #getRegistrationURN
       
    44  * uniform resource name} (URN) as its identifier.
       
    45  * <a name="EnvMap"></a>
       
    46  * It also has an <i>environment map</i> with
       
    47  * the following elements:
       
    48  * <blockquote>
       
    49  *       <table border=0>
       
    50  *       <tr>
       
    51  *          <td><tt>hostname</tt></td>
       
    52  *          <td>Hostname of the system</td>
       
    53  *          <td>e.g. woody</td>
       
    54  *       </tr>
       
    55  *       <tr>
       
    56  *          <td><tt>hostId</tt></td>
       
    57  *          <td>Host ID of the system</td>
       
    58  *          <td>e.g. 83abc1ab</td>
       
    59  *       </tr>
       
    60  *       <tr>
       
    61  *          <td><tt>osName</tt></td>
       
    62  *          <td>Operating system name</td>
       
    63  *          <td> e.g. SunOS</td>
       
    64  *       </tr>
       
    65  *       <tr>
       
    66  *          <td><tt>osVersion</tt></td>
       
    67  *          <td>Operating system version</td>
       
    68  *          <td> e.g. 5.10</td>
       
    69  *       </tr>
       
    70  *       <tr>
       
    71  *          <td><tt>osArchitecture</tt></td>
       
    72  *          <td>Operating system architecture</td>
       
    73  *          <td> e.g. sparc</td>
       
    74  *       </tr>
       
    75  *       <tr>
       
    76  *          <td><tt>systemModel</tt></td>
       
    77  *          <td>System model</td>
       
    78  *          <td> e.g. SUNW,Sun-Fire-V440</td>
       
    79  *       </tr>
       
    80  *       <tr>
       
    81  *          <td><tt>systemManufacturer</tt></td>
       
    82  *          <td>System manufacturer</td>
       
    83  *          <td> e.g. Oracle Corporation</td>
       
    84  *       </tr>
       
    85  *       <tr>
       
    86  *          <td><tt>cpuManufacturer</tt></td>
       
    87  *          <td>CPU manufacturer</td>
       
    88  *          <td> e.g. Oracle Corporation</td>
       
    89  *       </tr>
       
    90  *       <tr>
       
    91  *          <td><tt>serialNumber</tt></td>
       
    92  *          <td>System serial number</td>
       
    93  *          <td> e.g. BEL078932</td>
       
    94  *       </tr>
       
    95  *       </table>
       
    96  *  </blockquote>
       
    97  * The <tt>hostname</tt> and <tt>osName</tt> element must have a non-empty value.
       
    98  * If an element is not available on a system and their value will be
       
    99  * empty.
       
   100  * <p>
       
   101  * <a name="XMLSchema">
       
   102  * <b>Registration XML Schema</b></a>
       
   103  * <p>
       
   104  * A {@code RegistrationData} object can be {@link #loadFromXML loaded} from
       
   105  * and {@link #storeToXML stored} into an XML file in the format described
       
   106  * by the
       
   107  * <a href="https://sn-tools.central.sun.com/twiki/pub/ServiceTags/RegistrationRelayService/product_registration.xsd">
       
   108  * registration data schema</a>.  The registration data schema is defined by the
       
   109  * Service Tags Technology.
       
   110  * <p>
       
   111  * Typically the registration data is constructed at installation time
       
   112  * and stored in an XML file for later service tag lookup or registration.
       
   113  *
       
   114  * <p>
       
   115  * <b>Example Usage</b>
       
   116  * <p>
       
   117  * The examples below show how the {@code RegistrationData} can be
       
   118  * used for product registration.
       
   119  * Exception handling is not shown in these examples for clarity.
       
   120  * <ol>
       
   121  * <li>This example shows how the JDK creates a JDK service tag, installs it
       
   122  * in the system service tag registry and adds it to the registration data.
       
   123  * <br>
       
   124  * <blockquote><pre>
       
   125  *   // create a service tag object with an instance_urn
       
   126  *   ServiceTag st = ServiceTag.newInstance(ServiceTag.generateInstanceURN(),
       
   127  *                                          ....);
       
   128  *   // Adds to the system service tag registry if supported
       
   129  *   if (Registry.isSupported()) {
       
   130  *       Registry.getSystemRegistry().addServiceTag(st);
       
   131  *   }
       
   132  *
       
   133  *   // add to the registration data
       
   134  *   RegistrationData registration  = new RegistrationData();
       
   135  *   registration.addServiceTag(st);
       
   136  * </pre></blockquote>
       
   137  * </li>
       
   138  * <li>At this point, the registration data is ready to
       
   139  * send to Sun Connection for registration. This example shows how to register
       
   140  * the JDK via the <i>Registration Relay Service</i>.
       
   141  * <p>
       
   142  * There are several registration services for Sun Connection. For example,
       
   143  * the <a href="https://sn-tools.central.sun.com/twiki/bin/view/ServiceTags/RegistrationRelayService">
       
   144  * Registration Relay Service</a> is a web application interface that
       
   145  * processes the registration data payload sent via HTTP post
       
   146  * and hosts the registration user interface for a specified
       
   147  * registration URL.  Refer to the
       
   148  * Registration Relay Service Specification for details.
       
   149  * <p>
       
   150  * <blockquote><pre>
       
   151  *   // Open the connection to the URL of the registration service
       
   152  *   HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
       
   153  *   con.setDoInput(true);
       
   154  *   con.setDoOutput(true);
       
   155  *   con.setUseCaches(false);
       
   156  *   con.setAllowUserInteraction(false);
       
   157  *   con.setRequestMethod("POST");
       
   158  *   con.setRequestProperty("Content-Type", "text/xml;charset=\"utf-8\"");
       
   159  *   con.connect();
       
   160  *
       
   161  *   // send the registration data to the registration service
       
   162  *   OutputStream out = con.getOutputStream();
       
   163  *   registration.storeToXML(out);
       
   164  *   out.close();
       
   165  * </pre></blockquote>
       
   166  * </li>
       
   167  * <li>This example shows how to store the registration data in an XML file.
       
   168  *     for later service tag lookup or registration.
       
   169  * <br>
       
   170  * <blockquote><pre>
       
   171  *   BufferedOutputStream out = new BufferedOutputStream(
       
   172  *       new FileOutputStream(""&lt;JAVA_HOME&gt;/lib/servicetag/registration.xml"));
       
   173  *   registration.storeToXML(out);
       
   174  *   out.close();
       
   175  * </pre></blockquote>
       
   176  * </li>
       
   177  * <li>This example shows how to install service tags that are in the
       
   178  * registration data in the system service tag registry when determined
       
   179  * to be available.  The system service tag registry might not have existed
       
   180  * when the registration data was constructed.
       
   181  * <br>
       
   182  * <blockquote><pre>
       
   183  *   if (Registry.isSupported()) {
       
   184  *       Set&lt;ServiceTag&gt; svctags = registration.getServiceTags();
       
   185  *       for (ServiceTag st : svctags) {
       
   186  *           Registry.getSystemRegistry().addServiceTag(st);
       
   187  *       }
       
   188  *   }
       
   189  * </pre></blockquote>
       
   190  * </li>
       
   191  * </ol>
       
   192  *
       
   193  * @see <a href="https://sunconnection.sun.com/inventory">Sun Connection Inventory Channel</a>
       
   194  */
       
   195 public class RegistrationData {
       
   196     private final Map<String, String> environment = initEnvironment();
       
   197     private final Map<String, ServiceTag> svcTagMap =
       
   198         new LinkedHashMap<String, ServiceTag>();
       
   199     private final String urn;
       
   200 
       
   201     /**
       
   202      * Creates a {@code RegistrationData} object with a generated
       
   203      * {@link #getRegistrationURN registration URN}.
       
   204      * The following keys in the {@link #getEnvironmentMap environment map}
       
   205      * will be initialized for the configuration of the
       
   206      * running system:
       
   207      * <blockquote>
       
   208      * <tt>hostname</tt>, <tt>osName</tt>,  <tt>osVersion</tt> and
       
   209      * <tt>osArchitecture</tt>
       
   210      * </blockquote>
       
   211      * and the value of other keys may be empty.
       
   212      */
       
   213     public RegistrationData() {
       
   214         this(Util.generateURN());
       
   215         SystemEnvironment sysEnv = SystemEnvironment.getSystemEnvironment();
       
   216         setEnvironment(ST_NODE_HOSTNAME, sysEnv.getHostname());
       
   217         setEnvironment(ST_NODE_HOST_ID, sysEnv.getHostId());
       
   218         setEnvironment(ST_NODE_OS_NAME, sysEnv.getOsName());
       
   219         setEnvironment(ST_NODE_OS_VERSION, sysEnv.getOsVersion());
       
   220         setEnvironment(ST_NODE_OS_ARCH, sysEnv.getOsArchitecture());
       
   221         setEnvironment(ST_NODE_SYSTEM_MODEL, sysEnv.getSystemModel());
       
   222         setEnvironment(ST_NODE_SYSTEM_MANUFACTURER, sysEnv.getSystemManufacturer());
       
   223         setEnvironment(ST_NODE_CPU_MANUFACTURER, sysEnv.getCpuManufacturer());
       
   224         setEnvironment(ST_NODE_SERIAL_NUMBER, sysEnv.getSerialNumber());
       
   225     }
       
   226 
       
   227     // package private
       
   228     RegistrationData(String urn) {
       
   229         this.urn = urn;
       
   230     }
       
   231 
       
   232     private Map<String, String> initEnvironment() {
       
   233         Map<String, String> map = new LinkedHashMap<String, String>();
       
   234         map.put(ST_NODE_HOSTNAME, "");
       
   235         map.put(ST_NODE_HOST_ID, "");
       
   236         map.put(ST_NODE_OS_NAME, "");
       
   237         map.put(ST_NODE_OS_VERSION, "");
       
   238         map.put(ST_NODE_OS_ARCH, "");
       
   239         map.put(ST_NODE_SYSTEM_MODEL, "");
       
   240         map.put(ST_NODE_SYSTEM_MANUFACTURER, "");
       
   241         map.put(ST_NODE_CPU_MANUFACTURER, "");
       
   242         map.put(ST_NODE_SERIAL_NUMBER, "");
       
   243         return map;
       
   244     }
       
   245 
       
   246     /**
       
   247      * Returns the uniform resource name of this registration data
       
   248      * in this format:
       
   249      * <tt>urn:st:&lt;32-char {@link java.util.UUID uuid}&gt;</tt>
       
   250      *
       
   251      * @return the URN of this registration data.
       
   252      */
       
   253     public String getRegistrationURN() {
       
   254         return urn;
       
   255     }
       
   256 
       
   257     /**
       
   258      * Returns a map containing the environment information for this
       
   259      * registration data.  See the set of <a href="#EnvMap">keys</a>
       
   260      * in the environment map. Subsequent update to the environment
       
   261      * map via the {@link #setEnvironment setEnvironment} method will not be reflected
       
   262      * in the returned map.
       
   263      *
       
   264      * @return an environment map for this registration data.
       
   265      */
       
   266     public Map<String, String> getEnvironmentMap() {
       
   267         return new LinkedHashMap<String,String>(environment);
       
   268     }
       
   269 
       
   270     /**
       
   271      * Sets an element of the specified {@code name} in the environment map
       
   272      * with the given {@code value}.
       
   273      *
       
   274      * @throws IllegalArgumentException if {@code name} is not a valid key
       
   275      * in the environment map, or {@code value} is not valid.
       
   276      */
       
   277     public void setEnvironment(String name, String value) {
       
   278         if (name == null) {
       
   279             throw new NullPointerException("name is null");
       
   280         }
       
   281         if (value == null) {
       
   282             throw new NullPointerException("value is null");
       
   283         }
       
   284         if (environment.containsKey(name)) {
       
   285             if (name.equals(ST_NODE_HOSTNAME) || name.equals(ST_NODE_OS_NAME)) {
       
   286                 if (value.length() == 0) {
       
   287                     throw new IllegalArgumentException("\"" +
       
   288                         name + "\" requires non-empty value.");
       
   289                 }
       
   290             }
       
   291             environment.put(name, value);
       
   292         } else {
       
   293             throw new IllegalArgumentException("\"" +
       
   294                  name + "\" is not an environment element.");
       
   295         }
       
   296     }
       
   297 
       
   298     /**
       
   299      * Returns all service tags in this registration data.
       
   300      *
       
   301      * @return  a {@link Set Set} of the service tags
       
   302      * in this registration data.
       
   303      */
       
   304     public Set<ServiceTag> getServiceTags() {
       
   305         return new HashSet<ServiceTag>(svcTagMap.values());
       
   306     }
       
   307 
       
   308     /**
       
   309      * Adds a service tag to this registration data.
       
   310      * If the given service tag has an empty <tt>instance_urn</tt>,
       
   311      * this method will generate a URN and place it in the copy
       
   312      * of the service tag in this registration data.
       
   313      * This method will return the {@code ServiceTag} object
       
   314      * added to this registration data.
       
   315      *
       
   316      * @param st {@code ServiceTag} object to be added.
       
   317      * @return a {@code ServiceTag} object added to this registration data.
       
   318      *
       
   319      * @throws IllegalArgumentException if
       
   320      *   a service tag of the same {@link ServiceTag#getInstanceURN
       
   321      *   <tt>instance_urn</tt>} already exists in the registry.
       
   322      */
       
   323     public synchronized ServiceTag addServiceTag(ServiceTag st) {
       
   324         ServiceTag svcTag = ServiceTag.newInstanceWithUrnTimestamp(st);
       
   325 
       
   326         String instanceURN = svcTag.getInstanceURN();
       
   327         if (svcTagMap.containsKey(instanceURN)) {
       
   328             throw new IllegalArgumentException("Instance_urn = " + instanceURN +
       
   329                     " already exists in the registration data.");
       
   330         } else {
       
   331             svcTagMap.put(instanceURN, svcTag);
       
   332         }
       
   333         return svcTag;
       
   334     }
       
   335 
       
   336     /**
       
   337      * Returns a service tag of the given <tt>instance_urn</tt> in this registration
       
   338      * data.
       
   339      *
       
   340      * @param instanceURN the <tt>instance_urn</tt> of the service tag
       
   341      * @return the {@code ServiceTag} object of the given  <tt>instance_urn</tt>
       
   342      *         if exists; otherwise return {@code null}.
       
   343      */
       
   344     public synchronized ServiceTag getServiceTag(String instanceURN) {
       
   345         if (instanceURN == null) {
       
   346             throw new NullPointerException("instanceURN is null");
       
   347         }
       
   348         return svcTagMap.get(instanceURN);
       
   349     }
       
   350 
       
   351     /**
       
   352      * Removes a service tag of the given <tt>instance_urn</tt> from this
       
   353      * registration data.
       
   354      *
       
   355      * @param instanceURN the <tt>instance_urn</tt> of
       
   356      * the service tag to be removed.
       
   357      *
       
   358      * @return the removed {@code ServiceTag} object;
       
   359      * or {@code null} if the service tag does not exist in this
       
   360      * registration data.
       
   361      */
       
   362     public synchronized ServiceTag removeServiceTag(String instanceURN) {
       
   363         if (instanceURN == null) {
       
   364             throw new NullPointerException("instanceURN is null");
       
   365         }
       
   366 
       
   367         ServiceTag svcTag = null;
       
   368         if (svcTagMap.containsKey(instanceURN)) {
       
   369             svcTag = svcTagMap.remove(instanceURN);
       
   370         }
       
   371         return svcTag;
       
   372     }
       
   373 
       
   374      /**
       
   375      * Updates the <tt>product_defined_instance_id</tt> in the service tag
       
   376      * of the given <tt>instance_urn</tt> in this registration data.
       
   377      *
       
   378      * @param instanceURN the <tt>instance_urn</tt> of the service tag to be updated.
       
   379      * @param productDefinedInstanceID the value of the
       
   380      * <tt>product_defined_instance_id</tt> to be set.
       
   381      *
       
   382      * @return the updated {@code ServiceTag} object;
       
   383      * or {@code null} if the service tag does not exist in this
       
   384      * registration data.
       
   385      */
       
   386     public synchronized ServiceTag updateServiceTag(String instanceURN,
       
   387                                                     String productDefinedInstanceID) {
       
   388         ServiceTag svcTag = getServiceTag(instanceURN);
       
   389         if (svcTag == null) {
       
   390             return null;
       
   391         }
       
   392 
       
   393         svcTag = ServiceTag.newInstanceWithUrnTimestamp(svcTag);
       
   394         // update the product defined instance ID field
       
   395         svcTag.setProductDefinedInstanceID(productDefinedInstanceID);
       
   396         svcTagMap.put(instanceURN, svcTag);
       
   397         return svcTag;
       
   398     }
       
   399 
       
   400     /**
       
   401      * Reads the registration data from the XML document on the
       
   402      * specified input stream.  The XML document must be
       
   403      * in the format described by the <a href="#XMLSchema">
       
   404      * registration data schema</a>.
       
   405      * The specified stream is closed after this method returns.
       
   406      *
       
   407      * @param in the input stream from which to read the XML document.
       
   408      * @return a {@code RegistrationData} object read from the input
       
   409      * stream.
       
   410      *
       
   411      * @throws IllegalArgumentException if the input stream
       
   412      * contains an invalid registration data.
       
   413      *
       
   414      * @throws IOException if an error occurred when reading from the input stream.
       
   415      */
       
   416     public static RegistrationData loadFromXML(InputStream in) throws IOException {
       
   417         try {
       
   418             return RegistrationDocument.load(in);
       
   419         } finally {
       
   420             in.close();
       
   421         }
       
   422     }
       
   423 
       
   424     /**
       
   425      * Writes the registration data to the specified output stream
       
   426      * in the format described by the <a href="#XMLSchema">
       
   427      * registration data schema</a> with "UTF-8" encoding.
       
   428      * The specified stream remains open after this method returns.
       
   429      *
       
   430      * @param os the output stream on which to write the XML document.
       
   431      *
       
   432      * @throws IOException if an error occurred when writing to the output stream.
       
   433      */
       
   434     public void storeToXML(OutputStream os) throws IOException {
       
   435         RegistrationDocument.store(os, this);
       
   436         os.flush();
       
   437     }
       
   438 
       
   439     /**
       
   440      * Returns a newly allocated byte array containing the registration
       
   441      * data in XML format.
       
   442      *
       
   443      * @return a newly allocated byte array containing the registration
       
   444      * data in XML format.
       
   445      */
       
   446     public byte[] toXML() {
       
   447         try {
       
   448             ByteArrayOutputStream out = new ByteArrayOutputStream();
       
   449             storeToXML(out);
       
   450             return out.toByteArray();
       
   451         } catch (IOException e) {
       
   452             // should not reach here
       
   453             return new byte[0];
       
   454         }
       
   455     }
       
   456 
       
   457     /**
       
   458      * Returns a string representation of this registration data in XML
       
   459      * format.
       
   460      *
       
   461      * @return a string representation of this registration data in XML
       
   462      *         format.
       
   463      */
       
   464     @Override
       
   465     public String toString() {
       
   466         try {
       
   467             ByteArrayOutputStream out = new ByteArrayOutputStream();
       
   468             storeToXML(out);
       
   469             return out.toString("UTF-8");
       
   470         } catch (IOException e) {
       
   471             // should not reach here
       
   472             return "Error creating the return string.";
       
   473         }
       
   474     }
       
   475 }