001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002-2005
005: * Sleepycat Software. All rights reserved.
006: *
007: * $Id: JEApplicationMBean.java 4644 2006-09-20 22:40:21Z paul_jack $
008: */
009:
010: package org.archive.util;
011:
012: import java.lang.reflect.Constructor;
013: import java.util.List;
014:
015: import javax.management.Attribute;
016: import javax.management.AttributeList;
017: import javax.management.AttributeNotFoundException;
018: import javax.management.DynamicMBean;
019: import javax.management.InvalidAttributeValueException;
020: import javax.management.MBeanAttributeInfo;
021: import javax.management.MBeanConstructorInfo;
022: import javax.management.MBeanException;
023: import javax.management.MBeanInfo;
024: import javax.management.MBeanNotificationInfo;
025: import javax.management.MBeanOperationInfo;
026:
027: import com.sleepycat.je.DatabaseException;
028: import com.sleepycat.je.Environment;
029:
030: /**
031: * JEApplicationMBean is an example of how a JE application can incorporate JE
032: * monitoring into its existing MBean. It may be installed as is, or used as a
033: * starting point for building a MBean which includes JE support.
034: * <p>
035: * JE management is divided between the JEApplicationMBean class and
036: * JEMBeanHelper class. JEApplicationMBean contains an instance of
037: * JEMBeanHelper, which knows about JE attributes, operations and
038: * notifications. JEApplicationMBean itself has the responsibility of
039: * configuring, opening and closing the JE environment along with any other
040: * resources used by the application, and maintains a
041: * com.sleepycat.je.Environment handle.
042: * <p>
043: * The approach taken for accessing the environment is an application specific
044: * choice. Some of the salient considerations are:
045: * <ul>
046: * <li>Applications may open one or many Environment objects per process
047: * against a given environment.</li>
048: *
049: * <li>All Environment handles reference the same underlying JE environment
050: * implementation object.</li>
051:
052: * <li> The first Environment object instantiated in the process does the real
053: * work of configuring and opening the environment. Follow-on instantiations of
054: * Environment merely increment a reference count. Likewise,
055: * Environment.close() only does real work when it's called by the last
056: * Environment object in the process. </li>
057: * </ul>
058: * <p>
059: * Another MBean approach for environment access can be seen in
060: * com.sleepycat.je.jmx.JEMonitor. That MBean does not take responsibility for
061: * opening and closing environments, and can only operate against already-open
062: * environments.
063: * <p>This bean was copied from bdb je 2.0 source and modified so could pass
064: * in and monitor an environment created externally. Also added toString
065: * versions of the locks and stats calls since the objects don't seem to
066: * make it over the RMI divide (Not serializable. St.Ack
067: */
068:
069: public class JEApplicationMBean implements DynamicMBean {
070:
071: private static final String DESCRIPTION = "A MBean for an application which uses JE. Provides open and close "
072: + "operations which configure and open a JE environment as part of the "
073: + "applications's resources. Also supports general JE monitoring.";
074:
075: private MBeanInfo mbeanInfo; // this MBean's visible interface.
076: private JEMBeanHelper jeHelper; // gets JE management interface
077: private Environment targetEnv; // saved environment handle
078:
079: /**
080: * This MBean provides an open operation to open the JE environment.
081: */
082: public static final String OP_OPEN = "openJE";
083:
084: /**
085: * This MBean provides a close operation to release the JE environment.
086: * Note that environments must be closed to release resources.
087: */
088: public static final String OP_CLOSE = "closeJE";
089:
090: /**
091: * Instantiate a JEApplicationMBean
092: *
093: * @param env Environment to use. Externally managed.
094: * @throws DatabaseException
095: */
096: public JEApplicationMBean(Environment env) throws DatabaseException {
097: this .targetEnv = env;
098: jeHelper = new JEMBeanHelper(env.getConfig(), env.getHome(),
099: true);
100: resetMBeanInfo();
101: }
102:
103: /**
104: * @see DynamicMBean#getAttribute
105: */
106: public Object getAttribute(String attributeName)
107: throws AttributeNotFoundException, MBeanException {
108:
109: return jeHelper.getAttribute(targetEnv, attributeName);
110: }
111:
112: /**
113: * @see DynamicMBean#setAttribute
114: */
115: public void setAttribute(Attribute attribute)
116: throws AttributeNotFoundException,
117: InvalidAttributeValueException {
118:
119: jeHelper.setAttribute(targetEnv, attribute);
120: }
121:
122: /**
123: * @see DynamicMBean#getAttributes
124: */
125: public AttributeList getAttributes(String[] attributes) {
126:
127: /* Sanity checking. */
128: if (attributes == null) {
129: throw new IllegalArgumentException(
130: "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(
155: "attribute list can't be null");
156: }
157:
158: /* Set each attribute specified. */
159: AttributeList results = new AttributeList();
160: for (int i = 0; i < attributes.size(); i++) {
161: Attribute attr = (Attribute) attributes.get(i);
162: try {
163: /* Set new value. */
164: jeHelper.setAttribute(targetEnv, attr);
165:
166: /*
167: * Add the name and new value to the result list. Be sure
168: * to ask the MBean for the new value, rather than simply
169: * using attr.getValue(), because the new value may not
170: * be same if it is modified according to the JE
171: * implementation.
172: */
173: String name = attr.getName();
174: Object newValue = jeHelper
175: .getAttribute(targetEnv, name);
176: results.add(new Attribute(name, newValue));
177: } catch (Exception e) {
178: e.printStackTrace();
179: }
180: }
181: return results;
182: }
183:
184: /**
185: * @see DynamicMBean#invoke
186: */
187: public Object invoke(String actionName, Object[] params,
188: String[] signature) throws MBeanException {
189:
190: Object result = null;
191:
192: if (actionName == null) {
193: throw new IllegalArgumentException(
194: "actionName cannot be null");
195: }
196: // Don't allow opening and closing of environment. It was created
197: // externally. St.Ack
198: //
199: // if (actionName.equals(OP_OPEN)) {
200: // openEnvironment();
201: // return null;
202: // } else if (actionName.equals(OP_CLOSE)) {
203: // closeEnvironment();
204: // return null;
205: // } else {
206: result = jeHelper.invoke(targetEnv, actionName, params,
207: signature);
208: // }
209:
210: return result;
211: }
212:
213: /**
214: * @see DynamicMBean#getMBeanInfo
215: */
216: public MBeanInfo getMBeanInfo() {
217: return mbeanInfo;
218: }
219:
220: /**
221: * Create the available management interface for this environment.
222: * The attributes and operations available vary according to
223: * environment configuration.
224: *
225: */
226: private synchronized void resetMBeanInfo() {
227:
228: /*
229: * Get JE attributes, operation and notification information
230: * from JEMBeanHelper. An application may choose to add functionality
231: * of its own when constructing the MBeanInfo.
232: */
233:
234: /* Attributes. */
235: List<MBeanAttributeInfo> attributeList = jeHelper
236: .getAttributeList(targetEnv);
237: MBeanAttributeInfo[] attributeInfo = new MBeanAttributeInfo[attributeList
238: .size()];
239: attributeList.toArray(attributeInfo);
240:
241: /* Constructors. */
242: Constructor[] constructors = this .getClass().getConstructors();
243: MBeanConstructorInfo[] constructorInfo = new MBeanConstructorInfo[constructors.length];
244: for (int i = 0; i < constructors.length; i++) {
245: constructorInfo[i] = new MBeanConstructorInfo(this
246: .getClass().getName(), constructors[i]);
247: }
248:
249: /* Operations. */
250:
251: /*
252: * Get the list of operations available from the jeHelper. Then add
253: * an open and close operation.
254: */
255: List<MBeanOperationInfo> operationList = jeHelper
256: .getOperationList(targetEnv);
257: /* Don't allow opening or closing remotely.
258: if (targetEnv == null) {
259: operationList.add(
260: new MBeanOperationInfo(OP_OPEN,
261: "Configure and open the JE environment.",
262: new MBeanParameterInfo[0], // no params
263: "java.lang.Boolean",
264: MBeanOperationInfo.ACTION_INFO));
265: } else {
266: operationList.add(
267: new MBeanOperationInfo(OP_CLOSE,
268: "Close the JE environment.",
269: new MBeanParameterInfo[0], // no params
270: "void",
271: MBeanOperationInfo.ACTION_INFO));
272: }
273: */
274:
275: MBeanOperationInfo[] operationInfo = new MBeanOperationInfo[operationList
276: .size()];
277: operationList.toArray(operationInfo);
278:
279: /* Notifications. */
280: MBeanNotificationInfo[] notificationInfo = jeHelper
281: .getNotificationInfo(targetEnv);
282:
283: /* Generate the MBean description. */
284: mbeanInfo = new MBeanInfo(this .getClass().getName(),
285: DESCRIPTION, attributeInfo, constructorInfo,
286: operationInfo, notificationInfo);
287: }
288:
289: /**
290: * Open a JE environment using the configuration specified through
291: * MBean attributes and recorded within the JEMBeanHelper.
292: */
293: // private void openEnvironment()
294: // throws MBeanException {
295: //
296: // try {
297: // if (targetEnv == null) {
298: // /*
299: // * The environment configuration has been set through
300: // * mbean attributes managed by the JEMBeanHelper.
301: // */
302: // targetEnv =
303: // new Environment(jeHelper.getEnvironmentHome(),
304: // jeHelper.getEnvironmentOpenConfig());
305: // resetMBeanInfo();
306: // }
307: // } catch (DatabaseException e) {
308: // throw new MBeanException(e);
309: // }
310: // }
311: /**
312: * Release the environment handle contained within the MBean to properly
313: * release resources.
314: */
315: // private void closeEnvironment()
316: // throws MBeanException {
317: //
318: // try {
319: // if (targetEnv != null) {
320: // targetEnv.close();
321: // targetEnv = null;
322: // resetMBeanInfo();
323: // }
324: // } catch (DatabaseException e) {
325: // throw new MBeanException(e);
326: // }
327: // }
328: }
|