001 /*
002 * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.management.openmbean;
027
028 // java import
029 //
030 import java.util.Arrays;
031 import java.util.HashSet;
032
033 import javax.management.Descriptor;
034 import javax.management.MBeanAttributeInfo;
035 import javax.management.MBeanConstructorInfo;
036 import javax.management.MBeanInfo;
037 import javax.management.MBeanNotificationInfo;
038 import javax.management.MBeanOperationInfo;
039
040 /**
041 * The {@code OpenMBeanInfoSupport} class describes the management
042 * information of an <i>open MBean</i>: it is a subclass of {@link
043 * javax.management.MBeanInfo}, and it implements the {@link
044 * OpenMBeanInfo} interface. Note that an <i>open MBean</i> is
045 * recognized as such if its {@code getMBeanInfo()} method returns an
046 * instance of a class which implements the OpenMBeanInfo interface,
047 * typically {@code OpenMBeanInfoSupport}.
048 *
049 *
050 * @since 1.5
051 */
052 public class OpenMBeanInfoSupport extends MBeanInfo implements
053 OpenMBeanInfo {
054
055 /* Serial version */
056 static final long serialVersionUID = 4349395935420511492L;
057
058 // As this instance is immutable, these two values
059 // need only be calculated once.
060 private transient Integer myHashCode = null;
061 private transient String myToString = null;
062
063 /**
064 * <p>Constructs an {@code OpenMBeanInfoSupport} instance, which
065 * describes a class of open MBeans with the specified {@code
066 * className}, {@code description}, {@code openAttributes}, {@code
067 * openConstructors} , {@code openOperations} and {@code
068 * notifications}.</p>
069 *
070 * <p>The {@code openAttributes}, {@code openConstructors},
071 * {@code openOperations} and {@code notifications}
072 * array parameters are internally copied, so that subsequent changes
073 * to the arrays referenced by these parameters have no effect on this
074 * instance.</p>
075 *
076 * @param className The fully qualified Java class name of the
077 * open MBean described by this <CODE>OpenMBeanInfoSupport</CODE>
078 * instance.
079 *
080 * @param description A human readable description of the open
081 * MBean described by this <CODE>OpenMBeanInfoSupport</CODE>
082 * instance.
083 *
084 * @param openAttributes The list of exposed attributes of the
085 * described open MBean; Must be an array of instances of a
086 * subclass of {@code MBeanAttributeInfo}, typically {@code
087 * OpenMBeanAttributeInfoSupport}.
088 *
089 * @param openConstructors The list of exposed public constructors
090 * of the described open MBean; Must be an array of instances of a
091 * subclass of {@code MBeanConstructorInfo}, typically {@code
092 * OpenMBeanConstructorInfoSupport}.
093 *
094 * @param openOperations The list of exposed operations of the
095 * described open MBean. Must be an array of instances of a
096 * subclass of {@code MBeanOperationInfo}, typically {@code
097 * OpenMBeanOperationInfoSupport}.
098 *
099 * @param notifications The list of notifications emitted by the
100 * described open MBean.
101 *
102 * @throws ArrayStoreException If {@code openAttributes}, {@code
103 * openConstructors} or {@code openOperations} is not an array of
104 * instances of a subclass of {@code MBeanAttributeInfo}, {@code
105 * MBeanConstructorInfo} or {@code MBeanOperationInfo}
106 * respectively.
107 */
108 public OpenMBeanInfoSupport(String className, String description,
109 OpenMBeanAttributeInfo[] openAttributes,
110 OpenMBeanConstructorInfo[] openConstructors,
111 OpenMBeanOperationInfo[] openOperations,
112 MBeanNotificationInfo[] notifications) {
113 this (className, description, openAttributes, openConstructors,
114 openOperations, notifications, (Descriptor) null);
115 }
116
117 /**
118 * <p>Constructs an {@code OpenMBeanInfoSupport} instance, which
119 * describes a class of open MBeans with the specified {@code
120 * className}, {@code description}, {@code openAttributes}, {@code
121 * openConstructors} , {@code openOperations}, {@code
122 * notifications}, and {@code descriptor}.</p>
123 *
124 * <p>The {@code openAttributes}, {@code openConstructors}, {@code
125 * openOperations} and {@code notifications} array parameters are
126 * internally copied, so that subsequent changes to the arrays
127 * referenced by these parameters have no effect on this
128 * instance.</p>
129 *
130 * @param className The fully qualified Java class name of the
131 * open MBean described by this <CODE>OpenMBeanInfoSupport</CODE>
132 * instance.
133 *
134 * @param description A human readable description of the open
135 * MBean described by this <CODE>OpenMBeanInfoSupport</CODE>
136 * instance.
137 *
138 * @param openAttributes The list of exposed attributes of the
139 * described open MBean; Must be an array of instances of a
140 * subclass of {@code MBeanAttributeInfo}, typically {@code
141 * OpenMBeanAttributeInfoSupport}.
142 *
143 * @param openConstructors The list of exposed public constructors
144 * of the described open MBean; Must be an array of instances of a
145 * subclass of {@code MBeanConstructorInfo}, typically {@code
146 * OpenMBeanConstructorInfoSupport}.
147 *
148 * @param openOperations The list of exposed operations of the
149 * described open MBean. Must be an array of instances of a
150 * subclass of {@code MBeanOperationInfo}, typically {@code
151 * OpenMBeanOperationInfoSupport}.
152 *
153 * @param notifications The list of notifications emitted by the
154 * described open MBean.
155 *
156 * @param descriptor The descriptor for the MBean. This may be null
157 * which is equivalent to an empty descriptor.
158 *
159 * @throws ArrayStoreException If {@code openAttributes}, {@code
160 * openConstructors} or {@code openOperations} is not an array of
161 * instances of a subclass of {@code MBeanAttributeInfo}, {@code
162 * MBeanConstructorInfo} or {@code MBeanOperationInfo}
163 * respectively.
164 *
165 * @since 1.6
166 */
167 public OpenMBeanInfoSupport(String className, String description,
168 OpenMBeanAttributeInfo[] openAttributes,
169 OpenMBeanConstructorInfo[] openConstructors,
170 OpenMBeanOperationInfo[] openOperations,
171 MBeanNotificationInfo[] notifications, Descriptor descriptor) {
172 super (className, description, attributeArray(openAttributes),
173 constructorArray(openConstructors),
174 operationArray(openOperations),
175 (notifications == null) ? null : notifications.clone(),
176 descriptor);
177 }
178
179 private static MBeanAttributeInfo[] attributeArray(
180 OpenMBeanAttributeInfo[] src) {
181 if (src == null)
182 return null;
183 MBeanAttributeInfo[] dst = new MBeanAttributeInfo[src.length];
184 System.arraycopy(src, 0, dst, 0, src.length);
185 // may throw an ArrayStoreException
186 return dst;
187 }
188
189 private static MBeanConstructorInfo[] constructorArray(
190 OpenMBeanConstructorInfo[] src) {
191 if (src == null)
192 return null;
193 MBeanConstructorInfo[] dst = new MBeanConstructorInfo[src.length];
194 System.arraycopy(src, 0, dst, 0, src.length);
195 // may throw an ArrayStoreException
196 return dst;
197 }
198
199 private static MBeanOperationInfo[] operationArray(
200 OpenMBeanOperationInfo[] src) {
201 if (src == null)
202 return null;
203 MBeanOperationInfo[] dst = new MBeanOperationInfo[src.length];
204 System.arraycopy(src, 0, dst, 0, src.length);
205 return dst;
206 }
207
208 /* *** Commodity methods from java.lang.Object *** */
209
210 /**
211 * <p>Compares the specified {@code obj} parameter with this
212 * {@code OpenMBeanInfoSupport} instance for equality.</p>
213 *
214 * <p>Returns {@code true} if and only if all of the following
215 * statements are true:
216 *
217 * <ul>
218 * <li>{@code obj} is non null,</li>
219 * <li>{@code obj} also implements the {@code OpenMBeanInfo}
220 * interface,</li>
221 * <li>their class names are equal</li>
222 * <li>their infos on attributes, constructors, operations and
223 * notifications are equal</li>
224 * </ul>
225 *
226 * This ensures that this {@code equals} method works properly for
227 * {@code obj} parameters which are different implementations of
228 * the {@code OpenMBeanInfo} interface.
229 *
230 * @param obj the object to be compared for equality with this
231 * {@code OpenMBeanInfoSupport} instance;
232 *
233 * @return {@code true} if the specified object is equal to this
234 * {@code OpenMBeanInfoSupport} instance.
235 */
236 public boolean equals(Object obj) {
237
238 // if obj is null, return false
239 //
240 if (obj == null) {
241 return false;
242 }
243
244 // if obj is not a OpenMBeanInfo, return false
245 //
246 OpenMBeanInfo other;
247 try {
248 other = (OpenMBeanInfo) obj;
249 } catch (ClassCastException e) {
250 return false;
251 }
252
253 // Now, really test for equality between this OpenMBeanInfo
254 // implementation and the other:
255 //
256
257 // their MBean className should be equal
258 if (!this .getClassName().equals(other.getClassName()))
259 return false;
260
261 // their infos on attributes should be equal (order not
262 // significant => equality between sets, not arrays or lists)
263 if (!sameArrayContents(this .getAttributes(), other
264 .getAttributes()))
265 return false;
266
267 // their infos on constructors should be equal (order not
268 // significant => equality between sets, not arrays or lists)
269 if (!sameArrayContents(this .getConstructors(), other
270 .getConstructors()))
271 return false;
272
273 // their infos on operations should be equal (order not
274 // significant => equality between sets, not arrays or lists)
275 if (!sameArrayContents(this .getOperations(), other
276 .getOperations()))
277
278 return false;
279
280 // their infos on notifications should be equal (order not
281 // significant => equality between sets, not arrays or lists)
282 if (!sameArrayContents(this .getNotifications(), other
283 .getNotifications()))
284 return false;
285
286 // All tests for equality were successful
287 //
288 return true;
289 }
290
291 private static <T> boolean sameArrayContents(T[] a1, T[] a2) {
292 return (new HashSet<T>(Arrays.asList(a1))
293 .equals(new HashSet<T>(Arrays.asList(a2))));
294 }
295
296 /**
297 * <p>Returns the hash code value for this {@code
298 * OpenMBeanInfoSupport} instance.</p>
299 *
300 * <p>The hash code of an {@code OpenMBeanInfoSupport} instance is
301 * the sum of the hash codes of all elements of information used
302 * in {@code equals} comparisons (ie: its class name, and its
303 * infos on attributes, constructors, operations and
304 * notifications, where the hashCode of each of these arrays is
305 * calculated by a call to {@code new
306 * java.util.HashSet(java.util.Arrays.asList(this.getSignature)).hashCode()}).</p>
307 *
308 * <p>This ensures that {@code t1.equals(t2)} implies that {@code
309 * t1.hashCode()==t2.hashCode()} for any two {@code
310 * OpenMBeanInfoSupport} instances {@code t1} and {@code t2}, as
311 * required by the general contract of the method {@link
312 * Object#hashCode() Object.hashCode()}.</p>
313 *
314 * <p>However, note that another instance of a class implementing
315 * the {@code OpenMBeanInfo} interface may be equal to this {@code
316 * OpenMBeanInfoSupport} instance as defined by {@link
317 * #equals(java.lang.Object)}, but may have a different hash code
318 * if it is calculated differently.</p>
319 *
320 * <p>As {@code OpenMBeanInfoSupport} instances are immutable, the
321 * hash code for this instance is calculated once, on the first
322 * call to {@code hashCode}, and then the same value is returned
323 * for subsequent calls.</p>
324 *
325 * @return the hash code value for this {@code
326 * OpenMBeanInfoSupport} instance
327 */
328 public int hashCode() {
329
330 // Calculate the hash code value if it has not yet been done
331 // (ie 1st call to hashCode())
332 //
333 if (myHashCode == null) {
334 int value = 0;
335 value += this .getClassName().hashCode();
336 value += arraySetHash(this .getAttributes());
337 value += arraySetHash(this .getConstructors());
338 value += arraySetHash(this .getOperations());
339 value += arraySetHash(this .getNotifications());
340 myHashCode = new Integer(value);
341 }
342
343 // return always the same hash code for this instance (immutable)
344 //
345 return myHashCode.intValue();
346 }
347
348 private static <T> int arraySetHash(T[] a) {
349 return new HashSet<T>(Arrays.asList(a)).hashCode();
350 }
351
352 /**
353 * <p>Returns a string representation of this {@code
354 * OpenMBeanInfoSupport} instance.</p>
355 *
356 * <p>The string representation consists of the name of this class
357 * (ie {@code javax.management.openmbean.OpenMBeanInfoSupport}),
358 * the MBean class name, the string representation of infos on
359 * attributes, constructors, operations and notifications of the
360 * described MBean and the string representation of the descriptor.</p>
361 *
362 * <p>As {@code OpenMBeanInfoSupport} instances are immutable, the
363 * string representation for this instance is calculated once, on
364 * the first call to {@code toString}, and then the same value is
365 * returned for subsequent calls.</p>
366 *
367 * @return a string representation of this {@code
368 * OpenMBeanInfoSupport} instance
369 */
370 public String toString() {
371
372 // Calculate the string value if it has not yet been done (ie
373 // 1st call to toString())
374 //
375 if (myToString == null) {
376 myToString = new StringBuilder().append(
377 this .getClass().getName()).append(
378 "(mbean_class_name=").append(this .getClassName())
379 .append(",attributes=").append(
380 Arrays.asList(this .getAttributes())
381 .toString()).append(
382 ",constructors=").append(
383 Arrays.asList(this .getConstructors())
384 .toString()).append(",operations=")
385 .append(
386 Arrays.asList(this .getOperations())
387 .toString()).append(
388 ",notifications=").append(
389 Arrays.asList(this .getNotifications())
390 .toString()).append(",descriptor=")
391 .append(this .getDescriptor()).append(")")
392 .toString();
393 }
394
395 // return always the same string representation for this
396 // instance (immutable)
397 //
398 return myToString;
399 }
400
401 }
|