KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > rift > coad > lib > deployment > DeploymentManager


1 /*
2  * CoadunationLib: The coaduntion implementation library.
3  * Copyright (C) 2006 Rift IT Contracting
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *
19  * XMLConfigurationException.java
20  *
21  * DeploymentManager.java
22  *
23  * This object is responsible for controlling the loading of Coadunation
24  * deployment files using the deployment loader and other management objects.
25  */

26
27 // the package path
28
package com.rift.coad.lib.deployment;
29
30 // java imports
31
import java.io.File JavaDoc;
32 import java.util.Arrays JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.HashMap JavaDoc;
35 import java.util.HashSet JavaDoc;
36 import java.util.concurrent.ConcurrentHashMap JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.Set JavaDoc;
39 import java.util.Vector JavaDoc;
40
41 // logging import
42
import org.apache.log4j.Logger;
43
44 // import path
45
import com.rift.coad.lib.common.FileUtil;
46 import com.rift.coad.lib.cache.CacheRegistry;
47 import com.rift.coad.lib.configuration.Configuration;
48 import com.rift.coad.lib.configuration.ConfigurationFactory;
49 import com.rift.coad.lib.deployment.bean.BeanManager;
50 import com.rift.coad.lib.deployment.jmxbean.JMXBeanManager;
51 import com.rift.coad.lib.deployment.webservice.WebServiceManager;
52 import com.rift.coad.lib.naming.NamingDirector;
53 import com.rift.coad.lib.thread.CoadunationThreadGroup;
54 import com.rift.coad.lib.thread.BasicThread;
55 import com.rift.coad.lib.thread.ThreadGroupManager;
56 import com.rift.coad.util.lock.ObjectLockFactory;
57 import com.rift.coad.util.transaction.TransactionManager;
58
59 /**
60  * This object is responsible for controlling the loading of Coadunation
61  * deployment files using the deployment loader and other management objects.
62  *
63  * @author Brett Chaldecott
64  */

65 public class DeploymentManager {
66     
67     /**
68      * The deployment thread responsible for controlling the management of
69      * the deployed beans, jmx beans and web services.
70      */

71     public class DeploymentThread extends BasicThread {
72         // the reference to the deployment manager
73
private DeploymentManager deploymentManager = null;
74         private boolean terminated = false;
75         private long delayPeriod = 0;
76         
77         /**
78          * The constructor of the deployment thread.
79          *
80          * @param deploymentManager The reference to the deployment manager.
81          */

82         public DeploymentThread(DeploymentManager deploymentManager) throws
83                 DeploymentException, Exception JavaDoc {
84             try {
85                 this.deploymentManager = deploymentManager;
86                 
87                 // retrieve the configuration
88
Configuration config = ConfigurationFactory.getInstance().
89                         getConfig(this.getClass());
90                 
91                 delayPeriod = config.getLong("delay");
92                 
93             } catch (Exception JavaDoc ex) {
94                 throw new DeploymentException(
95                         "Failed to init the deployment thread",ex);
96             }
97         }
98         
99         
100         /**
101          * This method will be called to like the run method in a tradition thread.
102          */

103         public void process() {
104             // reset the class loader
105
while(isTerminated() == false) {
106                 deploymentManager.manage();
107                 delay();
108             }
109         }
110         
111         
112         /**
113          * This method will be implemented by child objects to terminate the
114          * processing of this thread.
115          */

116         public synchronized void terminate() {
117            terminated = true;
118            DeploymentMonitor.getInstance().terminate();
119         }
120
121
122         /**
123          * This method returns the information about what this thread is processing.
124          *
125          * @return String containing a description of this thread
126          */

127         public String JavaDoc getInfo() {
128             return "Managing the Coadunation deployment files.";
129         }
130         
131         
132         /**
133          * This method will be called to check the status of this thread.
134          */

135         private synchronized boolean isTerminated() {
136             return terminated;
137         }
138         
139         
140         /**
141          * This method will delay the processing for the processing for the given
142          * period of time.
143          */

144         private synchronized void delay() {
145             try {
146                 wait(delayPeriod);
147             } catch (Exception JavaDoc ex) {
148                 // ignore
149
}
150         }
151     }
152     
153     
154     /**
155      * This object is responsible for maintaining the loader list. It supplies
156      * thread safe access to the list within.
157      */

158     public class LoaderList {
159         // the classes member variables
160
private Map JavaDoc loaders = null;
161         
162         
163         /**
164          * The constructor of the loader list.
165          */

166         public LoaderList() {
167             loaders = new ConcurrentHashMap JavaDoc();
168         }
169         
170         
171         /**
172          * This method will return true if the loader represented by the file is
173          * contained
174          *
175          * @return TRUE if the object is found FALSE if it is not.
176          * @param file The file to find in the list
177          */

178         public synchronized boolean contains(File JavaDoc file) {
179             return loaders.containsKey(file);
180         }
181         
182         
183         /**
184          * This method will add a file to the container.
185          *
186          * @param file The file to add to the container.
187          * @param obj The object to add to the container.
188          */

189         public synchronized void add(File JavaDoc file, Object JavaDoc obj) {
190             loaders.put(file,obj);
191         }
192         
193         
194         /**
195          * This method will return the reference to the deployment loader
196          * identified by the file.
197          *
198          * @return The reference to the deployment loader.
199          * @param file The reference to the file.
200          */

201         public synchronized DeploymentLoader get(File JavaDoc file) {
202             return (DeploymentLoader)loaders.get(file);
203         }
204         
205         
206         /**
207          * This method removes the loader from the loader list identified by the
208          * key.
209          *
210          * @param file The file to remove from the list.
211          */

212         public synchronized void remove(File JavaDoc file) {
213             loaders.remove(file);
214         }
215         
216         
217         /**
218          * This method will return the keys for the loaders.
219          *
220          * @return The keys for the set.
221          */

222         public synchronized Set JavaDoc getKeys() {
223             return loaders.keySet();
224         }
225     }
226     
227     // the class log variable
228
protected Logger log =
229         Logger.getLogger(DeploymentManager.class.getName());
230     
231     // private member variables
232
private LoaderList loaderList = null;
233     private CoadunationThreadGroup threadGroup = null;
234     private BeanManager beanManager = null;
235     private JMXBeanManager jmxBeanManager = null;
236     private WebServiceManager webServiceManager = null;
237     private DeploymentThread deploymentThread = null;
238     private File JavaDoc deploymentDir = null;
239     
240     
241     /**
242      * Creates a new instance of DeploymentManager.
243      *
244      * @param threadGroup The reference to the thread manager.
245      * @param beanManager The reference to the bean manager object.
246      * @param jmxBeanManager The reference to the jmx bean object.
247      * @param webServiceManager The web service manager object.
248      * @exception DeploymentException
249      */

250     public DeploymentManager(CoadunationThreadGroup threadGroup,BeanManager beanManager,
251             JMXBeanManager jmxBeanManager, WebServiceManager webServiceManager)
252     throws DeploymentException {
253         try {
254             // setup the member variables
255
loaderList = new LoaderList();
256             this.threadGroup = threadGroup.createThreadGroup();
257             this.beanManager = beanManager;
258             this.jmxBeanManager = jmxBeanManager;
259             this.webServiceManager = webServiceManager;
260             
261             // maintain the tmp directory for the loaders
262
maintainTmpDirectory();
263             
264             // retrieve the configuration
265
Configuration config = ConfigurationFactory.getInstance().getConfig(
266                         this.getClass());
267             
268             // retrieve the user information
269
String JavaDoc user = config.getString("username");
270             
271             deploymentDir = new File JavaDoc(config.getString("directory"));
272             if (deploymentDir.isDirectory() == false) {
273                 throw new DeploymentException(
274                     "The deployment directory [" + config.getString("directory")
275                     + "] is invalid");
276             }
277             
278             // instanciate the deployment thread
279
deploymentThread = new DeploymentThread(this);
280             this.threadGroup.addThread(deploymentThread,user);
281             deploymentThread.start();
282             
283         } catch (Exception JavaDoc ex) {
284             throw new DeploymentException(
285                     "Failed to start the deployment loader : " + ex.getMessage()
286                     ,ex);
287         }
288     }
289     
290     
291     /**
292      * This method shutdown the processing of the deployment manager.
293      */

294     public void shutdown() {
295         threadGroup.terminate();
296         
297         // unload all the loaded entries
298
try {
299             deploymentThread.join();
300             Set JavaDoc keys = loaderList.getKeys();
301             File JavaDoc[] loadedFiles = new File JavaDoc[keys.size()];
302             loadedFiles = (File JavaDoc[])keys.toArray(loadedFiles);
303             Arrays.sort(loadedFiles);
304             for (int count = 0; count < loadedFiles.length; count++) {
305                     removeEntry(loadedFiles[loadedFiles.length - (count + 1)]);
306             }
307         } catch (Exception JavaDoc ex) {
308             log.error("Failed to shut down an entry because : " + ex.
309                     getMessage(),ex);
310         }
311     }
312     
313     
314     /**
315      * This private method is responsible for controlling the loading, and unloading
316      * of deployment files.
317      */

318     private void manage() {
319         try {
320             // retrieve a list of files
321
File JavaDoc[] files = FileUtil.filter(deploymentDir.listFiles(),".jar");
322             Arrays.sort(files);
323             
324             // check to see which file dates have changed
325
for (int count = 0; count < files.length; count++) {
326                 File JavaDoc file = files[count];
327                 if (loaderList.contains(file) == false) {
328                     continue;
329                 } else if (loaderList.get(file).getLastModified() !=
330                         file.lastModified()) {
331                     removeEntry(file);
332                 }
333             }
334             
335             
336             // load new files
337
for (int count = 0; count < files.length; count++) {
338                 File JavaDoc file = files[count];
339                 if (loaderList.contains(file) == false) {
340                     loadEntry(file);
341                 }
342             }
343             
344             // unload files that have date changes and are no longer there
345
Set JavaDoc keySet = new HashSet JavaDoc(loaderList.getKeys());
346             for (Iterator JavaDoc iter = keySet.iterator(); iter.hasNext();)
347             {
348                 // array for entry
349
File JavaDoc key = (File JavaDoc)iter.next();
350                 boolean found = false;
351                 for (int count = 0; count < files.length; count++) {
352                     File JavaDoc file = files[count];
353                     if (file.equals(key)) {
354                         found = true;
355                         break;
356                     }
357                 }
358                 if (found == false) {
359                     removeEntry(key);
360                 }
361             }
362             
363             
364         } catch (Exception JavaDoc ex) {
365             log.error("Failed to load the files : " + ex.getMessage(),ex);
366         }
367         // set the deployment monitor
368
if (false == DeploymentMonitor.getInstance().
369                 isInitDeployComplete()) {
370             DeploymentMonitor.getInstance().initDeployCompleted();
371         }
372     }
373     
374     
375     /**
376      * This method will be responsible for removing a loader from memory.
377      *
378      * @param file The path to the file to remove.
379      */

380     private void removeEntry(File JavaDoc file) {
381         ClassLoader JavaDoc originalLoader = null;
382         try {
383             // instanciate the
384
DeploymentLoader loader = loaderList.get(file);
385             if (loader.getSuccessful() == false) {
386                 log.info("This object was not loaded succesfully ["
387                         + file.getAbsolutePath() + "] removing internal " +
388                         "reference");
389                 loaderList.remove(file);
390                 return;
391             }
392             log.info("Un-load the deployment file [" + file.getAbsolutePath() +
393                     "]");
394             originalLoader = Thread.currentThread().getContextClassLoader();
395             Thread.currentThread().setContextClassLoader(loader.getClassLoader());
396             CacheRegistry.getInstance().terminateCache();
397             beanManager.unLoad(loader);
398             jmxBeanManager.unLoad(loader);
399             webServiceManager.unLoad(loader);
400             ObjectLockFactory.fin();
401             TransactionManager.fin();
402             loaderList.remove(file);
403             
404             // remove the reference to the loader from the class loader lookup
405
DeploymentLoader.ClassLoaderLookup.getInstance().removeClassLoader(
406                     loader);
407             
408             NamingDirector.getInstance().releaseContext();
409             ThreadGroupManager.getInstance().terminateThreadGroup();
410         } catch (Exception JavaDoc ex) {
411             log.error("Failed to unload the file [" + file.getAbsolutePath() +
412                     "]",ex);
413         } finally {
414             try {
415                 if (originalLoader != null) {
416                     // reset the class loader
417
Thread.currentThread().setContextClassLoader(
418                             originalLoader);
419                 }
420             } catch (Exception JavaDoc exc) {
421                 // ignore
422
}
423         }
424     }
425     
426     
427     /**
428      * This method will and entry into memory.
429      *
430      * @param file The file to load into memory.
431      */

432     private void loadEntry(File JavaDoc file) {
433         DeploymentLoader loader = null;
434         ClassLoader JavaDoc originalLoader = null;
435         try {
436             // instanciate the
437
log.info("Load the deployment file [" + file.getAbsolutePath() +
438                     "]");
439             try {
440                 loader = new DeploymentLoader(file);
441             } catch (Exception JavaDoc ex) {
442                 log.warn("Failed to load the file [" + file.getAbsolutePath() +
443                     "] will try this it again later.",ex);
444                 return;
445             }
446             
447             loaderList.add(file,loader);
448             if (loader.getSuccessful() == false) {
449                 log.info("The failed to load the ["
450                         + file.getAbsolutePath() + "].");
451                 return;
452             }
453             
454             // set the class loader for the beans
455
originalLoader = Thread.currentThread().getContextClassLoader();
456             Thread.currentThread().setContextClassLoader(loader.getClassLoader());
457             ThreadGroupManager.getInstance().initThreadGroup(threadGroup);
458             NamingDirector.getInstance().initContext();
459             CacheRegistry.getInstance().initCache();
460             ObjectLockFactory.init();
461             TransactionManager.init();
462             beanManager.load(loader);
463             jmxBeanManager.load(loader);
464             webServiceManager.load(loader);
465             
466             log.info("The file ["
467                         + file.getAbsolutePath() + "] was loaded successfully");
468         } catch (Exception JavaDoc ex) {
469             // unload if there was any problem while loading the entry.
470
try {
471                 if (loader != null) {
472                     beanManager.unLoad(loader);
473                     jmxBeanManager.unLoad(loader);
474                     webServiceManager.unLoad(loader);
475                 }
476                 
477             } catch (Exception JavaDoc exc) {
478                 // ignore any exceptions
479
}
480             try {
481                 CacheRegistry.getInstance().terminateCache();
482             } catch (Exception JavaDoc exc) {
483                 // failed to terminate the cache
484
log.error("Failed to terminate the cache [" + exc.getMessage() +
485                         "]",ex);
486             }
487             try {
488                 ThreadGroupManager.getInstance().terminateThreadGroup();
489             } catch (Exception JavaDoc exc) {
490                 // failed to terminate the cache
491
log.error("Failed to terminate the thread group ["
492                         + exc.getMessage() + "]",ex);
493             }
494             log.error("Failed to load the file [" + file.getAbsolutePath() +
495                     "]",ex);
496         } finally {
497             try {
498                 if (originalLoader != null) {
499                     // reset the class loader
500
Thread.currentThread().setContextClassLoader(
501                             originalLoader);
502                 }
503             } catch (Exception JavaDoc exc) {
504                 // ignore
505
}
506         }
507     }
508     
509     
510     /**
511      * This method maintains the jar temp directory if the directory does not
512      * exist it will create it, and it will delete all misc jar files that it
513      * finds.
514      *
515      * @exception DeploymentException
516      */

517     private void maintainTmpDirectory() throws DeploymentException {
518         try {
519             // retrieve the loader configuration.
520
Configuration loaderConfig = ConfigurationFactory.getInstance().
521                         getConfig(DeploymentLoader.class);
522             
523             // retrieve the temp directory
524
String JavaDoc tmpDirPath = loaderConfig.getString(
525                     DeploymentLoader.TEMP_DIRECTORY);
526             
527             // create the temporary directory
528
File JavaDoc tmpDir = new File JavaDoc(tmpDirPath);
529             tmpDir.mkdirs();
530             if (tmpDir.isDirectory() == false) {
531                 throw new DeploymentException(
532                         "Failed to create the directory [" + tmpDirPath + "]");
533             }
534             deleteDirectoryRecursive(tmpDir);
535         } catch (Exception JavaDoc ex) {
536             throw new DeploymentException("Failed to clean the tmp directory : "
537                     + ex.getMessage(),ex);
538         }
539     }
540     
541     
542     /**
543      * This method is called to delete all the files from a given directory.
544      *
545      * @param dir The directory to delete the files from
546      */

547     private void deleteDirectoryRecursive(File JavaDoc dir) throws Exception JavaDoc {
548         // list the files
549
File JavaDoc[] tmpFiles = dir.listFiles();
550         for (int index = 0; index < tmpFiles.length; index++) {
551             if (tmpFiles[index].isDirectory()) {
552                 deleteDirectoryRecursive(tmpFiles[index]);
553             }
554             tmpFiles[index].delete();
555         }
556     }
557 }
558
Popular Tags