jdk/test/javax/management/mxbean/Basic.java
changeset 34827 de746e7eb1e3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/Basic.java	Fri Dec 18 17:42:06 2015 +0100
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2005, 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.
+ */
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import javax.management.Descriptor;
+import javax.management.ImmutableDescriptor;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+
+/**
+ * Class Basic
+ * Basic Description
+ */
+public class Basic implements BasicMXBean, NotificationEmitter,
+                              MBeanRegistration {
+
+    public static final String EXCEPTION_MESSAGE = "from Basic";
+    public static final String NOTIFICATION_MESSAGE = "from Basic";
+    /** Attribute : IntAtt */
+    private int intAtt = 0;
+    /** Attribute : IntegerAtt */
+    private Integer integerAtt = 0;
+    /** Attribute : BoolAtt */
+    private boolean boolAtt = false;
+    /** Attribute : BooleanAtt */
+    private Boolean booleanAtt = false;
+    /** Attribute : StringAtt */
+    private String stringAtt = null;
+    /** Attribute : DateAtt */
+    private Date dateAtt = null;
+    /** Attribute : ObjectNameAtt */
+    private ObjectName objectNameAtt = null;
+    /** Attribute : NotifDescriptorAsMapAtt */
+    private Map<String, String> notifDescriptorAsMapAtt = null;
+    /** Attribute : NotifDescriptorAtt */
+    private Descriptor notifDescriptorAtt = null;
+    /** Attribute : SqeParameter */
+    private SqeParameter sqeParameterAtt = null;
+
+    /* Creates a new instance of Basic */
+    @SqeDescriptorKey("CONSTRUCTOR Basic")
+    public Basic() {
+    }
+
+    /* Creates a new instance of Basic */
+    @SqeDescriptorKey("CONSTRUCTOR Basic")
+    public Basic(
+            @SqeDescriptorKey("CONSTRUCTOR PARAMETER SqeParameter") SqeParameter param) {
+    }
+
+    /**
+     * Get int attribute
+     */
+    public int getIntAtt() {
+        return intAtt;
+    }
+
+    /**
+     * Set int attribute
+     */
+    public void setIntAtt(int value) {
+        intAtt = value;
+    }
+
+    /**
+     * Get Integer attribute
+     */
+    public Integer getIntegerAtt() {
+        return integerAtt;
+    }
+
+    /**
+     * Set Integer attribute
+     */
+    public void setIntegerAtt(Integer value) {
+        integerAtt = value;
+    }
+
+    /**
+     * Get boolean attribute
+     */
+    public boolean getBoolAtt() {
+        return boolAtt;
+    }
+
+    /**
+     * Set boolean attribute
+     */
+    public void setBoolAtt(boolean value) {
+        boolAtt = value;
+    }
+
+    /**
+     * Get Boolean attribute
+     */
+    public Boolean getBooleanAtt() {
+        return booleanAtt;
+    }
+
+    /**
+     * Set Boolean attribute
+     */
+    public void setBooleanAtt(Boolean value) {
+        booleanAtt = value;
+    }
+
+    /**
+     * Get String attribute
+     */
+    public String getStringAtt() {
+        return stringAtt;
+    }
+
+    /**
+     * Set String attribute
+     */
+    public void setStringAtt(String value) {
+        stringAtt = value;
+    }
+
+    /**
+     * Get Date attribute
+     */
+    public Date getDateAtt() {
+        return dateAtt;
+    }
+
+    /**
+     * Set Date attribute
+     */
+    public void setDateAtt(Date value) {
+        dateAtt = value;
+    }
+
+    /**
+     * Get ObjectName attribute
+     */
+    public ObjectName getObjectNameAtt() {
+        return objectNameAtt;
+    }
+
+    /**
+     * Set ObjectName attribute
+     */
+    public void setObjectNameAtt(ObjectName value) {
+        objectNameAtt = value;
+    }
+
+    /**
+     * Get SqeParameter attribute
+     */
+    public SqeParameter getSqeParameterAtt() throws Exception {
+        if (sqeParameterAtt == null) {
+            sqeParameterAtt = new SqeParameter();
+            sqeParameterAtt.setGlop("INITIALIZED");
+        }
+
+        return sqeParameterAtt;
+    }
+
+    /**
+     * Set SqeParameter attribute
+     */
+    public void setSqeParameterAtt(SqeParameter value) {
+        sqeParameterAtt = value;
+    }
+
+    /**
+     * Get the Descriptor used to build the NotificationInfo
+     * of emitted notifications.
+     */
+    public Map<String, String> getNotifDescriptorAsMapAtt() {
+        if (notifDescriptorAsMapAtt == null) {
+            initNotifDescriptorAtt();
+        }
+
+        return notifDescriptorAsMapAtt;
+    }
+
+    /**
+     * Set the Descriptor used to build the NotificationInfo
+     * of emitted notifications.
+     * <br>A Map<String, Object> would better fit Descriptor needs but then
+     * it is not convertible according the MXBean specification so the MBean
+     * registration fails.
+     * As we plan to test our custom Descriptor finds its way into
+     * the metadata of emitted notifications, String is good enough.
+     */
+    public void setNotifDescriptorAsMapAtt(Map<String, String> value) {
+        notifDescriptorAsMapAtt = new HashMap<String, String>(value);
+        notifDescriptorAtt = new ImmutableDescriptor(value);
+    }
+
+    /**
+     * Do nothing
+     */
+    public void doNothing() {
+        // I said NOTHING !
+    }
+
+    /**
+     * Do take SqeParameter as a parameter
+     */
+    public void doWeird(SqeParameter param) {
+    }
+
+    /**
+     * Throw an Exception
+     */
+    public void throwException() throws Exception {
+        throw new Exception(EXCEPTION_MESSAGE);
+    }
+
+    /**
+     * Throw an Error
+     */
+    public void throwError() {
+        throw new InternalError(EXCEPTION_MESSAGE);
+    }
+
+    /**
+     * Reset all attributes
+     */
+    public void reset() {
+        intAtt = 0;
+        integerAtt = 0;
+        boolAtt = false;
+        booleanAtt = Boolean.FALSE;
+        stringAtt = null;
+        dateAtt = null;
+        objectNameAtt = null;
+    }
+
+    /**
+     * Returns the weather for the coming days
+     * @param verbose <code>boolean</code> verbosity
+     * @throws java.lang.Exception <code>storm</code>
+     * @return <code>ObjectName</code>
+     */
+    public Weather getWeather(boolean verbose)
+            throws java.lang.Exception {
+        return Weather.SUNNY;
+    }
+
+    // Starting here are the 4 methods of MBeanRegistration interface.
+    // We use that to grab the ObjectName the MBean is registered with.
+    //
+    public ObjectName preRegister(MBeanServer server, ObjectName name)
+            throws Exception {
+        // Grab a reference on the MBeanServer we're registered in.
+        mbs = server;
+        // Compute the name we're registered with.
+        if (name != null) {
+            mbeanName = name;
+            return name;
+        } else {
+            mbeanName =
+                new ObjectName("sqe:type=" + Basic.class.getName());
+            return mbeanName;
+        }
+    }
+
+    public void postRegister(Boolean registrationDone) {
+        // Do nothing
+    }
+
+    public void preDeregister() throws Exception {
+        // Do nothing
+    }
+
+    public void postDeregister() {
+        // Do nothing
+    }
+
+    /**
+     * Send one Notification of the provided notifType type.
+     */
+    public void sendNotification(String notifType) {
+        Notification notification = null;
+
+        if (notifType.equals(NOTIF_TYPE_0)) {
+            notification = new Notification(NOTIF_TYPE_0,
+                    mbeanName,
+                    seqNumber,
+                    NOTIFICATION_MESSAGE);
+        } else if (notifType.equals(NOTIF_TYPE_1)) {
+            notification = new SqeNotification(NOTIF_TYPE_1,
+                    mbeanName,
+                    seqNumber,
+                    NOTIFICATION_MESSAGE);
+        }
+
+        seqNumber++;
+        broadcaster.sendNotification(notification);
+    }
+
+    /**
+     * That method starts a set of threads, each thread sends a given number of
+     * notifications.
+     * The number of threads can be set via the attribute numOfNotificationSenders.
+     * The number of notification sent by each thread can be set via
+     * the attribute numOfNotificationSenderLoops.
+     * Depending on the parameter customNotification we send either custom
+     * notification(s) or MBeanServer registration and unregistration notification(s).
+     * When customNotification=true the total number of notification(s) sent is
+     * (numOfNotificationSenders * numOfNotificationSenderLoops). They are
+     * sequentially of type NOTIF_TYPE_0 then NOTIF_TYPE_1 and so on.
+     *
+     * When customNotification=false the total number of notification(s) sent is
+     * (numOfNotificationSenders * numOfNotificationSenderLoops) registration
+     * notification(s)
+     * +
+     * (numOfNotificationSenders * numOfNotificationSenderLoops) unregistration
+     * notification(s)
+     *
+     * @throws java.lang.Exception
+     */
+    public void sendNotificationWave(boolean customNotification) throws
+            Exception {
+        // Build the set of notification sender.
+        Collection<Callable<Integer>> tasks =
+                new HashSet<Callable<Integer>>(numOfNotificationSenders);
+
+        for (int i = 1; i <= numOfNotificationSenders; i++) {
+            tasks.add(new NotifSender(numOfNotificationSenderLoops,
+                    customNotification, i));
+        }
+
+        // Start all notification sender in parallel.
+        ExecutorService execServ = null;
+        try {
+            execServ = Executors.newFixedThreadPool(numOfNotificationSenders);
+            List<Future<Integer>> taskHandlers = execServ.invokeAll(tasks);
+            checkNotifSenderThreadStatus(taskHandlers);
+        } finally {
+            if (!execServ.isShutdown()) {
+                execServ.shutdown();
+            }
+        }
+    }
+
+    public void setNumOfNotificationSenders(int value) {
+        numOfNotificationSenders = value;
+    }
+
+    public void setNumOfNotificationSenderLoops(int value) {
+        numOfNotificationSenderLoops = value;
+    }
+
+    /**
+     * MBean Notification support
+     * You shouldn't update these methods
+     */
+    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">
+    public void addNotificationListener(NotificationListener listener,
+                                        NotificationFilter filter,
+                                        Object handback)
+            throws IllegalArgumentException {
+        broadcaster.addNotificationListener(listener, filter, handback);
+    }
+
+    public MBeanNotificationInfo[] getNotificationInfo() {
+        if (notifDescriptorAtt == null) {
+            initNotifDescriptorAtt();
+        }
+
+        return new MBeanNotificationInfo[]{
+                    new MBeanNotificationInfo(new String[]{
+                        NOTIF_TYPE_0
+                    },
+                    javax.management.Notification.class.getName(),
+                    "Standard JMX Notification",
+                    notifDescriptorAtt),
+                    new MBeanNotificationInfo(new String[]{
+                        NOTIF_TYPE_1
+                    },
+                    SqeNotification.class.getName(),
+                    "SQE Notification",
+                    notifDescriptorAtt)
+                };
+    }
+
+    public void removeNotificationListener(NotificationListener listener)
+            throws ListenerNotFoundException {
+        broadcaster.removeNotificationListener(listener);
+    }
+
+    public void removeNotificationListener(NotificationListener listener,
+                                           NotificationFilter filter,
+                                           Object handback)
+            throws ListenerNotFoundException {
+        broadcaster.removeNotificationListener(listener, filter, handback);
+    }
+    // </editor-fold>
+    private synchronized long getNextSeqNumber() {
+        return seqNumber++;
+    }
+
+    private void initNotifDescriptorAtt() {
+        String key = "CRABE";
+        String value = "TAMBOUR";
+        notifDescriptorAtt =
+                new ImmutableDescriptor(new String[]{key + "=" + value});
+        notifDescriptorAsMapAtt =
+                new HashMap<String, String>();
+        notifDescriptorAsMapAtt.put(key, value);
+    }
+
+    private void checkNotifSenderThreadStatus(
+            List<Future<Integer>> taskHandlers)
+            throws Exception {
+        String msgTag = "Basic::checkNotifSenderThreadStatus: ";
+        // Grab back status of each notification sender.
+        for (Future<Integer> f : taskHandlers) {
+            if (f.isCancelled()) {
+                String message = msgTag +
+                        "---- ERROR : One thread has been cancelled";
+                System.out.println(message);
+                throw new RuntimeException(message);
+            } else {
+                Integer effectiveNumOfLoops = f.get();
+
+                if (effectiveNumOfLoops != numOfNotificationSenderLoops) {
+                    String message = msgTag + "---- ERROR : One thread did " +
+                            effectiveNumOfLoops + " loops in place of " +
+                            numOfNotificationSenderLoops;
+                    System.out.println(message);
+                    throw new RuntimeException(message);
+                }
+            }
+        }
+    }
+    //
+    private int numOfNotificationSenderLoops = 2;
+    private int numOfNotificationSenders = 13;
+
+    private class NotifSender implements Callable<Integer> {
+
+        private int cycles;
+        private boolean customNotification;
+        private int senderID;
+
+        public NotifSender(int cycles, boolean customNotification, int id) {
+            this.cycles = cycles;
+            this.customNotification = customNotification;
+            this.senderID = id;
+        }
+
+        public Integer call() throws Exception {
+            int callsDone = 0;
+
+            try {
+                for (int i = 1; i <= cycles; i++) {
+                    if (customNotification) {
+                        if (i % 2 == 0) {
+                            sendNotification(NOTIF_TYPE_0);
+                        } else {
+                            sendNotification(NOTIF_TYPE_1);
+                        }
+                    } else {
+                        ObjectName mbeanName = new ObjectName("SQE:type=" +
+                                mbeanClassName + ",senderID=" + senderID);
+                        mbs.createMBean(mbeanClassName, mbeanName);
+                        mbs.unregisterMBean(mbeanName);
+                    }
+                    callsDone++;
+                }
+            } catch (Exception e) {
+                System.out.println("NotifSender::call: (ERROR) Thread [" + senderID +
+                        "] failed after " + callsDone + " cycles");
+                throw e;
+            }
+
+            return Integer.valueOf(callsDone);
+        }
+    }
+
+    //
+    private long seqNumber;
+    private final NotificationBroadcasterSupport broadcaster =
+            new NotificationBroadcasterSupport();
+    private ObjectName mbeanName;
+    private MBeanServer mbs;
+    private String mbeanClassName = "Simple";
+
+    /**
+     * Notification types definitions. To use when creating JMX Notifications.
+     */
+    public static final String NOTIF_TYPE_0 =
+            "sqe.notification.a.type";
+    public static final String NOTIF_TYPE_1 =
+            "sqe.notification.b.type";
+}