jdk/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java
author duke
Sat, 01 Dec 2007 00:00:00 +0000
changeset 2 90ce3da70b43
child 1004 5ba8217eb504
permissions -rw-r--r--
Initial load

/*
 * 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;
}