1. /*
  2. * @(#)OpenMBeanInfoSupport.java 3.22 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.management.openmbean;
  8. // java import
  9. //
  10. import java.io.Serializable;
  11. import java.util.Arrays;
  12. import java.util.HashSet;
  13. // jmx import
  14. //
  15. import javax.management.MBeanInfo;
  16. import javax.management.MBeanAttributeInfo;
  17. import javax.management.MBeanOperationInfo;
  18. import javax.management.MBeanConstructorInfo;
  19. import javax.management.MBeanNotificationInfo;
  20. /**
  21. * The <tt>OpenMBeanInfoSupport</tt> class describes the management information of an <i>open MBean</i>:
  22. * it is a subclass of {@link javax.management.MBeanInfo}, and it implements the {@link OpenMBeanInfo} interface.
  23. * Note that an <i>open MBean</i> is recognized as such if its <tt>getMBeanInfo()</tt> method returns an instance of a class
  24. * which implements the OpenMBeanInfo interface, typically <tt>OpenMBeanInfoSupport</tt>.
  25. *
  26. * @version 3.22 03/12/19
  27. * @author Sun Microsystems, Inc.
  28. *
  29. * @since 1.5
  30. * @since.unbundled JMX 1.1
  31. */
  32. public class OpenMBeanInfoSupport
  33. extends MBeanInfo
  34. implements OpenMBeanInfo, Serializable {
  35. /* Serial version */
  36. static final long serialVersionUID = 4349395935420511492L;
  37. private transient Integer myHashCode = null; // As this instance is immutable, these two values
  38. private transient String myToString = null; // need only be calculated once.
  39. /**
  40. * Constructs an <tt>OpenMBeanInfoSupport</tt> instance,
  41. * which describes a class of open MBeans with the specified
  42. * <var>className</var>, <var>description</var>, <var>openAttributes</var>,
  43. * <var>openConstructors</var> , <var>openOperations</var> and <var>notifications</var>.
  44. * <p>
  45. * The <var>openAttributes</var>, <var>openConstructors</var>,
  46. * <var>openOperations</var> and <var>notifications</var>
  47. * array parameters are internally copied, so that subsequent changes
  48. * to the arrays referenced by these parameters have no effect on this instance.
  49. * <p>
  50. *
  51. *
  52. * @param className The fully qualified Java class name of
  53. * the open MBean described by this <CODE>OpenMBeanInfoSupport</CODE> instance.
  54. *
  55. * @param description A human readable description of
  56. * the open MBean described by this <CODE>OpenMBeanInfoSupport</CODE> instance.
  57. *
  58. * @param openAttributes The list of exposed attributes of the described open MBean;
  59. * Must be an array of instances of a subclass of <tt>MBeanAttributeInfo</tt>,
  60. * typically <tt>OpenMBeanAttributeInfoSupport</tt>.
  61. *
  62. * @param openConstructors The list of exposed public constructors of the described open MBean;
  63. * Must be an array of instances of a subclass of <tt>MBeanConstructorInfo</tt>,
  64. * typically <tt>OpenMBeanConstructorInfoSupport</tt>.
  65. *
  66. * @param openOperations The list of exposed operations of the described open MBean.
  67. * Must be an array of instances of a subclass of <tt>MBeanOperationInfo</tt>,
  68. * typically <tt>OpenMBeanOperationInfoSupport</tt>.
  69. *
  70. * @param notifications The list of notifications emitted by the described open MBean.
  71. *
  72. * @throws ArrayStoreException If <var>openAttributes</var>, <var>openConstructors</var> or <var>openOperations</var>
  73. * is not an array of instances of a subclass of <tt>MBeanAttributeInfo</tt>,
  74. * <tt>MBeanConstructorInfo</tt> or <tt>MBeanOperationInfo</tt> respectively.
  75. */
  76. public OpenMBeanInfoSupport(String className,
  77. String description,
  78. OpenMBeanAttributeInfo[] openAttributes,
  79. OpenMBeanConstructorInfo[] openConstructors,
  80. OpenMBeanOperationInfo[] openOperations,
  81. MBeanNotificationInfo[] notifications) {
  82. super(className,
  83. description,
  84. ( openAttributes == null ? null : attributesArrayCopyCast(openAttributes) ), // may throw an ArrayStoreException
  85. ( openConstructors == null ? null : constructorsArrayCopyCast(openConstructors) ), // may throw an ArrayStoreException
  86. ( openOperations == null ? null : operationsArrayCopyCast(openOperations) ), // may throw an ArrayStoreException
  87. ( notifications == null ? null : notificationsArrayCopy(notifications) ));
  88. }
  89. private static MBeanAttributeInfo[] attributesArrayCopyCast(OpenMBeanAttributeInfo[] src) throws ArrayStoreException {
  90. MBeanAttributeInfo[] dst = new MBeanAttributeInfo[src.length];
  91. System.arraycopy(src, 0, dst, 0, src.length); // may throw an ArrayStoreException
  92. return dst;
  93. }
  94. private static MBeanConstructorInfo[] constructorsArrayCopyCast(OpenMBeanConstructorInfo[] src) throws ArrayStoreException {
  95. MBeanConstructorInfo[] dst = new MBeanConstructorInfo[src.length];
  96. System.arraycopy(src, 0, dst, 0, src.length); // may throw an ArrayStoreException
  97. return dst;
  98. }
  99. private static MBeanOperationInfo[] operationsArrayCopyCast(OpenMBeanOperationInfo[] src) throws ArrayStoreException {
  100. MBeanOperationInfo[] dst = new MBeanOperationInfo[src.length];
  101. System.arraycopy(src, 0, dst, 0, src.length); // may throw an ArrayStoreException
  102. return dst;
  103. }
  104. private static MBeanNotificationInfo[] notificationsArrayCopy(MBeanNotificationInfo[] src) {
  105. MBeanNotificationInfo[] dst = new MBeanNotificationInfo[src.length];
  106. System.arraycopy(src, 0, dst, 0, src.length);
  107. return dst;
  108. }
  109. /* *** Commodity methods from java.lang.Object *** */
  110. /**
  111. * Compares the specified <var>obj</var> parameter with this <code>OpenMBeanInfoSupport</code> instance for equality.
  112. * <p>
  113. * Returns <tt>true</tt> if and only if all of the following statements are true:
  114. * <ul>
  115. * <li><var>obj</var> is non null,</li>
  116. * <li><var>obj</var> also implements the <code>OpenMBeanInfo</code> interface,</li>
  117. * <li>their class names are equal</li>
  118. * <li>their infos on attributes, constructors, operations and notifications are equal</li>
  119. * </ul>
  120. * This ensures that this <tt>equals</tt> method works properly for <var>obj</var> parameters which are
  121. * different implementations of the <code>OpenMBeanInfo</code> interface.
  122. * <br> 
  123. * @param obj the object to be compared for equality with this <code>OpenMBeanInfoSupport</code> instance;
  124. *
  125. * @return <code>true</code> if the specified object is equal to this <code>OpenMBeanInfoSupport</code> instance.
  126. */
  127. public boolean equals(Object obj) {
  128. // if obj is null, return false
  129. //
  130. if (obj == null) {
  131. return false;
  132. }
  133. // if obj is not a OpenMBeanInfo, return false
  134. //
  135. OpenMBeanInfo other;
  136. try {
  137. other = (OpenMBeanInfo) obj;
  138. } catch (ClassCastException e) {
  139. return false;
  140. }
  141. // Now, really test for equality between this OpenMBeanInfo implementation and the other:
  142. //
  143. // their MBean className should be equal
  144. if ( ! this.getClassName().equals(other.getClassName()) ) {
  145. return false;
  146. }
  147. // their infos on attributes should be equal (order not significant => equality between sets, not arrays or lists)
  148. if ( ! new HashSet(Arrays.asList(this.getAttributes())).equals(new HashSet(Arrays.asList(other.getAttributes()))) ) {
  149. return false;
  150. }
  151. // their infos on constructors should be equal (order not significant => equality between sets, not arrays or lists)
  152. if ( ! new HashSet(Arrays.asList(this.getConstructors())).equals(new HashSet(Arrays.asList(other.getConstructors()))) ) {
  153. return false;
  154. }
  155. // their infos on operations should be equal (order not significant => equality between sets, not arrays or lists)
  156. if ( ! new HashSet(Arrays.asList(this.getOperations())).equals(new HashSet(Arrays.asList(other.getOperations()))) ) {
  157. return false;
  158. }
  159. // their infos on notifications should be equal (order not significant => equality between sets, not arrays or lists)
  160. if ( ! new HashSet(Arrays.asList(this.getNotifications())).equals(new HashSet(Arrays.asList(other.getNotifications()))) ) {
  161. return false;
  162. }
  163. // All tests for equality were successfull
  164. //
  165. return true;
  166. }
  167. /**
  168. * Returns the hash code value for this <code>OpenMBeanInfoSupport</code> instance.
  169. * <p>
  170. * The hash code of an <code>OpenMBeanInfoSupport</code> instance is the sum of the hash codes
  171. * of all elements of information used in <code>equals</code> comparisons
  172. * (ie: its class name, and its infos on attributes, constructors, operations and notifications,
  173. * where the hashCode of each of these arrays is calculated by a call to
  174. * <tt>new java.util.HashSet(java.util.Arrays.asList(this.getSignature)).hashCode()</tt>).
  175. * <p>
  176. * This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
  177. * for any two <code>OpenMBeanInfoSupport</code> instances <code>t1</code> and <code>t2</code>,
  178. * as required by the general contract of the method
  179. * {@link Object#hashCode() Object.hashCode()}.
  180. * <p>
  181. * However, note that another instance of a class implementing the <code>OpenMBeanInfo</code> interface
  182. * may be equal to this <code>OpenMBeanInfoSupport</code> instance as defined by {@link #equals(java.lang.Object)},
  183. * but may have a different hash code if it is calculated differently.
  184. * <p>
  185. * As <code>OpenMBeanInfoSupport</code> instances are immutable, the hash code for this instance is calculated once,
  186. * on the first call to <code>hashCode</code>, and then the same value is returned for subsequent calls.
  187. *
  188. * @return the hash code value for this <code>OpenMBeanInfoSupport</code> instance
  189. */
  190. public int hashCode() {
  191. // Calculate the hash code value if it has not yet been done (ie 1st call to hashCode())
  192. //
  193. if (myHashCode == null) {
  194. int value = 0;
  195. value += this.getClassName().hashCode();
  196. value += new HashSet(Arrays.asList(this.getAttributes())).hashCode();
  197. value += new HashSet(Arrays.asList(this.getConstructors())).hashCode();
  198. value += new HashSet(Arrays.asList(this.getOperations())).hashCode();
  199. value += new HashSet(Arrays.asList(this.getNotifications())).hashCode();
  200. myHashCode = new Integer(value);
  201. }
  202. // return always the same hash code for this instance (immutable)
  203. //
  204. return myHashCode.intValue();
  205. }
  206. /**
  207. * Returns a string representation of this <code>OpenMBeanInfoSupport</code> instance.
  208. * <p>
  209. * The string representation consists of the name of this class (ie <code>javax.management.openmbean.OpenMBeanInfoSupport</code>),
  210. * the MBean class name,
  211. * and the string representation of infos on attributes, constructors, operations and notifications of the described MBean.
  212. * <p>
  213. * As <code>OpenMBeanInfoSupport</code> instances are immutable,
  214. * the string representation for this instance is calculated once,
  215. * on the first call to <code>toString</code>, and then the same value is returned for subsequent calls.
  216. *
  217. * @return a string representation of this <code>OpenMBeanInfoSupport</code> instance
  218. */
  219. public String toString() {
  220. // Calculate the hash code value if it has not yet been done (ie 1st call to toString())
  221. //
  222. if (myToString == null) {
  223. myToString = new StringBuffer()
  224. .append(this.getClass().getName())
  225. .append("(mbean_class_name=")
  226. .append(this.getClassName())
  227. .append(",attributes=")
  228. .append(Arrays.asList(this.getAttributes()).toString())
  229. .append(",constructors=")
  230. .append(Arrays.asList(this.getConstructors()).toString())
  231. .append(",operations=")
  232. .append(Arrays.asList(this.getOperations()).toString())
  233. .append(",notifications=")
  234. .append(Arrays.asList(this.getNotifications()).toString())
  235. .append(")")
  236. .toString();
  237. }
  238. // return always the same string representation for this instance (immutable)
  239. //
  240. return myToString;
  241. }
  242. }