001: /**
002: * Sequoia: Database clustering technology.
003: * Copyright (C) 2002-2004 French National Institute For Research In Computer
004: * Science And Control (INRIA).
005: * Contact: sequoia@continuent.org
006: *
007: * Licensed under the Apache License, Version 2.0 (the "License");
008: * you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: *
019: * Initial developer(s): Marc Wick.
020: * Contributor(s): Peter Royal
021: */package org.continuent.sequoia.controller.jmx;
022:
023: import java.util.Iterator;
024: import java.util.List;
025:
026: import javax.management.MBeanServer;
027: import javax.management.MBeanServerFactory;
028: import javax.management.ObjectInstance;
029: import javax.management.ObjectName;
030:
031: import org.continuent.sequoia.common.i18n.Translate;
032: import org.continuent.sequoia.common.jmx.JmxException;
033: import org.continuent.sequoia.common.log.Trace;
034:
035: /**
036: * The MBeanServerManager (Singleton) creates a single MBeanServer in an JVM.
037: * The server can be accessed with the getInstance() method.
038: * <p>
039: * The server is created with
040: * org.continuent.sequoia.controller.jmx.MBeanServerBuilder
041: *
042: * @author <a href="mailto:marc.wick@monte-bre.ch">Marc Wick </a>
043: * @version 1.0
044: */
045: public class MBeanServerManager {
046:
047: static Trace logger = Trace
048: .getLogger("org.continuent.sequoia.controller.jmx.MBeanServer");
049:
050: private static MBeanServer mbs;
051: private static boolean isJmxEnabled = true;
052:
053: /**
054: * creating a MBeanServer, if it does not exist, otherwise a reference to the
055: * MBeanServer is returned
056: *
057: * @return the mbeanserver instance, null if jmx is disabled
058: */
059: public static synchronized MBeanServer getInstance() {
060:
061: if (!isJmxEnabled) {
062: return null;
063: }
064:
065: if (mbs != null) {
066: return mbs;
067: }
068:
069: String defaultServerBuilder = System
070: .getProperty("javax.management.builder.initial");
071:
072: if (!MBeanServerBuilder.class.getName().equals(
073: defaultServerBuilder)) {
074: if (defaultServerBuilder != null)
075: logger
076: .error("property javax.management.builder.initial was "
077: + defaultServerBuilder);
078:
079: logger
080: .debug("setting property javax.management.builder.initial");
081: System
082: .setProperty(
083: "javax.management.builder.initial",
084: org.continuent.sequoia.controller.jmx.MBeanServerBuilder.class
085: .getName());
086:
087: }
088:
089: // try to use the MBeanServer provided by Java 5
090: createJava5PlatformMBeanServer();
091: // otherwise rely on the classpath to create the MBeanServer
092: if (null == mbs) {
093: mbs = MBeanServerFactory.createMBeanServer();
094: logger.debug(Translate.get("jmx.server.from.classpath")); //$NON-NLS-1$
095: }
096:
097: return mbs;
098: }
099:
100: /**
101: * Retrieve the MBeanServer provided by Java 5. This is done by reflection to
102: * avoid creating hard-coded dependencies to Java 5-only classes.
103: */
104: private static void createJava5PlatformMBeanServer() {
105: Class clazz;
106: try {
107: clazz = Class
108: .forName("java.lang.management.ManagementFactory"); //$NON-NLS-1$
109: } catch (ClassNotFoundException e) {
110: // Java 5-only class is not available: do nothing
111: return;
112: }
113: try {
114: mbs = (MBeanServer) clazz.getMethod(
115: "getPlatformMBeanServer", null).invoke(null, null); //$NON-NLS-1$
116: logger.debug(Translate.get("jmx.server.from.java5")); //$NON-NLS-1$
117: } catch (Exception e) {
118: logger.debug(Translate.get("jmx.server.not.java5"), e); //$NON-NLS-1$
119: }
120: }
121:
122: /**
123: * Returns the isJmxEnabled value.
124: *
125: * @return Returns the isJmxEnabled.
126: */
127: public static boolean isJmxEnabled() {
128: return isJmxEnabled;
129: }
130:
131: /**
132: * enable or disable jmx
133: *
134: * @param isJmxEnabled The isJmxEnabled to set.
135: * @throws JmxException an exception
136: */
137: public static void setJmxEnabled(boolean isJmxEnabled)
138: throws JmxException {
139: if (MBeanServerManager.isJmxEnabled != isJmxEnabled
140: && !isJmxEnabled && mbs != null) {
141: // stop rmi connectors
142: List list = RmiConnector.getRmiConnectors();
143: for (Iterator it = list.iterator(); it.hasNext();) {
144: RmiConnector rmi = (RmiConnector) it.next();
145: rmi.stop();
146: }
147:
148: // stop http adaptors
149: list = HttpAdaptor.getHttpAdaptors();
150: for (Iterator it = list.iterator(); it.hasNext();) {
151: HttpAdaptor http = (HttpAdaptor) it.next();
152: http.stop();
153: }
154: // Stop mbean server
155: MBeanServerFactory.releaseMBeanServer(mbs);
156: mbs = null;
157: }
158: // set jmx enabled to its value
159: MBeanServerManager.isJmxEnabled = isJmxEnabled;
160: }
161:
162: /**
163: * Registers an MBean with the MBean server if jmx is enabled, otherwise it
164: * returns null.
165: * <p>
166: * This method is equivalend to
167: *
168: * <pre>
169: * MBeanServer server = MBeanServerManager.getInstance();
170: * if (server != null)
171: * {
172: * server.registerMBean(object, name);
173: * }
174: * </pre>
175: *
176: * @param object The MBean to be registered as an MBean.
177: * @param name The object name of the MBean. May be null.
178: * @return An ObjectInstance, containing the ObjectName and the Java class
179: * name of the newly registered MBean. If the contained ObjectName is
180: * n, the contained Java class name is getMBeanInfo(n).getClassName().
181: * Or null if jmx is disabled
182: * @throws JmxException the object could not be registered
183: */
184: public static ObjectInstance registerMBean(Object object,
185: ObjectName name) throws JmxException {
186: MBeanServer server = getInstance();
187: try {
188:
189: if (server != null) {
190: logger.debug(Translate.get("jmx.register.mbean",
191: new String[] { object.getClass().toString(),
192: name.getCanonicalName() }));
193:
194: ObjectInstance objInstance = null;
195: if (!server.isRegistered(name)) {
196: objInstance = server.registerMBean(object, name);
197: } else {
198: logger.error(Translate.get(
199: "jmx.register.mbean.already.exist",
200: new String[] { name.getCanonicalName() }));
201: try {
202: server.unregisterMBean(name);
203: } catch (Exception e) {
204: logger.error(Translate.get(
205: "jmx.delete.mbean.failed",
206: new String[] { name.toString(),
207: e.getMessage() }));
208: }
209: objInstance = server.registerMBean(object, name);
210: }
211:
212: logger.debug(Translate.get("jmx.server.mbean.count", ""
213: + server.getMBeanCount()));
214: return objInstance;
215: }
216: return null;
217: } catch (Exception e) {
218: logger.error(Translate.get("jmx.register.mbean.failed",
219: new String[] { object.getClass().toString(),
220: e.getMessage(), e.getClass().toString() }));
221: e.printStackTrace();
222: e.getCause().printStackTrace();
223: throw new JmxException(e);
224: }
225: }
226:
227: /**
228: * unregister an mbean.
229: *
230: * @param name the name of the bean to unregister
231: * @throws JmxException problems
232: */
233: public static void unregister(ObjectName name) throws JmxException {
234: MBeanServer server = getInstance();
235: if (server != null) {
236: try {
237: // unregister the MBean
238: server.unregisterMBean(name);
239: logger.debug(Translate.get("jmx.server.mbean.count", ""
240: + server.getMBeanCount()));
241:
242: } catch (Exception e) {
243: logger.error(Translate.get("jmx.register.mbean.failed",
244: new String[] { name.getCanonicalName(),
245: e.getMessage() }));
246: throw new JmxException(e);
247: }
248: }
249: }
250:
251: }
|