KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > loom > components > deployer > DefaultDeployer


1 /* ====================================================================
2  * Loom Software License, version 1.1
3  *
4  * Copyright (c) 2003, Loom Group. All rights reserved.
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  *
17  * 3. Neither the name of the Loom Group nor the name "Loom" nor
18  * the names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior
20  * written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * ====================================================================
36  *
37  * Loom includes code from the Apache Software Foundation
38  *
39  * ====================================================================
40  * The Apache Software License, Version 1.1
41  *
42  * Copyright (c) 1997-2003 The Apache Software Foundation. All rights
43  * reserved.
44  *
45  * Redistribution and use in source and binary forms, with or without
46  * modification, are permitted provided that the following conditions
47  * are met:
48  *
49  * 1. Redistributions of source code must retain the above copyright
50  * notice, this list of conditions and the following disclaimer.
51  *
52  * 2. Redistributions in binary form must reproduce the above copyright
53  * notice, this list of conditions and the following disclaimer in
54  * the documentation and/or other materials provided with the
55  * distribution.
56  *
57  * 3. The end-user documentation included with the redistribution,
58  * if any, must include the following acknowledgment:
59  * "This product includes software developed by the
60  * Apache Software Foundation (http://www.apache.org/)."
61  * Alternately, this acknowledgment may appear in the software
62  * itself, if and wherever such third-party acknowledgments
63  * normally appear.
64  *
65  * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
66  * must not be used to endorse or promote products derived from this
67  * software without prior written permission. For written
68  * permission, please contact apache@apache.org.
69  *
70  * 5. Products derived from this software may not be called "Apache",
71  * nor may "Apache" appear in their name, without prior written
72  * permission of the Apache Software Foundation.
73  *
74  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
75  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
76  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
77  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
78  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
79  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
80  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
81  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
82  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
83  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
84  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
85  * SUCH DAMAGE.
86  */

87 package org.codehaus.loom.components.deployer;
88
89 import java.io.File JavaDoc;
90 import java.net.MalformedURLException JavaDoc;
91 import java.net.URL JavaDoc;
92 import java.util.HashMap JavaDoc;
93 import java.util.Hashtable JavaDoc;
94 import java.util.Map JavaDoc;
95 import java.util.Set JavaDoc;
96
97 import org.apache.avalon.phoenix.BlockContext;
98
99 import org.codehaus.loom.components.util.ConfigurationBuilder;
100 import org.codehaus.loom.components.util.profile.ComponentProfile;
101 import org.codehaus.loom.components.util.profile.PartitionProfile;
102 import org.codehaus.loom.components.util.profile.ProfileBuilder;
103 import org.codehaus.loom.components.util.verifier.SarVerifier;
104 import org.codehaus.loom.interfaces.ClassLoaderManager;
105 import org.codehaus.loom.interfaces.ClassLoaderSet;
106 import org.codehaus.loom.interfaces.ConfigurationInterceptor;
107 import org.codehaus.loom.interfaces.ConfigurationValidator;
108 import org.codehaus.loom.interfaces.ContainerConstants;
109 import org.codehaus.loom.interfaces.Deployer;
110 import org.codehaus.loom.interfaces.Installer;
111 import org.codehaus.loom.interfaces.Kernel;
112 import org.codehaus.loom.interfaces.LogManager;
113 import org.codehaus.loom.interfaces.LoomException;
114 import org.codehaus.spice.loggerstore.LoggerStore;
115 import org.codehaus.spice.salt.i18n.ResourceManager;
116 import org.codehaus.spice.salt.i18n.Resources;
117 import org.codehaus.dna.AbstractLogEnabled;
118 import org.codehaus.dna.Active;
119 import org.codehaus.dna.Composable;
120 import org.codehaus.dna.Configuration;
121 import org.codehaus.dna.ConfigurationException;
122 import org.codehaus.dna.MissingResourceException;
123 import org.codehaus.dna.ResourceLocator;
124 import org.codehaus.dna.impl.DefaultConfiguration;
125 import org.xml.sax.InputSource JavaDoc;
126
127 /**
128  * Deploy .sar files into a kernel using this class.
129  *
130  * @author Peter Donald
131  * @dna.component
132  * @mx.component
133  */

134 public class DefaultDeployer
135     extends AbstractLogEnabled
136     implements Deployer, Composable, Active
137 {
138     private static final Resources REZ =
139         ResourceManager.getPackageResources( DefaultDeployer.class );
140
141     private final SarVerifier m_verifier = new SarVerifier();
142     private final ProfileBuilder m_builder = new PhoenixProfileBuilder();
143     private final Map JavaDoc m_installations = new Hashtable JavaDoc();
144     private LogManager m_logManager;
145     private Kernel m_kernel;
146     private Installer m_installer;
147     private ConfigurationInterceptor m_repository;
148     private ClassLoaderManager m_classLoaderManager;
149     private ConfigurationValidator m_validator;
150
151     /**
152      * @dna.dependency type="Kernel"
153      * @dna.dependency type="ConfigurationInterceptor"
154      * @dna.dependency type="ClassLoaderManager"
155      * @dna.dependency type="LogManager"
156      * @dna.dependency type="ConfigurationValidator"
157      * @dna.dependency type="Installer"
158      */

159     public void compose( final ResourceLocator locator )
160         throws MissingResourceException
161     {
162         m_kernel = (Kernel)locator.lookup( Kernel.class.getName() );
163         m_repository = (ConfigurationInterceptor)locator.
164             lookup( ConfigurationInterceptor.class.getName() );
165         m_classLoaderManager = (ClassLoaderManager)locator.
166             lookup( ClassLoaderManager.class.getName() );
167         m_logManager =
168             (LogManager)locator.lookup( LogManager.class.getName() );
169         m_validator =
170             (ConfigurationValidator)locator.lookup( ConfigurationValidator.class.getName() );
171         m_installer = (Installer)locator.lookup( Installer.class.getName() );
172     }
173
174     public void initialize()
175         throws Exception JavaDoc
176     {
177         setupLogger( m_verifier );
178         setupLogger( m_builder );
179     }
180
181     /**
182      * Dispose the deployer which effectively means undeploying all the currently deployed apps.
183      */

184     public void dispose()
185     {
186         final Set JavaDoc set = m_installations.keySet();
187         final String JavaDoc[] applications =
188             (String JavaDoc[])set.toArray( new String JavaDoc[set.size()] );
189         for( int i = 0; i < applications.length; i++ )
190         {
191             final String JavaDoc name = applications[i];
192             try
193             {
194                 undeploy( name );
195             }
196             catch( final LoomException de )
197             {
198                 final String JavaDoc message =
199                     REZ.format( "deploy.undeploy-indispose.error",
200                                 name,
201                                 de.getMessage() );
202                 getLogger().error( message, de );
203             }
204         }
205     }
206
207     /**
208      * @throws LoomException if an error occurs
209      * @mx.operation description="Redeploy an installation."
210      * @mx.parameter name="name" description="the name of deployment"
211      */

212     public void redeploy( final String JavaDoc name )
213         throws LoomException
214     {
215         final Map JavaDoc installation =
216             (Map JavaDoc)m_installations.get( name );
217         if( null == installation )
218         {
219             final String JavaDoc message =
220                 REZ.format( "deploy.no-deployment.error", name );
221             throw new LoomException( message );
222         }
223         try
224         {
225             final File JavaDoc source = (File JavaDoc)installation.
226                 get( ContainerConstants.INSTALL_SOURCE );
227             redeploy( name, source.toURL() );
228         }
229         catch( final LoomException e )
230         {
231             throw e;
232         }
233         catch( final Exception JavaDoc e )
234         {
235             throw new LoomException( e.getMessage(), e );
236         }
237     }
238
239     /**
240      * Undeploy and deploy an installation.
241      *
242      * @param name the name of deployment
243      * @param location the installation to redeploy
244      *
245      * @throws LoomException if an error occurs
246      */

247     public void redeploy( String JavaDoc name, URL JavaDoc location )
248         throws LoomException
249     {
250         m_kernel.lock();
251         try
252         {
253             undeploy( name );
254             deploy( name, location );
255         }
256         catch( final Exception JavaDoc e )
257         {
258             throw new LoomException( e.getMessage(), e );
259         }
260         finally
261         {
262             m_kernel.unlock();
263         }
264     }
265
266     /**
267      * @throws LoomException if an error occurs
268      * @mx.operation description="Undeploy an installation."
269      * @mx.parameter name="name" description="the name of deployment"
270      */

271     public void undeploy( final String JavaDoc name )
272         throws LoomException
273     {
274         final Map JavaDoc installation =
275             (Map JavaDoc)m_installations.remove( name );
276         if( null == installation )
277         {
278             final String JavaDoc message =
279                 REZ.format( "deploy.no-deployment.error", name );
280             throw new LoomException( message );
281         }
282         try
283         {
284             m_kernel.removeApplication( name );
285             m_installer.uninstall( installation );
286         }
287         catch( final Exception JavaDoc e )
288         {
289             throw new LoomException( e.getMessage(), e );
290         }
291     }
292
293     /**
294      * @throws LoomException if an error occurs
295      * @mx.operation description="Deploy an installation."
296      * @mx.parameter name="name" description="the name of deployment"
297      * @mx.parameter name="sarURL" description="the installation to deploy"
298      */

299     public void deploy( final String JavaDoc name, final String JavaDoc sarURL )
300         throws LoomException
301     {
302         try
303         {
304             deploy( name, new URL JavaDoc( sarURL ) );
305         }
306         catch( MalformedURLException JavaDoc mue )
307         {
308             throw new LoomException( mue.getMessage(), mue );
309         }
310     }
311
312     /**
313      * @throws LoomException if an error occurs
314      * @mx.operation description="Deploy an installation."
315      * @mx.parameter name="name" description="the name of deployment"
316      * @mx.parameter name="location" description="the installation to deploy"
317      */

318     public void deploy( final String JavaDoc name, final URL JavaDoc location )
319         throws LoomException
320     {
321         if( m_installations.containsKey( name ) )
322         {
323             final String JavaDoc message =
324                 REZ.format( "deploy.already-deployed.error",
325                             name );
326             throw new LoomException( message );
327         }
328
329         /*
330          * Clear all the reosurces out of ResourceManager cache
331          * so that reloaded applications will have their i18n bundles
332          * reloaded.
333          */

334         ResourceManager.clearResourceCache();
335
336         Map JavaDoc installation = null;
337         boolean success = false;
338         try
339         {
340             //m_baseWorkDirectory
341
installation = m_installer.install( name, location );
342
343             final Configuration config =
344                 getConfigurationFor( installation,
345                                      ContainerConstants.INSTALL_CONFIG,
346                                      null );
347             final Configuration environment =
348                 getConfigurationFor( installation,
349                                      ContainerConstants.INSTALL_ENVIRONMENT,
350                                      null );
351             final Configuration assembly =
352                 getConfigurationFor( installation,
353                                      ContainerConstants.INSTALL_ASSEMBLY,
354                                      ConfigurationBuilder.ASSEMBLY_SCHEMA );
355
356             final File JavaDoc homeDirectory =
357                 (File JavaDoc)installation.get( ContainerConstants.INSTALL_HOME );
358             final File JavaDoc workDirectory =
359                 (File JavaDoc)installation.get( ContainerConstants.INSTALL_WORK );
360
361             final Map JavaDoc data = new HashMap JavaDoc();
362             data.put( BlockContext.APP_NAME, name );
363             data.put( BlockContext.APP_HOME_DIR, homeDirectory );
364
365             final Configuration logs = environment.getChild( "logs", false );
366             //Load hierarchy before classloader placed in context as
367
//that way the logFactory will not try to use the application
368
//specific classloader to load the targets which will cause
369
//CastClassExceptions
370
final LoggerStore store =
371                 m_logManager.createHierarchy( logs,
372                                               homeDirectory,
373                                               workDirectory,
374                                               data );
375
376             final ClassLoaderSet classLoaderSet =
377                 m_classLoaderManager.createClassLoaderSet( environment,
378                                                            data,
379                                                            homeDirectory,
380                                                            workDirectory );
381
382             //TODO: Add classLoaderSet to application resources
383

384             final ClassLoader JavaDoc classLoader =
385                 classLoaderSet.getDefaultClassLoader();
386
387             final Configuration newConfig =
388                 processConfiguration( name, config );
389
390             final Map JavaDoc parameters = new HashMap JavaDoc();
391             parameters.put( ContainerConstants.ASSEMBLY_NAME, name );
392             parameters.put( ContainerConstants.ASSEMBLY_DESCRIPTOR, assembly );
393             parameters.put( ContainerConstants.CONFIG_DESCRIPTOR, newConfig );
394             parameters.put( ContainerConstants.ASSEMBLY_CLASSLOADER,
395                             classLoader );
396
397             //assemble all the blocks for application
398
final PartitionProfile profile =
399                 m_builder.buildProfile( parameters );
400
401             m_verifier.verifySar( profile, classLoader );
402
403             //Setup configuration for all the applications blocks
404
verifyConfiguration( profile, newConfig );
405
406             validateConfiguration( profile, classLoader );
407
408             //Finally add application to kernel
409
m_kernel.addApplication( profile,
410                                      homeDirectory,
411                                      workDirectory,
412                                      classLoader,
413                                      store );
414
415             m_installations.put( name, installation );
416
417             final String JavaDoc message =
418                 REZ.format( "deploy.notice.sar.add",
419                             name );
420             getLogger().debug( message );
421             success = true;
422         }
423         catch( final LoomException de )
424         {
425             throw de;
426         }
427         catch( final Exception JavaDoc e )
428         {
429             //From classloaderManager/kernel
430
throw new LoomException( e.getMessage(), e );
431         }
432         finally
433         {
434             if( !success && null != installation )
435             {
436                 try
437                 {
438                     m_installer.uninstall( installation );
439                 }
440                 catch( final LoomException ie )
441                 {
442                     getLogger().error( ie.getMessage(), ie );
443                 }
444             }
445         }
446     }
447
448     /**
449      * Helper method to load configuration data.
450      *
451      * @param install the install data
452      * @param key the key under which config data is stored in install data
453      *
454      * @return the Configuration
455      *
456      * @throws LoomException if an error occurs
457      */

458     private Configuration getConfigurationFor( final Map JavaDoc install,
459                                                final String JavaDoc key,
460                                                final String JavaDoc schema )
461         throws LoomException
462     {
463         final String JavaDoc location = (String JavaDoc)install.get( key );
464         try
465         {
466             return ConfigurationBuilder.build( new InputSource JavaDoc( location ),
467                                                schema,
468                                                getLogger() );
469         }
470         catch( final Exception JavaDoc e )
471         {
472             final String JavaDoc message = REZ.format( "deploy.error.config.create",
473                                                location );
474             getLogger().error( message, e );
475             throw new LoomException( message, e );
476         }
477     }
478
479     /**
480      * Pass the configuration to the configurationManager and give it a chance to process the configuration in one form
481      * or another.
482      *
483      * @param configuration the block configurations.
484      *
485      * @throws LoomException if an error occurs
486      */

487     private Configuration processConfiguration( final String JavaDoc application,
488                                                 final Configuration configuration )
489         throws LoomException
490     {
491         final DefaultConfiguration newConfiguration =
492             new DefaultConfiguration( "config",
493                                       configuration.getPath(),
494                                       configuration.getLocation() );
495         final Configuration[] configurations = configuration.getChildren();
496         for( int i = 0; i < configurations.length; i++ )
497         {
498             final Configuration config = configurations[i];
499             try
500             {
501                 final Configuration newConfig =
502                     m_repository.processConfiguration( application,
503                                                        config.getName(),
504                                                        config );
505                 newConfiguration.addChild( newConfig );
506             }
507             catch( final ConfigurationException ce )
508             {
509                 throw new LoomException( ce.getMessage(), ce );
510             }
511         }
512         return newConfiguration;
513     }
514
515     /**
516      * Verify that configuration present in config file is valid for this assembly.
517      *
518      * @param profile the PartitionProfile
519      * @param config the block configurations.
520      *
521      * @throws LoomException if an error occurs
522      */

523     private void verifyConfiguration( final PartitionProfile profile,
524                                       final Configuration config )
525         throws LoomException
526     {
527         final Configuration[] configurations = config.getChildren();
528         final PartitionProfile listenerPartition =
529             profile.getPartition( ContainerConstants.LISTENER_PARTITION );
530         final PartitionProfile blockPartition =
531             profile.getPartition( ContainerConstants.BLOCK_PARTITION );
532         for( int i = 0; i < configurations.length; i++ )
533         {
534             final Configuration configuration = configurations[i];
535             final String JavaDoc name = configuration.getName();
536             ComponentProfile component = listenerPartition.getComponent( name );
537             if( null == component )
538             {
539                 component = blockPartition.getComponent( name );
540             }
541             if( null == component )
542             {
543                 final String JavaDoc message =
544                     REZ.format( "deploy.error.extra.config",
545                                 name );
546                 throw new LoomException( message );
547             }
548         }
549     }
550
551     /**
552      * Verify that configuration conforms to schema for all components in this assembly.
553      *
554      * @param profile the PartitionProfile
555      * @param classLoader the classloader application is loaded in
556      *
557      * @throws LoomException if an error occurs
558      */

559     private void validateConfiguration( final PartitionProfile profile,
560                                         final ClassLoader JavaDoc classLoader )
561         throws LoomException
562     {
563         final PartitionProfile[] partitions = profile.getPartitions();
564         for( int i = 0; i < partitions.length; i++ )
565         {
566             validateConfiguration( partitions[i], classLoader );
567         }
568         final ComponentProfile[] components = profile.getComponents();
569         for( int i = 0; i < components.length; i++ )
570         {
571             final ComponentProfile component = components[i];
572             boolean isValid = false;
573             try
574             {
575                 isValid = m_validator.isValid( component, classLoader );
576             }
577             catch( final Exception JavaDoc e )
578             {
579                 getLogger().warn( e.getMessage(), e );
580             }
581             if( !isValid )
582             {
583                 final String JavaDoc message =
584                     "Unable to validate configuration of component " +
585                     component.getTemplate().getName() +
586                     " of type " +
587                     component.getInfo().getType().getName();
588                 throw new LoomException( message );
589             }
590         }
591     }
592 }
593
Popular Tags