KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mx4j > monitor > MX4JMonitor


1 /*
2  * Copyright (C) The MX4J Contributors.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the MX4J License version 1.0.
6  * See the terms of the MX4J License in the documentation provided with this software.
7  */

8
9 package mx4j.monitor;
10
11 import java.util.ArrayList JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import java.util.Iterator JavaDoc;
14 import java.util.List JavaDoc;
15 import java.util.Map JavaDoc;
16
17 import javax.management.AttributeNotFoundException JavaDoc;
18 import javax.management.InstanceNotFoundException JavaDoc;
19 import javax.management.ListenerNotFoundException JavaDoc;
20 import javax.management.MBeanException JavaDoc;
21 import javax.management.MBeanRegistration JavaDoc;
22 import javax.management.MBeanServer JavaDoc;
23 import javax.management.NotCompliantMBeanException JavaDoc;
24 import javax.management.Notification JavaDoc;
25 import javax.management.NotificationBroadcasterSupport JavaDoc;
26 import javax.management.NotificationEmitter JavaDoc;
27 import javax.management.NotificationFilter JavaDoc;
28 import javax.management.NotificationListener JavaDoc;
29 import javax.management.ObjectName JavaDoc;
30 import javax.management.ReflectionException JavaDoc;
31 import javax.management.StandardMBean JavaDoc;
32 import javax.management.monitor.MonitorNotification JavaDoc;
33
34 import mx4j.log.Log;
35 import mx4j.log.Logger;
36 import mx4j.timer.TimeQueue;
37 import mx4j.timer.TimeTask;
38
39 /**
40  * The class that implements the Monitor behavior of the JMX specification.
41  * IMPLEMENTATION NOTE:
42  * There is one single thread that handles monitoring, for all monitor objects.
43  * There is one single task per each monitor object that runs.
44  * The queue will have possibly many tasks per each monitor type.
45  * Each monitor handles many MBeans, but only one attribute; however, both MBeans and attribute can be changed,
46  * though it would be a strange way to use the monitor.
47  *
48  * @version $Revision: 1.6 $
49  */

50 public abstract class MX4JMonitor extends StandardMBean JavaDoc implements MX4JMonitorMBean, MBeanRegistration JavaDoc, NotificationEmitter JavaDoc
51 {
52    private static final TimeQueue queue = new TimeQueue();
53    private static int references = 0;
54    private static int sequenceNumber;
55
56    private NotificationBroadcasterSupport JavaDoc emitter;
57    private MBeanServer JavaDoc server;
58    private boolean active;
59    private List JavaDoc observeds = new ArrayList JavaDoc();
60    private volatile String JavaDoc attribute;
61    private volatile long granularity = 10 * 1000; // Spec says default is 10 seconds
62
private boolean errorNotified;
63    private final TimeTask task = new MonitorTask();
64    private final Map JavaDoc infos = new HashMap JavaDoc();
65
66    protected MX4JMonitor(Class JavaDoc management) throws NotCompliantMBeanException JavaDoc
67    {
68       super(management);
69    }
70
71    // TODO: override descriptions for this MBean
72

73    public ObjectName JavaDoc preRegister(MBeanServer JavaDoc server, ObjectName JavaDoc name)
74    {
75       this.server = server;
76       return name;
77    }
78
79    public void postRegister(Boolean JavaDoc 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 JavaDoc createNotificationEmitter()
94    {
95       return new NotificationBroadcasterSupport JavaDoc();
96    }
97
98    public void addNotificationListener(NotificationListener JavaDoc listener, NotificationFilter JavaDoc filter, Object JavaDoc handback) throws IllegalArgumentException JavaDoc
99    {
100       emitter.addNotificationListener(listener, filter, handback);
101    }
102
103    public void removeNotificationListener(NotificationListener JavaDoc listener) throws ListenerNotFoundException JavaDoc
104    {
105       emitter.removeNotificationListener(listener);
106    }
107
108    public void removeNotificationListener(NotificationListener JavaDoc listener, NotificationFilter JavaDoc filter, Object JavaDoc handback) throws ListenerNotFoundException JavaDoc
109    {
110       emitter.removeNotificationListener(listener, filter, handback);
111    }
112
113    public void sendNotification(Notification JavaDoc notification)
114    {
115       emitter.sendNotification(notification);
116    }
117
118    public synchronized void start()
119    {
120       if (isActive()) return;
121       active = true;
122       for (Iterator JavaDoc 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 JavaDoc name) throws IllegalArgumentException JavaDoc
143    {
144       if (name == null) throw new IllegalArgumentException JavaDoc("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 JavaDoc name)
153    {
154       observeds.remove(name);
155       removeMonitorInfo(name);
156    }
157
158    public synchronized boolean containsObservedObject(ObjectName JavaDoc name)
159    {
160       return observeds.contains(name);
161    }
162
163    public synchronized ObjectName JavaDoc[] getObservedObjects()
164    {
165       return (ObjectName JavaDoc[])observeds.toArray(new ObjectName JavaDoc[observeds.size()]);
166    }
167
168    public synchronized void clearObservedObjects()
169    {
170       observeds.clear();
171    }
172
173    public synchronized String JavaDoc getObservedAttribute()
174    {
175       return attribute;
176    }
177
178    public synchronized void setObservedAttribute(String JavaDoc 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 JavaDoc
189    {
190       if (granularity <= 0) throw new IllegalArgumentException JavaDoc("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 JavaDoc type, String JavaDoc message, ObjectName JavaDoc name, String JavaDoc attribute, Object JavaDoc gauge, Object JavaDoc trigger)
222    {
223       int sequence = 0;
224       synchronized (MX4JMonitor.class)
225       {
226          sequence = ++sequenceNumber;
227       }
228
229       Notification JavaDoc notification = createMonitorNotification(type, sequence, message, name, attribute, gauge, trigger);
230       sendNotification(notification);
231    }
232
233    protected Notification JavaDoc createMonitorNotification(String JavaDoc type, long sequence, String JavaDoc message, ObjectName JavaDoc observed, String JavaDoc attribute, Object JavaDoc gauge, Object JavaDoc trigger)
234    {
235       return new MX4JMonitorNotification(type, this, sequence, System.currentTimeMillis(), message, observed, attribute, gauge, trigger);
236    }
237
238    protected abstract void monitor(ObjectName JavaDoc name, String JavaDoc attribute, Object JavaDoc value, MonitorInfo info);
239
240    protected abstract MonitorInfo createMonitorInfo();
241
242    protected synchronized MonitorInfo getMonitorInfo(ObjectName JavaDoc name)
243    {
244       return (MonitorInfo)infos.get(name);
245    }
246
247    protected synchronized void putMonitorInfo(ObjectName JavaDoc name, MonitorInfo info)
248    {
249       infos.put(name, info);
250    }
251
252    protected synchronized void removeMonitorInfo(ObjectName JavaDoc name)
253    {
254       infos.remove(name);
255    }
256
257    protected void sendErrorNotification(MonitorInfo info, String JavaDoc type, String JavaDoc message, ObjectName JavaDoc observed, String JavaDoc 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 JavaDoc 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 no attribute, sleep and try again
304
if (attribute != null)
305             {
306                ObjectName JavaDoc[] names = getObservedObjects();
307                // If no names, sleep and try again
308
for (int i = 0; i < names.length; i++)
309                {
310                   ObjectName JavaDoc name = names[i];
311                   MonitorInfo info = getMonitorInfo(name);
312                   if (info == null) continue;
313                   try
314                   {
315                      Object JavaDoc value = server.getAttribute(name, attribute);
316                      // If no value, sleep and try again
317
if (value != null)
318                      {
319                         monitor(name, attribute, value, info);
320                      }
321                   }
322                   catch (InstanceNotFoundException JavaDoc x)
323                   {
324                      sendErrorNotification(info, MonitorNotification.OBSERVED_OBJECT_ERROR, "Could not find observed MBean", name, attribute);
325                   }
326                   catch (AttributeNotFoundException JavaDoc x)
327                   {
328                      sendErrorNotification(info, MonitorNotification.OBSERVED_ATTRIBUTE_ERROR, "Could not find observed attribute " + attribute, name, attribute);
329                   }
330                   catch (MBeanException JavaDoc x)
331                   {
332                      sendErrorNotification(info, MonitorNotification.RUNTIME_ERROR, x.toString(), name, attribute);
333                   }
334                   catch (ReflectionException JavaDoc 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 JavaDoc toString()
364       {
365          return "errorNotified=" + isErrorNotified();
366       }
367
368       public void clearNotificationStatus()
369       {
370          errorNotified = false;
371       }
372    }
373 }
374
Popular Tags