001: /**
002: * Copyright 2004-2005 jManage.org
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */package org.jmanage.core.modules;
016:
017: import org.jmanage.core.management.*;
018: import org.jmanage.core.management.ObjectName;
019: import org.jmanage.core.management.MalformedObjectNameException;
020: import org.jmanage.core.util.Loggers;
021:
022: import javax.management.*;
023: import javax.management.openmbean.CompositeData;
024: import javax.management.openmbean.TabularData;
025: import java.util.*;
026: import java.util.logging.Logger;
027: import java.util.logging.Level;
028: import java.lang.reflect.Method;
029: import java.lang.reflect.InvocationTargetException;
030: import java.io.IOException;
031:
032: /**
033: * Date: Sep 3, 2004 11:19:06 PM
034: * @author Shashank Bellary
035: * @author Rakesh Kalra
036: */
037: public abstract class JMXServerConnection implements ServerConnection {
038:
039: private static final Logger logger = Loggers
040: .getLogger(JMXServerConnection.class);
041:
042: private Object mbeanServer;
043: // this is required as the mbeanServer object may be of a class
044: // which is private inner class (e.g. in JSR160)
045: private Class mbeanServerClass;
046:
047: public JMXServerConnection() {
048: }
049:
050: public JMXServerConnection(Object mbeanServer,
051: Class mbeanServerClass) {
052: this .mbeanServer = mbeanServer;
053: this .mbeanServerClass = mbeanServerClass;
054: }
055:
056: /**
057: * Queries the MBeanServer for the given object name pattern.
058: *
059: * @param objectName the ObjectName pattern
060: * @return Set of ObjectName objects
061: */
062: public Set queryNames(ObjectName objectName) {
063:
064: Class[] methodSignature = new Class[] {
065: javax.management.ObjectName.class,
066: javax.management.QueryExp.class };
067: Object[] methodArgs = new Object[] {
068: toJMXObjectName(objectName), null };
069: Set mbeans = (Set) callMBeanServer("queryNames",
070: methodSignature, methodArgs);
071: return toJmanageObjectNameInstance(mbeans);
072: }
073:
074: /**
075: * Invokes the given "operationName" on the object identified by
076: * "objectName".
077: *
078: * @param objectName
079: * @param operationName
080: * @param params
081: * @param signature
082: * @return
083: */
084: public Object invoke(ObjectName objectName, String operationName,
085: Object[] params, String[] signature) {
086:
087: Class[] methodSignature = new Class[] {
088: javax.management.ObjectName.class, String.class,
089: new Object[0].getClass(), new String[0].getClass() };
090: Object[] methodArgs = new Object[] {
091: toJMXObjectName(objectName), operationName, params,
092: signature };
093: return callMBeanServer("invoke", methodSignature, methodArgs);
094: }
095:
096: /**
097: * Returns the information about the given objectName.
098: *
099: * @param objectName
100: * @return
101: */
102: public ObjectInfo getObjectInfo(ObjectName objectName) {
103:
104: Class[] methodSignature = new Class[] { javax.management.ObjectName.class };
105: Object[] methodArgs = new Object[] { toJMXObjectName(objectName) };
106: MBeanInfo mbeanInfo = (MBeanInfo) callMBeanServer(
107: "getMBeanInfo", methodSignature, methodArgs);
108: return toObjectInfo(objectName, mbeanInfo);
109: }
110:
111: /**
112: * Gets the value for a single attribute.
113: *
114: * @param objectName
115: * @param attributeName
116: * @return attribute value
117: */
118: public Object getAttribute(ObjectName objectName,
119: String attributeName) {
120:
121: Class[] methodSignature = new Class[] {
122: javax.management.ObjectName.class, String.class };
123: Object[] methodArgs = new Object[] {
124: toJMXObjectName(objectName), attributeName };
125: return callMBeanServer("getAttribute", methodSignature,
126: methodArgs);
127: }
128:
129: /**
130: * Returns a list of ObjectAttribute objects containing attribute names
131: * and values for the given attributeNames
132: *
133: * @param objectName
134: * @param attributeNames
135: * @return
136: */
137: public List getAttributes(ObjectName objectName,
138: String[] attributeNames) {
139:
140: Class[] methodSignature = new Class[] {
141: javax.management.ObjectName.class,
142: new String[0].getClass() };
143: Object[] methodArgs = new Object[] {
144: toJMXObjectName(objectName), attributeNames };
145: AttributeList attrList = (AttributeList) callMBeanServer(
146: "getAttributes", methodSignature, methodArgs);
147: return toObjectAttributeList(attrList);
148: }
149:
150: /**
151: * Saves the attribute values.
152: *
153: * @param objectName
154: * @param attributeList list of ObjectAttribute objects
155: */
156: public List setAttributes(ObjectName objectName, List attributeList) {
157:
158: Class[] methodSignature = new Class[] {
159: javax.management.ObjectName.class,
160: javax.management.AttributeList.class };
161: Object[] methodArgs = new Object[] {
162: toJMXObjectName(objectName),
163: toJMXAttributeList(attributeList) };
164: AttributeList output = (AttributeList) callMBeanServer(
165: "setAttributes", methodSignature, methodArgs);
166: return toObjectAttributeList(output);
167: }
168:
169: // maps for storing jmanage notification objects to jmx notification
170: // object relationships
171: protected Map notifications = new HashMap();
172: protected Map notifFilters = new HashMap();
173:
174: public void addNotificationListener(ObjectName objectName,
175: ObjectNotificationListener listener,
176: ObjectNotificationFilter filter, Object handback) {
177:
178: NotificationListener notifListener = toJMXNotificationListener(listener);
179: notifications.put(listener, notifListener);
180: NotificationFilter notifFilter = toJMXNotificationFilter(filter);
181: notifFilters.put(filter, notifFilter);
182:
183: Class[] methodSignature = new Class[] {
184: javax.management.ObjectName.class,
185: NotificationListener.class, NotificationFilter.class,
186: Object.class };
187: Object[] methodArgs = new Object[] {
188: toJMXObjectName(objectName), notifListener,
189: notifFilter, handback };
190: callMBeanServer("addNotificationListener", methodSignature,
191: methodArgs);
192: }
193:
194: public void removeNotificationListener(ObjectName objectName,
195: ObjectNotificationListener listener,
196: ObjectNotificationFilter filter, Object handback) {
197:
198: NotificationListener notifListener = (NotificationListener) notifications
199: .remove(listener);
200: NotificationFilter notifFilter = (NotificationFilter) notifFilters
201: .remove(filter);
202: assert notifListener != null;
203: assert notifFilter != null;
204:
205: Class[] methodSignature = new Class[] {
206: javax.management.ObjectName.class,
207: NotificationListener.class, NotificationFilter.class,
208: Object.class };
209: Object[] methodArgs = new Object[] {
210: toJMXObjectName(objectName), notifListener,
211: notifFilter, handback };
212: callMBeanServer("removeNotificationListener", methodSignature,
213: methodArgs);
214: }
215:
216: // todo: this method will need to throw InstanceAlreadyExistsException
217: public void createMBean(String className, ObjectName name,
218: Object[] params, String[] signature) {
219: Class[] methodSignature = new Class[] { String.class,
220: javax.management.ObjectName.class,
221: new Object[0].getClass(), new String[0].getClass() };
222: Object[] methodArgs = new Object[] { className,
223: toJMXObjectName(name), params, signature };
224: callMBeanServer("createMBean", methodSignature, methodArgs);
225: }
226:
227: public void unregisterMBean(ObjectName objectName) {
228:
229: Class[] methodSignature = new Class[] { javax.management.ObjectName.class };
230: Object[] methodArgs = new Object[] { toJMXObjectName(objectName) };
231: callMBeanServer("unregisterMBean", methodSignature, methodArgs);
232: }
233:
234: public Object buildObjectName(String objectName) {
235: try {
236: return new javax.management.ObjectName(objectName);
237: } catch (javax.management.MalformedObjectNameException e) {
238: throw new RuntimeException(e);
239: }
240: }
241:
242: /**
243: * checks if this connection is open.
244: * It simply calls getMBeanCount() method on MBeanServer Connection.
245: * If there is no errors, then the connection is assumed to be open.
246: *
247: * @return true if this connection is open
248: */
249: public boolean isOpen() {
250: try {
251: Class[] methodSignature = new Class[0];
252: Object[] methodArgs = new Object[0];
253: Integer count = (Integer) callMBeanServer("getMBeanCount",
254: methodSignature, methodArgs);
255: return true;
256: } catch (Exception e) {
257: logger.log(Level.INFO, "Connection to the server is lost. "
258: + "Error message: " + e.getMessage());
259: return false;
260: }
261: }
262:
263: /**
264: * Closes the connection to the server
265: */
266: public void close() throws IOException {
267: logger.fine("Noop close operation.");
268: }
269:
270: ///////////////////////////////////////////////////////////////////////////
271: // Utility methods
272:
273: private Object callMBeanServer(String methodName, Class[] params,
274: Object[] args) {
275:
276: try {
277: Method method = mbeanServerClass.getMethod(methodName,
278: params);
279: return method.invoke(mbeanServer, args);
280: } catch (InvocationTargetException e) {
281: if (e.getCause() != null
282: && e.getCause() instanceof RuntimeException) {
283: throw (RuntimeException) e.getCause();
284: }
285: throw new RuntimeException(e.getCause());
286: } catch (Throwable e) {
287: if (e instanceof RuntimeException) {
288: throw (RuntimeException) e;
289: } else {
290: throw new RuntimeException(e);
291: }
292: }
293: }
294:
295: protected static javax.management.ObjectName toJMXObjectName(
296: ObjectName objectName) {
297: try {
298: return new javax.management.ObjectName(objectName
299: .toString());
300: } catch (javax.management.MalformedObjectNameException e) {
301: throw new MalformedObjectNameException(e);
302: }
303: }
304:
305: protected static ObjectName toJmanageObjectName(
306: javax.management.ObjectName objectName) {
307: return new ObjectName(objectName.toString(), objectName
308: .getCanonicalName());
309: }
310:
311: /**
312: * Converts a Set of javax.management.ObjectName to
313: * org.jmanage.core.management.ObjectName
314: */
315: protected static Set toJmanageObjectNameInstance(Set mbeans) {
316: final Set output = new HashSet(mbeans.size());
317: for (Iterator it = mbeans.iterator(); it.hasNext();) {
318: javax.management.ObjectName objName = (javax.management.ObjectName) it
319: .next();
320: output.add(toJmanageObjectName(objName));
321: }
322: return output;
323: }
324:
325: protected static ObjectInfo toObjectInfo(ObjectName objectName,
326: MBeanInfo mbeanInfo) {
327:
328: ObjectAttributeInfo[] attributes = toObjectAttributes(mbeanInfo
329: .getAttributes());
330: ObjectConstructorInfo[] constructors = toObjectConstructors(mbeanInfo
331: .getConstructors());
332: ObjectOperationInfo[] operations = toObjectOperations(mbeanInfo
333: .getOperations());
334: ObjectNotificationInfo[] notifications = toObjectNotifications(mbeanInfo
335: .getNotifications());
336: return new ObjectInfo(objectName, mbeanInfo.getClassName(),
337: mbeanInfo.getDescription(), attributes, constructors,
338: operations, notifications);
339: }
340:
341: protected static ObjectAttributeInfo[] toObjectAttributes(
342: MBeanAttributeInfo[] attributes) {
343: ObjectAttributeInfo[] objAttributes = new ObjectAttributeInfo[attributes.length];
344: for (int i = 0; i < attributes.length; i++) {
345: objAttributes[i] = toObjectAttributeInfo(attributes[i]);
346: }
347: return objAttributes;
348: }
349:
350: protected static ObjectAttributeInfo toObjectAttributeInfo(
351: MBeanAttributeInfo attribute) {
352:
353: return new ObjectAttributeInfo(attribute.getName(), attribute
354: .getDescription(), attribute.getType(), attribute
355: .isWritable(), attribute.isReadable(), attribute.isIs());
356: }
357:
358: protected static ObjectConstructorInfo[] toObjectConstructors(
359: MBeanConstructorInfo[] constructors) {
360: ObjectConstructorInfo[] objCtors = new ObjectConstructorInfo[constructors.length];
361: for (int i = 0; i < constructors.length; i++) {
362: objCtors[i] = toObjectConstructorInfo(constructors[i]);
363: }
364: return objCtors;
365: }
366:
367: protected static ObjectConstructorInfo toObjectConstructorInfo(
368: MBeanConstructorInfo constructor) {
369: return new ObjectConstructorInfo(constructor.getName(),
370: constructor.getDescription(),
371: toObjectParameters(constructor.getSignature()));
372: }
373:
374: protected static ObjectOperationInfo[] toObjectOperations(
375: MBeanOperationInfo[] operations) {
376: ObjectOperationInfo[] objOperations = new ObjectOperationInfo[operations.length];
377: for (int i = 0; i < operations.length; i++) {
378: objOperations[i] = toObjectOperationInfo(operations[i]);
379: }
380: return objOperations;
381: }
382:
383: protected static ObjectOperationInfo toObjectOperationInfo(
384: MBeanOperationInfo operation) {
385: return new ObjectOperationInfo(operation.getName(), operation
386: .getDescription(), toObjectParameters(operation
387: .getSignature()), operation.getReturnType(), operation
388: .getImpact());
389: }
390:
391: protected static ObjectNotificationInfo[] toObjectNotifications(
392: MBeanNotificationInfo[] notifications) {
393: ObjectNotificationInfo[] objNotifications = new ObjectNotificationInfo[notifications.length];
394: for (int i = 0; i < notifications.length; i++) {
395: objNotifications[i] = toObjectNotificationInfo(notifications[i]);
396: }
397: return objNotifications;
398: }
399:
400: protected static ObjectNotificationInfo toObjectNotificationInfo(
401: MBeanNotificationInfo notification) {
402: return new ObjectNotificationInfo(notification.getNotifTypes(),
403: notification.getName(), notification.getDescription());
404: }
405:
406: protected static ObjectParameterInfo[] toObjectParameters(
407: MBeanParameterInfo[] parameters) {
408: ObjectParameterInfo[] objParameters = new ObjectParameterInfo[parameters.length];
409: for (int i = 0; i < parameters.length; i++) {
410: objParameters[i] = toObjectParameterInfo(parameters[i]);
411: }
412: return objParameters;
413: }
414:
415: protected static ObjectParameterInfo toObjectParameterInfo(
416: MBeanParameterInfo parameter) {
417:
418: return new ObjectParameterInfo(parameter.getName(), parameter
419: .getDescription(), parameter.getType());
420: }
421:
422: protected static List toObjectAttributeList(AttributeList attrList) {
423: final List objAttrList = new ArrayList(attrList.size());
424: for (Iterator it = attrList.iterator(); it.hasNext();) {
425: Attribute attr = (Attribute) it.next();
426: objAttrList.add(toObjectAttribute(attr));
427: }
428: return objAttrList;
429: }
430:
431: protected static ObjectAttribute toObjectAttribute(Attribute attr) {
432: Object value = attr.getValue();
433: if (value != null) {
434: // todo: ideally this needs to be done only if the JMX classes
435: // are not compatible
436: if (value instanceof CompositeData) {
437: value = JMXInterfaceProxy.newProxyInstance(
438: CompositeData.class, value);
439: } else if (value instanceof TabularData) {
440: value = JMXInterfaceProxy.newProxyInstance(
441: TabularData.class, value);
442: }
443: }
444: return new ObjectAttribute(attr.getName(), value);
445: }
446:
447: protected static AttributeList toJMXAttributeList(List objAttrs) {
448: AttributeList attrList = new AttributeList(objAttrs.size());
449: for (Iterator it = objAttrs.iterator(); it.hasNext();) {
450: attrList.add(toJMXAttribute((ObjectAttribute) it.next()));
451: }
452: return attrList;
453: }
454:
455: protected static Attribute toJMXAttribute(ObjectAttribute objAttr) {
456: return new Attribute(objAttr.getName(), objAttr.getValue());
457: }
458:
459: protected static ObjectNotification toObjectNotification(
460: Notification n) {
461:
462: return new ObjectNotification(n.getType(), n.getSource(), n
463: .getSequenceNumber(), n.getTimeStamp(), n.getMessage(),
464: n.getUserData());
465: }
466:
467: protected static NotificationListener toJMXNotificationListener(
468: final ObjectNotificationListener listener) {
469:
470: return new NotificationListener() {
471: public void handleNotification(Notification notification,
472: Object handback) {
473: listener.handleNotification(
474: toObjectNotification(notification), handback);
475: }
476: };
477: }
478:
479: protected static NotificationFilter toJMXNotificationFilter(
480: final ObjectNotificationFilter filter) {
481: NotificationFilterSupport notificationFilter = new NotificationFilterSupport();
482: for (Iterator it = filter.getEnabledTypes().iterator(); it
483: .hasNext();) {
484: notificationFilter.enableType((String) it.next());
485: }
486: return notificationFilter;
487: }
488: }
|