/*
 * Copyright (c) 2005, 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 6200391
 * @summary Test that the jmx.monitor.error.runtime monitor notification
 *          is emitted when getAttribute throws RuntimeException.
 * @author Luis-Miguel Alventosa
 * @run clean RuntimeExceptionTest MBeanServerBuilderImpl
 *            MBeanServerForwarderInvocationHandler
 * @run build RuntimeExceptionTest MBeanServerBuilderImpl
 *            MBeanServerForwarderInvocationHandler
 * @run main RuntimeExceptionTest
 */

import java.lang.reflect.Proxy;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.monitor.CounterMonitor;
import javax.management.monitor.GaugeMonitor;
import javax.management.monitor.MonitorNotification;
import javax.management.monitor.StringMonitor;

public class RuntimeExceptionTest implements NotificationListener {

    // MBean class
    public class ObservedObject implements ObservedObjectMBean {
        public Integer getIntegerAttribute() {
            return i;
        }
        public void setIntegerAttribute(Integer i) {
            this.i = i;
        }
        public String getStringAttribute() {
            return s;
        }
        public void setStringAttribute(String s) {
            this.s = s;
        }
        private Integer i = 1;
        private String s = "dummy";
    }

    // MBean interface
    public interface ObservedObjectMBean {
        public Integer getIntegerAttribute();
        public void setIntegerAttribute(Integer i);
        public String getStringAttribute();
        public void setStringAttribute(String s);
    }

    // Notification handler
    public void handleNotification(Notification notification, Object handback) {
        echo(">>> Received notification: " + notification);
        if (notification instanceof MonitorNotification) {
            String type = notification.getType();
            if (type.equals(MonitorNotification.RUNTIME_ERROR)) {
                MonitorNotification mn = (MonitorNotification) notification;
                echo("\tType: " + mn.getType());
                echo("\tTimeStamp: " + mn.getTimeStamp());
                echo("\tObservedObject: " + mn.getObservedObject());
                echo("\tObservedAttribute: " + mn.getObservedAttribute());
                echo("\tDerivedGauge: " + mn.getDerivedGauge());
                echo("\tTrigger: " + mn.getTrigger());
                messageReceived = true;
            }
        }
    }

    /**
     * Update the counter and check for notifications
     */
    public int counterMonitorNotification() throws Exception {

        CounterMonitor counterMonitor = new CounterMonitor();
        try {
            // Create a new CounterMonitor MBean and add it to the MBeanServer.
            //
            echo(">>> CREATE a new CounterMonitor MBean");
            ObjectName counterMonitorName = new ObjectName(
                            domain + ":type=" + CounterMonitor.class.getName());
            server.registerMBean(counterMonitor, counterMonitorName);

            echo(">>> ADD a listener to the CounterMonitor");
            counterMonitor.addNotificationListener(this, null, null);

            //
            // MANAGEMENT OF A STANDARD MBEAN
            //

            echo(">>> SET the attributes of the CounterMonitor:");

            counterMonitor.addObservedObject(obsObjName);
            echo("\tATTRIBUTE \"ObservedObject\"    = " + obsObjName);

            counterMonitor.setObservedAttribute("IntegerAttribute");
            echo("\tATTRIBUTE \"ObservedAttribute\" = IntegerAttribute");

            counterMonitor.setNotify(false);
            echo("\tATTRIBUTE \"NotifyFlag\"        = false");

            Integer threshold = 2;
            counterMonitor.setInitThreshold(threshold);
            echo("\tATTRIBUTE \"Threshold\"         = " + threshold);

            int granularityperiod = 500;
            counterMonitor.setGranularityPeriod(granularityperiod);
            echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);

            echo(">>> START the CounterMonitor");
            counterMonitor.start();

            // Wait for granularity period (multiplied by 2 for sure)
            //
            Thread.sleep(granularityperiod * 2);

            // Check if notification was received
            //
            if (messageReceived) {
                echo("\tOK: CounterMonitor got RUNTIME_ERROR notification!");
            } else {
                echo("\tKO: CounterMonitor did not get " +
                     "RUNTIME_ERROR notification!");
                return 1;
            }
        } finally {
            messageReceived = false;
            if (counterMonitor != null)
                counterMonitor.stop();
        }

        return 0;
    }

    /**
     * Update the gauge and check for notifications
     */
    public int gaugeMonitorNotification() throws Exception {

        GaugeMonitor gaugeMonitor = new GaugeMonitor();
        try {
            // Create a new GaugeMonitor MBean and add it to the MBeanServer.
            //
            echo(">>> CREATE a new GaugeMonitor MBean");
            ObjectName gaugeMonitorName = new ObjectName(
                            domain + ":type=" + GaugeMonitor.class.getName());
            server.registerMBean(gaugeMonitor, gaugeMonitorName);

            echo(">>> ADD a listener to the GaugeMonitor");
            gaugeMonitor.addNotificationListener(this, null, null);

            //
            // MANAGEMENT OF A STANDARD MBEAN
            //

            echo(">>> SET the attributes of the GaugeMonitor:");

            gaugeMonitor.addObservedObject(obsObjName);
            echo("\tATTRIBUTE \"ObservedObject\"    = " + obsObjName);

            gaugeMonitor.setObservedAttribute("IntegerAttribute");
            echo("\tATTRIBUTE \"ObservedAttribute\" = IntegerAttribute");

            gaugeMonitor.setNotifyLow(false);
            gaugeMonitor.setNotifyHigh(false);
            echo("\tATTRIBUTE \"Notify Low  Flag\"  = false");
            echo("\tATTRIBUTE \"Notify High Flag\"  = false");

            Integer highThreshold = 3, lowThreshold = 2;
            gaugeMonitor.setThresholds(highThreshold, lowThreshold);
            echo("\tATTRIBUTE \"Low  Threshold\"    = " + lowThreshold);
            echo("\tATTRIBUTE \"High Threshold\"    = " + highThreshold);

            int granularityperiod = 500;
            gaugeMonitor.setGranularityPeriod(granularityperiod);
            echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);

            echo(">>> START the GaugeMonitor");
            gaugeMonitor.start();

            // Wait for granularity period (multiplied by 2 for sure)
            //
            Thread.sleep(granularityperiod * 2);

            // Check if notification was received
            //
            if (messageReceived) {
                echo("\tOK: GaugeMonitor got RUNTIME_ERROR notification!");
            } else {
                echo("\tKO: GaugeMonitor did not get " +
                     "RUNTIME_ERROR notification!");
                return 1;
            }
        } finally {
            messageReceived = false;
            if (gaugeMonitor != null)
                gaugeMonitor.stop();
        }

        return 0;
    }

    /**
     * Update the string and check for notifications
     */
    public int stringMonitorNotification() throws Exception {

        StringMonitor stringMonitor = new StringMonitor();
        try {
            // Create a new StringMonitor MBean and add it to the MBeanServer.
            //
            echo(">>> CREATE a new StringMonitor MBean");
            ObjectName stringMonitorName = new ObjectName(
                            domain + ":type=" + StringMonitor.class.getName());
            server.registerMBean(stringMonitor, stringMonitorName);

            echo(">>> ADD a listener to the StringMonitor");
            stringMonitor.addNotificationListener(this, null, null);

            //
            // MANAGEMENT OF A STANDARD MBEAN
            //

            echo(">>> SET the attributes of the StringMonitor:");

            stringMonitor.addObservedObject(obsObjName);
            echo("\tATTRIBUTE \"ObservedObject\"    = " + obsObjName);

            stringMonitor.setObservedAttribute("StringAttribute");
            echo("\tATTRIBUTE \"ObservedAttribute\" = StringAttribute");

            stringMonitor.setNotifyMatch(false);
            echo("\tATTRIBUTE \"NotifyMatch\"       = false");

            stringMonitor.setNotifyDiffer(false);
            echo("\tATTRIBUTE \"NotifyDiffer\"      = false");

            stringMonitor.setStringToCompare("dummy");
            echo("\tATTRIBUTE \"StringToCompare\"   = \"dummy\"");

            int granularityperiod = 500;
            stringMonitor.setGranularityPeriod(granularityperiod);
            echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);

            echo(">>> START the StringMonitor");
            stringMonitor.start();

            // Wait for granularity period (multiplied by 2 for sure)
            //
            Thread.sleep(granularityperiod * 2);

            // Check if notification was received
            //
            if (messageReceived) {
                echo("\tOK: StringMonitor got RUNTIME_ERROR notification!");
            } else {
                echo("\tKO: StringMonitor did not get " +
                     "RUNTIME_ERROR notification!");
                return 1;
            }
        } finally {
            messageReceived = false;
            if (stringMonitor != null)
                stringMonitor.stop();
        }

        return 0;
    }

    /**
     * Test the monitor notifications.
     */
    public int monitorNotifications() throws Exception {

        server = MBeanServerFactory.newMBeanServer();

        MBeanServerForwarderInvocationHandler mbsfih =
            (MBeanServerForwarderInvocationHandler)
            Proxy.getInvocationHandler(server);

        mbsfih.setGetAttributeException(
            new RuntimeException("Test RuntimeException"));

        domain = server.getDefaultDomain();

        obsObjName = ObjectName.getInstance(domain + ":type=ObservedObject");
        server.registerMBean(new ObservedObject(), obsObjName);

        echo(">>> ----------------------------------------");
        int error = counterMonitorNotification();
        echo(">>> ----------------------------------------");
        error += gaugeMonitorNotification();
        echo(">>> ----------------------------------------");
        error += stringMonitorNotification();
        echo(">>> ----------------------------------------");
        return error;
    }

    /*
     * Print message
     */
    private static void echo(String message) {
        System.out.println(message);
    }

    /*
     * Standalone entry point.
     *
     * Run the test and report to stdout.
     */
    public static void main (String args[]) throws Exception {
        System.setProperty("javax.management.builder.initial",
                           MBeanServerBuilderImpl.class.getName());
        RuntimeExceptionTest test = new RuntimeExceptionTest();
        int error = test.monitorNotifications();
        if (error > 0) {
            echo(">>> Unhappy Bye, Bye!");
            throw new IllegalStateException("Test FAILED: Didn't get all " +
                                            "the notifications that were " +
                                            "expected by the test!");
        } else {
            echo(">>> Happy Bye, Bye!");
        }
    }

    // Flag to notify that a message has been received
    private boolean messageReceived = false;

    private MBeanServer server;
    private ObjectName obsObjName;
    private String domain;
}
