0N/A/*
2362N/A * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A * @test
0N/A * @bug 4661545
0N/A * @summary Tests to use an executor to send notifications.
0N/A * @author Shanliang JIANG
0N/A * @run clean NotifExecutorTest
0N/A * @run build NotifExecutorTest
0N/A * @run main NotifExecutorTest
0N/A */
0N/A
0N/A// java imports
0N/A//
0N/Aimport java.io.IOException;
0N/Aimport java.util.concurrent.*;
0N/A
0N/A// JMX imports
0N/A//
0N/Aimport javax.management.*;
0N/Aimport javax.management.remote.*;
0N/A
0N/Apublic class NotifExecutorTest {
0N/A
0N/A public static void main(String[] args) throws Exception {
0N/A System.out.println("Tests to use an executor to send notifications.");
0N/A
0N/A final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
0N/A final ObjectName mbean = new ObjectName ("Default:name=NotificationEmitter");
0N/A final MyListener myLister = new MyListener();
0N/A final NotificationListener nullListener = new NotificationListener() {
0N/A public void handleNotification(Notification n, Object hb) {
0N/A // nothing
0N/A }
0N/A };
0N/A final Object[] params = new Object[] {new Integer(nb)};
0N/A final String[] signatures = new String[] {"java.lang.Integer"};
0N/A
0N/A // test with null executor
0N/A System.out.println(">>> Test with a null executor.");
0N/A mbs.registerMBean(new NotificationEmitter(null), mbean);
0N/A
0N/A mbs.addNotificationListener(mbean, myLister, null, null);
0N/A mbs.addNotificationListener(mbean, nullListener, null, null);
0N/A
0N/A mbs.invoke(mbean, "sendNotifications", params, signatures);
0N/A check(nb, 0);
0N/A
0N/A mbs.unregisterMBean(mbean);
0N/A
0N/A // test with an executor
0N/A System.out.println(">>> Test with a executor.");
0N/A mbs.registerMBean(new NotificationEmitter(
0N/A new NotifExecutorTest.MyExecutor()), mbean);
0N/A mbs.addNotificationListener(mbean, myLister, null, null);
0N/A mbs.addNotificationListener(mbean, nullListener, null, null);
0N/A
0N/A mbs.invoke(mbean, "sendNotifications", params, signatures);
0N/A
0N/A check(nb, nb*2);
0N/A
0N/A // test without listener
0N/A System.out.println(">>> Test without listener.");
0N/A
0N/A mbs.removeNotificationListener(mbean, myLister);
0N/A mbs.removeNotificationListener(mbean, nullListener);
0N/A
0N/A mbs.invoke(mbean, "sendNotifications", params, signatures);
0N/A check(0, 0);
0N/A }
0N/A
0N/A private static void check(int notifs, int called) throws Exception {
0N/A // Waiting...
0N/A synchronized (lock) {
0N/A for (int i = 0; i < 10; i++) {
0N/A if (receivedNotifs < notifs) {
0N/A lock.wait(1000);
0N/A }
0N/A }
0N/A }
0N/A
0N/A // Waiting again to ensure no more notifs
0N/A //
0N/A Thread.sleep(1000);
0N/A
0N/A // checking
0N/A synchronized (lock) {
0N/A if (receivedNotifs != notifs) {
0N/A throw new RuntimeException("The listener expected to receive " +
0N/A notifs + " notifs, but got " + receivedNotifs);
0N/A } else {
0N/A System.out.println(">>> The listener recieved as expected: "+receivedNotifs);
0N/A }
0N/A
0N/A if (calledTimes != called) {
0N/A throw new RuntimeException("The notif executor should be called " +
0N/A called + " times, but got " + calledTimes);
0N/A } else {
0N/A System.out.println(">>> The executor was called as expected: "+calledTimes);
0N/A }
0N/A }
0N/A
0N/A // clean
0N/A receivedNotifs = 0;
0N/A calledTimes = 0;
0N/A }
0N/A
0N/A
0N/A //--------------------------
0N/A // private classes
0N/A //--------------------------
0N/A private static class MyListener implements NotificationListener {
0N/A public void handleNotification(Notification notif, Object handback) {
0N/A synchronized(lock) {
0N/A if(++receivedNotifs >= nb) {
0N/A lock.notifyAll();
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A public static class NotificationEmitter
0N/A extends NotificationBroadcasterSupport
0N/A implements NotificationEmitterMBean {
0N/A
0N/A public NotificationEmitter(Executor executor) {
0N/A super(executor);
0N/A }
0N/A
0N/A /**
0N/A * Send a Notification object with the specified times.
0N/A * The sequence number will be from zero to times-1.
0N/A *
0N/A * @param nb The number of notifications to send
0N/A */
0N/A public void sendNotifications(Integer nb) {
0N/A System.out.println(">>> NotificationEmitter: asked to send " +
0N/A "notifications: " + nb);
0N/A
0N/A Notification notif;
0N/A for (int i = 1; i <= nb.intValue(); i++) {
0N/A notif = new Notification(null, this, ++seqno);
0N/A super.sendNotification(notif);
0N/A }
0N/A }
0N/A }
0N/A
0N/A public interface NotificationEmitterMBean {
0N/A public void sendNotifications(Integer nb);
0N/A }
0N/A
0N/A public static class MyExecutor extends ThreadPoolExecutor {
0N/A public MyExecutor() {
0N/A super(1, 1, 1L, TimeUnit.MILLISECONDS,
0N/A new ArrayBlockingQueue(nb*5));
0N/A }
0N/A
0N/A public synchronized void execute(Runnable job) {
0N/A synchronized(lock) {
0N/A calledTimes++;
0N/A }
0N/A
0N/A super.execute(job);
0N/A }
0N/A }
0N/A
0N/A private static int nb = 10;
0N/A private static int receivedNotifs = 0;
0N/A private static int[] lock = new int[0];
0N/A private static volatile long seqno;
0N/A
0N/A private static int calledTimes = 0;
0N/A}