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 javax.management.monitor;
023:
024: import java.util.HashSet;
025: import java.util.Iterator;
026: import java.util.Map;
027: import java.util.Set;
028:
029: import javax.management.MBeanRegistration;
030: import javax.management.MBeanServer;
031: import javax.management.NotificationBroadcasterSupport;
032: import javax.management.ObjectName;
033:
034: import org.jboss.mx.util.ObservedObject;
035:
036: import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
037:
038: /**
039: * The monitor service.
040: *
041: * <p><b>Revisions:</b>
042: * <p><b>20020319 Adrian Brock:</b>
043: * <ul>
044: * <li>Notify using the object name and fix the notification payloads
045: * </ul>
046: *
047: * @author <a href="mailto:Adrian.Brock@HappeningTimes.com">Adrian Brock</a>
048: * @version $Revision: 57200 $
049: */
050: public abstract class Monitor extends NotificationBroadcasterSupport
051: implements MonitorMBean, MBeanRegistration {
052: // Constants -----------------------------------------------------
053:
054: /**
055: * The amount by which arrays are incremented.
056: */
057: protected static final int capacityIncrement = 16;
058:
059: /**
060: * Used to reset errors in {@link #alreadyNotified}.
061: */
062: protected static final int RESET_FLAGS_ALREADY_NOTIFIED = 0;
063:
064: /**
065: * An observed attribute type error has been notified.
066: */
067: protected static final int RUNTIME_ERROR_NOTIFIED = 8;
068:
069: /**
070: * An observed object error has been notified.
071: */
072: protected static final int OBSERVED_OBJECT_ERROR_NOTIFIED = 1;
073:
074: /**
075: * An observed attribute error has been notified.
076: */
077: protected static final int OBSERVED_ATTRIBUTE_ERROR_NOTIFIED = 2;
078:
079: /**
080: * An observed attribute type error has been notified.
081: */
082: protected static final int OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED = 4;
083:
084: // Attributes ----------------------------------------------------
085:
086: /**
087: * The number of valid elements in the arrays.
088: */
089: protected int elementCount = 0;
090:
091: /**
092: * The granularity period.
093: */
094: long granularityPeriod = 10000;
095:
096: /**
097: * The observed attribute.
098: */
099: String observedAttribute = null;
100:
101: /**
102: * The observed objects.
103: */
104: ConcurrentHashMap observedObjects = new ConcurrentHashMap();
105:
106: /**
107: * Whether the service is active.
108: */
109: boolean active = false;
110:
111: /**
112: * The server this service is registered in.
113: */
114: protected MBeanServer server;
115:
116: /**
117: * The object name of this monitor.
118: */
119: ObjectName objectName;
120:
121: /**
122: * The errors that have already been notified.
123: * REVIEW: Check
124: * @deprecated use {@link #alreadyNotifieds}[0]
125: */
126: protected int alreadyNotified = 0;
127:
128: /**
129: * The errors that have already been notified.
130: */
131: protected int[] alreadyNotifieds = new int[0];
132:
133: /** @deprecated No replacement. */
134: protected String dbgTag = null;
135:
136: /**
137: * The notification sequence number.
138: */
139: private long sequenceNumber;
140:
141: // Static --------------------------------------------------------
142:
143: // Constructors --------------------------------------------------
144:
145: // Public --------------------------------------------------------
146:
147: // MonitorMBean implementation -----------------------------------
148:
149: public long getGranularityPeriod() {
150: return granularityPeriod;
151: }
152:
153: public String getObservedAttribute() {
154: return observedAttribute;
155: }
156:
157: public ObjectName getObservedObject() {
158: ObservedObject object = getFirstObservedObject();
159: if (object != null)
160: return object.getObjectName();
161: else
162: return null;
163: }
164:
165: public ObjectName[] getObservedObjects() {
166: Set set = new HashSet(observedObjects.values());
167: elementCount = set.size();
168: ObjectName[] result = new ObjectName[set.size()];
169: alreadyNotifieds = new int[set.size()];
170: int count = 0;
171: for (Iterator i = set.iterator(); i.hasNext();) {
172: ObservedObject object = (ObservedObject) i.next();
173: result[count] = object.getObjectName();
174: alreadyNotifieds[count++] = object.getAlreadyNotified();
175: }
176: return result;
177: }
178:
179: public synchronized boolean isActive() {
180: return active;
181: }
182:
183: public void setGranularityPeriod(long period)
184: throws IllegalArgumentException {
185: if (period <= 0)
186: throw new IllegalArgumentException(
187: "Period must be positive.");
188: granularityPeriod = period;
189: }
190:
191: public void setObservedAttribute(String attribute)
192: throws IllegalArgumentException {
193: observedAttribute = attribute;
194: }
195:
196: public void setObservedObject(ObjectName object)
197: throws IllegalArgumentException {
198: observedObjects.clear();
199: addObservedObject(object);
200: }
201:
202: public void addObservedObject(ObjectName object)
203: throws IllegalArgumentException {
204: if (object == null)
205: throw new IllegalArgumentException("null object name");
206: ObservedObject o = new ObservedObject(object);
207: initObservedObject(o);
208: observedObjects.put(object, o);
209: }
210:
211: public void removeObservedObject(ObjectName object) {
212: if (object == null)
213: throw new IllegalArgumentException("null object name");
214: observedObjects.remove(object);
215: }
216:
217: public boolean containsObservedObject(ObjectName object) {
218: if (object == null)
219: throw new IllegalArgumentException("null object name");
220: return observedObjects.containsKey(object);
221: }
222:
223: public abstract void start();
224:
225: public abstract void stop();
226:
227: public String toString() {
228: StringBuffer buffer = new StringBuffer(100);
229: buffer.append(getClass()).append(System.identityHashCode(this ))
230: .append(": {");
231: buffer.append(" objectName=").append(objectName);
232: return buffer.append("}").toString();
233: }
234:
235: // MBeanRegistrationImplementation overrides ---------------------
236:
237: public ObjectName preRegister(MBeanServer server,
238: ObjectName objectName) throws Exception {
239: // Remember the server.
240: this .server = server;
241:
242: // Remember the object name.
243: this .objectName = objectName;
244:
245: // Use the passed object name.
246: return objectName;
247: }
248:
249: public void postRegister(Boolean registrationDone) {
250: }
251:
252: public void preDeregister() throws Exception {
253: // Stop the monitor before deregistration.
254: stop();
255: }
256:
257: public void postDeregister() {
258: }
259:
260: // Package protected ---------------------------------------------
261:
262: /**
263: * Get an observed object
264: */
265: ObservedObject retrieveObservedObject(ObjectName name) {
266: return (ObservedObject) observedObjects.get(name);
267: }
268:
269: /**
270: * retrieve the observed objects
271: */
272: Map retrieveObservedObjects() {
273: return observedObjects;
274: }
275:
276: /**
277: * retrieve the first observed objects
278: */
279: ObservedObject getFirstObservedObject() {
280: Iterator i = observedObjects.values().iterator();
281: if (i.hasNext())
282: return (ObservedObject) i.next();
283: else
284: return null;
285: }
286:
287: void initObservedObject(ObservedObject object) {
288: object.resetAlreadyNotified();
289: object.setDerivedGaugeTimeStamp(System.currentTimeMillis());
290: }
291:
292: /**
293: * Sends the notification
294: *
295: * @param object the observedObject.
296: * @param type the notification type.
297: * @param timestamp the time of the notification.
298: * @param message the human readable message to send.
299: * @param attribute the attribute name.
300: * @param gauge the derived gauge.
301: * @param trigger the trigger value.
302: */
303: void sendNotification(ObservedObject object, String type,
304: long timestamp, String message, String attribute,
305: Object gauge, Object trigger) {
306: long seq = nextSeqNo();
307: if (timestamp == 0)
308: timestamp = System.currentTimeMillis();
309: sendNotification(new MonitorNotification(type, objectName, seq,
310: timestamp, message, gauge, attribute, object
311: .getObjectName(), trigger));
312: }
313:
314: /**
315: * Send a runtime error notification.
316: *
317: * @param object the observedObject.
318: * @param message the human readable message to send.
319: */
320: void sendRuntimeErrorNotification(ObservedObject object,
321: String message) {
322: if (object.notAlreadyNotified(RUNTIME_ERROR_NOTIFIED))
323: sendNotification(object, MonitorNotification.RUNTIME_ERROR,
324: 0, message, observedAttribute, null, null);
325: }
326:
327: /**
328: * Send an object error notification.
329: *
330: * @param object the observedObject.
331: * @param message the human readable message to send.
332: */
333: void sendObjectErrorNotification(ObservedObject object,
334: String message) {
335: if (object.notAlreadyNotified(OBSERVED_OBJECT_ERROR_NOTIFIED))
336: sendNotification(object,
337: MonitorNotification.OBSERVED_OBJECT_ERROR, 0,
338: message, observedAttribute, null, null);
339: }
340:
341: /**
342: * Send an attribute error notification.
343: *
344: * @param object the observedObject.
345: * @param message the human readable message to send.
346: */
347: void sendAttributeErrorNotification(ObservedObject object,
348: String message) {
349: if (object
350: .notAlreadyNotified(OBSERVED_ATTRIBUTE_ERROR_NOTIFIED))
351: sendNotification(object,
352: MonitorNotification.OBSERVED_ATTRIBUTE_ERROR, 0,
353: message, observedAttribute, null, null);
354: }
355:
356: /**
357: * Send an attribute type error notification.
358: *
359: * @param object the observedObject.
360: * @param message the human readable message to send.
361: */
362: void sendAttributeTypeErrorNotification(ObservedObject object,
363: String message) {
364: if (object
365: .notAlreadyNotified(OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED))
366: sendNotification(object,
367: MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR,
368: 0, message, observedAttribute, null, null);
369: }
370:
371: /**
372: * Reset the already notifieds
373: */
374: void resetAlreadyNotified() {
375: for (Iterator i = observedObjects.values().iterator(); i
376: .hasNext();)
377: ((ObservedObject) i.next()).resetAlreadyNotified();
378: }
379:
380: synchronized long nextSeqNo() {
381: long nextSeqNo = sequenceNumber++;
382: return nextSeqNo;
383: }
384:
385: // Protected -----------------------------------------------------
386:
387: // Private -------------------------------------------------------
388:
389: // Inner classes -------------------------------------------------
390:
391: }
|