1 /* 2 * Copyright (c) 2000, 2013, 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 27 package javax.management.openmbean; 28 29 30 // java import 31 // 32 import java.util.Set; 33 import javax.management.Descriptor; 34 import javax.management.DescriptorRead; // for Javadoc 35 import javax.management.ImmutableDescriptor; 36 import javax.management.MBeanParameterInfo; 37 38 // OpenMBeanAttributeInfoSupport and this class are very similar 39 // but can't easily be refactored because there's no multiple inheritance. 40 // The best we can do for refactoring is to put a bunch of static methods 41 // in OpenMBeanAttributeInfoSupport and import them here. 42 import static javax.management.openmbean.OpenMBeanAttributeInfoSupport.*; 43 44 /** 45 * Describes a parameter used in one or more operations or 46 * constructors of an open MBean. 47 * 48 * 49 * @since 1.5 50 */ 51 public class OpenMBeanParameterInfoSupport 52 extends MBeanParameterInfo 53 implements OpenMBeanParameterInfo { 54 55 /* Serial version */ 56 static final long serialVersionUID = -7235016873758443122L; 57 58 /** 59 * @serial The open mbean parameter's <i>open type</i> 60 */ 61 private OpenType<?> openType; 62 63 /** 64 * @serial The open mbean parameter's default value 65 */ 66 private Object defaultValue = null; 67 68 /** 69 * @serial The open mbean parameter's legal values. This {@link 70 * Set} is unmodifiable 71 */ 72 private Set<?> legalValues = null; // to be constructed unmodifiable 73 74 /** 75 * @serial The open mbean parameter's min value 76 */ 77 private Comparable<?> minValue = null; 78 79 /** 80 * @serial The open mbean parameter's max value 81 */ 82 private Comparable<?> maxValue = null; 83 84 85 // As this instance is immutable, these two values need only 86 // be calculated once. 87 private transient Integer myHashCode = null; // As this instance is immutable, these two values 88 private transient String myToString = null; // need only be calculated once. 89 90 91 /** 92 * Constructs an {@code OpenMBeanParameterInfoSupport} instance, 93 * which describes the parameter used in one or more operations or 94 * constructors of a class of open MBeans, with the specified 95 * {@code name}, {@code openType} and {@code description}. 96 * 97 * @param name cannot be a null or empty string. 98 * 99 * @param description cannot be a null or empty string. 100 * 101 * @param openType cannot be null. 102 * 103 * @throws IllegalArgumentException if {@code name} or {@code 104 * description} are null or empty string, or {@code openType} is 105 * null. 106 */ 107 public OpenMBeanParameterInfoSupport(String name, 108 String description, 109 OpenType<?> openType) { 110 this(name, description, openType, (Descriptor) null); 111 } 112 113 /** 114 * Constructs an {@code OpenMBeanParameterInfoSupport} instance, 115 * which describes the parameter used in one or more operations or 116 * constructors of a class of open MBeans, with the specified 117 * {@code name}, {@code openType}, {@code description}, 118 * and {@code descriptor}. 119 * 120 * <p>The {@code descriptor} can contain entries that will define 121 * the values returned by certain methods of this class, as 122 * explained in the <a href="package-summary.html#constraints"> 123 * package description</a>. 124 * 125 * @param name cannot be a null or empty string. 126 * 127 * @param description cannot be a null or empty string. 128 * 129 * @param openType cannot be null. 130 * 131 * @param descriptor The descriptor for the parameter. This may be null 132 * which is equivalent to an empty descriptor. 133 * 134 * @throws IllegalArgumentException if {@code name} or {@code 135 * description} are null or empty string, or {@code openType} is 136 * null, or the descriptor entries are invalid as described in the 137 * <a href="package-summary.html#constraints">package 138 * description</a>. 139 * 140 * @since 1.6 141 */ 142 public OpenMBeanParameterInfoSupport(String name, 143 String description, 144 OpenType<?> openType, 145 Descriptor descriptor) { 146 147 148 // Construct parent's state 149 // 150 super(name, 151 (openType==null) ? null : openType.getClassName(), 152 description, 153 ImmutableDescriptor.union(descriptor,(openType==null)?null: 154 openType.getDescriptor())); 155 156 // Initialize this instance's specific state 157 // 158 this.openType = openType; 159 160 descriptor = getDescriptor(); // replace null by empty 161 this.defaultValue = valueFrom(descriptor, "defaultValue", openType); 162 this.legalValues = valuesFrom(descriptor, "legalValues", openType); 163 this.minValue = comparableValueFrom(descriptor, "minValue", openType); 164 this.maxValue = comparableValueFrom(descriptor, "maxValue", openType); 165 166 try { 167 check(this); 168 } catch (OpenDataException e) { 169 throw new IllegalArgumentException(e.getMessage(), e); 170 } 171 } 172 173 174 /** 175 * Constructs an {@code OpenMBeanParameterInfoSupport} instance, 176 * which describes the parameter used in one or more operations or 177 * constructors of a class of open MBeans, with the specified 178 * {@code name}, {@code openType}, {@code description} and {@code 179 * defaultValue}. 180 * 181 * @param name cannot be a null or empty string. 182 * 183 * @param description cannot be a null or empty string. 184 * 185 * @param openType cannot be null. 186 * 187 * @param defaultValue must be a valid value for the {@code 188 * openType} specified for this parameter; default value not 189 * supported for {@code ArrayType} and {@code TabularType}; can be 190 * null, in which case it means that no default value is set. 191 * 192 * @param <T> allows the compiler to check that the {@code defaultValue}, 193 * if non-null, has the correct Java type for the given {@code openType}. 194 * 195 * @throws IllegalArgumentException if {@code name} or {@code 196 * description} are null or empty string, or {@code openType} is 197 * null. 198 * 199 * @throws OpenDataException if {@code defaultValue} is not a 200 * valid value for the specified {@code openType}, or {@code 201 * defaultValue} is non null and {@code openType} is an {@code 202 * ArrayType} or a {@code TabularType}. 203 */ 204 public <T> OpenMBeanParameterInfoSupport(String name, 205 String description, 206 OpenType<T> openType, 207 T defaultValue) 208 throws OpenDataException { 209 this(name, description, openType, defaultValue, (T[]) null); 210 } 211 212 /** 213 * <p>Constructs an {@code OpenMBeanParameterInfoSupport} instance, 214 * which describes the parameter used in one or more operations or 215 * constructors of a class of open MBeans, with the specified 216 * {@code name}, {@code openType}, {@code description}, {@code 217 * defaultValue} and {@code legalValues}.</p> 218 * 219 * <p>The contents of {@code legalValues} are copied, so subsequent 220 * modifications of the array referenced by {@code legalValues} 221 * have no impact on this {@code OpenMBeanParameterInfoSupport} 222 * instance.</p> 223 * 224 * @param name cannot be a null or empty string. 225 * 226 * @param description cannot be a null or empty string. 227 * 228 * @param openType cannot be null. 229 * 230 * @param defaultValue must be a valid value for the {@code 231 * openType} specified for this parameter; default value not 232 * supported for {@code ArrayType} and {@code TabularType}; can be 233 * null, in which case it means that no default value is set. 234 * 235 * @param legalValues each contained value must be valid for the 236 * {@code openType} specified for this parameter; legal values not 237 * supported for {@code ArrayType} and {@code TabularType}; can be 238 * null or empty. 239 * 240 * @param <T> allows the compiler to check that the {@code 241 * defaultValue} and {@code legalValues}, if non-null, have the 242 * correct Java type for the given {@code openType}. 243 * 244 * @throws IllegalArgumentException if {@code name} or {@code 245 * description} are null or empty string, or {@code openType} is 246 * null. 247 * 248 * @throws OpenDataException if {@code defaultValue} is not a 249 * valid value for the specified {@code openType}, or one value in 250 * {@code legalValues} is not valid for the specified {@code 251 * openType}, or {@code defaultValue} is non null and {@code 252 * openType} is an {@code ArrayType} or a {@code TabularType}, or 253 * {@code legalValues} is non null and non empty and {@code 254 * openType} is an {@code ArrayType} or a {@code TabularType}, or 255 * {@code legalValues} is non null and non empty and {@code 256 * defaultValue} is not contained in {@code legalValues}. 257 */ 258 public <T> OpenMBeanParameterInfoSupport(String name, 259 String description, 260 OpenType<T> openType, 261 T defaultValue, 262 T[] legalValues) 263 throws OpenDataException { 264 this(name, description, openType, 265 defaultValue, legalValues, null, null); 266 } 267 268 269 /** 270 * Constructs an {@code OpenMBeanParameterInfoSupport} instance, 271 * which describes the parameter used in one or more operations or 272 * constructors of a class of open MBeans, with the specified 273 * {@code name}, {@code openType}, {@code description}, {@code 274 * defaultValue}, {@code minValue} and {@code maxValue}. 275 * 276 * It is possible to specify minimal and maximal values only for 277 * an open type whose values are {@code Comparable}. 278 * 279 * @param name cannot be a null or empty string. 280 * 281 * @param description cannot be a null or empty string. 282 * 283 * @param openType cannot be null. 284 * 285 * @param defaultValue must be a valid value for the {@code 286 * openType} specified for this parameter; default value not 287 * supported for {@code ArrayType} and {@code TabularType}; can be 288 * null, in which case it means that no default value is set. 289 * 290 * @param minValue must be valid for the {@code openType} 291 * specified for this parameter; can be null, in which case it 292 * means that no minimal value is set. 293 * 294 * @param maxValue must be valid for the {@code openType} 295 * specified for this parameter; can be null, in which case it 296 * means that no maximal value is set. 297 * 298 * @param <T> allows the compiler to check that the {@code 299 * defaultValue}, {@code minValue}, and {@code maxValue}, if 300 * non-null, have the correct Java type for the given {@code 301 * openType}. 302 * 303 * @throws IllegalArgumentException if {@code name} or {@code 304 * description} are null or empty string, or {@code openType} is 305 * null. 306 * 307 * @throws OpenDataException if {@code defaultValue}, {@code 308 * minValue} or {@code maxValue} is not a valid value for the 309 * specified {@code openType}, or {@code defaultValue} is non null 310 * and {@code openType} is an {@code ArrayType} or a {@code 311 * TabularType}, or both {@code minValue} and {@code maxValue} are 312 * non-null and {@code minValue.compareTo(maxValue) > 0} is {@code 313 * true}, or both {@code defaultValue} and {@code minValue} are 314 * non-null and {@code minValue.compareTo(defaultValue) > 0} is 315 * {@code true}, or both {@code defaultValue} and {@code maxValue} 316 * are non-null and {@code defaultValue.compareTo(maxValue) > 0} 317 * is {@code true}. 318 */ 319 public <T> OpenMBeanParameterInfoSupport(String name, 320 String description, 321 OpenType<T> openType, 322 T defaultValue, 323 Comparable<T> minValue, 324 Comparable<T> maxValue) 325 throws OpenDataException { 326 this(name, description, openType, 327 defaultValue, null, minValue, maxValue); 328 } 329 330 private <T> OpenMBeanParameterInfoSupport(String name, 331 String description, 332 OpenType<T> openType, 333 T defaultValue, 334 T[] legalValues, 335 Comparable<T> minValue, 336 Comparable<T> maxValue) 337 throws OpenDataException { 338 super(name, 339 (openType == null) ? null : openType.getClassName(), 340 description, 341 makeDescriptor(openType, 342 defaultValue, legalValues, minValue, maxValue)); 343 344 this.openType = openType; 345 346 Descriptor d = getDescriptor(); 347 this.defaultValue = defaultValue; 348 this.minValue = minValue; 349 this.maxValue = maxValue; 350 // We already converted the array into an unmodifiable Set 351 // in the descriptor. 352 this.legalValues = (Set<?>) d.getFieldValue("legalValues"); 353 354 check(this); 355 } 356 357 /** 358 * An object serialized in a version of the API before Descriptors were 359 * added to this class will have an empty or null Descriptor. 360 * For consistency with our 361 * behavior in this version, we must replace the object with one 362 * where the Descriptors reflect the same values of openType, defaultValue, 363 * etc. 364 **/ 365 private Object readResolve() { 366 if (getDescriptor().getFieldNames().length == 0) { 367 // This noise allows us to avoid "unchecked" warnings without 368 // having to suppress them explicitly. 369 OpenType<Object> xopenType = cast(openType); 370 Set<Object> xlegalValues = cast(legalValues); 371 Comparable<Object> xminValue = cast(minValue); 372 Comparable<Object> xmaxValue = cast(maxValue); 373 return new OpenMBeanParameterInfoSupport( 374 name, description, openType, 375 makeDescriptor(xopenType, defaultValue, xlegalValues, 376 xminValue, xmaxValue)); 377 } else 378 return this; 379 } 380 381 /** 382 * Returns the open type for the values of the parameter described 383 * by this {@code OpenMBeanParameterInfoSupport} instance. 384 */ 385 public OpenType<?> getOpenType() { 386 return openType; 387 } 388 389 /** 390 * Returns the default value for the parameter described by this 391 * {@code OpenMBeanParameterInfoSupport} instance, if specified, 392 * or {@code null} otherwise. 393 */ 394 public Object getDefaultValue() { 395 396 // Special case for ArrayType and TabularType 397 // [JF] TODO: clone it so that it cannot be altered, 398 // [JF] TODO: if we decide to support defaultValue as an array itself. 399 // [JF] As of today (oct 2000) it is not supported so 400 // defaultValue is null for arrays. Nothing to do. 401 402 return defaultValue; 403 } 404 405 /** 406 * Returns an unmodifiable Set of legal values for the parameter 407 * described by this {@code OpenMBeanParameterInfoSupport} 408 * instance, if specified, or {@code null} otherwise. 409 */ 410 public Set<?> getLegalValues() { 411 412 // Special case for ArrayType and TabularType 413 // [JF] TODO: clone values so that they cannot be altered, 414 // [JF] TODO: if we decide to support LegalValues as an array itself. 415 // [JF] As of today (oct 2000) it is not supported so 416 // legalValues is null for arrays. Nothing to do. 417 418 // Returns our legalValues Set (set was constructed unmodifiable) 419 return (legalValues); 420 } 421 422 /** 423 * Returns the minimal value for the parameter described by this 424 * {@code OpenMBeanParameterInfoSupport} instance, if specified, 425 * or {@code null} otherwise. 426 */ 427 public Comparable<?> getMinValue() { 428 429 // Note: only comparable values have a minValue, so that's not 430 // the case of arrays and tabulars (always null). 431 432 return minValue; 433 } 434 435 /** 436 * Returns the maximal value for the parameter described by this 437 * {@code OpenMBeanParameterInfoSupport} instance, if specified, 438 * or {@code null} otherwise. 439 */ 440 public Comparable<?> getMaxValue() { 441 442 // Note: only comparable values have a maxValue, so that's not 443 // the case of arrays and tabulars (always null). 444 445 return maxValue; 446 } 447 448 /** 449 * Returns {@code true} if this {@code 450 * OpenMBeanParameterInfoSupport} instance specifies a non-null 451 * default value for the described parameter, {@code false} 452 * otherwise. 453 */ 454 public boolean hasDefaultValue() { 455 456 return (defaultValue != null); 457 } 458 459 /** 460 * Returns {@code true} if this {@code 461 * OpenMBeanParameterInfoSupport} instance specifies a non-null 462 * set of legal values for the described parameter, {@code false} 463 * otherwise. 464 */ 465 public boolean hasLegalValues() { 466 467 return (legalValues != null); 468 } 469 470 /** 471 * Returns {@code true} if this {@code 472 * OpenMBeanParameterInfoSupport} instance specifies a non-null 473 * minimal value for the described parameter, {@code false} 474 * otherwise. 475 */ 476 public boolean hasMinValue() { 477 478 return (minValue != null); 479 } 480 481 /** 482 * Returns {@code true} if this {@code 483 * OpenMBeanParameterInfoSupport} instance specifies a non-null 484 * maximal value for the described parameter, {@code false} 485 * otherwise. 486 */ 487 public boolean hasMaxValue() { 488 489 return (maxValue != null); 490 } 491 492 493 /** 494 * Tests whether {@code obj} is a valid value for the parameter 495 * described by this {@code OpenMBeanParameterInfo} instance. 496 * 497 * @param obj the object to be tested. 498 * 499 * @return {@code true} if {@code obj} is a valid value 500 * for the parameter described by this 501 * {@code OpenMBeanParameterInfo} instance, 502 * {@code false} otherwise. 503 */ 504 public boolean isValue(Object obj) { 505 return OpenMBeanAttributeInfoSupport.isValue(this, obj); 506 // compiler bug? should be able to omit class name here 507 // also below in toString and hashCode 508 } 509 510 511 /* *** Commodity methods from java.lang.Object *** */ 512 513 514 /** 515 * <p>Compares the specified {@code obj} parameter with this {@code 516 * OpenMBeanParameterInfoSupport} instance for equality.</p> 517 * 518 * <p>Returns {@code true} if and only if all of the following 519 * statements are true: 520 * 521 * <ul> 522 * <li>{@code obj} is non null,</li> 523 * <li>{@code obj} also implements the {@code OpenMBeanParameterInfo} 524 * interface,</li> 525 * <li>their names are equal</li> 526 * <li>their open types are equal</li> 527 * <li>their default, min, max and legal values are equal.</li> 528 * </ul> 529 * This ensures that this {@code equals} method works properly for 530 * {@code obj} parameters which are different implementations of 531 * the {@code OpenMBeanParameterInfo} interface. 532 * 533 * <p>If {@code obj} also implements {@link DescriptorRead}, then its 534 * {@link DescriptorRead#getDescriptor() getDescriptor()} method must 535 * also return the same value as for this object.</p> 536 * 537 * @param obj the object to be compared for equality with this 538 * {@code OpenMBeanParameterInfoSupport} instance. 539 * 540 * @return {@code true} if the specified object is equal to this 541 * {@code OpenMBeanParameterInfoSupport} instance. 542 */ 543 public boolean equals(Object obj) { 544 if (!(obj instanceof OpenMBeanParameterInfo)) 545 return false; 546 547 OpenMBeanParameterInfo other = (OpenMBeanParameterInfo) obj; 548 549 return equal(this, other); 550 } 551 552 /** 553 * <p>Returns the hash code value for this {@code 554 * OpenMBeanParameterInfoSupport} instance.</p> 555 * 556 * <p>The hash code of an {@code OpenMBeanParameterInfoSupport} 557 * instance is the sum of the hash codes of all elements of 558 * information used in {@code equals} comparisons (ie: its name, 559 * its <i>open type</i>, its default, min, max and legal 560 * values, and its Descriptor). 561 * 562 * <p>This ensures that {@code t1.equals(t2)} implies that {@code 563 * t1.hashCode()==t2.hashCode()} for any two {@code 564 * OpenMBeanParameterInfoSupport} instances {@code t1} and {@code 565 * t2}, as required by the general contract of the method {@link 566 * Object#hashCode() Object.hashCode()}. 567 * 568 * <p>However, note that another instance of a class implementing 569 * the {@code OpenMBeanParameterInfo} interface may be equal to 570 * this {@code OpenMBeanParameterInfoSupport} instance as defined 571 * by {@link #equals(java.lang.Object)}, but may have a different 572 * hash code if it is calculated differently. 573 * 574 * <p>As {@code OpenMBeanParameterInfoSupport} instances are 575 * immutable, the hash code for this instance is calculated once, 576 * on the first call to {@code hashCode}, and then the same value 577 * is returned for subsequent calls. 578 * 579 * @return the hash code value for this {@code 580 * OpenMBeanParameterInfoSupport} instance 581 */ 582 public int hashCode() { 583 584 // Calculate the hash code value if it has not yet been done 585 // (ie 1st call to hashCode()) 586 // 587 if (myHashCode == null) 588 myHashCode = OpenMBeanAttributeInfoSupport.hashCode(this); 589 590 // return always the same hash code for this instance (immutable) 591 // 592 return myHashCode.intValue(); 593 } 594 595 /** 596 * Returns a string representation of this 597 * {@code OpenMBeanParameterInfoSupport} instance. 598 * <p> 599 * The string representation consists of the name of this class (i.e. 600 * {@code javax.management.openmbean.OpenMBeanParameterInfoSupport}), 601 * the string representation of the name and open type of the described 602 * parameter, the string representation of its default, min, max and legal 603 * values and the string representation of its descriptor. 604 * <p> 605 * As {@code OpenMBeanParameterInfoSupport} instances are immutable, 606 * the string representation for this instance is calculated once, 607 * on the first call to {@code toString}, and then the same value 608 * is returned for subsequent calls. 609 * 610 * @return a string representation of this 611 * {@code OpenMBeanParameterInfoSupport} instance. 612 */ 613 public String toString() { 614 615 // Calculate the string value if it has not yet been done (ie 616 // 1st call to toString()) 617 // 618 if (myToString == null) 619 myToString = OpenMBeanAttributeInfoSupport.toString(this); 620 621 // return always the same string representation for this 622 // instance (immutable) 623 // 624 return myToString; 625 } 626 627 }