jdk/test/javax/management/notification/NotifExecutorTest.java
author ykantser
Thu, 07 May 2015 09:11:49 +0200
changeset 30376 2ccf2cf7ea48
parent 5506 202f599c92aa
child 44423 306c020eb154
permissions -rw-r--r--
8078896: Add @modules as needed to the jdk_svc tests Reviewed-by: alanb, mchung

/*
 * Copyright (c) 2005, 2015, 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.
 *
 * 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.
 */

/*
 * @test
 * @bug 4661545
 * @summary Tests to use an executor to send notifications.
 * @author Shanliang JIANG
 * @modules java.management
 * @run clean NotifExecutorTest
 * @run build NotifExecutorTest
 * @run main NotifExecutorTest
 */

// java imports
//
import java.io.IOException;
import java.util.concurrent.*;

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

public class NotifExecutorTest {

    public static void main(String[] args) throws Exception {
        System.out.println("Tests to use an executor to send notifications.");

        final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
        final ObjectName mbean = new ObjectName ("Default:name=NotificationEmitter");
        final MyListener myLister = new MyListener();
        final NotificationListener nullListener = new NotificationListener() {
                public void handleNotification(Notification n, Object hb) {
                    // nothing
                }
            };
        final Object[] params = new Object[] {new Integer(nb)};
        final String[] signatures = new String[] {"java.lang.Integer"};

        // test with null executor
        System.out.println(">>> Test with a null executor.");
        mbs.registerMBean(new NotificationEmitter(null), mbean);

        mbs.addNotificationListener(mbean, myLister, null, null);
        mbs.addNotificationListener(mbean, nullListener, null, null);

        mbs.invoke(mbean, "sendNotifications", params, signatures);
        check(nb, 0);

        mbs.unregisterMBean(mbean);

        // test with an executor
        System.out.println(">>> Test with a executor.");
        mbs.registerMBean(new NotificationEmitter(
                           new NotifExecutorTest.MyExecutor()), mbean);
        mbs.addNotificationListener(mbean, myLister, null, null);
        mbs.addNotificationListener(mbean, nullListener, null, null);

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

        check(nb, nb*2);

        // test without listener
        System.out.println(">>> Test without listener.");

        mbs.removeNotificationListener(mbean, myLister);
        mbs.removeNotificationListener(mbean, nullListener);

        mbs.invoke(mbean, "sendNotifications", params, signatures);
        check(0, 0);
    }

    private static void check(int notifs, int called) throws Exception {
        // Waiting...
        synchronized (lock) {
            for (int i = 0; i < 10; i++) {
                if (receivedNotifs < notifs) {
                    lock.wait(1000);
                }
            }
        }

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

        // checking
        synchronized (lock) {
            if (receivedNotifs != notifs) {
                throw new RuntimeException("The listener expected to receive " +
                                           notifs + " notifs, but got " + receivedNotifs);
            } else {
                System.out.println(">>> The listener recieved as expected: "+receivedNotifs);
            }

            if (calledTimes != called) {
                throw new RuntimeException("The notif executor should be called " +
                                           called + " times, but got " + calledTimes);
            } else {
                System.out.println(">>> The executor was called as expected: "+calledTimes);
            }
        }

        // clean
        receivedNotifs = 0;
        calledTimes = 0;
    }


    //--------------------------
    // private classes
    //--------------------------
    private static class MyListener implements NotificationListener {
        public void handleNotification(Notification notif, Object handback) {
            synchronized(lock) {
                if(++receivedNotifs >= nb) {
                    lock.notifyAll();
                }
            }
        }
    }

    public static class NotificationEmitter
        extends NotificationBroadcasterSupport
        implements NotificationEmitterMBean {

        public NotificationEmitter(Executor executor) {
            super(executor);
        }

        /**
         * 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(null, this, ++seqno);
                super.sendNotification(notif);
            }
        }
    }

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

    public static class MyExecutor extends ThreadPoolExecutor {
        public MyExecutor() {
            super(1, 1, 1L, TimeUnit.MILLISECONDS,
                  new ArrayBlockingQueue(nb*5));
        }

        public synchronized void execute(Runnable job) {
            synchronized(lock) {
                calledTimes++;
            }

            super.execute(job);
        }
    }

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

    private static int calledTimes = 0;
}