1 7 8 package com.sun.jmx.remote.internal; 9 10 import java.io.IOException ; 11 import java.security.AccessControlContext ; 12 import java.security.AccessController ; 13 import java.security.PrivilegedAction ; 14 import java.security.PrivilegedActionException ; 15 import java.security.PrivilegedExceptionAction ; 16 import java.util.Set ; 17 import java.util.HashSet ; 18 import java.util.Map ; 19 20 import javax.management.ObjectInstance ; 21 import javax.management.ObjectName ; 22 import javax.management.MBeanPermission ; 23 import javax.management.MBeanServer ; 24 import javax.management.Notification ; 25 import javax.management.NotificationBroadcaster ; 26 import javax.management.NotificationListener ; 27 import javax.management.NotificationFilter ; 28 import javax.management.MBeanServerNotification ; 29 import javax.management.NotificationFilterSupport ; 30 import javax.management.ListenerNotFoundException ; 31 import javax.management.InstanceNotFoundException ; 32 33 import javax.management.remote.TargetedNotification ; 34 import javax.management.remote.NotificationResult ; 35 36 import javax.security.auth.Subject ; 37 38 import com.sun.jmx.remote.util.ClassLogger; 39 import com.sun.jmx.remote.util.EnvHelp; 40 import com.sun.jmx.remote.internal.ListenerInfo; 41 42 public class ServerNotifForwarder { 43 44 public ServerNotifForwarder(MBeanServer mbeanServer, 45 Map env, 46 NotificationBuffer notifBuffer) { 47 this.mbeanServer = mbeanServer; 48 49 this.notifBuffer = notifBuffer; 50 51 52 connectionTimeout = EnvHelp.getServerConnectionTimeout(env); 53 } 54 55 public Integer addNotificationListener(final ObjectName name, 56 final NotificationFilter filter) 57 throws InstanceNotFoundException , IOException { 58 59 if (logger.traceOn()) { 60 logger.trace("addNotificationListener", 61 "Add a listener at " + name); 62 } 63 64 checkState(); 65 66 checkMBeanPermission(name, "addNotificationListener"); 69 70 try { 71 Boolean instanceOf = (Boolean ) 72 AccessController.doPrivileged(new PrivilegedExceptionAction () { 73 public Object run() throws InstanceNotFoundException { 74 return new Boolean ( 75 mbeanServer.isInstanceOf(name, 76 broadcasterClass)); 77 } 78 }); 79 if (!instanceOf.booleanValue()) { 80 throw new IllegalArgumentException ("The specified MBean [" + 81 name + "] is not a " + 82 "NotificationBroadcaster " + 83 "object."); 84 } 85 } catch (PrivilegedActionException e) { 86 throw (InstanceNotFoundException ) extractException(e); 87 } 88 89 final Integer id = getListenerID(); 90 synchronized(listenerList) { 91 listenerList.add(new ListenerInfo(id, name, filter)); 92 } 93 94 return id; 95 } 96 97 public void removeNotificationListener(ObjectName name, 98 Integer [] listenerIDs) 99 throws Exception { 100 101 if (logger.traceOn()) { 102 logger.trace("removeNotificationListener", 103 "Remove some listeners from " + name); 104 } 105 106 checkState(); 107 108 checkMBeanPermission(name, "removeNotificationListener"); 111 112 Exception re = null; 113 for (int i = 0 ; i < listenerIDs.length ; i++) { 114 try { 115 removeNotificationListener(name, listenerIDs[i]); 116 } catch (Exception e) { 117 if (re != null) { 120 re = e; 121 } 122 } 123 } 124 if (re != null) { 125 throw re; 126 } 127 } 128 129 public void removeNotificationListener(ObjectName name, Integer listenerID) 130 throws 131 InstanceNotFoundException , 132 ListenerNotFoundException , 133 IOException { 134 135 if (logger.traceOn()) { 136 logger.trace("removeNotificationListener", 137 "Remove the listener " + listenerID + " from " + name); 138 } 139 140 checkState(); 141 142 if (name != null && !name.isPattern()) { 143 if (!mbeanServer.isRegistered(name)) { 144 throw new InstanceNotFoundException ("The MBean " + name + 145 " is not registered."); 146 } 147 } 148 149 synchronized(listenerList) { 150 if (!listenerList.remove(new ListenerInfo(listenerID,name,null))) { 151 throw new ListenerNotFoundException ("Listener not found!"); 152 } 153 } 154 } 155 156 public NotificationResult fetchNotifs(long startSequenceNumber, 157 long timeout, 158 int maxNotifications) { 159 if (logger.traceOn()) { 160 logger.trace("fetchNotifs", "Fetching notifications, the " + 161 "startSequenceNumber is " + startSequenceNumber + 162 ", the timeout is " + timeout + 163 ", the maxNotifications is " + maxNotifications); 164 } 165 166 NotificationResult nr = null; 167 final long t = Math.min(connectionTimeout, timeout); 168 try { 169 nr = notifBuffer.fetchNotifications(listenerList, 170 startSequenceNumber, 171 t, maxNotifications); 172 } catch (InterruptedException ire) { 173 nr = new NotificationResult (0L, 0L, new TargetedNotification [0]); 174 } 175 176 if (logger.traceOn()) { 177 logger.trace("fetchNotifs", "Forwarding the notifs: "+nr); 178 } 179 180 return nr; 181 } 182 183 public void terminate() { 184 if (logger.traceOn()) { 185 logger.trace("terminate", "Be called."); 186 } 187 188 synchronized(terminationLock) { 189 if (terminated) { 190 return; 191 } 192 193 terminated = true; 194 195 synchronized(listenerList) { 196 listenerList.clear(); 197 } 198 } 199 200 if (logger.traceOn()) { 201 logger.trace("terminate", "Terminated."); 202 } 203 } 204 205 209 private void checkState() throws IOException { 210 synchronized(terminationLock) { 211 if (terminated) { 212 throw new IOException ("The connection has been terminated."); 213 } 214 } 215 } 216 217 private Integer getListenerID() { 218 synchronized(listenerCounterLock) { 219 return new Integer (listenerCounter++); 220 } 221 } 222 223 227 private void checkMBeanPermission(final ObjectName name, 228 final String actions) 229 throws InstanceNotFoundException , SecurityException { 230 SecurityManager sm = System.getSecurityManager(); 231 if (sm != null) { 232 AccessControlContext acc = AccessController.getContext(); 233 ObjectInstance oi = null; 234 try { 235 oi = (ObjectInstance ) AccessController.doPrivileged( 236 new PrivilegedExceptionAction () { 237 public Object run() 238 throws InstanceNotFoundException { 239 return mbeanServer.getObjectInstance(name); 240 } 241 }); 242 } catch (PrivilegedActionException e) { 243 throw (InstanceNotFoundException ) extractException(e); 244 } 245 String classname = oi.getClassName(); 246 MBeanPermission perm = new MBeanPermission (classname, 247 null, 248 name, 249 actions); 250 sm.checkPermission(perm, acc); 251 } 252 } 253 254 258 private static Exception extractException(Exception e) { 259 while (e instanceof PrivilegedActionException ) { 260 e = ((PrivilegedActionException )e).getException(); 261 } 262 return e; 263 } 264 265 269 private MBeanServer mbeanServer; 270 271 private final long connectionTimeout; 272 273 private static int listenerCounter = 0; 274 private final static int[] listenerCounterLock = new int[0]; 275 276 private NotificationBuffer notifBuffer; 277 private Set listenerList = new HashSet (); 278 279 private boolean terminated = false; 280 private final int[] terminationLock = new int[0]; 281 282 static final String broadcasterClass = 283 NotificationBroadcaster .class.getName(); 284 285 private static final ClassLogger logger = 286 new ClassLogger("javax.management.remote.misc", "ServerNotifForwarder"); 287 } 288 | Popular Tags |