1 /* 2 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @summary Test that we can create proxies which are NotificationEmitters. 27 * @bug 6411747 28 * @author Daniel Fuchs 29 * @run clean NotificationEmitterProxy 30 * @run build NotificationEmitterProxy 31 * @run main NotificationEmitterProxy 32 */ 33 34 import java.lang.management.ManagementFactory; 35 36 import javax.management.*; 37 import javax.management.remote.*; 38 import javax.naming.NoPermissionException; 39 40 public class NotificationEmitterProxy { 41 42 public static class Counter { 43 int count; 44 public synchronized int count() { 45 count++; 46 notifyAll(); 47 return count; 48 } 49 public synchronized int peek() { 50 return count; 51 } 52 public synchronized int waitfor(int max, long timeout) 53 throws InterruptedException { 54 final long start = System.currentTimeMillis(); 55 while (count < max && timeout > 0) { 56 final long rest = timeout - 57 (System.currentTimeMillis() - start); 58 if (rest <= 0) break; 59 wait(rest); 60 } 61 return count; 62 } 63 } 64 65 public static class CounterListener 66 implements NotificationListener { 67 final private Counter counter; 68 public CounterListener(Counter counter) { 69 this.counter = counter; 70 } 71 public void handleNotification(Notification notification, 72 Object handback) { 73 System.out.println("Received notif from " + handback + 74 ":\n\t" + notification); 75 counter.count(); 76 } 77 } 78 79 public static void main(String[] args) throws Exception { 80 System.out.println("<<< Register for notification from a proxy"); 81 82 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 83 final ObjectName name = new ObjectName(":class=Simple"); 84 85 JMXServiceURL url = new JMXServiceURL("rmi", null, 0); 86 final JMXConnectorServer server = 87 JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); 88 server.start(); 89 url = server.getAddress(); 90 91 final JMXConnector client = JMXConnectorFactory.connect(url); 92 93 final Counter counter = new Counter(); 94 final CounterListener listener = new CounterListener(counter); 95 final Counter mxcounter = new Counter(); 96 final CounterListener mxlistener = new CounterListener(mxcounter); 97 final NotificationFilterSupport filter = 98 new NotificationFilterSupport(); 99 filter.enableType(MBeanServerNotification.REGISTRATION_NOTIFICATION); 100 filter.enableType(MBeanServerNotification.UNREGISTRATION_NOTIFICATION); 101 int registered = 0; 102 try { 103 final MBeanServerDelegateMBean delegate = 104 JMX.newMBeanProxy(client.getMBeanServerConnection(), 105 MBeanServerDelegate.DELEGATE_NAME, 106 MBeanServerDelegateMBean.class, 107 true); 108 109 NotificationEmitter emitter = (NotificationEmitter)delegate; 110 emitter.addNotificationListener(listener,filter,"JMX.newMBeanProxy"); 111 } catch (Exception x) { 112 throw new RuntimeException("Failed to register listener with "+ 113 " JMX.newMBeanProxy: " + x, x); 114 } 115 116 try { 117 final MBeanServerDelegateMBean delegate = 118 MBeanServerInvocationHandler.newProxyInstance(mbs, 119 MBeanServerDelegate.DELEGATE_NAME, 120 MBeanServerDelegateMBean.class, 121 true); 122 123 NotificationEmitter emitter = (NotificationEmitter)delegate; 124 emitter.addNotificationListener(listener,filter, 125 "MBeanServerInvocationHandler.newProxyInstance"); 126 } catch (Exception x) { 127 throw new RuntimeException("Failed to register listener with "+ 128 " MBeanServerInvocationHandler.newProxyInstance: " + x, x); 129 } 130 131 System.out.println("<<< Register an MBean."); 132 133 final Simple simple = new Simple(); 134 mbs.registerMBean(simple, name); 135 registered++; 136 137 SimpleMXBean simple0 = 138 JMX.newMXBeanProxy(client.getMBeanServerConnection(), 139 name, 140 SimpleMXBean.class, 141 true); 142 143 SimpleMXBean simple1 = 144 JMX.newMXBeanProxy(mbs, 145 name, 146 SimpleMXBean.class, 147 false); 148 149 final int expected = 2*registered; 150 final int reg = counter.waitfor(expected,3000); 151 if (reg != expected) 152 throw new RuntimeException("Bad notification count: " + reg + 153 ", expected " +expected); 154 System.out.println("Received expected "+reg+ 155 " notifs after registerMBean"); 156 157 ((NotificationEmitter)simple0) 158 .addNotificationListener(mxlistener,null,name); 159 simple1.equals("Are you a Wombat?"); 160 final int mxnotifs = mxcounter.waitfor(1,3000); 161 if (mxnotifs != 1) 162 throw new RuntimeException("Bad MXBean notification count: " + 163 mxnotifs); 164 System.out.println("Received expected "+mxnotifs+ 165 " notifs from MXBean"); 166 167 mbs.unregisterMBean(name); 168 final int unreg = counter.waitfor(expected+reg,3000); 169 if (unreg != (expected+reg)) 170 throw new RuntimeException("Bad notification count: " + unreg + 171 ", expected " +expected+reg); 172 System.out.println("Received expected "+(unreg-reg)+ 173 " notifs after unregisterMBean"); 174 System.out.println("Total notifs received: " + unreg); 175 176 177 } 178 179 public static interface Simplest { 180 181 } 182 183 public static interface SimpleMXBean extends Simplest { 184 public String equals(String x); 185 } 186 187 private static class Simple extends NotificationBroadcasterSupport 188 implements SimpleMXBean { 189 public static final String NOTIF_TYPE = "simple.equals"; 190 private static long seq=0; 191 private static synchronized long seq() { return ++seq; }; 192 public String equals(String x) { 193 sendNotification(new Notification(NOTIF_TYPE,this,seq(),x)); 194 return x; 195 } 196 197 } 198 199 200 201 }