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: * BeanManager.java
022: *
023: * This object is responsible for managing the loading and unloading of
024: * coadunation beans.
025: */
026:
027: // package path
028: package com.rift.coad.lib.deployment.bean;
029:
030: // java imports
031: import java.util.Map;
032: import java.util.HashMap;
033: import java.util.Iterator;
034: import java.util.Set;
035: import java.rmi.Remote;
036: import javax.naming.Context;
037: import javax.naming.InitialContext;
038: import javax.naming.Name;
039: import javax.rmi.PortableRemoteObject;
040:
041: // logging import
042: import org.apache.log4j.Logger;
043:
044: // coadunation imports
045: import com.rift.coad.lib.security.ThreadsPermissionContainer;
046: import com.rift.coad.lib.deployment.DeploymentLoader;
047: import com.rift.coad.lib.thread.CoadunationThreadGroup;
048: import com.rift.coad.lib.deployment.BeanInfo;
049: import com.rift.coad.lib.configuration.Configuration;
050: import com.rift.coad.lib.configuration.ConfigurationFactory;
051: import com.rift.coad.lib.naming.ContextManager;
052: import com.rift.coad.lib.bean.BeanWrapper;
053:
054: /**
055: * This object is responsible for managing the loading and unloading of
056: * coadunation beans.
057: *
058: * @author Brett Chaldecott
059: */
060: public class BeanManager {
061:
062: /**
063: * This object wrapps access to the beans.
064: *
065: * @author Brett Chaldecott
066: */
067: public class BeanList {
068:
069: // class constants
070: private final static String DEFAULT_PATH = "java:comp/env/bean";
071: private final static String BEAN_CTX = "beanctx";
072:
073: // private member variables
074: private Map beans = null;
075: private Configuration config = null;
076: private Context context = null;
077: private ContextManager contextManager = null;
078:
079: /**
080: * The constructor of the bean list.
081: *
082: * @exception BeanException
083: */
084: public BeanList() throws BeanException {
085: beans = new HashMap();
086: try {
087: config = ConfigurationFactory.getInstance().getConfig(
088: this .getClass());
089: context = new InitialContext();
090: contextManager = new ContextManager(config.getString(
091: BEAN_CTX, DEFAULT_PATH));
092: } catch (Exception ex) {
093: throw new BeanException(
094: "Failed to instanciate the BeanList : "
095: + ex.getMessage(), ex);
096: }
097: }
098:
099: /**
100: * This method adds a new bean to the list of beans
101: *
102: * @param key The new key to add.
103: * @param bean The object reference to add.
104: */
105: public synchronized void addBean(String key, Object bean)
106: throws BeanException {
107: try {
108: BeanWrapper wrapper = (BeanWrapper) bean;
109: if (wrapper.getTie() != null) {
110: log.info("Adding the [" + key
111: + "] to the portable remote object.");
112: javax.rmi.PortableRemoteObject.exportObject(wrapper
113: .getTie());
114: context.bind(key, wrapper.getTie());
115: }
116: // local context binding
117: contextManager.bind(key, wrapper.getProxy());
118:
119: // add to maps
120: beans.put(key, bean);
121: } catch (Exception ex) {
122: log.error("Failed to add the bean [" + key + "]", ex);
123: throw new BeanException(
124: "Failed to add the bean to the list : "
125: + ex.getMessage(), ex);
126: }
127: }
128:
129: /**
130: * This method removes the bean from the map.
131: *
132: * @param key The key identifying the bean to remove.
133: */
134: public synchronized void removeBean(String key)
135: throws BeanException {
136: try {
137: BeanWrapper wrapper = (BeanWrapper) beans.get(key);
138: if (wrapper.getTie() != null) {
139: // we do not need to remove the local reference as
140: // this gets removed when the context gets released
141: try {
142: log.info("Unbinding an object [" + key
143: + "] from the portable object");
144: context.unbind(key);
145: javax.rmi.PortableRemoteObject
146: .unexportObject(wrapper.getTie());
147: } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
148: log.info("Failed to unbind the object [" + key
149: + "] as it is not bound.", ex);
150: }
151: }
152: beans.remove(key);
153: } catch (Exception ex) {
154: throw new BeanException(
155: "Failed to remove the bean from the list : "
156: + ex.getMessage(), ex);
157: }
158: }
159:
160: /**
161: * This method returns true if the bean list contains the key.
162: *
163: * @return TRUE if the bean is found FALSE if not.
164: * @param key The key to check for.
165: */
166: public synchronized boolean contains(String key) {
167: return beans.containsKey(key);
168: }
169:
170: /**
171: * This method returns the reference to the object, if it cannot be
172: * found it returns null.
173: *
174: * @return The reference to the object.
175: * @param key The key to look for.
176: */
177: public synchronized Object getBean(String key) {
178: return beans.get(key);
179: }
180:
181: /**
182: * This method returns the keys identifying the beans.
183: *
184: * @return The list of keys.
185: */
186: public synchronized Set getKeys() {
187: return beans.keySet();
188: }
189: }
190:
191: // class constants
192: private final static String USERNAME = "bean_user";
193:
194: // the class log variable
195: protected Logger log = Logger
196: .getLogger(BeanManager.class.getName());
197:
198: // the classes private member variables
199: private ThreadsPermissionContainer permissions = null;
200:
201: // the private member variables
202: private Map entries = null;
203: private BeanList beanList = null;
204: private CoadunationThreadGroup threadGroup = null;
205: private String username = null;
206:
207: /**
208: * Creates a new instance of BeanManager
209: *
210: * @param permissions The reference to the permission object.
211: * @param threadGroup The reference to the thread group.
212: * @exception Exception
213: */
214: public BeanManager(ThreadsPermissionContainer permissions,
215: CoadunationThreadGroup threadGroup) throws Exception {
216: this .permissions = permissions;
217: this .threadGroup = threadGroup.createThreadGroup();
218: entries = new HashMap();
219: beanList = new BeanList();
220: try {
221: Configuration config = ConfigurationFactory.getInstance()
222: .getConfig(BeanManager.class);
223: username = config.getString(USERNAME);
224: } catch (Exception ex) {
225: throw new BeanException(
226: "Failed to start the bean manager ["
227: + ex.getMessage() + "]", ex);
228: }
229: }
230:
231: /**
232: * This method will load beans from a deployment file.
233: *
234: * @param deploymentLoader The reference reference to the deployment loader.
235: * @exception BeanException
236: */
237: public void load(DeploymentLoader deploymentLoader)
238: throws BeanException, Exception {
239: if (entries.containsKey(deploymentLoader)) {
240: throw new BeanException(
241: "This entries has been loaded before.");
242: }
243:
244: // check for classesh
245: beanClash(deploymentLoader.getDeploymentInfo().getBeans());
246:
247: // load the beans
248: BeanLoader beanLoader = new BeanLoader(deploymentLoader,
249: permissions, threadGroup);
250: beanLoader.setContextClassLoader(deploymentLoader
251: .getClassLoader());
252: threadGroup.addThread(beanLoader, username);
253: beanLoader.start();
254: beanLoader.join();
255: if (!beanLoader.wasSucessfull()) {
256: throw beanLoader.getException();
257: }
258:
259: // add the new beans
260: Map beans = beanLoader.getBeans();
261: for (Iterator iter = beans.keySet().iterator(); iter.hasNext();) {
262: String key = (String) iter.next();
263: log.info("Load bean [" + key + "]");
264: beanList.addBean(key, beans.get(key));
265: }
266: entries.put(deploymentLoader, beanLoader);
267:
268: }
269:
270: /**
271: * This method will unload the entry from the bean management object.
272: *
273: * @param deploymentLoader The reference to the deployment loader object.
274: * @exception BeanException
275: */
276: public void unLoad(DeploymentLoader deploymentLoader)
277: throws BeanException {
278: if (false == entries.containsKey(deploymentLoader)) {
279: // do nothing there is nothing known about this entry
280: return;
281: }
282: // remove all the bean references.
283: BeanLoader beanLoader = (BeanLoader) entries
284: .get(deploymentLoader);
285: Map beans = beanLoader.getBeans();
286: for (Iterator iter = beans.keySet().iterator(); iter.hasNext();) {
287: String key = (String) iter.next();
288: log.info("Unload bean [" + key + "]");
289: beanList.removeBean(key);
290: }
291:
292: // remove the bean
293: entries.remove(deploymentLoader);
294:
295: // unload the bean loader
296: beanLoader.stopThreads();
297: }
298:
299: /**
300: * This method returns the list of keys.
301: *
302: * @return The list of beans managed by this object.
303: */
304: public Set getKeys() {
305: return beanList.getKeys();
306: }
307:
308: /**
309: * Retrieve the bean that matches the key
310: *
311: * @return Return the object identified by the key.
312: * @param key The key identifying the bean.
313: */
314: public Object getBean(String key) {
315: return beanList.getBean(key);
316: }
317:
318: /**
319: * This method determines if there are any bean classes based on name.
320: *
321: * @param newBeans The new beans to add to the list.
322: * @exception BeanException
323: */
324: private void beanClash(Map newBeans) throws BeanException {
325:
326: for (Iterator iter = newBeans.keySet().iterator(); iter
327: .hasNext();) {
328: BeanInfo beanInfo = (BeanInfo) newBeans.get(iter.next());
329: if (this .beanList.contains(beanInfo.getBindName())) {
330: throw new BeanException(
331: "One of the beans clashes with an existing one ["
332: + beanInfo.getBindName() + "]");
333: }
334: }
335: }
336:
337: }
|