001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.monitor.alarm;
023:
024: import java.util.HashMap;
025: import java.util.Iterator;
026: import java.util.Map;
027:
028: import javax.management.AttributeChangeNotification;
029: import javax.management.Notification;
030: import javax.management.ObjectName;
031:
032: import org.jboss.system.ServiceMBeanSupport;
033:
034: /**
035: * AlarmManager
036: *
037: * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
038: * @version $Revision: 57210 $
039: */
040: public class AlarmManager {
041: // Private/Protected Data ----------------------------------------
042:
043: /** Mediates the related MBean */
044: protected MBeanImplAccess mbeanImpl;
045:
046: /** Holds map of maps, each one containing type --> severity mappings */
047: private Map nameMap;
048:
049: // Constructors --------------------------------------------------
050:
051: /**
052: * CTOR
053: *
054: * @param mbeanImpl providing access to notification broadcasting
055: */
056: public AlarmManager(MBeanImplAccess mbeanImpl) {
057: this .mbeanImpl = mbeanImpl;
058: this .nameMap = new HashMap();
059: }
060:
061: /**
062: * CTOR
063: *
064: * @param service hosting the AlarmManager
065: */
066: public AlarmManager(final ServiceMBeanSupport service) {
067: this (new MBeanImplAccess() {
068: public ObjectName getMBeanName() {
069: return service.getServiceName();
070: }
071:
072: public long getSequenceNumber() {
073: return service.nextNotificationSequenceNumber();
074: }
075:
076: public void emitNotification(Notification n) {
077: service.sendNotification(n);
078: }
079: });
080: }
081:
082: // High-level part of the interface used to support Statefull Alarms.
083: // The sending of the actual AlarmNotifications is done through the
084: // sendAlarmNotification() method.
085:
086: /**
087: * Sets the severity of an Alarm, keyed by its type, without producing
088: * an AlarmNotification, for the current mbean.
089: */
090: public void setSeverity(String type, int severity) {
091: setSeverity(mbeanImpl.getMBeanName(), type, severity);
092: }
093:
094: /**
095: * Sets the severity of an Alarm, keyed by its type, without producing
096: * an AlarmNotification, for the specified mbean.
097: */
098: public void setSeverity(ObjectName name, String type, int severity) {
099: synchronized (this ) {
100: // find or add TypeMap
101: Map typeMap = getTypeMap(name);
102:
103: Severity s = (Severity) typeMap.get(type);
104: if (s == null) {
105: typeMap.put(type, new Severity(severity));
106: } else {
107: s.severity = severity;
108: }
109: }
110: }
111:
112: /**
113: * Gets the severity of an alarm, keyed by its type, for the current mbean.
114: */
115: public int getSeverity(String type) {
116: return getSeverity(mbeanImpl.getMBeanName(), type);
117: }
118:
119: /**
120: * Gets the severity of an alarm, keyed by its type, for the specified mbean.
121: */
122: public int getSeverity(ObjectName name, String type) {
123: synchronized (this ) {
124: Map typeMap = (Map) nameMap.get(name);
125: if (typeMap == null) {
126: return Alarm.SEVERITY_NORMAL;
127: } else {
128: Severity s = (Severity) typeMap.get(type);
129: if (s == null) {
130: return Alarm.SEVERITY_NORMAL;
131: } else {
132: return s.severity;
133: }
134: }
135: }
136: }
137:
138: /**
139: * Gets the severity of an alarm as a String,
140: * keyed by its type for the current mbean
141: */
142: public String getSeverityAsString(String type) {
143: return getSeverityAsString(mbeanImpl.getMBeanName(), type);
144: }
145:
146: /**
147: * Gets the severity of an alarm as a String,
148: * keyed by its type for the specified mbean
149: */
150: public String getSeverityAsString(ObjectName name, String type) {
151: return Alarm.SEVERITY_STRINGS[getSeverity(name, type)];
152: }
153:
154: /**
155: * Sets the alarm for the current mbean, keyed by its type.
156: * If severity has changed an AlarmNotification will be thrown.
157: * The alarmState of the AlarmNotification will be either
158: * Alarm.STATE_CREATED, Alarm.STATE_CHANGED or Alarm.STATE_CLEARED.
159: */
160: public void setAlarm(String type, int severity, String message,
161: Object userData) {
162: setAlarm(mbeanImpl.getMBeanName(), type, severity, message,
163: userData);
164: }
165:
166: /**
167: * Sets the alarm for the specified target mbean, keyed by its type.
168: * If severity has changed an AlarmNotification will be thrown.
169: * The alarmState of the AlarmNotification will be either
170: * Alarm.STATE_CREATED, Alarm.STATE_CHANGED or Alarm.STATE_CLEARED.
171: */
172: public void setAlarm(ObjectName target, String type, int severity,
173: String message, Object userData) {
174: Severity s;
175: synchronized (this ) {
176: Map typeMap = getTypeMap(target);
177: s = (Severity) typeMap.get(type);
178:
179: // if alarm does not exist, add it with a default severity
180: if (s == null) {
181: s = new Severity(Alarm.SEVERITY_NORMAL);
182: typeMap.put(type, s);
183: }
184: }
185:
186: // There must be a small race condition here if 2 threads
187: // set the same severity, thus producing duplicate notifications
188: // Not a big deal...
189: int oldSeverity = s.severity;
190:
191: // if the severity has changed, send an AlarmNotification
192: if (severity != oldSeverity) {
193: // store the new severity
194: s.severity = severity;
195:
196: if (severity == Alarm.SEVERITY_NORMAL) {
197: sendAlarmNotification(target, type, severity,
198: Alarm.STATE_CLEARED, message, userData);
199: } else if (oldSeverity == Alarm.SEVERITY_NORMAL) {
200: sendAlarmNotification(target, type, severity,
201: Alarm.STATE_CREATED, message, userData);
202: } else {
203: sendAlarmNotification(target, type, severity,
204: Alarm.STATE_CHANGED, message, userData);
205: }
206: }
207: }
208:
209: /**
210: * See set Alarm above
211: *
212: * Essentially a helper method that will populate the userData field
213: * of the Notification with a HashMap, containing a single key/value pair.
214: *
215: * Note, that an AlarmNotification will not be emitted if there is no
216: * severity change.
217: */
218: public void setAlarm(String type, int severity, String message,
219: String key, Object value) {
220: setAlarm(mbeanImpl.getMBeanName(), type, severity, message,
221: key, value);
222: }
223:
224: /**
225: * See set Alarm above
226: *
227: * Essentially a helper method that will populate the userData field
228: * of the Notification with a HashMap, containing a single key/value pair.
229: *
230: * Note, that an AlarmNotification will not be thrown if there is no
231: * severity change.
232: */
233: public void setAlarm(ObjectName target, String type, int severity,
234: String message, String key, Object value) {
235: HashMap map = new HashMap();
236: map.put(key, value);
237: setAlarm(target, type, severity, message, map);
238: }
239:
240: // Low-level part of the interface used to generate and send
241: // various types of notifications, including AlarmNotifications
242: // corresponding to Stateless Alarms.
243:
244: /**
245: * Generates and sends an AlarmNotification.
246: *
247: * source, sequenceNumber, timeStamp
248: * will be automatically filled.
249: */
250: public void sendAlarm(String type, int severity, String message,
251: String key, Object value) {
252: sendAlarm(null, type, severity, message, key, value);
253: }
254:
255: /**
256: * Generates and sends an AlarmNotification.
257: *
258: * source, sequenceNumber, timeStamp
259: * will be automatically filled.
260: */
261: public void sendAlarm(ObjectName target, String type, int severity,
262: String message, String key, Object value) {
263: HashMap map = new HashMap();
264: map.put(key, value);
265: sendAlarm(target, type, severity, message, map);
266: }
267:
268: /**
269: * Generates and sends an AlarmNotification.
270: *
271: * source, sequenceNumber, timeStamp
272: * will be automatically filled.
273: */
274: public void sendAlarm(String type, int severity, String message,
275: Object userData) {
276: sendAlarm(null, type, severity, message, userData);
277: }
278:
279: /**
280: * Generates and sends an AlarmNotification.
281: *
282: * source, sequenceNumber, timeStamp
283: * will be automatically filled.
284: */
285: public void sendAlarm(ObjectName target, String type, int severity,
286: String message, Object userData) {
287: sendAlarmNotification(target, type, severity, Alarm.STATE_NONE,
288: message, userData);
289: }
290:
291: /**
292: * Generates and sends an AlarmNotification.
293: *
294: * An alarmState of Alarm.STATE_CLEARED forces severity to SEVERITY_NORMAL
295: *
296: * source, sequenceNumber, timeStamp
297: * will be automatically filled.
298: */
299: protected void sendAlarmNotification(ObjectName target,
300: String type, int severity, int alarmState, String message,
301: Object userData) {
302: Notification n = new AlarmNotification(type, mbeanImpl
303: .getMBeanName(), // source
304: target, severity, alarmState, this .mbeanImpl
305: .getSequenceNumber(), System
306: .currentTimeMillis(), message);
307: n.setUserData(userData);
308:
309: // send it away
310: mbeanImpl.emitNotification(n);
311: }
312:
313: /**
314: * Generates and sends an AttributeChangeNotification.
315: *
316: * source, sequenceNumber, timeStamp
317: * will be automatically filled in.
318: */
319: public void sendAttributeChangeNotification(String type,
320: String message, Object userData, String attributeName,
321: String attributeType, Object oldValue, Object newValue) {
322: Notification n = new AttributeChangeNotification(
323: mbeanImpl.getMBeanName(), // source
324: mbeanImpl.getSequenceNumber(), System
325: .currentTimeMillis(), message, attributeName,
326: attributeType, oldValue, newValue);
327: n.setUserData(userData);
328:
329: // send it away
330: mbeanImpl.emitNotification(n);
331: }
332:
333: /**
334: * Generates and sends a simple Notification.
335: *
336: * source, sequenceNumber, timeStamp
337: * will be automatically filled in.
338: */
339: public void sendNotification(String type, String message,
340: Object userData) {
341: Notification n = new Notification(type, mbeanImpl
342: .getMBeanName(), // source
343: mbeanImpl.getSequenceNumber(), System
344: .currentTimeMillis(), message);
345: n.setUserData(userData);
346:
347: // send it away
348: mbeanImpl.emitNotification(n);
349: }
350:
351: /**
352: * Clear all the stored severities
353: *
354: */
355: public void clear() {
356: synchronized (this ) {
357: for (Iterator i = nameMap.entrySet().iterator(); i
358: .hasNext();) {
359: Map.Entry entry = (Map.Entry) i.next();
360: Map typeMap = (Map) entry.getValue();
361: typeMap.clear();
362: }
363: nameMap.clear();
364: }
365: }
366:
367: // Private -------------------------------------------------------
368:
369: /**
370: * Return the typeMap for an ObjectName, create it if needed
371: */
372: private Map getTypeMap(ObjectName name) {
373: Map typeMap = (Map) nameMap.get(name);
374: if (typeMap == null) {
375: typeMap = new HashMap();
376: nameMap.put(name, typeMap);
377: }
378: return typeMap;
379: }
380:
381: // Inner Class ---------------------------------------------------
382:
383: /**
384: * Simple Data Holder
385: */
386: private static class Severity {
387: public int severity;
388:
389: public Severity(int severity) {
390: this.severity = severity;
391: }
392: }
393:
394: }
|