--- a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java Wed Oct 21 16:28:57 2009 +0200
+++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java Wed Oct 21 17:33:18 2009 +0200
@@ -25,12 +25,10 @@
package javax.management.remote.rmi;
-import com.sun.jmx.mbeanserver.Util;
import static com.sun.jmx.mbeanserver.Util.cast;
import com.sun.jmx.remote.internal.ServerCommunicatorAdmin;
import com.sun.jmx.remote.internal.ServerNotifForwarder;
import com.sun.jmx.remote.security.JMXSubjectDomainCombiner;
-import com.sun.jmx.remote.security.NotificationAccessController;
import com.sun.jmx.remote.security.SubjectDelegator;
import com.sun.jmx.remote.util.ClassLoaderWithRepository;
import com.sun.jmx.remote.util.ClassLogger;
@@ -38,7 +36,6 @@
import com.sun.jmx.remote.util.OrderClassLoaders;
import java.io.IOException;
-import java.lang.reflect.UndeclaredThrowableException;
import java.rmi.MarshalledObject;
import java.rmi.UnmarshalException;
import java.rmi.server.Unreferenced;
@@ -59,25 +56,18 @@
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
-import javax.management.JMX;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
-import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.QueryExp;
import javax.management.ReflectionException;
import javax.management.RuntimeOperationsException;
-import javax.management.event.EventClientDelegate;
-import javax.management.event.EventClientDelegateMBean;
-import javax.management.event.EventClientNotFoundException;
-import javax.management.event.FetchingEventForwarder;
-import javax.management.namespace.JMXNamespaces;
import javax.management.remote.JMXServerErrorException;
import javax.management.remote.NotificationResult;
import javax.management.remote.TargetedNotification;
@@ -168,6 +158,17 @@
this.env = env;
}
+ private synchronized ServerNotifForwarder getServerNotifFwd() {
+ // Lazily created when first use. Mainly when
+ // addNotificationListener is first called.
+ if (serverNotifForwarder == null)
+ serverNotifForwarder =
+ new ServerNotifForwarder(mbeanServer,
+ env,
+ rmiServer.getNotifBuffer(),
+ connectionId);
+ return serverNotifForwarder;
+ }
public String getConnectionId() throws IOException {
// We should call reqIncomming() here... shouldn't we?
@@ -178,7 +179,6 @@
final boolean debug = logger.debugOn();
final String idstr = (debug?"["+this.toString()+"]":null);
- final SubscriptionManager mgr;
synchronized (this) {
if (terminated) {
if (debug) logger.debug("close",idstr + " already terminated.");
@@ -193,12 +193,11 @@
serverCommunicatorAdmin.terminate();
}
- mgr = subscriptionManager;
- subscriptionManager = null;
+ if (serverNotifForwarder != null) {
+ serverNotifForwarder.terminate();
+ }
}
- if (mgr != null) mgr.terminate();
-
rmiServer.clientClosed(this);
if (debug) logger.debug("close",idstr + " closed.");
@@ -997,7 +996,8 @@
// remove all registered listeners
for (int j=0; j<i; j++) {
try {
- doRemoveListener(names[j],ids[j]);
+ getServerNotifFwd().removeNotificationListener(names[j],
+ ids[j]);
} catch (Exception eee) {
// strange
}
@@ -1247,330 +1247,22 @@
final long csn = clientSequenceNumber;
final int mn = maxNotifications;
final long t = timeout;
-
- final PrivilegedExceptionAction<NotificationResult> action =
- new PrivilegedExceptionAction<NotificationResult>() {
- public NotificationResult run() throws IOException {
- return doFetchNotifs(csn, t, mn);
+ PrivilegedAction<NotificationResult> action =
+ new PrivilegedAction<NotificationResult>() {
+ public NotificationResult run() {
+ return getServerNotifFwd().fetchNotifs(csn, t, mn);
}
};
- try {
- if (acc == null)
- return action.run();
- else
- return AccessController.doPrivileged(action, acc);
- } catch (IOException x) {
- throw x;
- } catch (RuntimeException x) {
- throw x;
- } catch (Exception x) {
- // should not happen
- throw new UndeclaredThrowableException(x);
- }
-
+ if (acc == null)
+ return action.run();
+ else
+ return AccessController.doPrivileged(action, acc);
} finally {
serverCommunicatorAdmin.rspOutgoing();
}
}
/**
- * This is an abstraction class that let us use the legacy
- * ServerNotifForwarder and the new EventClientDelegateMBean
- * indifferently.
- **/
- private static interface SubscriptionManager {
- public void removeNotificationListener(ObjectName name, Integer id)
- throws InstanceNotFoundException, ListenerNotFoundException, IOException;
- public void removeNotificationListener(ObjectName name, Integer[] ids)
- throws Exception;
- public NotificationResult fetchNotifications(long csn, long timeout, int maxcount)
- throws IOException;
- public Integer addNotificationListener(ObjectName name, NotificationFilter filter)
- throws InstanceNotFoundException, IOException;
- public void terminate()
- throws IOException;
- }
-
- /**
- * A SubscriptionManager that uses a ServerNotifForwarder.
- **/
- private static class LegacySubscriptionManager implements SubscriptionManager {
- private final ServerNotifForwarder forwarder;
- LegacySubscriptionManager(ServerNotifForwarder forwarder) {
- this.forwarder = forwarder;
- }
-
- public void removeNotificationListener(ObjectName name, Integer id)
- throws InstanceNotFoundException, ListenerNotFoundException,
- IOException {
- if (!JMXNamespaces.getContainingNamespace(name).equals("")) {
- logger.debug("removeNotificationListener",
- "This connector server is not configured to support " +
- "forwarding of notification subscriptions to name spaces");
- throw new RuntimeOperationsException(
- new UnsupportedOperationException(
- "removeNotificationListener on name space MBeans. "));
- }
- forwarder.removeNotificationListener(name,id);
- }
-
- public void removeNotificationListener(ObjectName name, Integer[] ids)
- throws Exception {
- if (!JMXNamespaces.getContainingNamespace(name).equals("")) {
- logger.debug("removeNotificationListener",
- "This connector server is not configured to support " +
- "forwarding of notification subscriptions to name spaces");
- throw new RuntimeOperationsException(
- new UnsupportedOperationException(
- "removeNotificationListener on name space MBeans. "));
- }
- forwarder.removeNotificationListener(name,ids);
- }
-
- public NotificationResult fetchNotifications(long csn, long timeout, int maxcount) {
- return forwarder.fetchNotifs(csn,timeout,maxcount);
- }
-
- public Integer addNotificationListener(ObjectName name,
- NotificationFilter filter)
- throws InstanceNotFoundException, IOException {
- if (!JMXNamespaces.getContainingNamespace(name).equals("")) {
- logger.debug("addNotificationListener",
- "This connector server is not configured to support " +
- "forwarding of notification subscriptions to name spaces");
- throw new RuntimeOperationsException(
- new UnsupportedOperationException(
- "addNotificationListener on name space MBeans. "));
- }
- return forwarder.addNotificationListener(name,filter);
- }
-
- public void terminate() {
- forwarder.terminate();
- }
- }
-
- /**
- * A SubscriptionManager that uses an EventClientDelegateMBean.
- **/
- private static class EventSubscriptionManager
- implements SubscriptionManager {
- private final MBeanServer mbeanServer;
- private final EventClientDelegateMBean delegate;
- private final NotificationAccessController notifAC;
- private final boolean checkNotificationEmission;
- private final String clientId;
- private final String connectionId;
- private volatile String mbeanServerName;
-
- EventSubscriptionManager(
- MBeanServer mbeanServer,
- EventClientDelegateMBean delegate,
- Map<String, ?> env,
- String clientId,
- String connectionId) {
- this.mbeanServer = mbeanServer;
- this.delegate = delegate;
- this.notifAC = EnvHelp.getNotificationAccessController(env);
- this.checkNotificationEmission =
- EnvHelp.computeBooleanFromString(
- env, "jmx.remote.x.check.notification.emission", false);
- this.clientId = clientId;
- this.connectionId = connectionId;
- }
-
- private String mbeanServerName() {
- if (mbeanServerName != null) return mbeanServerName;
- else return (mbeanServerName = getMBeanServerName(mbeanServer));
- }
-
- @SuppressWarnings("serial") // no serialVersionUID
- private class AccessControlFilter implements NotificationFilter {
- private final NotificationFilter wrapped;
- private final ObjectName name;
-
- AccessControlFilter(ObjectName name, NotificationFilter wrapped) {
- this.name = name;
- this.wrapped = wrapped;
- }
-
- public boolean isNotificationEnabled(Notification notification) {
- try {
- if (checkNotificationEmission) {
- ServerNotifForwarder.checkMBeanPermission(
- mbeanServerName(), mbeanServer, name,
- "addNotificationListener");
- }
- notifAC.fetchNotification(
- connectionId, name, notification, getSubject());
- return (wrapped == null) ? true :
- wrapped.isNotificationEnabled(notification);
- } catch (InstanceNotFoundException e) {
- return false;
- } catch (SecurityException e) {
- return false;
- }
- }
-
- }
-
- public Integer addNotificationListener(
- ObjectName name, NotificationFilter filter)
- throws InstanceNotFoundException, IOException {
- if (notifAC != null) {
- notifAC.addNotificationListener(connectionId, name, getSubject());
- filter = new AccessControlFilter(name, filter);
- }
- try {
- return delegate.addListener(clientId,name,filter);
- } catch (EventClientNotFoundException x) {
- throw new IOException("Unknown clientId: "+clientId,x);
- }
- }
-
- public void removeNotificationListener(ObjectName name, Integer id)
- throws InstanceNotFoundException, ListenerNotFoundException,
- IOException {
- if (notifAC != null)
- notifAC.removeNotificationListener(connectionId, name, getSubject());
- try {
- delegate.removeListenerOrSubscriber(clientId, id);
- } catch (EventClientNotFoundException x) {
- throw new IOException("Unknown clientId: "+clientId,x);
- }
- }
-
- public void removeNotificationListener(ObjectName name, Integer[] ids)
- throws InstanceNotFoundException, ListenerNotFoundException,
- IOException {
- if (notifAC != null)
- notifAC.removeNotificationListener(connectionId, name, getSubject());
- try {
- for (Integer id : ids)
- delegate.removeListenerOrSubscriber(clientId, id);
- } catch (EventClientNotFoundException x) {
- throw new IOException("Unknown clientId: "+clientId,x);
- }
- }
-
- public NotificationResult fetchNotifications(long csn, long timeout,
- int maxcount)
- throws IOException {
- try {
- // For some reason the delegate doesn't accept a negative
- // sequence number. However legacy clients will always call
- // fetchNotifications with a negative sequence number, when
- // they call it for the first time.
- // In that case, we will use 0 instead.
- //
- return delegate.fetchNotifications(
- clientId, Math.max(csn, 0), maxcount, timeout);
- } catch (EventClientNotFoundException x) {
- throw new IOException("Unknown clientId: "+clientId,x);
- }
- }
-
- public void terminate()
- throws IOException {
- try {
- delegate.removeClient(clientId);
- } catch (EventClientNotFoundException x) {
- throw new IOException("Unknown clientId: "+clientId,x);
- }
- }
-
- private static Subject getSubject() {
- return Subject.getSubject(AccessController.getContext());
- }
- }
-
- /**
- * Creates a SubscriptionManager that uses either the legacy notifications
- * mechanism (ServerNotifForwarder) or the new event service
- * (EventClientDelegateMBean) depending on which option was passed in
- * the connector's map.
- **/
- private SubscriptionManager createSubscriptionManager()
- throws IOException {
- if (EnvHelp.delegateToEventService(env) &&
- mbeanServer.isRegistered(EventClientDelegate.OBJECT_NAME)) {
- final EventClientDelegateMBean mbean =
- JMX.newMBeanProxy(mbeanServer,
- EventClientDelegate.OBJECT_NAME,
- EventClientDelegateMBean.class);
- String clientId;
- try {
- clientId =
- mbean.addClient(
- FetchingEventForwarder.class.getName(),
- new Object[] {EnvHelp.getNotifBufferSize(env)},
- new String[] {int.class.getName()});
- } catch (Exception e) {
- if (e instanceof IOException)
- throw (IOException) e;
- else
- throw new IOException(e);
- }
-
- // we're going to call remove client...
- try {
- mbean.lease(clientId, Long.MAX_VALUE);
- } catch (EventClientNotFoundException x) {
- throw new IOException("Unknown clientId: "+clientId,x);
- }
- return new EventSubscriptionManager(mbeanServer, mbean, env,
- clientId, connectionId);
- } else {
- final ServerNotifForwarder serverNotifForwarder =
- new ServerNotifForwarder(mbeanServer,
- env,
- rmiServer.getNotifBuffer(),
- connectionId);
- return new LegacySubscriptionManager(serverNotifForwarder);
- }
- }
-
- /**
- * Lazy creation of a SubscriptionManager.
- **/
- private synchronized SubscriptionManager getSubscriptionManager()
- throws IOException {
- // Lazily created when first use. Mainly when
- // addNotificationListener is first called.
-
- if (subscriptionManager == null) {
- subscriptionManager = createSubscriptionManager();
- }
- return subscriptionManager;
- }
-
- // calls SubscriptionManager.
- private void doRemoveListener(ObjectName name, Integer id)
- throws InstanceNotFoundException, ListenerNotFoundException,
- IOException {
- getSubscriptionManager().removeNotificationListener(name,id);
- }
-
- // calls SubscriptionManager.
- private void doRemoveListener(ObjectName name, Integer[] ids)
- throws Exception {
- getSubscriptionManager().removeNotificationListener(name,ids);
- }
-
- // calls SubscriptionManager.
- private NotificationResult doFetchNotifs(long csn, long timeout, int maxcount)
- throws IOException {
- return getSubscriptionManager().fetchNotifications(csn, timeout, maxcount);
- }
-
- // calls SubscriptionManager.
- private Integer doAddListener(ObjectName name, NotificationFilter filter)
- throws InstanceNotFoundException, IOException {
- return getSubscriptionManager().addNotificationListener(name,filter);
- }
-
-
- /**
* <p>Returns a string representation of this object. In general,
* the <code>toString</code> method returns a string that
* "textually represents" this object. The result should be a
@@ -1787,8 +1479,9 @@
return null;
case ADD_NOTIFICATION_LISTENERS:
- return doAddListener((ObjectName)params[0],
- (NotificationFilter)params[1]);
+ return getServerNotifFwd().addNotificationListener(
+ (ObjectName)params[0],
+ (NotificationFilter)params[1]);
case ADD_NOTIFICATION_LISTENER_OBJECTNAME:
mbeanServer.addNotificationListener((ObjectName)params[0],
@@ -1798,7 +1491,9 @@
return null;
case REMOVE_NOTIFICATION_LISTENER:
- doRemoveListener((ObjectName)params[0],(Integer[])params[1]);
+ getServerNotifFwd().removeNotificationListener(
+ (ObjectName)params[0],
+ (Integer[])params[1]);
return null;
case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME:
@@ -1909,15 +1604,6 @@
return e;
}
- private static String getMBeanServerName(final MBeanServer server) {
- final PrivilegedAction<String> action = new PrivilegedAction<String>() {
- public String run() {
- return Util.getMBeanServerSecurityName(server);
- }
- };
- return AccessController.doPrivileged(action);
- }
-
private static final Object[] NO_OBJECTS = new Object[0];
private static final String[] NO_STRINGS = new String[0];
@@ -2033,7 +1719,7 @@
// SERVER NOTIFICATION
//--------------------
- private SubscriptionManager subscriptionManager;
+ private ServerNotifForwarder serverNotifForwarder;
private Map<String, ?> env;
// TRACES & DEBUG