001/* MBeanInfo.java -- Information about a management bean.
002   Copyright (C) 2006 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038package javax.management;
039
040import java.io.Serializable;
041
042import java.util.Arrays;
043
044/**
045 * <p>
046 * Describes the interface of a management bean.  This allows
047 * the user to access the bean dynamically, without knowing
048 * the details of any of its attributes, operations,
049 * constructors or notifications beforehand.  The information
050 * is immutable as standard.  Of course, subclasses may change
051 * this, but this behaviour is not recommended.
052 * </p>
053 * <p>
054 * The contents of this class, for standard management beans,
055 * are dynamically compiled using reflection.
056 * {@link #getClassName()} and {@link #getConstructors()}
057 * return the name of the class and its constructors, respectively.
058 * This is much the same as could be obtained by reflection on the
059 * bean.  {@link #getAttributes()} and {@link #getOperations()},
060 * however, do something more in splitting the methods of the
061 * class into two sets.  Those of the form, <code>getXXX</code>,
062 * <code>setXXX</code> and <code>isXXX</code> are taken to be
063 * the accessors and mutators of a series of attributes, with
064 * <code>XXX</code> being the attribute name.  These are returned
065 * by {@link getAttributes()} and the {@link Attribute} class can
066 * be used to manipulate them.  The remaining methods are classified
067 * as operations and returned by {@link getOperations()}.
068 * </p>
069 * <p>
070 * Beans can also broadcast notifications.  If the bean provides this
071 * facility, by implementing the {@link NotificationBroadcaster}
072 * interface, then an array of {@link MBeanNotificationInfo} objects
073 * may be obtained from {@link #getNotifications()}, which describe
074 * the notifications emitted.
075 * </p>
076 * <p>
077 * Model management beans and open management beans also supply an
078 * instance of this class, as part of implementing the
079 * {@link DynamicMBean#getMBeanInfo()} method of {@link DynamicMBean}.
080 * </p>
081 *
082 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
083 * @since 1.5
084 */
085public class MBeanInfo
086  implements Cloneable, Serializable
087{
088
089  /**
090   * Compatible with JDK 1.5
091   */
092  private static final long serialVersionUID = -6451021435135161911L;
093
094  /**
095   * A description of the bean.
096   *
097   * @serial The bean's description.
098   */
099  private String description;
100
101  /**
102   * The class name of the management bean.
103   *
104   * @serial The bean's class name.
105   */
106  private String className;
107
108  /**
109   * Descriptions of the attributes provided by the bean.
110   */
111  private MBeanAttributeInfo[] attributes;
112
113  /**
114   * Descriptions of the operations provided by the bean.
115   */
116  private MBeanOperationInfo[] operations;
117
118  /**
119   * Descriptions of the bean's constructors.
120   */
121  private MBeanConstructorInfo[] constructors;
122
123  /**
124   * Descriptions of the notifications emitted by the bean.
125   *
126   * @serial The bean's notifications.
127   */
128  private MBeanNotificationInfo[] notifications;
129
130  /**
131   * The <code>toString()</code> result of this instance.
132   */
133  private transient String string;
134
135  /**
136   * Constructs a new {@link MBeanInfo} using the supplied
137   * class name and description with the given attributes,
138   * operations, constructors and notifications.  The class
139   * name does not have to actually specify a valid class that
140   * can be loaded by the MBean server or class loader; it merely
141   * has to be a syntactically correct class name.  Any of the
142   * arrays may be <code>null</code>; this will be treated as if
143   * an empty array was supplied.  A copy of the arrays is
144   * taken, so later changes have no effect.
145   *
146   * @param name the name of the class this instance describes.
147   * @param desc a description of the bean.
148   * @param attribs the attribute descriptions for the bean,
149   *                or <code>null</code>.
150   * @param cons the constructor descriptions for the bean,
151   *             or <code>null</code>.
152   * @param ops the operation descriptions for the bean,
153   *            or <code>null</code>.
154   * @param notifs the notification descriptions for the bean,
155   *               or <code>null</code>.
156   */
157  public MBeanInfo(String name, String desc, MBeanAttributeInfo[] attribs,
158                   MBeanConstructorInfo[] cons, MBeanOperationInfo[] ops,
159                   MBeanNotificationInfo[] notifs)
160  {
161    className = name;
162    description = desc;
163
164    if (attribs == null)
165      attributes = new MBeanAttributeInfo[0];
166    else
167      attributes = (MBeanAttributeInfo[]) attribs.clone();
168
169    if (cons == null)
170      constructors = new MBeanConstructorInfo[0];
171    else
172      constructors = (MBeanConstructorInfo[]) cons.clone();
173
174    if (ops == null)
175      operations = new MBeanOperationInfo[0];
176    else
177      operations = (MBeanOperationInfo[]) ops.clone();
178
179    if (notifs == null)
180      notifications = new MBeanNotificationInfo[0];
181    else
182      notifications = (MBeanNotificationInfo[]) notifs.clone();
183  }
184
185  /**
186   * Returns a shallow clone of the information.  This is
187   * simply a new copy of each string and a clone
188   * of each array, which still references the same objects,
189   * as obtained by the {@link Object} implementation of
190   * {@link Object#clone()}.  As the fields can not be
191   * changed, this method is only really of interest to
192   * subclasses which may add new mutable fields or make
193   * the existing ones mutable.
194   *
195   * @return a shallow clone of this {@link MBeanInfo}.
196   */
197  public Object clone()
198  {
199    MBeanInfo clone = null;
200    try
201      {
202        clone = (MBeanInfo) super.clone();
203      }
204    catch (CloneNotSupportedException e)
205      {
206        /* This won't happen as we implement Cloneable */
207      }
208    return clone;
209  }
210
211  /**
212   * Compares this feature with the supplied object.  This returns
213   * true iff the object is an instance of {@link MBeanInfo} and
214   * {@link Object#equals()} returns true for a comparison of the
215   * class name and description, and the arrays each contain the same
216   * elements in the same order (but one may be longer than the
217   * other).
218   *
219   * @param obj the object to compare.
220   * @return true if the object is a {@link MBeanInfo}
221   *         instance,
222   *         <code>className.equals(object.getClassName())</code>,
223   *         <code>description.equals(object.getDescription())</code>
224   *         and the corresponding elements of the arrays are
225   *         equal.
226   */
227  public boolean equals(Object obj)
228  {
229    if (!(obj instanceof MBeanInfo))
230      return false;
231    if (!(super.equals(obj)))
232      return false;
233    MBeanInfo o = (MBeanInfo) obj;
234    MBeanAttributeInfo[] attr = o.getAttributes();
235    for (int a = 0; a < attributes.length; ++a)
236      {
237        if (a == attr.length)
238          return true;
239        if (!(attributes[a].equals(attr[a])))
240          return false;
241      }
242    MBeanConstructorInfo[] cons = o.getConstructors();
243    for (int a = 0; a < constructors.length; ++a)
244      {
245        if (a == cons.length)
246          return true;
247        if (!(constructors[a].equals(cons[a])))
248          return false;
249      }
250    MBeanOperationInfo[] ops = o.getOperations();
251    for (int a = 0; a < operations.length; ++a)
252      {
253        if (a == ops.length)
254          return true;
255        if (!(operations[a].equals(ops[a])))
256          return false;
257      }
258    MBeanNotificationInfo[] notifs = o.getNotifications();
259    for (int a = 0; a < notifications.length; ++a)
260      {
261        if (a == notifs.length)
262          return true;
263        if (!(notifications[a].equals(notifs[a])))
264          return false;
265      }
266    return (className.equals(o.getClassName()) &&
267            description.equals(o.getDescription()));
268  }
269
270  /**
271   * Returns descriptions of each of the attributes provided
272   * by this management bean.  The returned value is a shallow
273   * copy of the attribute array maintained by this instance.
274   * Hence, changing the elements of the returned array will not
275   * affect the attribute array, and the elements (instances
276   * of the {@link MBeanAttributeInfo} class) are immutable.
277   *
278   * @return an array of {@link MBeanAttributeInfo} objects,
279   *         representing the attributes emitted by this
280   *         management bean.
281   */
282  public MBeanAttributeInfo[] getAttributes()
283  {
284    return (MBeanAttributeInfo[]) attributes.clone();
285  }
286
287  /**
288   * Returns the class name of the management bean.
289   *
290   * @return the bean's class name.
291   */
292  public String getClassName()
293  {
294    return className;
295  }
296
297  /**
298   * Returns descriptions of each of the constructors provided
299   * by this management bean.  The returned value is a shallow
300   * copy of the constructor array maintained by this instance.
301   * Hence, changing the elements of the returned array will not
302   * affect the constructor array, and the elements (instances
303   * of the {@link MBeanConstructorInfo} class) are immutable.
304   *
305   * @return an array of {@link MBeanConstructorInfo} objects,
306   *         representing the constructors emitted by this
307   *         management bean.
308   */
309  public MBeanConstructorInfo[] getConstructors()
310  {
311    return (MBeanConstructorInfo[]) constructors.clone();
312  }
313
314  /**
315   * Returns a description of the management bean.
316   *
317   * @return the bean's description.
318   */
319  public String getDescription()
320  {
321    return description;
322  }
323
324  /**
325   * Returns descriptions of each of the notifications emitted
326   * by this management bean.  The returned value is a shallow
327   * copy of the notification array maintained by this instance.
328   * Hence, changing the elements of the returned array will not
329   * affect the notification array, and the elements (instances
330   * of the {@link MBeanNotificationInfo} class) are immutable.
331   *
332   * @return an array of {@link MBeanNotificationInfo} objects,
333   *         representing the notifications emitted by this
334   *         management bean.
335   */
336  public MBeanNotificationInfo[] getNotifications()
337  {
338    return (MBeanNotificationInfo[]) notifications.clone();
339  }
340
341  /**
342   * Returns descriptions of each of the operations provided
343   * by this management bean.  The returned value is a shallow
344   * copy of the operation array maintained by this instance.
345   * Hence, changing the elements of the returned array will not
346   * affect the operation array, and the elements (instances
347   * of the {@link MBeanOperationInfo} class) are immutable.
348   *
349   * @return an array of {@link MBeanOperationInfo} objects,
350   *         representing the operations emitted by this
351   *         management bean.
352   */
353  public MBeanOperationInfo[] getOperations()
354  {
355    return (MBeanOperationInfo[]) operations.clone();
356  }
357
358  /**
359   * Returns the hashcode of the information as the sum of the
360   * hashcode of the classname, description and each array.
361   *
362   * @return the hashcode of the information.
363   */
364  public int hashCode()
365  {
366    return className.hashCode() + description.hashCode()
367      + Arrays.hashCode(attributes) + Arrays.hashCode(constructors)
368      + Arrays.hashCode(operations) + Arrays.hashCode(notifications);
369  }
370
371  /**
372   * <p>
373   * Returns a textual representation of this instance.  This
374   * is constructed using the class name
375   * (<code>javax.management.MBeanInfo</code>),
376   * the name and description of the bean and the contents
377   * of the four arrays.
378   * </p>
379   * <p>
380   * As instances of this class are immutable, the return value
381   * is computed just once for each instance and reused
382   * throughout its life.
383   * </p>
384   *
385   * @return a @link{java.lang.String} instance representing
386   *         the instance in textual form.
387   */
388  public String toString()
389  {
390    if (string == null)
391      string = getClass().getName()
392        + "[name=" + className
393        + ",desc=" + description
394        + ",attributes=" + Arrays.toString(attributes)
395        + ",constructors=" + Arrays.toString(constructors)
396        + ",operations=" + Arrays.toString(operations)
397        + ",notifications=" + Arrays.toString(notifications)
398        + "]";
399    return string;
400  }
401
402}