1 /*
   2  * Copyright (c) 2003, 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  * @bug 7654321
  27  * @summary Tests to receive notifications for opened and closed connections
  28  * @author sjiang
  29  *
  30  * @run clean RMINotifTest
  31  * @run build RMINotifTest
  32  * @run main RMINotifTest
  33  * @run main RMINotifTest event
  34  */
  35 
  36 // java imports
  37 //
  38 
  39 import java.rmi.RemoteException;
  40 import java.rmi.registry.LocateRegistry;
  41 import java.rmi.registry.Registry;
  42 import java.util.Random;
  43 import javax.management.MBeanNotificationInfo;
  44 import javax.management.MBeanServer;
  45 import javax.management.MBeanServerConnection;
  46 import javax.management.MBeanServerFactory;
  47 import javax.management.Notification;
  48 import javax.management.NotificationBroadcasterSupport;
  49 import javax.management.NotificationFilterSupport;
  50 import javax.management.NotificationListener;
  51 import javax.management.ObjectInstance;
  52 import javax.management.ObjectName;
  53 import javax.management.remote.JMXConnector;
  54 import javax.management.remote.JMXConnectorFactory;
  55 import javax.management.remote.JMXConnectorServer;
  56 import javax.management.remote.JMXConnectorServerFactory;
  57 import javax.management.remote.JMXServiceURL;
  58 
  59 public class RMINotifTest {
  60 
  61     public static void main(String[] args) {
  62         try {
  63             // create a rmi registry
  64             Registry reg = null;
  65             int port = 6666;
  66             final Random r = new Random();
  67 
  68             while(port++<7000) {
  69                 try {
  70                     reg = LocateRegistry.createRegistry(++port);
  71                     System.out.println("Creation of rmi registry succeeded. Running on port " + port);
  72                     break;
  73                 } catch (RemoteException re) {
  74                 // no problem
  75                 }
  76             }
  77 
  78             if (reg == null) {
  79                 System.out.println("Failed to create a RMI registry, "+
  80                                    "the ports from 6666 to 6999 are all occupied.");
  81                 System.exit(1);
  82             }
  83 
  84             // create a MBeanServer
  85             MBeanServer server = MBeanServerFactory.createMBeanServer();
  86 
  87             // create a notif emitter mbean
  88             ObjectName mbean = new ObjectName ("Default:name=NotificationEmitter");
  89 
  90             server.registerMBean(new NotificationEmitter(), mbean);
  91 
  92             // create a rmi server
  93             JMXServiceURL url =
  94                 new JMXServiceURL("rmi", null, port,
  95                                   "/jndi/rmi://:" + port + "/server" + port);
  96             System.out.println("RMIConnectorServer address " + url);
  97 
  98             JMXConnectorServer sServer =
  99                 JMXConnectorServerFactory.newJMXConnectorServer(url, null,
 100                                                                 null);
 101 
 102             ObjectInstance ss = server.registerMBean(sServer, new ObjectName("Default:name=RmiConnectorServer"));
 103 
 104             sServer.start();
 105 
 106             // create a rmi client
 107             JMXConnector rmiConnection =
 108                 JMXConnectorFactory.newJMXConnector(url, null);
 109             rmiConnection.connect(null);
 110             MBeanServerConnection client = rmiConnection.getMBeanServerConnection();
 111 
 112             // add listener at the client side
 113             client.addNotificationListener(mbean, listener, null, null);
 114 
 115             //ask to send notifs
 116             Object[] params = new Object[1];
 117             String[] signatures = new String[1];
 118 
 119             params[0] = new Integer(nb);
 120             signatures[0] = "java.lang.Integer";
 121 
 122             client.invoke(mbean, "sendNotifications", params, signatures);
 123 
 124             // waiting ...
 125             synchronized (lock) {
 126                 if (receivedNotifs != nb) {
 127                     lock.wait(10000);
 128                     System.out.println(">>> Received notifications..."+receivedNotifs);
 129 
 130                 }
 131             }
 132 
 133             // check
 134             if (receivedNotifs != nb) {
 135                 System.exit(1);
 136             } else {
 137                 System.out.println("The client received all notifications.");
 138             }
 139 
 140             // remove listener
 141             client.removeNotificationListener(mbean, listener);
 142 
 143             // more test
 144             NotificationFilterSupport filter = new NotificationFilterSupport();
 145             Object o = new Object();
 146             client.addNotificationListener(mbean, listener, filter, o);
 147             client.removeNotificationListener(mbean, listener, filter, o);
 148 
 149             sServer.stop();
 150 
 151 //          // clean
 152 //          client.unregisterMBean(mbean);
 153 //          rmiConnection.close();
 154 
 155 //          Thread.sleep(2000);
 156 
 157 
 158 
 159         } catch (Exception e) {
 160             e.printStackTrace();
 161             System.exit(1);
 162         }
 163     }
 164 
 165 //--------------------------
 166 // private classes
 167 //--------------------------
 168 
 169     private static class Listener implements NotificationListener {
 170         public void handleNotification(Notification notif, Object handback) {
 171             if(++receivedNotifs == nb) {
 172                 synchronized(lock) {
 173                     lock.notifyAll();
 174                 }
 175             }
 176         }
 177     }
 178 
 179     public static class NotificationEmitter extends NotificationBroadcasterSupport implements NotificationEmitterMBean {
 180 //      public NotificationEmitter() {
 181 //              super();
 182 // System.out.println("===NotificationEmitter: new instance.");
 183 //      }
 184 
 185         /**
 186          * Returns a NotificationInfo object containing the name of the Java class of the notification
 187          * and the notification types sent by this notification broadcaster.
 188          */
 189         public MBeanNotificationInfo[] getNotificationInfo() {
 190 
 191             MBeanNotificationInfo[] ntfInfoArray  = new MBeanNotificationInfo[1];
 192 
 193             String[] ntfTypes = new String[1];
 194             ntfTypes[0] = myType;
 195 
 196             ntfInfoArray[0] = new MBeanNotificationInfo(ntfTypes,
 197                                                         "javax.management.Notification",
 198                                                         "Notifications sent by the NotificationEmitter");
 199             return ntfInfoArray;
 200         }
 201 
 202 //      public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) {
 203 //          super.addNotificationListener(listener, filter, handback);
 204 
 205 //          System.out.println("============NotificationEmitter: add new listener");
 206 //      }
 207 
 208         /**
 209          * Send a Notification object with the specified times.
 210          * The sequence number will be from zero to times-1.
 211          *
 212          * @param nb The number of notifications to send
 213          */
 214         public void sendNotifications(Integer nb) {
 215             System.out.println("===NotificationEmitter: be asked to send notifications: "+nb);
 216 
 217             Notification notif;
 218             for (int i=1; i<=nb.intValue(); i++) {
 219                 notif = new Notification(myType, this, i);
 220                 sendNotification(notif);
 221             }
 222         }
 223 
 224         private String myType = "notification.my_notification";
 225     }
 226 
 227     public interface NotificationEmitterMBean {
 228         public void sendNotifications(Integer nb);
 229     }
 230 
 231     private static NotificationListener listener = new Listener();
 232 
 233     private static int nb = 10;
 234     private static int receivedNotifs = 0;
 235     private static int[] lock = new int[0];
 236 }