ServerNotifForwarderpublic class ServerNotifForwarder extends Object
Fields Summary |
---|
private final NotificationBufferFilter | bufferFilter | private MBeanServer | mbeanServer | private final String | connectionId | private final long | connectionTimeout | private static int | listenerCounter | private static final int[] | listenerCounterLock | private NotificationBuffer | notifBuffer | private Map | listenerMap | private boolean | terminated | private final int[] | terminationLock | static final String | broadcasterClass | private final boolean | checkNotificationEmission | private final NotificationAccessController | notificationAccessController | private static final ClassLogger | logger |
Constructors Summary |
---|
public ServerNotifForwarder(MBeanServer mbeanServer, Map env, NotificationBuffer notifBuffer, String connectionId)
this.mbeanServer = mbeanServer;
this.notifBuffer = notifBuffer;
this.connectionId = connectionId;
connectionTimeout = EnvHelp.getServerConnectionTimeout(env);
checkNotificationEmission = EnvHelp.computeBooleanFromString(
env,
"jmx.remote.x.check.notification.emission");
notificationAccessController = (NotificationAccessController)
env.get("com.sun.jmx.remote.notification.access.controller");
|
Methods Summary |
---|
public java.lang.Integer | addNotificationListener(javax.management.ObjectName name, javax.management.NotificationFilter filter)
if (logger.traceOn()) {
logger.trace("addNotificationListener",
"Add a listener at " + name);
}
checkState();
// Explicitly check MBeanPermission for addNotificationListener
//
checkMBeanPermission(name, "addNotificationListener");
if (notificationAccessController != null) {
notificationAccessController.addNotificationListener(
connectionId,
name,
Subject.getSubject(AccessController.getContext()));
}
try {
Boolean instanceOf = (Boolean)
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws InstanceNotFoundException {
return new Boolean(
mbeanServer.isInstanceOf(name,
broadcasterClass));
}
});
if (!instanceOf.booleanValue()) {
throw new IllegalArgumentException("The specified MBean [" +
name + "] is not a " +
"NotificationBroadcaster " +
"object.");
}
} catch (PrivilegedActionException e) {
throw (InstanceNotFoundException) extractException(e);
}
final Integer id = getListenerID();
// 6238731: set the default domain if no domain is set.
ObjectName nn = name;
if (name.getDomain() == null || name.getDomain().equals("")) {
try {
nn = ObjectName.getInstance(mbeanServer.getDefaultDomain(),
name.getKeyPropertyList());
} catch (MalformedObjectNameException mfoe) {
// impossible, but...
IOException ioe = new IOException(mfoe.getMessage());
ioe.initCause(mfoe);
throw ioe;
}
}
synchronized (listenerMap) {
IdAndFilter idaf = new IdAndFilter(id, filter);
Set<IdAndFilter> set = listenerMap.get(nn);
// Tread carefully because if set.size() == 1 it may be the
// Collections.singleton we make here, which is unmodifiable.
if (set == null)
set = Collections.singleton(idaf);
else {
if (set.size() == 1)
set = new HashSet<IdAndFilter>(set);
set.add(idaf);
}
listenerMap.put(nn, set);
}
return id;
| private boolean | allowNotificationEmission(javax.management.ObjectName name, javax.management.remote.TargetedNotification tn)Check if the caller has the right to get the following notifications.
try {
if (checkNotificationEmission) {
checkMBeanPermission(name, "addNotificationListener");
}
if (notificationAccessController != null) {
notificationAccessController.fetchNotification(
connectionId,
name,
tn.getNotification(),
Subject.getSubject(AccessController.getContext()));
}
return true;
} catch (SecurityException e) {
if (logger.debugOn()) {
logger.debug("fetchNotifs", "Notification " +
tn.getNotification() + " not forwarded: the " +
"caller didn't have the required access rights");
}
return false;
} catch (Exception e) {
if (logger.debugOn()) {
logger.debug("fetchNotifs", "Notification " +
tn.getNotification() + " not forwarded: " +
"got an unexpected exception: " + e);
}
return false;
}
| private void | checkMBeanPermission(javax.management.ObjectName name, java.lang.String actions)Explicitly check the MBeanPermission for
the current access control context.
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
AccessControlContext acc = AccessController.getContext();
ObjectInstance oi = null;
try {
oi = (ObjectInstance) AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run()
throws InstanceNotFoundException {
return mbeanServer.getObjectInstance(name);
}
});
} catch (PrivilegedActionException e) {
throw (InstanceNotFoundException) extractException(e);
}
String classname = oi.getClassName();
MBeanPermission perm = new MBeanPermission(classname,
null,
name,
actions);
sm.checkPermission(perm, acc);
}
| private void | checkState()
synchronized(terminationLock) {
if (terminated) {
throw new IOException("The connection has been terminated.");
}
}
| private static java.lang.Exception | extractException(java.lang.Exception e)Iterate until we extract the real exception
from a stack of PrivilegedActionExceptions.
while (e instanceof PrivilegedActionException) {
e = ((PrivilegedActionException)e).getException();
}
return e;
| public javax.management.remote.NotificationResult | fetchNotifs(long startSequenceNumber, long timeout, int maxNotifications)
if (logger.traceOn()) {
logger.trace("fetchNotifs", "Fetching notifications, the " +
"startSequenceNumber is " + startSequenceNumber +
", the timeout is " + timeout +
", the maxNotifications is " + maxNotifications);
}
NotificationResult nr = null;
final long t = Math.min(connectionTimeout, timeout);
try {
nr = notifBuffer.fetchNotifications(bufferFilter,
startSequenceNumber,
t, maxNotifications);
} catch (InterruptedException ire) {
nr = new NotificationResult(0L, 0L, new TargetedNotification[0]);
}
if (logger.traceOn()) {
logger.trace("fetchNotifs", "Forwarding the notifs: "+nr);
}
return nr;
| private java.lang.Integer | getListenerID()
synchronized(listenerCounterLock) {
return new Integer(listenerCounter++);
}
| public void | removeNotificationListener(javax.management.ObjectName name, java.lang.Integer[] listenerIDs)
if (logger.traceOn()) {
logger.trace("removeNotificationListener",
"Remove some listeners from " + name);
}
checkState();
// Explicitly check MBeanPermission for removeNotificationListener
//
checkMBeanPermission(name, "removeNotificationListener");
if (notificationAccessController != null) {
notificationAccessController.removeNotificationListener(
connectionId,
name,
Subject.getSubject(AccessController.getContext()));
}
Exception re = null;
for (int i = 0 ; i < listenerIDs.length ; i++) {
try {
removeNotificationListener(name, listenerIDs[i]);
} catch (Exception e) {
// Give back the first exception
//
if (re != null) {
re = e;
}
}
}
if (re != null) {
throw re;
}
| public void | removeNotificationListener(javax.management.ObjectName name, java.lang.Integer listenerID)
if (logger.traceOn()) {
logger.trace("removeNotificationListener",
"Remove the listener " + listenerID + " from " + name);
}
checkState();
if (name != null && !name.isPattern()) {
if (!mbeanServer.isRegistered(name)) {
throw new InstanceNotFoundException("The MBean " + name +
" is not registered.");
}
}
synchronized (listenerMap) {
// Tread carefully because if set.size() == 1 it may be a
// Collections.singleton, which is unmodifiable.
Set<IdAndFilter> set = listenerMap.get(name);
IdAndFilter idaf = new IdAndFilter(listenerID, null);
if (set == null || !set.contains(idaf))
throw new ListenerNotFoundException("Listener not found");
if (set.size() == 1)
listenerMap.remove(name);
else
set.remove(idaf);
}
| public void | terminate()
if (logger.traceOn()) {
logger.trace("terminate", "Be called.");
}
synchronized(terminationLock) {
if (terminated) {
return;
}
terminated = true;
synchronized(listenerMap) {
listenerMap.clear();
}
}
if (logger.traceOn()) {
logger.trace("terminate", "Terminated.");
}
|
|