001    package org.apache.fulcrum.yaafi.framework.container;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.io.File;
023    import java.io.InputStream;
024    import java.util.ArrayList;
025    import java.util.HashMap;
026    import java.util.List;
027    import java.util.Properties;
028    
029    import org.apache.avalon.framework.configuration.Configuration;
030    import org.apache.avalon.framework.configuration.ConfigurationException;
031    import org.apache.avalon.framework.configuration.DefaultConfiguration;
032    import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
033    import org.apache.avalon.framework.container.ContainerUtil;
034    import org.apache.avalon.framework.context.Context;
035    import org.apache.avalon.framework.context.ContextException;
036    import org.apache.avalon.framework.context.DefaultContext;
037    import org.apache.avalon.framework.logger.Logger;
038    import org.apache.avalon.framework.parameters.ParameterException;
039    import org.apache.avalon.framework.parameters.Parameters;
040    import org.apache.avalon.framework.service.ServiceException;
041    import org.apache.avalon.framework.service.ServiceManager;
042    import org.apache.fulcrum.yaafi.framework.component.AvalonServiceComponentImpl;
043    import org.apache.fulcrum.yaafi.framework.component.ServiceComponent;
044    import org.apache.fulcrum.yaafi.framework.configuration.ComponentConfigurationPropertiesResolver;
045    import org.apache.fulcrum.yaafi.framework.configuration.ComponentConfigurationPropertiesResolverImpl;
046    import org.apache.fulcrum.yaafi.framework.constant.AvalonYaafiConstants;
047    import org.apache.fulcrum.yaafi.framework.context.AvalonToYaafiContextMapper;
048    import org.apache.fulcrum.yaafi.framework.context.YaafiToAvalonContextMapper;
049    import org.apache.fulcrum.yaafi.framework.role.RoleConfigurationParser;
050    import org.apache.fulcrum.yaafi.framework.role.RoleConfigurationParserImpl;
051    import org.apache.fulcrum.yaafi.framework.role.RoleEntry;
052    import org.apache.fulcrum.yaafi.framework.util.ConfigurationUtil;
053    import org.apache.fulcrum.yaafi.framework.util.InputStreamLocator;
054    import org.apache.fulcrum.yaafi.framework.util.StringUtils;
055    import org.apache.fulcrum.yaafi.framework.util.ToStringBuilder;
056    import org.apache.fulcrum.yaafi.framework.util.Validate;
057    import org.apache.fulcrum.yaafi.framework.crypto.CryptoStreamFactory;
058    
059    /**
060     * Yet another avalon framework implementation (YAAFI).
061     *
062     * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
063     */
064    
065    public class ServiceContainerImpl
066        implements ServiceContainer, ServiceConstants
067    {
068        /** the timeout before reconfiguring the container or services */
069        private static final int RECONFIGURATION_DELAY = 2000;
070    
071        /** The role configuration file to be used */
072        private String componentRolesLocation;
073    
074        /** is the component role file encrypted? */
075        private String isComponentRolesEncrypted;
076    
077        /** which flavour of component role file we have to parse? */
078        private String componentRolesFlavour;
079    
080        /** The service configuration file to be used */
081        private String componentConfigurationLocation;
082    
083        /** is the component configuration file encrypted? */
084        private String isComponentConfigurationEncrypted;
085    
086        /** The parameters file to be used */
087        private String parametersLocation;
088    
089        /** is the parameters file encrypted? */
090        private String isParametersEncrypted;
091    
092        /** The application directory aka the current woring directory */
093        private File applicationRootDir;
094    
095        /** The directory for storing temporary files */
096        private File tempRootDir;
097    
098        /** The logger to be used passed by the caller */
099        private Logger logger;
100    
101        /** The service manager passed to the container */
102        private ServiceManager parentServiceManager;
103    
104        /** The list of services instantiated */
105        private List serviceList;
106    
107        /** The map of services used for the lookup */
108        private HashMap serviceMap;
109    
110        /** The Avalon role configuration loaded by this class */
111        private Configuration roleConfiguration;
112    
113        /** The Avalon service configuration loaded by this class */
114        private Configuration serviceConfiguration;
115    
116        /** The temporary Avalon context passed to the implementation */
117        private Context callerContext;
118    
119        /** The default Avalon context passed to the services */
120        private Context context;
121    
122        /** The default Avalon parameters */
123        private Parameters parameters;
124    
125        /** Is this instance already disposed? */
126        private boolean isDisposed;
127    
128        /** The type of container where YAAFI is embedded */
129        private String containerFlavour;
130    
131        /** The ms to wait before triggering a reconfiguration of the container os service */
132        private int reconfigurationDelay;
133    
134        /** global flag for enabling/disabling dynamic proxies */
135        private boolean hasDynamicProxies;
136    
137        /** The list of interceptor services applied to all services */
138        private ArrayList defaultInterceptorServiceList;
139    
140        /** The list of ServiceManagers as fallback service lookup */
141        private ArrayList fallbackServiceManagerList;
142    
143        /** the configuration for running the ComponentConfigurationPropertiesResolver */
144        private Configuration componentConfigurationPropertiesResolverConfig;
145    
146        /////////////////////////////////////////////////////////////////////////
147        // Avalon Service Lifecycle
148        /////////////////////////////////////////////////////////////////////////
149    
150        /**
151         * Constructor using sensible defaults.
152         */
153        public ServiceContainerImpl()
154        {
155            super();
156    
157            this.reconfigurationDelay = RECONFIGURATION_DELAY;
158            this.containerFlavour = COMPONENT_CONTAINERFLAVOUR_VALUE;
159            this.componentRolesFlavour = COMPONENT_ROLECONFIGFLAVOUR_VALUE;
160    
161            this.componentRolesLocation = COMPONENT_ROLE_VALUE;
162            this.componentConfigurationLocation = COMPONENT_CONFIG_VALUE;
163            this.parametersLocation = COMPONENT_PARAMETERS_VALUE;
164    
165            this.isComponentConfigurationEncrypted = "false";
166            this.isComponentRolesEncrypted = "false";
167            this.isParametersEncrypted = "false";
168    
169            this.isDisposed = false;
170            this.serviceList = new ArrayList();
171            this.serviceMap = new HashMap();
172    
173            this.applicationRootDir = new File( new File("").getAbsolutePath() );
174            this.tempRootDir = new File( System.getProperty("java.io.tmpdir",".") );
175    
176            this.fallbackServiceManagerList = new ArrayList();
177            this.defaultInterceptorServiceList = new ArrayList();
178    
179            this.reconfigurationDelay = RECONFIGURATION_DELAY;
180        }
181    
182        /**
183         * @see org.apache.avalon.framework.logger.LogEnabled#enableLogging(org.apache.avalon.framework.logger.Logger)
184         */
185        public void enableLogging(Logger logger)
186        {
187            Validate.notNull( logger, "logger" );
188            this.logger = logger;
189        }
190    
191        /**
192         * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
193         */
194        public void contextualize(Context context) throws ContextException
195        {
196            Validate.notNull( context, "context" );
197            // Argghhh - I need to to parse the Configuration before I can map the Context
198            this.callerContext = context;
199        }
200    
201    
202        /**
203         * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
204         */
205        public void service(ServiceManager serviceManager) throws ServiceException
206        {
207            this.parentServiceManager = serviceManager;
208        }
209    
210        /**
211         * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
212         */
213        public void configure(Configuration configuration) throws ConfigurationException
214        {
215            Validate.notNull( configuration, "configuration" );
216    
217            // retrieve the reconfigurationDelay
218    
219            this.reconfigurationDelay =
220                configuration.getChild(RECONFIGURATION_DELAY_KEY).getValueAsInteger(
221                    RECONFIGURATION_DELAY
222                    );
223    
224            // evaluate if we are using dynamic proxies
225    
226            this.hasDynamicProxies =
227                configuration.getChild(DYNAMICPROXY_ENABLED_KEY).getValueAsBoolean(false);
228    
229            // retrieve the container flavour
230    
231            this.setContainerFlavour(
232                configuration.getChild(CONTAINERFLAVOUR_CONFIG_KEY).getValue(
233                    COMPONENT_CONTAINERFLAVOUR_VALUE )
234                );
235    
236            this.getLogger().debug( "Using the following container type : " + this.getContainerFlavour() );
237    
238            // process the caller-suppied context here
239    
240            try
241            {
242                // instantiate a mapper using the existing context - it might
243                // contain application specific entries we are not aware of
244    
245                AvalonToYaafiContextMapper mapper = new AvalonToYaafiContextMapper(
246                    this.getTempRootDir(),
247                    this.callerContext,
248                    this.getClassLoader()
249                    );
250    
251                // do the magic mapping
252    
253                this.context = mapper.mapFrom(
254                    this.callerContext,
255                    this.getContainerFlavour()
256                    );
257    
258                // don't keep a reference of the caller-supplide context
259    
260                this.callerContext = null;
261            }
262            catch( ContextException e )
263            {
264                String msg = "Failed to parse the caller-supplied context";
265                this.getLogger().error( msg, e );
266                throw new ConfigurationException( msg );
267            }
268    
269            // evaluate componentRoles
270    
271            Configuration currComponentRoles = configuration.getChild(COMPONENT_ROLE_KEYS);
272    
273            this.setComponentRolesLocation(
274                currComponentRoles.getChild(COMPONENT_LOCATION_KEY).getValue(
275                    COMPONENT_ROLE_VALUE )
276                    );
277    
278            this.setComponentRolesFlavour(
279                currComponentRoles.getChild(CONTAINERFLAVOUR_CONFIG_KEY).getValue(
280                    COMPONENT_ROLECONFIGFLAVOUR_VALUE )
281                    );
282    
283            this.setComponentRolesEncrypted(
284                currComponentRoles.getChild(COMPONENT_ISENCRYPTED_KEY).getValue(
285                    "false" )
286                    );
287    
288            // evaluate componentConfiguraion
289    
290            Configuration currComponentConfiguration = configuration.getChild(COMPONENT_CONFIG_KEY);
291    
292            this.setComponentConfigurationLocation(
293                currComponentConfiguration.getChild(COMPONENT_LOCATION_KEY).getValue(
294                    COMPONENT_CONFIG_VALUE )
295                    );
296    
297            this.setComponentConfigurationEncrypted(
298                currComponentConfiguration.getChild(COMPONENT_ISENCRYPTED_KEY).getValue(
299                    "false" )
300                    );
301    
302            // get the configuration for componentConfigurationPropertiesResolver
303    
304            this.componentConfigurationPropertiesResolverConfig = configuration.getChild(
305                COMPONENT_CONFIG_PROPERTIES_KEY
306                );
307    
308            // evaluate parameters
309    
310            Configuration currParameters = configuration.getChild(COMPONENT_PARAMETERS_KEY);
311    
312            this.setParametersLocation(
313                currParameters.getChild(COMPONENT_LOCATION_KEY).getValue(
314                    COMPONENT_PARAMETERS_VALUE )
315                    );
316    
317            this.setParametersEncrypted(
318                currParameters.getChild(COMPONENT_ISENCRYPTED_KEY).getValue(
319                    "false" )
320                    );
321    
322            // evaluate the default interceptors
323    
324            Configuration currInterceptorList = configuration.getChild(
325                INTERCEPTOR_LIST_KEY
326                );
327    
328            Configuration[] interceptorConfigList = currInterceptorList.getChildren(
329                INTERCEPTOR_KEY
330                );
331    
332            for( int i=0; i<interceptorConfigList.length; i++ )
333            {
334                String interceptorServiceName = interceptorConfigList[i].getValue(null);
335    
336                if( !StringUtils.isEmpty(interceptorServiceName) && this.hasDynamicProxies())
337                {
338                        this.defaultInterceptorServiceList.add( interceptorServiceName );
339    
340                        this.getLogger().debug("Using the following default interceptor service : "
341                            + interceptorServiceName
342                            );
343                }
344            }
345    
346            // evaluate a list of service managers managing their own set of services
347            // independent from the Avalon container. This service managers are used
348            // to find services implemented as Spring bean or remote webservices.
349    
350            Configuration currServiceManagerList = configuration.getChild(
351                SERVICEMANAGER_LIST_KEY
352                );
353    
354            Configuration[] serviceManagerConfigList = currServiceManagerList.getChildren(
355                SERVICEMANAGER_KEY
356                );
357    
358            for( int i=0; i<serviceManagerConfigList.length; i++ )
359            {
360                String serviceManagerName = serviceManagerConfigList[i].getValue(null);
361    
362                if( !StringUtils.isEmpty(serviceManagerName) )
363                {
364                        this.fallbackServiceManagerList.add( serviceManagerName );
365    
366                        this.getLogger().debug("Using the following fallback service manager : "
367                            + serviceManagerName
368                            );
369                }
370            }
371        }
372    
373        /**
374         * @see org.apache.avalon.framework.parameters.Parameterizable#parameterize(org.apache.avalon.framework.parameters.Parameters)
375         */
376        public void parameterize(Parameters parameters) throws ParameterException
377        {
378            this.parameters = parameters;
379        }
380    
381        /**
382         * @see org.apache.avalon.framework.activity.Initializable#initialize()
383         */
384        public void initialize() throws Exception
385        {
386            this.getLogger().debug( "YAAFI Service Framework is starting up");
387    
388            // set the directories being used
389    
390            this.setApplicationRootDir(
391                (File) this.getContext().get(AvalonYaafiConstants.URN_AVALON_HOME )
392                );
393    
394            this.setTempRootDir(
395                (File) this.getContext().get(AvalonYaafiConstants.URN_AVALON_TEMP )
396                );
397    
398            // get the configuration files
399    
400            this.roleConfiguration = loadConfiguration(
401                this.componentRolesLocation,
402                this.isComponentRolesEncrypted()
403                );
404    
405            if( this.roleConfiguration == null )
406            {
407                String msg = "Unable to locate the role configuration : " + this.componentRolesLocation;
408                this.getLogger().error( msg );
409                throw new ConfigurationException( msg );
410            }
411    
412            this.serviceConfiguration = loadConfiguration(
413                this.componentConfigurationLocation,
414                this.isComponentConfigurationEncrypted()
415                );
416    
417            // create the configuration properties
418    
419            Properties componentConfigurationProperties = this.loadComponentConfigurationProperties();
420    
421            // expand the componentConfiguration using the componentConfigurationProperties
422    
423            ConfigurationUtil.expand(
424                this.getLogger(),
425                (DefaultConfiguration) this.serviceConfiguration,
426                componentConfigurationProperties
427                );
428    
429            // create the default parameters
430    
431            if( this.getParameters() == null )
432            {
433                this.parameters= this.loadParameters(
434                    this.parametersLocation,
435                    this.isParametersEncrypted()
436                    );
437            }
438    
439            // create the service implementaion instances
440    
441            List currServiceList = this.createServiceComponents(
442                this.roleConfiguration,
443                this.getLogger()
444                );
445    
446            this.setServiceList( currServiceList );
447    
448            // fill the service map mapping from a service name to an instance
449    
450            for( int i=0; i<this.getServiceList().size(); i++ )
451            {
452                ServiceComponent serviceComponent = (ServiceComponent) this.getServiceList().get(i);
453                this.getServiceMap().put( serviceComponent.getName(), serviceComponent );
454            }
455    
456            // ensure that fallback service managers are available
457    
458            for(int i=0; i<this.fallbackServiceManagerList.size(); i++)
459            {
460                String currServiceManagerName = (String) this.fallbackServiceManagerList.get(i);
461                if(this.getServiceMap().get(currServiceManagerName) == null)
462                {
463                    String msg = "The following fallback service manager was not found : " + currServiceManagerName;
464                    throw new IllegalArgumentException(msg);
465                }
466            }
467    
468            // run the various lifecycle stages
469    
470            this.incarnateAll( this.getServiceList() );
471    
472            // we are up and running
473    
474            this.isDisposed = false;
475            this.getLogger().debug( "YAAFI Avalon Service Container is up and running");
476        }
477    
478    
479        /**
480         * Disposes the service container implementation.
481         *
482         * @see org.apache.avalon.framework.activity.Disposable#dispose()
483         */
484        public synchronized void dispose()
485        {
486            if( this.isDisposed )
487            {
488                return;
489            }
490    
491            if( this.getLogger() != null )
492            {
493                this.getLogger().debug("Disposing all services");
494            }
495    
496            // decommision all servcies
497    
498            this.decommisionAll( this.getServiceList() );
499    
500            // dispose all servcies
501    
502            this.disposeAll( this.getServiceList() );
503    
504            // clean up
505    
506            this.getServiceList().clear();
507            this.getServiceMap().clear();
508    
509            this.componentRolesLocation = null;
510            this.componentConfigurationLocation = null;
511            this.context = null;
512            this.parametersLocation = null;
513            this.roleConfiguration = null;
514            this.serviceConfiguration = null;
515            this.parameters = null;
516            this.fallbackServiceManagerList = null;
517            this.defaultInterceptorServiceList = null;
518            this.isDisposed = true;
519    
520            if( this.getLogger() != null )
521            {
522                this.getLogger().debug( "All services are disposed" );
523            }
524        }
525    
526        /**
527         * Reconfiguring the services. I'm not sure how to implement this properly since
528         * the Avalon docs is vague on this subject. For now we suspend, reconfigure and
529         * resume the services in the correct order.
530         *
531         * @see org.apache.avalon.framework.configuration.Reconfigurable#reconfigure(org.apache.avalon.framework.configuration.Configuration)
532         */
533        public synchronized void reconfigure(Configuration configuration)
534            throws ConfigurationException
535        {
536            Validate.notNull( configuration, "configuration" );
537    
538            int exceptionCounter = 0;
539            ServiceComponent serviceComponent = null;
540    
541            this.getLogger().warn("Reconfiguring all services ...");
542    
543            // 1) wait for some time
544    
545            this.waitForReconfiguration();
546    
547            // 2) store the new configuration
548    
549            this.serviceConfiguration = configuration;
550    
551            Properties componentConfigurationProperties = this.loadComponentConfigurationProperties();
552    
553            ConfigurationUtil.expand(
554                this.getLogger(),
555                (DefaultConfiguration) this.serviceConfiguration,
556                componentConfigurationProperties
557                );
558    
559            // 3) reconfigure the services
560    
561            for( int i=0; i<this.getServiceList().size(); i++ )
562            {
563                serviceComponent = (ServiceComponent) this.getServiceList().get(i);
564    
565                Configuration serviceComponentConfiguraton = this.getServiceConfiguration().getChild(
566                    serviceComponent.getShorthand()
567                    );
568    
569                try
570                {
571                    serviceComponent.setConfiguration(serviceComponentConfiguraton);
572                    serviceComponent.reconfigure();
573                }
574                catch(Throwable t)
575                {
576                    String msg = "Reconfiguring of " + serviceComponent.getShorthand() + " failed";
577                    this.getLogger().error(msg);
578                    exceptionCounter++;
579                }
580            }
581    
582            // 4) check the result
583    
584            if( exceptionCounter > 0 )
585            {
586                String msg = "The reconfiguration failed with " + exceptionCounter + " exception(s)";
587                this.getLogger().error(msg);
588                throw new ConfigurationException(msg);
589            }
590        }
591    
592        /////////////////////////////////////////////////////////////////////////
593        // Server Interface Implementation
594        /////////////////////////////////////////////////////////////////////////
595    
596        /**
597         * @see org.apache.fulcrum.yaafi.framework.container.ServiceLifecycleManager#getRoleEntry(java.lang.String)
598         */
599        public synchronized RoleEntry getRoleEntry(String name)
600            throws ServiceException
601        {
602            return this.getServiceComponentEx(name).getRoleEntry();
603        }
604    
605        /**
606         * @see org.apache.fulcrum.yaafi.framework.container.ServiceLifecycleManager#getRoleEntries()
607         */
608        public synchronized RoleEntry[] getRoleEntries()
609        {
610            List serviceList = this.getServiceList();
611            ServiceComponent serviceComponent = null;
612            RoleEntry[] result = new RoleEntry[serviceList.size()];
613    
614            for( int i=0; i<result.length; i++ )
615            {
616                serviceComponent = (ServiceComponent) serviceList.get(i);
617                result[i] = serviceComponent.getRoleEntry();
618            }
619    
620            return result;
621        }
622    
623        /**
624         * @see org.apache.fulcrum.yaafi.framework.container.ServiceLifecycleManager#reconfigure(java.lang.String[])
625         */
626        public synchronized void reconfigure(String[] names) throws ServiceException,
627            ConfigurationException
628        {
629            Validate.notNull(names,"names");
630            Validate.noNullElements(names,"names");
631            
632            this.waitForReconfiguration();
633    
634            for( int i=0; i<names.length; i++ )
635            {
636                // ensure that the service exists since during our reconfiguration
637                // we might use a stle recofniguration entry
638    
639                if( this.getServiceMap().get(names[i]) != null )
640                {
641                    this.reconfigure(names[i]);
642                }
643            }
644        }
645    
646        /**
647         * @see org.apache.avalon.framework.service.ServiceManager#hasService(java.lang.String)
648         */
649        public boolean hasService(String name)
650        {
651            Validate.notEmpty( name, "name" );
652    
653            boolean result = false;
654    
655            synchronized(this)
656            {
657                // look at our available service
658    
659                result = (this.getLocalServiceComponent(name) != null);
660    
661                // look at fallback service managers
662    
663                if(!result)
664                {
665                    result = this.hasFallbackService(name);
666                }
667            }
668    
669            // if we haven't found anything ask the parent ServiceManager
670    
671            if( (!result) && ( this.hasParentServiceManager() ) )
672            {
673                result = this.getParentServiceManager().hasService(name);
674            }
675    
676            return result;
677        }
678    
679        /**
680         * Lookup a service instance. The implementation uses the following
681         * mechanism
682         * <ul>
683         *  <li>look for a matching local service
684         *  <li>use the fallback service manager as they might know the service
685         *  <li>ask the parent service manager
686         * </ul>
687         *
688         * @see org.apache.avalon.framework.service.ServiceManager#lookup(java.lang.String)
689         */
690        public Object lookup(String name) throws ServiceException
691        {
692            Validate.notEmpty( name, "name" );
693    
694            Object result = null;
695            ServiceComponent serviceManagerComponent = null;
696    
697            try
698            {
699                synchronized (this)
700                {
701                    // 1) check our local services
702    
703                    serviceManagerComponent = this.getLocalServiceComponent(name);
704    
705                    if( serviceManagerComponent != null )
706                    {
707                        result = serviceManagerComponent.getInstance();
708    
709                        if((result != null) && this.getLogger().isDebugEnabled())
710                        {
711                            String msg = "Located the service '" + name + "' in the local container";
712                            this.getLogger().debug(msg);
713                        }
714                    }
715    
716                    // 2) look at fallback service managers
717    
718                    if(result == null)
719                    {
720                        result = this.getFallbackService(name);
721                    }
722                }
723            }
724            catch(ServiceException e)
725            {
726                String msg = "Failed to lookup a service " + name;
727                this.getLogger().error( msg, e );            
728                throw e;
729            }
730            catch( Throwable t )
731            {
732                String msg = "Failed to lookup a service " + name;
733                this.getLogger().error( msg, t );
734                throw new ServiceException( name, msg, t );
735            }
736    
737            // 3) if we haven't found anything ask the parent ServiceManager
738    
739            if( (result == null) && this.hasParentServiceManager() )
740            {
741                result = this.getParentServiceManager().lookup(name);
742    
743                if((result != null) && this.getLogger().isDebugEnabled())
744                {
745                    String msg = "Located the service '" + name + "' using the parent service manager";
746                    this.getLogger().debug(msg);
747                }
748            }
749    
750            // if we still haven't found anything then complain
751    
752            if( result == null )
753            {
754                String msg = "The following component does not exist : " + name;
755                this.getLogger().error(msg);
756                throw new ServiceException( AvalonYaafiConstants.AVALON_CONTAINER_YAAFI, name );
757            }
758    
759            return result;
760        }
761    
762        /**
763         * @see org.apache.avalon.framework.service.ServiceManager#release(java.lang.Object)
764         */
765        public void release(Object object)
766        {
767            // AFAIK this is only useful for lifecycle management regarding
768            // lifestyle other than singleton.
769        }
770    
771        /**
772         * @see org.apache.fulcrum.yaafi.framework.container.ServiceContainer#decommision(java.lang.String)
773         */
774        public synchronized void decommision(String name) throws ServiceException
775        {
776            this.waitForReconfiguration();       
777            ServiceComponent serviceComponent = this.getServiceComponentEx(name);
778            this.decommision(serviceComponent);
779        }
780    
781        /**
782         * @see org.apache.fulcrum.yaafi.framework.container.ServiceContainer#getParameters()
783         */
784        public Parameters getParameters()
785        {
786            return this.parameters;
787        }
788    
789        /////////////////////////////////////////////////////////////////////////
790        // Service Implementation
791        /////////////////////////////////////////////////////////////////////////
792    
793        /**
794         * @see java.lang.Object#toString()
795         */
796        public String toString()
797        {
798            ToStringBuilder toStringBuilder = new ToStringBuilder(this);
799    
800            toStringBuilder.append("applicationRootDir", this.getApplicationRootDir());
801            toStringBuilder.append("tempRootDir", this.getTempRootDir());
802            toStringBuilder.append("componentRolesLocation", this.componentRolesLocation);
803            toStringBuilder.append("componentConfigurationLocation", this.componentConfigurationLocation);
804            toStringBuilder.append("parametersLocation", parametersLocation);
805            toStringBuilder.append("logger", this.getLogger().getClass().getName());
806            toStringBuilder.append("hasDynamicProxies", this.hasDynamicProxies);
807            toStringBuilder.append("containerFlavour", this.containerFlavour);
808            toStringBuilder.append("componentRolesFlavour", this.componentRolesFlavour);
809            toStringBuilder.append("isComponentRolesEncrypted", this.isComponentRolesEncrypted);
810            toStringBuilder.append("isComponentConfigurationEncrypted", this.isComponentConfigurationEncrypted);
811            toStringBuilder.append("isParametersEncrypted", this.isParametersEncrypted);
812    
813            return toStringBuilder.toString();
814        }
815    
816        /**
817         * Create a role configuration parser based on the container flavour.
818         * @return the role configuration parser
819         */
820        private RoleConfigurationParser createRoleConfigurationParser()
821        {
822            return new RoleConfigurationParserImpl(
823                this.getComponentRolesFlavour()
824                );
825        }
826    
827        /**
828         * Reconfigure a single service
829         *
830         * @param name the name of the service to be reconfigured
831         * @throws ServiceException the service was not found
832         * @throws ConfigurationException the reconfiguration failed
833         */
834        private void reconfigure(String name)
835            throws ServiceException, ConfigurationException
836        {
837            Validate.notEmpty( name, "name" );
838            ServiceComponent serviceComponent = this.getServiceComponentEx(name);
839    
840            // reconfigure the component
841    
842            try
843            {
844                serviceComponent.reconfigure();
845            }
846            catch(ConfigurationException e)
847            {
848                String msg = "Reconfiguring failed : " + serviceComponent.getShorthand();
849                this.getLogger().error(msg,e);
850                throw new ConfigurationException(msg,e);
851            }
852            catch(Throwable t)
853            {
854                String msg = "Reconfiguring failed : " + serviceComponent.getShorthand();
855                this.getLogger().error(msg,t);
856                throw new ConfigurationException(msg,t);
857            }
858        }
859    
860        /**
861         * Enforce that a service is known to simplify error handling.
862         *
863         * @param name the name of the service component
864         * @return the service component
865         * @throws ServiceException the service was not found
866         */
867        private ServiceComponent getServiceComponentEx(String name)
868            throws ServiceException
869        {
870            Validate.notEmpty( name, "name" );
871            ServiceComponent result = (ServiceComponent) this. getServiceMap().get(name);
872    
873            if( result == null )
874            {
875                String msg = "The following component does not exist : " + name;
876                this.getLogger().error(msg);
877                throw new ServiceException( AvalonYaafiConstants.AVALON_CONTAINER_YAAFI, name );
878            }
879    
880            return result;
881        }
882    
883        /**
884         * Try to get a local service component.
885         *
886         * @param name the name of the service component
887         * @return the service component if any
888         */
889        private ServiceComponent getLocalServiceComponent(String name)
890        {
891            Validate.notEmpty( name, "name" );
892            ServiceComponent result = (ServiceComponent) this. getServiceMap().get(name);
893            return result;
894        }
895    
896        /**
897         * Try to get a service component provided by a fallback service
898         * manager.
899         *
900         * @param name the name of the service component
901         * @return the service component if any
902         * @throws Exception getting the service failed
903         */
904        private Object getFallbackService(String name) throws Exception
905        {
906    
907            Validate.notEmpty( name, "name" );
908    
909            Object result = null;
910            ServiceComponent serviceManagerComponent = null;
911    
912            for(int i=0; i<this.fallbackServiceManagerList.size(); i++)
913            {
914                String serviceManagerComponentName = (String) fallbackServiceManagerList.get(i);
915                serviceManagerComponent = this.getLocalServiceComponent(serviceManagerComponentName);
916    
917                if(serviceManagerComponent != null)
918                {
919                    ServiceManager currServiceManager = (ServiceManager) serviceManagerComponent.getInstance();
920    
921                    if (currServiceManager.hasService(name))
922                    {
923                        result = currServiceManager.lookup(name);
924    
925                        if((result != null) && this.getLogger().isDebugEnabled())
926                        {
927                            String msg = "Located the service '" + name + "' using the fallback service manager '" + serviceManagerComponentName + "'";
928                            this.getLogger().debug(msg);
929                        }
930                    }
931                }
932            }
933    
934            return result;
935        }
936    
937        /**
938         * Try to get a service provided by a fallback service manager.
939         *
940         * @param name the name of the service component
941         * @return the service component if any
942         */
943        private boolean hasFallbackService(String name)
944        {
945            Validate.notEmpty( name, "name" );
946    
947            ServiceComponent serviceManagerComponent = null;
948    
949            for(int i=0; i<this.fallbackServiceManagerList.size(); i++)
950            {
951                String serviceManagerComponentName = (String) fallbackServiceManagerList.get(i);
952                serviceManagerComponent = this.getLocalServiceComponent(serviceManagerComponentName);
953    
954                if(serviceManagerComponent != null)
955                {
956                    ServiceManager currServiceManager;
957    
958                    try
959                    {
960                        currServiceManager = (ServiceManager) serviceManagerComponent.getInstance();
961                        if (currServiceManager.hasService(name))
962                        {
963                            return true;
964                        }
965                    }
966                    catch (Exception e)
967                    {
968                        String msg = "Unable to invoke fallback service manager '" + serviceManagerComponentName + "'";
969                        this.getLogger().error(msg, e);
970                        throw new RuntimeException(msg);
971                    }
972                }
973            }
974    
975            return false;
976        }
977    
978        /**
979         * @param string The location of the component configuration file
980         */
981        private void setComponentConfigurationLocation(String string)
982        {
983            this.componentConfigurationLocation = string;
984        }
985    
986        /**
987         * @param string The location of the component role file
988         */
989        private void setComponentRolesLocation(String string)
990        {
991            this.componentRolesLocation = string;
992        }
993    
994        /**
995         * @param string The location of the parameters file
996         */
997        private void setParametersLocation(String string)
998        {
999            this.parametersLocation = string;
1000        }
1001    
1002        /**
1003         * @return The logger of the service containe
1004         */
1005        private Logger getLogger()
1006        {
1007            return this.logger;
1008        }
1009    
1010        /**
1011         * @return Returns the serviceMap.
1012         */
1013        private HashMap getServiceMap()
1014        {
1015            return this.serviceMap;
1016        }
1017    
1018        /**
1019         * Incarnation of a list of services.
1020         *
1021         * @param serviceList the list of available services
1022         * @throws Exception the incarnation of a service failed
1023         */
1024        private void incarnateAll(List serviceList)
1025            throws Exception
1026        {
1027            ServiceComponent serviceComponent = null;
1028    
1029            // configure all services
1030    
1031            for( int i=0; i<serviceList.size(); i++ )
1032            {
1033                serviceComponent = (ServiceComponent) this.getServiceList().get(i);
1034                this.configure( serviceComponent );
1035            }
1036    
1037            // incarnate all services
1038    
1039            for( int i=0; i<serviceList.size(); i++ )
1040            {
1041                serviceComponent = (ServiceComponent) this.getServiceList().get(i);
1042                this.incarnate( serviceComponent );
1043            }
1044    
1045        }
1046    
1047        /**
1048         * Configure a single service component. After the invocation
1049         * the service component is ready to be incarnated.
1050         *
1051         * @param serviceComponent The service component to be configured
1052         * @throws Exception the configuration failed
1053         */
1054        private void configure( ServiceComponent serviceComponent )
1055            throws Exception
1056        {
1057            this.getLogger().debug( "Configuring the service component "
1058                + serviceComponent.getShorthand()
1059                );
1060    
1061            // map the context according to the Avalon component type
1062    
1063            YaafiToAvalonContextMapper mapper = new YaafiToAvalonContextMapper(
1064                serviceComponent.getName(),
1065                this.getClassLoader()
1066                );
1067    
1068            RoleEntry roleEntry = serviceComponent.getRoleEntry();
1069            String componentFlavour = roleEntry.getComponentFlavour();
1070    
1071            DefaultContext serviceComponentContext = mapper.mapTo(
1072                this.getContext(),
1073                componentFlavour
1074                );
1075    
1076            // create the remaining Avalon artifacts for the service component
1077    
1078            Logger serviceComponentLogger = this.getLogger().getChildLogger(
1079                roleEntry.getLogCategory()
1080                );
1081    
1082            Configuration serviceComponentConfiguraton = this.getServiceConfiguration().getChild(
1083                roleEntry.getShorthand()
1084                );
1085    
1086            Parameters serviceComponentParameters = this.getParameters();
1087    
1088            // configure the service component with all the artifacts
1089    
1090            serviceComponent.setLogger(serviceComponentLogger);
1091            serviceComponent.setServiceManager(this);
1092            serviceComponent.setContext(serviceComponentContext);
1093            serviceComponent.setConfiguration(serviceComponentConfiguraton);
1094            serviceComponent.setParameters(serviceComponentParameters);
1095    
1096            // load the implementation class of the service
1097    
1098            serviceComponent.loadImplemtationClass(
1099               this.getClassLoader()
1100                );
1101        }
1102    
1103        /**
1104         * Incarnation of a configured service component. After the
1105         * incarnation the service component is operational.
1106         *
1107         * @param serviceComponent The service component to incarnate
1108         * @exception Exception incarnating the service component failed
1109         */
1110        private void incarnate( ServiceComponent serviceComponent )
1111            throws Exception
1112        {
1113            this.getLogger().debug( "Incarnating the service "
1114                + serviceComponent.getShorthand()
1115                );
1116    
1117            serviceComponent.incarnate();
1118        }
1119    
1120        /**
1121         * Decommision a ist of services.
1122         *
1123         * @param serviceList the list of services to decommision
1124         */
1125        private void decommisionAll(List serviceList)
1126        {
1127            ServiceComponent serviceComponent = null;
1128    
1129            for( int i=serviceList.size()-1; i>=0; i-- )
1130            {
1131                serviceComponent = (ServiceComponent) serviceList.get(i);
1132                this.decommision( serviceComponent );
1133            }
1134        }
1135    
1136        /**
1137         * Decommision of a single service component. Decommision consists of running the
1138         * whole Avalon decommision lifecycle process for a service component. After
1139         * decommision the service is not operational any longer. During decommisioning
1140         * we ignore any exceptions since it is quite common that something goes wrong.
1141         *
1142         * @param serviceComponent The service component to decommision
1143         */
1144        private void decommision( ServiceComponent serviceComponent )
1145        {
1146            this.getLogger().debug( "Decommision the service " + serviceComponent.getShorthand() );
1147    
1148            try
1149            {
1150                serviceComponent.decommision();
1151            }
1152            catch (Throwable e)
1153            {
1154                String msg = "Decommisioning the following service failed : " + serviceComponent.getName();
1155                this.getLogger().error( msg, e );
1156            }
1157        }
1158    
1159        /**
1160         * Disposing a ist of services
1161         *
1162         * @param serviceList the list of services to dispose
1163         */
1164        private void disposeAll(List serviceList)
1165        {
1166            ServiceComponent serviceComponent = null;
1167    
1168            for( int i=serviceList.size()-1; i>=0; i-- )
1169            {
1170                serviceComponent = (ServiceComponent) serviceList.get(i);
1171                this.dispose( serviceComponent );
1172            }
1173        }
1174    
1175        /**
1176         * Disposing of a single service component.
1177    
1178         * @param serviceComponent The service component to decommision
1179         */
1180        private void dispose( ServiceComponent serviceComponent )
1181        {
1182            this.getLogger().debug( "Disposing the service " + serviceComponent.getShorthand() );
1183    
1184            try
1185            {
1186                serviceComponent.dispose();
1187            }
1188            catch (Throwable e)
1189            {
1190                String msg = "Disposing the following service failed : " + serviceComponent.getName();
1191                this.getLogger().error( msg, e );
1192            }
1193        }
1194    
1195        /**
1196         * @return The list of currently know services
1197         */
1198        private List getServiceList()
1199        {
1200            return this.serviceList;
1201        }
1202    
1203        /**
1204         * @param list The list of known services
1205         */
1206        private void setServiceList(List list)
1207        {
1208            this.serviceList = list;
1209        }
1210    
1211        /**
1212         * @return The service configuration
1213         */
1214        private Configuration getServiceConfiguration()
1215        {
1216            return this.serviceConfiguration;
1217        }
1218    
1219        /**
1220         * Factory method for creating services. The service
1221         * instances are not initialized at this point.
1222         *
1223         * @param roleConfiguration the role configuration file
1224         * @param logger the logger
1225         * @return the list of service components
1226         * @throws ConfigurationException creating the service instance failed
1227         */
1228        private List createServiceComponents(Configuration roleConfiguration, Logger logger )
1229            throws ConfigurationException
1230        {
1231            Validate.notNull(roleConfiguration,"roleConfiguration");
1232            Validate.notNull(logger,"logger");
1233    
1234            ArrayList result = new ArrayList();
1235            ServiceComponent serviceComponent = null;
1236    
1237            // create an appropriate instance of role configuration parser
1238    
1239            RoleConfigurationParser roleConfigurationParser = this.createRoleConfigurationParser();
1240    
1241            // extract the role entries
1242    
1243            RoleEntry[] roleEntryList = roleConfigurationParser.parse(roleConfiguration);
1244    
1245            // get the default interceptors defined for the container
1246    
1247            ArrayList defaultInterceptorList = this.getDefaultInterceptorServiceList();
1248    
1249            // create the service components based on the role entries
1250    
1251            for ( int i=0; i<roleEntryList.length; i++ )
1252            {
1253                try
1254                {
1255                    // add the default interceptors to all role entries
1256    
1257                    RoleEntry roleEntry = roleEntryList[i];
1258    
1259                    if( this.hasDynamicProxies() )
1260                    {
1261                        roleEntry.addInterceptors(defaultInterceptorList);
1262                    }
1263                    else
1264                    {
1265                        roleEntry.setHasDynamicProxy(false);
1266                    }
1267    
1268                    serviceComponent = new AvalonServiceComponentImpl(
1269                        roleEntry,
1270                        this.getLogger(),
1271                        logger
1272                        );
1273    
1274                    result.add( serviceComponent );
1275                }
1276                catch( Throwable t )
1277                {
1278                    String serviceComponentName = ( serviceComponent != null ? serviceComponent.getName() : "unknown" ); 
1279                    String msg = "Failed to load the service " + serviceComponentName;
1280                    this.getLogger().error( msg, t );
1281                    throw new ConfigurationException( msg, t );
1282                }
1283            }
1284    
1285            return result;
1286        }
1287    
1288        /**
1289         * Load a configuration file either from a file or using the class loader.
1290         * @param location the location of the file
1291         * @param isEncrypted  is the configuration encryped
1292         * @return The loaded configuration
1293         * @throws Exception Something went wrong
1294         */
1295        private Configuration loadConfiguration( String location, String isEncrypted )
1296            throws Exception
1297        {
1298            Configuration result = null;
1299            InputStreamLocator locator = this.createInputStreamLocator();
1300            InputStream is = locator.locate( location );
1301            DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
1302    
1303            if( is != null )
1304            {
1305                try
1306                {
1307                    is = this.getDecryptingInputStream( is, isEncrypted );
1308                    result = builder.build( is );
1309                    is.close();
1310                    is = null;
1311                }
1312                catch ( Exception e )
1313                {
1314                    String msg = "Unable to parse the following file : " + location;
1315                    this.getLogger().error( msg , e );
1316                    throw e;
1317                }
1318            }
1319    
1320            return result;
1321        }
1322    
1323        /**
1324         * Load a configuration property file either from a file or using the class loader.
1325         * 
1326         * @return The loaded proeperty file
1327         * @throws ConfigurationException Something went wrong
1328         */
1329        private Properties loadComponentConfigurationProperties()
1330            throws ConfigurationException
1331        {
1332            Properties result = new Properties();
1333            ComponentConfigurationPropertiesResolver resolver = null;
1334    
1335            String className = this.componentConfigurationPropertiesResolverConfig.getChild("resolver").getValue(
1336                ComponentConfigurationPropertiesResolverImpl.class.getName()
1337                );
1338    
1339            try
1340            {
1341                Class resolverClass = this.getClassLoader().loadClass( className );
1342                resolver = (ComponentConfigurationPropertiesResolver) resolverClass.newInstance();
1343                ContainerUtil.enableLogging(resolver, this.getLogger());
1344                ContainerUtil.contextualize(resolver, this.getContext());
1345                ContainerUtil.configure(resolver, this.componentConfigurationPropertiesResolverConfig);
1346    
1347                result = resolver.resolve(null);
1348    
1349                this.getLogger().debug("Using the following componentConfigurationProperties: " + result);
1350            }
1351            catch (Exception e)
1352            {
1353                String msg = "Resolving componentConfigurationProperties failed using the following class : " + className;
1354                this.getLogger().error(msg, e);
1355                throw new ConfigurationException(msg, e);
1356            }
1357    
1358            return result;
1359        }
1360    
1361        /**
1362         * Load the parameters
1363         * @param location The location as a file
1364         * @param isEncrypted is the file encrypted
1365         * @return The loaded configuration
1366         * @throws Exception Something went wrong
1367         */
1368        private Parameters loadParameters( String location, String isEncrypted )
1369            throws Exception
1370        {
1371            InputStreamLocator locator = this.createInputStreamLocator();
1372            InputStream is = locator.locate( location );
1373            Parameters result = new Parameters();
1374    
1375            if( is != null )
1376            {
1377                is = this.getDecryptingInputStream( is, isEncrypted );
1378                Properties props = new Properties();
1379                props.load( is );
1380                is.close();
1381                is = null;
1382                result = Parameters.fromProperties( props );
1383            }
1384    
1385            return result;
1386        }
1387    
1388    
1389        /**
1390         * Creates a locator to find a resource either in the file system or in
1391         * the classpath.
1392         *
1393         * @return the locator
1394         */
1395        private InputStreamLocator createInputStreamLocator()
1396        {
1397            return new InputStreamLocator( this.getApplicationRootDir(), this.getLogger() );
1398        }
1399    
1400        /**
1401         * Set the application directory of the container.
1402         *
1403         * @param dir The applicationRootDir to set.
1404         */
1405        private void setApplicationRootDir(File dir)
1406        {
1407            this.getLogger().debug( "Setting applicationRootDir to " + dir.getAbsolutePath() );
1408    
1409            Validate.notNull(dir,"applicationRootDir is <null>");
1410            Validate.isTrue(dir.exists(),"applicationRootDir does not exist");
1411    
1412            this.applicationRootDir = dir;
1413        }
1414    
1415        /**
1416         * @return Returns the applicationRootDir.
1417         */
1418        private File getApplicationRootDir()
1419        {
1420            return this.applicationRootDir;
1421        }
1422    
1423        /**
1424         * @return Returns the serviceManager of the parent container
1425         */
1426        private ServiceManager getParentServiceManager()
1427        {
1428            return this.parentServiceManager;
1429        }
1430    
1431        /**
1432         * @return is a parent ServiceManager available
1433         */
1434        private boolean hasParentServiceManager()
1435        {
1436            return (this.getParentServiceManager() != null);
1437        }
1438        /**
1439         * Set the temporary directory of the container.
1440         *
1441         * @param dir The tempRootDir to set.
1442         */
1443        private void setTempRootDir(File dir)
1444        {
1445            this.getLogger().debug( "Setting tempRootDir to " + dir.getAbsolutePath() );
1446    
1447            Validate.notNull(dir,"tempRootDir is <null>");
1448            Validate.isTrue(dir.exists(),"tempRootDir does not exist");
1449            Validate.isTrue(dir.canWrite(),"tempRootDir is not writeable");
1450    
1451            this.tempRootDir = dir;
1452        }
1453    
1454        /**
1455         * @return Returns the tempRootDir.
1456         */
1457        private File getTempRootDir()
1458        {
1459            return tempRootDir;
1460        }
1461    
1462        /**
1463         * @return Returns the isComponentConfigurationEncrypted.
1464         */
1465        private String isComponentConfigurationEncrypted()
1466        {
1467            return isComponentConfigurationEncrypted;
1468        }
1469    
1470        /**
1471         * @param isComponentConfigurationEncrypted The isComponentConfigurationEncrypted to set.
1472         */
1473        private void setComponentConfigurationEncrypted(
1474            String isComponentConfigurationEncrypted)
1475        {
1476            this.isComponentConfigurationEncrypted = isComponentConfigurationEncrypted;
1477        }
1478    
1479        /**
1480         * @return Returns the isComponentRolesEncrypted.
1481         */
1482        private String isComponentRolesEncrypted()
1483        {
1484            return isComponentRolesEncrypted;
1485        }
1486    
1487        /**
1488         * @param isComponentRolesEncrypted The isComponentRolesEncrypted to set.
1489         */
1490        private void setComponentRolesEncrypted(String isComponentRolesEncrypted)
1491        {
1492            this.isComponentRolesEncrypted = isComponentRolesEncrypted;
1493        }
1494    
1495        /**
1496         * @return Returns the isParametersEncrypted.
1497         */
1498        private String isParametersEncrypted()
1499        {
1500            return isParametersEncrypted;
1501        }
1502    
1503        /**
1504         * @param isParametersEncrypted The isParametersEncrypted to set.
1505         */
1506        private void setParametersEncrypted(String isParametersEncrypted)
1507        {
1508            this.isParametersEncrypted = isParametersEncrypted;
1509        }
1510    
1511        /**
1512         * Create a decrypting input stream using the default password.
1513         *
1514         * @param is the input stream to be decrypted
1515         * @param isEncrypted the encryption mode (true|false|auto)
1516         * @return an decrypting input stream
1517         * @throws Exception reading the input stream failed
1518         */
1519        private InputStream getDecryptingInputStream( InputStream is, String isEncrypted )
1520            throws Exception
1521        {
1522            return CryptoStreamFactory.getDecryptingInputStream(is, isEncrypted);
1523        }
1524    
1525        /**
1526         * @return Returns the containerFlavour.
1527         */
1528        private String getContainerFlavour()
1529        {
1530            return containerFlavour;
1531        }
1532    
1533        /**
1534         * @param containerFlavour The containerFlavour to set.
1535         */
1536        private void setContainerFlavour(String containerFlavour)
1537        {
1538            this.containerFlavour = containerFlavour;
1539        }
1540    
1541        /**
1542         * @return Returns the componentRolesFlavour.
1543         */
1544        private String getComponentRolesFlavour()
1545        {
1546            return componentRolesFlavour;
1547        }
1548    
1549        /**
1550         * @param componentRolesFlavour The componentRolesFlavour to set.
1551         */
1552        private void setComponentRolesFlavour(String componentRolesFlavour)
1553        {
1554            this.componentRolesFlavour = componentRolesFlavour;
1555        }
1556    
1557        /**
1558         * @return Returns the context.
1559         */
1560        private Context getContext()
1561        {
1562            return context;
1563        }
1564    
1565        /**
1566         * @return Returns the hasDynamicProxies.
1567         */
1568        private boolean hasDynamicProxies()
1569        {
1570            return this.hasDynamicProxies;
1571        }
1572    
1573        /**
1574         * @return Returns the defaultInterceptorServiceList.
1575         */
1576        private ArrayList getDefaultInterceptorServiceList()
1577        {
1578            return defaultInterceptorServiceList;
1579        }
1580    
1581        /**
1582         * @return the containers class loader
1583         */
1584        private ClassLoader getClassLoader()
1585        {
1586            return this.getClass().getClassLoader();
1587        }
1588    
1589        /**
1590         * Wait for the time configured as 'reconfigurationDelay' before
1591         * reconfiguring the container or services.
1592         */
1593        private void waitForReconfiguration()
1594        {
1595            try
1596            {
1597                Thread.sleep(this.reconfigurationDelay);
1598            }
1599            catch(InterruptedException e)
1600            {
1601                // nothing to do
1602            }
1603        }
1604    }