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, nullnull);
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 trueif 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 trueif 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 trueif 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 trueif 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 trueif {@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 trueif 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 trueif 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 }
628