/*
 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.management;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// remaining imports are for Javadoc
import java.io.InvalidObjectException;
import java.lang.management.MemoryUsage;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Arrays;
import java.util.List;
import javax.management.openmbean.ArrayType;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataInvocationHandler;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeDataView;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenMBeanInfo;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;

/**
    <p>Annotation to mark an interface explicitly as being an MXBean
    interface, or as not being an MXBean interface.  By default, an
    interface is an MXBean interface if its name ends with {@code
    MXBean}, as in {@code SomethingMXBean}.  The following interfaces
    are MXBean interfaces:</p>

    <pre>
    public interface WhatsitMXBean {}

    &#64;MXBean
    public interface Whatsit1Interface {}

    &#64;MXBean(true)
    public interface Whatsit2Interface {}
    </pre>

    <p>The following interfaces are not MXBean interfaces:</p>

    <pre>
    public interface Whatsit3Interface{}

    &#64;MXBean(false)
    public interface MisleadingMXBean {}
    </pre>

    <h3 id="MXBean-spec">MXBean specification</a></h3>

    <p>The MXBean concept provides a simple way to code an MBean
      that only references a predefined set of types, the ones defined
      by {@link javax.management.openmbean}.  In this way, you can be
      sure that your MBean will be usable by any client, including
      remote clients, without any requirement that the client have
      access to <em>model-specific classes</em> representing the types
      of your MBeans.</p>

    <p>The concepts are easier to understand by comparison with the
      Standard MBean concept.  Here is how a managed object might be
      represented as a Standard MBean, and as an MXBean:</p>

    <table border="1" cellpadding="5">
      <tr>
        <th>Standard MBean</th><th>MXBean</th>
      </tr>
      <tr>
        <td><pre>
public interface MemoryPool<b>MBean</b> {
    String getName();
    MemoryUsage getUsage();
    // ...
}
          </pre></td>
        <td><pre>
public interface MemoryPool<b>MXBean</b> {
    String getName();
    MemoryUsage getUsage();
    // ...
}
          </pre></td>
      </tr>
    </table>

    <p>As you can see, the definitions are very similar.  The only
      difference is that the convention for naming the interface is to use
      <code><em>Something</em>MXBean</code> for MXBeans, rather than
      <code><em>Something</em>MBean</code> for Standard MBeans.</p>

    <p>In this managed object, there is an attribute called
      <code>Usage</code> of type {@link MemoryUsage}.  The point of an
      attribute like this is that it gives a coherent snapshot of a set
      of data items.  For example, it might include the current amount
      of used memory in the memory pool, and the current maximum of the
      memory pool.  If these were separate items, obtained with separate
      {@link MBeanServer#getAttribute getAttribute} calls, then we could
      get values seen at different times that were not consistent.  We
      might get a <code>used</code> value that was greater than the
      <code>max</code> value.</p>

    <p>So, we might define <code>MemoryUsage</code> like this:</p>

    <table border="1" cellpadding="5">
      <tr>
        <th>Standard MBean</th><th>MXBean</th>
      </tr>
      <tr>
        <td><pre>
public class MemoryUsage <b>implements Serializable</b> {
    // standard JavaBean conventions with getters

    public MemoryUsage(long init, long used,
                       long committed, long max) {...}
    long getInit() {...}
    long getUsed() {...}
    long getCommitted() {...}
    long getMax() {...}
}
          </pre></td>
        <td><pre>
public class MemoryUsage {
    // standard JavaBean conventions with getters
    <b>&#64;ConstructorProperties({"init", "used", "committed", "max"})</b>
    public MemoryUsage(long init, long used,
                       long committed, long max) {...}
    long getInit() {...}
    long getUsed() {...}
    long getCommitted() {...}
    long getMax() {...}
}
          </pre></td>
      </tr>
    </table>

    <p>The definitions are the same in the two cases, except
      that with the MXBean, <code>MemoryUsage</code> no longer needs to
      be marked <code>Serializable</code> (though it can be).  On
      the other hand, we have added a {@code @ConstructorProperties} annotation
      to link the constructor parameters to the corresponding getters.
      We will see more about this below.</p>

    <p><code>MemoryUsage</code> is a <em>model-specific class</em>.
      With Standard MBeans, a client of the MBean Server cannot access the
      <code>Usage</code> attribute if it does not know the class
      <code>MemoryUsage</code>.  Suppose the client is a generic console
      based on JMX technology.  Then the console would have to be
      configured with the model-specific classes of every application it
      might connect to.  The problem is even worse for clients that are
      not written in the Java language.  Then there may not be any way
      to tell the client what a <code>MemoryUsage</code> looks like.</p>

    <p>This is where MXBeans differ from Standard MBeans.  Although we
      define the management interface in almost exactly the same way,
      the MXBean framework <em>converts</em> model-specific classes into
      standard classes from the Java platform.  Using arrays and the
      {@link javax.management.openmbean.CompositeData CompositeData} and
      {@link javax.management.openmbean.TabularData TabularData} classes
      from the standard {@link javax.management.openmbean} package, it
      is possible to build data structures of arbitrary complexity
      using only standard classes.</p>

    <p>This becomes clearer if we compare what the clients of the two
      models might look like:</p>

    <table border="1" cellpadding="5">
      <tr>
        <th>Standard MBean</th><th>MXBean</th>
      </tr>
      <tr>
        <td><pre>
String name = (String)
    mbeanServer.{@link MBeanServer#getAttribute
    getAttribute}(objectName, "Name");
<b>MemoryUsage</b> usage = (<b>MemoryUsage</b>)
    mbeanServer.getAttribute(objectName, "Usage");
<b>long used = usage.getUsed();</b>
          </pre></td>
        <td><pre>
String name = (String)
    mbeanServer.{@link MBeanServer#getAttribute
    getAttribute}(objectName, "Name");
<b>{@link CompositeData}</b> usage = (<b>CompositeData</b>)
    mbeanServer.getAttribute(objectName, "Usage");
<b>long used = (Long) usage.{@link CompositeData#get get}("used");</b>
          </pre></td>
    </table>

    <p>For attributes with simple types like <code>String</code>, the
      code is the same.  But for attributes with complex types, the
      Standard MBean code requires the client to know the model-specific
      class <code>MemoryUsage</code>, while the MXBean code requires no
      non-standard classes.</p>

    <p>The client code shown here is slightly more complicated for the
      MXBean client.  But, if the client does in fact know the model,
      here the interface <code>MemoryPoolMXBean</code> and the
      class <code>MemoryUsage</code>, then it can construct a
      <em>proxy</em>.  This is the recommended way to interact with
      managed objects when you know the model beforehand, regardless
      of whether you are using Standard MBeans or MXBeans:</p>

    <table border="1" cellpadding="5">
      <tr>
        <th>Standard MBean</th><th>MXBean</th>
      </tr>
      <tr>
        <td><pre>
MemoryPool<b>MBean</b> proxy =
    JMX.<b>{@link JMX#newMBeanProxy(MBeanServerConnection, ObjectName,
              Class) newMBeanProxy}</b>(
        mbeanServer,
        objectName,
        MemoryPool<b>MBean</b>.class);
String name = proxy.getName();
MemoryUsage usage = proxy.getUsage();
long used = usage.getUsed();
          </pre></td>
        <td><pre>
MemoryPool<b>MXBean</b> proxy =
    JMX.<b>{@link JMX#newMXBeanProxy(MBeanServerConnection, ObjectName,
              Class) newMXBeanProxy}</b>(
        mbeanServer,
        objectName,
        MemoryPool<b>MXBean</b>.class);
String name = proxy.getName();
MemoryUsage usage = proxy.getUsage();
long used = usage.getUsed();
          </pre></td>
      </tr>
    </table>

    <p>Implementing the MemoryPool object works similarly for both
      Standard MBeans and MXBeans.</p>

    <table border="1" cellpadding="5">
      <tr>
        <th>Standard MBean</th><th>MXBean</th>
      </tr>
      <tr>
        <td><pre>
public class MemoryPool
        implements MemoryPool<b>MBean</b> {
    public String getName() {...}
    public MemoryUsage getUsage() {...}
    // ...
}
          </pre></td>
        <td><pre>
public class MemoryPool
        implements MemoryPool<b>MXBean</b> {
    public String getName() {...}
    public MemoryUsage getUsage() {...}
    // ...
}
          </pre></td>
      </tr>
    </table>

    <p>Registering the MBean in the MBean Server works in the same way
      in both cases:</p>

    <table border="1" cellpadding="5">
      <tr>
        <th>Standard MBean</th><th>MXBean</th>
      </tr>
      <tr>
        <td><pre>
{
    MemoryPool<b>MBean</b> pool = new MemoryPool();
    mbeanServer.{@link MBeanServer#registerMBean
    registerMBean}(pool, objectName);
}
          </pre></td>
        <td><pre>
{
    MemoryPool<b>MXBean</b> pool = new MemoryPool();
    mbeanServer.{@link MBeanServer#registerMBean
    registerMBean}(pool, objectName);
}
          </pre></td>
      </tr>
    </table>


    <h2 id="mxbean-def">Definition of an MXBean</h2>

    <p>An MXBean is a kind of MBean.  An MXBean object can be
      registered directly in the MBean Server, or it can be used as an
      argument to {@link StandardMBean} and the resultant MBean
      registered in the MBean Server.</p>

    <p>When an object is registered in the MBean Server using the
      {@code registerMBean} or {@code createMBean} methods of the
      {@link MBeanServer} interface, the object's class is examined
      to determine what type of MBean it is:</p>

    <ul>
      <li>If the class implements the interface {@link DynamicMBean}
        then the MBean is a Dynamic MBean.  Note that the class
        {@code StandardMBean} implements this interface, so this
        case applies to a Standard MBean or MXBean created using
        the class {@code StandardMBean}.</li>

      <li>Otherwise, if the class matches the Standard MBean naming
        conventions, then the MBean is a Standard MBean.</li>

      <li>Otherwise, it may be an MXBean.  The set of interfaces
        implemented by the object is examined for interfaces that:

        <ul>
          <li>have a class name <code><em>S</em>MXBean</code> where
            <code><em>S</em></code> is any non-empty string, and
            do not have an annotation {@code @MXBean(false)}; and/or</li>
          <li>have an annotation {@code @MXBean(true)}
            or just {@code @MXBean}.</li>
        </ul>

        If there is exactly one such interface, or if there is one
        such interface that is a subinterface of all the others, then
        the object is an MXBean.  The interface in question is the
        <em>MXBean interface</em>.  In the example above, the MXBean
        interface is {@code MemoryPoolMXBean}.

      <li>If none of these conditions is met, the MBean is invalid and
        the attempt to register it will generate {@link
        NotCompliantMBeanException}.
    </ul>

    <p>Every Java type that appears as the parameter or return type of a
      method in an MXBean interface must be <em>convertible</em> using
      the rules below.  Additionally, parameters must be
      <em>reconstructible</em> as defined below.</p>

    <p>An attempt to construct an MXBean that does not conform to the
      above rules will produce an exception.</p>


    <h2 id="naming-conv">Naming conventions</h2>

    <p>The same naming conventions are applied to the methods in an
      MXBean as in a Standard MBean:</p>

    <ol>
      <li>A method <code><em>T</em> get<em>N</em>()</code>, where
        <code><em>T</em></code> is a Java type (not <code>void</code>)
        and <code><em>N</em></code> is a non-empty string, specifies
        that there is a readable attribute called
        <code><em>N</em></code>.  The Java type and Open type of the
        attribute are determined by the mapping rules below.
        The method {@code final Class getClass()} inherited from {@code
        Object} is ignored when looking for getters.</li>

      <li>A method <code>boolean is<em>N</em>()</code> specifies that
        there is a readable attribute called <code><em>N</em></code>
        with Java type <code>boolean</code> and Open type
        <code>SimpleType.Boolean</code>.</li>

      <li>A method <code>void set<em>N</em>(<em>T</em> x)</code>
        specifies that there is a writeable attribute called
        <code><em>N</em></code>.  The Java type and Open type of the
        attribute are determined by the mapping rules below.  (Of
        course, the name <code>x</code> of the parameter is
        irrelevant.)</li>

      <li>Every other method specifies that there is an operation with
        the same name as the method.  The Java type and Open type of the
        return value and of each parameter are determined by the mapping
        rules below.</li>
    </ol>

    <p>The rules for <code>get<em>N</em></code> and
      <code>is<em>N</em></code> collectively define the notion of a
      <em>getter</em>.  The rule for <code>set<em>N</em></code> defines
      the notion of a <em>setter</em>.</p>

    <p>It is an error for there to be two getters with the same name, or
      two setters with the same name.  If there is a getter and a setter
      for the same name, then the type <code><em>T</em></code> in both
      must be the same.  In this case the attribute is read/write.  If
      there is only a getter or only a setter, the attribute is
      read-only or write-only respectively.</p>


    <h2 id="mapping-rules">Type mapping rules</h2>

    <p>An MXBean is a kind of Open MBean, as defined by the {@link
      javax.management.openmbean} package.  This means that the types of
      attributes, operation parameters, and operation return values must
      all be describable using <em>Open Types</em>, that is the four
      standard subclasses of {@link javax.management.openmbean.OpenType}.
      MXBeans achieve this by mapping Java types into Open Types.</p>

    <p>For every Java type <em>J</em>, the MXBean mapping is described
      by the following information:</p>

    <ul>
      <li>The corresponding Open Type, <em>opentype(J)</em>.  This is
        an instance of a subclass of {@link
        javax.management.openmbean.OpenType}.</li>
      <li>The <em>mapped</em> Java type, <em>opendata(J)</em>, which is
        always the same for any given <em>opentype(J)</em>.  This is a Java
        class.</li>
      <li>How a value is converted from type <em>J</em> to type
        <em>opendata(J)</em>.</li>
      <li>How a value is converted from type <em>opendata(J)</em> to
        type <em>J</em>, if it can be.</li>
    </ul>

    <p>For example, for the Java type {@code List<String>}:</p>

    <ul>
      <li>The Open Type, <em>opentype(</em>{@code
        List<String>}<em>)</em>, is {@link ArrayType}<code>(1, </code>{@link
          SimpleType#STRING}<code>)</code>, representing a 1-dimensional
          array of <code>String</code>s.</li>
      <li>The mapped Java type, <em>opendata(</em>{@code
        List<String>}<em>)</em>, is {@code String[]}.</li>
      <li>A {@code List<String>} can be converted to a {@code String[]}
          using {@link List#toArray(Object[]) List.toArray(new
          String[0])}.</li>
      <li>A {@code String[]} can be converted to a {@code List<String>}
          using {@link Arrays#asList Arrays.asList}.</li>
    </ul>

    <p>If no mapping rules exist to derive <em>opentype(J)</em> from
      <em>J</em>, then <em>J</em> cannot be the type of a method
      parameter or return value in an MXBean interface.</p>

    <p id="reconstructible-def">If there is a way to convert
      <em>opendata(J)</em> back to <em>J</em> then we say that <em>J</em> is
      <em>reconstructible</em>.  All method parameters in an MXBean
      interface must be reconstructible, because when the MXBean
      framework is invoking a method it will need to convert those
      parameters from <em>opendata(J)</em> to <em>J</em>.  In a proxy
      generated by {@link JMX#newMXBeanProxy(MBeanServerConnection,
      ObjectName, Class) JMX.newMXBeanProxy}, it is the return values
      of the methods in the MXBean interface that must be
      reconstructible.</p>

    <p>Null values are allowed for all Java types and Open Types,
      except primitive Java types where they are not possible.  When
      converting from type <em>J</em> to type <em>opendata(J)</em> or
      from type <em>opendata(J)</em> to type <em>J</em>, a null value is
      mapped to a null value.</p>

    <p>The following table summarizes the type mapping rules.</p>

    <table border="1" cellpadding="5">
      <tr>
        <th>Java type <em>J</em></th>
        <th><em>opentype(J)</em></th>
        <th><em>opendata(J)</em></th>
      </tr>
      <tbody cellvalign="top">
        <tr>
          <td>{@code int}, {@code boolean}, etc<br>
            (the 8 primitive Java types)</td>
          <td>{@code SimpleType.INTEGER},<br>
            {@code SimpleType.BOOLEAN}, etc</td>
          <td>{@code Integer}, {@code Boolean}, etc<br>
            (the corresponding boxed types)</td>
        </tr>
        <tr>
          <td>{@code Integer}, {@code ObjectName}, etc<br>
            (the types covered by {@link SimpleType})</td>
          <td>the corresponding {@code SimpleType}</td>
          <td><em>J</em>, the same type</td>
        </tr>
        <tr>
          <td>{@code int[]} etc<br>
            (a one-dimensional array with<br>
            primitive element type)</td>
          <td>{@code ArrayType.getPrimitiveArrayType(int[].class)} etc</td>
          <td><em>J</em>, the same type</td>
        <tr>
          <td><em>E</em>{@code []}<br>
            (an array with non-primitive element type <em>E</em>;
              this includes {@code int[][]}, where <em>E</em> is {@code int[]})</td>
          <td>{@code ArrayType.getArrayType(}<em>opentype(E)</em>{@code )}</td>
          <td><em>opendata(E)</em>{@code []}</td>
        </tr>
        <tr>
          <td>{@code List<}<em>E</em>{@code >}<br>
            {@code Set<}<em>E</em>{@code >}<br>
            {@code SortedSet<}<em>E</em>{@code >} (see below)</td>
          <td>same as for <em>E</em>{@code []}</td>
          <td>same as for <em>E</em>{@code []}</td>
        </tr>
        <tr>
          <td>An enumeration <em>E</em><br>
            (declared in Java as {@code enum }<em>E</em>
            {@code {...}})</td>
          <td>{@code SimpleType.STRING}</td>
          <td>{@code String}</td>
        </tr>
        <tr>
          <td>{@code Map<}<em>K</em>,<em>V</em>{@code >}<br>
            {@code SortedMap<}<em>K</em>,<em>V</em>{@code >}</td>
          <td>{@link TabularType}<br>
            (see below)</td>
          <td>{@link TabularData}<br>
            (see below)</td>
        </tr>
        <tr>
          <td>An MXBean interface</td>
          <td>{@code SimpleType.OBJECTNAME}<br>
            (see below)</td>
          <td>{@link ObjectName}<br>
            (see below)</td>
        </tr>
        <tr>
          <td>Any other type</td>
          <td>{@link CompositeType},
            if possible<br>
            (see below)</td>
          <td>{@link CompositeData}</td>
      </tbody>
    </table>

    <p>The following sections give further details of these rules.</p>


    <h3>Mappings for primitive types</h3>

    <p>The 8 primitive Java types
      ({@code boolean}, {@code byte}, {@code short}, {@code int}, {@code
      long}, {@code float}, {@code double}, {@code char}) are mapped to the
      corresponding boxed types from {@code java.lang}, namely {@code
      Boolean}, {@code Byte}, etc.  The Open Type is the corresponding
      {@code SimpleType}.  Thus, <em>opentype(</em>{@code
      long}<em>)</em> is {@code SimpleType.LONG}, and
      <em>opendata(</em>{@code long}<em>)</em> is {@code
      java.lang.Long}.</p>

    <p>An array of primitive type such as {@code long[]} can be represented
      directly as an Open Type.  Thus, <em>openType(</em>{@code
      long[]}<em>)</em> is {@code
      ArrayType.getPrimitiveArrayType(long[].class)}, and
      <em>opendata(</em>{@code long[]}<em>)</em> is {@code
      long[]}.</p>

    <p>In practice, the difference between a plain {@code int} and {@code
      Integer}, etc, does not show up because operations in the JMX API
      are always on Java objects, not primitives.  However, the
      difference <em>does</em> show up with arrays.</p>


    <h3>Mappings for collections ({@code List<}<em>E</em>{@code >} etc)</h3>

    <p>A {@code List<}<em>E</em>{@code >} or {@code
      Set<}<em>E</em>{@code >}, such as {@code List<String>} or {@code
        Set<ObjectName>}, is mapped in the same way as an array of the
          same element type, such as {@code String[]} or {@code
          ObjectName[]}.</p>

    <p>A {@code SortedSet<}<em>E</em>{@code >} is also mapped in the
      same way as an <em>E</em>{@code []}, but it is only convertible if
      <em>E</em> is a class or interface that implements {@link
      java.lang.Comparable}.  Thus, a {@code SortedSet<String>} or
        {@code SortedSet<Integer>} is convertible, but a {@code
          SortedSet<int[]>} or {@code SortedSet<List<String>>} is not.  The
                conversion of a {@code SortedSet} instance will fail with an
                {@code IllegalArgumentException} if it has a
                non-null {@link java.util.SortedSet#comparator()
                comparator()}.</p>

    <p>A {@code List<}<em>E</em>{@code >} is reconstructed as a
      {@code java.util.ArrayList<}<em>E</em>{@code >};
      a {@code Set<}<em>E</em>{@code >} as a
      {@code java.util.HashSet<}<em>E</em>{@code >};
      a {@code SortedSet<}<em>E</em>{@code >} as a
      {@code java.util.TreeSet<}<em>E</em>{@code >}.</p>


    <h3>Mappings for maps ({@code Map<}<em>K</em>,<em>V</em>{@code >} etc)</h3>

    <p>A {@code Map<}<em>K</em>,<em>V</em>{@code >} or {@code
      SortedMap<}<em>K</em>,<em>V</em>{@code >}, for example {@code
      Map<String,ObjectName>}, has Open Type {@link TabularType} and is mapped
        to a {@link TabularData}.
        The {@code TabularType} has two items called {@code key} and
        {@code value}.  The Open Type of {@code key} is
        <em>opentype(K)</em>, and the Open Type of {@code value} is
        <em>opentype(V)</em>.  The index of the {@code TabularType} is the
        single item {@code key}.</p>

    <p>For example, the {@code TabularType} for a {@code
      Map<String,ObjectName>} might be constructed with code like
        this:</p>

    <pre>
String typeName =
    "java.util.Map&lt;java.lang.String, javax.management.ObjectName&gt;";
String[] keyValue =
    new String[] {"key", "value"};
OpenType[] openTypes =
    new OpenType[] {SimpleType.STRING, SimpleType.OBJECTNAME};
CompositeType rowType =
    new CompositeType(typeName, typeName, keyValue, keyValue, openTypes);
TabularType tabularType =
    new TabularType(typeName, typeName, rowType, new String[] {"key"});
    </pre>

    <p>The {@code typeName} here is determined by the <a href="#type-names">
      type name rules</a> detailed below.

    <p>A {@code SortedMap<}<em>K</em>,<em>V</em>{@code >} is mapped in the
      same way, but it is only convertible if
      <em>K</em> is a class or interface that implements {@link
      java.lang.Comparable}.  Thus, a {@code SortedMap<String,int[]>}
        is convertible, but a
        {@code SortedMap<int[],String>} is not.  The conversion of a
          {@code SortedMap} instance will fail with an {@code
          IllegalArgumentException} if it has a non-null {@link
          java.util.SortedMap#comparator() comparator()}.</p>

    <p>A {@code Map<}<em>K</em>,<em>V</em>{@code >} is reconstructed as
      a {@code java.util.HashMap<}<em>K</em>,<em>V</em>{@code >};
      a {@code SortedMap<}<em>K</em>,<em>V</em>{@code >} as
      a {@code java.util.TreeMap<}<em>K</em>,<em>V</em>{@code >}.</p>

    <p>{@code TabularData} is an interface.  The concrete class that is
      used to represent a {@code Map<}<em>K</em>,<em>V</em>{@code >} as
      Open Data is {@link TabularDataSupport},
      or another class implementing {@code
      TabularData} that serializes as {@code TabularDataSupport}.</p>


    <h3 id="mxbean-map">Mappings for MXBean interfaces</h3>

    <p>An MXBean interface, or a type referenced within an MXBean
      interface, can reference another MXBean interface, <em>J</em>.
      Then <em>opentype(J)</em> is {@code SimpleType.OBJECTNAME} and
      <em>opendata(J)</em> is {@code ObjectName}.</p>

    <p>For example, suppose you have two MXBean interfaces like this:</p>

    <pre>
public interface ProductMXBean {
    public ModuleMXBean[] getModules();
}

public interface ModuleMXBean {
    public ProductMXBean getProduct();
}
    </pre>

    <p>The object implementing the {@code ModuleMXBean} interface
      returns from its {@code getProduct} method an object
      implementing the {@code ProductMXBean} interface.  The
      {@code ModuleMXBean} object and the returned {@code
      ProductMXBean} objects must both be registered as MXBeans in the
      same MBean Server.</p>

    <p>The method {@code ModuleMXBean.getProduct()} defines an
      attribute called {@code Product}.  The Open Type for this
      attribute is {@code SimpleType.OBJECTNAME}, and the corresponding
      {@code ObjectName} value will be the name under which the
      referenced {@code ProductMXBean} is registered in the MBean
      Server.</p>

    <p>If you make an MXBean proxy for a {@code ModuleMXBean} and
      call its {@code getProduct()} method, the proxy will map the
      {@code ObjectName} back into a {@code ProductMXBean} by making
      another MXBean proxy.  More formally, when a proxy made with
      {@link JMX#newMXBeanProxy(MBeanServerConnection, ObjectName,
       Class)
      JMX.newMXBeanProxy(mbeanServerConnection, objectNameX,
      interfaceX)} needs to map {@code objectNameY} back into {@code
      interfaceY}, another MXBean interface, it does so with {@code
      JMX.newMXBeanProxy(mbeanServerConnection, objectNameY,
      interfaceY)}.  The implementation may return a proxy that was
      previously created by a call to {@code JMX.newMXBeanProxy}
      with the same parameters, or it may create a new proxy.</p>

    <p>The reverse mapping is illustrated by the following change to the
      {@code ModuleMXBean} interface:</p>

    <pre>
public interface ModuleMXBean {
    public ProductMXBean getProduct();
    public void setProduct(ProductMXBean c);
}
    </pre>

    <p>The presence of the {@code setProduct} method now means that the
      {@code Product} attribute is read/write.  As before, the value
      of this attribute is an {@code ObjectName}.  When the attribute is
      set, the {@code ObjectName} must be converted into the
      {@code ProductMXBean} object that the {@code setProduct} method
      expects.  This object will be an MXBean proxy for the given
      {@code ObjectName} in the same MBean Server.</p>

    <p>If you make an MXBean proxy for a {@code ModuleMXBean} and
      call its {@code setProduct} method, the proxy will map its
      {@code ProductMXBean} argument back into an {@code ObjectName}.
      This will only work if the argument is in fact another proxy,
      for a {@code ProductMXBean} in the same {@code
      MBeanServerConnection}.  The proxy can have been returned from
      another proxy (like {@code ModuleMXBean.getProduct()} which
      returns a proxy for a {@code ProductMXBean}); or it can have
      been created by {@link
      JMX#newMXBeanProxy(MBeanServerConnection, ObjectName, Class)
      JMX.newMXBeanProxy}; or it can have been created using {@link
      java.lang.reflect.Proxy Proxy} with an invocation handler that
      is {@link MBeanServerInvocationHandler} or a subclass.</p>

    <p>If the same MXBean were registered under two different
      {@code ObjectName}s, a reference to that MXBean from another
      MXBean would be ambiguous.  Therefore, if an MXBean object is
      already registered in an MBean Server and an attempt is made to
      register it in the same MBean Server under another name, the
      result is an {@link InstanceAlreadyExistsException}.  Registering
      the same MBean object under more than one name is discouraged in
      general, notably because it does not work well for MBeans that are
      {@link NotificationBroadcaster}s.</p>

    <h3 id="composite-map">Mappings for other types</h3>

    <p>Given a Java class or interface <em>J</em> that does not match the other
      rules in the table above, the MXBean framework will attempt to map
      it to a {@link CompositeType} as follows.  The type name of this
      {@code CompositeType} is determined by the <a href="#type-names">
      type name rules</a> below.</p>

    <p>The class is examined for getters using the conventions
      <a href="#naming-conv">above</a>.  (Getters must be public
      instance methods.)  If there are no getters, or if
      any getter has a type that is not convertible, then <em>J</em> is
      not convertible.</p>

    <p>If there is at least one getter and every getter has a
      convertible type, then <em>opentype(J)</em> is a {@code
      CompositeType} with one item for every getter.  If the getter is

    <blockquote>
      <code><em>T</em> get<em>Name</em>()</code>
    </blockquote>

    then the item in the {@code CompositeType} is called {@code name}
    and has type <em>opentype(T)</em>.  For example, if the item is

    <blockquote>
      <code>String getOwner()</code>
    </blockquote>

    then the item is called {@code owner} and has Open Type {@code
    SimpleType.STRING}.  If the getter is

    <blockquote>
      <code>boolean is<em>Name</em>()</code>
    </blockquote>

    then the item in the {@code CompositeType} is called {@code name}
    and has type {@code SimpleType.BOOLEAN}.</p>

    <p>Notice that the first character (or code point) is converted to
      lower case.  This follows the Java Beans convention, which for
      historical reasons is different from the Standard MBean
      convention.  In a Standard MBean or MXBean interface, a method
      {@code getOwner} defines an attribute called {@code Owner}, while
      in a Java Bean or mapped {@code CompositeType}, a method {@code
      getOwner} defines a property or item called {@code owner}.</p>

    <p>If two methods produce the same item name (for example, {@code
      getOwner} and {@code isOwner}, or {@code getOwner} and {@code
      getowner}) then the type is not convertible.</p>

    <p>When the Open Type is {@code CompositeType}, the corresponding
      mapped Java type (<em>opendata(J)</em>) is {@link
      CompositeData}.  The mapping from an instance of <em>J</em> to a
      {@code CompositeData} corresponding to the {@code CompositeType}
      just described is done as follows.  First, if <em>J</em>
      implements the interface {@link CompositeDataView}, then that
      interface's {@link CompositeDataView#toCompositeData
      toCompositeData} method is called to do the conversion.
      Otherwise, the {@code CompositeData} is constructed by calling
      the getter for each item and converting it to the corresponding
      Open Data type.  Thus, a getter such as</p>

    <blockquote>
      {@code List<String> getNames()}
    </blockquote>

    <p>will have been mapped to an item with name "{@code names}" and
      Open Type {@code ArrayType(1, SimpleType.STRING)}.  The conversion
      to {@code CompositeData} will call {@code getNames()} and convert
      the resultant {@code List<String>} into a {@code String[]} for the
        item "{@code names}".</p>

    <p>{@code CompositeData} is an interface.  The concrete class that is
      used to represent a type as Open Data is {@link
      CompositeDataSupport}, or another class implementing {@code
      CompositeData} that serializes as {@code
      CompositeDataSupport}.</p>


    <h4>Reconstructing an instance of Java type <em>J</em> from
      a {@code CompositeData}</h4>

    <p>If <em>opendata(J)</em> is {@code CompositeData} for a Java type
      <em>J</em>, then either an instance of <em>J</em> can be
      reconstructed from a {@code CompositeData}, or <em>J</em> is not
      reconstructible.  If any item in the {@code CompositeData} is not
      reconstructible, then <em>J</em> is not reconstructible either.</p>

    <p>For any given <em>J</em>, the following rules are consulted to
      determine how to reconstruct instances of <em>J</em> from
      {@code CompositeData}.  The first applicable rule in the list is
      the one that will be used.</p>

    <ol>

      <li><p>If <em>J</em> has a method<br>
        {@code public static }<em>J </em>{@code from(CompositeData cd)}<br>
        then that method is called to reconstruct an instance of
        <em>J</em>.</p></li>

      <li><p>Otherwise, if <em>J</em> has at least one public
        constructor with a {@link java.beans.ConstructorProperties
        ConstructorProperties} annotation, then one
        of those constructors (not necessarily always the same one)
        will be called to reconstruct an instance of <em>J</em>.
        Every such annotation must list as many strings as the
        constructor has parameters; each string must name a property
        corresponding to a getter of <em>J</em>; and the type of this
        getter must be the same as the corresponding constructor
        parameter.  It is not an error for there to be getters that
        are not mentioned in the {@code ConstructorProperties} annotation
        (these may correspond to information that is not needed to
        reconstruct the object).</p>

        <p>An instance of <em>J</em> is reconstructed by calling a
        constructor with the appropriate reconstructed items from the
        {@code CompositeData}.  The constructor to be called will be
        determined at runtime based on the items actually present in
        the {@code CompositeData}, given that this {@code
        CompositeData} might come from an earlier version of
        <em>J</em> where not all the items were present.  A
        constructor is <em>applicable</em> if all the properties named
        in its {@code ConstructorProperties} annotation are present as items
        in the {@code CompositeData}.  If no constructor is
        applicable, then the attempt to reconstruct <em>J</em> fails.</p>

        <p>For any possible combination of properties, it must be the
        case that either (a) there are no applicable constructors, or
        (b) there is exactly one applicable constructor, or (c) one of
        the applicable constructors names a proper superset of the
        properties named by each other applicable constructor.  (In
        other words, there should never be ambiguity over which
        constructor to choose.)  If this condition is not true, then
        <em>J</em> is not reconstructible.</p></li>

      <li><p>Otherwise, if <em>J</em> has a public no-arg constructor, and
        for every getter in <em>J</em> with type
        <em>T</em> and name <em>N</em> there is a corresponding setter
        with the same name and type, then an instance of <em>J</em> is
        constructed with the no-arg constructor and the setters are
        called with the reconstructed items from the {@code CompositeData}
        to restore the values.  For example, if there is a method<br>
        {@code public List<String> getNames()}<br>
          then there must also be a method<br>
          {@code public void setNames(List<String> names)}<br>
            for this rule to apply.</p>

        <p>If the {@code CompositeData} came from an earlier version of
        <em>J</em>, some items might not be present.  In this case,
        the corresponding setters will not be called.</p></li>

      <li><p>Otherwise, if <em>J</em> is an interface that has no methods
        other than getters, an instance of <em>J</em> is constructed
        using a {@link java.lang.reflect.Proxy} with a {@link
        CompositeDataInvocationHandler} backed by the {@code
        CompositeData} being converted.</p></li>

      <li><p>Otherwise, <em>J</em> is not reconstructible.</p></li>
    </ol>

    <p>Here are examples showing different ways to code a type {@code
      NamedNumber} that consists of an {@code int} and a {@code
      String}.  In each case, the {@code CompositeType} looks like this:</p>

    <blockquote>
      <pre>
{@link CompositeType}(
    "NamedNumber",                      // typeName
    "NamedNumber",                      // description
    new String[] {"number", "name"},    // itemNames
    new String[] {"number", "name"},    // itemDescriptions
    new OpenType[] {SimpleType.INTEGER,
                    SimpleType.STRING}  // itemTypes
);
      </pre>
    </blockquote>

    <ol>
      <li>Static {@code from} method:

        <blockquote>
          <pre>
public class NamedNumber {
    public int getNumber() {return number;}
    public String getName() {return name;}
    private NamedNumber(int number, String name) {
        this.number = number;
        this.name = name;
    }
    <b>public static NamedNumber from(CompositeData cd)</b> {
        return new NamedNumber((Integer) cd.get("number"),
                               (String) cd.get("name"));
    }
    private final int number;
    private final String name;
}
          </pre>
        </blockquote>
      </li>

      <li>Public constructor with <code>&#64;ConstructorProperties</code> annotation:

        <blockquote>
          <pre>
public class NamedNumber {
    public int getNumber() {return number;}
    public String getName() {return name;}
    <b>&#64;ConstructorProperties({"number", "name"})
    public NamedNumber(int number, String name)</b> {
        this.number = number;
        this.name = name;
    }
    private final int number;
    private final String name;
}
          </pre>
        </blockquote>
      </li>

      <li>Setter for every getter:

        <blockquote>
          <pre>
public class NamedNumber {
    public int getNumber() {return number;}
    public void <b>setNumber</b>(int number) {this.number = number;}
    public String getName() {return name;}
    public void <b>setName</b>(String name) {this.name = name;}
    <b>public NamedNumber()</b> {}
    private int number;
    private String name;
}
          </pre>
        </blockquote>
      </li>

      <li>Interface with only getters:

        <blockquote>
          <pre>
public interface NamedNumber {
    public int getNumber();
    public String getName();
}
          </pre>
        </blockquote>
      </li>
    </ol>

    <p>It is usually better for classes that simply represent a
      collection of data to be <em>immutable</em>.  An instance of an
      immutable class cannot be changed after it has been constructed.
      Notice that {@code CompositeData} itself is immutable.
      Immutability has many advantages, notably with regard to
      thread-safety and security.  So the approach using setters should
      generally be avoided if possible.</p>


    <h3>Recursive types</h3>

    <p>Recursive (self-referential) types cannot be used in MXBean
      interfaces.  This is a consequence of the immutability of {@link
      CompositeType}.  For example, the following type could not be the
      type of an attribute, because it refers to itself:</p>

    <pre>
public interface <b>Node</b> {
    public String getName();
    public int getPriority();
    public <b>Node</b> getNext();
}
</pre>

    <p>It is always possible to rewrite recursive types like this so
      they are no longer recursive.  Doing so may require introducing
      new types.  For example:</p>

    <pre>
public interface <b>NodeList</b> {
    public List&lt;Node&gt; getNodes();
}

public interface Node {
    public String getName();
    public int getPriority();
}
</pre>

    <h3>MBeanInfo contents for an MXBean</h3>

    <p>An MXBean is a type of Open MBean.  However, for compatibility
      reasons, its {@link MBeanInfo} is not an {@link OpenMBeanInfo}.
      In particular, when the type of an attribute, parameter, or
      operation return value is a primitive type such as {@code int},
      or is {@code void} (for a return type), then the attribute,
      parameter, or operation will be represented respectively by an
      {@link MBeanAttributeInfo}, {@link MBeanParameterInfo}, or
      {@link MBeanOperationInfo} whose {@code getType()} or {@code
      getReturnType()} returns the primitive name ("{@code int}" etc).
      This is so even though the mapping rules above specify that the
      <em>opendata</em> mapping is the wrapped type ({@code Integer}
      etc).</p>

    <p>The array of public constructors returned by {@link
      MBeanInfo#getConstructors()} for an MXBean that is directly
      registered in the MBean Server will contain all of the public
      constructors of that MXBean.  If the class of the MXBean is not
      public then its constructors are not considered public either.
      The list returned for an MXBean that is constructed using the
      {@link StandardMBean} class is derived in the same way as for
      Standard MBeans.  Regardless of how the MXBean was constructed,
      its constructor parameters are not subject to MXBean mapping
      rules and do not have a corresponding {@code OpenType}.</p>

    <p>The array of notification types returned by {@link
      MBeanInfo#getNotifications()} for an MXBean that is directly
      registered in the MBean Server will be empty if the MXBean does
      not implement the {@link NotificationBroadcaster} interface.
      Otherwise, it will be the result of calling {@link
      NotificationBroadcaster#getNotificationInfo()} at the time the MXBean
      was registered.  Even if the result of this method changes
      subsequently, the result of {@code MBeanInfo.getNotifications()}
      will not.  The list returned for an MXBean that is constructed
      using the {@link StandardMBean} or {@link StandardEmitterMBean}
      class is derived in the same way as for Standard MBeans.</p>

    <p>The {@link Descriptor} for all of the
      {@code MBeanAttributeInfo}, {@code MBeanParameterInfo}, and
      {@code MBeanOperationInfo} objects contained in the {@code MBeanInfo}
      will have a field {@code openType} whose value is the {@link OpenType}
      specified by the mapping rules above.  So even when {@code getType()}
      is "{@code int}", {@code getDescriptor().getField("openType")} will
      be {@link SimpleType#INTEGER}.</p>

    <p>The {@code Descriptor} for each of these objects will also have a
      field {@code originalType} that is a string representing the Java type
      that appeared in the MXBean interface.  The format of this string
      is described in the section <a href="#type-names">Type Names</a>
      below.</p>

    <p>The {@code Descriptor} for the {@code MBeanInfo} will have a field
      {@code mxbean} whose value is the string "{@code true}".</p>


    <h3 id="type-names">Type Names</h3>

    <p>Sometimes the unmapped type <em>T</em> of a method parameter or
    return value in an MXBean must be represented as a string.  If
    <em>T</em> is a non-generic type, this string is the value
    returned by {@link Class#getName()}.  Otherwise it is the value of
    <em>genericstring(T)</em>, defined as follows:

    <ul>

      <li>If <em>T</em> is a non-generic non-array type,
      <em>genericstring(T)</em> is the value returned by {@link
      Class#getName()}, for example {@code "int"} or {@code
      "java.lang.String"}.

      <li>If <em>T</em> is an array <em>E[]</em>,
      <em>genericstring(T)</em> is <em>genericstring(E)</em> followed
      by {@code "[]"}.  For example, <em>genericstring({@code int[]})</em>
      is {@code "int[]"}, and <em>genericstring({@code
      List<String>[][]})</em> is {@code
      "java.util.List<java.lang.String>[][]"}.

    <li>Otherwise, <em>T</em> is a parameterized type such as {@code
    List<String>} and <em>genericstring(T)</em> consists of the
    following: the fully-qualified name of the parameterized type as
    returned by {@code Class.getName()}; a left angle bracket ({@code
    "<"}); <em>genericstring(A)</em> where <em>A</em> is the first
    type parameter; if there is a second type parameter <em>B</em>
    then {@code ", "} (a comma and a single space) followed by
    <em>genericstring(B)</em>; a right angle bracket ({@code ">"}).

    </ul>

    <p>Note that if a method returns {@code int[]}, this will be
      represented by the string {@code "[I"} returned by {@code
      Class.getName()}, but if a method returns {@code List<int[]>},
      this will be represented by the string {@code
      "java.util.List<int[]>"}.

    <h3>Exceptions</h3>

    <p>A problem with mapping <em>from</em> Java types <em>to</em>
      Open types is signaled with an {@link OpenDataException}.  This
      can happen when an MXBean interface is being analyzed, for
      example if it references a type like {@link java.util.Random
      java.util.Random} that has no getters.  Or it can happen when an
      instance is being converted (a return value from a method in an
      MXBean or a parameter to a method in an MXBean proxy), for
      example when converting from {@code SortedSet<String>} to {@code
      String[]} if the {@code SortedSet} has a non-null {@code
      Comparator}.</p>

    <p>A problem with mapping <em>to</em> Java types <em>from</em>
      Open types is signaled with an {@link InvalidObjectException}.
      This can happen when an MXBean interface is being analyzed, for
      example if it references a type that is not
      <em>reconstructible</em> according to the rules above, in a
      context where a reconstructible type is required.  Or it can
      happen when an instance is being converted (a parameter to a
      method in an MXBean or a return value from a method in an MXBean
      proxy), for example from a String to an Enum if there is no Enum
      constant with that name.</p>

    <p>Depending on the context, the {@code OpenDataException} or
      {@code InvalidObjectException} may be wrapped in another
      exception such as {@link RuntimeMBeanException} or {@link
      UndeclaredThrowableException}.  For every thrown exception,
      the condition <em>C</em> will be true: "<em>e</em> is {@code
      OpenDataException} or {@code InvalidObjectException} (as
      appropriate), or <em>C</em> is true of <em>e</em>.{@link
      Throwable#getCause() getCause()}".</p>

   @since 1.6
*/

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MXBean {
    /**
       True if the annotated interface is an MXBean interface.
       @return true if the annotated interface is an MXBean interface.
    */
    boolean value() default true;
}
