private Object invokeAttribute(PropertyDescriptor pd, MethodInvocation invocation) throws JMException, IOException { String attributeName = JmxUtils.getAttributeName(pd, this.useStrictCasing); MBeanAttributeInfo inf = (MBeanAttributeInfo) this.allowedAttributes.get(attributeName); // If no attribute is returned, we know that it is not defined in the // management interface. if (inf == null) { throw new InvalidInvocationException( "Attribute '" + pd.getName() + "' is not exposed on the management interface"); } if (invocation.getMethod().equals(pd.getReadMethod())) { if (inf.isReadable()) { return this.server.getAttribute(this.objectName, attributeName); } else { throw new InvalidInvocationException("Attribute '" + attributeName + "' is not readable"); } } else if (invocation.getMethod().equals(pd.getWriteMethod())) { if (inf.isWritable()) { server.setAttribute( this.objectName, new Attribute(attributeName, invocation.getArguments()[0])); return null; } else { throw new InvalidInvocationException("Attribute '" + attributeName + "' is not writable"); } } else { throw new IllegalStateException( "Method [" + invocation.getMethod() + "] is neither a bean property getter nor a setter"); } }
protected Result describeMbean( @Nonnull MBeanServerConnection mbeanServer, @Nonnull ObjectName objectName) throws IntrospectionException, ReflectionException, InstanceNotFoundException, IOException { MBeanInfo mbeanInfo = mbeanServer.getMBeanInfo(objectName); StringWriter sw = new StringWriter(); PrintWriter out = new PrintWriter(sw); out.println("# MBEAN"); out.println(objectName.toString()); out.println(); out.println("## OPERATIONS"); List<MBeanOperationInfo> operations = Arrays.asList(mbeanInfo.getOperations()); Collections.sort( operations, new Comparator<MBeanOperationInfo>() { @Override public int compare(MBeanOperationInfo o1, MBeanOperationInfo o2) { return o1.getName().compareTo(o1.getName()); } }); for (MBeanOperationInfo opInfo : operations) { out.print("* " + opInfo.getName() + "("); MBeanParameterInfo[] signature = opInfo.getSignature(); for (int i = 0; i < signature.length; i++) { MBeanParameterInfo paramInfo = signature[i]; out.print(paramInfo.getType() + " " + paramInfo.getName()); if (i < signature.length - 1) { out.print(", "); } } out.print("):" + opInfo.getReturnType() /* + " - " + opInfo.getDescription() */); out.println(); } out.println(); out.println("## ATTRIBUTES"); List<MBeanAttributeInfo> attributes = Arrays.asList(mbeanInfo.getAttributes()); Collections.sort( attributes, new Comparator<MBeanAttributeInfo>() { @Override public int compare(MBeanAttributeInfo o1, MBeanAttributeInfo o2) { return o1.getName().compareTo(o2.getName()); } }); for (MBeanAttributeInfo attrInfo : attributes) { out.println( "* " + attrInfo.getName() + ": " + attrInfo.getType() + " - " + (attrInfo.isReadable() ? "r" : "") + (attrInfo.isWritable() ? "w" : "") /* + " - " + attrInfo.getDescription() */); } String description = sw.getBuffer().toString(); return new Result(objectName, description, description); }
/** * Description of the specified attribute name. * * @param attr - the attribute * @return String the description */ protected String describeAttribute(MBeanAttributeInfo attr) { StringBuilder buf = new StringBuilder(); buf.append("("); if (attr.isReadable()) { buf.append("r"); } if (attr.isWritable()) { buf.append("w"); } buf.append(") ").append(attr.getType()).append(" ").append(attr.getName()); return buf.toString(); }
public Object getPropertyValue(Object id) { if ("name".equals(id)) { // $NON-NLS-1$ return attrInfo.getName(); } if ("description".equals(id)) { // $NON-NLS-1$ return attrInfo.getDescription(); } if ("type".equals(id)) { // $NON-NLS-1$ Object obj = attrInfo.getType(); if (obj instanceof Object[]) { return Arrays.asList((Object[]) obj).toString(); } return obj; } if ("readable".equals(id)) { // $NON-NLS-1$ return Boolean.valueOf(attrInfo.isReadable()); } if ("writable".equals(id)) { // $NON-NLS-1$ return Boolean.valueOf(attrInfo.isWritable()); } if ("value".equals(id)) { // $NON-NLS-1$ try { if (mbsc != null) { Object obj = mbsc.getAttribute(on, attrInfo.getName()); if (obj instanceof Object[]) { return Arrays.asList((Object[]) obj).toString(); } return obj; } else { conn.run( new IJMXRunnable() { final Object[] ret = new Object[1]; @Override public void run(MBeanServerConnection connection) throws Exception { Object obj = connection.getAttribute(on, attrInfo.getName()); if (obj instanceof Object[]) { ret[0] = Arrays.asList((Object[]) obj).toString(); } ret[0] = obj; } }); } } catch (Exception e) { JMXUIActivator.log( IStatus.WARNING, NLS.bind(Messages.MBeanAttributeValue_Warning, attrInfo.getName()), e); return null; } } return null; }
private String getType(String attName, boolean read, boolean write) { boolean allowed = true; if (attributes.containsKey(attName)) { MBeanAttributeInfo temp = (MBeanAttributeInfo) attributes.get(attName); if (read) { if (!temp.isReadable()) allowed = false; } if (write) { if (!temp.isWritable()) allowed = false; } if (!allowed) return null; else return temp.getType(); } else return null; }
/** * Exports all the numeric attributes of beans matching the supplied MXBean name pattern. Also, * discovers the numeric properties of the attributes of type CompositeData and registers them as * well. * * @param beanNamePattern the bean name pattern used to discover the beans. * @see javax.management.ObjectName for bean name pattern syntax * @see java.lang.management for the list of java platform mbeans * @throws JMException if there are errors querying MBeans or information on them */ public void exportNumericAttributes(ObjectName beanNamePattern) throws JMException { MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer(); Set<ObjectName> beanNames = beanServer.queryNames(beanNamePattern, null); // Iterate through all beans and register their numeric properties with Stats for (ObjectName beanName : beanNames) { MBeanInfo beanInfo = beanServer.getMBeanInfo(beanName); // Iterate through all bean attributes for (MBeanAttributeInfo attributeInfo : beanInfo.getAttributes()) { if (attributeInfo.isReadable()) { // Figure out the open type for the attribute OpenType<?> openType = null; if (attributeInfo instanceof OpenMBeanAttributeInfo) { openType = ((OpenMBeanAttributeInfo) attributeInfo).getOpenType(); } else { // Sometimes the open mbean info is available in the descriptor Object obj = attributeInfo.getDescriptor().getFieldValue("openType"); if (obj != null && obj instanceof OpenType) { openType = (OpenType) obj; } } // once the open type is found, figure out if it's a numeric or composite type if (openType != null) { if (NUMERIC_TYPES.contains(openType)) { // numeric attribute types are registered with callbacks that simply // return their value addStatIfMatches( getStatName(beanName, attributeInfo.getName()), new MBeanLongAttributeFetcher(beanServer, beanName, attributeInfo.getName())); } else if (openType instanceof CompositeType) { // for composite types, we figure out which properties of the composite type // are numeric and register callbacks to fetch those composite type attributes CompositeType compositeType = (CompositeType) openType; for (String key : compositeType.keySet()) { if (NUMERIC_TYPES.contains(compositeType.getType(key))) { addStatIfMatches( getStatName(beanName, attributeInfo.getName(), key), new MBeanLongCompositeValueFetcher( beanServer, beanName, attributeInfo.getName(), key)); } } } } } } } }
@Test(dataProvider = "fixtures") public void testGetterAttributeInfo( String attribute, boolean isIs, Object[] values, Class<?> clazz) throws Exception { String methodName = "set" + attribute.replace(".", ""); for (T t : objects) { String attributeName = toFeatureName(attribute, t); SimpleInterface simpleInterface = toSimpleInterface(t); Method setter = getMethod(simpleInterface.getClass(), methodName, clazz); MBeanInfo info = getMBeanInfo(t); MBeanAttributeInfo attributeInfo = getAttributeInfo(info, attributeName); assertNotNull(attributeInfo, "AttributeInfo for " + attributeName); assertEquals(attributeInfo.getName(), attributeName, "Attribute Name for " + attributeName); assertEquals( attributeInfo.getType(), setter.getParameterTypes()[0].getName(), "Attribute type for " + attributeName); assertEquals(attributeInfo.isIs(), isIs, "Attribute isIs for " + attributeName); assertTrue(attributeInfo.isReadable(), "Attribute Readable for " + attributeName); assertFalse(attributeInfo.isWritable(), "Attribute Writable for " + attributeName); } }
/** * @param mbeanServer * @param objectName * @param attributeName * @param attributeValue if <code>null</code>, this is a read access. * @return if this is a read access, the returned value (may be null); if it is a write access, * return <code>void.class</code>. * @throws IOException * @throws JMException */ public Result invokeAttribute( @Nonnull MBeanServerConnection mbeanServer, @Nonnull ObjectName objectName, @Nonnull String attributeName, @Nullable String attributeValue) throws IOException, JMException { MBeanInfo mbeanInfo = mbeanServer.getMBeanInfo(objectName); MBeanAttributeInfo attributeInfo = null; for (MBeanAttributeInfo mai : mbeanInfo.getAttributes()) { if (mai.getName().equals(attributeName)) { attributeInfo = mai; break; } } if (attributeInfo == null) { throw new IllegalArgumentException( "No attribute '" + attributeName + "' found on '" + objectName + "'. Existing attributes: " + Arrays.asList(mbeanInfo.getAttributes())); } String description; Object resultValue; if (attributeValue == null) { if (attributeInfo.isReadable()) { Object attribute = mbeanServer.getAttribute(objectName, attributeName); logger.info("get attribute value {}:{}:{}", objectName, attributeName, attribute); resultValue = attribute; description = "Get attribute value " + objectName + ":" + attributeName + ": " + resultValue; } else { throw new IllegalArgumentException( "Attribute '" + attributeName + "' is not readable on '" + objectName + "': " + attributeInfo); } } else { if (attributeInfo.isWritable()) { Object value = convertValue(attributeValue, attributeInfo.getType()); mbeanServer.setAttribute(objectName, new Attribute(attributeName, value)); logger.info("set attribute value {}:{}:{}", objectName, attributeName, value); description = "Set attribute value " + objectName + ":" + attributeName + ": " + value; resultValue = void.class; } else { throw new IllegalArgumentException( "Attribute '" + attributeName + "' is not writable on '" + objectName + "': " + attributeInfo); } } return new Result(objectName, resultValue, description); }
private MBeanAttributeInfo[] createMBeanAttributeInfo( MBeanMetaData metadata, MBeanDescription description) { Logger logger = getLogger(); HashMap attributes = new HashMap(); HashMap getterNames = new HashMap(); Method[] methods = metadata.management.getMethods(); for (int j = 0; j < methods.length; ++j) { Method method = methods[j]; if (Utils.isAttributeGetter(method)) { String name = method.getName(); boolean isIs = name.startsWith("is"); String attribute = null; if (isIs) attribute = name.substring(2); else attribute = name.substring(3); String descr = description == null ? null : description.getAttributeDescription(attribute); MBeanAttributeInfo info = (MBeanAttributeInfo) attributes.get(attribute); if (info != null) { // JMX spec does not allow overloading attributes. // If an attribute with the same name already exists the MBean is not compliant if (!info.getType().equals(method.getReturnType().getName())) { if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("MBean is not compliant: has overloaded attribute " + attribute); return null; } else { // They return the same value, if (getterNames.get(name) != null) { // This is the case of an attribute being present in multiple interfaces // Ignore all but the first, since they resolve to the same method anyways continue; } // there is a chance that one is a get-getter and one is a is-getter // for a boolean attribute. In this case, the MBean is not compliant. if (info.isReadable()) { if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("MBean is not compliant: has overloaded attribute " + attribute); return null; } // MBeanAttributeInfo is already present due to a setter method, just update its // readability info = new MBeanAttributeInfo( attribute, info.getType(), info.getDescription(), true, info.isWritable(), isIs); } } else { info = new MBeanAttributeInfo( attribute, method.getReturnType().getName(), descr, true, false, isIs); } // Replace if exists attributes.put(attribute, info); getterNames.put(name, method); } else if (Utils.isAttributeSetter(method)) { String name = method.getName(); String attribute = name.substring(3); String descr = description == null ? null : description.getAttributeDescription(attribute); MBeanAttributeInfo info = (MBeanAttributeInfo) attributes.get(attribute); if (info != null) { // JMX spec does not allow overloading attributes. // If an attribute with the same name already exists the MBean is not compliant if (!info.getType().equals(method.getParameterTypes()[0].getName())) { if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("MBean is not compliant: has overloaded attribute " + attribute); return null; } else { // MBeanAttributeInfo is already present due to a getter method, just update its // writability info = new MBeanAttributeInfo( info.getName(), info.getType(), info.getDescription(), info.isReadable(), true, info.isIs()); } } else { info = new MBeanAttributeInfo( attribute, method.getParameterTypes()[0].getName(), descr, false, true, false); } // Replace if exists attributes.put(attribute, info); } } return (MBeanAttributeInfo[]) attributes.values().toArray(new MBeanAttributeInfo[attributes.size()]); }
private void assertNickName(MBeanAttributeInfo attr) { assertNotNull("Nick Name should not be null", attr); assertTrue("Nick Name should be writable", attr.isWritable()); assertTrue("Nick Name should be readable", attr.isReadable()); }
private void renderJsonDomain( final PrintWriter pw, final ObjectName objectName, final MBeanInfo mBeanInfo, boolean renderDetails) throws IOException, AttributeNotFoundException, InstanceNotFoundException { pw.write("{"); jsonKey(pw, "mbean"); // using toString to make shure that type is set before any other // property String canonicalName = objectName.toString(); String[] split = canonicalName.split(":"); jsonValue(pw, split[1]); if (renderDetails) { pw.write(','); jsonKey(pw, "attributes"); pw.write("[{"); final MBeanAttributeInfo[] attrs = mBeanInfo.getAttributes(); for (int i = 0; i < attrs.length; i++) { final MBeanAttributeInfo attr = attrs[i]; if (!attr.isReadable()) continue; // skip non readable properties // jsonValue(pw, attr.getName() + ":writable=" + // attr.isWritable()); jsonKey(pw, attr.getName()); pw.write("["); jsonValue(pw, "writable=" + attr.isWritable()); Object value = null; try { // Descriptor descriptor = attr.getDescriptor(); // descriptor.get value = (mBeanServer.getAttribute(objectName, attr.getName())); } catch (ReflectionException e) { // Munch skip this attribute then } catch (MBeanException e) { // Munch skip this attribute then } catch (RuntimeMBeanException e) { // Munch skip this attribute then } if (value != null) { pw.write(","); if (!value.getClass().isArray()) { jsonValue(pw, "value=" + value.toString()); } else { jsonValue(pw, "value=" + Arrays.toString((Object[]) value)); } } pw.write("]"); if (i < attrs.length) { pw.write(','); } } pw.write("}]"); pw.write(','); jsonKey(pw, "operations"); pw.write("["); final MBeanOperationInfo[] ops = mBeanInfo.getOperations(); for (int i = 0; i < ops.length; i++) { final MBeanOperationInfo op = ops[i]; // jsonValue(pw, op.getDescription() + ": " + op.getName() + // " - " // + op.getReturnType()); jsonValue(pw, op.getName()); if (i < ops.length) { pw.write(','); } } pw.write("]"); } pw.write("},"); }