jdk/test/javax/management/eventService/LeaseTest.java
changeset 4156 acaa49a2768a
parent 4155 460e37d40f12
child 4159 9e3aae7675f1
equal deleted inserted replaced
4155:460e37d40f12 4156:acaa49a2768a
     1 /*
       
     2  * Copyright 2007-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  * @test LeaseTest.java 1.6 08/01/22
       
    26  * @bug 5108776
       
    27  * @summary Basic test for Event service leasing.
       
    28  * @author Shanliang JIANG
       
    29  * @run clean LeaseTest
       
    30  * @run build LeaseTest
       
    31  * @run main LeaseTest
       
    32  */
       
    33 
       
    34 
       
    35 import java.io.IOException;
       
    36 import java.util.ArrayList;
       
    37 import java.util.List;
       
    38 import javax.management.ListenerNotFoundException;
       
    39 import javax.management.MBeanNotificationInfo;
       
    40 import javax.management.MBeanServer;
       
    41 import javax.management.MBeanServerFactory;
       
    42 import javax.management.Notification;
       
    43 import javax.management.NotificationBroadcasterSupport;
       
    44 import javax.management.NotificationFilter;
       
    45 import javax.management.NotificationListener;
       
    46 import javax.management.ObjectName;
       
    47 import javax.management.event.EventClient;
       
    48 import javax.management.event.EventClientDelegate;
       
    49 import javax.management.event.EventClientDelegateMBean;
       
    50 import javax.management.event.EventClientNotFoundException;
       
    51 import javax.management.event.FetchingEventRelay;
       
    52 import javax.management.remote.JMXConnector;
       
    53 import javax.management.remote.JMXConnectorFactory;
       
    54 import javax.management.remote.JMXConnectorServer;
       
    55 import javax.management.remote.JMXConnectorServerFactory;
       
    56 import javax.management.remote.JMXServiceURL;
       
    57 
       
    58 public class LeaseTest {
       
    59 
       
    60     private static MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer();
       
    61     private static List<Notification> notifList = new ArrayList<Notification>();
       
    62     private static ObjectName emitter;
       
    63     private static NotificationEmitter emitterImpl;
       
    64     private static JMXServiceURL url;
       
    65     private static JMXConnectorServer server;
       
    66     private static JMXConnector conn;
       
    67     private static Listener listener = new Listener();
       
    68 
       
    69     private static long leaseTime = 100;
       
    70     private static final int multiple = 5;
       
    71     private static final long bigWaiting = 6000;
       
    72 
       
    73     public static void main(String[] args) throws Exception {
       
    74         System.out.println(">>> Test the event service lease");
       
    75 
       
    76         // for 1.5
       
    77         if (System.getProperty("java.version").startsWith("1.5") &&
       
    78                 !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) {
       
    79             System.out.print("Working on "+System.getProperty("java.version")+
       
    80                     " register "+EventClientDelegateMBean.OBJECT_NAME);
       
    81 
       
    82             mbeanServer.registerMBean(EventClientDelegate.
       
    83                     getEventClientDelegate(mbeanServer),
       
    84                     EventClientDelegateMBean.OBJECT_NAME);
       
    85         }
       
    86 
       
    87         System.setProperty("com.sun.event.lease.time",
       
    88                 String.valueOf(leaseTime));
       
    89         emitter = new ObjectName("Default:name=NotificationEmitter");
       
    90         emitterImpl = new NotificationEmitter();
       
    91         mbeanServer.registerMBean(emitterImpl, emitter);
       
    92 
       
    93         String[] types = new String[]{"PushingEventRelay", "FetchingEventRelay"};
       
    94         String[] protos = new String[]{"rmi", "iiop", "jmxmp"};
       
    95         for (String prot : protos) {
       
    96             url = new JMXServiceURL(prot, null, 0);
       
    97 
       
    98             try {
       
    99                 server =
       
   100                 JMXConnectorServerFactory.newJMXConnectorServer(url,
       
   101                 null, mbeanServer);
       
   102                 server.start();
       
   103             } catch (Exception e) {
       
   104                 System.out.println(">>> Skip "+prot+", not support.");
       
   105                 continue;
       
   106             }
       
   107 
       
   108             url = server.getAddress();
       
   109 
       
   110             try {
       
   111                 for (String type: types) {
       
   112                     test(type);
       
   113                 }
       
   114             } finally {
       
   115                 server.stop();
       
   116             }
       
   117         }
       
   118     }
       
   119 
       
   120     private static void test(String type) throws Exception {
       
   121         System.out.println("\n\n>>> Testing "+type+" on "+url+" ...");
       
   122         newConn();
       
   123         EventClient ec = newEventClient(type);
       
   124 
       
   125         ec.addNotificationListener(emitter,
       
   126                 listener, null, null);
       
   127 
       
   128         System.out.println(">>> Send a notification and should receive it.");
       
   129         emitterImpl.sendNotif(++counter);
       
   130 
       
   131         if (!waitNotif(bigWaiting, counter)) {
       
   132             throw new RuntimeException(">>> Failed to receive notif.");
       
   133         }
       
   134 
       
   135         System.out.println(">>> Sleep 3 times of requested lease time.");
       
   136         Thread.sleep(leaseTime*3);
       
   137         System.out.println(">>> Send again a notification and should receive it.");
       
   138         emitterImpl.sendNotif(++counter);
       
   139 
       
   140         if (!waitNotif(bigWaiting, counter)) {
       
   141             throw new RuntimeException(">>> Failed to receive notif.");
       
   142         }
       
   143 
       
   144         System.out.println(">>> Close the client connection: "+
       
   145                 conn.getConnectionId());
       
   146         conn.close();
       
   147 
       
   148         System.out.println(">>> Waiting lease timeout to do clean.");
       
   149 
       
   150         if (!emitterImpl.waitingClean(leaseTime*multiple)) {
       
   151             throw new RuntimeException(
       
   152                     ">>> The event lease failed to do clean: "+
       
   153                     emitterImpl.listenerSize);
       
   154         } else {
       
   155             System.out.println(">>> The listener has been removed.");
       
   156         }
       
   157 
       
   158         // Check that the client id has indeed been removed, by trying to
       
   159         // remove it again, which should fail.
       
   160         newConn();
       
   161         try {
       
   162             EventClientDelegateMBean proxy =
       
   163                 EventClientDelegate.getProxy(conn.getMBeanServerConnection());
       
   164             proxy.removeClient(ec.getEventRelay().getClientId());
       
   165 
       
   166             throw new RuntimeException(
       
   167                     ">>> The client id is not removed.");
       
   168         } catch (EventClientNotFoundException ecnfe) {
       
   169             // OK
       
   170             System.out.println(">>> The client id has been removed.");
       
   171         }
       
   172         conn.close();
       
   173 
       
   174         System.out.println(">>> Reconnect to the server.");
       
   175         newConn();
       
   176 
       
   177         System.out.println(">>> Create a new EventClient and add the listeners" +
       
   178                 " in the failed EventClient into new EventClient");
       
   179         EventClient newEC = newEventClient(type);
       
   180         newEC.addListeners(ec.getListeners());
       
   181         // We expect ec.close() to get IOException because we closed the
       
   182         // underlying connection.
       
   183         try {
       
   184             ec.close();
       
   185             throw new RuntimeException(">>> EventClient.close did not throw " +
       
   186                     "expected IOException");
       
   187         } catch (IOException e) {
       
   188             System.out.println(">>> EventClient.close threw expected exception: " + e);
       
   189         }
       
   190 
       
   191         emitterImpl.sendNotif(++counter);
       
   192 
       
   193         if (!waitNotif(bigWaiting, counter)) {
       
   194             throw new RuntimeException(">>> The event client failed to add " +
       
   195                     "all old registered listeners after re-connection.");
       
   196         } else {
       
   197             System.out.println(">>> Successfully received notification from" +
       
   198                     " new EventClient.");
       
   199         }
       
   200 
       
   201         System.out.println(">>> Clean the failed EventClient.");
       
   202         ec.close();
       
   203         if (ec.getListeners().size() != 0) {
       
   204             throw new RuntimeException(">>> The event client fails to do clean.");
       
   205         }
       
   206 
       
   207         System.out.println(">>> Clean the new EventClient.");
       
   208         newEC.close();
       
   209         if (newEC.getListeners().size() != 0) {
       
   210             throw new RuntimeException(">>> The event client fails to do clean.");
       
   211         }
       
   212 
       
   213         conn.close();
       
   214         System.out.println(">>> Testing "+type+" on "+url+" ... done");
       
   215     }
       
   216 
       
   217     private static boolean waitNotif(long time, int sequenceNumber)
       
   218     throws Exception {
       
   219         synchronized(notifList) {
       
   220             if (search(sequenceNumber)) {
       
   221                 return true;
       
   222             }
       
   223 
       
   224             long stopTime = System.currentTimeMillis() + time;
       
   225             long toWait = time;
       
   226             while (toWait > 0) {
       
   227                 notifList.wait(toWait);
       
   228 
       
   229                 if (search(sequenceNumber)) {
       
   230                     return true;
       
   231                 }
       
   232 
       
   233                 toWait = stopTime - System.currentTimeMillis();
       
   234             }
       
   235 
       
   236             return false;
       
   237         }
       
   238     }
       
   239 
       
   240     private static boolean search(int sequenceNumber) {
       
   241         while(notifList.size() > 0) {
       
   242             Notification n = notifList.remove(0);
       
   243             if (n.getSequenceNumber() == sequenceNumber) {
       
   244                 return true;
       
   245             }
       
   246         }
       
   247 
       
   248         return false;
       
   249     }
       
   250 
       
   251 //--------------------------
       
   252 // private classes
       
   253 //--------------------------
       
   254 
       
   255     private static class Listener implements NotificationListener {
       
   256         public void handleNotification(Notification notif, Object handback) {
       
   257             synchronized (notifList) {
       
   258                 notifList.add(notif);
       
   259                 notifList.notify();
       
   260             }
       
   261         }
       
   262     }
       
   263 
       
   264     public static class NotificationEmitter extends NotificationBroadcasterSupport
       
   265             implements NotificationEmitterMBean {
       
   266 
       
   267         public MBeanNotificationInfo[] getNotificationInfo() {
       
   268             final String[] ntfTypes = {myType};
       
   269 
       
   270             final MBeanNotificationInfo[] ntfInfoArray  = {
       
   271                 new MBeanNotificationInfo(ntfTypes,
       
   272                         "javax.management.Notification",
       
   273                         "Notifications sent by the NotificationEmitter")};
       
   274 
       
   275             return ntfInfoArray;
       
   276         }
       
   277 
       
   278         /**
       
   279          * Send Notification objects.
       
   280          *
       
   281          * @param nb The number of notifications to send
       
   282          */
       
   283         public void sendNotif(int sequenceNumber) {
       
   284             Notification notif = new Notification(myType, this, sequenceNumber);
       
   285             sendNotification(notif);
       
   286         }
       
   287 
       
   288         public void addNotificationListener(NotificationListener listener,
       
   289                 NotificationFilter filter, Object handback) {
       
   290             super.addNotificationListener(listener, filter, handback);
       
   291 
       
   292             listenerSize++;
       
   293         }
       
   294 
       
   295         public void removeNotificationListener(NotificationListener listener)
       
   296         throws ListenerNotFoundException {
       
   297             super.removeNotificationListener(listener);
       
   298             listenerSize--;
       
   299 
       
   300             synchronized(this) {
       
   301                 if (listenerSize == 0) {
       
   302                     this.notifyAll();
       
   303                 }
       
   304             }
       
   305         }
       
   306 
       
   307         public void removeNotificationListener(NotificationListener listener,
       
   308                 NotificationFilter filter, Object handback)
       
   309                 throws ListenerNotFoundException {
       
   310             super.removeNotificationListener(listener, filter, handback);
       
   311             listenerSize--;
       
   312 
       
   313             synchronized(this) {
       
   314                 if (listenerSize == 0) {
       
   315                     this.notifyAll();
       
   316                 }
       
   317             }
       
   318         }
       
   319 
       
   320         public boolean waitingClean(long timeout) throws Exception {
       
   321             synchronized(this) {
       
   322                 long stopTime = System.currentTimeMillis() + timeout;
       
   323                 long toWait = timeout;
       
   324                 while (listenerSize != 0 && toWait > 0) {
       
   325                     this.wait(toWait);
       
   326                     toWait = stopTime - System.currentTimeMillis();
       
   327                 }
       
   328             }
       
   329 
       
   330             return listenerSize == 0;
       
   331         }
       
   332 
       
   333         public int listenerSize = 0;
       
   334 
       
   335         private final String myType = "notification.my_notification";
       
   336     }
       
   337 
       
   338     public interface NotificationEmitterMBean {
       
   339         public void sendNotif(int sequenceNumber);
       
   340     }
       
   341 
       
   342     private static void newConn() throws IOException {
       
   343         conn = JMXConnectorFactory.connect(url);
       
   344     }
       
   345 
       
   346     private static EventClient newEventClient(String type) throws Exception {
       
   347         EventClientDelegateMBean proxy =
       
   348                 EventClientDelegate.getProxy(conn.getMBeanServerConnection());
       
   349         if (type.equals("PushingEventRelay")) {
       
   350             return new EventClient(proxy,
       
   351                     new FetchingEventRelay(proxy), null, null, leaseTime);
       
   352         } else if (type.equals("FetchingEventRelay")) {
       
   353             return new EventClient(proxy,
       
   354                     new FetchingEventRelay(proxy), null, null, leaseTime);
       
   355         } else {
       
   356             throw new RuntimeException("Wrong event client type: "+type);
       
   357         }
       
   358     }
       
   359 
       
   360     private static int counter = 0;
       
   361 }