/*
 * Copyright 2005-2006 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.management;

/**
 * <p>An MBean whose management interface is determined by reflection
 * on a Java interface, and that emits notifications.</p>
 *
 * <p>The following example shows how to use the public constructor
 * {@link #StandardEmitterMBean(Object, Class, NotificationEmitter)
 * StandardEmitterMBean(implementation, mbeanInterface, emitter)} to
 * create an MBean emitting notifications with any
 * implementation class name <i>Impl</i>, with a management
 * interface defined (as for current Standard MBeans) by any interface
 * <i>Intf</i>, and with any implementation of the interface
 * {@link NotificationEmitter}. The example uses the class
 * {@link NotificationBroadcasterSupport} as an implementation
 * of the interface {@link NotificationEmitter}.</p>
 *
 *     <pre>
 *     MBeanServer mbs;
 *     ...
 *     final String[] types = new String[] {"sun.disc.space","sun.disc.alarm"};
 *     final MBeanNotificationInfo info = new MBeanNotificationInfo(
 *                                          types,
 *                                          Notification.class.getName(),
 *                                          "Notification about disc info.");
 *     final NotificationEmitter emitter =
 *                    new NotificationBroadcasterSupport(info);
 *
 *     final Intf impl = new Impl(...);
 *     final Object mbean = new StandardEmitterMBean(
 *                                     impl, Intf.class, emitter);
 *     mbs.registerMBean(mbean, objectName);
 *     </pre>
 *
 * @see StandardMBean
 *
 * @since 1.6
 */
public class StandardEmitterMBean extends StandardMBean
        implements NotificationEmitter {

    private final NotificationEmitter emitter;
    private final MBeanNotificationInfo[] notificationInfo;

    /**
     * <p>Make an MBean whose management interface is specified by
     * {@code mbeanInterface}, with the given implementation and
     * where notifications are handled by the given {@code NotificationEmitter}.
     * The resultant MBean implements the {@code NotificationEmitter} interface
     * by forwarding its methods to {@code emitter}.  It is legal and useful
     * for {@code implementation} and {@code emitter} to be the same object.</p>
     *
     * <p>If {@code emitter} is an instance of {@code
     * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
     * sendNotification} method will call {@code emitter.}{@link
     * NotificationBroadcasterSupport#sendNotification sendNotification}.</p>
     *
     * <p>The array returned by {@link #getNotificationInfo()} on the
     * new MBean is a copy of the array returned by
     * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo
     * getNotificationInfo()} at the time of construction.  If the array
     * returned by {@code emitter.getNotificationInfo()} later changes,
     * that will have no effect on this object's
     * {@code getNotificationInfo()}.</p>
     *
     * @param implementation the implementation of the MBean interface.
     * @param mbeanInterface a Standard MBean interface.
     * @param emitter the object that will handle notifications.
     *
     * @throws IllegalArgumentException if the {@code mbeanInterface}
     *    does not follow JMX design patterns for Management Interfaces, or
     *    if the given {@code implementation} does not implement the
     *    specified interface, or if {@code emitter} is null.
     */
    public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface,
                                    NotificationEmitter emitter) {
        super(implementation, mbeanInterface, false);
        if (emitter == null)
            throw new IllegalArgumentException("Null emitter");
        this.emitter = emitter;
        this.notificationInfo = emitter.getNotificationInfo();
    }

    /**
     * <p>Make an MBean whose management interface is specified by
     * {@code mbeanInterface}, with the given implementation and where
     * notifications are handled by the given {@code
     * NotificationEmitter}.  This constructor can be used to make
     * either Standard MBeans or MXBeans.  The resultant MBean
     * implements the {@code NotificationEmitter} interface by
     * forwarding its methods to {@code emitter}.  It is legal and
     * useful for {@code implementation} and {@code emitter} to be the
     * same object.</p>
     *
     * <p>If {@code emitter} is an instance of {@code
     * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
     * sendNotification} method will call {@code emitter.}{@link
     * NotificationBroadcasterSupport#sendNotification sendNotification}.</p>
     *
     * <p>The array returned by {@link #getNotificationInfo()} on the
     * new MBean is a copy of the array returned by
     * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo
     * getNotificationInfo()} at the time of construction.  If the array
     * returned by {@code emitter.getNotificationInfo()} later changes,
     * that will have no effect on this object's
     * {@code getNotificationInfo()}.</p>
     *
     * @param implementation the implementation of the MBean interface.
     * @param mbeanInterface a Standard MBean interface.
     * @param isMXBean If true, the {@code mbeanInterface} parameter
     * names an MXBean interface and the resultant MBean is an MXBean.
     * @param emitter the object that will handle notifications.
     *
     * @throws IllegalArgumentException if the {@code mbeanInterface}
     *    does not follow JMX design patterns for Management Interfaces, or
     *    if the given {@code implementation} does not implement the
     *    specified interface, or if {@code emitter} is null.
     */
    public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface,
                                    boolean isMXBean,
                                    NotificationEmitter emitter) {
        super(implementation, mbeanInterface, isMXBean);
        if (emitter == null)
            throw new IllegalArgumentException("Null emitter");
        this.emitter = emitter;
        this.notificationInfo = emitter.getNotificationInfo();
    }

    /**
     * <p>Make an MBean whose management interface is specified by
     * {@code mbeanInterface}, and
     * where notifications are handled by the given {@code NotificationEmitter}.
     * The resultant MBean implements the {@code NotificationEmitter} interface
     * by forwarding its methods to {@code emitter}.</p>
     *
     * <p>If {@code emitter} is an instance of {@code
     * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
     * sendNotification} method will call {@code emitter.}{@link
     * NotificationBroadcasterSupport#sendNotification sendNotification}.</p>
     *
     * <p>The array returned by {@link #getNotificationInfo()} on the
     * new MBean is a copy of the array returned by
     * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo
     * getNotificationInfo()} at the time of construction.  If the array
     * returned by {@code emitter.getNotificationInfo()} later changes,
     * that will have no effect on this object's
     * {@code getNotificationInfo()}.</p>
     *
     * <p>This constructor must be called from a subclass that implements
     * the given {@code mbeanInterface}.</p>
     *
     * @param mbeanInterface a StandardMBean interface.
     * @param emitter the object that will handle notifications.
     *
     * @throws IllegalArgumentException if the {@code mbeanInterface}
     *    does not follow JMX design patterns for Management Interfaces, or
     *    if {@code this} does not implement the specified interface, or
     *    if {@code emitter} is null.
     */
    protected StandardEmitterMBean(Class<?> mbeanInterface,
                                   NotificationEmitter emitter) {
        super(mbeanInterface, false);
        if (emitter == null)
            throw new IllegalArgumentException("Null emitter");
        this.emitter = emitter;
        this.notificationInfo = emitter.getNotificationInfo();
    }

    /**
     * <p>Make an MBean whose management interface is specified by
     * {@code mbeanInterface}, and where notifications are handled by
     * the given {@code NotificationEmitter}.  This constructor can be
     * used to make either Standard MBeans or MXBeans.  The resultant
     * MBean implements the {@code NotificationEmitter} interface by
     * forwarding its methods to {@code emitter}.</p>
     *
     * <p>If {@code emitter} is an instance of {@code
     * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
     * sendNotification} method will call {@code emitter.}{@link
     * NotificationBroadcasterSupport#sendNotification sendNotification}.</p>
     *
     * <p>The array returned by {@link #getNotificationInfo()} on the
     * new MBean is a copy of the array returned by
     * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo
     * getNotificationInfo()} at the time of construction.  If the array
     * returned by {@code emitter.getNotificationInfo()} later changes,
     * that will have no effect on this object's
     * {@code getNotificationInfo()}.</p>
     *
     * <p>This constructor must be called from a subclass that implements
     * the given {@code mbeanInterface}.</p>
     *
     * @param mbeanInterface a StandardMBean interface.
     * @param isMXBean If true, the {@code mbeanInterface} parameter
     * names an MXBean interface and the resultant MBean is an MXBean.
     * @param emitter the object that will handle notifications.
     *
     * @throws IllegalArgumentException if the {@code mbeanInterface}
     *    does not follow JMX design patterns for Management Interfaces, or
     *    if {@code this} does not implement the specified interface, or
     *    if {@code emitter} is null.
     */
    protected StandardEmitterMBean(Class<?> mbeanInterface, boolean isMXBean,
                                   NotificationEmitter emitter) {
        super(mbeanInterface, isMXBean);
        if (emitter == null)
            throw new IllegalArgumentException("Null emitter");
        this.emitter = emitter;
        this.notificationInfo = emitter.getNotificationInfo();
    }

    public void removeNotificationListener(NotificationListener listener)
            throws ListenerNotFoundException {
        emitter.removeNotificationListener(listener);
    }

    public void removeNotificationListener(NotificationListener listener,
                                           NotificationFilter filter,
                                           Object handback)
            throws ListenerNotFoundException {
        emitter.removeNotificationListener(listener, filter, handback);
    }

    public void addNotificationListener(NotificationListener listener,
                                        NotificationFilter filter,
                                        Object handback) {
        emitter.addNotificationListener(listener, filter, handback);
    }

    public MBeanNotificationInfo[] getNotificationInfo() {
        return notificationInfo;
    }

    /**
     * <p>Sends a notification.</p>
     *
     * <p>If the {@code emitter} parameter to the constructor was an
     * instance of {@code NotificationBroadcasterSupport} then this
     * method will call {@code emitter.}{@link
     * NotificationBroadcasterSupport#sendNotification
     * sendNotification}.</p>
     *
     * @param n the notification to send.
     *
     * @throws ClassCastException if the {@code emitter} parameter to the
     * constructor was not a {@code NotificationBroadcasterSupport}.
     */
    public void sendNotification(Notification n) {
        if (emitter instanceof NotificationBroadcasterSupport)
            ((NotificationBroadcasterSupport) emitter).sendNotification(n);
        else {
            final String msg =
                "Cannot sendNotification when emitter is not an " +
                "instance of NotificationBroadcasterSupport: " +
                emitter.getClass().getName();
            throw new ClassCastException(msg);
        }
    }

    /**
     * <p>Get the MBeanNotificationInfo[] that will be used in the
     * MBeanInfo returned by this MBean.</p>
     *
     * <p>The default implementation of this method returns
     * {@link #getNotificationInfo()}.</p>
     *
     * @param info The default MBeanInfo derived by reflection.
     * @return the MBeanNotificationInfo[] for the new MBeanInfo.
     */
    MBeanNotificationInfo[] getNotifications(MBeanInfo info) {
        return getNotificationInfo();
    }
}
