- /*
- * @(#)file RequiredModelMBean.java
- * @(#)author Sun Microsystems, Inc.
- * @(#)version 1.50
- * @(#)lastedit 04/02/11
- *
- * Copyright IBM Corp. 1999-2000. All rights reserved.
- *
- * The program is provided "as is" without any warranty express or implied,
- * including the warranty of non-infringement and the implied warranties of
- * merchantibility and fitness for a particular purpose. IBM will not be
- * liable for any damages suffered by you or any third party claim against
- * you regarding the Program.
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * This software is the proprietary information of Sun Microsystems, Inc.
- * Use is subject to license terms.
- *
- * Copyright 2004 Sun Microsystems, Inc. Tous droits reserves.
- * Ce logiciel est propriete de Sun Microsystems, Inc.
- * Distribue par des licences qui en restreignent l'utilisation.
- *
- */
-
-
-
-
- package javax.management.modelmbean;
-
- /* java imports */
-
- import java.lang.reflect.Method;
- import java.lang.reflect.InvocationTargetException;
-
- import java.util.Date;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Set;
-
- import java.io.PrintStream;
- import java.io.FileOutputStream;
-
- import javax.management.Attribute;
- import javax.management.AttributeList;
- import javax.management.AttributeChangeNotification;
- import javax.management.AttributeChangeNotificationFilter;
- import javax.management.AttributeNotFoundException;
- import javax.management.Descriptor;
- import javax.management.DescriptorAccess;
- import javax.management.InstanceNotFoundException;
- import javax.management.InvalidAttributeValueException;
- import javax.management.ListenerNotFoundException;
- import javax.management.MBeanAttributeInfo;
- import javax.management.MBeanConstructorInfo;
- import javax.management.MBeanException;
- import javax.management.MBeanInfo;
- import javax.management.MBeanNotificationInfo;
- import javax.management.MBeanOperationInfo;
- import javax.management.MBeanRegistration;
- import javax.management.MBeanRegistrationException;
- import javax.management.MBeanServer;
- import javax.management.MBeanServerFactory;
- import javax.management.Notification;
- import javax.management.NotificationBroadcasterSupport;
- import javax.management.NotificationFilter;
- import javax.management.NotificationListener;
- import javax.management.ObjectName;
- import javax.management.ReflectionException;
- import javax.management.RuntimeErrorException;
- import javax.management.RuntimeMBeanException;
- import javax.management.RuntimeOperationsException;
- import javax.management.ServiceNotFoundException;
- import javax.management.NotificationEmitter;
- import javax.management.loading.ClassLoaderRepository;
-
- import com.sun.jmx.trace.Trace;
-
-
- /**
- * This class is the implementation of a ModelMBean. An appropriate
- * implementation of a ModelMBean must be shipped with every JMX Agent
- * and the class must be named RequiredModelMBean.
- * <P>
- * Java resources wishing to be manageable instantiate the
- * RequiredModelMBean using the MBeanServer's createMBean method.
- * The resource then sets the MBeanInfo and Descriptors for the
- * RequiredModelMBean instance. The attributes and operations exposed
- * via the ModelMBeanInfo for the ModelMBean are accessible
- * from MBeans, connectors/adaptors like other MBeans. Through the
- * Descriptors, values and methods in the managed application can be
- * defined and mapped to attributes and operations of the ModelMBean.
- * This mapping can be defined in an XML formatted file or dynamically and
- * programmatically at runtime.
- * <P>
- * Every RequiredModelMBean which is instantiated in the MBeanServer
- * becomes manageable:<br>
- * its attributes and operations become remotely accessible through the
- * connectors/adaptors connected to that MBeanServer.
- * <P>
- * A Java object cannot be registered in the MBeanServer unless it is a
- * JMX compliant MBean. By instantiating a RequiredModelMBean, resources
- * are guaranteed that the MBean is valid.
- *
- * MBeanException and RuntimeOperationsException must be thrown on every
- * public method. This allows for wrapping exceptions from distributed
- * communications (RMI, EJB, etc.)
- *
- * @since 1.5
- */
-
- public class RequiredModelMBean
- implements ModelMBean, MBeanRegistration, NotificationEmitter {
-
- /*************************************/
- /* attributes */
- /*************************************/
- ModelMBeanInfo modelMBeanInfo;
-
- /* Notification broadcaster for any notification to be sent
- * from the application through the RequiredModelMBean. */
- private NotificationBroadcasterSupport generalBroadcaster = null;
-
- /* Notification broadcaster for attribute change notifications */
- private NotificationBroadcasterSupport attributeBroadcaster = null;
-
- /* handle, name, or reference for instance on which the actual invoke
- * and operations will be executed */
- private Object managedResource = null;
-
- private static final String currClass = "RequiredModelMBean";
-
- /* records the registering in MBeanServer */
- private boolean registered = false;
- private transient MBeanServer server = null;
-
- /*************************************/
- /* constructors */
- /*************************************/
-
- /**
- * Constructs an <CODE>RequiredModelMBean</CODE> with an empty
- * ModelMBeanInfo.
- * <P>
- * The RequiredModelMBean's MBeanInfo and Descriptors
- * can be customized using the {@link #setModelMBeanInfo} method.
- * After the RequiredModelMBean's MBeanInfo and Descriptors are
- * customized, the RequiredModelMBean can be registered with
- * the MBeanServer.
- *
- * @exception MBeanException Wraps a distributed communication Exception.
- *
- * @exception RuntimeOperationsException Wraps a {@link
- * RuntimeException} during the construction of the object.
- **/
- public RequiredModelMBean()
- throws MBeanException, RuntimeOperationsException {
-
- if (tracing())
- trace("RequiredModelMBean()","Entry and Exit");
-
- modelMBeanInfo = createDefaultModelMBeanInfo();
- }
-
- /**
- * Constructs a RequiredModelMBean object using ModelMBeanInfo passed in.
- * As long as the RequiredModelMBean is not registered
- * with the MBeanServer yet, the RequiredModelMBean's MBeanInfo and
- * Descriptors can be customized using the {@link #setModelMBeanInfo}
- * method.
- * After the RequiredModelMBean's MBeanInfo and Descriptors are
- * customized, the RequiredModelMBean can be registered with the
- * MBeanServer.
- *
- * @param mbi The ModelMBeanInfo object to be used by the
- * RequiredModelMBean. The given ModelMBeanInfo is cloned
- * and modified as specified by {@link #setModelMBeanInfo}
- *
- * @exception MBeanException Wraps a distributed communication Exception.
- * @exception RuntimeOperationsException Wraps an
- * {link java.lang.IllegalArgumentException}:
- * The MBeanInfo passed in parameter is null.
- *
- **/
- public RequiredModelMBean(ModelMBeanInfo mbi)
- throws MBeanException, RuntimeOperationsException {
-
- if (tracing())
- trace("RequiredModelMBean(MBeanInfo)","Entry");
-
- setModelMBeanInfo(mbi);
-
- if (tracing())
- trace("RequiredModelMBean(MBeanInfo)","Exit");
- }
-
-
- /*************************************/
- /* initializers */
- /*************************************/
-
- /**
- * Initializes a ModelMBean object using ModelMBeanInfo passed in.
- * This method makes it possible to set a customized ModelMBeanInfo on
- * the ModelMBean as long as it is not registered with the MBeanServer.
- * <br>
- * Once the ModelMBean's ModelMBeanInfo (with Descriptors) are
- * customized and set on the ModelMBean, the ModelMBean be
- * registered with the MBeanServer.
- * <P>
- * If the ModelMBean is currently registered, this method throws
- * a {@link javax.management.RuntimeOperationsException} wrapping an
- * {@link IllegalStateException}
- * <P>
- * If the given <var>inModelMBeanInfo</var> does not contain any
- * {@link ModelMBeanNotificationInfo} for the <code>GENERIC</code>
- * or <code>ATTRIBUTE_CHANGE</code> notifications, then the
- * RequiredModelMBean will supply its own default
- * {@link ModelMBeanNotificationInfo ModelMBeanNotificationInfo}s for
- * those missing notifications.
- *
- * @param mbi The ModelMBeanInfo object to be used
- * by the ModelMBean.
- *
- * @exception MBeanException Wraps a distributed communication
- * Exception.
- * @exception RuntimeOperationsException
- * <ul><li>Wraps an {@link IllegalArgumentException} if
- * the MBeanInfo passed in parameter is null.</li>
- * <li>Wraps an {@link IllegalStateException} if the ModelMBean
- * is currently registered in the MBeanServer.</li>
- * </ul>
- *
- **/
- public void setModelMBeanInfo(ModelMBeanInfo mbi)
- throws MBeanException, RuntimeOperationsException {
-
- if (tracing())
- trace("setModelMBeanInfo(ModelMBeanInfo)","Entry");
-
- if (mbi == null) {
- if (tracing())
- trace("setModelMBeanInfo(ModelMBeanInfo)",
- "ModelMBeanInfo is null: Raising exception.");
- final RuntimeException x = new
- IllegalArgumentException("ModelMBeanInfo must not be null");
- final String exceptionText =
- "Exception occured trying to initialize the " +
- "ModelMBeanInfo of the RequiredModelMBean";
- throw new RuntimeOperationsException(x,exceptionText);
- }
-
- if (registered) {
- if (tracing())
- trace("setModelMBeanInfo(ModelMBeanInfo)",
- "RequiredMBean is registered: Raising exception.");
- final String exceptionText =
- "Exception occured trying to set the " +
- "ModelMBeanInfo of the RequiredModelMBean";
- final RuntimeException x = new IllegalStateException(
- "cannot call setModelMBeanInfo while ModelMBean is registered");
- throw new RuntimeOperationsException(x,exceptionText);
- }
-
- if (tracing()) {
- trace("setModelMBeanInfo(ModelMBeanInfo)",
- "Setting ModelMBeanInfo to " + printModelMBeanInfo(mbi));
- trace("setModelMBeanInfo(ModelMBeanInfo)",
- "ModelMBeanInfo notifications has " +
- (mbi.getNotifications()).length + " elements");
- }
-
- modelMBeanInfo = (ModelMBeanInfo)mbi.clone();
-
- if (tracing())
- trace("setModelMBeanInfo(ModelMBeanInfo)","set mbeanInfo to: "+
- printModelMBeanInfo(modelMBeanInfo));
-
- if (tracing())
- trace("setModelMBeanInfo(ModelMBeanInfo)","Exit");
- }
-
-
- /**
- * Sets the instance handle of the object against which to
- * execute all methods in this ModelMBean management interface
- * (MBeanInfo and Descriptors).
- *
- * @param mr Object that is the managed resource
- * @param mr_type The type of reference for the managed resource.
- * <br>Can be: "ObjectReference", "Handle", "IOR", "EJBHandle",
- * or "RMIReference".
- * <br>In this implementation only "ObjectReference" is supported.
- *
- * @exception MBeanException The initializer of the object has
- * thrown an exception.
- * @exception InstanceNotFoundException The managed resource
- * object could not be found
- * @exception InvalidTargetObjectTypeException The managed
- * resource type should be "ObjectReference".
- * @exception RuntimeOperationsException Wraps a {@link
- * RuntimeException} when setting the resource.
- **/
- public void setManagedResource(Object mr, String mr_type)
- throws MBeanException, RuntimeOperationsException,
- InstanceNotFoundException, InvalidTargetObjectTypeException {
- if (tracing())
- trace("setManagedResource(Object,String)","Entry");
-
- // check that the mr_type is supported by this JMXAgent
- // only "objectReference" is supported
- if ((mr_type == null) ||
- (! mr_type.equalsIgnoreCase("objectReference"))) {
- if (tracing())
- trace("setManagedResource(Object,String)",
- "Managed Resouce Type is not supported: " + mr_type);
-
- throw new InvalidTargetObjectTypeException(mr_type);
- }
-
- if (tracing())
- trace("setManagedResource(Object,String)",
- "Managed Resouce is valid");
-
- managedResource = mr;
-
- if (tracing())
- trace("setManagedResource(Object, String)", "Exit");
- }
-
- /**
- * <p>Instantiates this MBean instance with the data found for
- * the MBean in the persistent store. The data loaded could include
- * attribute and operation values.</p>
- *
- * <p>This method should be called during construction or
- * initialization of this instance, and before the MBean is
- * registered with the MBeanServer.</p>
- *
- * <p>If the implementation of this class does not support
- * persistence, an {@link MBeanException} wrapping a {@link
- * ServiceNotFoundException} is thrown.</p>
- *
- * @exception MBeanException Wraps another exception, or
- * persistence is not supported
- * @exception RuntimeOperationsException Wraps exceptions from the
- * persistence mechanism
- * @exception InstanceNotFoundException Could not find or load
- * this MBean from persistent storage
- */
- public void load()
- throws MBeanException, RuntimeOperationsException,
- InstanceNotFoundException {
- final ServiceNotFoundException x = new ServiceNotFoundException(
- "Persistence not supported for this MBean");
- throw new MBeanException(x, x.getMessage());
- }
-
- /**
- * <p>Captures the current state of this MBean instance and writes
- * it out to the persistent store. The state stored could include
- * attribute and operation values.</p>
- *
- * <p>If the implementation of this class does not support
- * persistence, an {@link MBeanException} wrapping a {@link
- * ServiceNotFoundException} is thrown.</p>
- *
- * <p>Persistence policy from the MBean and attribute descriptor
- * is used to guide execution of this method. The MBean should be
- * stored if 'persistPolicy' field is:</p>
- *
- * <PRE> != "never"
- * = "always"
- * = "onTimer" and now > 'lastPersistTime' + 'persistPeriod'
- * = "NoMoreOftenThan" and now > 'lastPersistTime' + 'persistPeriod'
- * </PRE>
- *
- * <p>Do not store the MBean if 'persistPolicy' field is:</p>
- * <PRE>
- * = "never"
- * = "onUpdate"
- * = "onTimer" && now < 'lastPersistTime' + 'persistPeriod'
- * </PRE>
- *
- * @exception MBeanException Wraps another exception, or
- * persistence is not supported
- * @exception RuntimeOperationsException Wraps exceptions from the
- * persistence mechanism
- * @exception InstanceNotFoundException Could not find/access the
- * persistent store
- */
- public void store()
- throws MBeanException, RuntimeOperationsException,
- InstanceNotFoundException {
- final ServiceNotFoundException x = new ServiceNotFoundException(
- "Persistence not supported for this MBean");
- throw new MBeanException(x, x.getMessage());
- }
-
- /*************************************/
- /* DynamicMBean Interface */
- /*************************************/
-
- /**
- * The resolveForCacheValue method checks the descriptor passed in to
- * see if there is a valid cached value in the descriptor.
- * The valid value will be in the 'value' field if there is one.
- * If the 'currencyTimeLimit' field in the descriptor is:
- * <ul>
- * <li><b><0</b> Then the value is not cached and is never valid.
- * Null is returned. The 'value' and 'lastUpdatedTimeStamp'
- * fields are cleared.</li>
- * <li><b>=0</b> Then the value is always cached and always valid.
- * The 'value' field is returned.
- * The 'lastUpdatedTimeStamp' field is not checked.</li>
- * <li><b>>0</b> Represents the number of seconds that the
- * 'value' field is valid.
- * The 'value' field is no longer valid when
- * 'lastUpdatedTimeStamp' + 'currencyTimeLimit' > Now.</li>
- * </ul>
- * <li>When 'value' is valid, 'valid' is returned.</li>
- * <li>When 'value' is no longer valid then null is returned and
- * 'value' and 'lastUpdatedTimeStamp' fields are cleared.</li>
- *
- **/
- private Object resolveForCacheValue(Descriptor descr)
- throws MBeanException, RuntimeOperationsException {
- if (tracing())
- trace("resolveForCacheValue(Descriptor)","Entry");
-
- Object response = null;
- boolean resetValue = false, returnCachedValue = true;
- long currencyPeriod = 0;
-
- if (descr == null) {
- if (tracing())
- trace("resolveForCacheValue(Descriptor)",
- "Input Descriptor is null");
- return response;
- }
-
- if (tracing())
- trace("resolveForCacheValue(Descriptor)","descriptor is " +
- descr.toString());
-
- final Descriptor mmbDescr = modelMBeanInfo.getMBeanDescriptor();
- if (mmbDescr == null) {
- if (tracing())
- trace("resolveForCacheValue(Descriptor)",
- "MBean Descriptor is null");
- //return response;
- }
-
- Object objExpTime = descr.getFieldValue("currencyTimeLimit");
-
- String expTime;
- if (objExpTime != null) {
- expTime = objExpTime.toString();
- } else {
- expTime = null;
- }
-
- if ((expTime == null) && (mmbDescr != null)) {
- objExpTime = mmbDescr.getFieldValue("currencyTimeLimit");
- if (objExpTime != null) {
- expTime = objExpTime.toString();
- } else {
- expTime = null;
- }
- }
-
- if (expTime != null) {
- if (tracing())
- trace("resolveForCacheValue(Descriptor)",
- "currencyTimeLimit: " + expTime);
-
- // convert seconds to milliseconds for time comparison
- currencyPeriod = ((new Long(expTime)).longValue()) * 1000;
- if (currencyPeriod < 0) {
- /* if currencyTimeLimit is -1 then value is never cached */
- returnCachedValue = false;
- resetValue = true;
- if (tracing())
- trace("resolveForCacheValue(Descriptor)",
- currencyPeriod + ": never Cached");
- } else if (currencyPeriod == 0) {
- /* if currencyTimeLimit is 0 then value is always cached */
- returnCachedValue = true;
- resetValue = false;
- if (tracing())
- trace("resolveForCacheValue(Descriptor)",
- "always valid Cache");
- } else {
- Object objtStamp =
- descr.getFieldValue("lastUpdatedTimeStamp");
-
- String tStamp;
- if (objtStamp != null) tStamp = objtStamp.toString();
- else tStamp = null;
-
- if (tracing())
- trace("resolveForCacheValue(Descriptor)",
- "lastUpdatedTimeStamp: " + tStamp);
-
- if (tStamp == null)
- tStamp = "0";
-
- long lastTime = (new Long(tStamp)).longValue();
-
- if (tracing())
- trace("resolveForCacheValue(Descriptor)",
- " currencyPeriod:" + currencyPeriod +
- " lastUpdatedTimeStamp:" + lastTime);
-
- long now = (new Date()).getTime();
-
- if (now < (lastTime + currencyPeriod)) {
- returnCachedValue = true;
- resetValue = false;
- if (tracing())
- trace("resolveForCacheValue(Descriptor)",
- " timed valid Cache for " + now + " < " +
- (lastTime + currencyPeriod));
- } else { /* value is expired */
- returnCachedValue = false;
- resetValue = true;
- if (tracing())
- trace("resolveForCacheValue(Descriptor)",
- "timed expired cache for " + now + " > " +
- (lastTime + currencyPeriod));
- }
- }
-
- if (tracing())
- trace("resolveForCacheValue(Descriptor)",
- "returnCachedValue:" + returnCachedValue +
- " resetValue: " + resetValue);
-
- if (returnCachedValue == true) {
- Object currValue = descr.getFieldValue("value");
- if (currValue != null) {
- /* error/validity check return value here */
- response = currValue;
- /* need to cast string cached value to type */
- if (tracing())
- trace("resolveForCacheValue(Descriptor)",
- "valid Cache value: " + currValue);
-
- } else {
- response = null;
- if (tracing())
- trace("resolveForCacheValue(Descriptor)",
- "no Cached value");
- }
- }
-
- if (resetValue == true) {
- /* value is not current, so remove it */
- descr.removeField("lastUpdatedTimeStamp");
- descr.removeField("value");
- response = null;
- modelMBeanInfo.setDescriptor(descr,null);
- if (tracing())
- trace("resolveForCacheValue(Descriptor)",
- "reset cached value to null");
- }
- }
-
- if (tracing())
- trace("resolveForCache(Descriptor)","Exit");
-
- return response;
- }
-
- /**
- * Returns the attributes, operations, constructors and notifications
- * that this RequiredModelMBean exposes for management.
- *
- * @return An instance of ModelMBeanInfo allowing retrieval all
- * attributes, operations, and Notifications of this MBean.
- *
- **/
- public MBeanInfo getMBeanInfo() {
-
- if (tracing())
- trace("getMBeanInfo()","Entry and Exit");
-
- if (modelMBeanInfo == null) {
- if (tracing())
- trace("getMBeanInfo()","modelMBeanInfo is null");
- modelMBeanInfo = createDefaultModelMBeanInfo();
- //return new ModelMBeanInfo(" ", "", null, null, null, null);
- }
-
- if (tracing()) {
- trace("getMBeanInfo()","ModelMBeanInfo is " +
- modelMBeanInfo.getClassName() + " for " +
- modelMBeanInfo.getDescription());
- trace("getMBeanInfo()",printModelMBeanInfo(modelMBeanInfo));
- }
-
- return((MBeanInfo) ((ModelMBeanInfo)modelMBeanInfo).clone());
- }
-
- private String printModelMBeanInfo(ModelMBeanInfo info) {
- final StringBuffer retStr = new StringBuffer();
- if (info == null) {
- if (tracing())
- trace("printModelMBeanInfo(ModelMBeanInfo)",
- "ModelMBeanInfo to print is null, " +
- "printing local ModelMBeanInfo");
- info = modelMBeanInfo;
- }
-
- retStr.append("\nMBeanInfo for ModelMBean is:");
- retStr.append("\nCLASSNAME: \t"+ info.getClassName());
- retStr.append("\nDESCRIPTION: \t"+ info.getDescription());
-
-
- try {
- retStr.append("\nMBEAN DESCRIPTOR: \t"+
- info.getMBeanDescriptor());
- } catch (Exception e) {
- retStr.append("\nMBEAN DESCRIPTOR: \t" + " is invalid");
- }
-
- retStr.append("\nATTRIBUTES");
-
- final MBeanAttributeInfo[] attrInfo = info.getAttributes();
- if ((attrInfo != null) && (attrInfo.length>0)) {
- for (int i=0; i<attrInfo.length; i++) {
- final ModelMBeanAttributeInfo attInfo =
- (ModelMBeanAttributeInfo)attrInfo[i];
- retStr.append(" ** NAME: \t"+ attInfo.getName());
- retStr.append(" DESCR: \t"+ attInfo.getDescription());
- retStr.append(" TYPE: \t"+ attInfo.getType() +
- " READ: \t"+ attInfo.isReadable() +
- " WRITE: \t"+ attInfo.isWritable());
- retStr.append(" DESCRIPTOR: " +
- attInfo.getDescriptor().toString());
- }
- } else {
- retStr.append(" ** No attributes **");
- }
-
- retStr.append("\nCONSTRUCTORS");
- final MBeanConstructorInfo[] constrInfo = info.getConstructors();
- if ((constrInfo != null) && (constrInfo.length > 0 )) {
- for (int i=0; i<constrInfo.length; i++) {
- final ModelMBeanConstructorInfo ctorInfo =
- (ModelMBeanConstructorInfo)constrInfo[i];
- retStr.append(" ** NAME: \t"+ ctorInfo.getName());
- retStr.append(" DESCR: \t"+
- ctorInfo.getDescription());
- retStr.append(" PARAM: \t"+
- ctorInfo.getSignature().length +
- " parameter(s)");
- retStr.append(" DESCRIPTOR: " +
- ctorInfo.getDescriptor().toString());
- }
- } else {
- retStr.append(" ** No Constructors **");
- }
-
- retStr.append("\nOPERATIONS");
- final MBeanOperationInfo[] opsInfo = info.getOperations();
- if ((opsInfo != null) && (opsInfo.length>0)) {
- for (int i=0; i<opsInfo.length; i++) {
- final ModelMBeanOperationInfo operInfo =
- (ModelMBeanOperationInfo)opsInfo[i];
- retStr.append(" ** NAME: \t"+ operInfo.getName());
- retStr.append(" DESCR: \t"+ operInfo.getDescription());
- retStr.append(" PARAM: \t"+
- operInfo.getSignature().length +
- " parameter(s)");
- retStr.append(" DESCRIPTOR: " +
- operInfo.getDescriptor().toString());
- }
- } else {
- retStr.append(" ** No operations ** ");
- }
-
- retStr.append("\nNOTIFICATIONS");
-
- MBeanNotificationInfo[] notifInfo = info.getNotifications();
- if ((notifInfo != null) && (notifInfo.length>0)) {
- for (int i=0; i<notifInfo.length; i++) {
- final ModelMBeanNotificationInfo nInfo =
- (ModelMBeanNotificationInfo)notifInfo[i];
- retStr.append(" ** NAME: \t"+ nInfo.getName());
- retStr.append(" DESCR: \t"+ nInfo.getDescription());
- retStr.append(" DESCRIPTOR: " +
- nInfo.getDescriptor().toString());
- }
- } else {
- retStr.append(" ** No notifications **");
- }
-
- retStr.append(" ** ModelMBean: End of MBeanInfo ** ");
-
- return retStr.toString();
- }
-
- private void echo(String txt) {
- trace("echo(txt)",txt);
- }
-
-
- /**
- * Invokes a method on or through a RequiredModelMBean and returns
- * the result of the method execution.
- * <P>
- * If the given method to be invoked, together with the provided
- * signature, matches one of RequiredModelMbean
- * accessible methods, this one will be call. Otherwise the call to
- * the given method will be tried on the managed resource.
- * <P>
- * The last value returned by an operation may be cached in
- * the operation's descriptor which
- * is in the ModelMBeanOperationInfo's descriptor.
- * The valid value will be in the 'value' field if there is one.
- * If the 'currencyTimeLimit' field in the descriptor is:
- * <UL>
- * <LI><b><0</b> Then the value is not cached and is never valid.
- * The operation method is invoked.
- * The 'value' and 'lastUpdatedTimeStamp' fields are cleared.</LI>
- * <LI><b>=0</b> Then the value is always cached and always valid.
- * The 'value' field is returned. If there is no 'value' field
- * then the operation method is invoked for the attribute.
- * The 'lastUpdatedTimeStamp' field and `value' fields are set to
- * the operation's return value and the current time stamp.</LI>
- * <LI><b>>0</b> Represents the number of seconds that the 'value'
- * field is valid.
- * The 'value' field is no longer valid when
- * 'lastUpdatedTimeStamp' + 'currencyTimeLimit' > Now.
- * <UL>
- * <LI>When 'value' is valid, 'value' is returned.</LI>
- * <LI>When 'value' is no longer valid then the operation
- * method is invoked. The 'lastUpdatedTimeStamp' field
- * and `value' fields are updated.</lI>
- * </UL>
- * </LI>
- * </UL>
- *
- * <p><b>Note:</b> because of inconsistencies in previous versions of
- * this specification, it is recommended not to use negative or zero
- * values for <code>currencyTimeLimit</code>. To indicate that a
- * cached value is never valid, omit the
- * <code>currencyTimeLimit</code> field. To indicate that it is
- * always valid, use a very large number for this field.</p>
- *
- * @param opName The name of the method to be invoked. The
- * name can be the fully qualified method name including the
- * classname, or just the method name if the classname is
- * defined in the 'class' field of the operation descriptor.
- * @param opArgs An array containing the parameters to be set
- * when the operation is invoked
- * @param sig An array containing the signature of the
- * operation. The class objects will be loaded using the same
- * class loader as the one used for loading the MBean on which
- * the operation was invoked.
- *
- * @return The object returned by the method, which represents the
- * result of invoking the method on the specified managed resource.
- *
- * @exception MBeanException Wraps one of the following Exceptions:
- * <UL>
- * <LI> An Exception thrown by the managed object's invoked method.</LI>
- * <LI> {@link ServiceNotFoundException}: No ModelMBeanOperationInfo or
- * no descriptor defined for the specified operation or the managed
- * resource is null.</LI>
- * <LI> {@link InvalidTargetObjectTypeException}: The 'targetType'
- * field value is not 'objectReference'.</LI>
- * </UL>
- * @exception ReflectionException Wraps an {@link java.lang.Exception}
- * thrown while trying to invoke the method.
- * @exception RuntimeOperationsException Wraps an
- * {@link IllegalArgumentException} Method name is null.
- *
- **/
- /*
- The requirement to be able to invoke methods on the
- RequiredModelMBean class itself makes this method considerably
- more complicated than it might otherwise be. Note that, unlike
- earlier versions, we do not allow you to invoke such methods if
- they are not explicitly mentioned in the ModelMBeanInfo. Doing
- so was potentially a security problem, and certainly very
- surprising.
-
- We do not look for the method in the RequiredModelMBean class
- itself if:
- (a) there is a "targetObject" field in the Descriptor for the
- operation; or
- (b) there is a "class" field in the Descriptor for the operation
- and the named class is not RequiredModelMBean or one of its
- superinterfaces; or
- (c) the name of the operation is not the name of a method in
- RequiredModelMBean (this is just an optimization).
-
- In cases (a) and (b), if you have gone to the trouble of adding
- those fields specifically for this operation then presumably you
- do not want RequiredModelMBean's methods to be called.
-
- We have to pay attention to class loading issues. If the
- "class" field is present, the named class has to be resolved
- relative to RequiredModelMBean's class loader to test the
- condition (b) above, and relative to the managed resource's
- class loader to ensure that the managed resource is in fact of
- the named class (or a subclass). The class names in the sig
- array likewise have to be resolved, first against
- RequiredModelMBean's class loader, then against the managed
- resource's class loader. There is no point in using any other
- loader because when we call Method.invoke we must call it on
- a Method that is implemented by the target object.
- */
- public Object invoke(String opName, Object[] opArgs, String[] sig)
- throws MBeanException, ReflectionException {
- final boolean tracing = tracing();
-
- if (tracing)
- trace("invoke(String, Object[], String[])","Entry");
-
- if (opName == null) {
- final RuntimeException x =
- new IllegalArgumentException("Method name must not be null");
- throw new RuntimeOperationsException(x,
- "An exception occured while trying to " +
- "invoke a method on a RequiredModelMBean");
- }
-
- String opClassName = null;
- String opMethodName;
-
- // Parse for class name and method
- int opSplitter = opName.lastIndexOf(".");
- if (opSplitter > 0) {
- opClassName = opName.substring(0,opSplitter);
- opMethodName = opName.substring(opSplitter+1);
- } else
- opMethodName = opName;
-
- /* Ignore anything after a left paren. We keep this for
- compatibility but it isn't specified. */
- opSplitter = opMethodName.indexOf("(");
- if (opSplitter > 0)
- opMethodName = opMethodName.substring(0,opSplitter);
-
- if (tracing)
- trace("invoke(String, Object[], String[])",
- "Finding operation " + opName + " as " + opMethodName);
-
- ModelMBeanOperationInfo opInfo =
- modelMBeanInfo.getOperation(opMethodName);
- if (opInfo == null) {
- final String msg =
- "Operation " + opName + " not in ModelMBeanInfo";
- throw new MBeanException(new ServiceNotFoundException(msg), msg);
- }
-
- final Descriptor opDescr = opInfo.getDescriptor();
- if (opDescr == null) {
- final String msg = "Operation descriptor null";
- throw new MBeanException(new ServiceNotFoundException(msg), msg);
- }
-
- final Object cached = resolveForCacheValue(opDescr);
- if (cached != null) {
- if (tracing)
- trace("invoke(String, Object[], String[])",
- "Returning cached value");
- return cached;
- }
-
- if (opClassName == null)
- opClassName = (String) opDescr.getFieldValue("class");
- // may still be null now
-
- opMethodName = (String) opDescr.getFieldValue("name");
- if (opMethodName == null) {
- final String msg =
- "Method descriptor must include `name' field";
- throw new MBeanException(new ServiceNotFoundException(msg), msg);
- }
-
- final String targetTypeField = (String)
- opDescr.getFieldValue("targetType");
- if (targetTypeField != null
- && !targetTypeField.equalsIgnoreCase("objectReference")) {
- final String msg =
- "Target type must be objectReference: " + targetTypeField;
- throw new MBeanException(new InvalidTargetObjectTypeException(msg),
- msg);
- }
-
- final Object targetObjectField = opDescr.getFieldValue("targetObject");
- if (tracing && targetObjectField != null)
- trace("invoke(String, Object[], String[])",
- "Found target object in descriptor");
-
- /* Now look for the method, either in RequiredModelMBean itself
- or in the target object. Set "method" and "targetObject"
- appropriately. */
- Method method;
- Object targetObject;
-
- method = findRMMBMethod(opMethodName, targetObjectField,
- opClassName, sig);
-
- if (method != null)
- targetObject = this;
- else {
- if (tracing)
- trace("invoke(String, Object[], String[])",
- "looking for method in managedResource class");
- if (targetObjectField != null)
- targetObject = targetObjectField;
- else {
- targetObject = managedResource;
- if (targetObject == null) {
- final String msg =
- "managedResource for invoke " + opName +
- " is null";
- Exception snfe = new ServiceNotFoundException(msg);
- throw new MBeanException(snfe);
- }
- }
-
- final Class targetClass;
-
- if (opClassName != null) {
- try {
- final ClassLoader targetClassLoader =
- targetObject.getClass().getClassLoader();
- targetClass = Class.forName(opClassName, false,
- targetClassLoader);
- } catch (ClassNotFoundException e) {
- final String msg =
- "class for invoke " + opName + " not found";
- throw new ReflectionException(e, msg);
- }
- } else
- targetClass = targetObject.getClass();
-
- method = resolveMethod(targetClass, opMethodName, sig);
- }
-
- if (tracing)
- trace("invoke(String, Object[], String[])",
- "found " + opMethodName + ", now invoking");
-
- final Object result =
- invokeMethod(opName, method, targetObject, opArgs);
-
- if (tracing)
- trace("invoke(String, Object[], String[])",
- "successfully invoked method");
-
- if (result != null)
- cacheResult(opInfo, opDescr, result);
-
- return result;
- }
-
- private static Method resolveMethod(Class targetClass,
- String opMethodName,
- String[] sig)
- throws ReflectionException {
- final boolean tracing = tracing();
-
- if (tracing)
- trace("resolveMethod",
- "resolving " + targetClass + "." + opMethodName);
-
- final Class[] argClasses;
-
- if (sig == null)
- argClasses = null;
- else {
- final ClassLoader targetClassLoader = targetClass.getClassLoader();
- argClasses = new Class[sig.length];
- for (int i = 0; i < sig.length; i++) {
- if (tracing)
- trace("resolveMethod", "resolve type " + sig[i]);
- argClasses[i] = (Class) primitiveClassMap.get(sig[i]);
- if (argClasses[i] == null) {
- try {
- argClasses[i] =
- Class.forName(sig[i], false, targetClassLoader);
- } catch (ClassNotFoundException e) {
- if (tracing)
- trace("resolveMethod", "class not found");
- final String msg = "Parameter class not found";
- throw new ReflectionException(e, msg);
- }
- }
- }
- }
-
- try {
- return targetClass.getMethod(opMethodName, argClasses);
- } catch (NoSuchMethodException e) {
- final String msg =
- "Target method not found: " + targetClass.getName() + "." +
- opMethodName;
- throw new ReflectionException(e, msg);
- }
- }
-
- /* Map e.g. "int" to int.class. Goodness knows how many time this
- particular wheel has been reinvented. */
- private static final Class[] primitiveClasses = {
- int.class, long.class, boolean.class, double.class,
- float.class, short.class, byte.class, char.class,
- };
- private static final Map/*<String,Class>*/ primitiveClassMap =
- new HashMap();
- static {
- for (int i = 0; i < primitiveClasses.length; i++) {
- final Class c = primitiveClasses[i];
- primitiveClassMap.put(c.getName(), c);
- }
- }
-
- /* Find a method in RequiredModelMBean as determined by the given
- parameters. Return null if there is none, or if the parameters
- exclude using it. Called from invoke. */
- private static Method findRMMBMethod(String opMethodName,
- Object targetObjectField,
- String opClassName,
- String[] sig) {
- if (tracing())
- trace("invoke(String, Object[], String[])",
- "looking for method in RequiredModelMBean class");
- if (!isRMMBMethodName(opMethodName))
- return null;
- if (targetObjectField != null)
- return null;
- final Class rmmbClass = RequiredModelMBean.class;
- final Class targetClass;
- if (opClassName == null)
- targetClass = rmmbClass;
- else {
- try {
- final ClassLoader targetClassLoader =
- rmmbClass.getClassLoader();
- targetClass = Class.forName(opClassName, false,
- targetClassLoader);
- if (!rmmbClass.isAssignableFrom(targetClass))
- return null;
- } catch (ClassNotFoundException e) {
- return null;
- }
- }
- try {
- return resolveMethod(targetClass, opMethodName, sig);
- } catch (ReflectionException e) {
- return null;
- }
- }
-
- /*
- * Invoke the given method, and throw the somewhat unpredictable
- * appropriate exception if the method itself gets an exception.
- */
- private Object invokeMethod(String opName, Method method,
- Object targetObject, Object[] opArgs)
- throws MBeanException, ReflectionException {
- try {
- return method.invoke(targetObject, opArgs);
- } catch (RuntimeErrorException ree) {
- throw new RuntimeOperationsException(ree,
- "RuntimeException occured in RequiredModelMBean "+
- "while trying to invoke operation " + opName);
- } catch (RuntimeException re) {
- throw new RuntimeOperationsException(re,
- "RuntimeException occured in RequiredModelMBean "+
- "while trying to invoke operation " + opName);
- } catch (IllegalAccessException iae) {
- throw new ReflectionException(iae,
- "IllegalAccessException occured in " +
- "RequiredModelMBean while trying to " +
- "invoke operation " + opName);
- } catch (InvocationTargetException ite) {
- Throwable mmbTargEx = ite.getTargetException();
- if (mmbTargEx instanceof RuntimeException) {
- throw new MBeanException ((RuntimeException)mmbTargEx,
- "RuntimeException thrown in RequiredModelMBean "+
- "while trying to invoke operation " + opName);
- } else if (mmbTargEx instanceof Error) {
- throw new RuntimeErrorException((Error)mmbTargEx,
- "Error occured in RequiredModelMBean while trying "+
- "to invoke operation " + opName);
- } else if (mmbTargEx instanceof ReflectionException) {
- throw (ReflectionException) mmbTargEx;
- } else {
- throw new MBeanException ((Exception)mmbTargEx,
- "Exception thrown in RequiredModelMBean "+
- "while trying to invoke operation " + opName);
- }
- } catch (Error err) {
- throw new RuntimeErrorException(err,
- "Error occured in RequiredModelMBean while trying "+
- "to invoke operation " + opName);
- } catch (Exception e) {
- throw new ReflectionException(e,
- "Exception occured in RequiredModelMBean while " +
- "trying to invoke operation " + opName);
- }
- }
-
- /*
- * Cache the result of an operation in the descriptor, if that is
- * called for by the descriptor's configuration. Note that we
- * don't remember operation parameters when caching the result, so
- * this is unlikely to be useful if there are any.
- */
- private void cacheResult(ModelMBeanOperationInfo opInfo,
- Descriptor opDescr, Object result)
- throws MBeanException {
-
- Descriptor mmbDesc =
- modelMBeanInfo.getMBeanDescriptor();
-
- Object objctl =
- opDescr.getFieldValue("currencyTimeLimit");
- String ctl;
- if (objctl != null) {
- ctl = objctl.toString();
- } else {
- ctl = null;
- }
- if ((ctl == null) && (mmbDesc != null)) {
- objctl =
- mmbDesc.getFieldValue("currencyTimeLimit");
- if (objctl != null) {
- ctl = objctl.toString();
- } else {
- ctl = null;
- }
- }
- if ((ctl != null) && !(ctl.equals("-1"))) {
- opDescr.setField("value", result);
- opDescr.setField("lastUpdatedTimeStamp",
- (new Long((new Date()).getTime())).toString());
-
- modelMBeanInfo.setDescriptor(opDescr,
- "operation");
- if (tracing()) {
- trace("invoke(String,Object[],Object[])",
- "new descriptor is " +
- opDescr.toString());
- }
- }
- }
-
- /*
- * Determine whether the given name is the name of a public method
- * in this class. This is only an optimization: it prevents us
- * from trying to do argument type lookups and reflection on a
- * method that will obviously fail because it has the wrong name.
- *
- * The first time this method is called we do the reflection, and
- * every other time we reuse the remembered values.
- *
- * It's conceivable that the (possibly malicious) first caller
- * doesn't have the required permissions to do reflection, in
- * which case we don't touch anything so as not to interfere
- * with a later permissionful caller.
- */
- private static Set/*<String>*/ rmmbMethodNames;
- private static synchronized boolean isRMMBMethodName(String name) {
- if (rmmbMethodNames == null) {
- try {
- Set names = new HashSet();
- Method[] methods = RequiredModelMBean.class.getMethods();
- for (int i = 0; i < methods.length; i++)
- names.add(methods[i].getName());
- rmmbMethodNames = names;
- } catch (Exception e) {
- return true;
- // This is only an optimization so we'll go on to discover
- // whether the name really is an RMMB method.
- }
- }
- return rmmbMethodNames.contains(name);
- }
-
- /**
- * Returns the value of a specific attribute defined for this
- * ModelMBean.
- * The last value returned by an attribute may be cached in the
- * attribute's descriptor.
- * The valid value will be in the 'value' field if there is one.
- * If the 'currencyTimeLimit' field in the descriptor is:
- * <UL>
- * <LI> <b><0</b> Then the value is not cached and is never valid.
- * The getter method is invoked for the attribute.
- * The 'value' and 'lastUpdatedTimeStamp' fields are cleared.</LI>
- * <LI> <b>=0</b> Then the value is always cached and always valid.
- * The 'value' field is returned. If there is no'value' field
- * then the getter method is invoked for the attribute.
- * The 'lastUpdatedTimeStamp' field and `value' fields are set
- * to the attribute's value and the current time stamp.</LI>
- * <LI> <b>>0</b> Represents the number of seconds that the 'value'
- * field is valid.
- * The 'value' field is no longer valid when
- * 'lastUpdatedTimeStamp' + 'currencyTimeLimit' > Now.
- * <UL>
- * <LI>When 'value' is valid, 'value' is returned.</LI>
- * <LI>When 'value' is no longer valid then the getter
- * method is invoked for the attribute.
- * The 'lastUpdatedTimeStamp' field and `value' fields
- * are updated.</LI>
- * </UL></LI>
- * </UL>
- *
- * <p><b>Note:</b> because of inconsistencies in previous versions of
- * this specification, it is recommended not to use negative or zero
- * values for <code>currencyTimeLimit</code>. To indicate that a
- * cached value is never valid, omit the
- * <code>currencyTimeLimit</code> field. To indicate that it is
- * always valid, use a very large number for this field.</p>
- *
- * <p>If the 'getMethod' field contains the name of a valid
- * operation descriptor, then the method described by the
- * operation descriptor is executed. The response from the
- * method is returned as the value of the attribute. If the
- * operation fails or the returned value is not of the same
- * type as the attribute, an exception will be thrown. If no
- * 'getMethod' field is defined then the default value of the
- * attribute is returned. In this implementation, in every
- * case where the getMethod needs to be called, because the
- * method is invoked through the standard "invoke" method and
- * thus needs operationInfo, an operation must be specified
- * for that getMethod so that the invocation works correctly.</p>
- *
- * @param attrName A String specifying the name of the
- * attribute to be retrieved. It must match the name of a
- * ModelMBeanAttributeInfo.
- *
- * @return The value of the retrieved attribute from the
- * descriptor 'value' field or from the invocation of the
- * operation in the 'getMethod' field of the descriptor.
- *
- * @exception AttributeNotFoundException The specified attribute is
- * not accessible in the MBean.
- * The following cases may result in an AttributeNotFoundException:
- * <UL>
- * <LI> No ModelMBeanInfo was found for the Model MBean.</LI>
- * <LI> No ModelMBeanAttributeInfo was found for the specified
- * attribute name.</LI>
- * <LI> The ModelMBeanAttributeInfo isReadable method returns
- * 'false'.</LI>
- * </UL>
- * @exception MBeanException Wraps one of the following Exceptions:
- * <UL>
- * <LI> {@link InvalidAttributeValueException}: A wrong value type
- * was received from the attribute's getter method or
- * no 'getMethod' field defined in the descriptor for
- * the attribute and no default value exists.</LI>
- * <LI> {@link ServiceNotFoundException}: No
- * ModelMBeanOperationInfo defined for the attribute's
- * getter method or no descriptor associated with the
- * ModelMBeanOperationInfo or the managed resource is
- * null.</LI>
- * <LI> {@link InvalidTargetObjectTypeException} The 'targetType'
- * field value is not 'objectReference'.</LI>
- * <LI> An Exception thrown by the managed object's getter.</LI>
- * </UL>
- * @exception ReflectionException Wraps an {@link java.lang.Exception}
- * thrown while trying to invoke the getter.
- * @exception RuntimeOperationsException Wraps an
- * {@link IllegalArgumentException}: The attribute name in
- * parameter is null.
- *
- * @see #setAttribute(javax.management.Attribute)
- **/
- public Object getAttribute(String attrName)
- throws AttributeNotFoundException, MBeanException,
- ReflectionException {
- if (attrName == null)
- throw new RuntimeOperationsException(new
- IllegalArgumentException("attributeName must not be null"),
- "Exception occured trying to get attribute of a " +
- "RequiredModelMBean");
-
- if (tracing())
- trace("getAttribute(String)","Entry with" + attrName);
-
- /* Check attributeDescriptor for getMethod */
- ModelMBeanAttributeInfo attrInfo=null;
- Descriptor attrDescr=null;
- Object response = null;
-
- try {
- if (modelMBeanInfo == null)
- throw new AttributeNotFoundException(
- "getAttribute failed: ModelMBeanInfo not found for "+
- attrName);
-
- attrInfo = modelMBeanInfo.getAttribute(attrName);
- Descriptor mmbDesc = modelMBeanInfo.getMBeanDescriptor();
-
- if (attrInfo == null)
- throw new AttributeNotFoundException("getAttribute failed:"+
- " ModelMBeanAttributeInfo not found for " + attrName);
-
- attrDescr = attrInfo.getDescriptor();
- if (attrDescr != null) {
- if (!attrInfo.isReadable())
- throw new AttributeNotFoundException(
- "getAttribute failed: " + attrName +
- " is not readable ");
-
- response = resolveForCacheValue(attrDescr);
-
- /* return current cached value */
- if (tracing())
- trace("getAttribute(String)","*** cached value is " +
- response);
-
- if (response == null) {
- /* no cached value, run getMethod */
- if (tracing())
- trace("getAttribute(String)",
- "**** cached value is null" +
- " - " + "getting getMethod");
- String attrGetMethod =
- (String)(attrDescr.getFieldValue("getMethod"));
-
- if (attrGetMethod != null) {
- /* run method from operations descriptor */
- if (tracing())
- trace("getAttribute(String)",
- "invoking a getMethod for " + attrName);
-
- Object getResponse =
- invoke(attrGetMethod, new Object[] {},
- new String[] {});
-
- if (getResponse != null) {
- // error/validity check return value here
- if (tracing())
- trace("getAttribute(String)",
- "got a non-null response from getMethod\n");
-
- response = getResponse;
-
- // change cached value in attribute descriptor
- Object objctl =
- attrDescr.getFieldValue("currencyTimeLimit");
-
- String ctl;
- if (objctl != null) ctl = objctl.toString();
- else ctl = null;
-
- if ((ctl == null) && (mmbDesc != null)) {
- objctl = mmbDesc.
- getFieldValue("currencyTimeLimit");
- if (objctl != null) ctl = objctl.toString();
- else ctl = null;
- }
-
- if ((ctl != null) && !(ctl.equals("-1"))) {
- if (tracing())
- trace("getAttribute(String)",
- "setting cached value and "+
- "lastUpdatedTime in descriptor");
-
- attrDescr.setField("value", response);
- final String stamp =
- (new Long((new Date()).getTime())).
- toString();
- attrDescr.setField("lastUpdatedTimeStamp",
- stamp);
- attrInfo.setDescriptor(attrDescr);
- modelMBeanInfo.setDescriptor(attrDescr,
- "attribute");
- if (tracing()) {
- trace("getAttribute(String)",
- "new descriptor is " +
- attrDescr.toString());
- trace("getAttribute(String)","local: "+
- "AttributeInfo descriptor is "+
- attrInfo.getDescriptor().
- toString());
- final String attStr = modelMBeanInfo.
- getDescriptor(attrName,"attribute").
- toString();
- trace("getAttribute(String)",
- "modelMBeanInfo: " +
- "AttributeInfo descriptor is " +
- attStr);
- }
- }
- } else {
- // response was invalid or really returned null
- if (tracing())
- trace("getAttribute(String)",
- "got a null response from getMethod\n");
- response = null;
- }
- } else {
- // not getMethod so return descriptor (default) value
- String qualifier="";
- response = attrDescr.getFieldValue("value");
- if (response == null) {
- qualifier="default ";
- response = attrDescr.getFieldValue("default");
- }
- if (tracing())
- trace("getAttribute(String)",
- "could not find getMethod for " +
- attrName + ", returning descriptor " +
- qualifier + "value");
- // !! cast response to right class
- }
- }
-
- // make sure response class matches type field
- String respType = attrInfo.getType();
- if (response != null) {
- String responseClass = response.getClass().getName();
-
- if (! respType.equals(responseClass)) {
- // Revisit !! : this should be stacically initialized !
- final String[] primitiveTypes = new String[] {
- Boolean.TYPE.getName(),
- Byte.TYPE.getName(),
- Character.TYPE.getName(),
- Short.TYPE.getName(),
- Integer.TYPE.getName(),
- Long.TYPE.getName(),
- Float.TYPE.getName(),
- Double.TYPE.getName(),
- Void.TYPE.getName()};
- final String[] primitiveWrappers = new String[] {
- Boolean.class.getName(),
- Byte.class.getName(),
- Character.class.getName(),
- Short.class.getName(),
- Integer.class.getName(),
- Long.class.getName(),
- Float.class.getName(),
- Double.class.getName(),
- Void.class.getName()};
-
- // unequality may come from primitive/wrapper class specs
- boolean correspondingTypes = false;
- for (int i = 0; i <= 8; i++) {
- if ((respType.equals(primitiveTypes[i]))&&
- (responseClass.equals(primitiveWrappers[i]))) {
- correspondingTypes = true;
- break;
- }
- }
-
- // did we really get the expected response type ?
- if (! correspondingTypes) {
- if (tracing())
- trace("getAttribute(String)",
- "wrong response type '" + respType + "'" );
-
- // throw exception, didn't get back right attribute type
- throw new MBeanException(new
- InvalidAttributeValueException("Wrong value type received for get attribute"),
- "An exception occured while trying to get an "+
- "attribute value through a RequiredModelMBean");
- }
- }
- }
-
- } else {
- if (tracing())
- trace("getAttribute(String)","getMethod failed " +
- attrName + " not in attributeDescriptor\n");
- throw new MBeanException(new
- InvalidAttributeValueException(
- "Unable to resolve attribute value, " +
- "no getMethod defined in descriptor for attribute"),
- "An exception occured while trying to get an "+
- "attribute value through a RequiredModelMBean");
- }
-
- } catch (MBeanException mbe) {
- throw mbe;
- } catch (AttributeNotFoundException t) {
- throw t;
- } catch (Exception e) {
- if (tracing())
- trace("getAttribute(String)","getMethod failed with " +
- e.getMessage() + " exception type " +
- (e.getClass()).toString());
- throw new MBeanException(e,"An exception occured while trying "+
- "to get an attribute value: " + e.getMessage());
- }
-
- if (tracing())
- trace("getAttribute(String)","Exit");
-
- return response;
- }
-
- /**
- * Returns the values of several attributes in the ModelMBean.
- * Executes a getAttribute for each attribute name in the
- * attrNames array passed in.
- *
- * @param attrNames A String array of names of the attributes
- * to be retrieved.
- *
- * @return The array of the retrieved attributes.
- *
- * @exception RuntimeOperationsException Wraps an
- * {@link IllegalArgumentException}: The object name in parameter is
- * null or attributes in parameter is null.
- *
- * @see #setAttributes(javax.management.AttributeList)
- */
- public AttributeList getAttributes(String[] attrNames) {
- if (tracing())
- trace("getAttributes(String[])","Entry");
-
- AttributeList responseList = null;
- if (attrNames == null)
- throw new RuntimeOperationsException(new
- IllegalArgumentException("attributeNames must not be null"),
- "Exception occured trying to get attributes of a "+
- "RequiredModelMBean");
-
- responseList = new AttributeList();
- for (int i = 0; i < attrNames.length; i++) {
- try {
- responseList.add(new Attribute(attrNames[i],
- getAttribute(attrNames[i])));
- } catch (Exception e) {
- // eat exceptions because interface doesn't have an
- // exception on it
- error("getAttributes(String[])","Failed to get \"" +
- attrNames[i] + "\": " + e);
- traceX("getAttributes(String[])",e);
- }
- }
-
- if (tracing())
- trace("getAttributes(String[])","Exit");
-
- return responseList;
- }
-
- /**
- * Sets the value of a specific attribute of a named ModelMBean.
- *
- * If the 'setMethod' field of the attribute's descriptor
- * contains the name of a valid operation descriptor, then the
- * method described by the operation descriptor is executed.
- * In this implementation, the operation descriptor must be specified
- * correctly and assigned to the modelMBeanInfo so that the 'setMethod'
- * works correctly.
- * The response from the method is set as the value of the attribute
- * in the descriptor.
- *
- * <p>If currencyTimeLimit is > 0, then the new value for the
- * attribute is cached in the attribute descriptor's
- * 'value' field and the 'lastUpdatedTimeStamp' field is set to
- * the current time stamp.
- *
- * <p>If the persist field of the attribute's descriptor is not null
- * then Persistence policy from the attribute descriptor is used to
- * guide storing the attribute in a persistent store.
- * <br>Store the MBean if 'persistPolicy' field is:
- * <UL>
- * <Li> != "never"</Li>
- * <Li> = "always"</Li>
- * <Li> = "onUpdate"</Li>
- * <Li> = "onTimer" and now > 'lastPersistTime' + 'persistPeriod'</Li>
- * <Li> = "NoMoreOftenThan" and now > 'lastPersistTime' +
- * 'persistPeriod'</Li>
- * </UL>
- * Do not store the MBean if 'persistPolicy' field is:
- * <UL>
- * <Li> = "never"</Li>
- * <Li> = "onTimer" && now < 'lastPersistTime' + 'persistPeriod'</Li>
- * <Li> = "NoMoreOftenThan" and now < 'lastPersistTime' +
- * 'persistPeriod'</Li>
- * </UL>
- *
- * <p>The ModelMBeanInfo of the Model MBean is stored in a file.
- *
- * @param attribute The Attribute instance containing the name of
- * the attribute to be set and the value it is to be set to.
- *
- *
- * @exception AttributeNotFoundException The specified attribute is
- * not accessible in the MBean.
- * <br>The following cases may result in an AttributeNotFoundException:
- * <UL>
- * <LI> No ModelMBeanAttributeInfo is found for the specified
- * attribute.</LI>
- * <LI> The ModelMBeanAttributeInfo's isWritable method returns
- * 'false'.</LI>
- * </UL>
- * @exception InvalidAttributeValueException No descriptor is defined
- * for the specified attribute.
- * @exception MBeanException Wraps one of the following Exceptions:
- * <UL>
- * <LI> An Exception thrown by the managed object's setter.</LI>
- * <LI> A {@link ServiceNotFoundException} if no `setMethod` field
- * is defined in the descriptor for the attribute or the
- * managed resource is null.</LI>
- * <LI> {@link InvalidTargetObjectTypeException} The 'targetType'
- * field value is not 'objectReference'.</LI>
- * <LI> An Exception thrown by the managed object's getter.</LI>
- * </UL>
- * @exception ReflectionException Wraps an {@link java.lang.Exception}
- * thrown while trying to invoke the setter.
- * @exception RuntimeOperationsException Wraps an
- * {@link IllegalArgumentException}: The attribute in parameter is
- * null.
- *
- * @see #getAttribute(java.lang.String)
- **/
- public void setAttribute(Attribute attribute)
- throws AttributeNotFoundException, InvalidAttributeValueException,
- MBeanException, ReflectionException {
-
- if (tracing())
- trace("setAttribute()","Entry");
-
- if (attribute == null)
- throw new RuntimeOperationsException(new
- IllegalArgumentException("attribute must not be null"),
- "Exception occured trying to set an attribute of a "+
- "RequiredModelMBean");
-
- /* run setMethod if there is one */
- /* return cached value if its current */
- /* set cached value in descriptor and set date/time */
- /* send attribute change Notification */
- /* check persistence policy and persist if need be */
- String attrName = attribute.getName();
- Object attrValue = attribute.getValue();
- boolean updateDescriptor = false;
-
- ModelMBeanAttributeInfo attrInfo =
- modelMBeanInfo.getAttribute(attrName);
-
- if (attrInfo == null)
- throw new AttributeNotFoundException("setAttribute failed: " +
- attrName + " is not found ");
-
- Descriptor mmbDesc = modelMBeanInfo.getMBeanDescriptor();
- Descriptor attrDescr = attrInfo.getDescriptor();
-
- if (attrDescr != null) {
- if (!attrInfo.isWritable())
- throw new AttributeNotFoundException("setAttribute failed: "
- + attrName + " is not writable ");
-
- Object setResponse = null;
- String attrSetMethod = (String)
- (attrDescr.getFieldValue("setMethod"));
- String attrType = (String)(attrInfo.getType());
- Object currValue = "Unknown";
-
- try {
- currValue = this.getAttribute(attrName);
- } catch (Throwable t) {
- // OK: Default "Unknown" value used for unknown attribute
- }
-
- Attribute oldAttr = new Attribute(attrName, currValue);
-
- /* run method from operations descriptor */
- if (attrSetMethod == null) {
- if (attrValue != null) {
- try {
- final Class clazz = loadClass(attrType);
- if (! clazz.isInstance(attrValue)) throw new
- InvalidAttributeValueException(clazz.getName() +
- " expected, " +
- attrValue.getClass().getName() +
- " received.");
- } catch (ClassNotFoundException x) {
- error("setAttribute","Class " + attrType +
- " for attribute " + attrName + " not found: " +
- x);
- debug("setAttribute",x);
- }
- }
- updateDescriptor = true;
- } else {
- setResponse = invoke(attrSetMethod,
- (new Object[] {attrValue}),
- (new String[] {attrType}) );
- }
-
- /* change cached value */
- Object objctl = attrDescr.getFieldValue("currencyTimeLimit");
- String ctl;
- if (objctl != null) ctl = objctl.toString();
- else ctl = null;
-
- if ((ctl == null) && (mmbDesc != null)) {
- objctl = mmbDesc.getFieldValue("currencyTimeLimit");
- if (objctl != null) ctl = objctl.toString();
- else ctl = null;
- }
-
- final boolean updateCache = ((ctl != null) && !(ctl.equals("-1")));
- if (updateCache || updateDescriptor) {
- if (tracing())
- trace("setAttribute()","setting cached value of " +
- attrName + " to " + attrValue);
-
- attrDescr.setField("value", attrValue);
-
- if (updateCache) {
- final String currtime =
- (new Long((new Date()).getTime())).toString();
-
- attrDescr.setField("lastUpdatedTimeStamp", currtime);
- }
-
- attrInfo.setDescriptor(attrDescr);
-
- modelMBeanInfo.setDescriptor(attrDescr,"attribute");
- if (tracing()) {
- trace("setAttribute()","new descriptor is " +
- attrDescr.toString());
- trace("setAttribute()","AttributeInfo descriptor is " +
- attrInfo.getDescriptor().toString());
- trace("setAttribute()","AttributeInfo descriptor is " +
- modelMBeanInfo.getDescriptor(attrName,"attribute")
- .toString());
- }
-
- }
-
- if (tracing())
- trace("setAttribute()","sending sendAttributeNotification");
-
- sendAttributeChangeNotification(oldAttr,attribute);
-
- } else { // if descriptor ... else no descriptor
-
- if (tracing())
- trace("setAttribute(String)","setMethod failed "+attrName+
- " not in attributeDescriptor\n");
-
- throw new InvalidAttributeValueException(
- "Unable to resolve attribute value, "+
- "no defined in descriptor for attribute");
- } // else no descriptor
-
- if (tracing())
- trace("setAttribute(Attribute)","Exit");
-
- }
-
- /**
- * Sets the values of an array of attributes of this ModelMBean.
- * Executes the setAttribute() method for each attribute in the list.
- *
- * @param attributes A list of attributes: The identification of the
- * attributes to be set and the values they are to be set to.
- *
- * @return The array of attributes that were set, with their new
- * values in Attribute instances.
- *
- * @exception RuntimeOperationsException Wraps an
- * {@link IllegalArgumentException}: The object name in parameter
- * is null or attributes in parameter is null.
- *
- * @see #getAttributes
- **/
- public AttributeList setAttributes(AttributeList attributes) {
-
- if (tracing())
- trace("setAttributes(AttributeList)","Entry");
-
- if (attributes == null)
- throw new RuntimeOperationsException(new
- IllegalArgumentException("attributes must not be null"),
- "Exception occured trying to set attributes of a "+
- "RequiredModelMBean");
-
- final AttributeList responseList = new AttributeList();
-
- // Go through the list of attributes
- for (Iterator i = attributes.iterator(); i.hasNext();) {
- final Attribute attr = (Attribute) i.next();
- try {
- setAttribute(attr);
- responseList.add(attr);
- } catch (Exception excep) {
- responseList.remove(attr);
- }
- }
-
- return responseList;
- }
-
-
-
- private ModelMBeanInfo createDefaultModelMBeanInfo() {
- return(new ModelMBeanInfoSupport((this.getClass().getName()),
- "Default ModelMBean", null, null, null, null));
- }
-
- /*************************************/
- /* NotificationBroadcaster Interface */
- /*************************************/
-
-
- private synchronized void writeToLog(String logFileName,
- String logEntry) throws Exception {
-
- PrintStream logOut = null;
- FileOutputStream fos = null;
- if (tracing()) trace("writeToLog()","Notification Logging to " +
- logFileName + ": " + logEntry);
- if ((logFileName == null) || (logEntry == null)) {
- if (tracing()) trace("writeToLog()","Bad input parameters");
- return;
- }
-
- try {
- fos = new FileOutputStream(logFileName, true);
- logOut = new PrintStream(fos);
- logOut.println(logEntry);
- logOut.close();
- if (tracing()) trace("writeToLog()",
- "Successfully opened log " + logFileName);
- } catch (Exception e) {
- if (tracing())
- trace("writeToLog","Exception " + e.toString() +
- " trying to write to the Notification log file " +
- logFileName);
- throw e;
- }
- }
-
-
- /**
- * Registers an object which implements the NotificationListener
- * interface as a listener. This
- * object's 'handleNotification()' method will be invoked when any
- * notification is issued through or by the ModelMBean. This does
- * not include attributeChangeNotifications. They must be registered
- * for independently.
- *
- * @param listener The listener object which will handles
- * notifications emitted by the registered MBean.
- * @param filter The filter object. If null, no filtering will be
- * performed before handling notifications.
- * @param handback The context to be sent to the listener with
- * the notification when a notification is emitted.
- *
- * @exception IllegalArgumentException The listener cannot be null.
- *
- * @see #removeNotificationListener
- */
- public void addNotificationListener(NotificationListener listener,
- NotificationFilter filter,
- Object handback)
- throws java.lang.IllegalArgumentException {
- final String ftag = "addNotificationListener(NotificationListener, NotificationFilter, Object)";
- if (tracing())
- trace(ftag,"Entry");
-
- if (listener == null)
- throw new IllegalArgumentException(
- "notification listener must not be null");
-
- if (generalBroadcaster == null)
- generalBroadcaster = new NotificationBroadcasterSupport();
-
- generalBroadcaster.addNotificationListener(listener, filter,
- handback);
- if (tracing()) {
- trace(ftag,"NotificationListener added");
- trace(ftag,"Exit");
- }
- }
-
- /**
- * Removes a listener for Notifications from the RequiredModelMBean.
- *
- * @param listener The listener name which was handling notifications
- * emitted by the registered MBean.
- * This method will remove all information related to this listener.
- *
- * @exception ListenerNotFoundException The listener is not registered
- * in the MBean or is null.
- *
- * @see #addNotificationListener
- **/
- public void removeNotificationListener(NotificationListener listener)
- throws ListenerNotFoundException {
- if (listener == null)
- throw new ListenerNotFoundException(
- "Notification listener is null");
-
- final String ftag="removeNotificationListener(NotificationListener)";
-
- if (tracing()) trace(ftag,"Entry");
-
- if (generalBroadcaster == null)
- throw new ListenerNotFoundException(
- "No notification listeners registered");
-
-
- generalBroadcaster.removeNotificationListener(listener);
-
- if (tracing()) trace(ftag,"Exit");
-
- }
-
- public void removeNotificationListener(NotificationListener listener,
- NotificationFilter filter,
- Object handback)
- throws ListenerNotFoundException {
-
- if (listener == null)
- throw new ListenerNotFoundException(
- "Notification listener is null");
-
- final String ftag="removeNotificationListener(NotificationListener, NotificationFilter, Object)";
-
- if (tracing()) trace(ftag,"Entry");
-
- if (generalBroadcaster == null)
- throw new ListenerNotFoundException(
- "No notification listeners registered");
-
-
- generalBroadcaster.removeNotificationListener(listener,filter,
- handback);
-
- if (tracing()) trace(ftag,"Exit");
-
- }
-
- public void sendNotification(Notification ntfyObj)
- throws MBeanException, RuntimeOperationsException {
- if (tracing())
- trace("sendNotification(Notification)","Entry");
-
- if (ntfyObj == null)
- throw new RuntimeOperationsException(new
- IllegalArgumentException("notification object must not be "+
- "null"),
- "Exception occured trying to send a notification from a "+
- "RequiredModelMBean");
-
-
- // log notification if specified in descriptor
- Descriptor ntfyDesc =
- modelMBeanInfo.getDescriptor(ntfyObj.getType(),"notification");
- Descriptor mmbDesc = modelMBeanInfo.getMBeanDescriptor();
-
- if (ntfyDesc != null) {
- String logging = (String) ntfyDesc.getFieldValue("log");
-
- if (logging == null) {
- if (mmbDesc != null)
- logging = (String) mmbDesc.getFieldValue("log");
- }
-
- if ((logging != null) &&
- (logging.equalsIgnoreCase("t") ||
- logging.equalsIgnoreCase("true"))) {
-
- String logfile = (String) ntfyDesc.getFieldValue("logfile");
- if (logfile == null) {
- if (mmbDesc != null)
- logfile = (String)mmbDesc.getFieldValue("logfile");
- }
- if (logfile != null) {
- try {
- writeToLog(logfile,"LogMsg: " +
- ((new Date(ntfyObj.getTimeStamp())).toString())+
- " " + ntfyObj.getType() + " " +
- ntfyObj.getMessage() + " Severity = " +
- (String)ntfyDesc.getFieldValue("severity"));
- } catch (Exception e) {
- error("sendNotification(Notification)",
- "Failed to log " + ntfyObj.getType() +
- " notification: " + e);
- traceX("sendNotification(Notification)",e);
- }
- }
- }
- }
- if (generalBroadcaster != null) {
- generalBroadcaster.sendNotification(ntfyObj);
- }
-
- if (tracing()) trace("sendNotification(Notification)",
- "sendNotification sent provided notification object");
-
- if (tracing())
- trace("sendNotification(Notification)","Exit");
-
- }
-
-
- public void sendNotification(String ntfyText)
- throws MBeanException, RuntimeOperationsException {
- if (tracing())
- trace("sendNotification(String)","Entry");
-
- if (ntfyText == null)
- throw new RuntimeOperationsException(new
- IllegalArgumentException("notification message must not "+
- "be null"),
- "Exception occured trying to send a text notification "+
- "from a ModelMBean");
-
- Notification myNtfyObj = new Notification("jmx.modelmbean.generic",
- this, 1, ntfyText);
- sendNotification(myNtfyObj);
- if (tracing()) trace("sendNotification(string)",
- "Notification sent");
-
- if (tracing())
- trace("sendNotification(String)","Exit");
- }
-
- /**
- * Returns `true' if the notification `notifName' is found
- * in `info'. (bug 4744667)
- **/
- private static final
- boolean hasNotification(final ModelMBeanInfo info,
- final String notifName) {
- try {
- if (info == null) return false;
- else return (info.getNotification(notifName)!=null);
- } catch (MBeanException x) {
- return false;
- } catch (RuntimeOperationsException r) {
- return false;
- }
- }
-
- /**
- * Creates a default ModelMBeanNotificationInfo for GENERIC
- * notification. (bug 4744667)
- **/
- private static final ModelMBeanNotificationInfo makeGenericInfo() {
- final Descriptor genericDescriptor = new DescriptorSupport( new
- String[] {
- "name=GENERIC",
- "descriptorType=notification",
- "log=T",
- "severity=6",
- "displayName=jmx.modelmbean.generic"} );
-
- return new ModelMBeanNotificationInfo(new
- String[] {"jmx.modelmbean.generic"},
- "GENERIC",
- "A text notification has been issued by the managed resource",
- genericDescriptor);
- }
-
- /**
- * Creates a default ModelMBeanNotificationInfo for ATTRIBUTE_CHANGE
- * notification. (bug 4744667)
- **/
- private static final
- ModelMBeanNotificationInfo makeAttributeChangeInfo() {
- final Descriptor attributeDescriptor = new DescriptorSupport(new
- String[] {
- "name=ATTRIBUTE_CHANGE",
- "descriptorType=notification",
- "log=T",
- "severity=6",
- "displayName=jmx.attribute.change"});
-
- return new ModelMBeanNotificationInfo(new
- String[] {"jmx.attribute.change"},
- "ATTRIBUTE_CHANGE",
- "Signifies that an observed MBean attribute value has changed",
- attributeDescriptor );
- }
-
- /**
- * Returns the array of Notifications always generated by the
- * RequiredModelMBean.
- * <P>
- *
- * RequiredModelMBean may always send also two additional notifications:
- * <UL>
- * <LI> One with descriptor <code>"name=GENERIC,descriptorType=notification,log=T,severity=6,displayName=jmx.modelmbean.generic"</code></LI>
- * <LI> Second is a standard attribute change notification
- * with descriptor <code>"name=ATTRIBUTE_CHANGE,descriptorType=notification,log=T,severity=6,displayName=jmx.attribute.change"</code></LI>
- * </UL>
- * Thus these two notifications are always added to those specified
- * by the application.
- *
- * @return MBeanNotificationInfo[]
- *
- **/
- public MBeanNotificationInfo[] getNotificationInfo() {
- if (tracing())
- trace("getNotificationInfo()","Entry");
-
- // Using hasNotification() is not optimal, but shouldn't really
- // matter in this context...
-
- // hasGeneric==true if GENERIC notification is present.
- // (bug 4744667)
- final boolean hasGeneric = hasNotification(modelMBeanInfo,"GENERIC");
-
- // hasAttributeChange==true if ATTRIBUTE_CHANGE notification is
- // present.
- // (bug 4744667)
- final boolean hasAttributeChange =
- hasNotification(modelMBeanInfo,"ATTRIBUTE_CHANGE");
-
- // User supplied list of notification infos.
- //
- final ModelMBeanNotificationInfo[] currInfo =
- (ModelMBeanNotificationInfo[])modelMBeanInfo.getNotifications();
-
- // Length of the returned list of notification infos:
- // length of user suplied list + possibly 1 for GENERIC, +
- // possibly 1 for ATTRIBUTE_CHANGE
- // (bug 4744667)
- final int len = ((currInfo==null?0:currInfo.length) +
- (hasGeneric?0:1) + (hasAttributeChange?0:1));
-
- // Returned list of notification infos:
- //
- final ModelMBeanNotificationInfo[] respInfo =
- new ModelMBeanNotificationInfo[len];
-
- // Preserve previous ordering (JMX 1.1)
- //
-
- // Counter of "standard" notification inserted before user
- // supplied notifications.
- //
- int inserted=0;
- if (!hasGeneric)
- // We need to add description for GENERIC notification
- // (bug 4744667)
- respInfo[inserted++] = makeGenericInfo();
-
-
- if (!hasAttributeChange)
- // We need to add description for ATTRIBUTE_CHANGE notification
- // (bug 4744667)
- respInfo[inserted++] = makeAttributeChangeInfo();
-
- // Now copy user supplied list in returned list.
- //
- final int count = currInfo.length;
- final int offset = inserted;
- for (int j=0; j < count; j++) {
- respInfo[offset+j] = (ModelMBeanNotificationInfo)(currInfo[j]);
- }
-
- if (tracing())
- trace("getNotificationInfo()","Exit");
-
- return respInfo;
- }
-
-
- public void addAttributeChangeNotificationListener(NotificationListener
- inlistener,
- String
- inAttributeName,
- Object inhandback)
- throws MBeanException, RuntimeOperationsException,
- IllegalArgumentException {
- final String ftag="addAttributeChangeNotificationListener(NotificationListener, String, Object)";
-
- if (tracing()) trace(ftag,"Entry");
-
- if (inlistener == null)
- throw new IllegalArgumentException(
- "Listener to be registered must not be null");
-
-
- if (attributeBroadcaster == null)
- attributeBroadcaster = new NotificationBroadcasterSupport();
-
- AttributeChangeNotificationFilter currFilter =
- new AttributeChangeNotificationFilter();
-
- MBeanAttributeInfo[] attrInfo = modelMBeanInfo.getAttributes();
- boolean found = false;
- if (inAttributeName == null) {
- if ((attrInfo != null) && (attrInfo.length>0)) {
- for (int i=0; i<attrInfo.length; i++) {
- currFilter.enableAttribute(attrInfo[i].getName());
- }
- }
- } else {
- if ((attrInfo != null) && (attrInfo.length>0)) {
- for (int i=0; i<attrInfo.length; i++) {
- if (inAttributeName.equals(attrInfo[i].getName())) {
- found = true;
- currFilter.enableAttribute(inAttributeName);
- break;
- }
- }
- if (!found) {
- throw new RuntimeOperationsException(new
- IllegalArgumentException(
- "The attribute name does not exist"),
- "Exception occured trying to add an "+
- "AttributeChangeNotification listener");
- }
- }
- }
-
- if (tracing())
- trace(ftag, "Set attribute change filter to " +
- ((currFilter.getEnabledAttributes()).firstElement()).toString());
-
- attributeBroadcaster.addNotificationListener(inlistener,currFilter,
- inhandback);
- if (tracing()) trace("addAttributeChangeNotificationListener",
- "added for " + inAttributeName);
-
- if (tracing()) trace(ftag,"Exit");
- }
-
- public void removeAttributeChangeNotificationListener(NotificationListener inlistener, String inAttributeName)
- throws MBeanException, RuntimeOperationsException,
- ListenerNotFoundException {
- if (inlistener == null) throw new
- ListenerNotFoundException("Notification listener is null");
-
- final String ftag = "removeAttributeChangeNotificationListener(NotificationListener, String)";
-
- if (tracing()) trace(ftag,"Entry");
-
-
- if (attributeBroadcaster == null)
- throw new ListenerNotFoundException(
- "No attribute change notification listeners registered");
-
-
- MBeanAttributeInfo[] attrInfo = modelMBeanInfo.getAttributes();
- boolean found = false;
- if ((attrInfo != null) && (attrInfo.length>0)) {
- for (int i=0; i<attrInfo.length; i++) {
- if (attrInfo[i].getName().equals(inAttributeName)) {
- found = true;
- break;
- }
- }
- }
-
- if ((!found) && (inAttributeName != null)) {
- throw new RuntimeOperationsException(new
- IllegalArgumentException("Invalid attribute name"),
- "Exception occured trying to remove "+
- "attribute change notification listener");
- }
-
- /* note: */
- /* this may be a problem if the same listener is registered for
- multiple attributes with multiple filters and/or handback
- objects. It may remove all of them */
-
- attributeBroadcaster.removeNotificationListener(inlistener);
-
-
- if (tracing()) trace(ftag,"Exit");
-
- }
-
-
- public void sendAttributeChangeNotification(AttributeChangeNotification
- ntfyObj)
- throws MBeanException, RuntimeOperationsException {
- final String ftag =
- "sendAttributeChangeNotification(AttributeChangeNotification)";
-
- if (tracing()) trace(ftag,"Entry");
-
- if (ntfyObj == null)
- throw new RuntimeOperationsException(new
- IllegalArgumentException(
- "attribute change notification object must not be null"),
- "Exception occured trying to send "+
- "attribute change notification of a ModelMBean");
-
- Object oldv = ntfyObj.getOldValue();
- Object newv = ntfyObj.getNewValue();
-
- if (oldv == null) oldv = "null";
- if (newv == null) newv = "null";
-
- if (tracing())
- trace(ftag,"Sending AttributeChangeNotification " +
- " with " + ntfyObj.getAttributeName() +
- ntfyObj.getAttributeType() +
- ntfyObj.getNewValue() +
- ntfyObj.getOldValue());
-
- // log notification if specified in descriptor
- Descriptor ntfyDesc =
- modelMBeanInfo.getDescriptor(ntfyObj.getType(),"notification");
- Descriptor mmbDesc = modelMBeanInfo.getMBeanDescriptor();
-
- String logging, logfile;
-
- if (ntfyDesc != null) {
- logging =(String) ntfyDesc.getFieldValue("log");
- if (logging == null) {
- if (mmbDesc != null)
- logging = (String) mmbDesc.getFieldValue("log");
- }
- if ((logging != null) &&
- ( logging.equalsIgnoreCase("t") ||
- logging.equalsIgnoreCase("true"))) {
- logfile = (String) ntfyDesc.getFieldValue("logfile");
- if (logfile == null) {
- if (mmbDesc != null)
- logfile = (String)mmbDesc.getFieldValue("logfile");
- }
-
- if (logfile != null) {
- try {
- writeToLog(logfile,"LogMsg: " +
- ((new Date(ntfyObj.getTimeStamp())).toString())+
- " " + ntfyObj.getType() + " " +
- ntfyObj.getMessage() +
- " Name = " + ntfyObj.getAttributeName() +
- " Old value = " + oldv +
- " New value = " + newv);
- } catch (Exception e) {
- error(ftag,"Failed to log " + ntfyObj.getType() +
- " notification: " + e);
- traceX(ftag,e);
- }
- }
- }
- } else if (mmbDesc != null) {
- logging = (String) mmbDesc.getFieldValue("log");
- if ((logging != null) &&
- ( logging.equalsIgnoreCase("t") ||
- logging.equalsIgnoreCase("true") )) {
- logfile = (String) mmbDesc.getFieldValue("logfile");
-
- if (logfile != null) {
- try {
- writeToLog(logfile,"LogMsg: " +
- ((new Date(ntfyObj.getTimeStamp())).toString())+
- " " + ntfyObj.getType() + " " +
- ntfyObj.getMessage() +
- " Name = " + ntfyObj.getAttributeName() +
- " Old value = " + oldv +
- " New value = " + newv);
- } catch (Exception e) {
- error(ftag,"Failed to log " + ntfyObj.getType() +
- " notification: " + e);
- traceX(ftag,e);
- }
- }
- }
- }
- if (attributeBroadcaster != null) {
- attributeBroadcaster.sendNotification(ntfyObj);
- }
-
- // XXX Revisit: This is a quickfix: it would be better to have a
- // single broadcaster. However, it is not so simple because
- // removeAttributeChangeNotificationListener() should
- // remove only listeners whose filter is an instanceof
- // AttributeChangeNotificationFilter.
- //
- if (generalBroadcaster != null) {
- generalBroadcaster.sendNotification(ntfyObj);
- }
- if (tracing()) trace(ftag,"sent notification");
-
- if (tracing()) trace(ftag,"Exit");
- }
-
-
- public void sendAttributeChangeNotification(Attribute inOldVal,
- Attribute inNewVal)
- throws MBeanException, RuntimeOperationsException {
- final String ftag =
- "sendAttributeChangeNotification(Attribute, Attribute)";
- if (tracing()) trace(ftag,"Entry");
-
- // do we really want to do this?
- if ((inOldVal == null) || (inNewVal == null))
- throw new RuntimeOperationsException(new
- IllegalArgumentException("Attribute object must not be null"),
- "Exception occured trying to send " +
- "attribute change notification of a ModelMBean");
-
-
- if (!(inOldVal.getName().equals(inNewVal.getName())))
- throw new RuntimeOperationsException(new
- IllegalArgumentException("Attribute names are not the same"),
- "Exception occured trying to send " +
- "attribute change notification of a ModelMBean");
-
-
- Object newVal = inNewVal.getValue();
- Object oldVal = inOldVal.getValue();
- String className = "unknown";
- if (newVal != null)
- className = newVal.getClass().getName();
- if (oldVal != null)
- className = oldVal.getClass().getName();
-
- AttributeChangeNotification myNtfyObj = new
- AttributeChangeNotification(this,
- 1,
- ((new Date()).getTime()),
- "AttributeChangeDetected",
- inOldVal.getName(),
- className,
- inOldVal.getValue(),
- inNewVal.getValue());
-
- sendAttributeChangeNotification(myNtfyObj);
-
- if (tracing()) trace(ftag,"Exit");
-
- }
-
- /**
- * Return the Class Loader Repository used to perform class loading.
- * Subclasses may wish to redefine this method in order to return
- * the appropriate {@link javax.management.loading.ClassLoaderRepository}
- * that should be used in this object.
- *
- * @return the Class Loader Repository.
- *
- * @since.unbundled JMX 1.1
- */
- protected ClassLoaderRepository getClassLoaderRepository() {
- return MBeanServerFactory.getClassLoaderRepository(server);
- }
-
- private Class loadClass(String className)
- throws ClassNotFoundException {
- try {
- return Class.forName(className);
- } catch (ClassNotFoundException e) {
- final ClassLoaderRepository clr =
- getClassLoaderRepository();
- if (clr == null) throw new ClassNotFoundException(className);
- return clr.loadClass(className);
- }
- }
-
-
- /*************************************/
- /* MBeanRegistration Interface */
- /*************************************/
-
- /**
- * Allows the MBean to perform any operations it needs before
- * being registered in the MBean server. If the name of the MBean
- * is not specified, the MBean can provide a name for its
- * registration. If any exception is raised, the MBean will not be
- * registered in the MBean server.
- * <P>
- * In order to ensure proper run-time semantics of RequireModelMBean,
- * Any subclass of RequiredModelMBean overloading or overriding this
- * method should call <code>super.preRegister(server, name)</code>
- * in its own <code>preRegister</code> implementation.
- *
- * @param server The MBean server in which the MBean will be registered.
- *
- * @param name The object name of the MBean. This name is null if
- * the name parameter to one of the <code>createMBean</code> or
- * <code>registerMBean</code> methods in the {@link MBeanServer}
- * interface is null. In that case, this method must return a
- * non-null ObjectName for the new MBean.
- *
- * @return The name under which the MBean is to be registered.
- * This value must not be null. If the <code>name</code>
- * parameter is not null, it will usually but not necessarily be
- * the returned value.
- *
- * @exception java.lang.Exception This exception will be caught by
- * the MBean server and re-thrown as an
- * {@link javax.management.MBeanRegistrationException
- * MBeanRegistrationException}.
- */
- public ObjectName preRegister(MBeanServer server,
- ObjectName name)
- throws java.lang.Exception {
- // Since ModelMbeanInfo cannot be null (otherwise exception
- // thrown at creation)
- // no exception thrown on ModelMBeanInfo not set.
- if (name == null) throw new NullPointerException(
- "name of RequiredModelMBean to registered is null");
- this.server = server;
- return name;
- }
-
- /**
- * Allows the MBean to perform any operations needed after having been
- * registered in the MBean server or after the registration has failed.
- * <P>
- * In order to ensure proper run-time semantics of RequireModelMBean,
- * Any subclass of RequiredModelMBean overloading or overriding this
- * method should call <code>super.postRegister(registrationDone)</code>
- * in its own <code>postRegister</code> implementation.
- *
- * @param registrationDone Indicates whether or not the MBean has
- * been successfully registered in the MBean server. The value
- * false means that the registration phase has failed.
- */
- public void postRegister(Boolean registrationDone) {
- registered = registrationDone.booleanValue();
- }
-
- /**
- * Allows the MBean to perform any operations it needs before
- * being unregistered by the MBean server.
- * <P>
- * In order to ensure proper run-time semantics of RequireModelMBean,
- * Any subclass of RequiredModelMBean overloading or overriding this
- * method should call <code>super.preDeregister()</code> in its own
- * <code>preDeregister</code> implementation.
- *
- * @exception java.lang.Exception This exception will be caught by
- * the MBean server and re-thrown as an
- * {@link javax.management.MBeanRegistrationException
- * MBeanRegistrationException}.
- */
- public void preDeregister() throws java.lang.Exception {
- }
-
- /**
- * Allows the MBean to perform any operations needed after having been
- * unregistered in the MBean server.
- * <P>
- * In order to ensure proper run-time semantics of RequireModelMBean,
- * Any subclass of RequiredModelMBean overloading or overriding this
- * method should call <code>super.postDeregister()</code> in its own
- * <code>postDeregister</code> implementation.
- */
- public void postDeregister() {
- registered = false;
- this.server=null;
- }
-
- // SUN Trace and debug functions
- private final static boolean tracing() {
-
- return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_MODELMBEAN);
- }
-
- private static void trace(String inClass, String inMethod, String inText) {
- Trace.send(Trace.LEVEL_TRACE, Trace.INFO_MODELMBEAN, inClass,
- inMethod, inText);
- }
-
- private static void traceX(String inMethod, Throwable x) {
- Trace.send(Trace.LEVEL_TRACE, Trace.INFO_MODELMBEAN, currClass,
- inMethod, x);
- }
-
- private static void trace(String inMethod, String inText) {
- trace(currClass, inMethod, inText);
- }
-
- private static void error(String inMethod, String inText) {
- Trace.send(Trace.LEVEL_ERROR, Trace.INFO_MODELMBEAN, currClass,
- inMethod, inText);
- }
-
- private static boolean debugging() {
- return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_MODELMBEAN);
- }
-
- private static void debug(String inClass, String inMethod, String inText) {
- Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_MODELMBEAN, inClass,
- inMethod, inText);
- }
-
- private static void debug(String inMethod, String inText) {
- debug(currClass, inMethod, inText);
- }
-
- private static void debug(String inMethod, Throwable x) {
- Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_MODELMBEAN, currClass,
- inMethod, x);
- }
- }