View Javadoc

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 }