/*
 * Copyright (c) 2003, 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 ServerNotifs.java
 * @bug 7654321
 * @summary Tests the reception of the notifications for opened and closed
 * connections
 * @author sjiang
 * @modules java.management
 * @run clean ServerNotifs
 * @run build ServerNotifs
 * @run main ServerNotifs
 */

// JAVA
import java.io.*;
import java.net.*;
import java.util.*;

// JMX
import javax.management.*;

// RJMX
import javax.management.remote.*;

public class ServerNotifs {

    private static void echo(String msg) {
        System.out.println(msg);
    }

    public static void main(String[] args) {

        try {
            // Create MBeanServer
            //
            echo("---Create the MBeanServer...");
            MBeanServer mbs = MBeanServerFactory.createMBeanServer();

            // Create RMIConnectorServer
            //
            echo("---Instantiate the RMIConnectorServer...");
            JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
            JMXConnectorServer cs =
                JMXConnectorServerFactory.newJMXConnectorServer(url,
                                                                null,
                                                                mbs);

            echo("---Register the RMIConnectorServer in the MBeanServer...");
            ObjectName on =
                new ObjectName("JMXConnectors:name=RMIConnectorServer");
            mbs.registerMBean(cs, on);

            echo("---Start the RMIConnectorServer...");
            cs.start();
            url = cs.getAddress();
            echo("---RMIConnectorServer address: " + url);

            echo("---Add a local listener to the RMIConnectorServer...");
            mbs.addNotificationListener(on, new MyListener(), null, null);

            // Create RMI connector
            //
            echo("---Instantiate the RMIConnector...");
            JMXConnector c = JMXConnectorFactory.newJMXConnector(url, null);

            // Expect to get a "jmx.remote.connection.opened" notification
            //
            echo("---Open connection...");
            c.connect(null);
            Thread.sleep(100);

            // Expect to get a "jmx.remote.connection.closed" notification
            //
            echo("---Close connection...");
            c.close();
            Thread.sleep(100);

            // Waiting for all notifications
            //
            synchronized(waiting) {
                if (!succeeded) {
                    final long waitingTime = 10000;
                    long remainingTime = waitingTime;
                    final long startTime = System.currentTimeMillis();
                    while (!succeeded && remainingTime > 0) {
                        waiting.wait(remainingTime);
                        remainingTime = waitingTime -
                            (System.currentTimeMillis() - startTime);
                    }
                }
            }

            // Stop the RMIConnectorServer
            //
            echo("---Stop the RMIConnectorServer...");
            cs.stop();

            if (!succeeded) {
                System.out.println("Timeout, did not get all notifications!");
                System.exit(1);
            }
        } catch (MBeanException mbe) {
            echo("---Test failed.");
            echo("---Got exception: " + mbe);
            mbe.getTargetException().printStackTrace();
            System.exit(1);
        } catch (RuntimeOperationsException roe) {
            echo("---Test failed.");
            echo("---Got exception: " + roe);
            roe.getTargetException().printStackTrace();
            System.exit(1);
        } catch (Throwable t) {
            echo("---Test failed.");
            echo("---Got throwable: " + t);
            t.printStackTrace();
            System.exit(1);
        }
    }

    private static class MyListener implements NotificationListener {
        public void handleNotification(Notification n, Object o) {
            if (index == types.length) {
                return;
            }
            echo("---Got a notification: " + n.getType());
            echo(n.getMessage());
            if (n instanceof JMXConnectionNotification) {
                if (!n.getType().equals(types[index++])) {
                    System.out.println("Waiting to get a notification with " +
                                       "type: " + types[index-1] + ", but " +
                                       "got one with type: " + n.getType());
                    System.exit(1);
                }
                if (index == types.length) {
                    synchronized(waiting) {
                        succeeded = true;
                        waiting.notify();
                    }
                }
            }
        }
    }

    private static final String[] types =
        new String[] {JMXConnectionNotification.OPENED,
                      JMXConnectionNotification.CLOSED};
    private static int index = 0;
    private static int[] waiting = new int[0];
    private static boolean succeeded = false;
}