KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > phoenix > components > deployer > DefaultDeployer


1 /*
2  * Copyright (C) The Apache Software Foundation. All rights reserved.
3  *
4  * This software is published under the terms of the Apache Software License
5  * version 1.1, a copy of which has been included with this distribution in
6  * the LICENSE.txt file.
7  */

8 package org.apache.avalon.phoenix.components.deployer;
9
10 import java.io.File JavaDoc;
11 import java.io.IOException JavaDoc;
12 import java.net.MalformedURLException JavaDoc;
13 import java.net.URL JavaDoc;
14 import java.util.Hashtable JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.Set JavaDoc;
17 import java.util.Arrays JavaDoc;
18 import org.apache.avalon.excalibur.i18n.ResourceManager;
19 import org.apache.avalon.excalibur.i18n.Resources;
20 import org.apache.avalon.excalibur.io.FileUtil;
21 import org.apache.avalon.framework.activity.Disposable;
22 import org.apache.avalon.framework.activity.Initializable;
23 import org.apache.avalon.framework.configuration.Configuration;
24 import org.apache.avalon.framework.configuration.ConfigurationException;
25 import org.apache.avalon.framework.logger.AbstractLogEnabled;
26 import org.apache.avalon.framework.logger.Logger;
27 import org.apache.avalon.framework.parameters.ParameterException;
28 import org.apache.avalon.framework.parameters.Parameterizable;
29 import org.apache.avalon.framework.parameters.Parameters;
30 import org.apache.avalon.framework.service.ServiceException;
31 import org.apache.avalon.framework.service.ServiceManager;
32 import org.apache.avalon.framework.service.Serviceable;
33 import org.apache.avalon.phoenix.components.deployer.installer.Installation;
34 import org.apache.avalon.phoenix.components.deployer.installer.InstallationException;
35 import org.apache.avalon.phoenix.components.deployer.installer.Installer;
36 import org.apache.avalon.phoenix.interfaces.Application;
37 import org.apache.avalon.phoenix.interfaces.ClassLoaderManager;
38 import org.apache.avalon.phoenix.interfaces.ConfigurationRepository;
39 import org.apache.avalon.phoenix.interfaces.ConfigurationValidator;
40 import org.apache.avalon.phoenix.interfaces.Deployer;
41 import org.apache.avalon.phoenix.interfaces.DeployerMBean;
42 import org.apache.avalon.phoenix.interfaces.DeploymentException;
43 import org.apache.avalon.phoenix.interfaces.Kernel;
44 import org.apache.avalon.phoenix.interfaces.LogManager;
45 import org.apache.avalon.phoenix.metadata.BlockListenerMetaData;
46 import org.apache.avalon.phoenix.metadata.BlockMetaData;
47 import org.apache.avalon.phoenix.metadata.SarMetaData;
48 import org.apache.avalon.phoenix.metainfo.BlockDescriptor;
49 import org.apache.avalon.phoenix.tools.assembler.Assembler;
50 import org.apache.avalon.phoenix.tools.assembler.AssemblyException;
51 import org.apache.avalon.phoenix.tools.configuration.ConfigurationBuilder;
52 import org.apache.avalon.phoenix.tools.verifier.SarVerifier;
53 import org.apache.avalon.phoenix.tools.verifier.VerifyException;
54
55 /**
56  * Deploy .sar files into a kernel using this class.
57  *
58  * @author <a HREF="mailto:peter at apache.org">Peter Donald</a>
59  */

60 public class DefaultDeployer
61     extends AbstractLogEnabled
62     implements Deployer, Parameterizable, Serviceable, Initializable, Disposable, DeployerMBean
63 {
64     private static final Resources REZ =
65         ResourceManager.getPackageResources( DefaultDeployer.class );
66
67     private final Assembler m_assembler = new Assembler();
68     private final SarVerifier m_verifier = new SarVerifier();
69     private final Installer m_installer = new Installer();
70     private final Map JavaDoc m_installations = new Hashtable JavaDoc();
71     private LogManager m_logManager;
72     private Kernel m_kernel;
73     private ConfigurationRepository m_repository;
74     private ClassLoaderManager m_classLoaderManager;
75     private ConfigurationValidator m_validator;
76
77     /**
78      * The directory which is used as the base for
79      * extracting all temporary files from archives. It is
80      * expected that the temporary files will be deleted when
81      * the .sar file is undeployed.
82      */

83     private File JavaDoc m_baseWorkDirectory;
84
85     /**
86      * The base directory in which applications are deployed.
87      */

88     private File JavaDoc m_baseDirectory;
89
90     /**
91      * Retrieve parameter that specifies work directory.
92      *
93      * @param parameters the parameters to read
94      * @throws ParameterException if invlaid work directory
95      */

96     public void parameterize( final Parameters parameters )
97         throws ParameterException
98     {
99         final String JavaDoc phoenixHome = parameters.getParameter( "phoenix.home" );
100         final String JavaDoc defaultWorkDir = phoenixHome + File.separator + "work";
101         final String JavaDoc defaultAppsDir = phoenixHome + File.separator + "apps";
102         final String JavaDoc rawWorkDir =
103             parameters.getParameter( "phoenix.work.dir", defaultWorkDir );
104         final String JavaDoc rawAppsDir =
105             parameters.getParameter( "phoenix.apps.dir", defaultAppsDir );
106
107         final File JavaDoc workDir = new File JavaDoc( rawWorkDir );
108         try
109         {
110             m_baseWorkDirectory = workDir.getCanonicalFile();
111         }
112         catch( final IOException JavaDoc ioe )
113         {
114             m_baseWorkDirectory = workDir.getAbsoluteFile();
115         }
116
117         final File JavaDoc appsDir = new File JavaDoc( rawAppsDir );
118         try
119         {
120             m_baseDirectory = appsDir.getCanonicalFile();
121         }
122         catch( final IOException JavaDoc ioe )
123         {
124             m_baseDirectory = appsDir.getAbsoluteFile();
125         }
126     }
127
128     /**
129      * Retrieve relevant services needed to deploy.
130      *
131      * @param serviceManager the ComponentManager
132      * @throws ServiceException if an error occurs
133      */

134     public void service( final ServiceManager serviceManager )
135         throws ServiceException
136     {
137         m_kernel = (Kernel)serviceManager.lookup( Kernel.ROLE );
138         m_repository = (ConfigurationRepository)serviceManager.
139             lookup( ConfigurationRepository.ROLE );
140         m_classLoaderManager = (ClassLoaderManager)serviceManager.
141             lookup( ClassLoaderManager.ROLE );
142         m_logManager = (LogManager)serviceManager.lookup( LogManager.ROLE );
143         m_validator = (ConfigurationValidator)serviceManager.lookup( ConfigurationValidator.ROLE );
144     }
145
146     public void initialize()
147         throws Exception JavaDoc
148     {
149         initWorkDirectory();
150         try
151         {
152             FileUtil.cleanDirectory( m_baseWorkDirectory );
153         }
154         catch( final IOException JavaDoc ioe )
155         {
156             final String JavaDoc message =
157                 REZ.getString( "nodelete-workdir.error",
158                                m_baseWorkDirectory,
159                                ioe.getMessage() );
160             getLogger().warn( message, ioe );
161         }
162
163         setupLogger( m_installer );
164         setupLogger( m_assembler );
165         setupLogger( m_verifier );
166         m_installer.setBaseDirectory( m_baseDirectory );
167         m_installer.setBaseWorkDirectory( m_baseWorkDirectory );
168     }
169
170     /**
171      * Dispose the dpeloyer which effectively means undeploying
172      * all the currently deployed apps.
173      */

174     public void dispose()
175     {
176         final Set JavaDoc set = m_installations.keySet();
177         final String JavaDoc[] applications =
178             (String JavaDoc[])set.toArray( new String JavaDoc[ set.size() ] );
179         for( int i = 0; i < applications.length; i++ )
180         {
181             final String JavaDoc name = applications[ i ];
182             try
183             {
184                 undeploy( name );
185             }
186             catch( final DeploymentException de )
187             {
188                 final String JavaDoc message =
189                     REZ.getString( "deploy.undeploy-indispose.error",
190                                    name,
191                                    de.getMessage() );
192                 getLogger().error( message, de );
193             }
194         }
195     }
196
197     /**
198      * Redeploy an application.
199      *
200      * @param name the name of deployment
201      * @throws DeploymentException if an error occurs
202      */

203     public void redeploy( final String JavaDoc name )
204         throws DeploymentException
205     {
206         final Installation installation =
207             (Installation)m_installations.get( name );
208         if( null == installation )
209         {
210             final String JavaDoc message =
211                 REZ.getString( "deploy.no-deployment.error", name );
212             throw new DeploymentException( message );
213         }
214         try
215         {
216             final URL JavaDoc location = installation.getSource().toURL();
217             undeploy( name );
218             deploy( name, location );
219         }
220         catch( final Exception JavaDoc e )
221         {
222             throw new DeploymentException( e.getMessage(), e );
223         }
224     }
225
226     /**
227      * Undeploy an application.
228      *
229      * @param name the name of deployment
230      * @throws DeploymentException if an error occurs
231      */

232     public void undeploy( final String JavaDoc name )
233         throws DeploymentException
234     {
235         final Installation installation =
236             (Installation)m_installations.remove( name );
237         if( null == installation )
238         {
239             final String JavaDoc message =
240                 REZ.getString( "deploy.no-deployment.error", name );
241             throw new DeploymentException( message );
242         }
243         try
244         {
245             final Application application = m_kernel.getApplication( name );
246             final String JavaDoc[] blocks = application.getBlockNames();
247
248             m_kernel.removeApplication( name );
249
250             for( int i = 0; i < blocks.length; i++ )
251             {
252                 //remove configuration and schema from repository and validator
253
m_repository.removeConfiguration( name, blocks[ i ] );
254                 m_validator.removeSchema( name, blocks[ i ] );
255             }
256
257             m_installer.uninstall( installation );
258         }
259         catch( final Exception JavaDoc e )
260         {
261             throw new DeploymentException( e.getMessage(), e );
262         }
263     }
264
265     /**
266      * Deploy an application from an installation.
267      *
268      * @param name the name of application
269      * @param sarURL the location to deploy from represented as String
270      * @throws DeploymentException if an error occurs
271      */

272     public void deploy( final String JavaDoc name, final String JavaDoc sarURL )
273         throws DeploymentException
274     {
275         try
276         {
277             try
278             {
279                 deploy( name, new URL JavaDoc( sarURL ) );
280             }
281             catch( DeploymentException e )
282             {
283                 e.printStackTrace();
284             }
285         }
286         catch( MalformedURLException JavaDoc mue )
287         {
288             mue.printStackTrace();
289             throw new DeploymentException( mue.getMessage(), mue );
290         }
291     }
292
293     /**
294      * Deploy an application from an installation.
295      *
296      * @param name the name of application
297      * @param location the location to deploy from
298      * @throws DeploymentException if an error occurs
299      */

300     public void deploy( final String JavaDoc name, final URL JavaDoc location )
301         throws DeploymentException
302     {
303         if( m_installations.containsKey( name ) )
304         {
305             final String JavaDoc message =
306                 REZ.getString( "deploy.already-deployed.error",
307                                name );
308             throw new DeploymentException( message );
309         }
310
311         /*
312          * Clear all the reosurces out of ResourceManager cache
313          * so that reloaded applications will have their i18n bundles
314          * reloaded.
315          */

316         ResourceManager.clearResourceCache();
317
318         Installation installation = null;
319         boolean success = false;
320         try
321         {
322             //m_baseWorkDirectory
323
installation = m_installer.install( name, location );
324
325             final Configuration config = getConfigurationFor( installation.getConfig() );
326             final Configuration environment = getConfigurationFor( installation.getEnvironment() );
327             final Configuration assembly = getConfigurationFor( installation.getAssembly() );
328
329             final File JavaDoc directory = installation.getDirectory();
330
331             final ClassLoader JavaDoc classLoader =
332                 m_classLoaderManager.createClassLoader( environment,
333                                                         installation.getSource(),
334                                                         installation.getDirectory(),
335                                                         installation.getWorkDirectory(),
336                                                         installation.getClassPath() );
337             //assemble all the blocks for application
338
final SarMetaData metaData =
339                 m_assembler.assembleSar( name, assembly, directory, classLoader );
340
341             storeConfigurationSchemas( metaData, classLoader );
342
343             verify( metaData, classLoader );
344
345             //Setup configuration for all the applications blocks
346
setupConfiguration( metaData, config.getChildren() );
347
348             final Configuration logs = environment.getChild( "logs" );
349             final Logger logger =
350                 m_logManager.createHierarchy( metaData, logs, classLoader );
351
352             //Finally add application to kernel
353
m_kernel.addApplication( metaData,
354                                      installation.getWorkDirectory(),
355                                      classLoader,
356                                      logger,
357                                      environment );
358
359             m_installations.put( metaData.getName(), installation );
360
361             final String JavaDoc message =
362                 REZ.getString( "deploy.notice.sar.add",
363                                metaData.getName(),
364                                Arrays.asList( installation.getClassPath() ) );
365             getLogger().debug( message );
366             success = true;
367         }
368         catch( final DeploymentException de )
369         {
370             throw de;
371         }
372         catch( final AssemblyException ae )
373         {
374             throw new DeploymentException( ae.getMessage(), ae );
375         }
376         catch( final Exception JavaDoc e )
377         {
378             //From classloaderManager/kernel
379
throw new DeploymentException( e.getMessage(), e );
380         }
381         finally
382         {
383             if( !success && null != installation )
384             {
385                 try
386                 {
387                     m_installer.uninstall( installation );
388                 }
389                 catch( final InstallationException ie )
390                 {
391                     getLogger().error( ie.getMessage(), ie );
392                 }
393             }
394         }
395     }
396
397     /**
398      * Verify that the application conforms to our requirements.
399      *
400      * @param metaData the application metaData
401      * @param classLoader the ClassLoader associated with app
402      * @throws VerifyException on error
403      */

404     protected void verify( final SarMetaData metaData,
405                            final ClassLoader JavaDoc classLoader )
406         throws VerifyException
407     {
408         m_verifier.verifySar( metaData, classLoader );
409     }
410
411     /**
412      * Store the configuration schemas for this application
413      *
414      * @param metaData the application metaData
415      * @throws DeploymentException upon invalid schema
416      */

417     private void storeConfigurationSchemas( final SarMetaData metaData, ClassLoader JavaDoc classLoader )
418         throws DeploymentException
419     {
420         final BlockMetaData[] blocks = metaData.getBlocks();
421         int i = 0;
422
423         try
424         {
425             for( i = 0; i < blocks.length; i++ )
426             {
427                 final String JavaDoc name = blocks[ i ].getName();
428                 final BlockDescriptor descriptor = blocks[ i ].getBlockInfo().getBlockDescriptor();
429                 final String JavaDoc type = descriptor.getSchemaType();
430
431                 if( null != type )
432                 {
433                     m_validator.addSchema( metaData.getName(),
434                                            name,
435                                            type,
436                                            getConfigurationSchemaURL( name,
437                                                                       descriptor.getImplementationKey(),
438                                                                       classLoader )
439                     );
440                 }
441             }
442         }
443         catch( ConfigurationException e )
444         {
445             //uh-oh, bad schema bad bad!
446
final String JavaDoc message = REZ.getString( "deploy.error.config.schema.invalid",
447                                                   blocks[ i ].getName() );
448
449             //back out any schemas that we have already stored for this app
450
while( --i >= 0 )
451             {
452                 m_validator.removeSchema( metaData.getName(),
453                                           blocks[ i ].getName() );
454             }
455
456             throw new DeploymentException( message, e );
457         }
458     }
459
460     private String JavaDoc getConfigurationSchemaURL( final String JavaDoc name,
461                                               final String JavaDoc classname,
462                                               final ClassLoader JavaDoc classLoader )
463         throws DeploymentException
464     {
465         final String JavaDoc resourceName = classname.replace( '.', '/' ) + "-schema.xml";
466
467         final URL JavaDoc resource = classLoader.getResource( resourceName );
468         if( null == resource )
469         {
470
471             throw new DeploymentException( REZ.getString( "deploy.error.config.schema.missing",
472                                                           name,
473                                                           resourceName ) );
474         }
475         else
476         {
477             return resource.toString();
478         }
479     }
480
481     /**
482      * Helper method to load configuration data.
483      *
484      * @param location the location of configuration data as a url
485      * @return the Configuration
486      * @throws DeploymentException if an error occurs
487      */

488     private Configuration getConfigurationFor( final String JavaDoc location )
489         throws DeploymentException
490     {
491         try
492         {
493             return ConfigurationBuilder.build( location );
494         }
495         catch( final Exception JavaDoc e )
496         {
497             final String JavaDoc message = REZ.getString( "deploy.error.config.create", location );
498             getLogger().error( message, e );
499             throw new DeploymentException( message, e );
500         }
501     }
502
503     /**
504      * Setup Configuration for all the Blocks/BlockListeners in Sar.
505      *
506      * @param metaData the SarMetaData.
507      * @param configurations the block configurations.
508      * @throws DeploymentException if an error occurs
509      */

510     private void setupConfiguration( final SarMetaData metaData,
511                                      final Configuration[] configurations )
512         throws DeploymentException
513     {
514         final String JavaDoc application = metaData.getName();
515
516         for( int i = 0; i < configurations.length; i++ )
517         {
518             final Configuration configuration = configurations[ i ];
519             final String JavaDoc name = configuration.getName();
520             final boolean listener = hasBlockListener( name, metaData.getListeners() );
521
522             if( !hasBlock( name, metaData.getBlocks() ) && !listener )
523             {
524                 final String JavaDoc message =
525                     REZ.getString( "deploy.error.extra.config",
526                                    name );
527                 throw new DeploymentException( message );
528             }
529
530             try
531             {
532                 //No way to validate listener configuration--yet
533
if( listener || m_validator.isFeasiblyValid( application, name, configuration ) )
534                 {
535                     m_repository.storeConfiguration( application,
536                                                      name,
537                                                      configuration );
538                 }
539                 else
540                 {
541                     final String JavaDoc message = REZ.getString( "deploy.error.config.invalid", name );
542
543                     throw new DeploymentException( message );
544                 }
545             }
546             catch( final ConfigurationException ce )
547             {
548                 throw new DeploymentException( ce.getMessage(), ce );
549             }
550         }
551     }
552
553     /**
554      * Return true if specified array contains entry with specified name.
555      *
556      * @param name the blocks name
557      * @param blocks the set of BlockMetaData objects to search
558      * @return true if block present, false otherwise
559      */

560     private boolean hasBlock( final String JavaDoc name, final BlockMetaData[] blocks )
561     {
562         for( int i = 0; i < blocks.length; i++ )
563         {
564             final String JavaDoc other = blocks[ i ].getName();
565             if( other.equals( name ) )
566             {
567                 return true;
568             }
569         }
570
571         return false;
572     }
573
574     /**
575      * Return true if specified array contains entry with specified name.
576      *
577      * @param name the blocks name
578      * @param listeners the set of BlockListenerMetaData objects to search
579      * @return true if block present, false otherwise
580      */

581     private boolean hasBlockListener( final String JavaDoc name,
582                                       final BlockListenerMetaData[] listeners )
583     {
584         for( int i = 0; i < listeners.length; i++ )
585         {
586             if( listeners[ i ].getName().equals( name ) )
587             {
588                 return true;
589             }
590         }
591
592         return false;
593     }
594
595     /**
596      * Make sure that the work directory is created and not a file.
597      *
598      * @throws Exception if work directory can not be created or is a file
599      */

600     private void initWorkDirectory()
601         throws Exception JavaDoc
602     {
603         if( !m_baseWorkDirectory.exists() )
604         {
605             final String JavaDoc message =
606                 REZ.getString( "deploy.create-dir.notice",
607                                m_baseWorkDirectory );
608             getLogger().info( message );
609
610             if( !m_baseWorkDirectory.mkdirs() )
611             {
612                 final String JavaDoc error =
613                     REZ.getString( "deploy.workdir-nocreate.error",
614                                    m_baseWorkDirectory );
615                 throw new Exception JavaDoc( error );
616             }
617         }
618
619         if( !m_baseWorkDirectory.isDirectory() )
620         {
621             final String JavaDoc message =
622                 REZ.getString( "deploy.workdir-notadir.error",
623                                m_baseWorkDirectory );
624             throw new Exception JavaDoc( message );
625         }
626     }
627 }
628
Popular Tags