1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * The contents of this file are subject to the terms of either the Universal Permissive License 7 * v 1.0 as shown at http://oss.oracle.com/licenses/upl 8 * 9 * or the following license: 10 * 11 * Redistribution and use in source and binary forms, with or without modification, are permitted 12 * provided that the following conditions are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 15 * and the following disclaimer. 16 * 17 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 18 * conditions and the following disclaimer in the documentation and/or other materials provided with 19 * the distribution. 20 * 21 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to 22 * endorse or promote products derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 26 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 31 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 package org.openjdk.jmc.rjmx.test.synthetic; 34 35 import static org.junit.Assert.assertNotNull; 36 import static org.junit.Assert.assertTrue; 37 38 import java.io.IOException; 39 40 import javax.management.InstanceNotFoundException; 41 import javax.management.IntrospectionException; 42 import javax.management.ListenerNotFoundException; 43 import javax.management.MBeanInfo; 44 import javax.management.MBeanNotificationInfo; 45 import javax.management.MBeanServerConnection; 46 import javax.management.MalformedObjectNameException; 47 import javax.management.Notification; 48 import javax.management.NotificationListener; 49 import javax.management.ObjectName; 50 import javax.management.ReflectionException; 51 52 import org.junit.Assume; 53 import org.junit.Before; 54 import org.junit.Test; 55 56 import org.openjdk.jmc.rjmx.IConnectionHandle; 57 import org.openjdk.jmc.rjmx.test.ServerHandleTestCase; 58 59 public class SyntheticNotificationTest extends ServerHandleTestCase { 60 61 private IConnectionHandle handle; 62 private MBeanServerConnection connection; 63 private volatile boolean gotNotification = false; 64 65 private class SyntheticNotificationListener implements NotificationListener { 66 private Notification lastNotification; 67 68 @Override 69 public void handleNotification(Notification notification, Object handback) { 70 lastNotification = notification; 71 gotNotification = true; 72 synchronized (SyntheticNotificationTest.this) { 73 SyntheticNotificationTest.this.notify(); 74 } 75 } 76 77 public Notification getLastNotification() { 78 return lastNotification; 79 } 80 } 81 82 @Override 83 @Before 84 public void setUp() throws Exception { 85 super.setUp(); 86 handle = getDefaultServer().connect("Test"); //$NON-NLS-1$ 87 connection = handle.getServiceOrThrow(MBeanServerConnection.class); 88 gotNotification = false; 89 } 90 91 @Override 92 public void tearDown() throws Exception { 93 handle.close(); 94 } 95 96 /** 97 * Tests that we can add synthetic notifications. 98 */ 99 @Test 100 public void testGetNotificationMetadata() throws InstanceNotFoundException, IntrospectionException, 101 MalformedObjectNameException, ReflectionException, NullPointerException, IOException { 102 MBeanInfo info = connection.getMBeanInfo(new ObjectName("org.openjdk.jmc.test:type=Test")); //$NON-NLS-1$ 103 assertTrue(info.getNotifications().length > 0); 104 } 105 106 /** 107 * Tests that we can have attributes AND notifications on the same synthetic. 108 */ 109 @Test 110 public void testCombinedMetadata() throws InstanceNotFoundException, IntrospectionException, 111 MalformedObjectNameException, ReflectionException, NullPointerException, IOException { 112 MBeanInfo info = connection.getMBeanInfo(new ObjectName("org.openjdk.jmc.test:type=Test")); //$NON-NLS-1$ 113 assertTrue(info.getNotifications().length > 0); 114 assertTrue(info.getAttributes().length > 0); 115 } 116 117 /** 118 * Tests that we can overload existing real MBean with notification and still get values. 119 */ 120 @Test 121 public void testOverloadMetadata() throws InstanceNotFoundException, IntrospectionException, 122 MalformedObjectNameException, ReflectionException, NullPointerException, IOException { 123 MBeanInfo info = connection.getMBeanInfo(new ObjectName("java.lang:type=ClassLoading")); //$NON-NLS-1$ 124 assertTrue(info.getNotifications().length > 0); 125 assertTrue(info.getAttributes().length > 0); 126 } 127 128 /** 129 * Tests that we can shadow an existing notification. 130 */ 131 @Test 132 public void testShadowMetadata() throws InstanceNotFoundException, IntrospectionException, 133 MalformedObjectNameException, ReflectionException, NullPointerException, IOException { 134 Assume.assumeTrue("FIXME: Shadowing does not work yet!", false); //$NON-NLS-1$ 135 MBeanInfo info = connection.getMBeanInfo(new ObjectName("java.lang:type=Memory")); //$NON-NLS-1$ 136 assertTrue(info.getNotifications().length > 0); 137 for (MBeanNotificationInfo notificationInfo : info.getNotifications()) { 138 if (notificationInfo.getName().equals("java.management.memory.collection.threshold.exceeded")) { //$NON-NLS-1$ 139 assertTrue("Failed to shadow description", notificationInfo.getDescription().contains("shadow")); //$NON-NLS-1$ //$NON-NLS-2$ 140 assertTrue("Got the wrong type:" + notificationInfo.getNotifTypes()[0], "int".equals(notificationInfo //$NON-NLS-1$ //$NON-NLS-2$ 141 .getNotifTypes()[0])); 142 } else { 143 assertTrue("Should NOT contain shadow!", !notificationInfo.getDescription().contains("shadow")); //$NON-NLS-1$ //$NON-NLS-2$ 144 assertTrue("Should not be int!", !"int".equals(notificationInfo.getNotifTypes()[0])); //$NON-NLS-1$ //$NON-NLS-2$ 145 } 146 } 147 } 148 149 @Test 150 public void testNotificationListener() throws InstanceNotFoundException, MalformedObjectNameException, 151 NullPointerException, IOException, InterruptedException, ListenerNotFoundException { 152 Notification notif = null; 153 SyntheticNotificationListener listener = new SyntheticNotificationListener(); 154 ObjectName testMBean = new ObjectName("org.openjdk.jmc.test:type=Test"); //$NON-NLS-1$ 155 connection.addNotificationListener(testMBean, listener, null, null); 156 synchronized (this) { 157 this.wait(30000); 158 notif = listener.getLastNotification(); 159 } 160 assertTrue("Never got any notification!", gotNotification); //$NON-NLS-1$ 161 assertNotNull(notif); 162 assertTrue("Expected a user data > 0!", ((Integer) notif.getUserData()) > 0); //$NON-NLS-1$ 163 assertTrue("Expected Woho!", notif.getMessage().startsWith("Woho!")); //$NON-NLS-1$ //$NON-NLS-2$ 164 connection.removeNotificationListener(testMBean, listener, null, null); 165 } 166 }