    1   /*-
    2   * See the file LICENSE for redistribution information.
    3   *
    4   * Copyright (c) 2002-2005
    5   *      Sleepycat Software.  All rights reserved.
    6   *
    7   * $Id: JEApplicationMBean.java 4644 2006-09-20 22:40:21Z paul_jack $
    8   */
    9
    10  package org.archive.util;
    11
    12  import java.lang.reflect.Constructor;
    13  import java.util.List;
    14
    15  import javax.management.Attribute;
    16  import javax.management.AttributeList;
    17  import javax.management.AttributeNotFoundException;
    18  import javax.management.DynamicMBean;
    19  import javax.management.InvalidAttributeValueException;
    20  import javax.management.MBeanAttributeInfo;
    21  import javax.management.MBeanConstructorInfo;
    22  import javax.management.MBeanException;
    23  import javax.management.MBeanInfo;
    24  import javax.management.MBeanNotificationInfo;
    25  import javax.management.MBeanOperationInfo;
    26
    27  import com.sleepycat.je.DatabaseException;
    28  import com.sleepycat.je.Environment;
    29
    30  /***
    31   * JEApplicationMBean is an example of how a JE application can incorporate JE
    32   * monitoring into its existing MBean.  It may be installed as is, or used as a
    33   * starting point for building a MBean which includes JE support.
    34   * <p>
    35   * JE management is divided between the JEApplicationMBean class and
    36   * JEMBeanHelper class. JEApplicationMBean contains an instance of
    37   * JEMBeanHelper, which knows about JE attributes, operations and
    38   * notifications. JEApplicationMBean itself has the responsibility of
    39   * configuring, opening and closing the JE environment along with any other
    40   * resources used by the application, and maintains a
    41   * com.sleepycat.je.Environment handle.
    42   * <p>
    43   * The approach taken for accessing the environment is an application specific
    44   * choice. Some of the salient considerations are:
    45   * <ul>
    46   * <li>Applications may open one or many Environment objects per process
    47   * against a given environment.</li>
    48   *
    49   * <li>All Environment handles reference the same underlying JE environment
    50   * implementation object.</li>
    51
    52   * <li> The first Environment object instantiated in the process does the real
    53   * work of configuring and opening the environment. Follow-on instantiations of
    54   * Environment merely increment a reference count. Likewise,
    55   * Environment.close() only does real work when it's called by the last
    56   * Environment object in the process. </li>
    57   * </ul>
    58   * <p>
    59   * Another MBean approach for environment access can be seen in
    60   * com.sleepycat.je.jmx.JEMonitor. That MBean does not take responsibility for
    61   * opening and closing environments, and can only operate against already-open
    62   * environments.
    63   * <p>This bean was copied from bdb je 2.0 source and modified so could pass
    64   * in and monitor an environment created externally.  Also added toString
    65   * versions of the locks and stats calls since the objects don't seem to
    66   * make it over the RMI divide (Not serializable.  St.Ack
    67   */
    68
    69  public class JEApplicationMBean implements DynamicMBean {
    70
    71      private static final String DESCRIPTION =
    72          "A MBean for an application which uses JE. Provides open and close " +
    73          "operations which configure and open a JE environment as part of the "+
    74          "applications's resources. Also supports general JE monitoring.";
    75
    76      private MBeanInfo mbeanInfo;    // this MBean's visible interface.
    77      private JEMBeanHelper jeHelper; // gets JE management interface
    78      private Environment targetEnv;  // saved environment handle
    79
    80      /***
    81       * This MBean provides an open operation to open the JE environment.
    82       */
    83      public  static final String OP_OPEN = "openJE";
    84
    85      /***
    86       * This MBean provides a close operation to release the JE environment.
    87       * Note that environments must be closed to release resources.
    88       */
    89      public static final String OP_CLOSE = "closeJE";
    90
    91      /***
    92       * Instantiate a JEApplicationMBean
    93       *
    94       * @param env Environment to use.  Externally managed.
    95       * @throws DatabaseException
    96       */
    97      public JEApplicationMBean(Environment env) throws DatabaseException {
    98          this.targetEnv = env;
    99          jeHelper = new JEMBeanHelper(env.getConfig(), env.getHome(), true);
    100         resetMBeanInfo();
    101     }
    102
    103     /***
    104      * @see DynamicMBean#getAttribute
    105      */
    106     public Object getAttribute(String attributeName)
    107         throws AttributeNotFoundException,
    108                MBeanException {
    109
    110     	return jeHelper.getAttribute(targetEnv, attributeName);
    111     }
    112
    113     /***
    114      * @see DynamicMBean#setAttribute
    115      */
    116     public void setAttribute(Attribute attribute)
    117         throws AttributeNotFoundException,
    118                InvalidAttributeValueException {
    119
    120         jeHelper.setAttribute(targetEnv, attribute);
    121     }
    122
    123     /***
    124      * @see DynamicMBean#getAttributes
    125      */
    126     public AttributeList getAttributes(String[] attributes) {
    127
    128         /* Sanity checking. */
    129 	if (attributes == null) {
    130 	    throw new IllegalArgumentException("Attributes cannot be null");
    131 	}
    132
    133         /* Get each requested attribute. */
    134         AttributeList results = new AttributeList();
    135         for (int i = 0; i < attributes.length; i++) {
    136             try {
    137                 String name = attributes[i];
    138                 Object value = jeHelper.getAttribute(targetEnv, name);
    139                 results.add(new Attribute(name, value));
    140             } catch (Exception e) {
    141                 e.printStackTrace();
    142             }
    143         }
    144         return results;
    145     }
    146
    147     /***
    148      * @see DynamicMBean#setAttributes
    149      */
    150     public AttributeList setAttributes(AttributeList attributes) {
    151
    152         /* Sanity checking. */
    153 	if (attributes == null) {
    154 	    throw new IllegalArgumentException("attribute list can't be null");
    155 	}
    156
    157         /* Set each attribute specified. */
    158 	AttributeList results = new AttributeList();
    159         for (int i = 0; i < attributes.size(); i++) {
    160             Attribute attr = (Attribute) attributes.get(i);
    161             try {
    162                 /* Set new value. */
    163                 jeHelper.setAttribute(targetEnv, attr);
    164
    165                 /*
    166                  * Add the name and new value to the result list. Be sure
    167                  * to ask the MBean for the new value, rather than simply
    168                  * using attr.getValue(), because the new value may not
    169                  * be same if it is modified according to the JE
    170                  * implementation.
    171                  */
    172                 String name = attr.getName();
    173                 Object newValue = jeHelper.getAttribute(targetEnv, name);
    174                 results.add(new Attribute(name, newValue));
    175             } catch (Exception e) {
    176                 e.printStackTrace();
    177             }
    178         }
    179         return results;
    180     }
    181
    182     /***
    183      * @see DynamicMBean#invoke
    184      */
    185     public Object invoke(String actionName,
    186                          Object[] params,
    187                          String[] signature)
    188         throws MBeanException {
    189
    190         Object result = null;
    191
    192         if (actionName == null) {
    193             throw new IllegalArgumentException("actionName cannot be null");
    194         }
    195 // Don't allow opening and closing of environment.  It was created
    196 // externally.  St.Ack
    197 //
    198 //        if (actionName.equals(OP_OPEN)) {
    199 //            openEnvironment();
    200 //            return null;
    201 //        } else if (actionName.equals(OP_CLOSE)) {
    202 //            closeEnvironment();
    203 //            return null;
    204 //        } else {
    205             result = jeHelper.invoke(targetEnv, actionName, params, signature);
    206 //        }
    207
    208         return result;
    209     }
    210
    211     /***
    212      * @see DynamicMBean#getMBeanInfo
    213      */
    214     public MBeanInfo getMBeanInfo() {
    215 	return mbeanInfo;
    216     }
    217
    218     /***
    219      * Create the available management interface for this environment.
    220      * The attributes and operations available vary according to
    221      * environment configuration.
    222      *
    223      */
    224     private synchronized void resetMBeanInfo() {
    225
    226         /*
    227          * Get JE attributes, operation and notification information
    228          * from JEMBeanHelper. An application may choose to add functionality
    229          * of its own when constructing the MBeanInfo.
    230          */
    231
    232         /* Attributes. */
    233         List<MBeanAttributeInfo> attributeList =  jeHelper.getAttributeList(targetEnv);
    234         MBeanAttributeInfo [] attributeInfo =
    235             new MBeanAttributeInfo[attributeList.size()];
    236         attributeList.toArray(attributeInfo);
    237
    238         /* Constructors. */
    239         Constructor [] constructors = this.getClass().getConstructors();
    240         MBeanConstructorInfo [] constructorInfo =
    241             new MBeanConstructorInfo[constructors.length];
    242         for (int i = 0; i < constructors.length; i++) {
    243             constructorInfo[i] =
    244                 new MBeanConstructorInfo(this.getClass().getName(),
    245                                          constructors[i]);
    246         }
    247
    248         /* Operations. */
    249
    250         /*
    251          * Get the list of operations available from the jeHelper. Then add
    252          * an open and close operation.
    253          */
    254         List<MBeanOperationInfo> operationList = jeHelper.getOperationList(targetEnv);
    255         /* Don't allow opening or closing remotely.
    256         if (targetEnv == null) {
    257             operationList.add(
    258              new MBeanOperationInfo(OP_OPEN,
    259                                     "Configure and open the JE environment.",
    260                                     new MBeanParameterInfo[0], // no params
    261                                     "java.lang.Boolean",
    262                                     MBeanOperationInfo.ACTION_INFO));
    263         } else {
    264             operationList.add(
    265              new MBeanOperationInfo(OP_CLOSE,
    266                                     "Close the JE environment.",
    267                                     new MBeanParameterInfo[0], // no params
    268                                     "void",
    269                                     MBeanOperationInfo.ACTION_INFO));
    270         }
    271         */
    272
    273         MBeanOperationInfo [] operationInfo =
    274             new MBeanOperationInfo[operationList.size()];
    275         operationList.toArray(operationInfo);
    276
    277         /* Notifications. */
    278         MBeanNotificationInfo [] notificationInfo =
    279             jeHelper.getNotificationInfo(targetEnv);
    280
    281         /* Generate the MBean description. */
    282         mbeanInfo = new MBeanInfo(this.getClass().getName(),
    283                                   DESCRIPTION,
    284                                   attributeInfo,
    285                                   constructorInfo,
    286                                   operationInfo,
    287                                   notificationInfo);
    288     }
    289
    290     /***
    291      * Open a JE environment using the configuration specified through
    292      * MBean attributes and recorded within the JEMBeanHelper.
    293      */
    294 //    private  void openEnvironment()
    295 //        throws MBeanException {
    296 //
    297 //        try {
    298 //            if (targetEnv == null) {
    299 //                /*
    300 //                 * The environment configuration has been set through
    301 //                 * mbean attributes managed by the JEMBeanHelper.
    302 //                 */
    303 //                targetEnv =
    304 //                    new Environment(jeHelper.getEnvironmentHome(),
    305 //                                    jeHelper.getEnvironmentOpenConfig());
    306 //                resetMBeanInfo();
    307 //            }
    308 //        } catch (DatabaseException e) {
    309 //            throw new MBeanException(e);
    310 //        }
    311 //    }
    312
    313     /***
    314      * Release the environment handle contained within the MBean to properly
    315      * release resources.
    316      */
    317 //    private void closeEnvironment()
    318 //        throws MBeanException {
    319 //
    320 //        try {
    321 //            if (targetEnv != null) {
    322 //                targetEnv.close();
    323 //                targetEnv = null;
    324 //                resetMBeanInfo();
    325 //            }
    326 //        } catch (DatabaseException e) {
    327 //            throw new MBeanException(e);
    328 //        }
    329 //    }
    330 }