Save This Page
Home » openjdk-7 » javax » management » [javadoc | source]
    1   /*
    2    * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.management;
   27   
   28   import java.io.IOException;
   29   import java.io.StreamCorruptedException;
   30   import java.io.Serializable;
   31   import java.io.ObjectOutputStream;
   32   import java.io.ObjectInputStream;
   33   import java.lang.reflect.Method;
   34   import java.util.Arrays;
   35   import java.util.Map;
   36   import java.util.WeakHashMap;
   37   import java.security.AccessController;
   38   import java.security.PrivilegedAction;
   39   
   40   import static javax.management.ImmutableDescriptor.nonNullDescriptor;
   41   
   42   /**
   43    * <p>Describes the management interface exposed by an MBean; that is,
   44    * the set of attributes and operations which are available for
   45    * management operations.  Instances of this class are immutable.
   46    * Subclasses may be mutable but this is not recommended.</p>
   47    *
   48    * <p>The contents of the <code>MBeanInfo</code> for a Dynamic MBean
   49    * are determined by its {@link DynamicMBean#getMBeanInfo
   50    * getMBeanInfo()} method.  This includes Open MBeans and Model
   51    * MBeans, which are kinds of Dynamic MBeans.</p>
   52    *
   53    * <p>The contents of the <code>MBeanInfo</code> for a Standard MBean
   54    * are determined by the MBean server as follows:</p>
   55    *
   56    * <ul>
   57    *
   58    * <li>{@link #getClassName()} returns the Java class name of the MBean
   59    * object;
   60    *
   61    * <li>{@link #getConstructors()} returns the list of all public
   62    * constructors in that object;
   63    *
   64    * <li>{@link #getAttributes()} returns the list of all attributes
   65    * whose existence is deduced from the presence in the MBean interface
   66    * of a <code>get<i>Name</i></code>, <code>is<i>Name</i></code>, or
   67    * <code>set<i>Name</i></code> method that conforms to the conventions
   68    * for Standard MBeans;
   69    *
   70    * <li>{@link #getOperations()} returns the list of all methods in
   71    * the MBean interface that do not represent attributes;
   72    *
   73    * <li>{@link #getNotifications()} returns an empty array if the MBean
   74    * does not implement the {@link NotificationBroadcaster} interface,
   75    * otherwise the result of calling {@link
   76    * NotificationBroadcaster#getNotificationInfo()} on it;
   77    *
   78    * <li>{@link #getDescriptor()} returns a descriptor containing the contents
   79    * of any descriptor annotations in the MBean interface.
   80    *
   81    * </ul>
   82    *
   83    * <p>The description returned by {@link #getDescription()} and the
   84    * descriptions of the contained attributes and operations are determined
   85    * by the corresponding <!-- link here --> Description annotations if any;
   86    * otherwise their contents are not specified.</p>
   87    *
   88    * <p>The remaining details of the <code>MBeanInfo</code> for a
   89    * Standard MBean are not specified.  This includes the description of
   90    * any contained constructors, and notifications; the names
   91    * of parameters to constructors and operations; and the descriptions of
   92    * constructor parameters.</p>
   93    *
   94    * @since 1.5
   95    */
   96   public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
   97   
   98       /* Serial version */
   99       static final long serialVersionUID = -6451021435135161911L;
  100   
  101       /**
  102        * @serial The Descriptor for the MBean.  This field
  103        * can be null, which is equivalent to an empty Descriptor.
  104        */
  105       private transient Descriptor descriptor;
  106   
  107       /**
  108        * @serial The human readable description of the class.
  109        */
  110       private final String description;
  111   
  112       /**
  113        * @serial The MBean qualified name.
  114        */
  115       private final String className;
  116   
  117       /**
  118        * @serial The MBean attribute descriptors.
  119        */
  120       private final MBeanAttributeInfo[] attributes;
  121   
  122       /**
  123        * @serial The MBean operation descriptors.
  124        */
  125       private final MBeanOperationInfo[] operations;
  126   
  127        /**
  128        * @serial The MBean constructor descriptors.
  129        */
  130       private final MBeanConstructorInfo[] constructors;
  131   
  132       /**
  133        * @serial The MBean notification descriptors.
  134        */
  135       private final MBeanNotificationInfo[] notifications;
  136   
  137       private transient int hashCode;
  138   
  139       /**
  140        * <p>True if this class is known not to override the array-valued
  141        * getters of MBeanInfo.  Obviously true for MBeanInfo itself, and true
  142        * for a subclass where we succeed in reflecting on the methods
  143        * and discover they are not overridden.</p>
  144        *
  145        * <p>The purpose of this variable is to avoid cloning the arrays
  146        * when doing operations like {@link #equals} where we know they
  147        * will not be changed.  If a subclass overrides a getter, we
  148        * cannot access the corresponding array directly.</p>
  149        */
  150       private final transient boolean arrayGettersSafe;
  151   
  152       /**
  153        * Constructs an <CODE>MBeanInfo</CODE>.
  154        *
  155        * @param className The name of the Java class of the MBean described
  156        * by this <CODE>MBeanInfo</CODE>.  This value may be any
  157        * syntactically legal Java class name.  It does not have to be a
  158        * Java class known to the MBean server or to the MBean's
  159        * ClassLoader.  If it is a Java class known to the MBean's
  160        * ClassLoader, it is recommended but not required that the
  161        * class's public methods include those that would appear in a
  162        * Standard MBean implementing the attributes and operations in
  163        * this MBeanInfo.
  164        * @param description A human readable description of the MBean (optional).
  165        * @param attributes The list of exposed attributes of the MBean.
  166        * This may be null with the same effect as a zero-length array.
  167        * @param constructors The list of public constructors of the
  168        * MBean.  This may be null with the same effect as a zero-length
  169        * array.
  170        * @param operations The list of operations of the MBean.  This
  171        * may be null with the same effect as a zero-length array.
  172        * @param notifications The list of notifications emitted.  This
  173        * may be null with the same effect as a zero-length array.
  174        */
  175       public MBeanInfo(String className,
  176                        String description,
  177                        MBeanAttributeInfo[] attributes,
  178                        MBeanConstructorInfo[] constructors,
  179                        MBeanOperationInfo[] operations,
  180                        MBeanNotificationInfo[] notifications)
  181               throws IllegalArgumentException {
  182           this(className, description, attributes, constructors, operations,
  183                notifications, null);
  184       }
  185   
  186       /**
  187        * Constructs an <CODE>MBeanInfo</CODE>.
  188        *
  189        * @param className The name of the Java class of the MBean described
  190        * by this <CODE>MBeanInfo</CODE>.  This value may be any
  191        * syntactically legal Java class name.  It does not have to be a
  192        * Java class known to the MBean server or to the MBean's
  193        * ClassLoader.  If it is a Java class known to the MBean's
  194        * ClassLoader, it is recommended but not required that the
  195        * class's public methods include those that would appear in a
  196        * Standard MBean implementing the attributes and operations in
  197        * this MBeanInfo.
  198        * @param description A human readable description of the MBean (optional).
  199        * @param attributes The list of exposed attributes of the MBean.
  200        * This may be null with the same effect as a zero-length array.
  201        * @param constructors The list of public constructors of the
  202        * MBean.  This may be null with the same effect as a zero-length
  203        * array.
  204        * @param operations The list of operations of the MBean.  This
  205        * may be null with the same effect as a zero-length array.
  206        * @param notifications The list of notifications emitted.  This
  207        * may be null with the same effect as a zero-length array.
  208        * @param descriptor The descriptor for the MBean.  This may be null
  209        * which is equivalent to an empty descriptor.
  210        *
  211        * @since 1.6
  212        */
  213       public MBeanInfo(String className,
  214                        String description,
  215                        MBeanAttributeInfo[] attributes,
  216                        MBeanConstructorInfo[] constructors,
  217                        MBeanOperationInfo[] operations,
  218                        MBeanNotificationInfo[] notifications,
  219                        Descriptor descriptor)
  220               throws IllegalArgumentException {
  221   
  222           this.className = className;
  223   
  224           this.description = description;
  225   
  226           if (attributes == null)
  227               attributes = MBeanAttributeInfo.NO_ATTRIBUTES;
  228           this.attributes = attributes;
  229   
  230           if (operations == null)
  231               operations = MBeanOperationInfo.NO_OPERATIONS;
  232           this.operations = operations;
  233   
  234           if (constructors == null)
  235               constructors = MBeanConstructorInfo.NO_CONSTRUCTORS;
  236           this.constructors = constructors;
  237   
  238           if (notifications == null)
  239               notifications = MBeanNotificationInfo.NO_NOTIFICATIONS;
  240           this.notifications = notifications;
  241   
  242           if (descriptor == null)
  243               descriptor = ImmutableDescriptor.EMPTY_DESCRIPTOR;
  244           this.descriptor = descriptor;
  245   
  246           this.arrayGettersSafe =
  247                   arrayGettersSafe(this.getClass(), MBeanInfo.class);
  248       }
  249   
  250       /**
  251        * <p>Returns a shallow clone of this instance.
  252        * The clone is obtained by simply calling <tt>super.clone()</tt>,
  253        * thus calling the default native shallow cloning mechanism
  254        * implemented by <tt>Object.clone()</tt>.
  255        * No deeper cloning of any internal field is made.</p>
  256        *
  257        * <p>Since this class is immutable, the clone method is chiefly of
  258        * interest to subclasses.</p>
  259        */
  260        public Object clone () {
  261            try {
  262                return super.clone() ;
  263            } catch (CloneNotSupportedException e) {
  264                // should not happen as this class is cloneable
  265                return null;
  266            }
  267        }
  268   
  269   
  270       /**
  271        * Returns the name of the Java class of the MBean described by
  272        * this <CODE>MBeanInfo</CODE>.
  273        *
  274        * @return the class name.
  275        */
  276       public String getClassName()  {
  277           return className;
  278       }
  279   
  280       /**
  281        * Returns a human readable description of the MBean.
  282        *
  283        * @return the description.
  284        */
  285       public String getDescription()  {
  286           return description;
  287       }
  288   
  289       /**
  290        * Returns the list of attributes exposed for management.
  291        * Each attribute is described by an <CODE>MBeanAttributeInfo</CODE> object.
  292        *
  293        * The returned array is a shallow copy of the internal array,
  294        * which means that it is a copy of the internal array of
  295        * references to the <CODE>MBeanAttributeInfo</CODE> objects
  296        * but that each referenced <CODE>MBeanAttributeInfo</CODE> object is not copied.
  297        *
  298        * @return  An array of <CODE>MBeanAttributeInfo</CODE> objects.
  299        */
  300       public MBeanAttributeInfo[] getAttributes()   {
  301           MBeanAttributeInfo[] as = nonNullAttributes();
  302           if (as.length == 0)
  303               return as;
  304           else
  305               return as.clone();
  306       }
  307   
  308       private MBeanAttributeInfo[] fastGetAttributes() {
  309           if (arrayGettersSafe)
  310               return nonNullAttributes();
  311           else
  312               return getAttributes();
  313       }
  314   
  315       /**
  316        * Return the value of the attributes field, or an empty array if
  317        * the field is null.  This can't happen with a
  318        * normally-constructed instance of this class, but can if the
  319        * instance was deserialized from another implementation that
  320        * allows the field to be null.  It would be simpler if we enforced
  321        * the class invariant that these fields cannot be null by writing
  322        * a readObject() method, but that would require us to define the
  323        * various array fields as non-final, which is annoying because
  324        * conceptually they are indeed final.
  325        */
  326       private MBeanAttributeInfo[] nonNullAttributes() {
  327           return (attributes == null) ?
  328               MBeanAttributeInfo.NO_ATTRIBUTES : attributes;
  329       }
  330   
  331       /**
  332        * Returns the list of operations  of the MBean.
  333        * Each operation is described by an <CODE>MBeanOperationInfo</CODE> object.
  334        *
  335        * The returned array is a shallow copy of the internal array,
  336        * which means that it is a copy of the internal array of
  337        * references to the <CODE>MBeanOperationInfo</CODE> objects
  338        * but that each referenced <CODE>MBeanOperationInfo</CODE> object is not copied.
  339        *
  340        * @return  An array of <CODE>MBeanOperationInfo</CODE> objects.
  341        */
  342       public MBeanOperationInfo[] getOperations()  {
  343           MBeanOperationInfo[] os = nonNullOperations();
  344           if (os.length == 0)
  345               return os;
  346           else
  347               return os.clone();
  348       }
  349   
  350       private MBeanOperationInfo[] fastGetOperations() {
  351           if (arrayGettersSafe)
  352               return nonNullOperations();
  353           else
  354               return getOperations();
  355       }
  356   
  357       private MBeanOperationInfo[] nonNullOperations() {
  358           return (operations == null) ?
  359               MBeanOperationInfo.NO_OPERATIONS : operations;
  360       }
  361   
  362       /**
  363        * <p>Returns the list of the public constructors of the MBean.
  364        * Each constructor is described by an
  365        * <CODE>MBeanConstructorInfo</CODE> object.</p>
  366        *
  367        * <p>The returned array is a shallow copy of the internal array,
  368        * which means that it is a copy of the internal array of
  369        * references to the <CODE>MBeanConstructorInfo</CODE> objects but
  370        * that each referenced <CODE>MBeanConstructorInfo</CODE> object
  371        * is not copied.</p>
  372        *
  373        * <p>The returned list is not necessarily exhaustive.  That is,
  374        * the MBean may have a public constructor that is not in the
  375        * list.  In this case, the MBean server can construct another
  376        * instance of this MBean's class using that constructor, even
  377        * though it is not listed here.</p>
  378        *
  379        * @return  An array of <CODE>MBeanConstructorInfo</CODE> objects.
  380        */
  381       public MBeanConstructorInfo[] getConstructors()  {
  382           MBeanConstructorInfo[] cs = nonNullConstructors();
  383           if (cs.length == 0)
  384               return cs;
  385           else
  386               return cs.clone();
  387       }
  388   
  389       private MBeanConstructorInfo[] fastGetConstructors() {
  390           if (arrayGettersSafe)
  391               return nonNullConstructors();
  392           else
  393               return getConstructors();
  394       }
  395   
  396       private MBeanConstructorInfo[] nonNullConstructors() {
  397           return (constructors == null) ?
  398               MBeanConstructorInfo.NO_CONSTRUCTORS : constructors;
  399       }
  400   
  401       /**
  402        * Returns the list of the notifications emitted by the MBean.
  403        * Each notification is described by an <CODE>MBeanNotificationInfo</CODE> object.
  404        *
  405        * The returned array is a shallow copy of the internal array,
  406        * which means that it is a copy of the internal array of
  407        * references to the <CODE>MBeanNotificationInfo</CODE> objects
  408        * but that each referenced <CODE>MBeanNotificationInfo</CODE> object is not copied.
  409        *
  410        * @return  An array of <CODE>MBeanNotificationInfo</CODE> objects.
  411        */
  412       public MBeanNotificationInfo[] getNotifications()  {
  413           MBeanNotificationInfo[] ns = nonNullNotifications();
  414           if (ns.length == 0)
  415               return ns;
  416           else
  417               return ns.clone();
  418       }
  419   
  420       private MBeanNotificationInfo[] fastGetNotifications() {
  421           if (arrayGettersSafe)
  422               return nonNullNotifications();
  423           else
  424               return getNotifications();
  425       }
  426   
  427       private MBeanNotificationInfo[] nonNullNotifications() {
  428           return (notifications == null) ?
  429               MBeanNotificationInfo.NO_NOTIFICATIONS : notifications;
  430       }
  431   
  432       /**
  433        * Get the descriptor of this MBeanInfo.  Changing the returned value
  434        * will have no affect on the original descriptor.
  435        *
  436        * @return a descriptor that is either immutable or a copy of the original.
  437        *
  438        * @since 1.6
  439        */
  440       public Descriptor getDescriptor() {
  441           return (Descriptor) nonNullDescriptor(descriptor).clone();
  442       }
  443   
  444       public String toString() {
  445           return
  446               getClass().getName() + "[" +
  447               "description=" + getDescription() + ", " +
  448               "attributes=" + Arrays.asList(fastGetAttributes()) + ", " +
  449               "constructors=" + Arrays.asList(fastGetConstructors()) + ", " +
  450               "operations=" + Arrays.asList(fastGetOperations()) + ", " +
  451               "notifications=" + Arrays.asList(fastGetNotifications()) + ", " +
  452               "descriptor=" + getDescriptor() +
  453               "]";
  454       }
  455   
  456       /**
  457        * <p>Compare this MBeanInfo to another.  Two MBeanInfo objects
  458        * are equal if and only if they return equal values for {@link
  459        * #getClassName()}, for {@link #getDescription()}, and for
  460        * {@link #getDescriptor()}, and the
  461        * arrays returned by the two objects for {@link
  462        * #getAttributes()}, {@link #getOperations()}, {@link
  463        * #getConstructors()}, and {@link #getNotifications()} are
  464        * pairwise equal.  Here "equal" means {@link
  465        * Object#equals(Object)}, not identity.</p>
  466        *
  467        * <p>If two MBeanInfo objects return the same values in one of
  468        * their arrays but in a different order then they are not equal.</p>
  469        *
  470        * @param o the object to compare to.
  471        *
  472        * @return true if and only if <code>o</code> is an MBeanInfo that is equal
  473        * to this one according to the rules above.
  474        */
  475       public boolean equals(Object o) {
  476           if (o == this)
  477               return true;
  478           if (!(o instanceof MBeanInfo))
  479               return false;
  480           MBeanInfo p = (MBeanInfo) o;
  481           if (!isEqual(getClassName(),  p.getClassName()) ||
  482                   !isEqual(getDescription(), p.getDescription()) ||
  483                   !getDescriptor().equals(p.getDescriptor())) {
  484               return false;
  485           }
  486   
  487           return
  488               (Arrays.equals(p.fastGetAttributes(), fastGetAttributes()) &&
  489                Arrays.equals(p.fastGetOperations(), fastGetOperations()) &&
  490                Arrays.equals(p.fastGetConstructors(), fastGetConstructors()) &&
  491                Arrays.equals(p.fastGetNotifications(), fastGetNotifications()));
  492       }
  493   
  494       public int hashCode() {
  495           /* Since computing the hashCode is quite expensive, we cache it.
  496              If by some terrible misfortune the computed value is 0, the
  497              caching won't work and we will recompute it every time.
  498   
  499              We don't bother synchronizing, because, at worst, n different
  500              threads will compute the same hashCode at the same time.  */
  501           if (hashCode != 0)
  502               return hashCode;
  503   
  504           hashCode =
  505               getClassName().hashCode() ^
  506               getDescriptor().hashCode() ^
  507               arrayHashCode(fastGetAttributes()) ^
  508               arrayHashCode(fastGetOperations()) ^
  509               arrayHashCode(fastGetConstructors()) ^
  510               arrayHashCode(fastGetNotifications());
  511   
  512           return hashCode;
  513       }
  514   
  515       private static int arrayHashCode(Object[] array) {
  516           int hash = 0;
  517           for (int i = 0; i < array.length; i++)
  518               hash ^= array[i].hashCode();
  519           return hash;
  520       }
  521   
  522       /**
  523        * Cached results of previous calls to arrayGettersSafe.  This is
  524        * a WeakHashMap so that we don't prevent a class from being
  525        * garbage collected just because we know whether it's immutable.
  526        */
  527       private static final Map<Class, Boolean> arrayGettersSafeMap =
  528           new WeakHashMap<Class, Boolean>();
  529   
  530       /**
  531        * Return true if <code>subclass</code> is known to preserve the
  532        * immutability of <code>immutableClass</code>.  The class
  533        * <code>immutableClass</code> is a reference class that is known
  534        * to be immutable.  The subclass <code>subclass</code> is
  535        * considered immutable if it does not override any public method
  536        * of <code>immutableClass</code> whose name begins with "get".
  537        * This is obviously not an infallible test for immutability,
  538        * but it works for the public interfaces of the MBean*Info classes.
  539       */
  540       static boolean arrayGettersSafe(Class subclass, Class immutableClass) {
  541           if (subclass == immutableClass)
  542               return true;
  543           synchronized (arrayGettersSafeMap) {
  544               Boolean safe = arrayGettersSafeMap.get(subclass);
  545               if (safe == null) {
  546                   try {
  547                       ArrayGettersSafeAction action =
  548                           new ArrayGettersSafeAction(subclass, immutableClass);
  549                       safe = AccessController.doPrivileged(action);
  550                   } catch (Exception e) { // e.g. SecurityException
  551                       /* We don't know, so we assume it isn't.  */
  552                       safe = false;
  553                   }
  554                   arrayGettersSafeMap.put(subclass, safe);
  555               }
  556               return safe;
  557           }
  558       }
  559   
  560       /*
  561        * The PrivilegedAction stuff is probably overkill.  We can be
  562        * pretty sure the caller does have the required privileges -- a
  563        * JMX user that can't do reflection can't even use Standard
  564        * MBeans!  But there's probably a performance gain by not having
  565        * to check the whole call stack.
  566        */
  567       private static class ArrayGettersSafeAction
  568               implements PrivilegedAction<Boolean> {
  569   
  570           private final Class<?> subclass;
  571           private final Class<?> immutableClass;
  572   
  573           ArrayGettersSafeAction(Class<?> subclass, Class<?> immutableClass) {
  574               this.subclass = subclass;
  575               this.immutableClass = immutableClass;
  576           }
  577   
  578           public Boolean run() {
  579               Method[] methods = immutableClass.getMethods();
  580               for (int i = 0; i < methods.length; i++) {
  581                   Method method = methods[i];
  582                   String methodName = method.getName();
  583                   if (methodName.startsWith("get") &&
  584                           method.getParameterTypes().length == 0 &&
  585                           method.getReturnType().isArray()) {
  586                       try {
  587                           Method submethod =
  588                               subclass.getMethod(methodName);
  589                           if (!submethod.equals(method))
  590                               return false;
  591                       } catch (NoSuchMethodException e) {
  592                           return false;
  593                       }
  594                   }
  595               }
  596               return true;
  597           }
  598       }
  599   
  600       private static boolean isEqual(String s1, String s2) {
  601           boolean ret;
  602   
  603           if (s1 == null) {
  604               ret = (s2 == null);
  605           } else {
  606               ret = s1.equals(s2);
  607           }
  608   
  609           return ret;
  610       }
  611   
  612       /**
  613        * Serializes an {@link MBeanInfo} to an {@link ObjectOutputStream}.
  614        * @serialData
  615        * For compatibility reasons, an object of this class is serialized as follows.
  616        * <ul>
  617        * The method {@link ObjectOutputStream#defaultWriteObject defaultWriteObject()}
  618        * is called first to serialize the object except the field {@code descriptor}
  619        * which is declared as transient. The field {@code descriptor} is serialized
  620        * as follows:
  621        *     <ul>
  622        *     <li> If {@code descriptor} is an instance of the class
  623        *        {@link ImmutableDescriptor}, the method {@link ObjectOutputStream#write
  624        *        write(int val)} is called to write a byte with the value {@code 1},
  625        *        then the method {@link ObjectOutputStream#writeObject writeObject(Object obj)}
  626        *        is called twice to serialize the field names and the field values of the
  627        *        {@code descriptor}, respectively as a {@code String[]} and an
  628        *        {@code Object[]};</li>
  629        *     <li> Otherwise, the method {@link ObjectOutputStream#write write(int val)}
  630        *        is called to write a byte with the value {@code 0}, then the method
  631        *        {@link ObjectOutputStream#writeObject writeObject(Object obj)} is called
  632        *        to serialize the field {@code descriptor} directly.
  633        *     </ul>
  634        * </ul>
  635        * @since 1.6
  636        */
  637       private void writeObject(ObjectOutputStream out) throws IOException {
  638           out.defaultWriteObject();
  639   
  640           if (descriptor.getClass() == ImmutableDescriptor.class) {
  641               out.write(1);
  642   
  643               final String[] names = descriptor.getFieldNames();
  644   
  645               out.writeObject(names);
  646               out.writeObject(descriptor.getFieldValues(names));
  647           } else {
  648               out.write(0);
  649   
  650               out.writeObject(descriptor);
  651           }
  652       }
  653   
  654       /**
  655        * Deserializes an {@link MBeanInfo} from an {@link ObjectInputStream}.
  656        * @serialData
  657        * For compatibility reasons, an object of this class is deserialized as follows.
  658        * <ul>
  659        * The method {@link ObjectInputStream#defaultReadObject defaultReadObject()}
  660        * is called first to deserialize the object except the field
  661        * {@code descriptor}, which is not serialized in the default way. Then the method
  662        * {@link ObjectInputStream#read read()} is called to read a byte, the field
  663        * {@code descriptor} is deserialized according to the value of the byte value:
  664        *    <ul>
  665        *    <li>1. The method {@link ObjectInputStream#readObject readObject()}
  666        *       is called twice to obtain the field names (a {@code String[]}) and
  667        *       the field values (a {@code Object[]}) of the {@code descriptor}.
  668        *       The two obtained values then are used to construct
  669        *       an {@link ImmutableDescriptor} instance for the field
  670        *       {@code descriptor};</li>
  671        *    <li>0. The value for the field {@code descriptor} is obtained directly
  672        *       by calling the method {@link ObjectInputStream#readObject readObject()}.
  673        *       If the obtained value is null, the field {@code descriptor} is set to
  674        *       {@link ImmutableDescriptor#EMPTY_DESCRIPTOR EMPTY_DESCRIPTOR};</li>
  675        *    <li>-1. This means that there is no byte to read and that the object is from
  676        *       an earlier version of the JMX API. The field {@code descriptor} is set to
  677        *       {@link ImmutableDescriptor#EMPTY_DESCRIPTOR EMPTY_DESCRIPTOR}.</li>
  678        *    <li>Any other value. A {@link StreamCorruptedException} is thrown.</li>
  679        *    </ul>
  680        * </ul>
  681        * @since 1.6
  682        */
  683   
  684       private void readObject(ObjectInputStream in)
  685           throws IOException, ClassNotFoundException {
  686   
  687           in.defaultReadObject();
  688   
  689           switch (in.read()) {
  690           case 1:
  691               final String[] names = (String[])in.readObject();
  692   
  693               if (names.length == 0) {
  694                   descriptor = ImmutableDescriptor.EMPTY_DESCRIPTOR;
  695               } else {
  696                   final Object[] values = (Object[])in.readObject();
  697                   descriptor = new ImmutableDescriptor(names, values);
  698               }
  699   
  700               break;
  701           case 0:
  702               descriptor = (Descriptor)in.readObject();
  703   
  704               if (descriptor == null) {
  705                   descriptor = ImmutableDescriptor.EMPTY_DESCRIPTOR;
  706               }
  707   
  708               break;
  709           case -1: // from an earlier version of the JMX API
  710               descriptor = ImmutableDescriptor.EMPTY_DESCRIPTOR;
  711   
  712               break;
  713           default:
  714               throw new StreamCorruptedException("Got unexpected byte.");
  715           }
  716       }
  717   }

Save This Page
Home » openjdk-7 » javax » management » [javadoc | source]