/** * Create MBean for Object. Attempts to create an MBean for the object by searching the package * and class name space. For example an object of the type * * <PRE> * class com.acme.MyClass extends com.acme.util.BaseClass * </PRE> * * Then this method would look for the following classes: * * <UL> * <LI>com.acme.MyClassMBean * <LI>com.acme.jmx.MyClassMBean * <LI>com.acme.util.BaseClassMBean * <LI>com.acme.util.jmx.BaseClassMBean * </UL> * * @param o The object * @return A new instance of an MBean for the object or null. */ public static ModelMBean mbeanFor(Object o) { try { Class oClass = o.getClass(); ClassLoader loader = oClass.getClassLoader(); ModelMBean mbean = null; boolean jmx = false; Class[] interfaces = null; int i = 0; while (mbean == null && oClass != null) { Class focus = interfaces == null ? oClass : interfaces[i]; String pName = focus.getPackage().getName(); String cName = focus.getName().substring(pName.length() + 1); String mName = pName + (jmx ? ".jmx." : ".") + cName + "MBean"; try { Class mClass = loader.loadClass(mName); if (log.isTraceEnabled()) log.trace("mbeanFor " + o + " mClass=" + mClass); mbean = (ModelMBean) mClass.newInstance(); mbean.setManagedResource(o, "objectReference"); if (log.isDebugEnabled()) log.debug("mbeanFor " + o + " is " + mbean); return mbean; } catch (ClassNotFoundException e) { if (e.toString().endsWith("MBean")) { if (log.isTraceEnabled()) log.trace(e.toString()); } else log.warn(LogSupport.EXCEPTION, e); } catch (Error e) { log.warn(LogSupport.EXCEPTION, e); mbean = null; } catch (Exception e) { log.warn(LogSupport.EXCEPTION, e); mbean = null; } if (jmx) { if (interfaces != null) { i++; if (i >= interfaces.length) { interfaces = null; oClass = oClass.getSuperclass(); } } else { interfaces = oClass.getInterfaces(); i = 0; if (interfaces == null || interfaces.length == 0) { interfaces = null; oClass = oClass.getSuperclass(); } } } jmx = !jmx; } } catch (Exception e) { LogSupport.ignore(log, e); } return null; }
/* Find MBean descriptions. * MBean descriptions are searched for in ResourceBundles. Bundles * are looked for in a mbean.property files within each package of * the MBean class inheritance hierachy. * Once a bundle is found, the key is added to object names in the * following order: fully qualied managed resource class name, tail * managed resource class name, tail mbean class name. The string * "MBean" is stripped from the tail of any name. * <P>For example, if the class a.b.C is managed by a MBean * p.q.RMBean which is derived from p.SMBean, then the seach order * for a key x is as follows:<PRE> * bundle: p.q.mbean name: a.b.C.x * bundle: p.q.mbean name: C.x * bundle: p.q.mbean name: R.x * bundle: p.mbean name: a.b.C.x * bundle: p.mbean name: C.x * bundle: p.mbean name: S.x * </PRE> * <P>The convention used for keys passed to this method are:<PRE> * null or empty - Object description * xxx - Attribute xxx description * xxx() - Simple operation xxx description * xxx(type,..) - Operation xxx with signature desciption * xxx(type,..)[n] - Param n of operation xxx description * </PRE> * @param key * @return Description string. */ private String findDescription(String key) { Class lookIn = this.getClass(); // Array of possible objectNames String[] objectNames = new String[3]; objectNames[0] = _object.getClass().getName(); if (objectNames[0].indexOf(".") >= 0) objectNames[1] = objectNames[0].substring(objectNames[0].lastIndexOf(".") + 1); while (lookIn != null) { String pkg = lookIn.getName(); int lastDot = pkg.lastIndexOf("."); if (lastDot > 0) { objectNames[2] = pkg.substring(lastDot + 1); pkg = pkg.substring(0, lastDot); } else { objectNames[2] = pkg; pkg = null; } String resource = (pkg == null ? "mbean" : (pkg.replace('.', '/') + "/mbean")); if (log.isTraceEnabled()) log.trace("Look for: " + resource); try { ResourceBundle bundle = ResourceBundle.getBundle( resource, Locale.getDefault(), _object.getClass().getClassLoader()); if (log.isTraceEnabled()) log.trace("Bundle " + resource); for (int i = 0; i < objectNames.length; i++) { String name = objectNames[i]; if (name == null) continue; if (name.endsWith("MBean")) name = name.substring(0, name.length() - 5); if (key != null && key.length() > 0) name += "." + key; try { String description = bundle.getString(name); if (description != null && description.length() > 0) return description; } catch (Exception e) { if (log.isTraceEnabled()) log.trace(e.toString()); } } } catch (Exception e) { if (log.isTraceEnabled()) log.trace(e.toString()); } lookIn = lookIn.getSuperclass(); } if (key == null || key.length() == 0) return objectNames[0]; return key; }
/** * Define an operation on the managed object. Defines an operation with parameters. Refection is * used to determine find the method and it's return type. The description of the method is found * with a call to findDescription on "name(signature)". The name and description of each parameter * is found with a call to findDescription with "name(partialSignature", the returned description * is for the last parameter of the partial signature and is assumed to start with the parameter * name, followed by a colon. * * @param name The name of the method call. * @param signature The types of the operation parameters. * @param impact Impact as defined in MBeanOperationInfo * @param onMBean true if the operation is defined on the mbean */ public synchronized void defineOperation( String name, String[] signature, int impact, boolean onMBean) { _dirty = true; Class oClass = onMBean ? this.getClass() : _object.getClass(); if (signature == null) signature = new String[0]; try { Class[] types = new Class[signature.length]; MBeanParameterInfo[] pInfo = new MBeanParameterInfo[signature.length]; // Check types and build methodKey String methodKey = name + "("; for (int i = 0; i < signature.length; i++) { Class type = TypeUtil.fromName(signature[i]); if (type == null) type = Thread.currentThread().getContextClassLoader().loadClass(signature[i]); types[i] = type; signature[i] = type.isPrimitive() ? TypeUtil.toName(type) : signature[i]; methodKey += (i > 0 ? "," : "") + signature[i]; } methodKey += ")"; // Build param infos for (int i = 0; i < signature.length; i++) { String description = findDescription(methodKey + "[" + i + "]"); int colon = description.indexOf(":"); if (colon < 0) { description = "param" + i + ":" + description; colon = description.indexOf(":"); } pInfo[i] = new MBeanParameterInfo( description.substring(0, colon).trim(), signature[i], description.substring(colon + 1).trim()); } // build the operation info Method method = oClass.getMethod(name, types); Class returnClass = method.getReturnType(); _method.put(methodKey, method); _operations.add( new ModelMBeanOperationInfo( name, findDescription(methodKey), pInfo, returnClass.isPrimitive() ? TypeUtil.toName(returnClass) : (returnClass.getName()), impact)); } catch (Exception e) { log.warn("operation " + name, e); throw new IllegalArgumentException(e.toString()); } }