blob: bebef408e22f4feb0bd3fe1329eceac62468bd81 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26
27package javax.management.openmbean;
28
29
30// java import
31//
32import java.util.Arrays;
33import java.util.HashSet;
34
35import javax.management.Descriptor;
36import javax.management.MBeanAttributeInfo;
37import javax.management.MBeanConstructorInfo;
38import javax.management.MBeanInfo;
39import javax.management.MBeanNotificationInfo;
40import javax.management.MBeanOperationInfo;
41
42/**
43 * The {@code OpenMBeanInfoSupport} class describes the management
44 * information of an <i>open MBean</i>: it is a subclass of {@link
45 * javax.management.MBeanInfo}, and it implements the {@link
46 * OpenMBeanInfo} interface. Note that an <i>open MBean</i> is
47 * recognized as such if its {@code getMBeanInfo()} method returns an
48 * instance of a class which implements the OpenMBeanInfo interface,
49 * typically {@code OpenMBeanInfoSupport}.
50 *
51 *
52 * @since 1.5
53 */
54public class OpenMBeanInfoSupport
55 extends MBeanInfo
56 implements OpenMBeanInfo {
57
58 /* Serial version */
59 static final long serialVersionUID = 4349395935420511492L;
60
61 // As this instance is immutable, these two values
62 // need only be calculated once.
63 private transient Integer myHashCode = null;
64 private transient String myToString = null;
65
66
67 /**
68 * <p>Constructs an {@code OpenMBeanInfoSupport} instance, which
69 * describes a class of open MBeans with the specified {@code
70 * className}, {@code description}, {@code openAttributes}, {@code
71 * openConstructors} , {@code openOperations} and {@code
72 * notifications}.</p>
73 *
74 * <p>The {@code openAttributes}, {@code openConstructors},
75 * {@code openOperations} and {@code notifications}
76 * array parameters are internally copied, so that subsequent changes
77 * to the arrays referenced by these parameters have no effect on this
78 * instance.</p>
79 *
80 * @param className The fully qualified Java class name of the
81 * open MBean described by this <CODE>OpenMBeanInfoSupport</CODE>
82 * instance.
83 *
84 * @param description A human readable description of the open
85 * MBean described by this <CODE>OpenMBeanInfoSupport</CODE>
86 * instance.
87 *
88 * @param openAttributes The list of exposed attributes of the
89 * described open MBean; Must be an array of instances of a
90 * subclass of {@code MBeanAttributeInfo}, typically {@code
91 * OpenMBeanAttributeInfoSupport}.
92 *
93 * @param openConstructors The list of exposed public constructors
94 * of the described open MBean; Must be an array of instances of a
95 * subclass of {@code MBeanConstructorInfo}, typically {@code
96 * OpenMBeanConstructorInfoSupport}.
97 *
98 * @param openOperations The list of exposed operations of the
99 * described open MBean. Must be an array of instances of a
100 * subclass of {@code MBeanOperationInfo}, typically {@code
101 * OpenMBeanOperationInfoSupport}.
102 *
103 * @param notifications The list of notifications emitted by the
104 * described open MBean.
105 *
106 * @throws ArrayStoreException If {@code openAttributes}, {@code
107 * openConstructors} or {@code openOperations} is not an array of
108 * instances of a subclass of {@code MBeanAttributeInfo}, {@code
109 * MBeanConstructorInfo} or {@code MBeanOperationInfo}
110 * respectively.
111 */
112 public OpenMBeanInfoSupport(String className,
113 String description,
114 OpenMBeanAttributeInfo[] openAttributes,
115 OpenMBeanConstructorInfo[] openConstructors,
116 OpenMBeanOperationInfo[] openOperations,
117 MBeanNotificationInfo[] notifications) {
118 this(className, description,
119 openAttributes, openConstructors, openOperations, notifications,
120 (Descriptor) null);
121 }
122
123 /**
124 * <p>Constructs an {@code OpenMBeanInfoSupport} instance, which
125 * describes a class of open MBeans with the specified {@code
126 * className}, {@code description}, {@code openAttributes}, {@code
127 * openConstructors} , {@code openOperations}, {@code
128 * notifications}, and {@code descriptor}.</p>
129 *
130 * <p>The {@code openAttributes}, {@code openConstructors}, {@code
131 * openOperations} and {@code notifications} array parameters are
132 * internally copied, so that subsequent changes to the arrays
133 * referenced by these parameters have no effect on this
134 * instance.</p>
135 *
136 * @param className The fully qualified Java class name of the
137 * open MBean described by this <CODE>OpenMBeanInfoSupport</CODE>
138 * instance.
139 *
140 * @param description A human readable description of the open
141 * MBean described by this <CODE>OpenMBeanInfoSupport</CODE>
142 * instance.
143 *
144 * @param openAttributes The list of exposed attributes of the
145 * described open MBean; Must be an array of instances of a
146 * subclass of {@code MBeanAttributeInfo}, typically {@code
147 * OpenMBeanAttributeInfoSupport}.
148 *
149 * @param openConstructors The list of exposed public constructors
150 * of the described open MBean; Must be an array of instances of a
151 * subclass of {@code MBeanConstructorInfo}, typically {@code
152 * OpenMBeanConstructorInfoSupport}.
153 *
154 * @param openOperations The list of exposed operations of the
155 * described open MBean. Must be an array of instances of a
156 * subclass of {@code MBeanOperationInfo}, typically {@code
157 * OpenMBeanOperationInfoSupport}.
158 *
159 * @param notifications The list of notifications emitted by the
160 * described open MBean.
161 *
162 * @param descriptor The descriptor for the MBean. This may be null
163 * which is equivalent to an empty descriptor.
164 *
165 * @throws ArrayStoreException If {@code openAttributes}, {@code
166 * openConstructors} or {@code openOperations} is not an array of
167 * instances of a subclass of {@code MBeanAttributeInfo}, {@code
168 * MBeanConstructorInfo} or {@code MBeanOperationInfo}
169 * respectively.
170 *
171 * @since 1.6
172 */
173 public OpenMBeanInfoSupport(String className,
174 String description,
175 OpenMBeanAttributeInfo[] openAttributes,
176 OpenMBeanConstructorInfo[] openConstructors,
177 OpenMBeanOperationInfo[] openOperations,
178 MBeanNotificationInfo[] notifications,
179 Descriptor descriptor) {
180 super(className,
181 description,
182 attributeArray(openAttributes),
183 constructorArray(openConstructors),
184 operationArray(openOperations),
185 (notifications == null) ? null : notifications.clone(),
186 descriptor);
187 }
188
189
190 private static MBeanAttributeInfo[]
191 attributeArray(OpenMBeanAttributeInfo[] src) {
192 if (src == null)
193 return null;
194 MBeanAttributeInfo[] dst = new MBeanAttributeInfo[src.length];
195 System.arraycopy(src, 0, dst, 0, src.length);
196 // may throw an ArrayStoreException
197 return dst;
198 }
199
200 private static MBeanConstructorInfo[]
201 constructorArray(OpenMBeanConstructorInfo[] src) {
202 if (src == null)
203 return null;
204 MBeanConstructorInfo[] dst = new MBeanConstructorInfo[src.length];
205 System.arraycopy(src, 0, dst, 0, src.length);
206 // may throw an ArrayStoreException
207 return dst;
208 }
209
210 private static MBeanOperationInfo[]
211 operationArray(OpenMBeanOperationInfo[] src) {
212 if (src == null)
213 return null;
214 MBeanOperationInfo[] dst = new MBeanOperationInfo[src.length];
215 System.arraycopy(src, 0, dst, 0, src.length);
216 return dst;
217 }
218
219
220
221 /* *** Commodity methods from java.lang.Object *** */
222
223
224 /**
225 * <p>Compares the specified {@code obj} parameter with this
226 * {@code OpenMBeanInfoSupport} instance for equality.</p>
227 *
228 * <p>Returns {@code true} if and only if all of the following
229 * statements are true:
230 *
231 * <ul>
232 * <li>{@code obj} is non null,</li>
233 * <li>{@code obj} also implements the {@code OpenMBeanInfo}
234 * interface,</li>
235 * <li>their class names are equal</li>
236 * <li>their infos on attributes, constructors, operations and
237 * notifications are equal</li>
238 * </ul>
239 *
240 * This ensures that this {@code equals} method works properly for
241 * {@code obj} parameters which are different implementations of
242 * the {@code OpenMBeanInfo} interface.
243 *
244 * @param obj the object to be compared for equality with this
245 * {@code OpenMBeanInfoSupport} instance;
246 *
247 * @return {@code true} if the specified object is equal to this
248 * {@code OpenMBeanInfoSupport} instance.
249 */
250 public boolean equals(Object obj) {
251
252 // if obj is null, return false
253 //
254 if (obj == null) {
255 return false;
256 }
257
258 // if obj is not a OpenMBeanInfo, return false
259 //
260 OpenMBeanInfo other;
261 try {
262 other = (OpenMBeanInfo) obj;
263 } catch (ClassCastException e) {
264 return false;
265 }
266
267 // Now, really test for equality between this OpenMBeanInfo
268 // implementation and the other:
269 //
270
271 // their MBean className should be equal
272 if ( ! this.getClassName().equals(other.getClassName()) )
273 return false;
274
275 // their infos on attributes should be equal (order not
276 // significant => equality between sets, not arrays or lists)
277 if (!sameArrayContents(this.getAttributes(), other.getAttributes()))
278 return false;
279
280 // their infos on constructors should be equal (order not
281 // significant => equality between sets, not arrays or lists)
282 if (!sameArrayContents(this.getConstructors(), other.getConstructors()))
283 return false;
284
285 // their infos on operations should be equal (order not
286 // significant => equality between sets, not arrays or lists)
287 if (!sameArrayContents(this.getOperations(), other.getOperations()))
288
289 return false;
290
291 // their infos on notifications should be equal (order not
292 // significant => equality between sets, not arrays or lists)
293 if (!sameArrayContents(this.getNotifications(), other.getNotifications()))
294 return false;
295
296 // All tests for equality were successful
297 //
298 return true;
299 }
300
301 private static <T> boolean sameArrayContents(T[] a1, T[] a2) {
302 return (new HashSet<T>(Arrays.asList(a1))
303 .equals(new HashSet<T>(Arrays.asList(a2))));
304 }
305
306 /**
307 * <p>Returns the hash code value for this {@code
308 * OpenMBeanInfoSupport} instance.</p>
309 *
310 * <p>The hash code of an {@code OpenMBeanInfoSupport} instance is
311 * the sum of the hash codes of all elements of information used
312 * in {@code equals} comparisons (ie: its class name, and its
313 * infos on attributes, constructors, operations and
314 * notifications, where the hashCode of each of these arrays is
315 * calculated by a call to {@code new
316 * java.util.HashSet(java.util.Arrays.asList(this.getSignature)).hashCode()}).</p>
317 *
318 * <p>This ensures that {@code t1.equals(t2)} implies that {@code
319 * t1.hashCode()==t2.hashCode()} for any two {@code
320 * OpenMBeanInfoSupport} instances {@code t1} and {@code t2}, as
321 * required by the general contract of the method {@link
322 * Object#hashCode() Object.hashCode()}.</p>
323 *
324 * <p>However, note that another instance of a class implementing
325 * the {@code OpenMBeanInfo} interface may be equal to this {@code
326 * OpenMBeanInfoSupport} instance as defined by {@link
327 * #equals(java.lang.Object)}, but may have a different hash code
328 * if it is calculated differently.</p>
329 *
330 * <p>As {@code OpenMBeanInfoSupport} instances are immutable, the
331 * hash code for this instance is calculated once, on the first
332 * call to {@code hashCode}, and then the same value is returned
333 * for subsequent calls.</p>
334 *
335 * @return the hash code value for this {@code
336 * OpenMBeanInfoSupport} instance
337 */
338 public int hashCode() {
339
340 // Calculate the hash code value if it has not yet been done
341 // (ie 1st call to hashCode())
342 //
343 if (myHashCode == null) {
344 int value = 0;
345 value += this.getClassName().hashCode();
346 value += arraySetHash(this.getAttributes());
347 value += arraySetHash(this.getConstructors());
348 value += arraySetHash(this.getOperations());
349 value += arraySetHash(this.getNotifications());
350 myHashCode = new Integer(value);
351 }
352
353 // return always the same hash code for this instance (immutable)
354 //
355 return myHashCode.intValue();
356 }
357
358 private static <T> int arraySetHash(T[] a) {
359 return new HashSet<T>(Arrays.asList(a)).hashCode();
360 }
361
362
363
364 /**
365 * <p>Returns a string representation of this {@code
366 * OpenMBeanInfoSupport} instance.</p>
367 *
368 * <p>The string representation consists of the name of this class
369 * (ie {@code javax.management.openmbean.OpenMBeanInfoSupport}),
370 * the MBean class name, the string representation of infos on
371 * attributes, constructors, operations and notifications of the
372 * described MBean and the string representation of the descriptor.</p>
373 *
374 * <p>As {@code OpenMBeanInfoSupport} instances are immutable, the
375 * string representation for this instance is calculated once, on
376 * the first call to {@code toString}, and then the same value is
377 * returned for subsequent calls.</p>
378 *
379 * @return a string representation of this {@code
380 * OpenMBeanInfoSupport} instance
381 */
382 public String toString() {
383
384 // Calculate the string value if it has not yet been done (ie
385 // 1st call to toString())
386 //
387 if (myToString == null) {
388 myToString = new StringBuilder()
389 .append(this.getClass().getName())
390 .append("(mbean_class_name=")
391 .append(this.getClassName())
392 .append(",attributes=")
393 .append(Arrays.asList(this.getAttributes()).toString())
394 .append(",constructors=")
395 .append(Arrays.asList(this.getConstructors()).toString())
396 .append(",operations=")
397 .append(Arrays.asList(this.getOperations()).toString())
398 .append(",notifications=")
399 .append(Arrays.asList(this.getNotifications()).toString())
400 .append(",descriptor=")
401 .append(this.getDescriptor())
402 .append(")")
403 .toString();
404 }
405
406 // return always the same string representation for this
407 // instance (immutable)
408 //
409 return myToString;
410 }
411
412}