001: // THIS SOFTWARE IS PROVIDED BY SOFTARIS PTY.LTD. AND OTHER METABOSS
002: // CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
003: // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
004: // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTARIS PTY.LTD.
005: // OR OTHER METABOSS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
006: // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
007: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
008: // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
009: // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
010: // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
011: // EVEN IF SOFTARIS PTY.LTD. OR OTHER METABOSS CONTRIBUTORS ARE ADVISED OF THE
012: // POSSIBILITY OF SUCH DAMAGE.
013: //
014: // Copyright 2000-2005 © Softaris Pty.Ltd. All Rights Reserved.
015: package com.jamonapi.management;
016:
017: import java.util.Hashtable;
018:
019: import javax.management.Attribute;
020: import javax.management.AttributeList;
021: import javax.management.AttributeNotFoundException;
022: import javax.management.DynamicMBean;
023: import javax.management.JMException;
024: import javax.management.MBeanException;
025: import javax.management.MBeanInfo;
026: import javax.management.MBeanNotificationInfo;
027: import javax.management.MBeanServer;
028: import javax.management.MalformedObjectNameException;
029: import javax.management.ObjectName;
030: import javax.management.openmbean.CompositeType;
031: import javax.management.openmbean.OpenDataException;
032: import javax.management.openmbean.OpenMBeanAttributeInfo;
033: import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
034: import javax.management.openmbean.OpenMBeanConstructorInfo;
035: import javax.management.openmbean.OpenMBeanInfoSupport;
036: import javax.management.openmbean.OpenMBeanOperationInfo;
037: import javax.management.openmbean.OpenMBeanOperationInfoSupport;
038: import javax.management.openmbean.OpenMBeanParameterInfo;
039: import javax.management.openmbean.SimpleType;
040: import javax.management.openmbean.TabularType;
041:
042: import org.apache.commons.logging.Log;
043: import org.apache.commons.logging.LogFactory;
044:
045: import com.jamonapi.MonitorFactory;
046:
047: /** The controller MBean implementation */
048: public class MonitorControllerMBean implements DynamicMBean {
049: private static Log sLogger = LogFactory
050: .getLog(MonitorControllerMBean.class);
051: private static Object sSingletonCreationSemaphore = new Object();
052: private static MonitorControllerMBean sSingleton = null;
053: private CompositeType mTableReportRowType = null;
054: private TabularType mTableReportType = null;
055: private MBeanInfo mMBeanInfo = null;
056: private OpenMBeanAttributeInfo mHTMLReportAttributeInfo = null;
057: private OpenMBeanAttributeInfo mProfilingInProgressAttributeInfo = null;
058: private OpenMBeanOperationInfo mResetOperationInfo = null;
059: private OpenMBeanOperationInfo mDisableProfilingOperationInfo = null;
060: private OpenMBeanOperationInfo mEnableProfilingOperationInfo = null;
061:
062: /** This method registers the instance of the MonitorControllerMBean if it has not been registered yet.
063: * @return true if bean is registered (i.e. it has been registered during this call or prior to that) and
064: * false if something prevents the bean to be registered. */
065: public static boolean registerBeanIfNecessary(
066: String pApplicationName) {
067: // Possibly register MBean, if there is an MBean server and MBean is not registered yet
068: MBeanServer lMBeanServer = JMXUtils.getMBeanServer();
069: if (lMBeanServer != null) {
070: try {
071: ObjectName lObjectName = MonitorControllerMBean
072: .getApplicationObjectName(pApplicationName);
073: // If this bean is already registered - there is no need to register another one
074: if (!lMBeanServer.isRegistered(lObjectName)) {
075: sLogger
076: .info("Located JMX MBeanServer. Will register '"
077: + lObjectName.getCanonicalName()
078: + "' management bean. It can be used to manage profiling.");
079:
080: // Note that create bean may not work and throw ReflectionException
081: // because jmx implementation might not see the classloader.
082: // The registerMBean() appears to work better for us
083: lMBeanServer.registerMBean(MonitorControllerMBean
084: .getInstance(), lObjectName);
085: } else
086: sLogger
087: .info("Located JMX MBeanServer. The '"
088: + lObjectName.getCanonicalName()
089: + "' management bean is already registered. It can be used to manage profiling.");
090: return true;
091: } catch (JMException e) {
092: // This is an unexpected situation. Report it as an error
093: sLogger
094: .error(
095: "Unable to register JMX MBean. (Caught an unexpected exception). The profiling management via managed beans is not available.",
096: e);
097: }
098: } else
099: sLogger
100: .warn("Unable to locate JMX MBeanServer. The profiling management via managed beans is not available.");
101: return false;
102: }
103:
104: /** This method registers the instance of the MonitorControllerMBean. If existing bean
105: * with the same name is found it will be deregistered first. In other words this
106: * method will always register a new copy of the bean.
107: * @return true if bean is registered (i.e. it has been registered during this call or prior to that) and
108: * false if something prevents the bean to be registered. */
109: public static boolean registerBean(String pApplicationName) {
110: // Possibly register MBean, if there is an MBean server and MBean is not registered yet
111: MBeanServer lMBeanServer = JMXUtils.getMBeanServer();
112: if (lMBeanServer != null) {
113: try {
114: ObjectName lObjectName = MonitorControllerMBean
115: .getApplicationObjectName(pApplicationName);
116: // If this bean is already registered - there is no need to register another one
117: if (lMBeanServer.isRegistered(lObjectName)) {
118: sLogger.warn("Found old '"
119: + lObjectName.getCanonicalName()
120: + "' management bean. Deregistering it.");
121: lMBeanServer.unregisterMBean(lObjectName);
122: }
123: sLogger
124: .info("Located JMX MBeanServer. Will register '"
125: + lObjectName.getCanonicalName()
126: + "' management bean. It can be used to manage profiling.");
127: // Note that create bean may not work and throw ReflectionException
128: // because jmx implementation might not see the classloader.
129: // The registerMBean() appears to work better for us
130: lMBeanServer.registerMBean(MonitorControllerMBean
131: .getInstance(), lObjectName);
132: return true;
133: } catch (JMException e) {
134: // This is an unexpected situation. Report it as an error
135: sLogger
136: .error(
137: "Unable to register JMX MBean. (Caught an unexpected exception). The profiling management via managed beans is not available.",
138: e);
139: }
140: } else
141: sLogger
142: .warn("Unable to locate JMX MBeanServer. The profiling management via managed beans is not available.");
143: return false;
144: }
145:
146: /** This method unregisters the instance of the MonitorControllerMBean if one is registered.
147: * @return true if bean is deregistered (i.e. it has been deregistered during this call or it did
148: * not exists) and false if something prevents the bean to be deregistered. */
149: public static boolean unregisterBean(String pApplicationName) {
150: // Possibly register MBean, if there is an MBean server and MBean is not registered yet
151: MBeanServer lMBeanServer = JMXUtils.getMBeanServer();
152: if (lMBeanServer != null) {
153: try {
154: ObjectName lObjectName = MonitorControllerMBean
155: .getApplicationObjectName(pApplicationName);
156: sLogger
157: .info("Located JMX MBeanServer. Will deregister '"
158: + lObjectName.getCanonicalName()
159: + "' management bean.");
160: // If this bean is not registered - there is no need to deregister
161: if (lMBeanServer.isRegistered(lObjectName)) {
162: lMBeanServer.unregisterMBean(lObjectName);
163: }
164: return true;
165: } catch (JMException e) {
166: // This is an unexpected situation. Report it as an error
167: sLogger
168: .error(
169: "Unable to deregister JMX MBean. (Caught an unexpected exception). The profiling management via managed beans has not been cleaned up properly.",
170: e);
171: }
172: } else
173: sLogger
174: .warn("Unable to locate JMX MBeanServer. The profiling management via managed beans has not been cleaned up properly.");
175: return false;
176: }
177:
178: /** Access method to the instance of the MBean. If instance is not created yet it will be created on the fly. */
179: public static MonitorControllerMBean getInstance()
180: throws JMException {
181: if (sSingleton == null) {
182: synchronized (sSingletonCreationSemaphore) {
183: if (sSingleton == null) {
184: sSingleton = new MonitorControllerMBean();
185: }
186: }
187: }
188: return sSingleton;
189: }
190:
191: // This helper method generates the Object name of the MBean using an Application name.
192: private static ObjectName getApplicationObjectName(
193: String pApplicationName)
194: throws MalformedObjectNameException {
195: String lDomainName = "Application";
196: Hashtable lKeyValuePairs = new Hashtable();
197: lKeyValuePairs.put("applicationName", pApplicationName);
198: lKeyValuePairs.put("beanClass", MonitorControllerMBean.class
199: .getName());
200: return new ObjectName(lDomainName, lKeyValuePairs);
201: }
202:
203: private MonitorControllerMBean() throws OpenDataException {
204: // Construct information
205: mHTMLReportAttributeInfo = new OpenMBeanAttributeInfoSupport(
206: "HTMLReport",
207: "The performance report in html table format",
208: SimpleType.STRING, true, false, false);
209:
210: mProfilingInProgressAttributeInfo = new OpenMBeanAttributeInfoSupport(
211: "ProfilingInProgress",
212: "Shows the status of monitoring (ie. whether statistic are being accumulated)",
213: SimpleType.BOOLEAN, true, false, false);
214:
215: mResetOperationInfo = new OpenMBeanOperationInfoSupport(
216: "resetProfilingStats",
217: "Resets accumulated statistics back to the initial values",
218: new OpenMBeanParameterInfo[0], SimpleType.VOID,
219: OpenMBeanOperationInfoSupport.ACTION);
220:
221: mDisableProfilingOperationInfo = new OpenMBeanOperationInfoSupport(
222: "pauseProfiling",
223: "Pauses accumulating of statistics without resetting of the accumulated values",
224: new OpenMBeanParameterInfo[0], SimpleType.VOID,
225: OpenMBeanOperationInfoSupport.ACTION);
226:
227: mEnableProfilingOperationInfo = new OpenMBeanOperationInfoSupport(
228: "resumeProfiling",
229: "Resumes accumulating of statistics without resetting of the accumulated values",
230: new OpenMBeanParameterInfo[0], SimpleType.VOID,
231: OpenMBeanOperationInfoSupport.ACTION);
232:
233: mMBeanInfo = new OpenMBeanInfoSupport("MonitorController",
234: "Controls java monitor engine and produces report",
235: new OpenMBeanAttributeInfo[] {
236: mHTMLReportAttributeInfo,
237: mProfilingInProgressAttributeInfo },
238: new OpenMBeanConstructorInfo[0],
239: new OpenMBeanOperationInfo[] { mResetOperationInfo,
240: mEnableProfilingOperationInfo,
241: mDisableProfilingOperationInfo },
242: new MBeanNotificationInfo[0]);
243: }
244:
245: public MBeanInfo getMBeanInfo() {
246: return mMBeanInfo;
247: }
248:
249: public Object getAttribute(String attribute)
250: throws AttributeNotFoundException, MBeanException {
251: try {
252: if (attribute.equals(mHTMLReportAttributeInfo.getName()))
253: return getReport();
254: else if (attribute.equals(mProfilingInProgressAttributeInfo
255: .getName()))
256: return isProfilingEnabled();
257: } catch (Exception e) {
258: throw new MBeanException(e);
259: }
260: throw new AttributeNotFoundException();
261: }
262:
263: public AttributeList getAttributes(String[] attributes) {
264: AttributeList lReturnList = new AttributeList();
265: for (int i = 0; i < attributes.length; i++) {
266: String lAttributeName = attributes[i];
267: try {
268: lReturnList.add(new Attribute(lAttributeName,
269: getAttribute(lAttributeName)));
270: } catch (Exception e) {
271: // Ignore
272: }
273: }
274: return lReturnList;
275: }
276:
277: public Object invoke(String actionName, Object[] params,
278: String[] signature) throws MBeanException {
279: try {
280: if (actionName.equals(mResetOperationInfo.getName())) {
281: resetStatistics();
282: return null;
283: } else if (actionName.equals(mEnableProfilingOperationInfo
284: .getName())) {
285: enableProfiling();
286: return null;
287: } else if (actionName.equals(mDisableProfilingOperationInfo
288: .getName())) {
289: disableProfiling();
290: return null;
291: }
292: } catch (Exception e) {
293: throw new MBeanException(e);
294: }
295: throw new MBeanException(null, "Action '" + actionName
296: + "' is not supported.");
297: }
298:
299: public void setAttribute(Attribute attribute) {
300: }
301:
302: public AttributeList setAttributes(AttributeList attributes) {
303: return new AttributeList();
304: }
305:
306: /** Returns profiling report */
307: public String getReport() throws Exception {
308: return MonitorFactory.getReport();
309: }
310:
311: /** Enable collection of the profiling data */
312: public void enableProfiling() throws Exception {
313: MonitorFactory.setEnabled(true);
314: }
315:
316: /** Reports whether profiling is enabled or not */
317: public Boolean isProfilingEnabled() throws Exception {
318: return Boolean.valueOf(MonitorFactory.isEnabled());
319: }
320:
321: /** Disable collection of the profiling data */
322: public void disableProfiling() throws Exception {
323: MonitorFactory.setEnabled(false);
324: }
325:
326: /** Reset the statistics to zeros */
327: public void resetStatistics() throws Exception {
328: MonitorFactory.reset();
329: }
330: }
|