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