1 8 9 package mx4j.monitor; 10 11 import java.util.ArrayList ; 12 import java.util.HashMap ; 13 import java.util.Iterator ; 14 import java.util.List ; 15 import java.util.Map ; 16 17 import javax.management.AttributeNotFoundException ; 18 import javax.management.InstanceNotFoundException ; 19 import javax.management.ListenerNotFoundException ; 20 import javax.management.MBeanException ; 21 import javax.management.MBeanRegistration ; 22 import javax.management.MBeanServer ; 23 import javax.management.NotCompliantMBeanException ; 24 import javax.management.Notification ; 25 import javax.management.NotificationBroadcasterSupport ; 26 import javax.management.NotificationEmitter ; 27 import javax.management.NotificationFilter ; 28 import javax.management.NotificationListener ; 29 import javax.management.ObjectName ; 30 import javax.management.ReflectionException ; 31 import javax.management.StandardMBean ; 32 import javax.management.monitor.MonitorNotification ; 33 34 import mx4j.log.Log; 35 import mx4j.log.Logger; 36 import mx4j.timer.TimeQueue; 37 import mx4j.timer.TimeTask; 38 39 50 public abstract class MX4JMonitor extends StandardMBean implements MX4JMonitorMBean, MBeanRegistration , NotificationEmitter 51 { 52 private static final TimeQueue queue = new TimeQueue(); 53 private static int references = 0; 54 private static int sequenceNumber; 55 56 private NotificationBroadcasterSupport emitter; 57 private MBeanServer server; 58 private boolean active; 59 private List observeds = new ArrayList (); 60 private volatile String attribute; 61 private volatile long granularity = 10 * 1000; private boolean errorNotified; 63 private final TimeTask task = new MonitorTask(); 64 private final Map infos = new HashMap (); 65 66 protected MX4JMonitor(Class management) throws NotCompliantMBeanException 67 { 68 super(management); 69 } 70 71 73 public ObjectName preRegister(MBeanServer server, ObjectName name) 74 { 75 this.server = server; 76 return name; 77 } 78 79 public void postRegister(Boolean registrationDone) 80 { 81 } 82 83 public void preDeregister() 84 { 85 stop(); 86 } 87 88 public void postDeregister() 89 { 90 server = null; 91 } 92 93 protected NotificationBroadcasterSupport createNotificationEmitter() 94 { 95 return new NotificationBroadcasterSupport (); 96 } 97 98 public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException 99 { 100 emitter.addNotificationListener(listener, filter, handback); 101 } 102 103 public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException 104 { 105 emitter.removeNotificationListener(listener); 106 } 107 108 public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException 109 { 110 emitter.removeNotificationListener(listener, filter, handback); 111 } 112 113 public void sendNotification(Notification notification) 114 { 115 emitter.sendNotification(notification); 116 } 117 118 public synchronized void start() 119 { 120 if (isActive()) return; 121 active = true; 122 for (Iterator i = infos.values().iterator(); i.hasNext();) 123 { 124 MonitorInfo info = (MonitorInfo)i.next(); 125 info.clearNotificationStatus(); 126 } 127 startMonitor(); 128 } 129 130 public synchronized void stop() 131 { 132 if (!isActive()) return; 133 active = false; 134 stopMonitor(); 135 } 136 137 public synchronized boolean isActive() 138 { 139 return active; 140 } 141 142 public synchronized void addObservedObject(ObjectName name) throws IllegalArgumentException 143 { 144 if (name == null) throw new IllegalArgumentException ("Observed ObjectName cannot be null"); 145 if (!containsObservedObject(name)) 146 { 147 observeds.add(name); 148 putMonitorInfo(name, createMonitorInfo()); 149 } 150 } 151 152 public synchronized void removeObservedObject(ObjectName name) 153 { 154 observeds.remove(name); 155 removeMonitorInfo(name); 156 } 157 158 public synchronized boolean containsObservedObject(ObjectName name) 159 { 160 return observeds.contains(name); 161 } 162 163 public synchronized ObjectName [] getObservedObjects() 164 { 165 return (ObjectName [])observeds.toArray(new ObjectName [observeds.size()]); 166 } 167 168 public synchronized void clearObservedObjects() 169 { 170 observeds.clear(); 171 } 172 173 public synchronized String getObservedAttribute() 174 { 175 return attribute; 176 } 177 178 public synchronized void setObservedAttribute(String attribute) 179 { 180 this.attribute = attribute; 181 } 182 183 public synchronized long getGranularityPeriod() 184 { 185 return granularity; 186 } 187 188 public synchronized void setGranularityPeriod(long granularity) throws IllegalArgumentException 189 { 190 if (granularity <= 0) throw new IllegalArgumentException ("Granularity must be greater than zero"); 191 this.granularity = granularity; 192 } 193 194 protected void startMonitor() 195 { 196 synchronized (queue) 197 { 198 if (references == 0) queue.start(); 199 ++references; 200 } 201 202 if (emitter == null) this.emitter = createNotificationEmitter(); 203 queue.schedule(task); 204 } 205 206 protected void stopMonitor() 207 { 208 queue.unschedule(task); 209 210 synchronized (queue) 211 { 212 if (--references == 0) queue.stop(); 213 } 214 } 215 216 protected Logger getLogger() 217 { 218 return Log.getLogger(getClass().getName()); 219 } 220 221 protected void sendNotification(String type, String message, ObjectName name, String attribute, Object gauge, Object trigger) 222 { 223 int sequence = 0; 224 synchronized (MX4JMonitor.class) 225 { 226 sequence = ++sequenceNumber; 227 } 228 229 Notification notification = createMonitorNotification(type, sequence, message, name, attribute, gauge, trigger); 230 sendNotification(notification); 231 } 232 233 protected Notification createMonitorNotification(String type, long sequence, String message, ObjectName observed, String attribute, Object gauge, Object trigger) 234 { 235 return new MX4JMonitorNotification(type, this, sequence, System.currentTimeMillis(), message, observed, attribute, gauge, trigger); 236 } 237 238 protected abstract void monitor(ObjectName name, String attribute, Object value, MonitorInfo info); 239 240 protected abstract MonitorInfo createMonitorInfo(); 241 242 protected synchronized MonitorInfo getMonitorInfo(ObjectName name) 243 { 244 return (MonitorInfo)infos.get(name); 245 } 246 247 protected synchronized void putMonitorInfo(ObjectName name, MonitorInfo info) 248 { 249 infos.put(name, info); 250 } 251 252 protected synchronized void removeMonitorInfo(ObjectName name) 253 { 254 infos.remove(name); 255 } 256 257 protected void sendErrorNotification(MonitorInfo info, String type, String message, ObjectName observed, String attribute) 258 { 259 if (!info.isErrorNotified()) 260 { 261 info.setErrorNotified(true); 262 sendNotification(type, message, observed, attribute, null, null); 263 } 264 } 265 266 private class MonitorTask extends TimeTask 267 { 268 protected boolean isPeriodic() 269 { 270 return true; 271 } 272 273 protected long getPeriod() 274 { 275 return getGranularityPeriod(); 276 } 277 278 public boolean getFixedRate() 279 { 280 return true; 281 } 282 283 public void run() 284 { 285 if (!isActive()) return; 286 287 long start = System.currentTimeMillis(); 288 289 String attribute = getObservedAttribute(); 290 291 if (server == null) 292 { 293 if (!errorNotified) 294 { 295 errorNotified = true; 296 sendNotification(MonitorNotification.RUNTIME_ERROR, "Monitors must be registered in the MBeanServer", null, attribute, null, null); 297 } 298 } 299 else 300 { 301 errorNotified = false; 302 303 if (attribute != null) 305 { 306 ObjectName [] names = getObservedObjects(); 307 for (int i = 0; i < names.length; i++) 309 { 310 ObjectName name = names[i]; 311 MonitorInfo info = getMonitorInfo(name); 312 if (info == null) continue; 313 try 314 { 315 Object value = server.getAttribute(name, attribute); 316 if (value != null) 318 { 319 monitor(name, attribute, value, info); 320 } 321 } 322 catch (InstanceNotFoundException x) 323 { 324 sendErrorNotification(info, MonitorNotification.OBSERVED_OBJECT_ERROR, "Could not find observed MBean", name, attribute); 325 } 326 catch (AttributeNotFoundException x) 327 { 328 sendErrorNotification(info, MonitorNotification.OBSERVED_ATTRIBUTE_ERROR, "Could not find observed attribute " + attribute, name, attribute); 329 } 330 catch (MBeanException x) 331 { 332 sendErrorNotification(info, MonitorNotification.RUNTIME_ERROR, x.toString(), name, attribute); 333 } 334 catch (ReflectionException x) 335 { 336 sendErrorNotification(info, MonitorNotification.RUNTIME_ERROR, x.toString(), name, attribute); 337 } 338 } 339 } 340 } 341 342 long end = System.currentTimeMillis(); 343 long elapsed = end - start; 344 Logger logger = getLogger(); 345 if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Monitored attribute " + attribute + " in " + elapsed + " ms"); 346 } 347 } 348 349 protected class MonitorInfo 350 { 351 private boolean errorNotified; 352 353 public boolean isErrorNotified() 354 { 355 return errorNotified; 356 } 357 358 public void setErrorNotified(boolean errorNotified) 359 { 360 this.errorNotified = errorNotified; 361 } 362 363 public String toString() 364 { 365 return "errorNotified=" + isErrorNotified(); 366 } 367 368 public void clearNotificationStatus() 369 { 370 errorNotified = false; 371 } 372 } 373 } 374 | Popular Tags |