KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > loom > components > embeddor > DefaultEmbeddor


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.embeddor;
88
89 import java.io.File JavaDoc;
90 import java.util.Date JavaDoc;
91 import java.util.Observer JavaDoc;
92
93 import org.codehaus.loom.interfaces.ContainerConstants;
94 import org.codehaus.loom.interfaces.Deployer;
95 import org.codehaus.loom.interfaces.Embeddor;
96 import org.codehaus.loom.interfaces.Kernel;
97 import org.codehaus.loom.interfaces.LoomException;
98 import org.codehaus.loom.interfaces.SystemManager;
99 import org.codehaus.spice.salt.i18n.ResourceManager;
100 import org.codehaus.spice.salt.i18n.Resources;
101 import org.codehaus.dna.AbstractLogEnabled;
102 import org.codehaus.dna.Active;
103 import org.codehaus.dna.Composable;
104 import org.codehaus.dna.Configurable;
105 import org.codehaus.dna.Configuration;
106 import org.codehaus.dna.ConfigurationException;
107 import org.codehaus.dna.Logger;
108 import org.codehaus.dna.MissingResourceException;
109 import org.codehaus.dna.ResourceLocator;
110 import org.codehaus.dna.impl.ContainerUtil;
111 import org.codehaus.dna.impl.DefaultResourceLocator;
112
113 /**
114  * This is the object that is interacted with to create, manage and dispose of
115  * the kernel and related resources.
116  *
117  * @author Leo Simons
118  * @author Peter Donald
119  * @author Joerg Bauer
120  * @dna.component
121  * @mx.component
122  */

123 public class DefaultEmbeddor
124     extends AbstractLogEnabled
125     implements Embeddor, Composable, Configurable, Active
126 {
127     private static final Resources REZ =
128         ResourceManager.getPackageResources( DefaultEmbeddor.class );
129
130     private final EmbeddorObservable m_observable = new EmbeddorObservable();
131
132     private File JavaDoc m_loomHome;
133
134     private EmbeddorEntry[] m_entries;
135
136     /**
137      * If true, flag indicates that the Embeddor should
138      * shut down when there are no more applications in the
139      * kernel. Otherwise the Embeddor will be persistent.
140      */

141     private boolean m_temporary;
142
143     /**
144      * Flag is set to true when the embeddor should shut
145      * itself down. It is set to true as a result of a call
146      * to the shutdown() method.
147      *
148      * @see Embeddor#shutdown()
149      */

150     private boolean m_shutdown;
151
152     /** Time at which the embeddor was started. */
153     private long m_startTime;
154
155     /** The default directory in which applications are deployed from. */
156     private ClassLoader JavaDoc m_commonClassLoader;
157     private ClassLoader JavaDoc m_containerClassLoader;
158
159     /**
160      * @dna.dependency type="Observer" optional="true"
161      * @dna.dependency type="ClassLoader" qualifier="common"
162      * @dna.dependency type="ClassLoader" qualifier="container"
163      * @dna.dependency type="File" qualifier="home"
164      * @dna.dependency type="File" qualifier="apps"
165      * @dna.dependency type="Boolean" qualifier="persistent"
166      */

167     public void compose( final ResourceLocator locator )
168         throws MissingResourceException
169     {
170         if( locator.contains( Observer JavaDoc.class.getName() ) )
171         {
172             final Observer JavaDoc observer = (Observer JavaDoc)locator.lookup(
173                 Observer JavaDoc.class.getName() );
174             m_observable.addObserver( observer );
175         }
176         else
177         {
178             final String JavaDoc message = REZ.getString( "embeddor.notice.no-restart" );
179             getLogger().warn( message );
180         }
181         m_commonClassLoader = (ClassLoader JavaDoc)
182             locator.lookup( ClassLoader JavaDoc.class.getName() + "/common" );
183         m_containerClassLoader = (ClassLoader JavaDoc)
184             locator.lookup( ClassLoader JavaDoc.class.getName() + "/container" );
185         m_loomHome = (File JavaDoc)locator.lookup( File JavaDoc.class.getName() + "/home" );
186         final Boolean JavaDoc temporary =
187             (Boolean JavaDoc)locator.lookup( Boolean JavaDoc.class.getName() + "/temporary" );
188         m_temporary = temporary.booleanValue();
189     }
190
191     public void configure( final Configuration configuration )
192         throws ConfigurationException
193     {
194         final Configuration[] children = configuration.getChildren(
195             "component" );
196         m_entries = new EmbeddorEntry[ children.length ];
197         for( int i = 0; i < children.length; i++ )
198         {
199             final String JavaDoc role = children[ i ].getAttribute( "role", null );
200             final String JavaDoc classname = children[ i ].getAttribute( "class" );
201             final String JavaDoc logger = children[ i ].getAttribute( "logger" );
202             m_entries[ i ] =
203             new EmbeddorEntry( role, classname, logger, children[ i ] );
204         }
205     }
206
207     /**
208      * Creates the core handlers - logger, deployer, Manager and Kernel. Note
209      * that these are not set up properly until you have called the {@link
210      * #execute()} method.
211      */

212     public void initialize()
213         throws Exception JavaDoc
214     {
215         m_startTime = System.currentTimeMillis();
216         try
217         {
218             createComponents();
219             setupComponents();
220             registerComponents();
221         }
222         catch( final Exception JavaDoc e )
223         {
224             // whoops!
225
final String JavaDoc message = REZ.getString(
226                 "embeddor.error.start.failed" );
227             getLogger().error( message, e );
228             throw e;
229         }
230     }
231
232     /**
233      * This is the main method of the embeddor. It sets up the core components,
234      * and then deploys the <code>Facilities</code>. These are registered with
235      * the Kernel and the Manager. The same happens for the {@link
236      * org.codehaus.loom.interfaces.Application}s. Now, the Kernel is taken
237      * through its lifecycle. When it is finished, as well as all the
238      * applications running in it, it is shut down, after which the Embeddor is
239      * as well.
240      */

241     public void execute()
242         throws Exception JavaDoc
243     {
244         // If the kernel is empty at this point, it is because the server was
245
// started without supplying any applications. If 'temporary' was
246
// set to true, display a message to give the user a clue as to why
247
// the server is shutting down immediately.
248
if( emptyKernel() && m_temporary )
249         {
250             final String JavaDoc message = REZ.getString(
251                 "embeddor.error.start.no-apps" );
252             getLogger().error( message );
253         }
254         else
255         {
256             // loop until Shutdown occurs.
257
while( true )
258             {
259                 // wait() for shutdown() to take action...
260
if( m_shutdown || ( emptyKernel() && m_temporary ) )
261                 {
262                     // The server will shut itself down when all applications are disposed.
263
if( emptyKernel() && m_temporary )
264                     {
265                         final String JavaDoc message =
266                             REZ.getString( "embeddor.shutdown.all-apps-disposed" );
267                         getLogger().info( message );
268                     }
269                     break;
270                 }
271                 gotoSleep();
272             }
273         }
274     }
275
276     private boolean emptyKernel()
277     {
278         final Kernel kernel = (Kernel)getEmbeddorComponent(
279             Kernel.class.getName() );
280         if( null != kernel )
281         {
282             final String JavaDoc[] names = kernel.getApplicationNames();
283             return ( 0 == names.length );
284         }
285         else
286         {
287             //Consider the kernel empty
288
//if it has been shutdown
289
return true;
290         }
291     }
292
293     private void gotoSleep()
294     {
295         try
296         {
297             synchronized( this )
298             {
299                 wait( 1000 );
300             }
301         }
302         catch( final InterruptedException JavaDoc e )
303         {
304             //NOOP
305
}
306     }
307
308     /**
309      * Release all the resources associated with kernel.
310      */

311     public synchronized void dispose()
312     {
313         shutdown();
314         try
315         {
316             unregisterComponents();
317             shutdownComponents();
318         }
319         catch( final Exception JavaDoc e )
320         {
321             // whoops!
322
final String JavaDoc message = REZ.getString(
323                 "embeddor.error.shutdown.failed" );
324             getLogger().error( message, e );
325         }
326         for( int i = 0; i < m_entries.length; i++ )
327         {
328             m_entries[ i ].setObject( null );
329         }
330         System.gc(); // make sure resources are released
331
}
332
333     /**
334      * @mx.operation description="Request the Embeddor shutsdown."
335      */

336     public void shutdown()
337     {
338         m_shutdown = true;
339         synchronized( this )
340         {
341             notifyAll();
342         }
343     }
344
345     /**
346      * @throws UnsupportedOperationException if restart not a supported
347      * operation
348      * @mx.operation description="Request the Embeddor restart."
349      */

350     public void restart()
351         throws UnsupportedOperationException JavaDoc
352     {
353         try
354         {
355             m_observable.change();
356             m_observable.notifyObservers( "restart" );
357         }
358         catch( final Exception JavaDoc e )
359         {
360             throw new UnsupportedOperationException JavaDoc();
361         }
362     }
363
364     /**
365      * Get name by which the server is known. Usually this defaults to {@link
366      * ContainerConstants#SOFTWARE} but the admin may assign another name. This
367      * is useful when you are managing a cluster of servers.
368      *
369      * @return the name of server
370      * @mx.attribute description="The name by which the server is known."
371      */

372     public String JavaDoc getName()
373     {
374         return ContainerConstants.SOFTWARE;
375     }
376
377     /**
378      * Get location of container installation
379      *
380      * @return the home directory of container
381      * @mx.attribute description="The location of container installation."
382      */

383     public String JavaDoc getHomeDirectory()
384     {
385         return m_loomHome.getPath();
386     }
387
388     /**
389      * Get the date at which this server started.
390      *
391      * @return the date at which this server started
392      * @mx.attribute description="the date at which this server started."
393      */

394     public Date JavaDoc getStartTime()
395     {
396         return new Date JavaDoc( m_startTime );
397     }
398
399     /**
400      * Retrieve the number of millisecond the server has been up.
401      *
402      * @return the the number of millisecond the server has been up
403      * @mx.attribute description="the number of millisecond the server has been
404      * up."
405      */

406     public long getUpTimeInMillis()
407     {
408         return System.currentTimeMillis() - m_startTime;
409     }
410
411     /**
412      * Retrieve a string identifying version of server. Usually looks like
413      * "x.y.z".
414      *
415      * @return version string of server.
416      * @mx.attribute description="Retrieve a string identifying version of
417      * server."
418      */

419     public String JavaDoc getVersion()
420     {
421         return ContainerConstants.VERSION;
422     }
423
424     /**
425      * Get a string defining the build. Possibly the date on which it was built,
426      * where it was built, with what features it was built and so forth.
427      *
428      * @return the string describing build
429      * @mx.attribute description="a string defining the build."
430      */

431     public String JavaDoc getBuild()
432     {
433         return "(" + ContainerConstants.DATE + ")";
434     }
435
436     //////////////////////
437
/// HELPER METHODS ///
438
//////////////////////
439
/**
440      * Create the logger, deployer and kernel components. Note that these
441      * components are not ready to be used until setupComponents() is called.
442      */

443     private synchronized void createComponents()
444         throws Exception JavaDoc
445     {
446         try
447         {
448             for( int i = 0; i < m_entries.length; i++ )
449             {
450                 final String JavaDoc className = m_entries[ i ].getClassName();
451                 final Class JavaDoc clazz = Class.forName( className );
452                 final Object JavaDoc object = createObject( className, clazz );
453                 m_entries[ i ].setObject( object );
454             }
455         }
456         catch( final Exception JavaDoc e )
457         {
458             final String JavaDoc message =
459                 REZ.getString( "embeddor.error.createComponents.failed" );
460             getLogger().error( message, e );
461             throw new LoomException( message, e );
462         }
463     }
464
465     protected final synchronized void deployFile( final String JavaDoc name,
466                                                   final File JavaDoc file )
467         throws Exception JavaDoc
468     {
469         final Deployer deployer = (Deployer)getEmbeddorComponent(
470             Deployer.class.getName() );
471         deployer.deploy( name, file.toURL() );
472     }
473
474     private void setupComponents()
475         throws Exception JavaDoc
476     {
477         for( int i = 0; i < m_entries.length; i++ )
478         {
479             final EmbeddorEntry entry = m_entries[ i ];
480             setupComponent( entry.getObject(),
481                             entry.getLoggerName(),
482                             entry.getConfiguration() );
483         }
484     }
485
486     /**
487      * Setup a component and run it through al of it's setup lifecycle stages.
488      *
489      * @param object the component
490      * @throws Exception if an error occurs
491      */

492     private void setupComponent( final Object JavaDoc object,
493                                  final String JavaDoc loggerName,
494                                  final Configuration config )
495         throws Exception JavaDoc
496     {
497         final Logger childLogger = getLogger().getChildLogger( loggerName );
498         ContainerUtil.enableLogging( object, childLogger );
499         ContainerUtil.compose( object, getResourceLocator() );
500         ContainerUtil.configure( object, config );
501         ContainerUtil.initialize( object );
502     }
503
504     private void shutdownComponents()
505         throws Exception JavaDoc
506     {
507         //for( int i = m_entries.length - 1; i >= 0; i-- )
508
for( int i = 0; i < m_entries.length; i++ )
509         {
510             final Object JavaDoc object = m_entries[ i ].getObject();
511             if( null == object )
512             {
513                 continue;
514             }
515             ContainerUtil.dispose( object );
516         }
517     }
518
519     /**
520      * Create a component that implements an interface.
521      *
522      * @param classname the name of the objects class
523      * @param service the name of interface/type
524      * @return the created object
525      * @throws Exception if an error occurs
526      */

527     private Object JavaDoc createObject( final String JavaDoc classname,
528                                  final Class JavaDoc service )
529         throws Exception JavaDoc
530     {
531         try
532         {
533             final Object JavaDoc object = Class.forName( classname ).newInstance();
534             if( !service.isInstance( object ) )
535             {
536                 final String JavaDoc message =
537                     REZ.format( "bad-type.error",
538                                 classname,
539                                 service.getName() );
540                 throw new Exception JavaDoc( message );
541             }
542             return object;
543         }
544         catch( final IllegalAccessException JavaDoc iae )
545         {
546             final String JavaDoc message = REZ.format( "bad-ctor.error",
547                                                service.getName(),
548                                                classname );
549             throw new LoomException( message, iae );
550         }
551         catch( final InstantiationException JavaDoc ie )
552         {
553             final String JavaDoc message =
554                 REZ.format( "no-instantiate.error",
555                             service.getName(),
556                             classname );
557             throw new LoomException( message, ie );
558         }
559         catch( final ClassNotFoundException JavaDoc cnfe )
560         {
561             final String JavaDoc message = REZ.format( "no-class.error",
562                                                service.getName(),
563                                                classname );
564             throw new LoomException( message, cnfe );
565         }
566     }
567
568     /**
569      * Register embeddor and it's components to <code>SystemManager</code>.
570      */

571     private void registerComponents()
572         throws Exception JavaDoc
573     {
574         final SystemManager systemManager =
575             (SystemManager)getResourceLocator().lookup(
576                 SystemManager.class.getName() );
577
578         final SystemManager mxExporter =
579             systemManager.getSubContext( null, "component" );
580
581         mxExporter.register( "Embeddor", this );
582         for( int i = 0; i < m_entries.length; i++ )
583         {
584             final EmbeddorEntry entry = m_entries[ i ];
585             mxExporter.register( entry.getLoggerName(),
586                                  entry.getObject() );
587         }
588     }
589
590     /**
591      * Unregister embeddor and it's components from {@link SystemManager}.
592      */

593     private void unregisterComponents()
594         throws Exception JavaDoc
595     {
596         final SystemManager systemManager =
597             (SystemManager)getResourceLocator().lookup(
598                 SystemManager.class.getName() );
599
600         final SystemManager mxExporter =
601             systemManager.getSubContext( null, "component" );
602
603         mxExporter.unregister( "Embeddor" );
604
605         for( int i = 0; i < m_entries.length; i++ )
606         {
607             final EmbeddorEntry entry = m_entries[ i ];
608             mxExporter.unregister( entry.getLoggerName() );
609         }
610     }
611
612     private ResourceLocator getResourceLocator()
613         throws Exception JavaDoc
614     {
615         final DefaultResourceLocator locator = new DefaultResourceLocator();
616         locator.put( Embeddor.class.getName(), this );
617         for( int i = 0; i < m_entries.length; i++ )
618         {
619             final String JavaDoc role = m_entries[ i ].getRole();
620             if( null == role )
621             {
622                 continue;
623             }
624             final Object JavaDoc component = getEmbeddorComponent( role );
625             if( null != component )
626             {
627                 locator.put( role, component );
628             }
629         }
630
631         locator.put( File JavaDoc.class.getName() + "/home", m_loomHome );
632         locator.put( ClassLoader JavaDoc.class.getName() + "/common",
633                      m_commonClassLoader );
634         locator.put( ClassLoader JavaDoc.class.getName() + "/container",
635                      m_containerClassLoader );
636
637         return locator;
638     }
639
640     private Object JavaDoc getEmbeddorComponent( final String JavaDoc role )
641     {
642         for( int i = 0; i < m_entries.length; i++ )
643         {
644             final EmbeddorEntry entry = m_entries[ i ];
645             final String JavaDoc candidate = entry.getRole();
646             if( null == candidate )
647             {
648                 continue;
649             }
650             if( candidate.equals( role ) )
651             {
652                 return m_entries[ i ].getObject();
653             }
654         }
655         // Should never happen
656
// TODO: create error / warning
657
return null;
658     }
659 }
660
661
662
Popular Tags