/*
 * Copyright 2003 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.
 *
 * 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.
 */

/*
 * @test
 * @bug 7654321
 * @summary Tests whether a listener receives notifs emitted before the
 * listener is registered.
 * @author Shanliang JIANG
 * @run clean UnexpectedNotifTest
 * @run build UnexpectedNotifTest
 * @run main UnexpectedNotifTest
 */

// java imports
//
import java.io.IOException;

// JMX imports
//
import javax.management.*;
import javax.management.remote.*;

public class UnexpectedNotifTest {

    public static void main(String[] args) throws Exception {
        String[] protos = null;
        try {
            Class.forName("javax.management.remote.jmxmp.JMXMPConnectorServer");
            protos = new String[2];
            protos[0] = "rmi";
            protos[1] = "jmxmp";
        } catch (ClassNotFoundException e) {
            protos = new String[1];
            protos[0] = "rmi";
        }
        for (int i = 0; i < protos.length; i++) {
            System.out.println("Unexpected notifications test for protocol " +
                               protos[i]);
            MBeanServer mbs = null;
            try {
                // Create a MBeanServer
                //
                mbs = MBeanServerFactory.createMBeanServer();

                // Create a NotificationEmitter MBean
                //
                mbean = new ObjectName ("Default:name=NotificationEmitter");
                mbs.registerMBean(new NotificationEmitter(), mbean);

                // Create a connector server
                //
                url = new JMXServiceURL("service:jmx:" + protos[i] + "://");
                server = JMXConnectorServerFactory.newJMXConnectorServer(url,
                                                                         null,
                                                                         mbs);

                mbs.registerMBean(
                            server,
                            new ObjectName("Default:name=ConnectorServer"));

                server.start();

                url = server.getAddress();

                for (int j = 0; j < 2; j++) {
                    test();
                }
            } finally {
                // Stop server
                //
                server.stop();
                // Release the MBeanServer
                //
                MBeanServerFactory.releaseMBeanServer(mbs);
            }
        }
    }

    private static void test() throws Exception {
        // Create client
        //
        JMXConnector connector = JMXConnectorFactory.connect(url);
        MBeanServerConnection client = connector.getMBeanServerConnection();

        // Add listener at the client side
        //
        client.addNotificationListener(mbean, listener, null, null);

        // Cleanup
        //
        receivedNotifs = 0;

        // Ask to send notifs
        //
        Object[] params = new Object[] {new Integer(nb)};
        String[] signatures = new String[] {"java.lang.Integer"};

        client.invoke(mbean, "sendNotifications", params, signatures);

        // Waiting...
        //
        synchronized (lock) {
            for (int i = 0; i < 10; i++) {
                if (receivedNotifs < nb) {
                    lock.wait(1000);
                }
            }
        }

        // Waiting again to ensure no more notifs
        //
        Thread.sleep(3000);

        synchronized (lock) {
            if (receivedNotifs != nb) {
                throw new Exception("The client expected to receive " +
                                    nb + " notifs, but got " + receivedNotifs);
            }
        }

        // Remove listener
        //
        client.removeNotificationListener(mbean, listener);

        connector.close();
    }

    //--------------------------
    // private classes
    //--------------------------

    private static class Listener implements NotificationListener {
        public void handleNotification(Notification notif, Object handback) {
            System.out.println("Received: " + notif + " (" +
                               notif.getSequenceNumber() + ")");
            synchronized(lock) {
                if(++receivedNotifs == nb) {
                    lock.notifyAll();
                } else if (receivedNotifs > nb) {
                    System.out.println("The client expected to receive " +
                                       nb + " notifs, but got at least " +
                                       receivedNotifs);
                    System.exit(1);
                }
            }
        }
    }

    public static class NotificationEmitter
        extends NotificationBroadcasterSupport
        implements NotificationEmitterMBean {

        /**
         * Returns a NotificationInfo object containing the name of the Java
         * class of the notification and the notification types sent by this
         * notification broadcaster.
         */
        public MBeanNotificationInfo[] getNotificationInfo() {

            MBeanNotificationInfo[] ntfInfoArray = new MBeanNotificationInfo[1];

            String[] ntfTypes = new String[1];
            ntfTypes[0] = myType;

            ntfInfoArray[0] = new MBeanNotificationInfo(
                              ntfTypes,
                              "javax.management.Notification",
                              "Notifications sent by the NotificationEmitter");
            return ntfInfoArray;
        }

        /**
         * Send a Notification object with the specified times.
         * The sequence number will be from zero to times-1.
         *
         * @param nb The number of notifications to send
         */
        public void sendNotifications(Integer nb) {
            System.out.println("NotificationEmitter: asked to send " +
                               "notifications: " + nb);

            Notification notif;
            for (int i = 1; i <= nb.intValue(); i++) {
                notif = new Notification(myType, this, ++seqno);
                sendNotification(notif);
            }
        }

        private String myType = "notification.my_notification";
    }

    public interface NotificationEmitterMBean {
        public void sendNotifications(Integer nb);
    }

    private static JMXConnectorServer server;
    private static JMXServiceURL url;
    private static ObjectName mbean;
    private static NotificationListener listener = new Listener();

    private static int nb = 10;
    private static int receivedNotifs = 0;
    private static int[] lock = new int[0];
    private static volatile long seqno;
}
