001: /*
002: * CoadunationLib: The coaduntion implementation library.
003: * Copyright (C) 2006 Rift IT Contracting
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
018: *
019: * XMLConfigurationException.java
020: *
021: * JMXBeanManager.java
022: *
023: * The JMX Bean manager is responsible for loading and unloading of jmx beans.
024: * It is controlled by the DeploymentManager.
025: */
026:
027: package com.rift.coad.lib.deployment.jmxbean;
028:
029: // java imports
030: import java.util.Iterator;
031: import java.util.Map;
032: import java.util.HashMap;
033: import java.util.Set;
034: import javax.management.MBeanServer;
035: import java.lang.management.ManagementFactory;
036: import java.rmi.Remote;
037: import javax.naming.Context;
038: import javax.naming.InitialContext;
039: import javax.naming.Name;
040: import javax.rmi.PortableRemoteObject;
041:
042: // logging import
043: import org.apache.log4j.Logger;
044:
045: // coadunation imports
046: import com.rift.coad.lib.bean.BeanWrapper;
047: import com.rift.coad.lib.security.ThreadsPermissionContainer;
048: import com.rift.coad.lib.deployment.DeploymentLoader;
049: import com.rift.coad.lib.thread.CoadunationThreadGroup;
050: import com.rift.coad.lib.deployment.JMXBeanInfo;
051: import com.rift.coad.lib.configuration.Configuration;
052: import com.rift.coad.lib.configuration.ConfigurationFactory;
053: import com.rift.coad.lib.naming.ContextManager;
054: import com.rift.coad.lib.bean.BeanWrapper;
055:
056: /**
057: * The JMX Bean manager is responsible for loading and unloading of jmx beans.
058: * It is controlled by the DeploymentManager.
059: *
060: * @author Brett Chaldecott
061: */
062: public class JMXBeanManager {
063:
064: /**
065: * This object maintains the beans in memory.
066: */
067: public class BeanList {
068: // class constants
069: private final static String DEFAULT_PATH = "java:comp/env/jmx";
070: private final static String JMX_CTX = "jmxctx";
071:
072: // the list of beans
073: private Map objectList = null;
074: private Map bindList = null;
075: private Configuration config = null;
076: private Context context = null;
077: private ContextManager contextManager = null;
078:
079: /**
080: * The default constructor of the bean list.
081: *
082: * @exception JMXException
083: */
084: public BeanList() throws JMXException {
085: objectList = new HashMap();
086: bindList = new HashMap();
087: try {
088: config = ConfigurationFactory.getInstance().getConfig(
089: this .getClass());
090: context = new InitialContext();
091: contextManager = new ContextManager(config.getString(
092: JMX_CTX, DEFAULT_PATH));
093: } catch (Exception ex) {
094: throw new JMXException(
095: "Failed to instanciate the BeanList : "
096: + ex.getMessage(), ex);
097: }
098: }
099:
100: /**
101: * This method will add the jmx bean to the object and bind list.
102: *
103: * @param objectName The object name to use in the object list.
104: * @param bean The reference to the bean to add.
105: */
106: public synchronized void addBean(String objectName, Object bean)
107: throws JMXException {
108: BeanWrapper wrapper = (BeanWrapper) bean;
109: try {
110: if (wrapper.getTie() != null) {
111: log.info("Adding the [" + wrapper.getBindName()
112: + "] to the portable remote object.");
113: javax.rmi.PortableRemoteObject.exportObject(wrapper
114: .getTie());
115: context.bind(wrapper.getBindName(), wrapper
116: .getTie());
117: }
118: // Add to local context
119: contextManager.bind(wrapper.getBindName(), wrapper
120: .getProxy());
121:
122: // add to object lists
123: objectList.put(objectName, bean);
124: bindList.put(wrapper.getBindName(), bean);
125:
126: } catch (Exception ex) {
127: log.error("Failed to add the bean [" + objectName
128: + "][" + wrapper.getBindName() + "]", ex);
129: throw new JMXException(
130: "Failed to add the jmx bean to the list : "
131: + ex.getMessage(), ex);
132: }
133: }
134:
135: /**
136: * This method removed the bean from the lists.
137: *
138: * @param objectName The name of the object to remove from the list.
139: */
140: public synchronized void removeBean(String objectName)
141: throws JMXException {
142: try {
143: BeanWrapper wrapper = (BeanWrapper) objectList
144: .get(objectName);
145: if (wrapper != null) {
146: // we do not need to remove the local reference as
147: // this gets removed when the context gets released
148: bindList.remove(wrapper.getBindName());
149: if (wrapper.getTie() != null) {
150: try {
151: log.info("Unbinding an object ["
152: + objectName
153: + "] from the portable object");
154: context.unbind(wrapper.getBindName());
155: javax.rmi.PortableRemoteObject
156: .unexportObject(wrapper.getTie());
157: } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
158: log.info("Failed to unbind the object ["
159: + objectName
160: + "] as it is not bound.", ex);
161: }
162: }
163: }
164: objectList.remove(objectName);
165: } catch (Exception ex) {
166: throw new JMXException(
167: "Failed to remove the jmx bean from the list : "
168: + ex.getMessage(), ex);
169: }
170: }
171:
172: /**
173: * This method returns the list of keys identifying the objects.
174: *
175: * @return The keys identifying the objects in the system.
176: */
177: public synchronized Set getObjectKeys() {
178: return objectList.keySet();
179: }
180:
181: /**
182: * This method returns the object reference identified by the JMX object
183: * name.
184: *
185: * @return The object identified by the JMX object name, or null if it
186: * is not found.
187: * @param key The key identifying the object.
188: */
189: public synchronized Object getObject(String key) {
190: return objectList.get(key);
191: }
192:
193: /**
194: * This method returns true if the object list contains the specified
195: * key.
196: *
197: * @return TRUE if the key is found FALSE if not.
198: * @param key The key identifying the object.
199: */
200: public synchronized boolean containsObject(String key) {
201: return objectList.containsKey(key);
202: }
203:
204: /**
205: * This method returns the list of bind keys.
206: *
207: * @return The key set containing the bind keys.
208: */
209: public synchronized Set getBindKeys() {
210: return bindList.keySet();
211: }
212:
213: /**
214: * Thist method returns the bind information.
215: *
216: * @return The bind information.
217: * @param key The bind key identifying the object.
218: */
219: public synchronized Object getBindObject(String key) {
220: return bindList.get(key);
221: }
222:
223: /**
224: * This method returns true if the list contains the bind object.
225: *
226: * @return TRUE if found FALSE if not.
227: * @param key The key to find.
228: */
229: public synchronized boolean containsBindObject(String key) {
230: return bindList.containsKey(key);
231: }
232: }
233:
234: // class constants
235: private final static String USERNAME = "jmxbean_user";
236:
237: // the class log variable
238: protected Logger log = Logger.getLogger(JMXBeanManager.class
239: .getName());
240:
241: // class member variables
242: private final MBeanServer mbs = ManagementFactory
243: .getPlatformMBeanServer();
244: private ThreadsPermissionContainer permissions = null;
245: private Map loaders = null;
246: private BeanList beanList = null;
247: private CoadunationThreadGroup threadGroup = null;
248: private String username = null;
249:
250: /**
251: * Creates a new instance of JMXBeanManager
252: *
253: * @param permissions The reference thread permissions.
254: * @param threadGroup The group of threads.
255: * @exception Exception
256: */
257: public JMXBeanManager(ThreadsPermissionContainer permissions,
258: CoadunationThreadGroup threadGroup) throws Exception {
259: this .permissions = permissions;
260: loaders = new HashMap();
261: beanList = new BeanList();
262: this .threadGroup = threadGroup.createThreadGroup();
263: try {
264: Configuration config = ConfigurationFactory.getInstance()
265: .getConfig(JMXBeanManager.class);
266: username = config.getString(USERNAME);
267: } catch (Exception ex) {
268: throw new JMXException(
269: "Failed to start the JMX Bean manager ["
270: + ex.getMessage() + "]", ex);
271: }
272: }
273:
274: /**
275: * This method loads the JMX bean from the deployment file using the jmx
276: * bean deployment loader.
277: *
278: * @param loader The reference to the loader object.
279: * @exception JMXException
280: * @exception Exception
281: */
282: public void load(DeploymentLoader loader) throws JMXException,
283: Exception {
284: if (loaders.containsKey(loader)) {
285: throw new JMXException(
286: "This entries has been loaded before.");
287: }
288:
289: // check for clashes
290: beanClash(loader.getDeploymentInfo().getJmxBeans());
291:
292: // load the beans
293: JMXBeanLoader jmxBeanLoader = new JMXBeanLoader(mbs, loader,
294: permissions, threadGroup);
295: jmxBeanLoader.setContextClassLoader(loader.getClassLoader());
296: threadGroup.addThread(jmxBeanLoader, username);
297: jmxBeanLoader.start();
298: jmxBeanLoader.join();
299: if (!jmxBeanLoader.wasSucessfull()) {
300: throw jmxBeanLoader.getException();
301: }
302:
303: // add the beans to the bean list
304: Map beans = jmxBeanLoader.getBeans();
305: for (Iterator iter = beans.keySet().iterator(); iter.hasNext();) {
306: String key = (String) iter.next();
307: log.info("Load bean [" + key + "]");
308: beanList.addBean(key, beans.get(key));
309: }
310:
311: // add the beans
312: loaders.put(loader, jmxBeanLoader);
313: }
314:
315: /**
316: * This method unloads the deployment loader.
317: *
318: * @param loader The loader to unload.
319: * @exception JMXException
320: */
321: public void unLoad(DeploymentLoader loader) throws JMXException {
322: if (false == loaders.containsKey(loader)) {
323: // do nothing there is nothing known about this entry
324: return;
325: }
326: // remove all the bean references.
327: JMXBeanLoader jmxBeanLoader = (JMXBeanLoader) loaders
328: .get(loader);
329: Map beans = jmxBeanLoader.getBeans();
330: for (Iterator iter = beans.keySet().iterator(); iter.hasNext();) {
331: String key = (String) iter.next();
332: log.info("Unload bean [" + key + "]");
333: beanList.removeBean(key);
334: }
335:
336: // remove the bean
337: jmxBeanLoader.unRegisterBeans();
338: jmxBeanLoader.stopThreads();
339: loaders.remove(loader);
340: }
341:
342: /**
343: * Retrieve the objects keys. These are the standard lookup keys.
344: *
345: * @return The list of beans managed by this object.
346: */
347: public Set getObjectKeys() {
348: return beanList.getObjectKeys();
349: }
350:
351: /**
352: * This method will return the reference to the wrapper object using the
353: * bind key identifier.
354: *
355: * @return The object identified by the bind key.
356: * @param key The bind key to retrieve the object for.
357: */
358: public Object getObject(String key) {
359: return beanList.getObject(key);
360: }
361:
362: /**
363: * Retrieve the bind keys. These are the standard lookup keys.
364: *
365: * @return The list of beans managed by this object.
366: */
367: public Set getBindKeys() {
368: return beanList.getBindKeys();
369: }
370:
371: /**
372: * This method will return the reference to the wrapper object using the
373: * bind key identifier.
374: *
375: * @return The object identified by the bind key.
376: * @param key The bind key to retrieve the object for.
377: */
378: public Object getBindObject(String key) {
379: return beanList.getBindObject(key);
380: }
381:
382: /**
383: * This method checks to see if there are any clashing beans.
384: *
385: * @param beans The list of beans to perform the check on.
386: * @exception JMXException
387: */
388: private void beanClash(Map beans) throws JMXException {
389: for (Iterator iter = beans.keySet().iterator(); iter.hasNext();) {
390: JMXBeanInfo jmxBeanInfo = (JMXBeanInfo) beans.get(iter
391: .next());
392: if (beanList.containsObject(jmxBeanInfo.getObjectName())) {
393: throw new JMXException("The object with the name ["
394: + jmxBeanInfo.getObjectName()
395: + "] is already bound");
396: }
397: if (beanList.containsBindObject(jmxBeanInfo.getBindName())) {
398: throw new JMXException(
399: "The object with the bind name ["
400: + jmxBeanInfo.getBindName()
401: + "] is already bound");
402: }
403: }
404: }
405:
406: }
|