001: /* JFox, the OpenSource J2EE Application Server
002: *
003: * Copyright (C) 2002 huihoo.org
004: * Distributable under GNU LGPL license
005: * See the GNU Lesser General Public License for more details.
006: */
007:
008: package example.jmx.dynamic;
009:
010: import java.lang.reflect.Constructor;
011: import java.util.Iterator;
012:
013: import javax.management.MBeanInfo;
014: import javax.management.MBeanOperationInfo;
015: import javax.management.MBeanConstructorInfo;
016: import javax.management.MBeanAttributeInfo;
017: import javax.management.MBeanNotificationInfo;
018: import javax.management.MBeanParameterInfo;
019: import javax.management.Attribute;
020: import javax.management.AttributeList;
021: import javax.management.RuntimeOperationsException;
022: import javax.management.InvalidAttributeValueException;
023: import javax.management.ReflectionException;
024: import javax.management.MBeanException;
025: import javax.management.AttributeNotFoundException;
026: import javax.management.DynamicMBean;
027:
028: /**
029: *
030: * @author <a href="mailto:young_yy@hotmail.org">Young Yang</a>
031: */
032:
033: public class SimpleDynamic implements DynamicMBean {
034: /*
035: * -----------------------------------------------------
036: * PRIVATE VARIABLES
037: * -----------------------------------------------------
038: */
039:
040: private String state = "initial state";
041: private int nbChanges = 0;
042: private int nbResets = 0;
043:
044: private String dClassName = this .getClass().getName();
045: private String dDescription = "Simple implementation of a dynamic MBean.";
046:
047: private MBeanAttributeInfo[] dAttributes = new MBeanAttributeInfo[2];
048: private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1];
049: private MBeanOperationInfo[] dOperations = new MBeanOperationInfo[1];
050: private MBeanInfo dMBeanInfo = null;
051:
052: /*
053: * -----------------------------------------------------
054: * CONSTRUCTORS
055: * -----------------------------------------------------
056: */
057:
058: public SimpleDynamic() {
059:
060: // build the management information to be exposed by the dynamic MBean
061: //
062: buildDynamicMBeanInfo();
063: }
064:
065: /*
066: * -----------------------------------------------------
067: * IMPLEMENTATION OF THE DynamicMBean INTERFACE
068: * -----------------------------------------------------
069: */
070:
071: /**
072: * Allows the value of the specified attribute of the Dynamic MBean to be obtained.
073: */
074: public Object getAttribute(String attribute_name)
075: throws AttributeNotFoundException, MBeanException,
076: ReflectionException {
077:
078: // Check attribute_name is not null to avoid NullPointerException later on
079: if (attribute_name == null) {
080: throw new RuntimeOperationsException(
081: new IllegalArgumentException(
082: "Attribute name cannot be null"),
083: "Cannot reflectInvoke a getter of " + dClassName
084: + " with null attribute name");
085: }
086: // Check for a recognized attribute_name and call the corresponding getter
087: if (attribute_name.equals("State")) {
088: return getState();
089: }
090: if (attribute_name.equals("NbChanges")) {
091: return getNbChanges();
092: }
093: // If attribute_name has not been recognized throw an AttributeNotFoundException
094: throw (new AttributeNotFoundException("Cannot find "
095: + attribute_name + " attribute in " + dClassName));
096: }
097:
098: /**
099: * Sets the value of the specified attribute of the Dynamic MBean.
100: */
101: public void setAttribute(Attribute attribute)
102: throws AttributeNotFoundException,
103: InvalidAttributeValueException, MBeanException,
104: ReflectionException {
105:
106: // Check attribute is not null to avoid NullPointerException later on
107: if (attribute == null) {
108: throw new RuntimeOperationsException(
109: new IllegalArgumentException(
110: "Attribute cannot be null"),
111: "Cannot reflectInvoke a setter of " + dClassName
112: + " with null attribute");
113: }
114: String name = attribute.getName();
115: Object value = attribute.getValue();
116:
117: if (name == null) {
118: throw new RuntimeOperationsException(
119: new IllegalArgumentException(
120: "Attribute name cannot be null"),
121: "Cannot reflectInvoke the setter of " + dClassName
122: + " with null attribute name");
123: }
124: // Check for a recognized attribute name and call the corresponding setter
125: //
126: if (name.equals("State")) {
127: // if null value, try and see if the setter returns any exception
128: if (value == null) {
129: try {
130: setState(null);
131: } catch (Exception e) {
132: throw (new InvalidAttributeValueException(
133: "Cannot set attribute " + name + " to null"));
134: }
135: }
136: // if non null value, make sure it is assignable to the attribute
137: else {
138: try {
139: if ((Class.forName("java.lang.String"))
140: .isAssignableFrom(value.getClass())) {
141: setState((String) value);
142: } else {
143: throw (new InvalidAttributeValueException(
144: "Cannot set attribute " + name
145: + " to a "
146: + value.getClass().getName()
147: + " object, String expected"));
148: }
149: } catch (ClassNotFoundException e) {
150: e.printStackTrace();
151: }
152: }
153: }
154: // recognize an attempt to set "NbChanges" attribute (read-only):
155: else if (name.equals("NbChanges")) {
156: throw (new AttributeNotFoundException(
157: "Cannot set attribute " + name
158: + " because it is read-only"));
159: }
160: // unrecognized attribute name:
161: else {
162: throw (new AttributeNotFoundException("Attribute " + name
163: + " not found in " + this .getClass().getName()));
164: }
165: }
166:
167: /**
168: * Enables the to get the values of several attributes of the Dynamic MBean.
169: */
170: public AttributeList getAttributes(String[] attributeNames) {
171:
172: // Check attributeNames is not null to avoid NullPointerException later on
173: if (attributeNames == null) {
174: throw new RuntimeOperationsException(
175: new IllegalArgumentException(
176: "attributeNames[] cannot be null"),
177: "Cannot reflectInvoke a getter of " + dClassName);
178: }
179: AttributeList resultList = new AttributeList();
180:
181: // if attributeNames is empty, return an empty result list
182: if (attributeNames.length == 0)
183: return resultList;
184:
185: // build the result attribute list
186: for (int i = 0; i < attributeNames.length; i++) {
187: try {
188: Object value = getAttribute(attributeNames[i]);
189: resultList.add(new Attribute(attributeNames[i], value));
190: } catch (Exception e) {
191: e.printStackTrace();
192: }
193: }
194: return (resultList);
195: }
196:
197: /**
198: * Sets the values of several attributes of the Dynamic MBean, and returns the
199: * list of attributes that have been set.
200: */
201: public AttributeList setAttributes(AttributeList attributes) {
202:
203: // Check attributes is not null to avoid NullPointerException later on
204: if (attributes == null) {
205: throw new RuntimeOperationsException(
206: new IllegalArgumentException(
207: "AttributeList attributes cannot be null"),
208: "Cannot reflectInvoke a setter of " + dClassName);
209: }
210: AttributeList resultList = new AttributeList();
211:
212: // if attributeNames is empty, nothing more to do
213: if (attributes.isEmpty())
214: return resultList;
215:
216: // for each attribute, try to set it and add to the result list if successfull
217: for (Iterator i = attributes.iterator(); i.hasNext();) {
218: Attribute attr = (Attribute) i.next();
219: try {
220: setAttribute(attr);
221: String name = attr.getName();
222: Object value = getAttribute(name);
223: resultList.add(new Attribute(name, value));
224: } catch (Exception e) {
225: e.printStackTrace();
226: }
227: }
228: return (resultList);
229: }
230:
231: /**
232: * Allows an operation to be invoked on the Dynamic MBean.
233: */
234: public Object invoke(String operationName, Object params[],
235: String signature[]) throws MBeanException,
236: ReflectionException {
237:
238: // Check operationName is not null to avoid NullPointerException later on
239: if (operationName == null) {
240: throw new RuntimeOperationsException(
241: new IllegalArgumentException(
242: "Operation name cannot be null"),
243: "Cannot reflectInvoke a null operation in "
244: + dClassName);
245: }
246: // Check for a recognized operation name and call the corresponding operation
247: if (operationName.equals("reset")) {
248: reset();
249: return null;
250: } else {
251: // unrecognized operation name:
252: throw new ReflectionException(new NoSuchMethodException(
253: operationName), "Cannot find the operation "
254: + operationName + " in " + dClassName);
255: }
256: }
257:
258: /**
259: * This method provides the exposed attributes and operations of the Dynamic MBean.
260: * It provides this information using an MBeanInfo object.
261: */
262: public MBeanInfo getMBeanInfo() {
263:
264: // return the information we want to expose for management:
265: // the dMBeanInfo private field has been built at instanciation time,
266: return (dMBeanInfo);
267: }
268:
269: /*
270: * -----------------------------------------------------
271: * OTHER PUBLIC METHODS
272: * -----------------------------------------------------
273: */
274:
275: /**
276: * Getter: get the "State" attribute of the "SimpleDynamic" dynamic MBean.
277: */
278: public String getState() {
279: return state;
280: }
281:
282: /**
283: * Setter: set the "State" attribute of the "SimpleDynamic" dynamic MBean.
284: */
285: public void setState(String s) {
286: state = s;
287: System.out.println("[" + this .toString()
288: + "] state field have changed to: " + s);
289: nbChanges++;
290: }
291:
292: /**
293: * Getter: get the "NbChanges" attribute of the "SimpleDynamic" dynamic MBean.
294: */
295: public Integer getNbChanges() {
296: return new Integer(nbChanges);
297: }
298:
299: /**
300: * Operation: reset to their initial values the "State" and "NbChanges"
301: * attributes of the "SimpleDynamic" dynamic MBean.
302: */
303: public void reset() {
304: state = "initial state";
305: nbChanges = 0;
306: nbResets++;
307: }
308:
309: /**
310: * Return the "NbResets" property.
311: * This method is not a Getter in the JMX sense because
312: * it is not returned by the getMBeanInfo() method.
313: */
314: public Integer getNbResets() {
315: return new Integer(nbResets);
316: }
317:
318: /*
319: * -----------------------------------------------------
320: * PRIVATE METHODS
321: * -----------------------------------------------------
322: */
323:
324: /**
325: * Build the private dMBeanInfo field,
326: * which represents the management interface exposed by the MBean;
327: * that is, the set of attributes, constructors, operations and notifications
328: * which are available for management.
329: *
330: * A reference to the dMBeanInfo object is returned by the getMBeanInfo() method
331: * of the DynamicMBean interface. Note that, once constructed, an MBeanInfo object is immutable.
332: */
333: private void buildDynamicMBeanInfo() {
334:
335: dAttributes[0] = new MBeanAttributeInfo("State",
336: "java.lang.String", "State: state string.", true, true,
337: false);
338: dAttributes[1] = new MBeanAttributeInfo(
339: "NbChanges",
340: "java.lang.Integer",
341: "NbChanges: number of times the State string has been changed.",
342: true, false, false);
343:
344: Constructor[] constructors = this .getClass().getConstructors();
345: dConstructors[0] = new MBeanConstructorInfo(
346: "SimpleDynamic(): Constructs a SimpleDynamic object",
347: constructors[0]);
348:
349: MBeanParameterInfo[] params = null;
350: dOperations[0] = new MBeanOperationInfo(
351: "reset",
352: "reset(): reset State and NbChanges attributes to their initial values",
353: params, "void", MBeanOperationInfo.ACTION);
354:
355: dMBeanInfo = new MBeanInfo(dClassName, dDescription,
356: dAttributes, dConstructors, dOperations,
357: new MBeanNotificationInfo[0]);
358: }
359:
360: }
|