jdk/test/javax/management/namespace/NamespaceNotificationsTest.java
changeset 1156 bbc2d15aaf7a
child 1227 4546977d0d66
equal deleted inserted replaced
1155:a9a142fcf1b5 1156:bbc2d15aaf7a
       
     1 /*
       
     2  * Copyright 2008 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    21  * have any questions.
       
    22  */
       
    23 
       
    24 /*
       
    25  *
       
    26  * @test NamespaceNotificationsTest.java 1.12
       
    27  * @summary General Namespace & Notifications test.
       
    28  * @author Daniel Fuchs
       
    29  * @run clean NamespaceNotificationsTest
       
    30  *            Wombat WombatMBean JMXRemoteTargetNamespace
       
    31  *            NamespaceController NamespaceControllerMBean
       
    32  * @compile -XDignore.symbol.file=true  NamespaceNotificationsTest.java
       
    33  *            Wombat.java WombatMBean.java JMXRemoteTargetNamespace.java
       
    34  *            NamespaceController.java NamespaceControllerMBean.java
       
    35  * @run main NamespaceNotificationsTest
       
    36  */
       
    37 import com.sun.jmx.remote.util.EventClientConnection;
       
    38 import java.lang.management.ManagementFactory;
       
    39 import java.util.Arrays;
       
    40 import java.util.HashMap;
       
    41 import java.util.Map;
       
    42 import java.util.concurrent.ArrayBlockingQueue;
       
    43 import java.util.concurrent.BlockingQueue;
       
    44 import java.util.concurrent.TimeUnit;
       
    45 import java.util.logging.Logger;
       
    46 import javax.management.JMX;
       
    47 import javax.management.MBeanServer;
       
    48 import javax.management.MBeanServerConnection;
       
    49 import javax.management.MBeanServerDelegate;
       
    50 import javax.management.MBeanServerFactory;
       
    51 import javax.management.MBeanServerNotification;
       
    52 import javax.management.MalformedObjectNameException;
       
    53 import javax.management.Notification;
       
    54 import javax.management.NotificationEmitter;
       
    55 import javax.management.NotificationListener;
       
    56 import javax.management.ObjectInstance;
       
    57 import javax.management.ObjectName;
       
    58 import javax.management.loading.MLet;
       
    59 import javax.management.namespace.JMXNamespace;
       
    60 import javax.management.namespace.JMXNamespaces;
       
    61 import javax.management.remote.JMXAddressable;
       
    62 import javax.management.remote.JMXConnector;
       
    63 import javax.management.remote.JMXConnectorFactory;
       
    64 import javax.management.remote.JMXConnectorServer;
       
    65 import javax.management.remote.JMXConnectorServerFactory;
       
    66 import javax.management.remote.JMXServiceURL;
       
    67 
       
    68 /**
       
    69  *
       
    70  * @author Sun Microsystems, Inc.
       
    71  */
       
    72 public class NamespaceNotificationsTest {
       
    73 
       
    74     /**
       
    75      * A logger for this class.
       
    76      **/
       
    77     private static final Logger LOG =
       
    78             Logger.getLogger(NamespaceNotificationsTest.class.getName());
       
    79 
       
    80     /** Creates a new instance of NamespaceNotificationsTest */
       
    81     public NamespaceNotificationsTest() {
       
    82     }
       
    83 
       
    84 
       
    85     public static JMXServiceURL export(MBeanServer server)
       
    86     throws Exception {
       
    87         final JMXServiceURL in = new JMXServiceURL("rmi",null,0);
       
    88         final JMXConnectorServer cs =
       
    89                 JMXConnectorServerFactory.newJMXConnectorServer(in,null,null);
       
    90         final ObjectName csname = ObjectName.
       
    91                 getInstance(cs.getClass().getPackage().getName()+
       
    92                 ":type="+cs.getClass().getSimpleName());
       
    93         server.registerMBean(cs,csname);
       
    94         cs.start();
       
    95         return cs.getAddress();
       
    96     }
       
    97 
       
    98     public static class Counter {
       
    99         int count;
       
   100         public synchronized int count() {
       
   101             count++;
       
   102             notifyAll();
       
   103             return count;
       
   104         }
       
   105         public synchronized int peek() {
       
   106             return count;
       
   107         }
       
   108         public synchronized int waitfor(int max, long timeout)
       
   109         throws InterruptedException {
       
   110             final long start = System.currentTimeMillis();
       
   111             while (count < max && timeout > 0) {
       
   112                 final long rest = timeout -
       
   113                         (System.currentTimeMillis() - start);
       
   114                 if (rest <= 0) break;
       
   115                 wait(rest);
       
   116             }
       
   117             return count;
       
   118         }
       
   119     }
       
   120 
       
   121     public static class CounterListener
       
   122             implements NotificationListener {
       
   123         final private Counter counter;
       
   124         public CounterListener(Counter counter) {
       
   125             this.counter = counter;
       
   126         }
       
   127         public void handleNotification(Notification notification,
       
   128                 Object handback) {
       
   129             System.out.println("Received notif from " + handback +
       
   130                     ":\n\t" + notification);
       
   131             if (!notification.getSource().equals(handback)) {
       
   132                 System.err.println("OhOh... Unexpected source: \n\t"+
       
   133                         notification.getSource()+"\n\twas expecting:\n\t"+
       
   134                         handback);
       
   135             }
       
   136             counter.count();
       
   137         }
       
   138     }
       
   139 
       
   140     public static void simpleTest(String[] args) {
       
   141         try {
       
   142             final MBeanServer server1 =
       
   143                     ManagementFactory.getPlatformMBeanServer();
       
   144             final JMXServiceURL url1 = export(server1);
       
   145 
       
   146             final MBeanServer server2 =
       
   147                     MBeanServerFactory.createMBeanServer("server2");
       
   148             final JMXServiceURL url2 = export(server2);
       
   149 
       
   150             final MBeanServer server3 =
       
   151                     MBeanServerFactory.createMBeanServer("server3");
       
   152             final JMXServiceURL url3 = export(server3);
       
   153 
       
   154             final ObjectInstance ncinst =
       
   155                     NamespaceController.createInstance(server1);
       
   156 
       
   157             final NamespaceControllerMBean nc =
       
   158                     JMX.newMBeanProxy(server1,ncinst.getObjectName(),
       
   159                     NamespaceControllerMBean.class);
       
   160 
       
   161             final Map<String,Object> options = new HashMap<String,Object>();
       
   162             options.put(JMXRemoteTargetNamespace.CREATE_EVENT_CLIENT,"true");
       
   163 
       
   164             final String mount1 =
       
   165                     nc.mount(url1,"server1",options);
       
   166             final String mount2 = nc.mount(url2,"server1//server2",
       
   167                     options);
       
   168             final String mount3 = nc.mount(url3,
       
   169                     "server1//server2//server3",
       
   170                     options);
       
   171             final String mount13 = nc.mount(
       
   172                     url1,
       
   173                     "server3",
       
   174                     "server2//server3",
       
   175                     options);
       
   176             final String mount21 = nc.mount(url1,"server2//server1",
       
   177                     options);
       
   178             final String mount31 = nc.mount(
       
   179                     url1,
       
   180                     "server3//server1",
       
   181                     "server1",
       
   182                     options);
       
   183             final String mount32 = nc.mount(
       
   184                     url1,
       
   185                     "server3//server2",
       
   186                     "server2",
       
   187                     options);
       
   188 
       
   189 
       
   190             final ObjectName deep =
       
   191                     new ObjectName("server1//server2//server3//bush:type=Wombat,name=kanga");
       
   192             server1.createMBean(Wombat.class.getName(),deep);
       
   193 
       
   194             System.err.println("There's a wombat in the bush!");
       
   195 
       
   196             final Counter counter = new Counter();
       
   197 
       
   198             final NotificationListener listener =
       
   199                     new CounterListener(counter);
       
   200 
       
   201             final JMXConnector jc = JMXConnectorFactory.connect(url1);
       
   202             final MBeanServerConnection aconn =
       
   203                     EventClientConnection.getEventConnectionFor(
       
   204                         jc.getMBeanServerConnection(),null);
       
   205             aconn.addNotificationListener(deep,listener,null,deep);
       
   206 
       
   207 
       
   208             final JMXServiceURL urlx = new JMXServiceURL(url1.toString());
       
   209             System.out.println("conn: "+urlx);
       
   210             final JMXConnector jc2 = JMXNamespaces.narrowToNamespace(
       
   211                     JMXConnectorFactory.connect(urlx),"server1//server1");
       
   212             final JMXConnector jc3 = JMXNamespaces.narrowToNamespace(jc2,"server3");
       
   213             jc3.connect();
       
   214             System.out.println("JC#3: " +
       
   215                     ((jc3 instanceof JMXAddressable)?
       
   216                         ((JMXAddressable)jc3).getAddress():
       
   217                         jc3.toString()));
       
   218             final MBeanServerConnection bconn =
       
   219                     jc3.getMBeanServerConnection();
       
   220             final ObjectName shallow =
       
   221                     new ObjectName("bush:"+
       
   222                     deep.getKeyPropertyListString());
       
   223             final WombatMBean proxy =
       
   224                     JMX.newMBeanProxy(EventClientConnection.getEventConnectionFor(
       
   225                         bconn,null),shallow,WombatMBean.class,true);
       
   226 
       
   227             ((NotificationEmitter)proxy).
       
   228                     addNotificationListener(listener,null,shallow);
       
   229             proxy.setCaption("I am a new Wombat!");
       
   230             System.err.println("New caption: "+proxy.getCaption());
       
   231             final int rcvcount = counter.waitfor(2,3000);
       
   232             if (rcvcount != 2)
       
   233                 throw new RuntimeException("simpleTest failed: "+
       
   234                         "received count is " +rcvcount);
       
   235 
       
   236             System.err.println("simpleTest passed: got "+rcvcount+
       
   237                     " notifs");
       
   238 
       
   239         } catch (RuntimeException x) {
       
   240             throw x;
       
   241         } catch (Exception x) {
       
   242             throw new RuntimeException("simpleTest failed: " + x,x);
       
   243         }
       
   244     }
       
   245 
       
   246     public static class LocalNamespace extends
       
   247             JMXNamespace {
       
   248         LocalNamespace() {
       
   249             super(MBeanServerFactory.newMBeanServer());
       
   250         }
       
   251 
       
   252     }
       
   253 
       
   254     public static class ContextObject<K,V> {
       
   255         public final K name;
       
   256         public final V object;
       
   257         public ContextObject(K name, V object) {
       
   258             this.name = name;
       
   259             this.object = object;
       
   260         }
       
   261         private Object[] data() {
       
   262             return new Object[] {name,object};
       
   263         }
       
   264 
       
   265         @Override
       
   266         public boolean equals(Object x) {
       
   267             if (x instanceof ContextObject)
       
   268                 return Arrays.deepEquals(data(),((ContextObject<?,?>)x).data());
       
   269             return false;
       
   270         }
       
   271         @Override
       
   272         public int hashCode() {
       
   273             return Arrays.deepHashCode(data());
       
   274         }
       
   275     }
       
   276 
       
   277     private static <K,V> ContextObject<K,V> context(K k, V v) {
       
   278         return new ContextObject<K,V>(k,v);
       
   279     }
       
   280 
       
   281     private static ObjectName name(String name) {
       
   282         try {
       
   283             return new ObjectName(name);
       
   284         } catch(MalformedObjectNameException x) {
       
   285             throw new IllegalArgumentException(name,x);
       
   286         }
       
   287     }
       
   288 
       
   289     public static void simpleTest2() {
       
   290         try {
       
   291             System.out.println("\nsimpleTest2: STARTING\n");
       
   292             final LocalNamespace foo = new LocalNamespace();
       
   293             final LocalNamespace joe = new LocalNamespace();
       
   294             final LocalNamespace bar = new LocalNamespace();
       
   295             final MBeanServer server = MBeanServerFactory.newMBeanServer();
       
   296 
       
   297             server.registerMBean(foo,JMXNamespaces.getNamespaceObjectName("foo"));
       
   298             server.registerMBean(joe,JMXNamespaces.getNamespaceObjectName("foo//joe"));
       
   299             server.registerMBean(bar,JMXNamespaces.getNamespaceObjectName("foo//bar"));
       
   300             final BlockingQueue<ContextObject<String,MBeanServerNotification>> queue =
       
   301                     new ArrayBlockingQueue<ContextObject<String,MBeanServerNotification>>(20);
       
   302 
       
   303             final NotificationListener listener = new NotificationListener() {
       
   304                 public void handleNotification(Notification n, Object handback) {
       
   305                     if (!(n instanceof MBeanServerNotification)) {
       
   306                         System.err.println("Error: expected MBeanServerNotification");
       
   307                         return;
       
   308                     }
       
   309                     final MBeanServerNotification mbsn =
       
   310                             (MBeanServerNotification) n;
       
   311 
       
   312                     // We will pass the namespace name in the handback.
       
   313                     //
       
   314                     final String namespace = (String) handback;
       
   315                     System.out.println("Received " + mbsn.getType() +
       
   316                             " for MBean " + mbsn.getMBeanName() +
       
   317                             " from name space " + namespace);
       
   318                     try {
       
   319                         queue.offer(context(namespace,mbsn),500,TimeUnit.MILLISECONDS);
       
   320                     } catch (Exception x) {
       
   321                         System.err.println("Failed to enqueue received notif: "+mbsn);
       
   322                         x.printStackTrace();
       
   323                     }
       
   324                 }
       
   325             };
       
   326 
       
   327             server.addNotificationListener(JMXNamespaces.insertPath("foo//joe",
       
   328                     MBeanServerDelegate.DELEGATE_NAME),listener,null,"foo//joe");
       
   329             server.addNotificationListener(JMXNamespaces.insertPath("foo//bar",
       
   330                     MBeanServerDelegate.DELEGATE_NAME),listener,null,"foo//bar");
       
   331             server.createMBean(MLet.class.getName(),
       
   332                     name("foo//joe//domain:type=MLet"));
       
   333             checkQueue(queue,"foo//joe",
       
   334                     MBeanServerNotification.REGISTRATION_NOTIFICATION);
       
   335             server.createMBean(MLet.class.getName(),
       
   336                     name("foo//bar//domain:type=MLet"));
       
   337             checkQueue(queue,"foo//bar",
       
   338                     MBeanServerNotification.REGISTRATION_NOTIFICATION);
       
   339             server.unregisterMBean(
       
   340                     name("foo//joe//domain:type=MLet"));
       
   341             checkQueue(queue,"foo//joe",
       
   342                     MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
       
   343             server.unregisterMBean(
       
   344                     name("foo//bar//domain:type=MLet"));
       
   345             checkQueue(queue,"foo//bar",
       
   346                     MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
       
   347         } catch (RuntimeException x) {
       
   348             System.err.println("FAILED: "+x);
       
   349             throw x;
       
   350         } catch(Exception x) {
       
   351             System.err.println("FAILED: "+x);
       
   352             throw new RuntimeException("Unexpected exception: "+x,x);
       
   353         }
       
   354     }
       
   355 
       
   356 
       
   357     private static void checkQueue(
       
   358             BlockingQueue<ContextObject<String,MBeanServerNotification>> q,
       
   359                               String path, String type) {
       
   360         try {
       
   361           final ContextObject<String,MBeanServerNotification> ctxt =
       
   362                     q.poll(500,TimeUnit.MILLISECONDS);
       
   363           if (ctxt == null)
       
   364             throw new RuntimeException("Timeout expired: expected notif from "+
       
   365                     path +", type="+type);
       
   366           if (!ctxt.name.equals(path))
       
   367             throw new RuntimeException("expected notif from "+
       
   368                     path +", got "+ctxt.name);
       
   369           if (!ctxt.object.getType().equals(type))
       
   370             throw new RuntimeException(ctxt.name+": expected type="+
       
   371                     type +", got "+ctxt.object.getType());
       
   372           if (!ctxt.object.getType().equals(type))
       
   373             throw new RuntimeException(ctxt.name+": expected type="+
       
   374                     type +", got "+ctxt.object.getType());
       
   375           if (!ctxt.object.getMBeanName().equals(name("domain:type=MLet")))
       
   376             throw new RuntimeException(ctxt.name+": expected MBean=domain:type=MLet"+
       
   377                     ", got "+ctxt.object.getMBeanName());
       
   378         } catch(InterruptedException x) {
       
   379             throw new RuntimeException("unexpected interruption: "+x,x);
       
   380         }
       
   381     }
       
   382 
       
   383     public static void main(String[] args) {
       
   384         simpleTest(args);
       
   385         simpleTest2();
       
   386     }
       
   387 
       
   388 }