je/examples/jmx/JEApplicationMBean.java

330 lines
11 KiB
Java
Raw Normal View History

2021-06-06 17:46:45 +00:00
/*-
* Copyright (C) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle Berkeley
* DB Java Edition made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
* license and additional information.
*/
package jmx;
import java.io.File;
import java.lang.reflect.Constructor;
import java.util.List;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InvalidAttributeValueException;
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.MBeanParameterInfo;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.jmx.JEMBeanHelper;
/**
* JEApplicationMBean is an example of how a JE application can incorporate JE
* monitoring into its existing MBean. It may be installed as is, or used as a
* starting point for building a MBean which includes JE support.
* <p>
* JE management is divided between the JEApplicationMBean class and
* JEMBeanHelper class. JEApplicationMBean contains an instance of
* JEMBeanHelper, which knows about JE attributes, operations and
* notifications. JEApplicationMBean itself has the responsibility of
* configuring, opening and closing the JE environment along with any other
* resources used by the application, and maintains a
* com.sleepycat.je.Environment handle.
* <p>
* The approach taken for accessing the environment is an application specific
* choice. Some of the salient considerations are:
* <ul>
* <li>Applications may open one or many Environment objects per process
* against a given environment.</li>
*
* <li>All Environment handles reference the same underlying JE environment
* implementation object.</li>
* <li> The first Environment object instantiated in the process does the real
* work of configuring and opening the environment. Follow-on instantiations of
* Environment merely increment a reference count. Likewise,
* Environment.close() only does real work when it's called by the last
* Environment object in the process. </li>
* </ul>
* <p>
* Another MBean approach for environment access can be seen in
* com.sleepycat.je.jmx.JEMonitor. That MBean does not take responsibility for
* opening and closing environments, and can only operate against already-open
* environments.
*/
public class JEApplicationMBean implements DynamicMBean {
private static final String DESCRIPTION =
"A MBean for an application which uses JE. Provides open and close " +
"operations which configure and open a JE environment as part of the "+
"applications's resources. Also supports general JE monitoring.";
private MBeanInfo mbeanInfo; // this MBean's visible interface.
private JEMBeanHelper jeHelper; // gets JE management interface
private Environment targetEnv; // saved environment handle
/**
* This MBean provides an open operation to open the JE environment.
*/
public static final String OP_OPEN = "openJE";
/**
* This MBean provides a close operation to release the JE environment.
* Note that environments must be closed to release resources.
*/
public static final String OP_CLOSE = "closeJE";
/**
* Instantiate a JEApplicationMBean
*
* @param environmentHome home directory of the target JE environment.
*/
public JEApplicationMBean(String environmentHome) {
File environmentDirectory = new File(environmentHome);
jeHelper = new JEMBeanHelper(environmentDirectory, true);
resetMBeanInfo();
}
/**
* @see DynamicMBean#getAttribute
*/
public Object getAttribute(String attributeName)
throws AttributeNotFoundException,
MBeanException {
return jeHelper.getAttribute(targetEnv, attributeName);
}
/**
* @see DynamicMBean#setAttribute
*/
public void setAttribute(Attribute attribute)
throws AttributeNotFoundException,
InvalidAttributeValueException {
jeHelper.setAttribute(targetEnv, attribute);
}
/**
* @see DynamicMBean#getAttributes
*/
public AttributeList getAttributes(String[] attributes) {
/* Sanity checking. */
if (attributes == null) {
throw new IllegalArgumentException("Attributes cannot be null");
}
/* Get each requested attribute. */
AttributeList results = new AttributeList();
for (int i = 0; i < attributes.length; i++) {
try {
String name = attributes[i];
Object value = jeHelper.getAttribute(targetEnv, name);
results.add(new Attribute(name, value));
} catch (Exception e) {
e.printStackTrace();
}
}
return results;
}
/**
* @see DynamicMBean#setAttributes
*/
public AttributeList setAttributes(AttributeList attributes) {
/* Sanity checking. */
if (attributes == null) {
throw new IllegalArgumentException("attribute list can't be null");
}
/* Set each attribute specified. */
AttributeList results = new AttributeList();
for (int i = 0; i < attributes.size(); i++) {
Attribute attr = (Attribute) attributes.get(i);
try {
/* Set new value. */
jeHelper.setAttribute(targetEnv, attr);
/*
* Add the name and new value to the result list. Be sure
* to ask the MBean for the new value, rather than simply
* using attr.getValue(), because the new value may not
* be same if it is modified according to the JE
* implementation.
*/
String name = attr.getName();
Object newValue = jeHelper.getAttribute(targetEnv, name);
results.add(new Attribute(name, newValue));
} catch (Exception e) {
e.printStackTrace();
}
}
return results;
}
/**
* @see DynamicMBean#invoke
*/
public Object invoke(String actionName,
Object[] params,
String[] signature)
throws MBeanException {
Object result = null;
if (actionName == null) {
throw new IllegalArgumentException("actionName cannot be null");
}
if (actionName.equals(OP_OPEN)) {
openEnvironment();
return null;
} else if (actionName.equals(OP_CLOSE)) {
closeEnvironment();
return null;
} else {
result = jeHelper.invoke(targetEnv, actionName, params, signature);
}
return result;
}
/**
* @see DynamicMBean#getMBeanInfo
*/
public MBeanInfo getMBeanInfo() {
return mbeanInfo;
}
/**
* Create the available management interface for this environment.
* The attributes and operations available vary according to
* environment configuration.
*
*/
private synchronized void resetMBeanInfo() {
/*
* Get JE attributes, operation and notification information
* from JEMBeanHelper. An application may choose to add functionality
* of its own when constructing the MBeanInfo.
*/
/* Attributes. */
List attributeList = jeHelper.getAttributeList(targetEnv);
MBeanAttributeInfo[] attributeInfo =
new MBeanAttributeInfo[attributeList.size()];
attributeList.toArray(attributeInfo);
/* Constructors. */
Constructor[] constructors = this.getClass().getConstructors();
MBeanConstructorInfo[] constructorInfo =
new MBeanConstructorInfo[constructors.length];
for (int i = 0; i < constructors.length; i++) {
constructorInfo[i] =
new MBeanConstructorInfo(this.getClass().getName(),
constructors[i]);
}
/* Operations. */
/*
* Get the list of operations available from the jeHelper. Then add
* an open and close operation.
*/
List operationList = jeHelper.getOperationList(targetEnv);
if (targetEnv == null) {
operationList.add(
new MBeanOperationInfo(OP_OPEN,
"Configure and open the JE environment.",
new MBeanParameterInfo[0], // no params
"java.lang.Boolean",
MBeanOperationInfo.ACTION_INFO));
} else {
operationList.add(
new MBeanOperationInfo(OP_CLOSE,
"Close the JE environment.",
new MBeanParameterInfo[0], // no params
"void",
MBeanOperationInfo.ACTION_INFO));
}
MBeanOperationInfo[] operationInfo =
new MBeanOperationInfo[operationList.size()];
operationList.toArray(operationInfo);
/* Notifications. */
MBeanNotificationInfo[] notificationInfo =
jeHelper.getNotificationInfo(targetEnv);
/* Generate the MBean description. */
mbeanInfo = new MBeanInfo(this.getClass().getName(),
DESCRIPTION,
attributeInfo,
constructorInfo,
operationInfo,
notificationInfo);
}
/**
* Open a JE environment using the configuration specified through
* MBean attributes and recorded within the JEMBeanHelper.
*/
private void openEnvironment()
throws MBeanException {
try {
if (targetEnv == null) {
/*
* The environment configuration has been set through
* mbean attributes managed by the JEMBeanHelper.
*/
targetEnv =
new Environment(jeHelper.getEnvironmentHome(),
jeHelper.getEnvironmentOpenConfig());
resetMBeanInfo();
}
} catch (DatabaseException e) {
throw new MBeanException(e);
}
}
/**
* Release the environment handle contained within the MBean to properly
* release resources.
*/
private void closeEnvironment()
throws MBeanException {
try {
if (targetEnv != null) {
targetEnv.close();
targetEnv = null;
resetMBeanInfo();
}
} catch (DatabaseException e) {
throw new MBeanException(e);
}
}
}