1 /*
   2  * Copyright (c) 2004, 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 Tests to send a not serializable notification.
  27  * @bug 5022196 8132003
  28  * @author Shanliang JIANG
  29  * @modules java.management.rmi
  30  * @run clean NotSerializableNotifTest
  31  * @run build NotSerializableNotifTest
  32  * @run main NotSerializableNotifTest
  33  */
  34 
  35 // java imports
  36 //
  37 import java.net.MalformedURLException;
  38 import javax.management.MBeanNotificationInfo;
  39 import javax.management.MBeanServer;
  40 import javax.management.MBeanServerConnection;
  41 import javax.management.MBeanServerFactory;
  42 import javax.management.Notification;
  43 import javax.management.NotificationBroadcasterSupport;
  44 import javax.management.NotificationListener;
  45 import javax.management.ObjectName;
  46 import javax.management.remote.JMXConnector;
  47 import javax.management.remote.JMXConnectorFactory;
  48 import javax.management.remote.JMXConnectorServer;
  49 import javax.management.remote.JMXConnectorServerFactory;
  50 import javax.management.remote.JMXServiceURL;
  51 
  52 public class NotSerializableNotifTest {
  53     private static final MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer();
  54     private static ObjectName emitter;
  55 
  56     private static String[] protocols = new String[] {"rmi", "iiop", "jmxmp"};
  57 
  58     private static final int sentNotifs = 10;
  59 
  60     public static void main(String[] args) throws Exception {
  61         System.out.println(">>> Test to send a not serializable notification");
  62 
  63         emitter = new ObjectName("Default:name=NotificationEmitter");
  64         mbeanServer.registerMBean(new NotificationEmitter(), emitter);
  65 
  66         for (int i = 0; i < protocols.length; i++) {
  67             test(protocols[i]);
  68         }
  69 
  70         System.out.println(">>> Test passed");
  71     }
  72 
  73 
  74     private static void test(String proto) throws Exception {
  75         System.out.println("\n>>> Test for protocol " + proto);
  76 
  77         JMXServiceURL url = new JMXServiceURL(proto, null, 0);
  78 
  79         System.out.println(">>> Create a server: "+url);
  80 
  81         JMXConnectorServer server = null;
  82         try {
  83             server = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer);
  84         } catch (MalformedURLException e) {
  85             System.out.println("System does not recognize URL: " + url +
  86                                "; ignoring");
  87             return;
  88         }
  89 
  90         server.start();
  91 
  92         url = server.getAddress();
  93 
  94         System.out.println(">>> Creating a client connectint to: "+url);
  95         JMXConnector conn = JMXConnectorFactory.connect(url, null);
  96         MBeanServerConnection client = conn.getMBeanServerConnection();
  97 
  98         // add listener from the client side
  99         Listener listener = new Listener();
 100         client.addNotificationListener(emitter, listener, null, null);
 101 
 102         // ask to send one not serializable notif
 103         Object[] params = new Object[] {new Integer(1)};
 104         String[] signatures = new String[] {"java.lang.Integer"};
 105         client.invoke(emitter, "sendNotserializableNotifs", params, signatures);
 106 
 107         // listener clean
 108         client.removeNotificationListener(emitter, listener);
 109         listener = new Listener();
 110         client.addNotificationListener(emitter, listener, null, null);
 111 
 112         //ask to send serializable notifs
 113         params = new Object[] {new Integer(sentNotifs)};
 114         client.invoke(emitter, "sendNotifications", params, signatures);
 115 
 116         // waiting ...
 117         synchronized (listener) {
 118             while (listener.received() < sentNotifs) {
 119                 listener.wait(); // either pass or test timeout (killed by test harness)
 120 
 121             }
 122         }
 123 
 124         // clean
 125         client.removeNotificationListener(emitter, listener);
 126 
 127         conn.close();
 128         server.stop();
 129     }
 130 
 131 //--------------------------
 132 // private classes
 133 //--------------------------
 134 
 135     private static class Listener implements NotificationListener {
 136         public void handleNotification(Notification notif, Object handback) {
 137             synchronized (this) {
 138                 if(++receivedNotifs == sentNotifs) {
 139                     this.notifyAll();
 140                 }
 141             }
 142         }
 143 
 144         public int received() {
 145             return receivedNotifs;
 146         }
 147 
 148         private int receivedNotifs = 0;
 149     }
 150 
 151     public static class NotificationEmitter extends NotificationBroadcasterSupport
 152         implements NotificationEmitterMBean {
 153 
 154         public MBeanNotificationInfo[] getNotificationInfo() {
 155             final String[] ntfTypes = {myType};
 156 
 157             final MBeanNotificationInfo[] ntfInfoArray  = {
 158                 new MBeanNotificationInfo(ntfTypes,
 159                                           "javax.management.Notification",
 160                                           "Notifications sent by the NotificationEmitter")};
 161 
 162             return ntfInfoArray;
 163         }
 164 
 165         /**
 166          * Send not serializable Notifications.
 167          *
 168          * @param nb The number of notifications to send
 169          */
 170         public void sendNotserializableNotifs(Integer nb) {
 171 
 172             Notification notif;
 173             for (int i=1; i<=nb.intValue(); i++) {
 174                 notif = new Notification(myType, this, i);
 175 
 176                 notif.setUserData(new Object());
 177                 sendNotification(notif);
 178             }
 179         }
 180 
 181         /**
 182          * Send Notification objects.
 183          *
 184          * @param nb The number of notifications to send
 185          */
 186         public void sendNotifications(Integer nb) {
 187             Notification notif;
 188             for (int i=1; i<=nb.intValue(); i++) {
 189                 notif = new Notification(myType, this, i);
 190 
 191                 sendNotification(notif);
 192             }
 193         }
 194 
 195         private final String myType = "notification.my_notification";
 196     }
 197 
 198     public interface NotificationEmitterMBean {
 199         public void sendNotifications(Integer nb);
 200 
 201         public void sendNotserializableNotifs(Integer nb);
 202     }
 203 }