1 /*
2  * Copyright (c) 2006, 2015, 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  *
30  * @run clean NotificationEmitterProxy
31  * @run build NotificationEmitterProxy
32  * @run main NotificationEmitterProxy
33  */
34 
35 import java.lang.management.ManagementFactory;
36 
37 import javax.management.*;
38 import javax.management.remote.*;
39 import javax.naming.NoPermissionException;
40 
41 public class NotificationEmitterProxy {
42 
getInts()43     public static class Counter {
44         int count;
45         public synchronized int count() {
46             count++;
47             notifyAll();
48             return count;
49         }
50         public synchronized int peek() {
51             return count;
52         }
53         public synchronized int waitfor(int max, long timeout)
54             throws InterruptedException {
55             final long start = System.currentTimeMillis();
56             while (count < max && timeout > 0) {
57                 final long rest = timeout -
58                         (System.currentTimeMillis() - start);
59                 if (rest <= 0) break;
60                 wait(rest);
61             }
62             return count;
63         }
64     }
isInt()65 
66     public static class CounterListener
67             implements NotificationListener {
68         final private Counter counter;
69         public CounterListener(Counter counter) {
70             this.counter = counter;
71         }
72         public void handleNotification(Notification notification,
73                         Object handback) {
74                System.out.println("Received notif from " + handback +
75                                   ":\n\t" + notification);
76                counter.count();
77         }
78     }
setInt(int a)79 
80     public static void main(String[] args) throws Exception {
81         System.out.println("<<< Register for notification from a proxy");
82 
83         MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
84         final ObjectName name = new ObjectName(":class=Simple");
85 
86         JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
87         final JMXConnectorServer server =
88             JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
89         server.start();
90         url = server.getAddress();
91 
92         final JMXConnector client = JMXConnectorFactory.connect(url);
93 
94         final Counter counter = new Counter();
95         final CounterListener listener = new CounterListener(counter);
96         final Counter mxcounter = new Counter();
97         final CounterListener mxlistener = new CounterListener(mxcounter);
98         final NotificationFilterSupport filter =
99                 new NotificationFilterSupport();
100         filter.enableType(MBeanServerNotification.REGISTRATION_NOTIFICATION);
101         filter.enableType(MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
102         int registered = 0;
103         try {
104             final MBeanServerDelegateMBean delegate =
105                 JMX.newMBeanProxy(client.getMBeanServerConnection(),
106                        MBeanServerDelegate.DELEGATE_NAME,
107                        MBeanServerDelegateMBean.class,
108                        true);
109 
110             NotificationEmitter emitter = (NotificationEmitter)delegate;
111             emitter.addNotificationListener(listener,filter,"JMX.newMBeanProxy");
112         } catch (Exception x) {
113             throw new RuntimeException("Failed to register listener with "+
114                     " JMX.newMBeanProxy: " + x, x);
115         }
116 
117         try {
118             final MBeanServerDelegateMBean delegate =
119                 MBeanServerInvocationHandler.newProxyInstance(mbs,
120                        MBeanServerDelegate.DELEGATE_NAME,
121                        MBeanServerDelegateMBean.class,
122                        true);
123 
124             NotificationEmitter emitter = (NotificationEmitter)delegate;
125             emitter.addNotificationListener(listener,filter,
126                     "MBeanServerInvocationHandler.newProxyInstance");
127         } catch (Exception x) {
128             throw new RuntimeException("Failed to register listener with "+
129                     " MBeanServerInvocationHandler.newProxyInstance: " + x, x);
130         }
131 
132         System.out.println("<<< Register an MBean.");
133 
134         final Simple simple = new Simple();
135         mbs.registerMBean(simple, name);
136         registered++;
137 
138         SimpleMXBean simple0 =
139            JMX.newMXBeanProxy(client.getMBeanServerConnection(),
140                               name,
141                               SimpleMXBean.class,
142                               true);
143 
144         SimpleMXBean simple1 =
145             JMX.newMXBeanProxy(mbs,
146                                name,
147                                SimpleMXBean.class,
148                                false);
149 
150         final int expected = 2*registered;
151         final int reg = counter.waitfor(expected,3000);
152         if (reg != expected)
153             throw new RuntimeException("Bad notification count: " + reg +
154                     ", expected " +expected);
155         System.out.println("Received expected "+reg+
156                 " notifs after registerMBean");
157 
158         ((NotificationEmitter)simple0)
159             .addNotificationListener(mxlistener,null,name);
160         simple1.equals("Are you a Wombat?");
161         final int mxnotifs = mxcounter.waitfor(1,3000);
162         if (mxnotifs != 1)
163              throw new RuntimeException("Bad MXBean notification count: " +
164                      mxnotifs);
165         System.out.println("Received expected "+mxnotifs+
166                 " notifs from MXBean");
167 
168         mbs.unregisterMBean(name);
169         final int unreg = counter.waitfor(expected+reg,3000);
170         if (unreg != (expected+reg))
171             throw new RuntimeException("Bad notification count: " + unreg +
172                     ", expected " +expected+reg);
173         System.out.println("Received expected "+(unreg-reg)+
174                 " notifs after unregisterMBean");
175         System.out.println("Total notifs received: " + unreg);
176 
177 
178     }
179 
180     public static interface Simplest {
181 
182     }
183 
184     public static interface SimpleMXBean extends Simplest {
185         public String equals(String x);
186     }
187 
188     private static class Simple extends NotificationBroadcasterSupport
189             implements SimpleMXBean {
190         public static final String NOTIF_TYPE = "simple.equals";
191         private static long seq=0;
192         private static synchronized long seq() { return ++seq; };
193         public String equals(String x) {
194             sendNotification(new Notification(NOTIF_TYPE,this,seq(),x));
195             return x;
196         }
197 
198     }
199 
200 
201 
202  }
203