jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
changeset 4156 acaa49a2768a
parent 1510 e747d3193ef2
child 5175 56d64b1e78f9
equal deleted inserted replaced
4155:460e37d40f12 4156:acaa49a2768a
    23  * have any questions.
    23  * have any questions.
    24  */
    24  */
    25 
    25 
    26 package javax.management.remote.rmi;
    26 package javax.management.remote.rmi;
    27 
    27 
    28 import com.sun.jmx.mbeanserver.Util;
       
    29 import static com.sun.jmx.mbeanserver.Util.cast;
    28 import static com.sun.jmx.mbeanserver.Util.cast;
    30 import com.sun.jmx.remote.internal.ServerCommunicatorAdmin;
    29 import com.sun.jmx.remote.internal.ServerCommunicatorAdmin;
    31 import com.sun.jmx.remote.internal.ServerNotifForwarder;
    30 import com.sun.jmx.remote.internal.ServerNotifForwarder;
    32 import com.sun.jmx.remote.security.JMXSubjectDomainCombiner;
    31 import com.sun.jmx.remote.security.JMXSubjectDomainCombiner;
    33 import com.sun.jmx.remote.security.NotificationAccessController;
       
    34 import com.sun.jmx.remote.security.SubjectDelegator;
    32 import com.sun.jmx.remote.security.SubjectDelegator;
    35 import com.sun.jmx.remote.util.ClassLoaderWithRepository;
    33 import com.sun.jmx.remote.util.ClassLoaderWithRepository;
    36 import com.sun.jmx.remote.util.ClassLogger;
    34 import com.sun.jmx.remote.util.ClassLogger;
    37 import com.sun.jmx.remote.util.EnvHelp;
    35 import com.sun.jmx.remote.util.EnvHelp;
    38 import com.sun.jmx.remote.util.OrderClassLoaders;
    36 import com.sun.jmx.remote.util.OrderClassLoaders;
    39 
    37 
    40 import java.io.IOException;
    38 import java.io.IOException;
    41 import java.lang.reflect.UndeclaredThrowableException;
       
    42 import java.rmi.MarshalledObject;
    39 import java.rmi.MarshalledObject;
    43 import java.rmi.UnmarshalException;
    40 import java.rmi.UnmarshalException;
    44 import java.rmi.server.Unreferenced;
    41 import java.rmi.server.Unreferenced;
    45 import java.security.AccessControlContext;
    42 import java.security.AccessControlContext;
    46 import java.security.AccessController;
    43 import java.security.AccessController;
    57 import javax.management.AttributeNotFoundException;
    54 import javax.management.AttributeNotFoundException;
    58 import javax.management.InstanceAlreadyExistsException;
    55 import javax.management.InstanceAlreadyExistsException;
    59 import javax.management.InstanceNotFoundException;
    56 import javax.management.InstanceNotFoundException;
    60 import javax.management.IntrospectionException;
    57 import javax.management.IntrospectionException;
    61 import javax.management.InvalidAttributeValueException;
    58 import javax.management.InvalidAttributeValueException;
    62 import javax.management.JMX;
       
    63 import javax.management.ListenerNotFoundException;
    59 import javax.management.ListenerNotFoundException;
    64 import javax.management.MBeanException;
    60 import javax.management.MBeanException;
    65 import javax.management.MBeanInfo;
    61 import javax.management.MBeanInfo;
    66 import javax.management.MBeanRegistrationException;
    62 import javax.management.MBeanRegistrationException;
    67 import javax.management.MBeanServer;
    63 import javax.management.MBeanServer;
    68 import javax.management.NotCompliantMBeanException;
    64 import javax.management.NotCompliantMBeanException;
    69 import javax.management.Notification;
       
    70 import javax.management.NotificationFilter;
    65 import javax.management.NotificationFilter;
    71 import javax.management.ObjectInstance;
    66 import javax.management.ObjectInstance;
    72 import javax.management.ObjectName;
    67 import javax.management.ObjectName;
    73 import javax.management.QueryExp;
    68 import javax.management.QueryExp;
    74 import javax.management.ReflectionException;
    69 import javax.management.ReflectionException;
    75 import javax.management.RuntimeOperationsException;
    70 import javax.management.RuntimeOperationsException;
    76 import javax.management.event.EventClientDelegate;
       
    77 import javax.management.event.EventClientDelegateMBean;
       
    78 import javax.management.event.EventClientNotFoundException;
       
    79 import javax.management.event.FetchingEventForwarder;
       
    80 import javax.management.namespace.JMXNamespaces;
       
    81 import javax.management.remote.JMXServerErrorException;
    71 import javax.management.remote.JMXServerErrorException;
    82 import javax.management.remote.NotificationResult;
    72 import javax.management.remote.NotificationResult;
    83 import javax.management.remote.TargetedNotification;
    73 import javax.management.remote.TargetedNotification;
    84 import javax.security.auth.Subject;
    74 import javax.security.auth.Subject;
    85 
    75 
   166           RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env));
   156           RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env));
   167 
   157 
   168         this.env = env;
   158         this.env = env;
   169     }
   159     }
   170 
   160 
       
   161     private synchronized ServerNotifForwarder getServerNotifFwd() {
       
   162         // Lazily created when first use. Mainly when
       
   163         // addNotificationListener is first called.
       
   164         if (serverNotifForwarder == null)
       
   165             serverNotifForwarder =
       
   166                 new ServerNotifForwarder(mbeanServer,
       
   167                                          env,
       
   168                                          rmiServer.getNotifBuffer(),
       
   169                                          connectionId);
       
   170         return serverNotifForwarder;
       
   171     }
   171 
   172 
   172     public String getConnectionId() throws IOException {
   173     public String getConnectionId() throws IOException {
   173         // We should call reqIncomming() here... shouldn't we?
   174         // We should call reqIncomming() here... shouldn't we?
   174         return connectionId;
   175         return connectionId;
   175     }
   176     }
   176 
   177 
   177     public void close() throws IOException {
   178     public void close() throws IOException {
   178         final boolean debug = logger.debugOn();
   179         final boolean debug = logger.debugOn();
   179         final String  idstr = (debug?"["+this.toString()+"]":null);
   180         final String  idstr = (debug?"["+this.toString()+"]":null);
   180 
   181 
   181         final SubscriptionManager mgr;
       
   182         synchronized (this) {
   182         synchronized (this) {
   183             if (terminated) {
   183             if (terminated) {
   184                 if (debug) logger.debug("close",idstr + " already terminated.");
   184                 if (debug) logger.debug("close",idstr + " already terminated.");
   185                 return;
   185                 return;
   186             }
   186             }
   191 
   191 
   192             if (serverCommunicatorAdmin != null) {
   192             if (serverCommunicatorAdmin != null) {
   193                 serverCommunicatorAdmin.terminate();
   193                 serverCommunicatorAdmin.terminate();
   194             }
   194             }
   195 
   195 
   196             mgr = subscriptionManager;
   196             if (serverNotifForwarder != null) {
   197             subscriptionManager = null;
   197                 serverNotifForwarder.terminate();
   198         }
   198             }
   199 
   199         }
   200         if (mgr != null) mgr.terminate();
       
   201 
   200 
   202         rmiServer.clientClosed(this);
   201         rmiServer.clientClosed(this);
   203 
   202 
   204         if (debug) logger.debug("close",idstr + " closed.");
   203         if (debug) logger.debug("close",idstr + " closed.");
   205     }
   204     }
   995             return ids;
   994             return ids;
   996         } catch (Exception e) {
   995         } catch (Exception e) {
   997             // remove all registered listeners
   996             // remove all registered listeners
   998             for (int j=0; j<i; j++) {
   997             for (int j=0; j<i; j++) {
   999                 try {
   998                 try {
  1000                     doRemoveListener(names[j],ids[j]);
   999                     getServerNotifFwd().removeNotificationListener(names[j],
       
  1000                                                                    ids[j]);
  1001                 } catch (Exception eee) {
  1001                 } catch (Exception eee) {
  1002                     // strange
  1002                     // strange
  1003                 }
  1003                 }
  1004             }
  1004             }
  1005 
  1005 
  1245 
  1245 
  1246             }
  1246             }
  1247             final long csn = clientSequenceNumber;
  1247             final long csn = clientSequenceNumber;
  1248             final int mn = maxNotifications;
  1248             final int mn = maxNotifications;
  1249             final long t = timeout;
  1249             final long t = timeout;
  1250 
  1250             PrivilegedAction<NotificationResult> action =
  1251             final PrivilegedExceptionAction<NotificationResult> action =
  1251                 new PrivilegedAction<NotificationResult>() {
  1252                 new PrivilegedExceptionAction<NotificationResult>() {
  1252                     public NotificationResult run() {
  1253                     public NotificationResult run() throws IOException {
  1253                         return getServerNotifFwd().fetchNotifs(csn, t, mn);
  1254                             return doFetchNotifs(csn, t, mn);
       
  1255                     }
  1254                     }
  1256             };
  1255             };
  1257             try {
  1256             if (acc == null)
  1258                 if (acc == null)
  1257                 return action.run();
  1259                     return action.run();
  1258             else
  1260                 else
  1259                 return AccessController.doPrivileged(action, acc);
  1261                     return AccessController.doPrivileged(action, acc);
       
  1262             } catch (IOException x) {
       
  1263                 throw x;
       
  1264             } catch (RuntimeException x) {
       
  1265                 throw x;
       
  1266             } catch (Exception x) {
       
  1267                 // should not happen
       
  1268                 throw new UndeclaredThrowableException(x);
       
  1269             }
       
  1270 
       
  1271         } finally {
  1260         } finally {
  1272             serverCommunicatorAdmin.rspOutgoing();
  1261             serverCommunicatorAdmin.rspOutgoing();
  1273         }
  1262         }
  1274     }
  1263     }
  1275 
       
  1276     /**
       
  1277      * This is an abstraction class that let us use the legacy
       
  1278      * ServerNotifForwarder and the new EventClientDelegateMBean
       
  1279      * indifferently.
       
  1280      **/
       
  1281     private static interface SubscriptionManager {
       
  1282         public void removeNotificationListener(ObjectName name, Integer id)
       
  1283             throws InstanceNotFoundException, ListenerNotFoundException, IOException;
       
  1284         public void removeNotificationListener(ObjectName name, Integer[] ids)
       
  1285             throws Exception;
       
  1286         public NotificationResult fetchNotifications(long csn, long timeout, int maxcount)
       
  1287             throws IOException;
       
  1288         public Integer addNotificationListener(ObjectName name, NotificationFilter filter)
       
  1289             throws InstanceNotFoundException, IOException;
       
  1290         public void terminate()
       
  1291             throws IOException;
       
  1292     }
       
  1293 
       
  1294     /**
       
  1295      * A SubscriptionManager that uses a ServerNotifForwarder.
       
  1296      **/
       
  1297     private static class LegacySubscriptionManager implements SubscriptionManager {
       
  1298         private final ServerNotifForwarder forwarder;
       
  1299         LegacySubscriptionManager(ServerNotifForwarder forwarder) {
       
  1300             this.forwarder = forwarder;
       
  1301         }
       
  1302 
       
  1303         public void removeNotificationListener(ObjectName name, Integer id)
       
  1304             throws InstanceNotFoundException, ListenerNotFoundException,
       
  1305                 IOException {
       
  1306             if (!JMXNamespaces.getContainingNamespace(name).equals("")) {
       
  1307                 logger.debug("removeNotificationListener",
       
  1308                         "This connector server is not configured to support " +
       
  1309                         "forwarding of notification subscriptions to name spaces");
       
  1310                 throw new RuntimeOperationsException(
       
  1311                     new UnsupportedOperationException(
       
  1312                     "removeNotificationListener on name space MBeans. "));
       
  1313                 }
       
  1314             forwarder.removeNotificationListener(name,id);
       
  1315         }
       
  1316 
       
  1317         public void removeNotificationListener(ObjectName name, Integer[] ids)
       
  1318             throws Exception {
       
  1319             if (!JMXNamespaces.getContainingNamespace(name).equals("")) {
       
  1320                 logger.debug("removeNotificationListener",
       
  1321                         "This connector server is not configured to support " +
       
  1322                         "forwarding of notification subscriptions to name spaces");
       
  1323                 throw new RuntimeOperationsException(
       
  1324                     new UnsupportedOperationException(
       
  1325                     "removeNotificationListener on name space MBeans. "));
       
  1326             }
       
  1327             forwarder.removeNotificationListener(name,ids);
       
  1328         }
       
  1329 
       
  1330         public NotificationResult fetchNotifications(long csn, long timeout, int maxcount) {
       
  1331             return forwarder.fetchNotifs(csn,timeout,maxcount);
       
  1332         }
       
  1333 
       
  1334         public Integer addNotificationListener(ObjectName name,
       
  1335                 NotificationFilter filter)
       
  1336             throws InstanceNotFoundException, IOException {
       
  1337             if (!JMXNamespaces.getContainingNamespace(name).equals("")) {
       
  1338                 logger.debug("addNotificationListener",
       
  1339                         "This connector server is not configured to support " +
       
  1340                         "forwarding of notification subscriptions to name spaces");
       
  1341                 throw new RuntimeOperationsException(
       
  1342                     new UnsupportedOperationException(
       
  1343                     "addNotificationListener on name space MBeans. "));
       
  1344             }
       
  1345             return forwarder.addNotificationListener(name,filter);
       
  1346         }
       
  1347 
       
  1348         public void terminate() {
       
  1349             forwarder.terminate();
       
  1350         }
       
  1351     }
       
  1352 
       
  1353     /**
       
  1354      * A SubscriptionManager that uses an EventClientDelegateMBean.
       
  1355      **/
       
  1356     private static class EventSubscriptionManager
       
  1357             implements SubscriptionManager {
       
  1358         private final MBeanServer mbeanServer;
       
  1359         private final EventClientDelegateMBean delegate;
       
  1360         private final NotificationAccessController notifAC;
       
  1361         private final boolean checkNotificationEmission;
       
  1362         private final String clientId;
       
  1363         private final String connectionId;
       
  1364         private volatile String mbeanServerName;
       
  1365 
       
  1366         EventSubscriptionManager(
       
  1367                 MBeanServer mbeanServer,
       
  1368                 EventClientDelegateMBean delegate,
       
  1369                 Map<String, ?> env,
       
  1370                 String clientId,
       
  1371                 String connectionId) {
       
  1372             this.mbeanServer = mbeanServer;
       
  1373             this.delegate = delegate;
       
  1374             this.notifAC = EnvHelp.getNotificationAccessController(env);
       
  1375             this.checkNotificationEmission =
       
  1376                 EnvHelp.computeBooleanFromString(
       
  1377                     env, "jmx.remote.x.check.notification.emission", false);
       
  1378             this.clientId = clientId;
       
  1379             this.connectionId = connectionId;
       
  1380         }
       
  1381 
       
  1382         private String mbeanServerName() {
       
  1383             if (mbeanServerName != null) return mbeanServerName;
       
  1384             else return (mbeanServerName = getMBeanServerName(mbeanServer));
       
  1385         }
       
  1386 
       
  1387         @SuppressWarnings("serial")  // no serialVersionUID
       
  1388         private class AccessControlFilter implements NotificationFilter {
       
  1389             private final NotificationFilter wrapped;
       
  1390             private final ObjectName name;
       
  1391 
       
  1392             AccessControlFilter(ObjectName name, NotificationFilter wrapped) {
       
  1393                 this.name = name;
       
  1394                 this.wrapped = wrapped;
       
  1395             }
       
  1396 
       
  1397             public boolean isNotificationEnabled(Notification notification) {
       
  1398                 try {
       
  1399                     if (checkNotificationEmission) {
       
  1400                         ServerNotifForwarder.checkMBeanPermission(
       
  1401                                 mbeanServerName(), mbeanServer, name,
       
  1402                                 "addNotificationListener");
       
  1403                     }
       
  1404                     notifAC.fetchNotification(
       
  1405                             connectionId, name, notification, getSubject());
       
  1406                     return (wrapped == null) ? true :
       
  1407                         wrapped.isNotificationEnabled(notification);
       
  1408                 } catch (InstanceNotFoundException e) {
       
  1409                     return false;
       
  1410                 } catch (SecurityException e) {
       
  1411                     return false;
       
  1412                 }
       
  1413             }
       
  1414 
       
  1415         }
       
  1416 
       
  1417         public Integer addNotificationListener(
       
  1418                 ObjectName name, NotificationFilter filter)
       
  1419                 throws InstanceNotFoundException, IOException {
       
  1420             if (notifAC != null) {
       
  1421                 notifAC.addNotificationListener(connectionId, name, getSubject());
       
  1422                 filter = new AccessControlFilter(name, filter);
       
  1423             }
       
  1424             try {
       
  1425                 return delegate.addListener(clientId,name,filter);
       
  1426             } catch (EventClientNotFoundException x) {
       
  1427                 throw new IOException("Unknown clientId: "+clientId,x);
       
  1428             }
       
  1429         }
       
  1430 
       
  1431         public void removeNotificationListener(ObjectName name, Integer id)
       
  1432                 throws InstanceNotFoundException, ListenerNotFoundException,
       
  1433                        IOException {
       
  1434             if (notifAC != null)
       
  1435                 notifAC.removeNotificationListener(connectionId, name, getSubject());
       
  1436             try {
       
  1437                 delegate.removeListenerOrSubscriber(clientId, id);
       
  1438             } catch (EventClientNotFoundException x) {
       
  1439                 throw new IOException("Unknown clientId: "+clientId,x);
       
  1440             }
       
  1441         }
       
  1442 
       
  1443         public void removeNotificationListener(ObjectName name, Integer[] ids)
       
  1444                 throws InstanceNotFoundException, ListenerNotFoundException,
       
  1445                        IOException {
       
  1446             if (notifAC != null)
       
  1447                 notifAC.removeNotificationListener(connectionId, name, getSubject());
       
  1448             try {
       
  1449                 for (Integer id : ids)
       
  1450                     delegate.removeListenerOrSubscriber(clientId, id);
       
  1451             } catch (EventClientNotFoundException x) {
       
  1452                 throw new IOException("Unknown clientId: "+clientId,x);
       
  1453             }
       
  1454         }
       
  1455 
       
  1456         public NotificationResult fetchNotifications(long csn, long timeout,
       
  1457                 int maxcount)
       
  1458             throws IOException {
       
  1459             try {
       
  1460                 // For some reason the delegate doesn't accept a negative
       
  1461                 // sequence number. However legacy clients will always call
       
  1462                 // fetchNotifications with a negative sequence number, when
       
  1463                 // they call it for the first time.
       
  1464                 // In that case, we will use 0 instead.
       
  1465                 //
       
  1466                 return delegate.fetchNotifications(
       
  1467                         clientId, Math.max(csn, 0), maxcount, timeout);
       
  1468             } catch (EventClientNotFoundException x) {
       
  1469                 throw new IOException("Unknown clientId: "+clientId,x);
       
  1470             }
       
  1471         }
       
  1472 
       
  1473         public void terminate()
       
  1474             throws IOException {
       
  1475             try {
       
  1476                 delegate.removeClient(clientId);
       
  1477             } catch (EventClientNotFoundException x) {
       
  1478                 throw new IOException("Unknown clientId: "+clientId,x);
       
  1479             }
       
  1480         }
       
  1481 
       
  1482         private static Subject getSubject() {
       
  1483             return Subject.getSubject(AccessController.getContext());
       
  1484         }
       
  1485     }
       
  1486 
       
  1487     /**
       
  1488      * Creates a SubscriptionManager that uses either the legacy notifications
       
  1489      * mechanism (ServerNotifForwarder) or the new event service
       
  1490      * (EventClientDelegateMBean) depending on which option was passed in
       
  1491      * the connector's map.
       
  1492      **/
       
  1493     private SubscriptionManager createSubscriptionManager()
       
  1494         throws IOException {
       
  1495         if (EnvHelp.delegateToEventService(env) &&
       
  1496                 mbeanServer.isRegistered(EventClientDelegate.OBJECT_NAME)) {
       
  1497             final EventClientDelegateMBean mbean =
       
  1498                     JMX.newMBeanProxy(mbeanServer,
       
  1499                         EventClientDelegate.OBJECT_NAME,
       
  1500                         EventClientDelegateMBean.class);
       
  1501             String clientId;
       
  1502             try {
       
  1503                  clientId =
       
  1504                     mbean.addClient(
       
  1505                 FetchingEventForwarder.class.getName(),
       
  1506                 new Object[] {EnvHelp.getNotifBufferSize(env)},
       
  1507                 new String[] {int.class.getName()});
       
  1508             } catch (Exception e) {
       
  1509                 if (e instanceof IOException)
       
  1510                     throw (IOException) e;
       
  1511                 else
       
  1512                     throw new IOException(e);
       
  1513             }
       
  1514 
       
  1515             // we're going to call remove client...
       
  1516             try {
       
  1517                 mbean.lease(clientId, Long.MAX_VALUE);
       
  1518             } catch (EventClientNotFoundException x) {
       
  1519                 throw new IOException("Unknown clientId: "+clientId,x);
       
  1520             }
       
  1521             return new EventSubscriptionManager(mbeanServer, mbean, env,
       
  1522                     clientId, connectionId);
       
  1523         } else {
       
  1524             final ServerNotifForwarder serverNotifForwarder =
       
  1525                 new ServerNotifForwarder(mbeanServer,
       
  1526                                          env,
       
  1527                                          rmiServer.getNotifBuffer(),
       
  1528                                          connectionId);
       
  1529              return new LegacySubscriptionManager(serverNotifForwarder);
       
  1530         }
       
  1531     }
       
  1532 
       
  1533     /**
       
  1534      * Lazy creation of a  SubscriptionManager.
       
  1535      **/
       
  1536     private synchronized SubscriptionManager getSubscriptionManager()
       
  1537         throws IOException {
       
  1538         // Lazily created when first use. Mainly when
       
  1539         // addNotificationListener is first called.
       
  1540 
       
  1541         if (subscriptionManager == null) {
       
  1542              subscriptionManager = createSubscriptionManager();
       
  1543         }
       
  1544         return subscriptionManager;
       
  1545     }
       
  1546 
       
  1547     // calls SubscriptionManager.
       
  1548     private void doRemoveListener(ObjectName name, Integer id)
       
  1549         throws InstanceNotFoundException, ListenerNotFoundException,
       
  1550             IOException {
       
  1551            getSubscriptionManager().removeNotificationListener(name,id);
       
  1552     }
       
  1553 
       
  1554     // calls SubscriptionManager.
       
  1555     private void doRemoveListener(ObjectName name, Integer[] ids)
       
  1556         throws Exception {
       
  1557            getSubscriptionManager().removeNotificationListener(name,ids);
       
  1558     }
       
  1559 
       
  1560     // calls SubscriptionManager.
       
  1561     private NotificationResult doFetchNotifs(long csn, long timeout, int maxcount)
       
  1562          throws IOException {
       
  1563          return getSubscriptionManager().fetchNotifications(csn, timeout, maxcount);
       
  1564     }
       
  1565 
       
  1566     // calls SubscriptionManager.
       
  1567     private Integer doAddListener(ObjectName name, NotificationFilter filter)
       
  1568          throws InstanceNotFoundException, IOException {
       
  1569          return getSubscriptionManager().addNotificationListener(name,filter);
       
  1570     }
       
  1571 
       
  1572 
  1264 
  1573     /**
  1265     /**
  1574      * <p>Returns a string representation of this object.  In general,
  1266      * <p>Returns a string representation of this object.  In general,
  1575      * the <code>toString</code> method returns a string that
  1267      * the <code>toString</code> method returns a string that
  1576      * "textually represents" this object. The result should be a
  1268      * "textually represents" this object. The result should be a
  1785         case UNREGISTER_MBEAN:
  1477         case UNREGISTER_MBEAN:
  1786             mbeanServer.unregisterMBean((ObjectName)params[0]);
  1478             mbeanServer.unregisterMBean((ObjectName)params[0]);
  1787             return null;
  1479             return null;
  1788 
  1480 
  1789         case ADD_NOTIFICATION_LISTENERS:
  1481         case ADD_NOTIFICATION_LISTENERS:
  1790             return doAddListener((ObjectName)params[0],
  1482             return getServerNotifFwd().addNotificationListener(
  1791                                  (NotificationFilter)params[1]);
  1483                                                 (ObjectName)params[0],
       
  1484                                                 (NotificationFilter)params[1]);
  1792 
  1485 
  1793         case ADD_NOTIFICATION_LISTENER_OBJECTNAME:
  1486         case ADD_NOTIFICATION_LISTENER_OBJECTNAME:
  1794             mbeanServer.addNotificationListener((ObjectName)params[0],
  1487             mbeanServer.addNotificationListener((ObjectName)params[0],
  1795                                                 (ObjectName)params[1],
  1488                                                 (ObjectName)params[1],
  1796                                                 (NotificationFilter)params[2],
  1489                                                 (NotificationFilter)params[2],
  1797                                                 params[3]);
  1490                                                 params[3]);
  1798             return null;
  1491             return null;
  1799 
  1492 
  1800         case REMOVE_NOTIFICATION_LISTENER:
  1493         case REMOVE_NOTIFICATION_LISTENER:
  1801             doRemoveListener((ObjectName)params[0],(Integer[])params[1]);
  1494             getServerNotifFwd().removeNotificationListener(
       
  1495                                                    (ObjectName)params[0],
       
  1496                                                    (Integer[])params[1]);
  1802             return null;
  1497             return null;
  1803 
  1498 
  1804         case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME:
  1499         case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME:
  1805             mbeanServer.removeNotificationListener((ObjectName)params[0],
  1500             mbeanServer.removeNotificationListener((ObjectName)params[0],
  1806                                                    (ObjectName)params[1]);
  1501                                                    (ObjectName)params[1]);
  1907             e = ((PrivilegedActionException)e).getException();
  1602             e = ((PrivilegedActionException)e).getException();
  1908         }
  1603         }
  1909         return e;
  1604         return e;
  1910     }
  1605     }
  1911 
  1606 
  1912     private static String getMBeanServerName(final MBeanServer server) {
       
  1913         final PrivilegedAction<String> action = new PrivilegedAction<String>() {
       
  1914             public String run() {
       
  1915                 return Util.getMBeanServerSecurityName(server);
       
  1916             }
       
  1917         };
       
  1918         return AccessController.doPrivileged(action);
       
  1919     }
       
  1920 
       
  1921     private static final Object[] NO_OBJECTS = new Object[0];
  1607     private static final Object[] NO_OBJECTS = new Object[0];
  1922     private static final String[] NO_STRINGS = new String[0];
  1608     private static final String[] NO_STRINGS = new String[0];
  1923 
  1609 
  1924     /*
  1610     /*
  1925      * The JMX spec doesn't explicitly say that a null Object[] or
  1611      * The JMX spec doesn't explicitly say that a null Object[] or
  2031         UNREGISTER_MBEAN                                        = 24;
  1717         UNREGISTER_MBEAN                                        = 24;
  2032 
  1718 
  2033     // SERVER NOTIFICATION
  1719     // SERVER NOTIFICATION
  2034     //--------------------
  1720     //--------------------
  2035 
  1721 
  2036     private SubscriptionManager subscriptionManager;
  1722     private ServerNotifForwarder serverNotifForwarder;
  2037     private Map<String, ?> env;
  1723     private Map<String, ?> env;
  2038 
  1724 
  2039     // TRACES & DEBUG
  1725     // TRACES & DEBUG
  2040     //---------------
  1726     //---------------
  2041 
  1727