KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > servicemix > jbi > framework > InstallationService


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.servicemix.jbi.framework;
18
19 import java.io.File JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.Map JavaDoc;
23 import java.util.Properties JavaDoc;
24
25 import javax.jbi.JBIException;
26 import javax.jbi.management.DeploymentException;
27 import javax.jbi.management.InstallationServiceMBean;
28 import javax.jbi.management.InstallerMBean;
29 import javax.management.Attribute JavaDoc;
30 import javax.management.JMException JavaDoc;
31 import javax.management.MBeanOperationInfo JavaDoc;
32 import javax.management.MBeanServer JavaDoc;
33 import javax.management.ObjectName JavaDoc;
34 import javax.resource.spi.work.Work JavaDoc;
35 import javax.resource.spi.work.WorkException JavaDoc;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.apache.servicemix.jbi.container.ComponentEnvironment;
40 import org.apache.servicemix.jbi.container.EnvironmentContext;
41 import org.apache.servicemix.jbi.container.JBIContainer;
42 import org.apache.servicemix.jbi.deployment.Component;
43 import org.apache.servicemix.jbi.deployment.Descriptor;
44 import org.apache.servicemix.jbi.deployment.DescriptorFactory;
45 import org.apache.servicemix.jbi.deployment.SharedLibrary;
46 import org.apache.servicemix.jbi.management.BaseSystemService;
47 import org.apache.servicemix.jbi.management.ManagementContext;
48 import org.apache.servicemix.jbi.management.OperationInfoHelper;
49 import org.apache.servicemix.jbi.management.ParameterHelper;
50 import org.apache.servicemix.jbi.util.FileUtil;
51 import org.apache.servicemix.jbi.util.FileVersionUtil;
52
53 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
54
55 /**
56  * Installation Service - installs/uninstalls archives
57  *
58  * @version $Revision: 426415 $
59  */

60 public class InstallationService extends BaseSystemService implements InstallationServiceMBean {
61     
62     private static final Log log=LogFactory.getLog(InstallationService.class);
63     
64     private EnvironmentContext environmentContext;
65     private ManagementContext managementContext;
66     private Map JavaDoc installers=new ConcurrentHashMap();
67     private Map JavaDoc nonLoadedInstallers = new ConcurrentHashMap();
68
69     /**
70      * Get Description
71      *
72      * @return description of this item
73      */

74     public String JavaDoc getDescription(){
75         return "installs/uninstalls Components";
76     }
77
78     /**
79      * Load the installer for a new component from a component installation package.
80      *
81      * @param installJarURL -
82      * URL locating a jar file containing a JBI Installable Component.
83      * @return - the JMX ObjectName of the InstallerMBean loaded from installJarURL.
84      */

85     public synchronized ObjectName JavaDoc loadNewInstaller(String JavaDoc installJarURL){
86         try{
87             ObjectName JavaDoc result=null;
88             if(log.isDebugEnabled()){
89                 log.debug("Loading new installer from "+installJarURL);
90             }
91             File JavaDoc tmpDir=AutoDeploymentService.unpackLocation(environmentContext.getTmpDir(),installJarURL);
92             if(tmpDir!=null){
93                 Descriptor root=DescriptorFactory.buildDescriptor(tmpDir);
94                 if(root!=null&&root.getComponent()!=null){
95                     String JavaDoc componentName=root.getComponent().getIdentification().getName();
96                     if(!installers.containsKey(componentName)){
97                         InstallerMBeanImpl installer=doInstallArchive(tmpDir,root);
98                         if(installer!=null){
99                             result=installer.getObjectName();
100                             installers.put(componentName,installer);
101                         }
102                     }else{
103                         throw new RuntimeException JavaDoc("An installer already exists for "+componentName);
104                     }
105                 }else{
106                     throw new RuntimeException JavaDoc("Could not find Component from: "+installJarURL);
107                 }
108             }else{
109                 throw new RuntimeException JavaDoc("location: "+installJarURL+" isn't valid");
110             }
111             return result;
112         }catch(Throwable JavaDoc t){
113             log.error("Deployment failed",t);
114             if(t instanceof Error JavaDoc){
115                 throw (Error JavaDoc) t;
116             }
117             if(t instanceof RuntimeException JavaDoc){
118                 throw (RuntimeException JavaDoc) t;
119             }else{
120                 throw new RuntimeException JavaDoc("Deployment failed: "+t.getMessage());
121             }
122         }
123     }
124
125     /**
126      * Load the InstallerMBean for a previously installed component.
127      *
128      * @param aComponentName -
129      * the component name identifying the installer to load.
130      * @return - the JMX ObjectName of the InstallerMBean loaded from an existing installation context.
131      */

132     public ObjectName JavaDoc loadInstaller(String JavaDoc aComponentName) {
133         InstallerMBeanImpl installer = (InstallerMBeanImpl) installers.get(aComponentName);
134         if (installer == null) {
135             installer = (InstallerMBeanImpl) nonLoadedInstallers.get(aComponentName);
136             if (installer != null) {
137                 try {
138                     // create an MBean for the installer
139
ObjectName JavaDoc objectName = managementContext.createCustomComponentMBeanName("Installer", aComponentName);
140                     installer.setObjectName(objectName);
141                     managementContext.registerMBean(objectName, installer,
142                             InstallerMBean.class,
143                             "standard installation controls for a Component");
144                 } catch (Exception JavaDoc e) {
145                     throw new RuntimeException JavaDoc("Could not load installer", e);
146                 }
147                 return installer.getObjectName();
148             }
149         }
150         return null;
151     }
152     
153     private InstallerMBeanImpl createInstaller(String JavaDoc componentName) throws IOException JavaDoc, DeploymentException {
154         File JavaDoc installationDir = environmentContext.getComponentInstallationDir(componentName);
155         Descriptor root = DescriptorFactory.buildDescriptor(installationDir);
156         Component descriptor = root.getComponent();
157
158         InstallationContextImpl installationContext = new InstallationContextImpl(descriptor);
159         installationContext.setInstall(false);
160         installationContext.setInstallRoot(installationDir);
161         // now build the ComponentContext
162
File JavaDoc componentRoot = environmentContext.getComponentRootDir(componentName);
163         ComponentContextImpl context = buildComponentContext(componentRoot, installationDir, componentName);
164         installationContext.setContext(context);
165         InstallerMBeanImpl installer = new InstallerMBeanImpl(container,
166                                                               installationContext);
167         return installer;
168     }
169
170     /**
171      * Unload a JBI Installable Component installer.
172      *
173      * @param componentName -
174      * the component name identifying the installer to unload.
175      * @param isToBeDeleted -
176      * true if the component is to be deleted as well.
177      * @return - true if the operation was successful, otherwise false.
178      */

179     public boolean unloadInstaller(String JavaDoc componentName, boolean isToBeDeleted) {
180         boolean result = false;
181         try {
182             container.getBroker().suspend();
183             InstallerMBeanImpl installer = (InstallerMBeanImpl) installers.remove(componentName);
184             result = installer != null;
185             if(result) {
186                 container.getManagementContext().unregisterMBean(installer);
187                 if (isToBeDeleted) {
188                     installer.uninstall();
189                 } else {
190                     nonLoadedInstallers.put(componentName, installer);
191                 }
192             }
193         } catch(JBIException e) {
194             String JavaDoc errStr = "Problem shutting down Component: " + componentName;
195             log.error(errStr, e);
196         } finally {
197             container.getBroker().resume();
198         }
199         return result;
200     }
201
202     /**
203      * Install a shared library jar.
204      *
205      * @param aSharedLibURI -
206      * URI locating a jar file containing a shared library.
207      * @return - the name of the shared library loaded from aSharedLibURI.
208      */

209     public String JavaDoc installSharedLibrary(String JavaDoc aSharedLibURI){
210         String JavaDoc result="";
211         try{
212             File JavaDoc tmpDir=AutoDeploymentService.unpackLocation(environmentContext.getTmpDir(),aSharedLibURI);
213             if(tmpDir!=null){
214                 Descriptor root=DescriptorFactory.buildDescriptor(tmpDir);
215                 SharedLibrary sl=root.getSharedLibrary();
216                 if(sl!=null){
217                     result=doInstallSharedLibrary(tmpDir,sl);
218                 }
219             }else{
220                 log.warn("location: "+aSharedLibURI+" isn't valid");
221             }
222         }catch(DeploymentException e){
223             log.error("Deployment failed",e);
224         }
225         return result;
226     }
227
228     /**
229      * Uninstall a shared library.
230      *
231      * @param aSharedLibName -
232      * the name of the shared library to uninstall.
233      * @return - true iff the uninstall was successful.
234      */

235     public boolean uninstallSharedLibrary(String JavaDoc aSharedLibName) {
236         // TODO: should check existence of shared library
237
// and that it is not currently in use
238
container.getRegistry().unregisterSharedLibrary(aSharedLibName);
239         environmentContext.removeSharedLibraryDirectory(aSharedLibName);
240         return true;
241     }
242
243     /**
244      * Initialize the Service
245      *
246      * @param container
247      * @throws JBIException
248      * @throws DeploymentException
249      */

250     public void init(JBIContainer container) throws JBIException {
251         super.init(container);
252         this.environmentContext = container.getEnvironmentContext();
253         this.managementContext = container.getManagementContext();
254         buildState();
255     }
256     
257     protected Class JavaDoc getServiceMBean() {
258         return InstallationServiceMBean.class;
259     }
260
261     /**
262      * Install an archive
263      *
264      * @param location
265      * @param props
266      * @param autoStart
267      * @throws DeploymentException
268      */

269     public void install(String JavaDoc location, Properties JavaDoc props, boolean autoStart) throws DeploymentException {
270         File JavaDoc tmpDir = AutoDeploymentService.unpackLocation(environmentContext.getTmpDir(),location);
271         if (tmpDir != null) {
272             Descriptor root = DescriptorFactory.buildDescriptor(tmpDir);
273             if (root != null) {
274                 install(tmpDir, props, root, autoStart);
275             }else{
276                 log.error("Could not find Descriptor from: " + location);
277             }
278         }else{
279             log.warn("location: "+location+" isn't valid");
280         }
281     }
282
283     /**
284      * Install an archive
285      *
286      * @param tmpDir
287      * @param root
288      * @param autoStart
289      * @throws DeploymentException
290      */

291     protected void install(File JavaDoc tmpDir, Properties JavaDoc props, Descriptor root, boolean autoStart) throws DeploymentException {
292         if (root.getComponent() != null) {
293             String JavaDoc componentName = root.getComponent().getIdentification().getName();
294             if (installers.containsKey(componentName)) {
295                 throw new DeploymentException("Component " + componentName + " is already installed");
296             }
297             InstallerMBeanImpl installer = doInstallArchive(tmpDir,root);
298             if (installer != null) {
299                 try {
300                     if (props != null && props.size() > 0) {
301                         ObjectName JavaDoc on = installer.getInstallerConfigurationMBean();
302                         if (on == null ) {
303                             log.warn("Could not find installation configuration MBean. Installation properties will be ignored.");
304                         } else {
305                             MBeanServer JavaDoc mbs = managementContext.getMBeanServer();
306                             for (Iterator JavaDoc it = props.keySet().iterator(); it.hasNext();) {
307                                 String JavaDoc key = (String JavaDoc) it.next();
308                                 String JavaDoc val = props.getProperty(key);
309                                 try {
310                                     mbs.setAttribute(on, new Attribute JavaDoc(key, val));
311                                 } catch (JMException JavaDoc e) {
312                                     throw new DeploymentException("Could not set installation property: (" + key + " = " + val, e);
313                                 }
314                             }
315                         }
316                     }
317                     installer.install();
318                 } catch(JBIException e) {
319                     throw new DeploymentException(e);
320                 }
321                 if (autoStart) {
322                     try{
323                         ComponentMBeanImpl lcc = container.getComponent(componentName);
324                         if (lcc != null) {
325                             lcc.start();
326                         }else{
327                             log.warn("No ComponentConnector found for Component "+componentName);
328                         }
329                     }catch(JBIException e){
330                         String JavaDoc errStr="Failed to start Component: "+componentName;
331                         log.error(errStr,e);
332                         throw new DeploymentException(e);
333                     }
334                 }
335                 installers.put(componentName,installer);
336             }
337         }
338     }
339
340     /**
341      * Get an array of MBeanOperationInfo
342      *
343      * @return array of OperationInfos
344      * @throws JMException
345      */

346     public MBeanOperationInfo JavaDoc[] getOperationInfos() throws JMException JavaDoc{
347         OperationInfoHelper helper=new OperationInfoHelper();
348         ParameterHelper ph=helper.addOperation(getObjectToManage(),"loadNewInstaller",1,"load a new Installer ");
349         ph.setDescription(0,"installJarURL","URL locating the install Jar");
350         ph=helper.addOperation(getObjectToManage(),"loadInstaller",1,
351                         "load installer for a previously installed component");
352         ph.setDescription(0,"componentName","Name of the Component");
353         ph=helper.addOperation(getObjectToManage(),"unloadInstaller",2,"unload an installer");
354         ph.setDescription(0,"componentName","Name of the Component");
355         ph.setDescription(1,"isToBeDeleted","true if component is to be deleted");
356         ph=helper.addOperation(getObjectToManage(),"installSharedLibrary",1,"Install a shared library jar");
357         ph.setDescription(0,"sharedLibURI","URI for the jar to be installed");
358         ph=helper.addOperation(getObjectToManage(),"uninstallSharedLibrary",1,"Uninstall a shared library jar");
359         ph.setDescription(0,"sharedLibName","name of the shared library");
360         ph=helper.addOperation(getObjectToManage(),"install",1,"install and deplot an archive");
361         ph.setDescription(0,"location","location of archive");
362         ph=helper.addOperation(getObjectToManage(),"install",2,"install and deplot an archive");
363         ph.setDescription(0,"location","location of archive");
364         ph.setDescription(1,"autostart","automatically start the Component");
365         return OperationInfoHelper.join(super.getOperationInfos(),helper.getOperationInfos());
366     }
367
368     protected InstallerMBeanImpl doInstallArchive(File JavaDoc tmpDirectory,Descriptor descriptor) throws DeploymentException{
369         InstallerMBeanImpl installer=null;
370         Component component=descriptor.getComponent();
371         if(component!=null){
372             installer=doInstallComponent(tmpDirectory,component);
373         }
374         return installer;
375     }
376
377     protected String JavaDoc doInstallSharedLibrary(File JavaDoc tmpDirectory, SharedLibrary descriptor) throws DeploymentException{
378         String JavaDoc result = null;
379         if (descriptor != null) {
380             File JavaDoc installationDir = null;
381             try {
382                 result = descriptor.getIdentification().getName();
383                 File JavaDoc rootDir = environmentContext.createSharedLibraryDirectory(result);
384                 installationDir = FileVersionUtil.getNewVersionDirectory(rootDir);
385                 if (!tmpDirectory.renameTo(installationDir)) {
386                     throw new DeploymentException("Unable to rename " + tmpDirectory + " to " + installationDir);
387                 }
388                 if (log.isDebugEnabled()) {
389                     log.debug("Moved " + tmpDirectory + " to " + installationDir);
390                 }
391                 container.getRegistry().registerSharedLibrary(descriptor, installationDir);
392             } catch (Exception JavaDoc e) {
393                 log.error("Deployment of Shared Library failed", e);
394                 // remove any files created for installation
395
FileUtil.deleteFile(installationDir);
396                 throw new DeploymentException(e);
397             } finally {
398                 FileUtil.deleteFile(tmpDirectory);
399             }
400         }
401         return result;
402     }
403
404     protected InstallerMBeanImpl doInstallComponent(File JavaDoc tmpDirectory,Component descriptor) throws DeploymentException{
405         // move archive to Component directory
406
InstallerMBeanImpl result=null;
407         String JavaDoc name=descriptor.getIdentification().getName();
408         try{
409             File JavaDoc oldInstallationDir=environmentContext.getComponentInstallationDir(name);
410             // try and delete the old version ? - maybe should leave around ??
411
if(!FileUtil.deleteFile(oldInstallationDir)){
412                 log.warn("Failed to delete old installation directory: " + oldInstallationDir.getPath());
413             }
414             File JavaDoc componentRoot=environmentContext.createComponentRootDir(name);
415             // this will get the new one
416
File JavaDoc installationDir=environmentContext.getNewComponentInstallationDir(name);
417             tmpDirectory.renameTo(installationDir);
418             if (log.isDebugEnabled()) {
419                 log.debug("Moved " + tmpDirectory + " to " + installationDir);
420             }
421             result=initializeInstaller(installationDir,componentRoot,descriptor);
422             return result;
423         }catch(IOException JavaDoc e){
424             throw new DeploymentException(e);
425         }
426     }
427
428     private InstallerMBeanImpl initializeInstaller(File JavaDoc installationDir,File JavaDoc componentRoot,Component descriptor)
429                     throws DeploymentException{
430         InstallerMBeanImpl result=null;
431         try{
432             String JavaDoc name=descriptor.getIdentification().getName();
433             InstallationContextImpl installationContext=new InstallationContextImpl(descriptor);
434             installationContext.setInstall(true);
435             installationContext.setInstallRoot(installationDir);
436             // now build the ComponentContext
437
ComponentContextImpl context = buildComponentContext(componentRoot, installationDir, name);
438             installationContext.setContext(context);
439             result = new InstallerMBeanImpl(container,
440                                             installationContext);
441             // create an MBean for the installer
442
ObjectName JavaDoc objectName = managementContext.createCustomComponentMBeanName("Installer", name);
443             result.setObjectName(objectName);
444             managementContext.registerMBean(objectName,result,InstallerMBean.class,
445                             "standard installation controls for a Component");
446         }catch(Throwable JavaDoc e){
447             log.error("Deployment of Component failed",e);
448             // remove any files created for installation
449
environmentContext.removeComponentRootDirectory(descriptor.getIdentification().getName());
450             throw new DeploymentException(e);
451         }
452         return result;
453     }
454
455     protected void buildState(){
456         buildSharedLibs();
457         buildComponents();
458     }
459
460     /**
461      * returns true if a shared library is already installed
462      *
463      * @param name
464      * @return true/false
465      */

466     protected boolean containsSharedLibrary(String JavaDoc name){
467         return container.getRegistry().getSharedLibrary(name) != null;
468     }
469
470     protected void buildSharedLibs(){
471         // walk through shared libaries and add then to the ClassLoaderService
472
File JavaDoc top = environmentContext.getSharedLibDir();
473         if (top != null && top.exists() && top.isDirectory()) {
474             // directory structure is sharedlibraries/<lib name>/version_x/stuff ...
475
File JavaDoc[] files = top.listFiles();
476             if (files != null) {
477                 for (int i = 0; i < files.length; i++) {
478                     if (files[i].isDirectory()) {
479                         File JavaDoc dir = FileVersionUtil.getLatestVersionDirectory(files[i]);
480                         if (dir != null) {
481                             Descriptor root = DescriptorFactory.buildDescriptor(dir);
482                             if (root != null) {
483                                 SharedLibrary sl = root.getSharedLibrary();
484                                 if (sl != null) {
485                                     try {
486                                         container.getRegistry().registerSharedLibrary(sl, dir);
487                                     } catch (Exception JavaDoc e) {
488                                         log.error("Failed to initialize sharted library", e);
489                                     }
490                                 }
491                             }
492                         }
493                     }
494                 }
495             }
496         }
497     }
498
499     protected void buildComponents(){
500         // walk through components and add then to the ClassLoaderService
501
File JavaDoc top=environmentContext.getComponentsDir();
502         if(top!=null&&top.exists()&&top.isDirectory()){
503             // directory structure is components/<component name>/installation ...
504
File JavaDoc[] files=top.listFiles();
505             if(files!=null){
506                 for(int i=0;i<files.length;i++){
507                     if(files[i].isDirectory()){
508                         final File JavaDoc directory=files[i];
509                         try{
510                             container.getWorkManager().doWork(new Work JavaDoc(){
511                                 public void release(){}
512
513                                 public void run(){
514                                     try{
515                                         buildComponent(directory);
516                                     }catch(DeploymentException e){
517                                         log.error("Could not build Component: "+directory.getName(),e);
518                                         log.warn("Deleting Component directory: "+directory);
519                                         FileUtil.deleteFile(directory);
520                                     }
521                                 }
522                             });
523                         }catch(WorkException JavaDoc e){
524                             log.error("Could not build Component: "+directory.getName(),e);
525                             log.warn("Deleting Component directory: "+directory);
526                             FileUtil.deleteFile(directory);
527                         }
528                     }
529                 }
530             }
531         }
532     }
533
534     protected void buildComponent(File JavaDoc componentDirectory)
535             throws DeploymentException {
536         try {
537             String JavaDoc componentName = componentDirectory.getName();
538             ComponentEnvironment env = container.getEnvironmentContext().getComponentEnvironment(componentName);
539             if (!env.getStateFile().exists()) {
540                 // An installer has been created but the component has not been installed
541
// So remove it
542
FileUtil.deleteFile(componentDirectory);
543             } else {
544                 InstallerMBeanImpl installer = createInstaller(componentName);
545                 installer.activateComponent();
546                 nonLoadedInstallers.put(componentName, installer);
547             }
548         } catch (Throwable JavaDoc e) {
549             log.error("Failed to deploy component: "
550                     + componentDirectory.getName(), e);
551             throw new DeploymentException(e);
552         }
553     }
554
555     protected ComponentContextImpl buildComponentContext(File JavaDoc componentRoot, File JavaDoc installRoot, String JavaDoc name)
556                     throws IOException JavaDoc {
557         ComponentNameSpace cns = new ComponentNameSpace(container.getName(), name);
558         ComponentContextImpl context = new ComponentContextImpl(container, cns);
559         ComponentEnvironment env = new ComponentEnvironment();
560         FileUtil.buildDirectory(componentRoot);
561         File JavaDoc privateWorkspace = environmentContext.createWorkspaceDirectory(name);
562         env.setWorkspaceRoot(privateWorkspace);
563         env.setComponentRoot(componentRoot);
564         env.setInstallRoot(installRoot);
565         context.setEnvironment(env);
566         return context;
567     }
568
569 }
570
Popular Tags