private Logger getModelMBeanLogger(String notificationType) throws MBeanException { // Get a copy to avoid synchronization ModelMBeanInfo info = getModelMBeanInfo(); // First look if there is a suitable notification descriptor, otherwise use MBean descriptor Descriptor descriptor = null; Logger modelMBeanLogger = null; if (notificationType != null) { descriptor = info.getDescriptor(notificationType, "notification"); modelMBeanLogger = findLogger(descriptor); } if (modelMBeanLogger == null) { descriptor = info.getMBeanDescriptor(); modelMBeanLogger = findLogger(descriptor); if (modelMBeanLogger != null) return modelMBeanLogger; } return null; }
public Object invoke(String method, Object[] arguments, String[] params) throws MBeanException, ReflectionException { if (method == null) throw new RuntimeOperationsException( new IllegalArgumentException( LocalizedStrings.MX4JModelMBean_METHOD_NAME_CANNOT_BE_NULL.toLocalizedString())); if (arguments == null) arguments = new Object[0]; if (params == null) params = new String[0]; Logger logger = getLogger(); // Find operation descriptor ModelMBeanInfo info = getModelMBeanInfo(); if (info == null) throw new MBeanException( new ServiceNotFoundException( LocalizedStrings.MX4JModelMBean_MODELMBEANINFO_IS_NULL.toLocalizedString())); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("ModelMBeanInfo is: " + info); // This is a clone, we use it read only ModelMBeanOperationInfo operInfo = info.getOperation(method); if (operInfo == null) throw new MBeanException( new ServiceNotFoundException( LocalizedStrings.MX4JModelMBean_CANNOT_FIND_MODELMBEANOPERATIONINFO_FOR_OPERATION_0 .toLocalizedString(method))); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Operation info is: " + operInfo); // This descriptor is a clone Descriptor operationDescriptor = operInfo.getDescriptor(); if (operationDescriptor == null) throw new MBeanException( new ServiceNotFoundException( LocalizedStrings.MX4JModelMBean_OPERATION_DESCRIPTOR_FOR_OPERATION_0_CANNOT_BE_NULL .toLocalizedString(method))); String role = (String) operationDescriptor.getFieldValue("role"); if (role == null || !role.equals("operation")) throw new MBeanException( new ServiceNotFoundException( LocalizedStrings .MX4JModelMBean_OPERATION_DESCRIPTOR_FIELD_ROLE_MUST_BE_OPERATION_NOT_0 .toLocalizedString(role))); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Operation descriptor is: " + operationDescriptor); // This returns a clone of the mbean descriptor, we use it read only Descriptor mbeanDescriptor = info.getMBeanDescriptor(); if (mbeanDescriptor == null) throw new MBeanException( new ServiceNotFoundException( LocalizedStrings.MX4JModelMBean_MBEAN_DESCRIPTOR_CANNOT_BE_NULL.toLocalizedString())); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("MBean descriptor is: " + mbeanDescriptor); Object returnValue = null; String lastUpdateField = "lastReturnedTimeStamp"; // Check if the method should be invoked given the cache settings int staleness = getStaleness(operationDescriptor, mbeanDescriptor, lastUpdateField); if (staleness == ALWAYS_STALE || staleness == STALE) { if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Value is stale"); // Find parameters classes Class[] parameters = null; try { parameters = Utils.loadClasses(Thread.currentThread().getContextClassLoader(), params); } catch (ClassNotFoundException x) { logger.error(LocalizedStrings.MX4JModelMBean_CANNOT_FIND_OPERATIONS_PARAMETER_CLASSES, x); throw new ReflectionException(x); } if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Invoking operation..."); // Find target object Object target = resolveTargetObject(operationDescriptor); returnValue = invokeMethod(target, method, parameters, arguments); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Returned value is: " + returnValue); if (returnValue != null) { Class parameter = returnValue.getClass(); Class declared = loadClassWithContextClassLoader(operInfo.getReturnType()); checkAssignability(parameter, declared); } // Cache the new value only if caching is needed if (staleness != ALWAYS_STALE) { operationDescriptor.setField("lastReturnedValue", returnValue); operationDescriptor.setField(lastUpdateField, Long.valueOf(System.currentTimeMillis())); if (logger.isEnabledFor(Logger.TRACE)) { logger.trace("Returned value has been cached"); } // And now replace the descriptor with the updated clone info.setDescriptor(operationDescriptor, "operation"); } if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("invoke for operation " + method + " returns invoked value: " + returnValue); } else { // Return cached value returnValue = operationDescriptor.getFieldValue("lastReturnedValue"); if (returnValue != null) { Class parameter = returnValue.getClass(); Class declared = loadClassWithContextClassLoader(operInfo.getReturnType()); checkAssignability(parameter, declared); } if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("invoke for operation " + method + " returns cached value: " + returnValue); } // As an extension, persist this model mbean also after operation invocation, but using only // settings provided in the operation descriptor, without falling back to defaults set in // the MBean descriptor boolean persistNow = shouldPersistNow(operationDescriptor, null, lastUpdateField); int impact = operInfo.getImpact(); if (persistNow && impact != MBeanOperationInfo.INFO) { 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_OPERATION_INVOCATION, x); if (x instanceof MBeanException) throw (MBeanException) x; else throw new MBeanException(x); } } return returnValue; }
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); } } }
public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException { if (attribute == null) throw new RuntimeOperationsException( new IllegalArgumentException( LocalizedStrings.MX4JModelMBean_ATTRIBUTE_NAME_CANNOT_BE_NULL.toLocalizedString())); Logger logger = getLogger(); // 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); // This is a clone, we use it read only ModelMBeanAttributeInfo attrInfo = info.getAttribute(attribute); if (attrInfo == null) throw new AttributeNotFoundException( LocalizedStrings.MX4JModelMBean_CANNOT_FIND_MODELMBEANATTRIBUTEINFO_FOR_ATTRIBUTE_0 .toLocalizedString(attribute)); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Attribute info is: " + attrInfo); if (!attrInfo.isReadable()) throw new AttributeNotFoundException( LocalizedStrings.MX4JModelMBean_ATTRIBUTE_0_IS_NOT_READABLE.toLocalizedString(attribute)); // 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(attribute)); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Attribute descriptor is: " + attributeDescriptor); Object returnValue = null; String lastUpdateField = "lastUpdatedTimeStamp"; int staleness = getStaleness(attributeDescriptor, mbeanDescriptor, lastUpdateField); if (staleness == ALWAYS_STALE || staleness == STALE) { if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Value is stale"); String getter = (String) attributeDescriptor.getFieldValue("getMethod"); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("getMethod field is: " + getter); if (getter == null) { // No getter, use default value returnValue = attributeDescriptor.getFieldValue("default"); if (returnValue != null) { // Check if the return type is of the same type // As an extension allow covariant return type Class returned = returnValue.getClass(); Class declared = loadClassWithContextClassLoader(attrInfo.getType()); checkAssignability(returned, declared); } if (logger.isEnabledFor(Logger.DEBUG)) logger.debug( "getAttribute for attribute " + attribute + " returns default value: " + returnValue); } else { if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Invoking attribute getter..."); // As an extension, allow attributes to be called on target objects also Object target = resolveTargetObject(attributeDescriptor); returnValue = invokeMethod(target, getter, new Class[0], new Object[0]); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Returned value is: " + returnValue); if (returnValue != null) { // Check if the return type is of the same type // As an extension allow covariant return type Class returned = returnValue.getClass(); Class declared = loadClassWithContextClassLoader(attrInfo.getType()); checkAssignability(returned, declared); } // Cache the new value only if caching is needed if (staleness != ALWAYS_STALE) { attributeDescriptor.setField("value", returnValue); attributeDescriptor.setField(lastUpdateField, Long.valueOf(System.currentTimeMillis())); if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Returned value has been cached"); // And now replace the descriptor with the updated clone info.setDescriptor(attributeDescriptor, "attribute"); } if (logger.isEnabledFor(Logger.DEBUG)) logger.debug( "getAttribute for attribute " + attribute + " returns invoked value: " + returnValue); } } else { // Return cached value returnValue = attributeDescriptor.getFieldValue("value"); if (returnValue != null) { // Check if the return type is of the same type // As an extension allow covariant return type Class returned = returnValue.getClass(); Class declared = loadClassWithContextClassLoader(attrInfo.getType()); checkAssignability(returned, declared); } if (logger.isEnabledFor(Logger.DEBUG)) logger.debug( "getAttribute for attribute " + attribute + " returns cached value: " + returnValue); } // Puff, everything went ok return returnValue; }
private PersisterMBean findPersister() throws MBeanException, InstanceNotFoundException { Logger logger = getLogger(); ModelMBeanInfo info = getModelMBeanInfo(); if (info == null) { // Not yet initialized if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Can't find persister, ModelMBeanInfo is null"); return null; } Descriptor mbeanDescriptor = info.getMBeanDescriptor(); if (mbeanDescriptor == null) { // This is normally should not happen if ModelMBeanInfoSupport is used if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Can't find persister, MBean descriptor is null"); return null; } String location = (String) mbeanDescriptor.getFieldValue("persistLocation"); String name = (String) mbeanDescriptor.getFieldValue("persistName"); String mbeanName = (String) mbeanDescriptor.getFieldValue("name"); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Persistence fields: location=" + location + ", name=" + name); if (mbeanName == null && name == null) { if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Persistence is not supported by this ModelMBean"); return null; } // Try to see if this mbean should delegate to another mbean if (name != null) { try { ObjectName objectName = new ObjectName(name.trim()); // OK, a valid object name MBeanServer server = getMBeanServer(); if (server == null) throw new MBeanException( new IllegalStateException( LocalizedStrings.MX4JModelMBean_MX4JMODELMBEAN_IS_NOT_REGISTERED .toLocalizedString())); if (server.isRegistered(objectName) && server.isInstanceOf(objectName, PersisterMBean.class.getName())) { // OK, the given mbean is registered with this mbean server PersisterMBean persister = new MBeanPersister(server, objectName); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Persistence is delegated to this MBean: " + objectName); return persister; } else { throw new InstanceNotFoundException(objectName.toString()); } } catch (MalformedObjectNameException ignored) { // It does not delegates to another mbean, use default if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Persistence is not delegated to another MBean"); } // Default is serialization to file FilePersister persister = new FilePersister(location, name); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Persistence is realized through file system in " + persister.getFileName()); return persister; } else { // Only location given, use MBean name FilePersister persister = new FilePersister(location, mbeanName); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Persistence is realized through file system in " + persister.getFileName()); return persister; } }