001: /* JFox, the OpenSource J2EE Application Server
002: *
003: * Copyright (C) 2002 huihoo.org
004: * Distributable under GNU LGPL license
005: * See the GNU Lesser General Public License for more details.
006: */
007:
008: package javax.management.openmbean;
009:
010: import java.io.Serializable;
011: import java.util.HashSet;
012: import java.util.Arrays;
013: import javax.management.MBeanInfo;
014: import javax.management.MBeanAttributeInfo;
015: import javax.management.MBeanConstructorInfo;
016: import javax.management.MBeanOperationInfo;
017: import javax.management.MBeanNotificationInfo;
018:
019: /**
020: * The <tt>OpenMBeanInfoSupport</tt> class describes the management information of an <i>open MBean</i>:
021: * it is a subclass of {@link javax.management.MBeanInfo}, and it implements the {@link OpenMBeanInfo} interface.
022: * Note that an <i>open MBean</i> is recognized as such if its <tt>getMBeanInfo()</tt> method returns an instance of a class
023: * which implements the OpenMBeanInfo interface, typically <tt>OpenMBeanInfoSupport</tt>.
024: *
025: * @author <a href="mailto:young_yy@hotmail.org">Young Yang</a>
026: */
027:
028: public class OpenMBeanInfoSupport extends MBeanInfo implements
029: OpenMBeanInfo, Serializable {
030:
031: private transient Integer myHashCode = null; // As this instance is immutable, these two values
032: private transient String myToString = null; // need only be calculated once.
033:
034: /**
035: * Constructs an <tt>OpenMBeanInfoSupport</tt> instance,
036: * which describes a class of open MBeans with the specified
037: * <var>className</var>, <var>description</var>, <var>openAttributes</var>,
038: * <var>openConstructors</var> , <var>openOperations</var> and <var>notifications</var>.
039: * <p>
040: * The <var>openAttributes</var>, <var>openConstructors</var>,
041: * <var>openOperations</var> and <var>notifications</var>
042: * array parameters are internally copied, so that subsequent changes
043: * to the arrays referenced by these parameters have no effect on this instance.
044: * <p>
045: *
046: *
047: * @param className The fully qualified Java class name of
048: * the open MBean described by this <CODE>OpenMBeanInfoSupport</CODE> instance.
049: *
050: * @param description A human readable description of
051: * the open MBean described by this <CODE>OpenMBeanInfoSupport</CODE> instance.
052: *
053: * @param openAttributes The list of exposed attributes of the described open MBean;
054: * Must be an array of instances of a subclass of <tt>MBeanAttributeInfo</tt>,
055: * typically <tt>OpenMBeanAttributeInfoSupport</tt>.
056: *
057: * @param openConstructors The list of exposed public constructors of the described open MBean;
058: * Must be an array of instances of a subclass of <tt>MBeanConstructorInfo</tt>,
059: * typically <tt>OpenMBeanConstructorInfoSupport</tt>.
060: *
061: * @param openOperations The list of exposed operations of the described open MBean.
062: * Must be an array of instances of a subclass of <tt>MBeanOperationInfo</tt>,
063: * typically <tt>OpenMBeanOperationInfoSupport</tt>.
064: *
065: * @param notifications The list of notifications emitted by the described open MBean.
066: *
067: * @throws ArrayStoreException If <var>openAttributes</var>, <var>openConstructors</var> or <var>openOperations</var>
068: * is not an array of instances of a subclass of <tt>MBeanAttributeInfo</tt>,
069: * <tt>MBeanConstructorInfo</tt> or <tt>MBeanOperationInfo</tt> respectively.
070: */
071: public OpenMBeanInfoSupport(String className, String description,
072: OpenMBeanAttributeInfo[] openAttributes,
073: OpenMBeanConstructorInfo[] openConstructors,
074: OpenMBeanOperationInfo[] openOperations,
075: MBeanNotificationInfo[] notifications) {
076:
077: super (className, description, (openAttributes == null ? null
078: : attributesArrayCopyCast(openAttributes)), // may throw an ArrayStoreException
079: (openConstructors == null ? null
080: : constructorsArrayCopyCast(openConstructors)), // may throw an ArrayStoreException
081: (openOperations == null ? null
082: : operationsArrayCopyCast(openOperations)), // may throw an ArrayStoreException
083: (notifications == null ? null
084: : notificationsArrayCopy(notifications)));
085:
086: }
087:
088: private static MBeanAttributeInfo[] attributesArrayCopyCast(
089: OpenMBeanAttributeInfo[] src) throws ArrayStoreException {
090:
091: MBeanAttributeInfo[] dst = new MBeanAttributeInfo[src.length];
092: System.arraycopy(src, 0, dst, 0, src.length); // may throw an ArrayStoreException
093: return dst;
094: }
095:
096: private static MBeanConstructorInfo[] constructorsArrayCopyCast(
097: OpenMBeanConstructorInfo[] src) throws ArrayStoreException {
098:
099: MBeanConstructorInfo[] dst = new MBeanConstructorInfo[src.length];
100: System.arraycopy(src, 0, dst, 0, src.length); // may throw an ArrayStoreException
101: return dst;
102: }
103:
104: private static MBeanOperationInfo[] operationsArrayCopyCast(
105: OpenMBeanOperationInfo[] src) throws ArrayStoreException {
106:
107: MBeanOperationInfo[] dst = new MBeanOperationInfo[src.length];
108: System.arraycopy(src, 0, dst, 0, src.length); // may throw an ArrayStoreException
109: return dst;
110: }
111:
112: private static MBeanNotificationInfo[] notificationsArrayCopy(
113: MBeanNotificationInfo[] src) {
114:
115: MBeanNotificationInfo[] dst = new MBeanNotificationInfo[src.length];
116: System.arraycopy(src, 0, dst, 0, src.length);
117: return dst;
118: }
119:
120: /* *** Commodity methods from java.lang.Object *** */
121:
122: /**
123: * Compares the specified <var>obj</var> parameter with this <code>OpenMBeanInfoSupport</code> instance for equality.
124: * <p>
125: * Returns <tt>true</tt> if and only if all of the following statements are true:
126: * <ul>
127: * <li><var>obj</var> is non null,</li>
128: * <li><var>obj</var> also implements the <code>OpenMBeanInfo</code> interface,</li>
129: * <li>their class names are equal</li>
130: * <li>their infos on attributes, constructors, operations and notifications are equal</li>
131: * </ul>
132: * This ensures that this <tt>equals</tt> method works properly for <var>obj</var> parameters which are
133: * different implementations of the <code>OpenMBeanInfo</code> interface.
134: * <br>
135: * @param obj the object to be compared for equality with this <code>OpenMBeanInfoSupport</code> instance;
136: *
137: * @return <code>true</code> if the specified object is equal to this <code>OpenMBeanInfoSupport</code> instance.
138: */
139: public boolean equals(Object obj) {
140:
141: // if obj is null, return false
142: //
143: if (obj == null) {
144: return false;
145: }
146:
147: // if obj is not a OpenMBeanInfo, return false
148: //
149: OpenMBeanInfo other;
150: try {
151: other = (OpenMBeanInfo) obj;
152: } catch (ClassCastException e) {
153: return false;
154: }
155:
156: // Now, really test for equality between this OpenMBeanInfo implementation and the other:
157: //
158:
159: // their MBean className should be equal
160: if (!this .getClassName().equals(other.getClassName())) {
161: return false;
162: }
163:
164: // their infos on attributes should be equal (order not significant => equality between sets, not arrays or lists)
165: if (!new HashSet(Arrays.asList(this .getAttributes()))
166: .equals(new HashSet(Arrays
167: .asList(other.getAttributes())))) {
168: return false;
169: }
170:
171: // their infos on constructors should be equal (order not significant => equality between sets, not arrays or lists)
172: if (!new HashSet(Arrays.asList(this .getConstructors()))
173: .equals(new HashSet(Arrays.asList(other
174: .getConstructors())))) {
175: return false;
176: }
177:
178: // their infos on operations should be equal (order not significant => equality between sets, not arrays or lists)
179: if (!new HashSet(Arrays.asList(this .getOperations()))
180: .equals(new HashSet(Arrays
181: .asList(other.getOperations())))) {
182: return false;
183: }
184:
185: // their infos on notifications should be equal (order not significant => equality between sets, not arrays or lists)
186: if (!new HashSet(Arrays.asList(this .getNotifications()))
187: .equals(new HashSet(Arrays.asList(other
188: .getNotifications())))) {
189: return false;
190: }
191:
192: // All tests for equality were successfull
193: //
194: return true;
195: }
196:
197: /**
198: * Returns the hash code value for this <code>OpenMBeanInfoSupport</code> instance.
199: * <p>
200: * The hash code of an <code>OpenMBeanInfoSupport</code> instance is the sum of the hash codes
201: * of all elements of information used in <code>equals</code> comparisons
202: * (ie: its class name, and its infos on attributes, constructors, operations and notifications,
203: * where the hashCode of each of these arrays is calculated by a call to
204: * <tt>new java.util.HashSet(java.util.Arrays.asList(this.getSignature)).hashCode()</tt>).
205: * <p>
206: * This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
207: * for any two <code>OpenMBeanInfoSupport</code> instances <code>t1</code> and <code>t2</code>,
208: * as required by the general contract of the method
209: * {@link <a href="http://java.sun.com/j2se/1.3/docs/api/java/lang/Object.html#hashCode()">
210: * <code>Object.hashCode</code> </a>}.
211: * <p>
212: * However, note that another instance of a class implementing the <code>OpenMBeanInfo</code> interface
213: * may be equal to this <code>OpenMBeanInfoSupport</code> instance as defined by {@link #equals(java.lang.Object)},
214: * but may have a different hash code if it is calculated differently.
215: * <p>
216: * As <code>OpenMBeanInfoSupport</code> instances are immutable, the hash code for this instance is calculated once,
217: * on the first call to <code>hashCode</code>, and then the same value is returned for subsequent calls.
218: *
219: * @return the hash code value for this <code>OpenMBeanInfoSupport</code> instance
220: */
221: public int hashCode() {
222:
223: // Calculate the hash code value if it has not yet been done (ie 1st call to hashCode())
224: //
225: if (myHashCode == null) {
226: int value = 0;
227: value += this .getClassName().hashCode();
228: value += new HashSet(Arrays.asList(this .getAttributes()))
229: .hashCode();
230: value += new HashSet(Arrays.asList(this .getConstructors()))
231: .hashCode();
232: value += new HashSet(Arrays.asList(this .getOperations()))
233: .hashCode();
234: value += new HashSet(Arrays.asList(this .getNotifications()))
235: .hashCode();
236: myHashCode = new Integer(value);
237: }
238:
239: // return always the same hash code for this instance (immutable)
240: //
241: return myHashCode.intValue();
242: }
243:
244: /**
245: * Returns a string representation of this <code>OpenMBeanInfoSupport</code> instance.
246: * <p>
247: * The string representation consists of the name of this class (ie <code>javax.management.openmbean.OpenMBeanInfoSupport</code>),
248: * the MBean class name,
249: * and the string representation of infos on attributes, constructors, operations and notifications of the described MBean.
250: * <p>
251: * As <code>OpenMBeanInfoSupport</code> instances are immutable,
252: * the string representation for this instance is calculated once,
253: * on the first call to <code>toString</code>, and then the same value is returned for subsequent calls.
254: *
255: * @return a string representation of this <code>OpenMBeanInfoSupport</code> instance
256: */
257: public String toString() {
258:
259: // Calculate the hash code value if it has not yet been done (ie 1st call to toString())
260: //
261: if (myToString == null) {
262: myToString = new StringBuffer().append(
263: this .getClass().getName()).append(
264: "(mbean_class_name=").append(this .getClassName())
265: .append(",attributes=").append(
266: Arrays.asList(this .getAttributes())
267: .toString()).append(
268: ",constructors=").append(
269: Arrays.asList(this .getConstructors())
270: .toString()).append(",operations=")
271: .append(
272: Arrays.asList(this .getOperations())
273: .toString()).append(
274: ",notifications=").append(
275: Arrays.asList(this .getNotifications())
276: .toString()).append(")").toString();
277: }
278:
279: // return always the same string representation for this instance (immutable)
280: //
281: return myToString;
282: }
283:
284: }
|