001    /* MBeanInfo.java -- Information about a management bean.
002       Copyright (C) 2006 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    package javax.management;
039    
040    import java.io.Serializable;
041    
042    import 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     */
085    public 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    }