/** * Define an attribute. Explicit definition of an attribute. Reflection is used to locate the * actual getter and setter methods. * * @param attrInfo ModelMBeanAttributeInfo. */ public synchronized void defineAttribute(ModelMBeanAttributeInfo attrInfo) { if (_object == null) throw new IllegalStateException("No Object"); _dirty = true; String name = attrInfo.getName(); String uName = name.substring(0, 1).toUpperCase() + name.substring(1); Class oClass = _object.getClass(); try { Class type = TypeUtil.fromName(attrInfo.getType()); if (type == null) type = Thread.currentThread().getContextClassLoader().loadClass(attrInfo.getType()); Method getter = null; Method setter = null; if (attrInfo.isReadable()) getter = oClass.getMethod((attrInfo.isIs() ? "is" : "get") + uName, (java.lang.Class[]) null); if (attrInfo.isWritable()) setter = oClass.getMethod("set" + uName, new Class[] {type}); _getter.put(name, getter); _setter.put(name, setter); _attributes.add(attrInfo); } catch (Exception e) { log.warn(LogSupport.EXCEPTION, e); throw new IllegalArgumentException(e.toString()); } }
@Test public void testGetAgeIsReadOnly() throws Exception { ModelMBeanInfo info = getMBeanInfoFromAssembler(); ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE); assertTrue("Age is not readable", attr.isReadable()); assertFalse("Age is not writable", attr.isWritable()); }
public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { if (attribute == null) throw new RuntimeOperationsException( new IllegalArgumentException( LocalizedStrings.MX4JModelMBean_ATTRIBUTE_CANNOT_BE_NULL.toLocalizedString())); Logger logger = getLogger(); // No need to synchronize: I work mostly on clones // I want the real info, not its clone ModelMBeanInfo info = getModelMBeanInfo(); if (info == null) throw new AttributeNotFoundException( LocalizedStrings.MX4JModelMBean_MODELMBEANINFO_IS_NULL.toLocalizedString()); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("ModelMBeanInfo is: " + info); String attrName = attribute.getName(); Object attrValue = attribute.getValue(); // This is a clone, we use it read only ModelMBeanAttributeInfo attrInfo = info.getAttribute(attrName); if (attrInfo == null) throw new AttributeNotFoundException( LocalizedStrings.MX4JModelMBean_CANNOT_FIND_MODELMBEANATTRIBUTEINFO_FOR_ATTRIBUTE_0 .toLocalizedString(attrName)); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Attribute info is: " + attrInfo); if (!attrInfo.isWritable()) throw new AttributeNotFoundException( LocalizedStrings.MX4JModelMBean_ATTRIBUTE_0_IS_NOT_WRITABLE.toLocalizedString(attrName)); // This returns a clone of the mbean descriptor, we use it read only Descriptor mbeanDescriptor = info.getMBeanDescriptor(); if (mbeanDescriptor == null) throw new AttributeNotFoundException( LocalizedStrings.MX4JModelMBean_MBEAN_DESCRIPTOR_CANNOT_BE_NULL.toLocalizedString()); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("MBean descriptor is: " + mbeanDescriptor); // This descriptor is a clone Descriptor attributeDescriptor = attrInfo.getDescriptor(); if (attributeDescriptor == null) throw new AttributeNotFoundException( LocalizedStrings.MX4JModelMBean_ATTRIBUTE_DESCRIPTOR_FOR_ATTRIBUTE_0_CANNOT_BE_NULL .toLocalizedString(attrName)); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Attribute descriptor is: " + attributeDescriptor); String lastUpdateField = "lastUpdatedTimeStamp"; Object oldValue = null; try { oldValue = getAttribute(attrName); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Previous value of attribute " + attrName + ": " + oldValue); } catch (Exception x) { if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Cannot get previous value of attribute " + attrName, x); } // Check if setMethod is present String method = (String) attributeDescriptor.getFieldValue("setMethod"); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("setMethod field is: " + method); if (method != null) { Class declared = loadClassWithContextClassLoader(attrInfo.getType()); if (attrValue != null) { Class parameter = attrValue.getClass(); checkAssignability(parameter, declared); } // As an extension, allow attributes to be called on target objects also Object target = resolveTargetObject(attributeDescriptor); invokeMethod(target, method, new Class[] {declared}, new Object[] {attrValue}); // Cache the value only if currencyTimeLimit is not 0, ie it is not always stale int staleness = getStaleness(attributeDescriptor, mbeanDescriptor, lastUpdateField); if (staleness != ALWAYS_STALE) { attributeDescriptor.setField("value", attrValue); attributeDescriptor.setField(lastUpdateField, Long.valueOf(System.currentTimeMillis())); if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Attribute's value has been cached"); } else { if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Always stale, avoiding to cache attribute's value"); } } else { if (attrValue != null) { Class parameter = attrValue.getClass(); Class declared = loadClassWithContextClassLoader(attrInfo.getType()); checkAssignability(parameter, declared); } // Always store the value in the descriptor: no setMethod attributeDescriptor.setField("value", attrValue); } // And now replace the descriptor with the updated clone info.setDescriptor(attributeDescriptor, "attribute"); // Send notifications to listeners if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Sending attribute change notifications"); sendAttributeChangeNotification(new Attribute(attrName, oldValue), attribute); // Persist this ModelMBean boolean persistNow = shouldPersistNow(attributeDescriptor, mbeanDescriptor, lastUpdateField); if (persistNow) { if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Persisting this ModelMBean..."); try { store(); if (logger.isEnabledFor(Logger.TRACE)) logger.trace("ModelMBean persisted successfully"); } catch (Exception x) { logger.error(LocalizedStrings.MX4JModelMBean_CANNOT_STORE_MODELMBEAN_AFTER_SETATTRIBUTE, x); if (x instanceof MBeanException) throw (MBeanException) x; else throw new MBeanException(x); } } }