0001: /* JFox, the OpenSource J2EE Application Server
0002: *
0003: * Copyright (C) 2002 huihoo.org
0004: * Distributable under GNU LGPL license
0005: * See the GNU Lesser General Public License for more details.
0006: */
0007:
0008: package javax.management.modelmbean;
0009:
0010: import java.util.Date;
0011: import java.util.Iterator;
0012: import java.util.Arrays;
0013: import java.util.List;
0014: import java.util.ArrayList;
0015: import java.lang.reflect.InvocationTargetException;
0016: import java.io.PrintWriter;
0017: import java.io.FileWriter;
0018: import java.io.File;
0019: import java.io.FileInputStream;
0020: import java.io.ObjectInputStream;
0021: import java.io.FileOutputStream;
0022: import java.io.ObjectOutputStream;
0023:
0024: import javax.management.loading.ClassLoaderRepository;
0025: import javax.management.NotificationBroadcasterSupport;
0026: import javax.management.MBeanException;
0027: import javax.management.RuntimeOperationsException;
0028: import javax.management.InstanceNotFoundException;
0029: import javax.management.MBeanNotificationInfo;
0030: import javax.management.Descriptor;
0031: import javax.management.ServiceNotFoundException;
0032: import javax.management.MBeanInfo;
0033: import javax.management.MBeanAttributeInfo;
0034: import javax.management.ReflectionException;
0035: import javax.management.RuntimeErrorException;
0036: import javax.management.AttributeNotFoundException;
0037: import javax.management.AttributeList;
0038: import javax.management.InvalidAttributeValueException;
0039: import javax.management.Attribute;
0040: import javax.management.NotificationListener;
0041: import javax.management.NotificationFilter;
0042: import javax.management.ListenerNotFoundException;
0043: import javax.management.Notification;
0044: import javax.management.AttributeChangeNotificationFilter;
0045: import javax.management.AttributeChangeNotification;
0046: import javax.management.RuntimeMBeanException;
0047: import javax.management.MBeanRegistration;
0048: import javax.management.ObjectName;
0049: import javax.management.MBeanServer;
0050:
0051: import org.huihoo.jfox.jmx.loading.SignatureClassLoader;
0052: import org.huihoo.jfox.jmx.loading.PrimitiveClassLoader;
0053:
0054: /**
0055: * This class is the implementation of a ModelMBean. An appropriate implementation of a ModelMBean
0056: * must be shipped with every JMX Agent and the class must be named RequiredModelMBean.
0057: * <P>
0058: * Java resources wishing to be manageable instatiate the RequiredModelMBean using the MBeanServer's
0059: * createMBean method. The resource then sets the MBeanInfo and Descriptors for the RequiredModelMBean
0060: * instance. The attributes and operations exposed via the ModelMBeanInfo for the ModelMBean are accessible
0061: * from Mbeans, connectors/adapters like other MBeans. Through the Descriptors, values and methods in
0062: * the managed application can be defined and mapped to attributes and operations of the ModelMBean.
0063: * This mapping can be defined in an XML formatted file or dynamically and
0064: * programmatically at runtime.
0065: * <P>
0066: * Every RequiredModelMBean which is instantiated in the MBeanServer becomes manageable:
0067: * its attributes and operations
0068: * become remotely accessible through the connectors/adaptors connected to that MBeanServer.
0069: * A Java object cannot be registered in the MBeanServer unless it is a JMX compliant MBean.
0070: * By instantiating a RequiredModelMBean, resources are guaranteed that the MBean is valid.
0071: *
0072: * MBeanException and RuntimeOperatiosException must be thrown on every public method. This allows
0073: * for wrappering exceptions from distributed communications (RMI, EJB, etc.)
0074: *
0075: * @author <a href="mailto:young_yy@hotmail.org">Young Yang</a>
0076: */
0077:
0078: public class RequiredModelMBean implements ModelMBean,
0079: MBeanRegistration {
0080: /* Notification broadcaster for any notification to be sent from the application
0081: * through the RequiredModelMBean.
0082: */
0083: private NotificationBroadcasterSupport generalBroadcaster = new NotificationBroadcasterSupport();
0084: /* Notification broadcaster for attribute change notifications */
0085: private NotificationBroadcasterSupport attributeBroadcaster = new NotificationBroadcasterSupport();
0086: // handle, name, or reference for instance on which
0087: private Object managedResource = null;
0088: private SignatureClassLoader signatureLoader = SignatureClassLoader
0089: .getInstance();
0090: // will set at preRegister
0091: private ClassLoaderRepository defaultRepo = null;
0092:
0093: // private transient MBeanServer server = null;
0094:
0095: private ModelMBeanInfo modelMBeanInfo = new ModelMBeanInfoSupport(
0096: getClass().getName(), "Default ModelMBeanInfo", null, null,
0097: null, null);
0098:
0099: private ModelMBeanNotificationInfo genericNotificationInfo = new ModelMBeanNotificationInfo(
0100: new String[] { "jmx.modelmbean.generic" },
0101: "GENERIC",
0102: "A text notification has been issued by the managed resource",
0103: new DescriptorSupport(
0104: new String[] {
0105: DescriptorConstants.NAME + "=GENERIC",
0106: DescriptorConstants.DESCRIPTORTYPE
0107: + "="
0108: + DescriptorConstants.NOTIFICATION_TYPE,
0109: DescriptorConstants.LOG + "="
0110: + DescriptorConstants.TRUE,
0111: DescriptorConstants.NOTIFICATION_SEVERITY
0112: + "="
0113: + DescriptorConstants.NOTIFICATION_SEVERITY_WARN,
0114: DescriptorConstants.DISPLAYNAME
0115: + "=jmx.modelmbean.generic" }));
0116:
0117: private ModelMBeanNotificationInfo attributeChangeNotificationInfo = new ModelMBeanNotificationInfo(
0118: new String[] { "jmx.attribute.change" },
0119: "ATTRIBUTE_CHANGE",
0120: "Signifies that an observed MBean attribute value has changed",
0121: new DescriptorSupport(
0122: new String[] {
0123: DescriptorConstants.NAME
0124: + "=ATTRIBUTE_CHANGE",
0125: DescriptorConstants.DESCRIPTORTYPE
0126: + "="
0127: + DescriptorConstants.NOTIFICATION_TYPE,
0128: DescriptorConstants.LOG + "="
0129: + DescriptorConstants.TRUE,
0130: DescriptorConstants.NOTIFICATION_SEVERITY
0131: + "="
0132: + DescriptorConstants.NOTIFICATION_SEVERITY_WARN,
0133: DescriptorConstants.DISPLAYNAME
0134: + "=jmx.attribute.change" }));
0135:
0136: /**
0137: * Constructs an <CODE>RequiredModelMBean</CODE> with an empty ModelMBeanInfo.
0138: *
0139: * After the RequiredModelMBean's MBeanInfo and Descriptors are customized, the RequiredModelMBean
0140: * should be registered with the MBeanServer.
0141: * <P>
0142: *
0143: * @exception MBeanException The constructor of the object has thrown an exception.
0144: * @exception RuntimeOperationsException Wraps an IllegalArgumentException.
0145: *
0146: */
0147: public RequiredModelMBean() throws MBeanException,
0148: RuntimeOperationsException {
0149:
0150: }
0151:
0152: /**
0153: * Constructs a RequiredModelMBean object using ModelMBeanInfo passed in.
0154: * The RequiredModelMBean must be instantiated, but not registered with the MBeanServer.
0155: * After the RequiredModelMBean's MBeanInfo and Descriptors are customized, the RequiredModelMBean
0156: * should be registered with the MBeanServer.
0157: * <P>
0158: *
0159: * @param mbeanInfo The ModelMBeanInfo object to be used by the RequiredModelMBean.
0160: *
0161: * @exception MBeanException The constructor of the object has thrown an exception.
0162: * @exception RuntimeOperationsException Wraps an IllegalArgumentException:
0163: * The MBeanInfo passed in parameter is null or invalid.
0164: *
0165: */
0166: public RequiredModelMBean(ModelMBeanInfo mbeanInfo)
0167: throws MBeanException, RuntimeOperationsException {
0168: if (mbeanInfo != null) {
0169: setModelMBeanInfo(mbeanInfo);
0170: }
0171: }
0172:
0173: /**
0174: * Initializes a RequiredModelMBean object using ModelMBeanInfo passed in.
0175: * The RequiredModelMBean should be instantiated, but not registered with the MBeanServer.
0176: * After the RequiredModelMBean's MBeanInfo and Descriptors are customized, the RequiredModelMBean
0177: * should be registered with the MBeanServer.
0178: * <P>
0179: * @param mbeanInfo The MBeanInfo object to be used by the RequiredModelMBean.
0180: *
0181: *
0182: * @exception MBeanException The constructor of the MBeanInfo has return null
0183: * or thrown an exception.
0184: * @exception RuntimeOperationsException Wraps an IllegalArgumentException:
0185: * The MBeanInfo passed in parameter is null or invalid.
0186: *
0187: */
0188: public void setModelMBeanInfo(ModelMBeanInfo mbeanInfo)
0189: throws MBeanException, RuntimeOperationsException {
0190: if (mbeanInfo == null) {
0191: throw new RuntimeOperationsException(
0192: new IllegalArgumentException(
0193: "ModelMBeanInfo must not be null"),
0194: "Exception occured trying to initialize the ModelMBeanInfo of the RequiredModelMBean");
0195: }
0196: modelMBeanInfo = (ModelMBeanInfo) mbeanInfo.clone();
0197: }
0198:
0199: /**
0200: * Sets the instance handle of the object against which to execute all methods in this RequiredModelMBean
0201: * management interface (ModelMBeanInfo and Descriptors). This setting can be overridden by setting
0202: * the 'targetObject' field of the ModelMBeanOperationInfo's descriptor.
0203: *
0204: * @param resource Object that is the managed resource
0205: * @param type The type of reference for the managed resource. Can be: ObjectReference,
0206: * Handle, IOR, EJBHandle, RMIReference.
0207: * If the MBeanServer cannot process the mr_type passed in, an exception will be
0208: * thrown.
0209: *
0210: *
0211: * @exception MBeanException The initializer of the object has thrown an exception.
0212: * @exception RuntimeOperationsException Wraps an IllegalArgumentException:
0213: * The managed resource or managed resoure type passed in parameter is null or invalid.
0214: * @exception InstanceNotFoundException The managed resource object could not be found
0215: * @exception InvalidTargetObjectTypeException The managed resource type cannot be processed by the
0216: * RequiredModelMBean or JMX Agent.
0217: */
0218: public void setManagedResource(Object resource, String type)
0219: throws MBeanException, RuntimeOperationsException,
0220: InstanceNotFoundException, InvalidTargetObjectTypeException {
0221: if (resource == null)
0222: throw new RuntimeOperationsException(
0223: new IllegalArgumentException(
0224: "Managed resource cannot be null"));
0225: if (type == null || !isResourceTypeSupported(type)) {
0226: throw new InvalidTargetObjectTypeException(type);
0227: }
0228: managedResource = resource;
0229: }
0230:
0231: /**
0232: * load a modelMBean from a serialized file, if the ModelMBean is initliazing, use it's ClassName + ".ser" as
0233: * it's filename, or will look for the MBeanDescriptor
0234: * @throws MBeanException
0235: * @throws RuntimeOperationsException
0236: * @throws InstanceNotFoundException
0237: */
0238: public void load() throws MBeanException,
0239: RuntimeOperationsException, InstanceNotFoundException {
0240: // System.out.println("\n<<<<<<<<<<<<<RequiredModelMBean 144: loading...");
0241: Descriptor descriptor = modelMBeanInfo.getMBeanDescriptor();
0242: String identity;
0243: if (descriptor == null) { // use the classname as filename
0244: identity = this .getClass().getName() + ".ser";
0245:
0246: } else {
0247: identity = getPersistentIdentity();
0248: }
0249: try {
0250: FileInputStream fis = new FileInputStream(identity);
0251: ObjectInputStream ois = new ObjectInputStream(fis);
0252: // Read the serialized object
0253: ModelMBeanInfo info = (ModelMBeanInfo) ois.readObject();
0254: // Close
0255: fis.close();
0256: ois.close();
0257: //
0258: //
0259: // ObjectName persistenterObjectName = getPersistenterObjectName();
0260: //
0261: // Object obj = server.invoke(persistenterObjectName,
0262: // "load",
0263: // new Object[]{identity},
0264: // new String[]{"java.lang.Object"}
0265: // );
0266:
0267: this .setModelMBeanInfo(info);
0268: } catch (RuntimeException e) {
0269: throw new RuntimeOperationsException(e);
0270: } catch (MBeanException e) {
0271: throw e;
0272: } catch (Exception e) {
0273: throw new MBeanException(e, e.toString());
0274: }
0275: }
0276:
0277: public void store() throws MBeanException,
0278: RuntimeOperationsException, InstanceNotFoundException {
0279: try {
0280: // ObjectName persistenterObjectName = getPersistenterObjectName();
0281: String identity = getPersistentIdentity();
0282:
0283: // server.invoke(persistenterObjectName,
0284: // "store",
0285: // new Object[]{identity,modelMBeanInfo},
0286: // new String[]{"java.lang.Object","java.lang.Object"}
0287: // );
0288: FileOutputStream fos = new FileOutputStream(identity, false);
0289: ObjectOutputStream oos = new ObjectOutputStream(fos);
0290: oos.writeObject(modelMBeanInfo);
0291: fos.close();
0292: oos.close();
0293: } catch (RuntimeException e) {
0294: throw new RuntimeOperationsException(e);
0295: } catch (MBeanException e) {
0296: throw e;
0297: } catch (Exception e) {
0298: throw new MBeanException(e, e.toString());
0299: }
0300:
0301: }
0302:
0303: public MBeanInfo getMBeanInfo() {
0304: return (MBeanInfo) modelMBeanInfo.clone();
0305: }
0306:
0307: /**
0308: * Invokes a method on or through a RequiredModelMBean and returns the result of the method execution.
0309: * <PRE>
0310: * The last value returned by an operation may be cached in the operation's descriptor which
0311: * is in the ModelMBeanOperationInfo's descriptor.
0312: * The valid value will be in the 'value' field if there is one.
0313: * If the 'currencyTimeLimit' field in the descriptor is:
0314: * null
0315: * <0 Then the value is not cached and is never valid. Null is returned.
0316: * The 'value' and 'lastUpdatedTimeStamp' fields are cleared.
0317: * =0 Then the value is always cached and always valid. The 'value' field is returned.
0318: * The 'lastUpdatedTimeStamp' field is not checked.
0319: * >0 Represents the number of seconds that the 'value' field is valid.
0320: * The 'value' field is no longer valid when 'lastUpdatedTimeStamp' + 'currencyTimeLimit' > Now.
0321: * When 'value' is valid, 'valid' is returned.
0322: * When 'value' is no longer valid then null is returned and ;value' and 'lastUpdatedTimeStamp'
0323: * fields are cleared.
0324: *
0325: * Note: For this implementation: if the cached value is not a String, then the object must have
0326: * a constructor which accepts a string in the same format as the objects toString() method creates.
0327: * </pre>
0328: *
0329: * @param operationName The name of the method to be invoked. The name can be the fully qualified
0330: * method name including the classname, or just the method name if the classname is defined in the 'class'
0331: * field of the operation descriptor.
0332: * @param params An array containing the parameters to be set when the operation is
0333: * invoked
0334: * @param signature An array containing the signature of the operation. The class objects will
0335: * be loaded using the same class loader as the one used for loading the MBean on which the operatoion was invoked.
0336: *
0337: * @return The object returned by the method, which represents the result of invoking the method on the
0338: * specified managed resource.
0339: *
0340: * @exception MBeanException Wraps an exception thrown by the MBean's invoked method.
0341: * @exception ReflectionException Wraps an java.lang.Exception thrown while trying to invoke the method.
0342: *
0343: */
0344: public Object invoke(String operationName, Object[] params,
0345: String[] signature) throws MBeanException,
0346: ReflectionException {
0347: if (modelMBeanInfo == null)
0348: throw new MBeanException(new ServiceNotFoundException(
0349: "ModelMBeanInfo is null"));
0350: if (operationName == null)
0351: throw new RuntimeOperationsException(
0352: new IllegalArgumentException(
0353: "Method name must not be null"),
0354: "An exception occured while trying to reflectInvoke a method on a RequiredModelMBean");
0355:
0356: Class[] signatureClasses = null;
0357: if (signature != null && signature.length != 0) {
0358: try {
0359: signatureClasses = signatureLoader
0360: .loadClasses(signature);
0361: } catch (ClassNotFoundException e) {
0362: throw new ReflectionException(e, e.toString());
0363: }
0364: }
0365: // System.out.println("RequiredModelMBean:155 " + operationName);
0366:
0367: // test if the method is in RequireModelMBean ,ex: addAttributeChangeNotificationListener
0368: try {
0369: return this .reflectInvoke(this , operationName, params,
0370: signatureClasses);
0371: } catch (ReflectionException e) { // ignore the NoSuchMethodException
0372: if (!(e.getTargetException() instanceof NoSuchMethodException))
0373: throw e;
0374: } catch (MBeanException e) {
0375: throw e;
0376: }
0377:
0378: ModelMBeanOperationInfo operationInfo = modelMBeanInfo
0379: .getOperation(operationName);
0380: if (operationInfo == null)
0381: throw new MBeanException(new ServiceNotFoundException(
0382: "Cannot find ModelMBeanOperationInfo for operation "
0383: + operationName));
0384:
0385: Descriptor descriptor = operationInfo.getDescriptor();
0386: if (descriptor == null)
0387: throw new MBeanException(new ServiceNotFoundException(
0388: "Operation descriptor for operation "
0389: + operationName + " cannot be null"));
0390:
0391: String descriptorType = (String) descriptor
0392: .getFieldValue(DescriptorConstants.DESCRIPTORTYPE);
0393: if (descriptorType == null
0394: || !descriptorType
0395: .equalsIgnoreCase(DescriptorConstants.OPERATION_TYPE))
0396: throw new MBeanException(new ServiceNotFoundException(
0397: "Operation descriptor field 'descriptorTyoe' must be 'operation', not "
0398: + descriptorType));
0399:
0400: Descriptor mbeanDescriptor = modelMBeanInfo
0401: .getMBeanDescriptor();
0402: if (mbeanDescriptor == null)
0403: throw new MBeanException(new ServiceNotFoundException(
0404: "MBean descriptor cannot be null"));
0405:
0406: Object returnObj = null;
0407:
0408: int currencyTimeLimit = this .getCurrencyTimeLimit(descriptor);
0409: long lastReturnedTimeStamp = this .getLastTimeStamp(descriptor);
0410: if (isCacheValid(currencyTimeLimit, lastReturnedTimeStamp)) { // cache valid
0411: returnObj = descriptor
0412: .getFieldValue(DescriptorConstants.OPERATION_VALUE);
0413: } else { // will invoke by reflection with the targetObject
0414: Object targetObject = this .getTargetObject(descriptor);
0415: returnObj = this .reflectInvoke(targetObject, operationName,
0416: params, signatureClasses);
0417: }
0418:
0419: // check type return Object validate
0420: if (returnObj != null) {
0421: Class returnClass = null;
0422: try {
0423: returnClass = defaultRepo.loadClass(operationInfo
0424: .getReturnType());
0425: } catch (ClassNotFoundException e) {
0426: throw new ReflectionException(e, e.toString());
0427: }
0428: if (!checkAssignability(returnObj.getClass(), returnClass))
0429: throw new MBeanException(
0430: new InvalidAttributeValueException(
0431: "Returned type and declared type are not assignable"));
0432: }
0433:
0434: // maybe do store by PersistMBean
0435: if (operationInfo.getImpact() != ModelMBeanOperationInfo.INFO
0436: && needPersist(descriptor)) {
0437: try {
0438: this .store();
0439: } catch (InstanceNotFoundException e) {
0440: e.printStackTrace();
0441: }
0442: }
0443:
0444: return returnObj;
0445: }
0446:
0447: /**
0448: * Returns the value of a specific attribute defined for this ModelMBean.
0449: * <PRE>
0450: * The last value returned by an attribute may be cached in the attribute's descriptor.
0451: * The valid value will be in the 'value' field if there is one.
0452: * If the 'currencyTimeLimit' field in the descriptor is:
0453: * null
0454: * <0 Then the value is not cached and is never valid. Null is returned.
0455: * The 'value' and 'lastUpdatedTimeStamp' fields are cleared.
0456: * =0 Then the value is always cached and always valid. The 'value' field is returned.
0457: * The 'lastUpdatedTimeStamp' field is not checked.
0458: * >0 Represents the number of seconds that the 'value' field is valid.
0459: * The 'value' field is no longer valid when 'lastUpdatedTimeStamp' + 'currencyTimeLimit' > Now.
0460: * When 'value' is valid, 'valid' is returned.
0461: * When 'value' is no longer valid then null is returned and ;value' and 'lastUpdatedTimeStamp'
0462: * fields are cleared.
0463: *
0464: *
0465: * </PRE>
0466: * If there is no valid cached value then the 'getMethod' field in the attributes descriptor
0467: * is analyzed. If 'getMethod' contains the attributeName of a valid operation descriptor, then the
0468: * method described by the operation descriptor is executed. The response from the method
0469: * is returned as the value of the attribute. If the operation fails or the response value is
0470: * not of the same type as the attribute, an exception will be thrown.
0471: *
0472: * If currencyTimeLimit is > 0, then the value of the attribute is cached in the attribute descriptor's
0473: * 'value' field and the 'lastUpdatedTimeStamp' field is set to the current time stamp.
0474: *
0475: * @param attributeName A String specifying the attributeName of the attribute to be
0476: * retrieved. It must match the attributeName of a ModelMBeanAttributeInfo.
0477: *
0478: * @return The value of the retrieved attribute from the descriptor 'value' field or from the
0479: * invokation of the operation in the 'getMethod' field of the descriptor.
0480: *
0481: * @exception AttributeNotFoundException The specified attribute is not accessible in the MBean.
0482: * @exception MBeanException Wraps an exception thrown by the MBean's getter.
0483: * @exception ReflectionException Wraps an java.lang.Exception thrown while trying to invoke the setter.
0484: * @exception RuntimeOperationsException Wraps an IllegalArgumentException: The object attributeName in parameter is null or
0485: * the attribute in parameter is null.
0486: */
0487: public Object getAttribute(String attributeName)
0488: throws AttributeNotFoundException, MBeanException,
0489: ReflectionException {
0490: if (modelMBeanInfo == null)
0491: throw new AttributeNotFoundException(
0492: "getAttributeInfo failed: ModelMBeanInfo not found for "
0493: + attributeName);
0494: Descriptor mbeanDescriptor = modelMBeanInfo
0495: .getMBeanDescriptor();
0496: if (mbeanDescriptor == null) {
0497: throw new AttributeNotFoundException(
0498: "MBean descriptor cannot be null");
0499: }
0500:
0501: if (attributeName == null)
0502: throw new RuntimeOperationsException(
0503: new IllegalArgumentException(
0504: "attributeName must not be null"),
0505: "Exception occured trying to get attribute of a RequiredModelMBean");
0506: ModelMBeanAttributeInfo attributeInfo = modelMBeanInfo
0507: .getAttribute(attributeName);
0508: if (attributeInfo == null)
0509: throw new AttributeNotFoundException(
0510: "getAttributeInfo failed: ModelMBeanAttributeInfo not found for "
0511: + attributeName);
0512: if (!attributeInfo.isReadable())
0513: throw new AttributeNotFoundException(
0514: "getAttributeInfo failed: " + attributeName
0515: + " is not readable ");
0516: Descriptor descriptor = attributeInfo.getDescriptor();
0517: if (descriptor == null)
0518: throw new MBeanException(
0519: new InvalidAttributeValueException(
0520: "Unable to resolve attribute value, no getMethod defined in descriptor for attribute"),
0521: "An exception occured while trying to get an attribute value through a RequiredModelMBean");
0522:
0523: Object returnObj = null;
0524: int currencyTimeLimit = this .getCurrencyTimeLimit(descriptor);
0525: long lastReturnedTimeStamp = this .getLastTimeStamp(descriptor);
0526: if (isCacheValid(currencyTimeLimit, lastReturnedTimeStamp)) { // cache valid
0527: returnObj = descriptor
0528: .getFieldValue(DescriptorConstants.ATTRIBUTE_VALUE);
0529: } else { // cache not valid
0530: String getter = (String) descriptor
0531: .getFieldValue(DescriptorConstants.ATTRIBUTE_GETMETHOD);
0532: if (getter == null) { // getter not set, use the default value
0533: returnObj = descriptor
0534: .getFieldValue(DescriptorConstants.ATTRIBUTE_DEFAULT);
0535: } else { // get the value by reflection
0536: Object targetObject = this .getTargetObject(descriptor);
0537: returnObj = this .reflectInvoke(targetObject, getter,
0538: null, null);
0539: }
0540: }
0541:
0542: // will check the return value's Class
0543: if (returnObj != null) {
0544: Class returnClass = null;
0545: try {
0546: returnClass = defaultRepo.loadClass(attributeInfo
0547: .getType());
0548: } catch (ClassNotFoundException e) {
0549: throw new ReflectionException(e, e.toString());
0550: }
0551: if (!checkAssignability(returnObj.getClass(), returnClass))
0552: throw new MBeanException(
0553: new InvalidAttributeValueException(
0554: "Returned type and declared type are not assignable"));
0555: }
0556:
0557: return returnObj;
0558: }
0559:
0560: /**
0561: * Returns the values of several attributes in the ModelMBean.
0562: * Executes a getAttribute for each attribute name in the attrNames array passed in.
0563: *
0564: * @param attributes A String array of names of the attributes to be retrieved.
0565: *
0566: * @return The array of the retrieved attributes.
0567: *
0568: * @exception RuntimeOperationsException Wraps an IllegalArgumentException: The object name in parameter is null or
0569: * attributes in parameter is null.
0570: *
0571: */
0572: public AttributeList getAttributes(String[] attributes) {
0573: AttributeList attrList = null;
0574: if (attributes == null)
0575: throw new RuntimeOperationsException(
0576: new IllegalArgumentException(
0577: "attributeNames must not be null"),
0578: "Exception occured trying to get attributes of a RequiredModelMBean");
0579: attrList = new AttributeList();
0580: for (int i = 0; i < attributes.length; i++) {
0581: try {
0582: attrList.add(new Attribute(attributes[i],
0583: getAttribute(attributes[i])));
0584: } catch (Exception e) {
0585: e.printStackTrace();
0586: }
0587: }
0588: return attrList;
0589: }
0590:
0591: /**
0592: * Sets the value of a specific attribute of a named ModelMBean.
0593: *
0594: * If the 'setMethod' field of the attribute's descriptor
0595: * contains the name of a valid operation descriptor, then the
0596: * method described by the operation descriptor is executed. The response from the method
0597: * is set as the value of the attribute in the descriptor. If the operation fails or the response value is
0598: * not of the same type as the attribute, an exception will be thrown.
0599: * <PRE>
0600: * If currencyTimeLimit is > 0, then the new value for the attribute is cached in the attribute descriptor's
0601: * 'value' field and the 'lastUpdatedTimeStamp' field is set to the current time stamp.
0602: *
0603: *
0604: * If the persist field of the attribute's descriptor is not null then
0605: * Persistance policy from the attribute descriptor is used to guide storing the attribute in a
0606: * persistenant store.
0607: * Store the MBean if 'persistPolicy' field is:
0608: * != "never"
0609: * = "always"
0610: * = "onUpdate"
0611: * = "onTimer" and now > 'lastPersistTime' + 'persistPeriod'
0612: * = "NoMoreOftenThan" and now > 'lastPersistTime' + 'persistPeriod'
0613: *
0614: * Do not store the MBean if 'persistPolicy' field is:
0615: * = "never"
0616: * = "onTimer" && now < 'lastPersistTime' + 'persistPeriod'
0617: * = "NoMoreOftenThan" and now < 'lastPersistTime' + 'persistPeriod'
0618: * </PRE>
0619: * @param attribute The Attribute instance containing the name of the attribute to be set and the value it is to be set to.
0620: *
0621: *
0622: * @exception AttributeNotFoundException The specified attribute is not accessible in the MBean.
0623: * @exception InvalidAttributeValueException The specified value for the attribute is not valid.
0624: * @exception MBeanException Wraps an exception thrown by the MBean's setter.
0625: * @exception ReflectionException Wraps an java.lang.Exception thrown while trying to invoke the setter.
0626: * @exception RuntimeOperationsException Wraps an IllegalArgumentException: The object name in parameter is null or
0627: * the attribute in parameter is null.
0628: */
0629: public void setAttribute(Attribute attribute)
0630: throws AttributeNotFoundException,
0631: InvalidAttributeValueException, MBeanException,
0632: ReflectionException {
0633: if (modelMBeanInfo == null)
0634: throw new AttributeNotFoundException(
0635: "getAttributeInfo failed: ModelMBeanInfo not found for "
0636: + attribute);
0637: Descriptor mbeanDescriptor = modelMBeanInfo
0638: .getMBeanDescriptor();
0639: if (mbeanDescriptor == null) {
0640: throw new AttributeNotFoundException(
0641: "MBean descriptor cannot be null");
0642: }
0643:
0644: if (attribute == null)
0645: throw new RuntimeOperationsException(
0646: new IllegalArgumentException(
0647: "attribute must not be null"),
0648: "Exception occured trying to set an attribute of a RequiredModelMBean");
0649: String name = attribute.getName();
0650: Object value = attribute.getValue();
0651: ModelMBeanAttributeInfo attributeInfo = modelMBeanInfo
0652: .getAttribute(name);
0653: if (attributeInfo == null)
0654: throw new AttributeNotFoundException(
0655: "setAttribute failed: " + name + " is not found ");
0656:
0657: Descriptor descriptor = attributeInfo.getDescriptor();
0658: if (descriptor == null)
0659: throw new InvalidAttributeValueException(
0660: "Unable to resolve attribute value, no defined in mbeanDescriptor for attribute");
0661:
0662: if (!attributeInfo.isWritable())
0663: throw new AttributeNotFoundException(
0664: "setAttribute failed: " + name
0665: + " is not writable ");
0666:
0667: String setter = (String) descriptor.getFieldValue("setMethod");
0668: // if (setter == null) throw new MBeanException(new ServiceNotFoundException("No setter method defined"), "Exception thrown trying to set an attribute");
0669:
0670: Object oldValue = null;
0671: try {
0672: oldValue = this .getAttribute(name);
0673: } catch (Exception e) {
0674: e.printStackTrace();
0675: }
0676:
0677: Class attributeClass = null;
0678: try {
0679: attributeClass = defaultRepo.loadClass(attributeInfo
0680: .getType());
0681: } catch (ClassNotFoundException e) {
0682: throw new ReflectionException(e, e.toString());
0683: }
0684: if (!checkAssignability(value.getClass(), attributeClass))
0685: throw new MBeanException(
0686: new InvalidAttributeValueException(name));
0687:
0688: if (setter == null || setter.trim().length() == 0) { // will use the Attribute value
0689: // Always refresh the cache if no setMethod
0690: descriptor.setField(DescriptorConstants.ATTRIBUTE_VALUE,
0691: value);
0692: } else { // reflect invoke
0693: Object targetObject = this .getTargetObject(descriptor);
0694: this .reflectInvoke(targetObject, setter,
0695: new Object[] { value },
0696: new Class[] { attributeClass });
0697:
0698: // refresh the cache
0699: if (this .getCurrencyTimeLimit(descriptor) != DescriptorConstants.CURRENCYTIMELIMIT_ALWARYSSTALE) {
0700: descriptor.setField(
0701: DescriptorConstants.ATTRIBUTE_VALUE, value);
0702: descriptor
0703: .setField(
0704: DescriptorConstants.ATTRIBUTE_LASTUPDATEDTIMESTAMP,
0705: new Long(System.currentTimeMillis()));
0706: }
0707: }
0708: // update the attribute descriptor
0709: modelMBeanInfo.setDescriptor(descriptor,
0710: DescriptorConstants.ATTRIBUTE_TYPE);
0711: this .sendAttributeChangeNotification(new Attribute(name,
0712: oldValue), attribute);
0713:
0714: // when support PersistMBean,will do store();
0715: if (this .needPersist(descriptor)) {
0716: try {
0717: this .store();
0718: } catch (InstanceNotFoundException e) {
0719: e.printStackTrace();
0720: }
0721: }
0722: }
0723:
0724: /**
0725: * Sets the values of an array of attributes of this ModelMBean.
0726: * Executes the setAttribute() method for each attribute in the list.
0727: *
0728: * @param attributes A list of attributes: The identification of the
0729: * attributes to be set and the values they are to be set to.
0730: *
0731: * @return The array of attributes that were set, with their new values in Attribute instances.
0732: *
0733: * @exception RuntimeOperationsException Wraps an IllegalArgumentException: The object name in parameter is null or
0734: * attributes in parameter is null.
0735: *
0736: */
0737: public AttributeList setAttributes(AttributeList attributes) {
0738: AttributeList attrList = null;
0739: if (attributes == null)
0740: throw new RuntimeOperationsException(
0741: new IllegalArgumentException(
0742: "attributes must not be null"),
0743: "Exception occured trying to set attributes of a RequiredModelMBean");
0744: attrList = new AttributeList();
0745: for (Iterator iterator = attributes.iterator(); iterator
0746: .hasNext();) {
0747: Attribute attribute = (Attribute) iterator.next();
0748: try {
0749: setAttribute(attribute);
0750: attrList.add(attribute);
0751: } catch (Exception e) {
0752: e.printStackTrace();
0753: }
0754: }
0755: return attrList;
0756: }
0757:
0758: /**
0759: * Registers an object which implements the NotificationListener interface as a listener. This
0760: * object's 'handleNotification()' method will be invoked when any notification is issued through
0761: * or by the ModelMBean. This does not include attributeChangeNotifications. They must be registered
0762: * for independently.
0763: *
0764: * @param listener The listener object which will handles notifications emitted by the registered MBean.
0765: * @param filter The filter object. If null, no filtering will be performed before handling notifications.
0766: * @param handback The context to be sent to the listener with the notification when a notification is emitted.
0767: *
0768: * @exception IllegalArgumentException The listener could not be added.
0769: *
0770: */
0771: public void addNotificationListener(NotificationListener listener,
0772: NotificationFilter filter, Object handback)
0773: throws IllegalArgumentException {
0774: if (listener == null)
0775: throw new IllegalArgumentException(
0776: "notification listener must not be null");
0777: generalBroadcaster.addNotificationListener(listener, filter,
0778: handback);
0779: }
0780:
0781: /**
0782: * Removes a listener for Notifications from the RequiredModelMBean.
0783: *
0784: * @param listener The listener name which was handling notifications emitted by the registered MBean.
0785: * This method will remove all information related to this listener.
0786: *
0787: * @exception ListenerNotFoundException The couple (listener,handback) is not registered in the MBean.
0788: * The exception message contains either "listener", "handback" or the object name depending on which object cannot be found.
0789: *
0790: *
0791: */
0792: public void removeNotificationListener(NotificationListener listener)
0793: throws ListenerNotFoundException {
0794: if (listener == null)
0795: throw new ListenerNotFoundException(
0796: "Notification listener is null");
0797: // if(generalBroadcaster == null)
0798: // throw new ListenerNotFoundException("No notification listeners registered");
0799: generalBroadcaster.removeNotificationListener(listener);
0800: }
0801:
0802: /**
0803: * Sends a Notification which is passed in to the registered Notification listeners on the RequiredModelMBean.
0804: *
0805: * @param notification The notification which is to be passed to the 'handleNotification' method
0806: * of the listener object.
0807: *
0808: * @exception MBeanException for implementation exceptions
0809: * @exception RuntimeOperationsException to wrapper IllegalArugementExceptions
0810: *
0811: */
0812: public void sendNotification(Notification notification)
0813: throws MBeanException, RuntimeOperationsException {
0814: if (notification == null)
0815: throw new RuntimeOperationsException(
0816: new IllegalArgumentException(
0817: "notification object must not be null"),
0818: "Exception occured trying to send a notification from a RequiredModelMBean");
0819: Descriptor descriptor = modelMBeanInfo.getDescriptor(
0820: notification.getType(),
0821: DescriptorConstants.NOTIFICATION_TYPE);
0822: if (descriptor != null) {
0823: if (isLogEnabled(descriptor)) {
0824: String logFile = getLogFile(descriptor);
0825: if (logFile != null && logFile.trim().length() != 0) {
0826: try {
0827: writeToLog(
0828: logFile,
0829: "LogMsg: "
0830: + (new Date(notification
0831: .getTimeStamp()))
0832: .toString()
0833: + " "
0834: + notification.getType()
0835: + " "
0836: + notification.getMessage()
0837: + " Severity = "
0838: + (String) descriptor
0839: .getFieldValue(DescriptorConstants.NOTIFICATION_SEVERITY));
0840: } catch (Exception e) {
0841: e.printStackTrace();
0842: }
0843: }
0844: }
0845: }
0846: generalBroadcaster.sendNotification(notification);
0847: }
0848:
0849: /**
0850: * Sends a Notification which contains the text string that is passed in
0851: * to the registered Notification listeners on the ModelMBean.
0852: *
0853: * @param message The text which is to be passed in the Notification to the 'handleNotification'
0854: * method of the listener object.
0855: * the constructed Notification will be:
0856: * type "jmx.modelmbean.general"
0857: * source this ModelMBean instance
0858: * sequence 1
0859: *
0860: * @exception MBeanException for implementation exceptions
0861: * @exception RuntimeOperationsException to wrapper IllegalArugementExceptions
0862: *
0863: */
0864: public void sendNotification(String message) throws MBeanException,
0865: RuntimeOperationsException {
0866: if (message == null)
0867: throw new RuntimeOperationsException(
0868: new IllegalArgumentException(
0869: "notification message must not be null"),
0870: "Exception occured trying to send a text notification from a ModelMBean");
0871: Notification notification = new Notification(
0872: "jmx.modelmbean.generic", this , 1L, message);
0873: sendNotification(notification);
0874: }
0875:
0876: /**
0877: * Returns the array of Notifications always generated by the RequiredModelMBean.
0878: * This will include those specified by the application plus the jmx.modelmbean.generic and
0879: * jmx.attribute.change notifications.
0880: *
0881: * @return MBeanNotificationInfo[]
0882: *
0883: */
0884: public MBeanNotificationInfo[] getNotificationInfo() {
0885: MBeanNotificationInfo[] mbeanNotificationInfos = modelMBeanInfo
0886: .getNotifications();
0887: ModelMBeanNotificationInfo[] notificationInfos = {
0888: genericNotificationInfo,
0889: attributeChangeNotificationInfo };
0890: if (mbeanNotificationInfos == null
0891: || mbeanNotificationInfos.length == 0)
0892: return notificationInfos;
0893: List infos = new ArrayList(Arrays.asList(notificationInfos));
0894: infos.addAll(Arrays.asList(mbeanNotificationInfos));
0895: return (MBeanNotificationInfo[]) infos
0896: .toArray(new MBeanNotificationInfo[0]);
0897: }
0898:
0899: /**
0900: * Registers an object which implements the NotificationListener interface as a listener. This
0901: * object's 'handleNotification()' method will be invoked when any attributeChangeNotification is issued through
0902: * or by the ModelMBean. This does not include other Notifications. They must be registered
0903: * for independently. An AttributeChangeNotification will be generated for this attributeName.
0904: *
0905: * @param listener The listener object which will handles notifications emitted by the registered MBean.
0906: * @param attributeName The name of the ModelMBean attributeName for which to receive change notifications.
0907: * If null, then all attributeName changes will cause an attributeChangeNotification to be issued.
0908: * @param handback The context to be sent to the listener with the notification when a notification is emitted.
0909: *
0910: * @exception IllegalArgumentException The MBean name doesn't correspond to a registered MBean.
0911: *
0912: */
0913: public void addAttributeChangeNotificationListener(
0914: NotificationListener listener, String attributeName,
0915: Object handback) throws MBeanException,
0916: RuntimeOperationsException, IllegalArgumentException {
0917: if (listener == null)
0918: throw new IllegalArgumentException(
0919: "Listener to be registered must not be null");
0920: AttributeChangeNotificationFilter filter = new AttributeChangeNotificationFilter();
0921: MBeanAttributeInfo[] attributeInfos = modelMBeanInfo
0922: .getAttributes();
0923: if (attributeInfos == null || attributeInfos.length == 0)
0924: return;
0925: boolean exists = false;
0926: if (attributeName == null) { // attributeName is null, enable filter for all notification
0927: for (int i = 0; i < attributeInfos.length; i++)
0928: filter.enableAttribute(attributeInfos[i].getName());
0929: } else {
0930: for (int j = 0; j < attributeInfos.length; j++) {
0931: if (attributeName.equals(attributeInfos[j].getName())) {
0932: exists = true;
0933: filter.enableAttribute(attributeName);
0934: break;
0935: }
0936: }
0937: if (!exists) // attributeName not exist
0938: throw new RuntimeOperationsException(
0939: new IllegalArgumentException(
0940: "The attributeName " + attributeName
0941: + " does not exist"),
0942: "Exception occured trying to add an AttributeChangeNotification listener");
0943: }
0944: attributeBroadcaster.addNotificationListener(listener, filter,
0945: handback);
0946: }
0947:
0948: /**
0949: * Removes a listener for attributeChangeNotifications from the RequiredModelMBean.
0950: *
0951: * @param listener The listener name which was handling notifications emitted by the registered MBean.
0952: * This method will remove all information related to this listener.
0953: * @param attributeName The attributeName for which the listener no longer wants to receive attributeChangeNotifications.
0954: *
0955: * @exception ListenerNotFoundException The couple (listener,handback) is not registered in the MBean.
0956: * The exception message contains either "listener", "handback" or the object name depending on which object cannot be found.
0957: *
0958: */
0959: public void removeAttributeChangeNotificationListener(
0960: NotificationListener listener, String attributeName)
0961: throws MBeanException, RuntimeOperationsException,
0962: ListenerNotFoundException {
0963: if (listener == null)
0964: throw new ListenerNotFoundException(
0965: "Notification listener is null");
0966: if (attributeName == null) {
0967: throw new RuntimeOperationsException(
0968: new IllegalArgumentException(
0969: "Attribute attributeName cannot be null"));
0970: }
0971: MBeanAttributeInfo[] attributeInfos = modelMBeanInfo
0972: .getAttributes();
0973: if (attributeInfos == null || attributeInfos.length == 0)
0974: return;
0975: boolean exists = false;
0976: for (int j = 0; j < attributeInfos.length; j++) {
0977: if (attributeName.equals(attributeInfos[j].getName())) {
0978: exists = true;
0979: break;
0980: }
0981: }
0982: if (!exists) // attributeName not exist
0983: throw new RuntimeOperationsException(
0984: new IllegalArgumentException(
0985: "The attributeName name " + attributeName
0986: + " does not exist"),
0987: "Exception occured trying to remove attributeName change notification listener");
0988: attributeBroadcaster.removeNotificationListener(listener);
0989: }
0990:
0991: /**
0992: * Sends an attributeChangeNotification which is passed in to the registered
0993: * attributeChangeNotification listeners on the ModelMBean.
0994: *
0995: * @param notification The notification which is to be passed to the 'handleNotification' method
0996: * of the listener object.
0997: *
0998: * @exception MBeanException
0999: * @exception RuntimeOperationsException
1000: *
1001: */
1002: public void sendAttributeChangeNotification(
1003: AttributeChangeNotification notification)
1004: throws MBeanException, RuntimeOperationsException {
1005: if (notification == null)
1006: throw new RuntimeOperationsException(
1007: new IllegalArgumentException(
1008: "attribute change notification object must not be null"),
1009: "Exception occured trying to send attribute change notification of a ModelMBean");
1010: Object oldValue = notification.getOldValue();
1011: Object newValue = notification.getNewValue();
1012: if (oldValue == null)
1013: oldValue = "null";
1014: if (newValue == null)
1015: newValue = "null";
1016: Descriptor descriptor = modelMBeanInfo.getDescriptor(
1017: notification.getType(),
1018: DescriptorConstants.NOTIFICATION_TYPE);
1019: if (descriptor != null) {
1020: if (isLogEnabled(descriptor)) {
1021: String logFile = getLogFile(descriptor);
1022: if (logFile != null && logFile.trim().length() != 0) {
1023: try {
1024: writeToLog(logFile,
1025: "LogMsg: "
1026: + (new Date(notification
1027: .getTimeStamp()))
1028: .toString()
1029: + " "
1030: + notification.getType()
1031: + " "
1032: + notification.getMessage()
1033: + " Name = "
1034: + notification
1035: .getAttributeName()
1036: + " Old value = " + oldValue
1037: + " New value = " + newValue);
1038: } catch (Exception e) {
1039: e.printStackTrace();
1040: }
1041: }
1042: }
1043: }
1044: attributeBroadcaster.sendNotification(notification);
1045: }
1046:
1047: /**
1048: * Sends an attributeChangeNotification which contains the old value and new value for the
1049: * attribute to the registered AttributeChangeNotification listeners on the RequiredModelMBean.
1050: * <P>
1051: * @param oldAttribute The origional value for the Attribute
1052: * @param newAttribute The current value for the Attribute
1053: *<P>
1054: * <PRE>
1055: * The constructed attributeChangeNotification will be:
1056: * type "jmx.attribute.change"
1057: * source this RequiredModelMBean instance
1058: * sequence 1
1059: * attributeName oldValue.getNameSpace()
1060: * attributeType oldValue's class
1061: * attributeOldValue oldValue.getValue()
1062: * attributeNewValue newValue.getValue()
1063: * </PRE>
1064: *
1065: * @exception MBeanException to wrapper implementation exceptions
1066: * @exception RuntimeOperationsException to wrapper IllegalArgumentExceptions.
1067: *
1068: */
1069: public void sendAttributeChangeNotification(Attribute oldAttribute,
1070: Attribute newAttribute) throws MBeanException,
1071: RuntimeOperationsException {
1072: if (oldAttribute == null || newAttribute == null)
1073: throw new RuntimeOperationsException(
1074: new IllegalArgumentException(
1075: "Attribute object must not be null"),
1076: "Exception occured trying to send oldAttribute change notification of a ModelMBean");
1077: if (!oldAttribute.getName().equals(newAttribute.getName()))
1078: throw new RuntimeOperationsException(
1079: new IllegalArgumentException(
1080: "Attribute names are not the same"),
1081: "Exception occured trying to send oldAttribute change notification of a ModelMBean");
1082: Object oldValue = newAttribute.getValue();
1083: Object newValue = oldAttribute.getValue();
1084: String attributeType = "unknown";
1085: if (oldValue != null)
1086: attributeType = oldValue.getClass().getName();
1087: if (newValue != null)
1088: attributeType = newValue.getClass().getName();
1089: AttributeChangeNotification notification = new AttributeChangeNotification(
1090: this , 1L, (new Date()).getTime(),
1091: "AttributeChangeDetected", oldAttribute.getName(),
1092: attributeType, oldValue, newValue);
1093: sendAttributeChangeNotification(notification);
1094: }
1095:
1096: public void removeNotificationListener(
1097: NotificationListener listener, NotificationFilter filter,
1098: Object handback) throws ListenerNotFoundException {
1099: if (generalBroadcaster == null) {
1100: throw new ListenerNotFoundException(
1101: "No notification listeners registered");
1102: }
1103: generalBroadcaster.removeNotificationListener(listener, filter,
1104: handback);
1105: }
1106:
1107: public ObjectName preRegister(MBeanServer server, ObjectName name)
1108: throws Exception {
1109: if (name == null)
1110: throw new NullPointerException(
1111: "ObjectName of RequiredModelMBean to registered is null");
1112: defaultRepo = server.getClassLoaderRepository();
1113: return name;
1114: }
1115:
1116: public void postRegister(Boolean registrationDone) {
1117: }
1118:
1119: public void preDeregister() throws Exception {
1120: }
1121:
1122: public void postDeregister() {
1123: }
1124:
1125: private static boolean isCacheValid(int currencyTimeLimit,
1126: long lastTimeStamp) {
1127: boolean cacheValid = false;
1128: if (currencyTimeLimit <= DescriptorConstants.CURRENCYTIMELIMIT_ALWARYSSTALE) { //never Cached
1129: cacheValid = false;
1130: } else if (currencyTimeLimit == DescriptorConstants.CURRENCYTIMELIMIT_NEVERSTALE) { //always valid Cache
1131: cacheValid = true;
1132: } else if (currencyTimeLimit >= DescriptorConstants.CURRENCYTIMELIMIT_CONDITIONSTALE) {
1133: if (System.currentTimeMillis() < lastTimeStamp
1134: + currencyTimeLimit) { // valid cache
1135: cacheValid = true;
1136: } else { // cache expired
1137: cacheValid = false;
1138: }
1139: } else {
1140: throw new RuntimeException("error currencyTimeLimit: "
1141: + currencyTimeLimit + ", must be -1, 0, 1");
1142: }
1143:
1144: return cacheValid;
1145:
1146: }
1147:
1148: private int getCurrencyTimeLimit(Descriptor descriptor)
1149: throws MBeanException {
1150: String currencyTimeLimit = "-1";
1151: if (descriptor != null) {
1152: Object currencyTimeLimitObj = descriptor
1153: .getFieldValue(DescriptorConstants.CURRENCYTIMELIMIT);
1154: if (currencyTimeLimitObj != null)
1155: currencyTimeLimit = currencyTimeLimitObj.toString();
1156: } else {
1157: Descriptor mbeanDescriptor = modelMBeanInfo
1158: .getMBeanDescriptor();
1159: Object mbeanCurrencyTimeLimitObj = mbeanDescriptor
1160: .getFieldValue(DescriptorConstants.CURRENCYTIMELIMIT);
1161: if (mbeanCurrencyTimeLimitObj != null)
1162: currencyTimeLimit = mbeanCurrencyTimeLimitObj
1163: .toString();
1164: }
1165: return Integer.parseInt(currencyTimeLimit);
1166: }
1167:
1168: private long getLastTimeStamp(Descriptor descriptor)
1169: throws MBeanException {
1170: Object lastUpdatedTimeStampObj = null;
1171: String descriptorType = (String) descriptor
1172: .getFieldValue(DescriptorConstants.DESCRIPTORTYPE);
1173:
1174: if (descriptorType
1175: .equalsIgnoreCase(DescriptorConstants.OPERATION_TYPE)) {
1176: lastUpdatedTimeStampObj = descriptor
1177: .getFieldValue(DescriptorConstants.OPERATION_LASTRETURNEDTIMESTAMP);
1178: } else if (descriptorType
1179: .equalsIgnoreCase(DescriptorConstants.ATTRIBUTE_TYPE)) {
1180: lastUpdatedTimeStampObj = descriptor
1181: .getFieldValue(DescriptorConstants.ATTRIBUTE_LASTUPDATEDTIMESTAMP);
1182: } else {
1183: throw new MBeanException(new RuntimeException(
1184: "Descriptor: " + descriptor
1185: + " not support LastTimeStamp"));
1186: }
1187: String lastUpdatedTimeStampStr = lastUpdatedTimeStampObj == null ? "0"
1188: : lastUpdatedTimeStampObj.toString();
1189: return Long.parseLong(lastUpdatedTimeStampStr);
1190: }
1191:
1192: private Object getTargetObject(Descriptor descriptor)
1193: throws MBeanException {
1194: Object targetObject = managedResource;
1195: String targetType = DescriptorConstants.OPERATION_TARGETTYPE_OBJECTREFERENCE;
1196: String descriptorType = (String) descriptor
1197: .getFieldValue(DescriptorConstants.DESCRIPTORTYPE);
1198:
1199: if (descriptorType
1200: .equalsIgnoreCase(DescriptorConstants.OPERATION_TYPE)) { // operation descriptor
1201: Object _targetObject = descriptor
1202: .getFieldValue(DescriptorConstants.OPERATION_TARGETOBJECT);
1203: String _targetType = (String) descriptor
1204: .getFieldValue(DescriptorConstants.OPERATION_TARGETTYPE);
1205: if (_targetObject != null)
1206: targetObject = _targetObject;
1207: if (_targetType != null)
1208: targetType = _targetType;
1209: }
1210:
1211: if (!isResourceTypeSupported(targetType)) {
1212: // System.out.println("$$$$$$$$$$$$$$$$$RequiredModelMbean:554 " + targetType);
1213: throw new MBeanException(
1214: new InvalidTargetObjectTypeException(targetType),
1215: targetType);
1216: }
1217: return targetObject;
1218: }
1219:
1220: private boolean isLogEnabled(Descriptor descriptor)
1221: throws MBeanException {
1222: String isLogEnabled = getDescriptorValue(descriptor,
1223: DescriptorConstants.LOG);
1224: if (isLogEnabled == null || isLogEnabled.trim().length() == 0)
1225: return false;
1226: else if (isLogEnabled
1227: .equalsIgnoreCase(DescriptorConstants.TRUE)
1228: || isLogEnabled.equalsIgnoreCase(Boolean.TRUE
1229: .toString()))
1230: return true;
1231: else
1232: return false;
1233: }
1234:
1235: private String getLogFile(Descriptor descriptor)
1236: throws MBeanException {
1237: return getDescriptorValue(descriptor,
1238: DescriptorConstants.LOGFILE);
1239: }
1240:
1241: private String getPersistentPolicy(Descriptor descriptor)
1242: throws MBeanException {
1243: return getDescriptorValue(descriptor,
1244: DescriptorConstants.PERSISTPOLICY);
1245: }
1246:
1247: private long getPersistentPeriod(Descriptor descriptor)
1248: throws MBeanException {
1249: String pperiod = getDescriptorValue(descriptor,
1250: DescriptorConstants.PERSISTPERIOD);
1251: if (pperiod == null) {
1252: return -1;
1253: } else {
1254: try {
1255: return Integer.parseInt(pperiod);
1256: } catch (Exception e) {
1257: e.printStackTrace();
1258: return -1;
1259: }
1260: }
1261: }
1262:
1263: private String getDescriptorValue(Descriptor descriptor,
1264: String fieldName) throws MBeanException {
1265: Descriptor mbeanDescriptor = modelMBeanInfo
1266: .getMBeanDescriptor();
1267: String value = (String) descriptor.getFieldValue(fieldName);
1268: if (value == null && mbeanDescriptor != null) {
1269: value = (String) mbeanDescriptor
1270: .getFieldValue(DescriptorConstants.PERSISTPOLICY);
1271: }
1272: if (value == null
1273: || (value != null && value.trim().length() == 0)) {
1274: return null;
1275: }
1276: return value.trim();
1277:
1278: }
1279:
1280: private boolean isResourceTypeSupported(String resourceType) {
1281: if (resourceType == null)
1282: return false;
1283: if (resourceType
1284: .equalsIgnoreCase(DescriptorConstants.OPERATION_TARGETTYPE_OBJECTREFERENCE)
1285: || resourceType
1286: .equalsIgnoreCase(DescriptorConstants.OPERATION_TARGETTYPE_EJBHANDLE)
1287: || resourceType
1288: .equalsIgnoreCase(DescriptorConstants.OPERATION_TARGETTYPE_HANDLE)
1289: || resourceType
1290: .equalsIgnoreCase(DescriptorConstants.OPERATION_TARGETTYPE_IOR)
1291: || resourceType
1292: .equalsIgnoreCase(DescriptorConstants.OPERATION_TARGETTYPE_RMIREFERENCE)) {
1293: return true;
1294: }
1295: return false;
1296: }
1297:
1298: private Object reflectInvoke(Object obj, String method,
1299: Object[] params, Class[] signatures) throws MBeanException,
1300: ReflectionException {
1301: try {
1302: // System.out.println("$$$$$$$$$RequiredModelMBean:596 " + obj.getClass().getNameSpace() +":" +method + ":" + params + ":" + signatures);
1303: if (params == null)
1304: params = new Object[0];
1305: return obj.getClass().getMethod(method, signatures).invoke(
1306: obj, params);
1307: } catch (NoSuchMethodException e) {
1308: throw new ReflectionException(e, e.toString());
1309: } catch (IllegalAccessException e) {
1310: throw new ReflectionException(e, e.toString());
1311: } catch (IllegalArgumentException e) {
1312: throw new MBeanException(e, e.toString());
1313: } catch (InvocationTargetException e) {
1314: Throwable thrw = e.getTargetException();
1315: if (thrw instanceof RuntimeException)
1316: throw new RuntimeMBeanException(
1317: (RuntimeException) thrw, thrw.toString());
1318: if (thrw instanceof Error)
1319: throw new RuntimeErrorException((Error) thrw, thrw
1320: .toString());
1321: else
1322: throw new MBeanException((Exception) thrw, thrw
1323: .toString());
1324: }
1325:
1326: }
1327:
1328: /**
1329: * Write the Log if the Descriptor's Log and LogFile are defined
1330: * @ todo use log4j or logBroadCast instead
1331: * @param filename
1332: * @param message
1333: * @throws Exception
1334: */
1335: private synchronized static void writeToLog(String filename,
1336: String message) throws Exception {
1337: if (filename == null || message == null) {
1338: return;
1339: }
1340: PrintWriter out = new PrintWriter(
1341: new FileWriter(filename, true));
1342: out.println(message);
1343: out.close();
1344: }
1345:
1346: // use to check the parameter and return type
1347: private static boolean checkAssignability(Class parameter,
1348: Class declared) {
1349: boolean assignable = PrimitiveClassLoader.getInstance()
1350: .isAssignable(parameter, declared);
1351: if (assignable == false) // may be not primitive class
1352: assignable = declared.isAssignableFrom(parameter);
1353: return assignable;
1354: }
1355:
1356: /*
1357: // because the Persistenter is a MBean. if Persistenter is not registered , register it use the default ObjectName
1358: private ObjectName getPersistenterObjectName() throws ReflectionException, MBeanException, InstanceAlreadyExistsException, NotCompliantMBeanException {
1359: if(!server.isRegistered(FilePersistenter.DEFAULT_OBJECTNAME)){
1360: server.createMBean(FilePersistenter.class.getNameSpace(),FilePersistenter.DEFAULT_OBJECTNAME);
1361: }
1362: return FilePersistenter.DEFAULT_OBJECTNAME;
1363: }
1364: */
1365:
1366: /* get the filename to persistent
1367: *
1368: */
1369: private String getPersistentIdentity() throws MBeanException {
1370: Descriptor mbeanDescriptor = modelMBeanInfo
1371: .getMBeanDescriptor();
1372: if (mbeanDescriptor == null) { // not MBeanDescriptor, use a default filename
1373: return getDefualtPersistentFile() + ".ser";
1374: } else { // compound persistLocation and persistName as filename
1375: String location = (String) mbeanDescriptor
1376: .getFieldValue(DescriptorConstants.PERSISTLOCATION);
1377: if (location == null) {
1378: location = "";
1379: } else {
1380: File dir = new File(location);
1381: if (!dir.exists()) {
1382: boolean boo = dir.mkdirs();
1383: if (boo == false) {
1384: throw new RuntimeException(
1385: "can not doCreate directories: "
1386: + dir.toString());
1387: }
1388: }
1389: if (!dir.isDirectory() || !dir.canWrite()) {
1390: throw new RuntimeException(dir.toString()
1391: + " is not a directory or is not writable.");
1392: }
1393: }
1394: String filename = (String) mbeanDescriptor
1395: .getFieldValue(DescriptorConstants.PERSISTNAME);
1396: if (filename == null) {
1397: filename = (String) mbeanDescriptor
1398: .getFieldValue(DescriptorConstants.NAME);
1399: }
1400:
1401: if (filename == null) {
1402: filename = getDefualtPersistentFile();
1403: }
1404:
1405: filename += ".ser";
1406:
1407: if (location.length() > 0) {
1408: filename = location + File.separator + filename;
1409: ;
1410: }
1411: return filename;
1412: }
1413: }
1414:
1415: private String getDefualtPersistentFile() {
1416: String identity = getClass().getName() + "_";
1417: if (managedResource != null) {
1418: identity += managedResource.getClass().getName();
1419: }
1420: return identity;
1421: }
1422:
1423: // test whether the a descriptor need to be persist or not
1424: private boolean needPersist(Descriptor descriptor)
1425: throws MBeanException {
1426: String persistPolicy = getPersistentPolicy(descriptor);
1427:
1428: if (persistPolicy
1429: .equalsIgnoreCase(DescriptorConstants.PERSISTPOLICY_NEVER)) {
1430: return false;
1431: } else if (persistPolicy
1432: .equalsIgnoreCase(DescriptorConstants.PERSISTPOLICY_ONUPDATE)) {
1433: return true;
1434: } else if (persistPolicy
1435: .equalsIgnoreCase(DescriptorConstants.PERSISTPOLICY_NOMOREOFTENTHAN)) {
1436: long period = getPersistentPeriod(descriptor);
1437: long now = System.currentTimeMillis();
1438: long lastUpdate = getLastTimeStamp(descriptor);
1439: if (now - lastUpdate > period) {
1440: return true;
1441: } else {
1442: return false;
1443: }
1444: } else if (persistPolicy
1445: .equalsIgnoreCase(DescriptorConstants.PERSISTPOLICY_ONTIMER)) {
1446: // if period expired, persist every time
1447: long period = getPersistentPeriod(descriptor);
1448: long now = System.currentTimeMillis();
1449: if (now > period) {
1450: return true;
1451: } else {
1452: return false;
1453: }
1454: } else {
1455: return false;
1456: }
1457: }
1458:
1459: }
|