/*
 * Copyright 2005 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 4661545
 * @summary Tests to use an executor to send notifications.
 * @author Shanliang JIANG
 * @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;
}
