/*
 * Copyright 2006 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
 * @summary Test that we can create proxies which are NotificationEmitters.
 * @bug 6411747
 * @author Daniel Fuchs
 * @run clean NotificationEmitterProxy
 * @run build NotificationEmitterProxy
 * @run main NotificationEmitterProxy
 */

import java.lang.management.ManagementFactory;

import javax.management.*;
import javax.management.remote.*;
import javax.naming.NoPermissionException;

public class NotificationEmitterProxy {

    public static class Counter {
        int count;
        public synchronized int count() {
            count++;
            notifyAll();
            return count;
        }
        public synchronized int peek() {
            return count;
        }
        public synchronized int waitfor(int max, long timeout)
            throws InterruptedException {
            final long start = System.currentTimeMillis();
            while (count < max && timeout > 0) {
                final long rest = timeout -
                        (System.currentTimeMillis() - start);
                if (rest <= 0) break;
                wait(rest);
            }
            return count;
        }
    }

    public static class CounterListener
            implements NotificationListener {
        final private Counter counter;
        public CounterListener(Counter counter) {
            this.counter = counter;
        }
        public void handleNotification(Notification notification,
                        Object handback) {
               System.out.println("Received notif from " + handback +
                                  ":\n\t" + notification);
               counter.count();
        }
    }

    public static void main(String[] args) throws Exception {
        System.out.println("<<< Register for notification from a proxy");

        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        final ObjectName name = new ObjectName(":class=Simple");

        JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
        final JMXConnectorServer server =
            JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
        server.start();
        url = server.getAddress();

        final JMXConnector client = JMXConnectorFactory.connect(url);

        final Counter counter = new Counter();
        final CounterListener listener = new CounterListener(counter);
        final Counter mxcounter = new Counter();
        final CounterListener mxlistener = new CounterListener(mxcounter);
        final NotificationFilterSupport filter =
                new NotificationFilterSupport();
        filter.enableType(MBeanServerNotification.REGISTRATION_NOTIFICATION);
        filter.enableType(MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
        int registered = 0;
        try {
            final MBeanServerDelegateMBean delegate =
                JMX.newMBeanProxy(client.getMBeanServerConnection(),
                       MBeanServerDelegate.DELEGATE_NAME,
                       MBeanServerDelegateMBean.class,
                       true);

            NotificationEmitter emitter = (NotificationEmitter)delegate;
            emitter.addNotificationListener(listener,filter,"JMX.newMBeanProxy");
        } catch (Exception x) {
            throw new RuntimeException("Failed to register listener with "+
                    " JMX.newMBeanProxy: " + x, x);
        }

        try {
            final MBeanServerDelegateMBean delegate =
                MBeanServerInvocationHandler.newProxyInstance(mbs,
                       MBeanServerDelegate.DELEGATE_NAME,
                       MBeanServerDelegateMBean.class,
                       true);

            NotificationEmitter emitter = (NotificationEmitter)delegate;
            emitter.addNotificationListener(listener,filter,
                    "MBeanServerInvocationHandler.newProxyInstance");
        } catch (Exception x) {
            throw new RuntimeException("Failed to register listener with "+
                    " MBeanServerInvocationHandler.newProxyInstance: " + x, x);
        }

        System.out.println("<<< Register an MBean.");

        final Simple simple = new Simple();
        mbs.registerMBean(simple, name);
        registered++;

        SimpleMXBean simple0 =
           JMX.newMXBeanProxy(client.getMBeanServerConnection(),
                              name,
                              SimpleMXBean.class,
                              true);

        SimpleMXBean simple1 =
            JMX.newMXBeanProxy(mbs,
                               name,
                               SimpleMXBean.class,
                               false);

        final int expected = 2*registered;
        final int reg = counter.waitfor(expected,3000);
        if (reg != expected)
            throw new RuntimeException("Bad notification count: " + reg +
                    ", expected " +expected);
        System.out.println("Received expected "+reg+
                " notifs after registerMBean");

        ((NotificationEmitter)simple0)
            .addNotificationListener(mxlistener,null,name);
        simple1.equals("Are you a Wombat?");
        final int mxnotifs = mxcounter.waitfor(1,3000);
        if (mxnotifs != 1)
             throw new RuntimeException("Bad MXBean notification count: " +
                     mxnotifs);
        System.out.println("Received expected "+mxnotifs+
                " notifs from MXBean");

        mbs.unregisterMBean(name);
        final int unreg = counter.waitfor(expected+reg,3000);
        if (unreg != (expected+reg))
            throw new RuntimeException("Bad notification count: " + unreg +
                    ", expected " +expected+reg);
        System.out.println("Received expected "+(unreg-reg)+
                " notifs after unregisterMBean");
        System.out.println("Total notifs received: " + unreg);


    }

    public static interface Simplest {

    }

    public static interface SimpleMXBean extends Simplest {
        public String equals(String x);
    }

    private static class Simple extends NotificationBroadcasterSupport
            implements SimpleMXBean {
        public static final String NOTIF_TYPE = "simple.equals";
        private static long seq=0;
        private static synchronized long seq() { return ++seq; };
        public String equals(String x) {
            sendNotification(new Notification(NOTIF_TYPE,this,seq(),x));
            return x;
        }

    }



 }
