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.util.Date; 29 import java.io.IOException; 30 import static com.sun.servicetag.RegistrationDocument.*; 31 32 /** 33 * A service tag is an XML-based data structure that identifies a product or 34 * a component on a system. The service tag schema is defined by the 35 * Service Tags Technology. The location of the DTD file is platform dependent. 36 * On Solaris, see <tt>/usr/share/lib/xml/dtd/servicetag.dtd</tt>. 37 * <p> 38 * A valid {@code ServiceTag} instance must comply to the service tag schema 39 * and contain the following fields: 40 * <ul> 41 * <li>{@link #getInstanceURN <tt>instance_urn</tt>}</li> 42 * <li>{@link #getProductName <tt>product_name</tt>}</li> 43 * <li>{@link #getProductVersion <tt>product_version</tt>}</li> 44 * <li>{@link #getProductURN <tt>product_urn</tt>}</li> 45 * <li>{@link #getProductParent <tt>product_parent</tt>}</li> 46 * <li>{@link #getProductParentURN <tt>product_parent_urn</tt>}</li> 47 * <li>{@link #getProductDefinedInstanceID <tt>product_defined_inst_id</tt>}</li> 48 * <li>{@link #getProductVendor <tt>product_vendor</tt>}</li> 49 * <li>{@link #getPlatformArch <tt>platform_arch</tt>}</li> 50 * <li>{@link #getContainer <tt>container</tt>}</li> 51 * <li>{@link #getSource <tt>source</tt>}</li> 52 * <li>{@link #getInstallerUID <tt>installer_uid</tt>}</li> 53 * <li>{@link #getTimestamp <tt>timestamp</tt>}</li> 54 * </ul> 55 * 56 * The <tt>instance_urn</tt> can be specified when a {@code ServiceTag} 57 * object is created, or it can be generated when it is added to 58 * a {@link RegistrationData} object, or {@link Registry 59 * system service tag registry}. The <tt>installer_uid</tt> and 60 * <tt>timestamp</tt> are set when a {@code ServiceTag} object 61 * is added to a {@link RegistrationData} object, or {@link Registry 62 * system service tag registry}. 63 * 64 * @see <a href="https://sunconnection.sun.com/FAQ/sc_faq.html">Service Tags FAQ</a> 65 */ 66 public class ServiceTag { 67 68 private String instanceURN; 69 private String productName; 70 private String productVersion; 71 private String productURN; 72 private String productParent; 73 private String productParentURN; 74 private String productDefinedInstanceID; 75 private String productVendor; 76 private String platformArch; 77 private String container; 78 private String source; 79 private int installerUID; 80 private Date timestamp; 81 82 // Service Tag Field Lengths (defined in sthelper.h) 83 // Since the constants defined in sthelper.h includes the null-terminated 84 // character, so minus 1 from the sthelper.h defined values. 85 private final int MAX_URN_LEN = 256 - 1; 86 private final int MAX_PRODUCT_NAME_LEN = 256 - 1; 87 private final int MAX_PRODUCT_VERSION_LEN = 64 - 1; 88 private final int MAX_PRODUCT_PARENT_LEN = 256 - 1; 89 private final int MAX_PRODUCT_VENDOR_LEN = 64 - 1; 90 private final int MAX_PLATFORM_ARCH_LEN = 64 - 1; 91 private final int MAX_CONTAINER_LEN = 64 - 1; 92 private final int MAX_SOURCE_LEN = 64 - 1; 93 94 // private constructors 95 private ServiceTag() { 96 } 97 // package private 98 ServiceTag(String instanceURN, 99 String productName, 100 String productVersion, 101 String productURN, 102 String productParent, 103 String productParentURN, 104 String productDefinedInstanceID, 105 String productVendor, 106 String platformArch, 107 String container, 108 String source, 109 int installerUID, 110 Date timestamp) { 111 setInstanceURN(instanceURN); 112 setProductName(productName); 113 setProductVersion(productVersion); 114 setProductURN(productURN); 115 setProductParentURN(productParentURN); 116 setProductParent(productParent); 117 setProductDefinedInstanceID(productDefinedInstanceID); 118 setProductVendor(productVendor); 119 setPlatformArch(platformArch); 120 setContainer(container); 121 setSource(source); 122 setInstallerUID(installerUID); 123 setTimestamp(timestamp); 124 } 125 126 /** 127 * Creates a service tag object with no <tt>instance_urn</tt>. 128 * 129 * @param productName the name of the product. 130 * @param productVersion the version of the product. 131 * @param productURN the uniform resource name of the product 132 * @param productParent the name of the product's parent. 133 * @param productParentURN the uniform resource name of the product's parent. 134 * @param productDefinedInstanceID the instance identifier. 135 * @param productVendor the vendor of the product. 136 * @param platformArch the operating system architecture. 137 * @param container the container of the product. 138 * @param source the source of the product. 139 * 140 * @throws IllegalArgumentException if any value of the input fields 141 * does not conform to the service tag XML schema. 142 */ 143 public static ServiceTag newInstance(String productName, 144 String productVersion, 145 String productURN, 146 String productParent, 147 String productParentURN, 148 String productDefinedInstanceID, 149 String productVendor, 150 String platformArch, 151 String container, 152 String source) { 153 return new ServiceTag("", /* empty instance_urn */ 154 productName, 155 productVersion, 156 productURN, 157 productParent, 158 productParentURN, 159 productDefinedInstanceID, 160 productVendor, 161 platformArch, 162 container, 163 source, 164 -1, 165 null); 166 } 167 168 /** 169 * Creates a service tag object with a specified <tt>instance_urn</tt>. 170 * 171 * @param instanceURN the uniform resource name of this instance. 172 * @param productName the name of the product. 173 * @param productVersion the version of the product. 174 * @param productURN the uniform resource name of the product 175 * @param productParent the name of the product's parent. 176 * @param productParentURN the uniform resource name of the product's parent. 177 * @param productDefinedInstanceID the instance identifier. 178 * @param productVendor the vendor of the product. 179 * @param platformArch the operating system architecture. 180 * @param container the container of the product. 181 * @param source the source of the product. 182 * 183 * @throws IllegalArgumentException if any value of the input fields 184 * does not conform to the service tag XML schema. 185 */ 186 public static ServiceTag newInstance(String instanceURN, 187 String productName, 188 String productVersion, 189 String productURN, 190 String productParent, 191 String productParentURN, 192 String productDefinedInstanceID, 193 String productVendor, 194 String platformArch, 195 String container, 196 String source) { 197 return new ServiceTag(instanceURN, 198 productName, 199 productVersion, 200 productURN, 201 productParent, 202 productParentURN, 203 productDefinedInstanceID, 204 productVendor, 205 platformArch, 206 container, 207 source, 208 -1, 209 null); 210 } 211 212 // Creates a copy of the ServiceTag instance 213 // with instance_urn and timestamp initialized 214 static ServiceTag newInstanceWithUrnTimestamp(ServiceTag st) { 215 String instanceURN = 216 (st.getInstanceURN().length() == 0 ? Util.generateURN() : 217 st.getInstanceURN()); 218 ServiceTag svcTag = new ServiceTag(instanceURN, 219 st.getProductName(), 220 st.getProductVersion(), 221 st.getProductURN(), 222 st.getProductParent(), 223 st.getProductParentURN(), 224 st.getProductDefinedInstanceID(), 225 st.getProductVendor(), 226 st.getPlatformArch(), 227 st.getContainer(), 228 st.getSource(), 229 st.getInstallerUID(), 230 new Date()); 231 return svcTag; 232 } 233 234 /** 235 * Returns a uniform resource name (URN) in this format: 236 * <blockquote> 237 * "<tt>urn:st:<32-char {@link java.util.UUID uuid}></tt>" 238 * </blockquote> 239 * @return a URN. 240 */ 241 public static String generateInstanceURN() { 242 return Util.generateURN(); 243 } 244 245 /** 246 * Returns the uniform resource name of this service tag instance. 247 * 248 * @return the <tt>instance_urn</tt> of this service tag. 249 */ 250 public String getInstanceURN() { 251 return instanceURN; 252 } 253 254 /** 255 * Returns the name of the product. 256 * 257 * @return the product name. 258 */ 259 public String getProductName() { 260 return productName; 261 } 262 263 /** 264 * Returns the version of the product. 265 * 266 * @return the product version. 267 */ 268 public String getProductVersion() { 269 return productVersion; 270 } 271 272 /** 273 * Returns the uniform resource name of the product. 274 * 275 * @return the product URN. 276 */ 277 public String getProductURN() { 278 return productURN; 279 } 280 281 /** 282 * Returns the uniform resource name of the product's parent. 283 * 284 * @return the product's parent URN. 285 */ 286 public String getProductParentURN() { 287 return productParentURN; 288 } 289 290 /** 291 * Returns the name of the product's parent. 292 * 293 * @return the product's parent name. 294 */ 295 public String getProductParent() { 296 return productParent; 297 } 298 299 /** 300 * Returns the identifier defined for this product instance. 301 * 302 * @return the identifier defined for this product instance. 303 */ 304 public String getProductDefinedInstanceID() { 305 return productDefinedInstanceID; 306 } 307 308 /** 309 * Returns the vendor of the product. 310 * 311 * @return the product vendor. 312 */ 313 public String getProductVendor() { 314 return productVendor; 315 } 316 317 /** 318 * Returns the platform architecture on which the product 319 * is running on. 320 * 321 * @return the platform architecture on which the product is running on. 322 */ 323 public String getPlatformArch() { 324 return platformArch; 325 } 326 327 /** 328 * Returns the timestamp. This timestamp is set when this service tag 329 * is added to or updated in a {@code RegistrationData} object or 330 * the system service tag registry. 331 * This method may return {@code null}. 332 * 333 * @return timestamp when this service tag 334 * is added to or updated in a {@code RegistrationData} object or 335 * the system service tag registry, or {@code null}. 336 */ 337 public Date getTimestamp() { 338 if (timestamp != null) { 339 return (Date) timestamp.clone(); 340 } else { 341 return null; 342 } 343 } 344 345 346 /** 347 * Returns the container of the product. 348 * 349 * @return the container of the product. 350 */ 351 public String getContainer() { 352 return container; 353 } 354 355 /** 356 * Returns the source of this service tag. 357 * 358 * @return source of this service tag. 359 */ 360 public String getSource() { 361 return source; 362 } 363 364 /** 365 * Returns the UID. The UID is set when this service tag 366 * is added to or updated in the system service tag registry. 367 * This is platform dependent whose default value is {@code -1}. 368 * When this service tag is added to a {@code RegistrationData}, 369 * the UID is not set. 370 * 371 * @return the UID of whom this service tag 372 * is added to or updated in the system service tag registry, 373 * or {@code -1}. 374 */ 375 public int getInstallerUID() { 376 return installerUID; 377 } 378 379 // The following setter methods are used to validate the 380 // input field when constructing a ServiceTag instance 381 382 private void setInstanceURN(String instanceURN) { 383 if (instanceURN == null) { 384 throw new NullPointerException("Parameter instanceURN cannot be null"); 385 } 386 if (instanceURN.length() > MAX_URN_LEN) { 387 throw new IllegalArgumentException("instanceURN \"" + instanceURN + 388 "\" exceeds maximum length " + MAX_URN_LEN); 389 } 390 this.instanceURN = instanceURN; 391 } 392 393 private void setProductName(String productName) { 394 if (productName == null) { 395 throw new NullPointerException("Parameter productName cannot be null"); 396 } 397 if (productName.length() == 0) { 398 throw new IllegalArgumentException("product name cannot be empty"); 399 } 400 if (productName.length() > MAX_PRODUCT_NAME_LEN) { 401 throw new IllegalArgumentException("productName \"" + productName + 402 "\" exceeds maximum length " + MAX_PRODUCT_NAME_LEN); 403 } 404 this.productName = productName; 405 } 406 407 private void setProductVersion(String productVersion) { 408 if (productVersion == null) { 409 throw new NullPointerException("Parameter productVersion cannot be null"); 410 } 411 412 if (productVersion.length() == 0) { 413 throw new IllegalArgumentException("product version cannot be empty"); 414 } 415 if (productVersion.length() > MAX_PRODUCT_VERSION_LEN) { 416 throw new IllegalArgumentException("productVersion \"" + 417 productVersion + "\" exceeds maximum length " + 418 MAX_PRODUCT_VERSION_LEN); 419 } 420 this.productVersion = productVersion; 421 } 422 423 private void setProductURN(String productURN) { 424 if (productURN == null) { 425 throw new NullPointerException("Parameter productURN cannot be null"); 426 } 427 if (productURN.length() == 0) { 428 throw new IllegalArgumentException("product URN cannot be empty"); 429 } 430 if (productURN.length() > MAX_URN_LEN) { 431 throw new IllegalArgumentException("productURN \"" + productURN + 432 "\" exceeds maximum length " + MAX_URN_LEN); 433 } 434 this.productURN = productURN; 435 } 436 437 private void setProductParentURN(String productParentURN) { 438 if (productParentURN == null) { 439 throw new NullPointerException("Parameter productParentURN cannot be null"); 440 } 441 // optional field - can be empty 442 if (productParentURN.length() > MAX_URN_LEN) { 443 throw new IllegalArgumentException("productParentURN \"" + 444 productParentURN + "\" exceeds maximum length " + 445 MAX_URN_LEN); 446 } 447 this.productParentURN = productParentURN; 448 } 449 450 private void setProductParent(String productParent) { 451 if (productParent == null) { 452 throw new NullPointerException("Parameter productParent cannot be null"); 453 } 454 if (productParent.length() == 0) { 455 throw new IllegalArgumentException("product parent cannot be empty"); 456 } 457 if (productParent.length() > MAX_PRODUCT_PARENT_LEN) { 458 throw new IllegalArgumentException("productParent \"" + 459 productParent + "\" exceeds maximum length " + 460 MAX_PRODUCT_PARENT_LEN); 461 } 462 this.productParent = productParent; 463 } 464 465 void setProductDefinedInstanceID(String productDefinedInstanceID) { 466 if (productDefinedInstanceID == null) { 467 throw new NullPointerException("Parameter productDefinedInstanceID cannot be null"); 468 } 469 if (productDefinedInstanceID.length() > MAX_URN_LEN) { 470 throw new IllegalArgumentException("productDefinedInstanceID \"" + 471 productDefinedInstanceID + "\" exceeds maximum length " + 472 MAX_URN_LEN); 473 } 474 // optional field - can be empty 475 this.productDefinedInstanceID = productDefinedInstanceID; 476 } 477 478 private void setProductVendor(String productVendor) { 479 if (productVendor == null) { 480 throw new NullPointerException("Parameter productVendor cannot be null"); 481 } 482 if (productVendor.length() == 0) { 483 throw new IllegalArgumentException("product vendor cannot be empty"); 484 } 485 if (productVendor.length() > MAX_PRODUCT_VENDOR_LEN) { 486 throw new IllegalArgumentException("productVendor \"" + 487 productVendor + "\" exceeds maximum length " + 488 MAX_PRODUCT_VENDOR_LEN); 489 } 490 this.productVendor = productVendor; 491 } 492 493 private void setPlatformArch(String platformArch) { 494 if (platformArch == null) { 495 throw new NullPointerException("Parameter platformArch cannot be null"); 496 } 497 if (platformArch.length() == 0) { 498 throw new IllegalArgumentException("platform architecture cannot be empty"); 499 } 500 if (platformArch.length() > MAX_PLATFORM_ARCH_LEN) { 501 throw new IllegalArgumentException("platformArch \"" + 502 platformArch + "\" exceeds maximum length " + 503 MAX_PLATFORM_ARCH_LEN); 504 } 505 this.platformArch = platformArch; 506 } 507 508 private void setTimestamp(Date timestamp) { 509 // can be null 510 this.timestamp = timestamp; 511 } 512 513 private void setContainer(String container) { 514 if (container == null) { 515 throw new NullPointerException("Parameter container cannot be null"); 516 } 517 if (container.length() == 0) { 518 throw new IllegalArgumentException("container cannot be empty"); 519 } 520 if (container.length() > MAX_CONTAINER_LEN) { 521 throw new IllegalArgumentException("container \"" + 522 container + "\" exceeds maximum length " + 523 MAX_CONTAINER_LEN); 524 } 525 this.container = container; 526 } 527 528 private void setSource(String source) { 529 if (source == null) { 530 throw new NullPointerException("Parameter source cannot be null"); 531 } 532 if (source.length() == 0) { 533 throw new IllegalArgumentException("source cannot be empty"); 534 } 535 if (source.length() > MAX_SOURCE_LEN) { 536 throw new IllegalArgumentException("source \"" + source + 537 "\" exceeds maximum length " + MAX_SOURCE_LEN); 538 } 539 this.source = source; 540 } 541 542 private void setInstallerUID(int installerUID) { 543 this.installerUID = installerUID; 544 } 545 546 /** 547 * Compares this service tag to the specified object. 548 * The result is {@code true} if and only if the argument is 549 * not {@code null} and is a {@code ServiceTag} object whose 550 * <tt>instance_urn</tt> is the same as the 551 * <tt>instance_urn</tt> of this service tag. 552 * 553 * @return {@code true} if this service tag is the same as 554 * the specified object. 555 */ 556 @Override 557 public boolean equals(Object obj) { 558 if (obj == null || !(obj instanceof ServiceTag)) { 559 return false; 560 } 561 ServiceTag st = (ServiceTag) obj; 562 if (st == this) { 563 return true; 564 } 565 return st.getInstanceURN().equals(getInstanceURN()); 566 } 567 568 /** 569 * Returns the hash code value for this service tag. 570 * @return the hash code value for this service tag. 571 */ 572 @Override 573 public int hashCode() { 574 int hash = 7; 575 hash = 19 * hash + (this.instanceURN != null ? this.instanceURN.hashCode() : 0); 576 return hash; 577 } 578 579 /** 580 * Returns the string representation of this service tag. 581 * The format is implementation specific. 582 * 583 * @return the string representation of this service tag. 584 */ 585 public String toString() { 586 StringBuilder sb = new StringBuilder(); 587 sb.append(ST_NODE_INSTANCE_URN).append("=").append(instanceURN).append("\n"); 588 sb.append(ST_NODE_PRODUCT_NAME).append("=").append(productName).append("\n"); 589 sb.append(ST_NODE_PRODUCT_VERSION).append("=").append(productVersion).append("\n"); 590 sb.append(ST_NODE_PRODUCT_URN).append("=").append(productURN).append("\n"); 591 sb.append(ST_NODE_PRODUCT_PARENT_URN).append("=").append(productParentURN).append("\n"); 592 sb.append(ST_NODE_PRODUCT_PARENT).append("=").append(productParent).append("\n"); 593 sb.append(ST_NODE_PRODUCT_DEFINED_INST_ID).append("=").append(productDefinedInstanceID).append("\n"); 594 sb.append(ST_NODE_PRODUCT_VENDOR).append("=").append(productVendor).append("\n"); 595 sb.append(ST_NODE_PLATFORM_ARCH).append("=").append(platformArch).append("\n"); 596 sb.append(ST_NODE_TIMESTAMP).append("=").append(Util.formatTimestamp(timestamp)).append("\n"); 597 sb.append(ST_NODE_CONTAINER).append("=").append(container).append("\n"); 598 sb.append(ST_NODE_SOURCE).append("=").append(source).append("\n"); 599 sb.append(ST_NODE_INSTALLER_UID).append("=").append(String.valueOf(installerUID)).append("\n"); 600 return sb.toString(); 601 } 602 603 604 /** 605 * Returns the {@link ServiceTag} instance for the running Java 606 * platform. The {@link ServiceTag#setSource source} field 607 * of the {@code ServiceTag} will be set to the given {@code source}. 608 * This method will return {@code null} if there is no service tag 609 * for the running Java platform. 610 * <p> 611 * This method is designed for Sun software that bundles the JDK 612 * or the JRE to use. It is recommended that the {@code source} 613 * string contains information about the bundling software 614 * such as the name and the version of the software bundle, 615 * for example, 616 * <blockquote> 617 * <tt>NetBeans IDE 6.0 with JDK 6 Update 5 Bundle</tt> 618 * </blockquote> 619 * in a NetBeans/JDK bundle. 620 * <p> 621 * At the first time to call this method the application 622 * is required to have the write permission to the installed 623 * directory of this running JDK or JRE instance. 624 * 625 * @param source the source that bundles the JDK or the JRE. 626 * @return a {@code ServiceTag} object for the Java platform, 627 * or {@code null} if not supported. 628 * @throws IOException if an error occurs in this operation. 629 */ 630 public static ServiceTag getJavaServiceTag(String source) throws IOException { 631 return Installer.getJavaServiceTag(source); 632 } 633 634 }