KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > loom > components > kernel > DefaultKernel


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.kernel;
88
89 import java.io.File JavaDoc;
90 import java.util.HashMap JavaDoc;
91 import org.apache.avalon.framework.container.ContainerUtil;
92 import org.apache.excalibur.instrument.InstrumentManager;
93 import org.codehaus.loom.components.application.DefaultApplication;
94 import org.codehaus.loom.components.util.profile.PartitionProfile;
95 import org.codehaus.loom.interfaces.Application;
96 import org.codehaus.loom.interfaces.ApplicationContext;
97 import org.codehaus.loom.interfaces.ConfigurationInterceptor;
98 import org.codehaus.loom.interfaces.ConfigurationValidator;
99 import org.codehaus.loom.interfaces.Kernel;
100 import org.codehaus.loom.interfaces.LoomException;
101 import org.codehaus.loom.interfaces.SystemManager;
102 import org.codehaus.spice.loggerstore.LoggerStore;
103 import org.codehaus.spice.salt.i18n.ResourceManager;
104 import org.codehaus.spice.salt.i18n.Resources;
105 import org.codehaus.dna.AbstractLogEnabled;
106 import org.codehaus.dna.Active;
107 import org.codehaus.dna.Composable;
108 import org.codehaus.dna.Configurable;
109 import org.codehaus.dna.Configuration;
110 import org.codehaus.dna.ConfigurationException;
111 import org.codehaus.dna.Logger;
112 import org.codehaus.dna.MissingResourceException;
113 import org.codehaus.dna.ResourceLocator;
114 import org.codehaus.dna.impl.DefaultResourceLocator;
115
116 /**
117  * The ServerKernel is the core of the container system. The kernel is
118  * responsible for orchestrating low level services such as loading, configuring
119  * and destroying blocks. It also gives access to basic facilities such as
120  * scheduling sub-systems, protected execution contexts, naming and directory
121  * services etc.
122  *
123  * Note that no facilities are available until after the Kernel has been
124  * configured and initialized.
125  *
126  * @author Peter Donald
127  * @author Leo Simons
128  * @dna.component
129  * @mx.component
130  */

131 public class DefaultKernel
132     extends AbstractLogEnabled
133     implements Kernel, Active, Composable, Configurable
134 {
135     private static final Resources REZ =
136         ResourceManager.getPackageResources( DefaultKernel.class );
137
138     ///SystemManager provided by Embeddor
139
private SystemManager m_systemManager;
140
141     private SystemManager m_applicationManager;
142
143     ///Configuration Repository
144
private ConfigurationInterceptor m_repository;
145
146     //Configuration Validator
147
private ConfigurationValidator m_validator;
148
149     //Instrument Manager
150
private InstrumentManager m_instrumentManager;
151
152     private final HashMap JavaDoc m_entries = new HashMap JavaDoc();
153
154     //Allow applications that fail to startup to remain in the kernel in a stopped state?
155
private boolean m_addInvalidApplications;
156
157     //Counter to provide simple locking. when the count is 0, the kernel is unlocked
158
private int m_lockCount;
159
160     //List of applications to return when the kernel is locked
161
private String JavaDoc[] m_lockedApplications;
162
163     /**
164      * @dna.dependency type="InstrumentManager"
165      * @dna.dependency type="SystemManager"
166      * @dna.dependency type="ConfigurationInterceptor"
167      * @dna.dependency type="ConfigurationValidator"
168      */

169     public void compose( final ResourceLocator locator )
170         throws MissingResourceException
171     {
172         m_systemManager = (SystemManager)locator.
173             lookup( SystemManager.class.getName() );
174         m_repository = (ConfigurationInterceptor)locator.
175             lookup( ConfigurationInterceptor.class.getName() );
176         m_validator = (ConfigurationValidator)locator.
177             lookup( ConfigurationValidator.class.getName() );
178         m_instrumentManager = (InstrumentManager)locator.
179             lookup( InstrumentManager.class.getName() );
180     }
181
182     public void configure( final Configuration configuration )
183         throws ConfigurationException
184     {
185         m_addInvalidApplications =
186         configuration.getChild( "add-invalid-applications" ).getValueAsBoolean(
187             false );
188     }
189
190     public void initialize()
191         throws Exception JavaDoc
192     {
193         m_applicationManager =
194         m_systemManager.getSubContext( null, "application" );
195     }
196
197     public void dispose()
198     {
199         final String JavaDoc[] names = getApplicationNames();
200         for( int i = 0; i < names.length; i++ )
201         {
202             try
203             {
204                 final SarEntry entry = (SarEntry)m_entries.get( names[ i ] );
205                 shutdown( entry );
206             }
207             catch( final Exception JavaDoc e )
208             {
209                 final String JavaDoc message = REZ.format(
210                     "kernel.error.entry.dispose", names[ i ] );
211                 getLogger().warn( message, e );
212             }
213         }
214     }
215
216     /**
217      * Lock the kernel, temporarily preserving the list of applications running
218      * in the container
219      */

220     public void lock()
221     {
222         synchronized( this )
223         {
224             m_lockedApplications = getApplicationNames();
225             m_lockCount++;
226
227             if( getLogger().isDebugEnabled() )
228             {
229                 getLogger().debug( "Kernel locked [count:" + m_lockCount + "]" );
230             }
231         }
232     }
233
234     /**
235      * Unlock the kernel, restoring the list of applications to be the current
236      * active list
237      */

238     public void unlock()
239     {
240         synchronized( this )
241         {
242             m_lockCount--;
243
244             if( m_lockCount < 0 )
245             {
246                 throw new IllegalStateException JavaDoc(
247                     REZ.getString( "kernel.error.negativelock" ) );
248             }
249
250             if( getLogger().isDebugEnabled() )
251             {
252                 getLogger().debug(
253                     "Kernel unlocked [count:" + m_lockCount + "]" );
254             }
255         }
256     }
257
258     /**
259      * @mx.attribute description="the list of applications running in the
260      * container"
261      */

262     public String JavaDoc[] getApplicationNames()
263     {
264         if( isLocked() )
265         {
266             return m_lockedApplications;
267         }
268         else
269         {
270             return (String JavaDoc[])m_entries.keySet().toArray( new String JavaDoc[ 0 ] );
271         }
272     }
273
274     private boolean isLocked()
275     {
276         return m_lockCount > 0;
277     }
278
279     public Application getApplication( final String JavaDoc name )
280     {
281         final SarEntry entry = (SarEntry)m_entries.get( name );
282         if( null == entry )
283         {
284             return null;
285         }
286         else
287         {
288             return entry.getApplication();
289         }
290     }
291
292     /**
293      * Create and initialize the application instance if it is not already
294      * initialized.
295      *
296      * @param entry the entry for application
297      * @throws Exception if an error occurs
298      */

299     private void startup( final SarEntry entry )
300         throws Exception JavaDoc
301     {
302         //lock for application startup and shutdown
303
synchronized( entry )
304         {
305             final String JavaDoc name = entry.getProfile().getMetaData().getName();
306
307             Application application = entry.getApplication();
308             if( null == application )
309             {
310                 try
311                 {
312                     final Application newApp = new DefaultApplication();
313                     final Logger childLogger =
314                         getLogger().getChildLogger( name );
315                     org.codehaus.dna.impl.ContainerUtil.enableLogging(
316                         newApp, childLogger );
317
318                     final ApplicationContext context =
319                         createApplicationContext( entry );
320                     newApp.setApplicationContext( context );
321
322                     org.codehaus.dna.impl.ContainerUtil.initialize( newApp );
323
324                     application = newApp;
325                 }
326                 catch( final Throwable JavaDoc t )
327                 {
328                     //Initialization failed so clean entry
329
//so invalid instance is not used
330
entry.setApplication( null );
331
332                     final String JavaDoc message =
333                         REZ.format( "kernel.error.entry.initialize",
334                                     entry.getProfile().getMetaData().getName() );
335                     throw new LoomException( message, t );
336                 }
337
338                 try
339                 {
340                     ContainerUtil.start( application );
341                 }
342                 catch( final Throwable JavaDoc t )
343                 {
344                     final String JavaDoc message =
345                         REZ.format( "kernel.error.entry.start",
346                                     entry.getProfile().getMetaData().getName() );
347
348                     if( m_addInvalidApplications )
349                     {
350                         getLogger().warn( message, t );
351                     }
352                     else
353                     {
354                         //Initialization failed so clean entry
355
//so invalid instance is not used
356
entry.setApplication( null );
357
358                         throw new LoomException( message, t );
359                     }
360                 }
361
362                 entry.setApplication( application );
363
364                 // manage application
365
try
366                 {
367                     m_applicationManager.register( name, application );
368                 }
369                 catch( final Throwable JavaDoc t )
370                 {
371                     final String JavaDoc message =
372                         REZ.format( "kernel.error.entry.manage", name );
373                     throw new LoomException( message, t );
374                 }
375             }
376         }
377     }
378
379     private void shutdown( final SarEntry entry )
380         throws Exception JavaDoc
381     {
382         //lock for application startup and shutdown
383
synchronized( entry )
384         {
385             final Application application = entry.getApplication();
386             if( null != application )
387             {
388                 entry.setApplication( null );
389                 ContainerUtil.stop( application );
390                 org.codehaus.dna.impl.ContainerUtil.dispose( application );
391             }
392             else
393             {
394                 final String JavaDoc message =
395                     REZ.format( "kernel.error.entry.nostop",
396                                 entry.getProfile().getMetaData().getName() );
397                 getLogger().warn( message );
398             }
399         }
400     }
401
402     public void addApplication( final PartitionProfile profile,
403                                 final File JavaDoc homeDirectory,
404                                 final File JavaDoc workDirectory,
405                                 final ClassLoader JavaDoc classLoader,
406                                 final LoggerStore store )
407         throws Exception JavaDoc
408     {
409
410         final String JavaDoc name = profile.getMetaData().getName();
411         final SarEntry entry =
412             new SarEntry( profile, homeDirectory,
413                           workDirectory, classLoader,
414                           store );
415         m_entries.put( name, entry );
416
417         try
418         {
419             startup( entry );
420         }
421         catch( final Exception JavaDoc e )
422         {
423             final String JavaDoc message =
424                 REZ.format( "kernel.error.entry.start", name );
425             getLogger().warn( message, e );
426             throw e;
427         }
428     }
429
430     private ApplicationContext createApplicationContext( final SarEntry entry )
431         throws Exception JavaDoc
432     {
433         final String JavaDoc name = entry.getProfile().getMetaData().getName();
434
435         final DefaultApplicationContext context =
436             new DefaultApplicationContext( entry.getProfile(),
437                                            entry.getHomeDirectory(),
438                                            entry.getWorkDirectory(),
439                                            entry.getClassLoader(),
440                                            entry.getLoggerStore() );
441
442         org.codehaus.dna.impl.ContainerUtil.
443             enableLogging( context, createContextLogger( name ) );
444         org.codehaus.dna.impl.ContainerUtil.
445             compose( context, createResourceLocator() );
446         org.codehaus.dna.impl.ContainerUtil.initialize( context );
447         return context;
448     }
449
450     /**
451      * Create a logger for specified ApplicationContext.
452      *
453      * @param name the name of application name
454      * @return the Logger for context
455      */

456     private Logger createContextLogger( final String JavaDoc name )
457     {
458         final String JavaDoc loggerName = name + ".frame";
459         final Logger childLogger =
460             getLogger().getChildLogger( loggerName );
461         return childLogger;
462     }
463
464     private ResourceLocator createResourceLocator()
465     {
466         final DefaultResourceLocator serviceManager = new DefaultResourceLocator();
467         serviceManager.put( SystemManager.class.getName(), m_systemManager );
468         serviceManager.put( ConfigurationInterceptor.class.getName(),
469                             m_repository );
470         serviceManager.put( ConfigurationValidator.class.getName(),
471                             m_validator );
472         serviceManager.put( InstrumentManager.class.getName(),
473                             m_instrumentManager );
474         serviceManager.put( Kernel.class.getName(), this );
475         serviceManager.makeReadOnly();
476         return serviceManager;
477     }
478
479     /**
480      * @mx.operation description="Removes the application from the container"
481      * @mx.parameter name="name" description="the name of application to
482      * remove"
483      */

484     public void removeApplication( final String JavaDoc name )
485         throws Exception JavaDoc
486     {
487         final SarEntry entry = (SarEntry)m_entries.remove( name );
488         if( null == entry )
489         {
490             final String JavaDoc message =
491                 REZ.format( "kernel.error.entry.initialize", name );
492             throw new Exception JavaDoc( message );
493         }
494         else
495         {
496             // un-manage application
497
try
498             {
499                 m_applicationManager.unregister( name );
500             }
501             catch( final Throwable JavaDoc t )
502             {
503                 final String JavaDoc message =
504                     REZ.format( "kernel.error.entry.unmanage", name );
505                 throw new LoomException( message, t );
506             }
507
508             shutdown( entry );
509         }
510     }
511 }
512
Popular Tags