Re: Multiple lifecycles per container
Bert van Brakel <[email protected]> 25 Jul 2003 16:22:23 +1200
| Newsgroups | gmane.comp.java.plexus.devel |
|---|---|
| Organization | Tua Works Ltd |
| Message-ID | <1059106943.30353.3.camel@localhost> |
--=-opuB+PvQQ2sYLuPYhFxN Content-Type: text/plain Content-Transfer-Encoding: 7bit I've just put it into jira. Diffed off the cvs HEAD at round about 1600 NZ (GMT +12). I reproduce what I put in there, and attached the patch: ============== Patch to allow choice of lifecycle handler, instantiation strategy, correct singlton handling. Moved lifecycle handling from Plexus Container and into ComponentRepository, which uses pluggable LifecycleHandlers. Can specify default in plexus.conf, which can be overwritten. Components can specify which lifecycleHandler they wish to use. Some further work on InstanceMangers. Added a true pooling manager. Added a singleton instance manager which keeps the singleton alive and behaves correctly across multiple threads. Previous singlton strategy is now in ClassicSingletonInstanceManager. Instance managers are now treated differently to normal components as they shouldn't be accessible to other components, and to solve the problem of them looking themselves up. Because of this instance managers now occupy a different location in the configuration file. Added a Thread safe Map implementation. Multiple concurrent reads and locks on writes. Maybe require more extensive tests, but works so far. Used in a number of places. Added a few other classes for testing with threads and a generic pool with a sweeper, used by the poolable instance manager. Components are now given a logger named using the components class. Not sure if this is the preferred method, but at least one can now see where the log statements are coming from. To change this back edit the LogEnablePhase. Also added some more documentation to classes while figuring out how plexus works (again). I've taken the liberty to upgrade the plexus version from 0.6 to 0.6.1 in project.xml also. Maybe it should be 0.7 due to change in the configuration file. On Fri, 2003-07-25 at 15:05, Jason van Zyl wrote: > On Thu, 2003-07-24 at 19:59, Bert van Brakel wrote: > > Sorry I've been out of touch. Got caught up in one of my projects. > > > > The patch allows one to specify a default instantiation strategy and > > lifecycle handler, being capable of being overridden per component. > > > > The plexus default is an avalon lifecycle handler with the classical > > singlton, as per currently. > > > > I'll upload the patch to jira today. Haven't had time to fully write the > > tests as I was hoping, but I'll get round to it once I have a few other > > problems sorted out first. > > > > The big patch is probably not so big. Basically it's just this. > > Cool, I'll write some tests for it while I integrate the patch. > > > Anyway, see jira in a couple of hours. > > > > -bert > > > > On Fri, 2003-07-25 at 03:56, Jason van Zyl wrote: > > > Howdy, > > > > > > I'm not sure where Bert is but I think he's already done the work to do > > > this. Bert if you are around and you can separate that bit out of your > > > massive patch I will integrate that as I do think that is useful now. > > > Previously I was think of limiting a set lifecycle to a container but I > > > don't really see any downside to not allowing components to do different > > > things inside the same container. > > > > > > Which leads me into the next thing which is a little configuration > > > change that would allow a component profile of sorts. So in a profile > > > you could specify a default lifecycle and instantiation strategy for a > > > component and just use the profile id in the component configuration. As > > > well there could just be a default component profile. > > > > _______________________________________________ > > Plexus-dev mailing list > > [email protected] > > http://lists.codehaus.org/mailman/listinfo/plexus-dev --=-opuB+PvQQ2sYLuPYhFxN Content-Disposition: attachment; filename=plexus_06_to_06_1_patch.txt Content-Type: text/x-patch; name=plexus_06_to_06_1_patch.txt; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-MIME-Autoconverted: from 8bit to quoted-printable by codehaus.org id h6QMc5X06631 Index: project.xml =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/project.xml,v retrieving revision 1.10 diff -u -r1.10 project.xml --- project.xml 13 Jul 2003 18:00:53 -0000 1.10 +++ project.xml 25 Jul 2003 03:50:26 -0000 @@ -6,7 +6,7 @@ <artifactId>plexus</artifactId> <id>plexus</id> <name>plexus</name> - <currentVersion>0.6</currentVersion> + <currentVersion>0.6.1</currentVersion> <organization> <name>Apache Software Foundation</name> <url>http://jakarta.apache.org/</url> Index: src/conf/plexus.conf =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/conf/plexus.conf,v retrieving revision 1.10 diff -u -r1.10 plexus.conf --- src/conf/plexus.conf 10 May 2003 16:39:29 -0000 1.10 +++ src/conf/plexus.conf 25 Jul 2003 03:50:27 -0000 @@ -1,85 +1,135 @@ <plexus> - <logging> - <implementation>org.apache.plexus.logging.ConsoleLoggerManager</impl= ementation> - </logging> - <service-repository> - <implementation>org.apache.plexus.lifecycle.avalon.AvalonComponentRe= pository</implementation> - </service-repository> - <resource-manager> - <implementation>org.apache.plexus.classloader.DefaultResourceManager= </implementation> - </resource-manager> - <lifecycle-handler> - <id>avalon-lifecycle-handler</id> - <name>Avalon Lifecycle Handler</name> - <implementation>org.apache.plexus.lifecycle.avalon.AvalonLifecycleHa= ndler</implementation> - <start-segment> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.LogEnab= lePhase"/> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.Context= ualizePhase"/> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.Service= Phase"/> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.Configu= rePhase"/> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.Paramet= erizePhase"/> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.Initial= izePhase"/> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.StartPh= ase"/> - </start-segment> - <suspend-segment> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.Suspend= Phase"/> - </suspend-segment> - <resume-segment> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.ResumeP= hase"/> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.Reconte= xtualizePhase"/> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.Reconfi= gurePhase"/> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.Reparam= eterizePhase"/> - </resume-segment> - <end-segment> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.StopPha= se"/> - <phase implementation=3D"org.apache.plexus.lifecycle.phase.Dispose= Phase"/> - </end-segment> - </lifecycle-handler> + <logging> + <implementation>org.apache.plexus.logging.ConsoleLoggerManager</implem= entation> + </logging> + <service-repository> + <implementation>org.apache.plexus.lifecycle.avalon.AvalonComponentRepo= sitory</implementation> + </service-repository> + <resource-manager> + <implementation>org.apache.plexus.classloader.DefaultResourceManager</= implementation> + </resource-manager> + <lifecycle-handlers default=3D"avalon"> + <lifecycle-handler> + <id>avalon</id> + <name>Avalon Lifecycle Handler</name> + <implementation>org.apache.plexus.lifecycle.avalon.AvalonLifecycleHan= dler</implementation> + <start-segment> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.LogEnable= Phase" /> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.Contextua= lizePhase" /> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.ServicePh= ase" /> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.Configure= Phase" /> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.Parameter= izePhase" /> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.Initializ= ePhase" /> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.StartPhas= e" /> + </start-segment> + <suspend-segment> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.SuspendPh= ase" /> + </suspend-segment> + <resume-segment> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.ResumePha= se"/> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.Recontext= ualizePhase" /> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.Reconfigu= rePhase" /> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.Reparamet= erizePhase" /> + </resume-segment> + <end-segment> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.StopPhase= " /> + <phase implementation=3D"org.apache.plexus.lifecycle.phase.DisposePh= ase" /> + </end-segment> + </lifecycle-handler> + </lifecycle-handlers> + <instantiation-managers default=3D"singleton"> + <!-- + | + | These are the default instance managers. + | + --> + <instance-manager> + <instantiation-strategy>per-lookup</instantiation-strategy> + <description>New component instance per lookup which is disposed upon= release</description> + <role>org.apache.plexus.service.repository.instance.InstanceManager</= role> + <implementation>org.apache.plexus.service.repository.instance.PerLook= upInstanceManager</implementation> + <configuration> + </configuration> + </instance-manager> + <instance-manager> + <instantiation-strategy>poolable</instantiation-strategy> + <description>Component is pooled and only disposed when the pool gets= too big. Growable pool</description> + <role>org.apache.plexus.service.repository.instance.InstanceManager</= role> + <implementation>org.apache.plexus.service.repository.instance.Poolabl= eInstanceManager</implementation> + <configuration> + <initial-capacity>5</initial-capacity> + <sweep-interval>5</sweep-interval> + <max-capacity>30</max-capacity> + <min-capacity>5</min-capacity> + <trigger-size>20</trigger-size> + </configuration> + </instance-manager> + <instance-manager> + <instantiation-strategy>singleton</instantiation-strategy> + <description>The classic singleton manager. Once no more components a= re connected the=20 + instance is disposed</description> + <role>org.apache.plexus.service.repository.instance.InstanceManager</= role> + <implementation>org.apache.plexus.service.repository.instance.Classic= SingletonInstanceManager</implementation> + <configuration> + </configuration> + </instance-manager>=09 + <instance-manager> + <instantiation-strategy>singleton-keep-alive</instantiation-strategy> + <description>Singleton instance manager which keeps a single instance= alive until + the component repository is disposed.</description> + <role>org.apache.plexus.service.repository.instance.InstanceManager</= role> + <implementation>org.apache.plexus.service.repository.instance.KeepAli= veSingletonInstanceManager</implementation> + <configuration> + </configuration> + </instance-manager> =09 + </instantiation-managers> =20 - <!-- Default Components --> + <!-- Default Components --> =20 - <components> - <!-- + <components> + <!-- | | These are the default component factories. | --> - <component> - <role>org.apache.plexus.service.repository.factory.ComponentFactor= y</role> - <role-hint>java</role-hint> - <implementation>org.apache.plexus.service.repository.factory.JavaC= omponentFactory</implementation> - <configuration> - </configuration> - </component> + <component> + <role>org.apache.plexus.service.repository.factory.ComponentFactory</= role> + <role-hint>java</role-hint> + <implementation>org.apache.plexus.service.repository.factory.JavaComp= onentFactory</implementation> + <configuration> + </configuration> + </component> =20 - <!-- + <!-- | | These are the default instance managers. | --> - <component> - <role>org.apache.plexus.service.repository.instance.InstanceManage= r</role> - <role-hint>per-lookup</role-hint> - <implementation>org.apache.plexus.service.repository.instance.PerL= ookupInstanceManager</implementation> - <configuration> - <tag>per-lookup</tag> - </configuration> - </component> - <component> - <role>org.apache.plexus.service.repository.instance.InstanceManage= r</role> - <role-hint>poolable</role-hint> - <implementation>org.apache.plexus.service.repository.instance.Pool= ableInstanceManager</implementation> - <configuration> - <tag>poolable</tag> - </configuration> - </component> - <component> - <role>org.apache.plexus.service.repository.instance.InstanceManage= r</role> - <role-hint>singleton</role-hint> - <implementation>org.apache.plexus.service.repository.instance.Sing= letonInstanceManager</implementation> - <configuration> - <tag>poolable</tag> - </configuration> - </component> - </components> + <!-- + <component> + <role>org.apache.plexus.service.repository.instance.InstanceManager</= role> + <role-hint>per-lookup</role-hint> + <implementation>org.apache.plexus.service.repository.instance.PerLook= upInstanceManager</implementation> + <configuration> + <tag>per-lookup</tag> + </configuration> + </component> + <component> + <role>org.apache.plexus.service.repository.instance.InstanceManager</= role> + <role-hint>poolable</role-hint> + <implementation>org.apache.plexus.service.repository.instance.Poolabl= eInstanceManager</implementation> + <configuration> + <tag>poolable</tag> + </configuration> + </component> + <component> + <role>org.apache.plexus.service.repository.instance.InstanceManager</= role> + <role-hint>singleton</role-hint> + <implementation>org.apache.plexus.service.repository.instance.Singlet= onInstanceManager</implementation> + <configuration> + <tag>poolable</tag> + </configuration> + </component> + --> + </components> </plexus> Index: src/java/org/apache/plexus/DefaultPlexusContainer.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/Def= aultPlexusContainer.java,v retrieving revision 1.27 diff -u -r1.27 DefaultPlexusContainer.java --- src/java/org/apache/plexus/DefaultPlexusContainer.java 21 Jul 2003 02= :16:31 -0000 1.27 +++ src/java/org/apache/plexus/DefaultPlexusContainer.java 25 Jul 2003 03= :50:29 -0000 @@ -120,13 +120,6 @@ private Reader configurationReader; =20 /** - * Lifecycle handler for this container. One lifecycle handler per - * container is permitted. This may change in the short term to allo= w running - * components with varying lifecycles in the same container. - */ - private LifecycleHandler lifecycleHandler; - - /** * Typically Plexus will use a ClassWorld for all its class loading= and * resource requirements, but it remains to be seen if this will be= possible * in environments like j2me. We need to be able to initialize the = Plexus @@ -188,7 +181,6 @@ initializeComponentRepository(); initializeResourceManager(); initializeContext(); - initializeLifecycleHandler(); initializeSystemProperties(); } =20 @@ -233,11 +225,6 @@ // Post-initialization - can only be called post initialization // -----------------------------------------------------------------= ----- =20 - public LifecycleHandler getLifecycleHandler() - { - return lifecycleHandler; - } - public ClassLoader getClassLoader() { if ( classLoader =3D=3D null ) @@ -432,7 +419,8 @@ getConfiguration(), getLoggerManager(), this, - getClassLoader() ); + getClassLoader(), + getContext() ); =20 setComponentRepository( componentRepository ); } @@ -461,22 +449,6 @@ } =20 /**=20 - * Initialize the lifecycle handler. - */ - private void initializeLifecycleHandler() - throws Exception - { - LifecycleHandler lh =3D LifecycleHandlerFactory.create( getDefau= ltConfiguration(), - getConfigu= ration(), - getLoggerM= anager(), - getClassLo= ader(), - getContext= (), - getCompone= ntRepository() ); - - setLifecycleHandler( lh ); - } - - /**=20 * Initialize system properties. * * If the application needs to setup any system properties than they= will @@ -592,17 +564,6 @@ private void setComponentRepository( ComponentRepository componentRe= pository ) { this.componentRepository =3D componentRepository; - } - - // --[ Lifecycle Handler ]-- - - /** - * - * @param lifecycleHandler - */ - private void setLifecycleHandler( LifecycleHandler lifecycleHandler = ) - { - this.lifecycleHandler =3D lifecycleHandler; } =20 /** Index: src/java/org/apache/plexus/PlexusContainer.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/Ple= xusContainer.java,v retrieving revision 1.7 diff -u -r1.7 PlexusContainer.java --- src/java/org/apache/plexus/PlexusContainer.java 13 Jun 2003 01:08:49 = -0000 1.7 +++ src/java/org/apache/plexus/PlexusContainer.java 25 Jul 2003 03:50:29 = -0000 @@ -3,7 +3,6 @@ import com.werken.classworlds.ClassWorld; =20 import org.apache.plexus.configuration.ConfigurationResourceException; -import org.apache.plexus.lifecycle.LifecycleHandler; import org.apache.plexus.service.repository.ComponentRepository; =20 import java.io.Reader; @@ -46,9 +45,11 @@ // Post-initialization - can only be called post initialization // -----------------------------------------------------------------= ----- =20 - /** */ + /** *//* public LifecycleHandler getLifecycleHandler(); =20 + + public LifecycleHandler getLifecycleHandler(String id);*/ /** */ public ClassLoader getClassLoader(); =20 Index: src/java/org/apache/plexus/lifecycle/AbstractLifecycleHandler.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/lif= ecycle/AbstractLifecycleHandler.java,v retrieving revision 1.5 diff -u -r1.5 AbstractLifecycleHandler.java --- src/java/org/apache/plexus/lifecycle/AbstractLifecycleHandler.java 1 = May 2003 19:35:36 -0000 1.5 +++ src/java/org/apache/plexus/lifecycle/AbstractLifecycleHandler.java 25= Jul 2003 03:50:30 -0000 @@ -1,8 +1,9 @@ package org.apache.plexus.lifecycle; =20 +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.plexus.lifecycle.phase.Phase; import org.apache.plexus.logging.AbstractLogEnabled; -import org.apache.plexus.service.repository.ComponentManager; import org.apache.plexus.service.repository.ComponentHousing; =20 import java.util.ArrayList; @@ -20,7 +21,8 @@ private List suspendSegment; private List resumeSegment; private List endSegment; - + private Configuration configuration; +=09 public AbstractLifecycleHandler() { beginSegment =3D new ArrayList(); @@ -162,4 +164,21 @@ phase.execute( housing, this ); } } + =20 + /** + * @see org.apache.plexus.lifecycle.LifecycleHandler#configure(org.apac= he.avalon.framework.configuration.Configuration) + */ + public void configure(Configuration config) throws ConfigurationExcepti= on + { + this.configuration =3D config; + + } + + /** + * @return + */ + public Configuration getConfiguration() + { + return configuration; + } } Index: src/java/org/apache/plexus/lifecycle/LifecycleHandler.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/lif= ecycle/LifecycleHandler.java,v retrieving revision 1.4 diff -u -r1.4 LifecycleHandler.java --- src/java/org/apache/plexus/lifecycle/LifecycleHandler.java 1 May 2003= 19:35:36 -0000 1.4 +++ src/java/org/apache/plexus/lifecycle/LifecycleHandler.java 25 Jul 200= 3 03:50:30 -0000 @@ -1,11 +1,19 @@ package org.apache.plexus.lifecycle; =20 +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.logger.Logger; import org.apache.plexus.lifecycle.phase.Phase; import org.apache.plexus.service.repository.ComponentHousing; =20 + import java.util.Map; =20 +/** + * Takes a component through it's lifecycle. + *=20 + *=20 + */ public interface LifecycleHandler { /** */ @@ -17,8 +25,12 @@ =20 /** Set lifecycle specifics. * - * The lifecycle of a particular service may vary from implementati= on - * to implementation + * <p>The lifecycle of a particular service may vary from implement= ation + * to implementation.</p> + *=20 + * <p>These entities are made available to the various phases, are a= re global + * to the Lifecycel handler (no component specific stuff in here)</p= > + *=20 */ void addEntity( String key, Object entity ); =20 @@ -48,4 +60,7 @@ void addEndSegmentPhase( Phase phase ); =20 void enableLogging( Logger logger ); + =20 + public void configure(Configuration config) throws ConfigurationExce= ption; + =20 } Index: src/java/org/apache/plexus/lifecycle/LifecycleHandlerFactory.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/lif= ecycle/LifecycleHandlerFactory.java,v retrieving revision 1.5 diff -u -r1.5 LifecycleHandlerFactory.java --- src/java/org/apache/plexus/lifecycle/LifecycleHandlerFactory.java 1 M= ay 2003 19:35:36 -0000 1.5 +++ src/java/org/apache/plexus/lifecycle/LifecycleHandlerFactory.java 25 = Jul 2003 03:50:30 -0000 @@ -1,6 +1,7 @@ package org.apache.plexus.lifecycle; =20 import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.context.Context; import org.apache.plexus.factory.AbstractPlexusFactory; import org.apache.plexus.lifecycle.phase.Phase; @@ -10,7 +11,7 @@ public class LifecycleHandlerFactory extends AbstractPlexusFactory { - public static LifecycleHandler create( Configuration defaultConfigur= ation, + /* public static LifecycleHandler create( Configuration defaultConfig= uration, Configuration configuration, LoggerManager loggerManager, ClassLoader classLoader, @@ -64,5 +65,78 @@ lh.initialize(); =20 return lh; - } + }*/ + =20 + /** + * Return a new a LifecycleHandlerHousing, with an instantiated and= initialized=20 + * Lifecyclehandler=20 + *=20 + * @param config + * @param loggerManager + * @param classLoader + * @param context + * @param componentRepository + * @return + * @throws Exception + */ + public static LifecycleHandlerHousing createLifecycleHandlerHousing( Co= nfiguration config, + LoggerManager loggerManager, + ClassLoader classLoader, + Context context, + ComponentRepository componentRepository ) + throws Exception + { + LifecycleHandlerHousing housing =3D new LifecycleHandlerHousing(); + =09 + String implementation =3D config.getChild( "implementation" ).getValue= ( null ); + if( implementation =3D=3D null) + { + throw new ConfigurationException("No lifecycle implementation"); + } + String id =3D config.getChild("id").getValue(null); + if( id =3D=3D null ) + { + throw new ConfigurationException("No role specified for lifecycle han= dler"); + } + =09 + housing.setImplementation(implementation); + housing.setId(id); + housing.setConfiguration( config ); + LifecycleHandler lh =3D (LifecycleHandler) getInstance( implementation= , classLoader ); + + // Setup logging for the lifecycle handler. Not used by components + lh.enableLogging( loggerManager.getLogger( "lifecycle-handler:" + id )= ); + + Configuration[] a =3D config.getChild( "start-segment" ).getChildren( = "phase" ); + for ( int i =3D 0; i < a.length; i++ ) + { + lh.addBeginSegmentPhase( + (Phase) getInstance( a[i].getAttribute( "implementation" ), classLoa= der ) ); + } + + Configuration[] b =3D config.getChild( "end-segment" ).getChildren( "p= hase" ); + for ( int i =3D 0; i < b.length; i++ ) + { + lh.addEndSegmentPhase( + (Phase) getInstance( b[i].getAttribute( "implementation" ), classLoa= der ) ); + } + + // Add some standard entities to the lifecycle handler. The lifecycle + // handler may wish to use some of these entities to create new types + // of entities for its lifecycle phases. For example the AvalonLifecyc= leHandler + // uses the ServiceRepository and adapts it to create an Avalon Servic= eManager. + // The entities MUST be added before initialization of the lifecycleha= ndler. + lh.addEntity( LifecycleHandler.LOGGER, loggerManager.getRootLogger() )= ; + lh.addEntity( LifecycleHandler.CONTEXT, context ); + lh.addEntity( LifecycleHandler.SERVICE_REPOSITORY, componentRepository= ); + + // Initialize the lifecycle handler before returning the instance. + lh.configure(config.getChild("configuration")); + lh.initialize(); + =09 + //wrap the handler in an immutable wrapper. THis is so components can'= t modify it + housing.setHandler(lh); + =09 + return housing; + } } Index: src/java/org/apache/plexus/lifecycle/LifecycleHandlerHousing.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/java/org/apache/plexus/lifecycle/LifecycleHandlerHousing.ja= va diff -N src/java/org/apache/plexus/lifecycle/LifecycleHandlerHousing.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/java/org/apache/plexus/lifecycle/LifecycleHandlerHousing.java 25 = Jul 2003 03:50:31 -0000 @@ -0,0 +1,116 @@ +package org.apache.plexus.lifecycle; + +import org.apache.avalon.framework.configuration.Configuration; + + /** + * Holds a LifecycleHandler. + *=20 + * <p>Created on 19/07/2003</p> + * + * @author <a href=3D"mailto:[email protected]">Bert van Brakel</a> + * @version $Revision$ + */ +public class LifecycleHandlerHousing +{ + /** + * LifecycleHandler instance.=20 + */ + private LifecycleHandler handler; +=09 + /** + * Configuration for the lifecycle handler + */ + private Configuration configuration; +=09 + /** + * Lifecycle Handler implementation + */ + private String implementation; +=09 + /** Unique id for the held LifecycleHandler type. This id is used by + * components to specify their lifecycle handler.*/ + private String id; +=09 + /** Used by humans?*/ + private String name; + /** + * @return + */ + public Configuration getConfiguration() + { + return configuration; + } + + /** + * @return + */ + public LifecycleHandler getHandler() + { + return handler; + } + + /** + * @return + */ + public String getId() + { + return id; + } + + /** + * @return + */ + public String getImplementation() + { + return implementation; + } + + /** + * @param configuration + */ + public void setConfiguration(Configuration configuration) + { + this.configuration =3D configuration; + } + + /** + * @param handler + */ + public void setHandler(LifecycleHandler handler) + { + this.handler =3D handler; + } + + /** + * @param string + */ + public void setId(String id) + { + this.id =3D id; + } + + /** + * @param string + */ + public void setImplementation(String impl) + { + implementation =3D impl; + } + + /** + * @return + */ + public String getName() + { + return name; + } + + /** + * @param string + */ + public void setName(String name) + { + this.name =3D name; + } + +} Index: src/java/org/apache/plexus/lifecycle/phase/LogEnablePhase.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/lif= ecycle/phase/LogEnablePhase.java,v retrieving revision 1.2 diff -u -r1.2 LogEnablePhase.java --- src/java/org/apache/plexus/lifecycle/phase/LogEnablePhase.java 1 May = 2003 19:35:36 -0000 1.2 +++ src/java/org/apache/plexus/lifecycle/phase/LogEnablePhase.java 25 Jul= 2003 03:50:31 -0000 @@ -21,7 +21,8 @@ final String message =3D "logger is null"; throw new IllegalArgumentException( message ); } - ( (LogEnabled) object ).enableLogging( logger ); + //give a new child logger named by the components class + ( (LogEnabled) object ).enableLogging( logger.getChildLogger= (object.getClass().getName()) ); } } } Index: src/java/org/apache/plexus/service/repository/ComponentDescriptor.= java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/ser= vice/repository/ComponentDescriptor.java,v retrieving revision 1.2 diff -u -r1.2 ComponentDescriptor.java --- src/java/org/apache/plexus/service/repository/ComponentDescriptor.jav= a 10 May 2003 16:39:30 -0000 1.2 +++ src/java/org/apache/plexus/service/repository/ComponentDescriptor.jav= a 25 Jul 2003 03:50:32 -0000 @@ -93,6 +93,9 @@ =20 /** Instantiation strategy. */ private String instantiationStrategy; + =20 + /** Which lifecyclehandler to use. If null, use the containers defau= lt one. */ + private String lifecycleHandlerId; =20 // -----------------------------------------------------------------= ----- // Constructors @@ -252,4 +255,22 @@ { return parameters; } + /** + * @return + */ + public String getLifecycleHandlerId() + { + return lifecycleHandlerId; + } + + /** + * Set the id of the lifecycle handler the component uses + *=20 + * @param string + */ + public void setLifecycleHandlerId(String id) + { + lifecycleHandlerId =3D id; + } + } Index: src/java/org/apache/plexus/service/repository/ComponentHousing.jav= a =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/ser= vice/repository/ComponentHousing.java,v retrieving revision 1.1 diff -u -r1.1 ComponentHousing.java --- src/java/org/apache/plexus/service/repository/ComponentHousing.java 1= May 2003 19:35:36 -0000 1.1 +++ src/java/org/apache/plexus/service/repository/ComponentHousing.java 2= 5 Jul 2003 03:50:32 -0000 @@ -1,7 +1,8 @@ package org.apache.plexus.service.repository; =20 /** - * + * Holds the actual instantiated component + * =20 *=20 * @author <a href=3D"mailto:[email protected]">Jason van Zyl</a> * @@ -9,15 +10,15 @@ */ public class ComponentHousing { - /** Component Manager that oversees this intance. */ + /** Component Manager that oversees this instance. */ private ComponentManager componentManager; =20 /** The component being housed. */ private Object component; =20 /** How many clients are connected to this component. */ - private int connections; - + //private int connections; +=09 // -----------------------------------------------------------------= ----- // Accessors // -----------------------------------------------------------------= ----- @@ -32,7 +33,7 @@ this.component =3D component; } =20 - public int getConnections() + /* public int getConnections() { return connections; } @@ -40,9 +41,9 @@ public void setConnections( int connections ) { this.connections =3D connections; - } + }*/ =20 - public ComponentManager getComponentManager() + public ComponentManager getComponentManager() { return componentManager; } Index: src/java/org/apache/plexus/service/repository/ComponentManager.jav= a =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/ser= vice/repository/ComponentManager.java,v retrieving revision 1.2 diff -u -r1.2 ComponentManager.java --- src/java/org/apache/plexus/service/repository/ComponentManager.java 1= 2 May 2003 18:57:22 -0000 1.2 +++ src/java/org/apache/plexus/service/repository/ComponentManager.java 2= 5 Jul 2003 03:50:32 -0000 @@ -1,9 +1,18 @@ package org.apache.plexus.service.repository; =20 -import org.apache.avalon.framework.service.ServiceException; +import org.apache.plexus.lifecycle.LifecycleHandler; +import org.apache.plexus.lifecycle.UndefinedLifecycleHandlerException; import org.apache.plexus.service.repository.instance.InstanceManager; =20 -/** House the information for a single instantiated service. +import com.werken.classworlds.ConfigurationException; + +/**=20 + * House the information for a component + * and the instance manager which performs the=20 + * management of this component on behalf of this=20 + * ComponentManager. + *=20 + * <p>This is used so that the instance managers can be pluggable</p> * */ public class ComponentManager @@ -20,10 +29,11 @@ private ComponentRepository componentRespository; =20 /** Constuctor. */ - public ComponentManager( ComponentDescriptor componentDescriptor, - ComponentRepository componentRepository, - ComponentDescriptor instanceManagerDescript= or, - ClassLoader classLoader ) + public ComponentManager( + ComponentDescriptor componentDescriptor, + ComponentRepository componentRepository, + ComponentDescriptor instanceManagerDescriptor, + ClassLoader classLoader) { this.componentDescriptor =3D componentDescriptor; this.componentRespository =3D componentRepository; @@ -35,14 +45,39 @@ // Lifecylce Management // -----------------------------------------------------------------= ----- =20 - public void initialize() - throws Exception + public void initialize() throws Exception { - Class c =3D classLoader.loadClass( instanceManagerDescriptor.get= Implementation() ); + Class c =3D classLoader.loadClass(instanceManagerDescriptor.getI= mplementation()); instanceManager =3D (InstanceManager) c.newInstance(); - instanceManager.setClassLoader( classLoader ); - instanceManager.setImplementation( componentDescriptor.getImplem= entation() ); - instanceManager.setComponentManager( this ); + instanceManager.setClassLoader(classLoader); + instanceManager.setComponentImplementation(componentDescriptor.g= etImplementation()); + instanceManager.setComponentManager( this ); + //the lifecyclehandler used is based on the component descriptor= =20 + //look it up from the component repository + String id =3D componentDescriptor.getLifecycleHandlerId(); + if (id =3D=3D null) + { + //use the default handler + instanceManager.setLifecycleHandler( + getComponentRespository().getDefaultLifecycleHandler()); + } + else + { + LifecycleHandler lh; + try + { + lh =3D getComponentRespository().getLifecycleHandler(id)= ; + } + catch (UndefinedLifecycleHandlerException e) + { + throw new ConfigurationException( + "No LifecycleHandler confgured with id:" + + id + + " required by component with role:" + + componentDescriptor.getRole()); + } + instanceManager.setLifecycleHandler(lh); + } instanceManager.initialize(); } =20 @@ -77,39 +112,69 @@ return componentRespository; } =20 + /** + * + * @param componentRespository + */ + public void setComponentRespository( ComponentRepository componentRespo= sitory ) + { + this.componentRespository =3D componentRespository; + } + /** - * - * @param componentRespository + * Release the component back to this manager.=20 + *=20 + * @param component */ - public void setComponentRespository( ComponentRepository componentRe= spository ) + public void release(Object component) { - this.componentRespository =3D componentRespository; + if (component !=3D null) + { + getInstanceManager().release(component); + } } =20 /** - * + * Obtain the component this manager manages. + *=20 * @return */ - public ComponentHousing getComponentHousing() - throws ServiceException + public Object getComponent() throws Exception + { + return getInstanceManager().getComponent(); + } + /** + * + * @return + *//* + public ComponentHousing getComponentHousing() throws ServiceExceptio= n { try { return getInstanceManager().getInstance(); } - catch ( Exception e ) + catch (Exception e) { - throw new ServiceException( "instance-manager", e.getMessage= (), e ); + throw new ServiceException("instance-manager", e.getMessage(= ), e); } - } + }*/ =20 - public InstanceManager getInstanceManager() + private InstanceManager getInstanceManager() { return instanceManager; } =20 - public void setInstanceManager( InstanceManager instanceManager ) + /* public void setInstanceManager( InstanceManager instanceManager= ) + { + this.instanceManager =3D instanceManager; + }*/ + + /** + * Dispose this manager. This will also cause all components this ma= nager=20 + * manages to be disposed. + */ + public void dispose() { - this.instanceManager =3D instanceManager; + getInstanceManager().dispose(); } } Index: src/java/org/apache/plexus/service/repository/ComponentRepository.= java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/ser= vice/repository/ComponentRepository.java,v retrieving revision 1.2 diff -u -r1.2 ComponentRepository.java --- src/java/org/apache/plexus/service/repository/ComponentRepository.jav= a 12 May 2003 18:57:22 -0000 1.2 +++ src/java/org/apache/plexus/service/repository/ComponentRepository.jav= a 25 Jul 2003 03:50:33 -0000 @@ -1,42 +1,115 @@ package org.apache.plexus.service.repository; =20 import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.context.Context; import org.apache.avalon.framework.logger.Logger; import org.apache.avalon.framework.service.ServiceException; import org.apache.plexus.PlexusContainer; - -public interface ComponentRepository -{ - void configure( Configuration defaultConfiguration, Configuration co= nfiguration ); - - void initialize() - throws Exception; - - Object lookup( String role ) - throws ServiceException; - - Object lookup( String role, String id ) - throws ServiceException; - - boolean hasService( String role ); - - boolean hasService( String role, String id ); - - void release( Object service ); - - void dispose(); - - void setPlexusContainer( PlexusContainer container ); - - // Information - - int configuredComponents(); - - int instantiatedComponents(); - - ClassLoader getClassLoader(); - - void enableLogging( Logger logger ); - - void startComponentLifecycle( ComponentHousing housing ); +import org.apache.plexus.lifecycle.LifecycleHandler; +import org.apache.plexus.lifecycle.UndefinedLifecycleHandlerException; +import org.apache.plexus.logging.LoggerManager; + +/** + * Like the avalon service manager. Central point to get the components = from. + * + * + */ +public interface ComponentRepository { + void configure( + Configuration defaultConfiguration, + Configuration configuration); + + void contextualize(Context context); + /** + * Initialize this repository + * @throws Exception + */ + void initialize() throws Exception; +=09 + /** + * Lookup the component with the given role + *=20 + * @param role + * @return + * @throws ServiceException if no component with the given role exists,= or there was an + * error taking the component through a lifecycle + */ + Object lookup(String role) throws ServiceException; + + Object lookup(String role, String id) throws ServiceException; + + /** + * Test if this repository manages the component with the given role + *=20 + * @param role + * @return + */ + boolean hasService(String role); + + /** + * Test if this repository manages the component with the given role + * and id + *=20 + * @param role + * @return + */ + boolean hasService(String role, String id); + + void release(Object service); + + /** + * Dispose of this Repository + * + */ + void dispose(); + + void setPlexusContainer(PlexusContainer container); + + // Information + + /** + * Return the number of configured components + */ + int configuredComponents(); + + /** + * Return the number of instantiated components + * @return + */ + int instantiatedComponents(); + + ClassLoader getClassLoader(); + + /** Set this repositories logger */ + void enableLogging(Logger logger); +=09 + /** Set the logManager to be used for components */ + void setComponentLogManager(LoggerManager logManager); + /** + * Start the lifecycle for the component in this housing + *=20 + * @param housing + */ + //void startComponentLifecycle(ComponentHousing housing); +=09 + /** + * Return the lifecycle handler with the given id. Throws exception if = no lifecycle + * handler with the given id exists.=20 + *=20 + * <p>Note: it is recommended the returned handler is immutable</p> + *=20 + * @param id + * @return + */ + LifecycleHandler getLifecycleHandler(String id) throws UndefinedLifecy= cleHandlerException; +=09 + /** + * Return the default lifecycle handler. This is the handler used for c= omponents=20 + * which don't specify a handler. + *=20 + * <p>Note: it is recommended the returned handler is immutable</p> + *=20 + * @return + */ + LifecycleHandler getDefaultLifecycleHandler(); } Index: src/java/org/apache/plexus/service/repository/ComponentRepositoryF= actory.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/ser= vice/repository/ComponentRepositoryFactory.java,v retrieving revision 1.2 diff -u -r1.2 ComponentRepositoryFactory.java --- src/java/org/apache/plexus/service/repository/ComponentRepositoryFact= ory.java 31 May 2003 18:13:13 -0000 1.2 +++ src/java/org/apache/plexus/service/repository/ComponentRepositoryFact= ory.java 25 Jul 2003 03:50:33 -0000 @@ -1,6 +1,7 @@ package org.apache.plexus.service.repository; =20 import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.context.Context; import org.apache.plexus.PlexusContainer; import org.apache.plexus.factory.AbstractPlexusFactory; import org.apache.plexus.logging.LoggerManager; @@ -12,7 +13,8 @@ Configuration configuratio= n, LoggerManager loggerManage= r, PlexusContainer container, - ClassLoader classLoader ) + ClassLoader classLoader, + Context context ) throws Exception { String implementation; @@ -31,8 +33,9 @@ =20 ComponentRepository sr =3D (ComponentRepository) getInstance( implementation, classLoad= er ); - + sr.setComponentLogManager(loggerManager); sr.enableLogging( loggerManager.getLogger( "service-repository" = ) ); + sr.contextualize(context); sr.setPlexusContainer( container ); sr.configure( defaultConfiguration, configuration ); sr.initialize(); Index: src/java/org/apache/plexus/service/repository/DefaultComponentRepo= sitory.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/ser= vice/repository/DefaultComponentRepository.java,v retrieving revision 1.7 diff -u -r1.7 DefaultComponentRepository.java --- src/java/org/apache/plexus/service/repository/DefaultComponentReposit= ory.java 12 Jun 2003 18:08:32 -0000 1.7 +++ src/java/org/apache/plexus/service/repository/DefaultComponentReposit= ory.java 25 Jul 2003 03:50:36 -0000 @@ -1,49 +1,79 @@ package org.apache.plexus.service.repository; =20 import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.context.Context; import org.apache.avalon.framework.service.ServiceException; import org.apache.plexus.PlexusContainer; import org.apache.plexus.lifecycle.LifecycleHandler; +import org.apache.plexus.lifecycle.LifecycleHandlerFactory; +import org.apache.plexus.lifecycle.LifecycleHandlerHousing; import org.apache.plexus.lifecycle.UndefinedLifecycleHandlerException; import org.apache.plexus.logging.AbstractLogEnabled; -import org.apache.plexus.service.repository.instance.InstanceManager; +import org.apache.plexus.logging.LoggerManager; +import org.apache.plexus.util.ThreadSafeMap; +import org.apache.plexus.util.Tracer; =20 import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import java.util.Set; =20 /** - * @todo find appropriate lifecycle handler + *=20 */ -public class DefaultComponentRepository - extends AbstractLogEnabled - implements ComponentRepository +public class DefaultComponentRepository extends AbstractLogEnabled imple= ments ComponentRepository { + // -----------------------------------------------------------------= ----- // Constants // -----------------------------------------------------------------= ----- =20 /** Components tag. */ - private static String COMPONENTS =3D "components"; + private static final String COMPONENTS =3D "components"; + /** LifecycleHandlers tag. */ + private static final String LIFECYCLE_HANDLERS =3D "lifecycle-handle= rs"; + /** InstanceManagers tag. */ + private static final String INSTANCE_MANAGERS =3D "instantiation-man= agers"; + /** A InstanceManager tag. */ + private static final String INSTANCE_MANAGER =3D "instance-manager"; /** Component tag. */ - private static String COMPONENT =3D "component"; + private static final String COMPONENT =3D "component"; /** Id tag. */ - private static String ID =3D "id"; + private static final String ID =3D "id"; /** Role tag. */ - private static String ROLE =3D "role"; + private static final String ROLE =3D "role"; /** Role tag. */ - private static String ROLE_HINT =3D "role-hint"; + private static final String ROLE_HINT =3D "role-hint"; /** Implementation tag. */ - private static String IMPLEMENTATION =3D "implementation"; - /** Configuration tag. */ - private static String INSTANTIATION_STRATEGY =3D "instantiation-stra= tegy"; + private static final String IMPLEMENTATION =3D "implementation"; + /** Configuration tag used by the components to indicate their prefe= rred instantiation + * strategy. */ + private static final String INSTANTIATION_STRATEGY =3D "instantiatio= n-strategy"; + /** Configuration tag used by the components to indicate their lifecycl= e type. */ + private static final String LIFECYCLE_HANDLER =3D "lifecycle-handler= "; /** Configuration tag. */ - private static String CONFIGURATION =3D "configuration"; + private static final String CONFIGURATION =3D "configuration"; + + /** Object to lock on when creating a new componentManager during + * component lookup. Seperate from enclosing class as we have no + * control on what locks calling code places*/ + private Object lookupLock =3D new Object(); + + /** + * Lifecycle handler used if none is specified for a component. + */ + private LifecycleHandler defaultLifecycleHandler; + /** Holds the various instantiated lifecycle handlers. Keyed by id = (eg 'avalon')*/ + private Map lifecycleHandlers; =20 - // The instantiation strategies will be broken out into separate cla= sses so - // breath easy :-) + /** + * Instantiation strategy used if none specified. + */ + private String defaultInstantiationStrategy; =20 + /** + * Some default instantiation strategies + */ protected static String PER_LOOKUP_STRATEGY =3D "per-lookup"; protected static String POOLABLE_STRATEGY =3D "poolable"; protected static String SINGLETON_STRATEGY =3D "singleton"; @@ -61,25 +91,44 @@ /** Map of service descriptors keyed by role. */ private Map componentDescriptors; =20 - /** Map of component managers by component key. */ + /** Map of component managers by component key. Needs to be=20 + * threadSafe with lots of reads, small number of writes.*/ private Map componentManagers; =20 - /** Map of service capsules key by the service object. */ - private Map componentHousings; + /** Map of ComponentManagers keyed by component class. Use a Map + * which can handle concurrent reads and writes. Will be about + * the same number of reads as writes + */ + private Map compManagersByCompClass; + + /** Map of component housings keyed by the component object. */ + //private Map componentHousings; =20 private PlexusContainer plexusContainer; =20 + /** Parent containers context */ + private Context context; + + private LoggerManager loggerManager; + + /** The instance manager descriptors. Seperate from the other=20 + * components as they shouldn't have access to them. Keyed + * by instantiation strategy*/ + private Map instanceManagerDescriptors; + /** Constructor. */ public DefaultComponentRepository() { componentDescriptors =3D new HashMap(); - componentManagers =3D new HashMap(); - componentHousings =3D new HashMap(); + instanceManagerDescriptors =3D new HashMap(); + componentManagers =3D new ThreadSafeMap(); + //componentHousings =3D new HashMap(); + compManagersByCompClass =3D new ThreadSafeMap(); + lifecycleHandlers =3D new HashMap(); } =20 // take the lifecycle handler stuff out of here =20 - // -----------------------------------------------------------------= ----- // Lifecylce Management // -----------------------------------------------------------------= ----- @@ -98,27 +147,91 @@ * * @throws Exception */ - public void initialize() - throws Exception + public void initialize()=20 + throws Exception { + initializeLifecycleHandlers(); + initializeInstanceManagers(); + initializeComponentDescriptors(); + } + + /** + * Grab all the component descriptors from the configuration and + * make them available during lookup + *=20 + * @throws Exception + */ + public void initializeComponentDescriptors() + throws Exception + { + Configuration[] defaultComponentConfigurations =3D + defaultConfiguration.getChild( COMPONENTS ).getChildren( COMPONENT ); + + for ( int i =3D 0; i < defaultComponentConfigurations.length; i++ ) + { + addComponentDescriptor( createComponentDescriptor( defaultComponentCo= nfigurations[i] ) ); + } + + Configuration[] componentConfigurations =3D + configuration.getChild( COMPONENTS ).getChildren( COMPONENT ); + + for ( int i =3D 0; i < componentConfigurations.length; i++ ) + { + addComponentDescriptor( createComponentDescriptor( componentConfigura= tions[i] ) ); + } + + } + + /** + * Grab all the InstanceManager configurations and make them available=20 + * during lookup + *=20 + * @throws Exception + */ + private void initializeInstanceManagers()=20 + throws Exception + { + + + =09 Configuration[] defaultComponentConfigurations =3D - defaultConfiguration.getChild( COMPONENTS ).getChildren( COM= PONENT ); + defaultConfiguration.getChild( INSTANCE_MANAGERS ).getChildr= en( INSTANCE_MANAGER ); =20 for ( int i =3D 0; i < defaultComponentConfigurations.length; i+= + ) { - addComponentDescriptor( createComponentDescriptor( defaultCo= mponentConfigurations[i] ) ); + addInstanceManagerDescriptor( + createComponentDescriptor( defaultComponentConfiguration= s[i] ) ); } =20 Configuration[] componentConfigurations =3D - configuration.getChild( COMPONENTS ).getChildren( COMPONENT = ); + configuration.getChild( INSTANCE_MANAGERS ).getChildren( INS= TANCE_MANAGER ); =20 - for ( int i =3D 0; i < componentConfigurations.length; i++ ) + for (int i =3D 0; i < componentConfigurations.length; i++) { - addComponentDescriptor( createComponentDescriptor( component= Configurations[i] ) ); + addInstanceManagerDescriptor( createComponentDescriptor( com= ponentConfigurations[i] ) ); } - + =20 + defaultInstantiationStrategy =3D + getConfiguration().getChild(INSTANCE_MANAGERS).getAttribute( + "default", + getDefaultConfiguration().getChild(INSTANCE_MANAGERS).getAttribute( + "default", + null)); + =09 + if ( defaultInstantiationStrategy =3D=3D null || defaultInstantiationS= trategy.length()=3D=3D0) + { + throw new ConfigurationException("No default instantiation strate= gy defined"); + } + if( false =3D=3D getInstanceManagerDescriptors().containsKey(defaultIn= stantiationStrategy)) + { + throw new ConfigurationException( + "The default instantiation strategy is specified as: '" + + defaultInstantiationStrategy + + "' but no InstanceManager" + + " with this id is defined"); =20 + } + getLogger().info("Default instantiation strategy set to: '" + defaultI= nstantiationStrategy + "'"); =09 } - // -----------------------------------------------------------------= ----- // Accessors // -----------------------------------------------------------------= ----- @@ -155,11 +268,106 @@ return getComponentDescriptors().size(); } =20 + /** + * @todo correct this + * @see org.apache.plexus.service.repository.ComponentRepository#ins= tantiatedComponents() + */ public int instantiatedComponents() { + //this is no longer correct. Each manager could + //be managing multiple instances. Should sum + //the number of component managers active=20 + //connections return getComponentManagers().size(); } =20 + /**=20 + *Adds all the lifecycle handlers and initializes them. Sets up the = default lifecycle handler + */ + private void initializeLifecycleHandlers()=20 + throws Exception + { + String defaultHandlerId =3D + getConfiguration().getChild(LIFECYCLE_HANDLERS).getAttribute= ( + "default", + getDefaultConfiguration().getChild(LIFECYCLE_HANDLERS).g= etAttribute( + "default", + null)); + + if (defaultHandlerId =3D=3D null) + { + throw new ConfigurationException("No default lifecycle handl= er defined"); + } + =20 + Configuration[] configs =3D + getConfiguration().getChild(LIFECYCLE_HANDLERS).getChildren(= LIFECYCLE_HANDLER); + Configuration[] defaults =3D + getDefaultConfiguration().getChild(LIFECYCLE_HANDLERS).getCh= ildren(LIFECYCLE_HANDLER); + for (int i =3D 0; i < configs.length; i++) + { + addLifecycleHandlerHousing(configs[i], false); + } + for (int i =3D 0; i < defaults.length; i++) + { + //ignore duplicates as we allow the custom configuration + //to override default handlers + addLifecycleHandlerHousing(defaults[i], true); + } + + //grab the default LifecycleHandler. This is the one used when c= omponents don't specify + //one + LifecycleHandlerHousing housing =3D + (LifecycleHandlerHousing) lifecycleHandlers.get(defaultHandl= erId); + if (housing =3D=3D null) + { + throw new ConfigurationException( + "The default LifecycleHandler is specified as: " + + defaultHandlerId + + " but no LifecycleHandler" + + " of this id is defined"); + + } + defaultLifecycleHandler =3D housing.getHandler(); + getLogger().info("Default LifecycleHandler id is set to: '" + defaultH= andlerId + "'"); + } + /** + * Add a LifecycleHandler to this container. + *=20 + * @param config + * @param ignoreDuplicates if duplicate handlers should be quitely i= gnored + * @throws Exception + */ + void addLifecycleHandlerHousing(Configuration config, boolean ignore= Duplicates) + throws Exception + { + LifecycleHandlerHousing housing =3D + LifecycleHandlerFactory.createLifecycleHandlerHousing( + config, + getComponnetLogManager(), + getClassLoader(), + getContext(), + this); + if (lifecycleHandlers.containsKey(housing.getId()) =3D=3D false) + { + getLogger().info( + "Adding Lifecyclehandler. id=3D" + + housing.getId() + + ", impl=3D" + + housing.getImplementation()); + lifecycleHandlers.put(housing.getId(), housing); + } + else + { + if (ignoreDuplicates =3D=3D false) + { + + throw new ConfigurationException( + "Duplicate Lifecycle handler. Duplicate id: " + hous= ing.getId()); + } + } + + } + // -----------------------------------------------------------------= ----- // Package Scoped Accessors // -----------------------------------------------------------------= ----- @@ -190,35 +398,56 @@ /** * * @return - */ + *//* Map getComponentHousings() { return componentHousings; - } + }*/ =20 // -----------------------------------------------------------------= ----- // Component Descriptor processing and Holder creation. // -----------------------------------------------------------------= ----- =20 /** - * + * Create a new ComponentManager with the correct InstanceManager fo= r the + * component specified by the given descriptor. The ComponentManager + * will select the correct LifecycleHandler based on the descriptor + *=20 * @return The new component instance. * * @throws Exception If an error occurs while attempting to locate * the class or instantiate the component object. */ - ComponentManager instantiateComponentManager( ComponentDescriptor de= scriptor ) - throws Exception + ComponentManager instantiateComponentManager( ComponentDescriptor de= scriptor )=20 + throws Exception { - ComponentDescriptor instantiationManagerDescriptor =3D (Componen= tDescriptor) - getComponentDescriptors().get( InstanceManager.ROLE + descri= ptor.getInstantiationStrategy() ); + ComponentDescriptor instantiationManagerDescriptor; + String strategy =3D descriptor.getInstantiationStrategy(); + //don=CB=88t want a 'ROLE#null' lookup + if ( strategy =3D=3D null) + { + strategy =3D defaultInstantiationStrategy; + } =20 + instantiationManagerDescriptor =3D + (ComponentDescriptor) getInstanceManagerDescriptors().ge= t(strategy); =20 - ComponentManager componentManager =3D new ComponentManager( desc= riptor, - this, - instan= tiationManagerDescriptor, - getCla= ssLoader() ); - componentManager.initialize(); + if (instantiationManagerDescriptor =3D=3D null) + { + throw new ConfigurationException( + "No instance manager configured with strategy: " + + strategy + + " for component with role: " + + descriptor.getRole()); + } + ComponentManager componentManager =3D + new ComponentManager( + descriptor, + this, + instantiationManagerDescriptor, + getClassLoader()); =20 + componentManager.initialize(); + //make the ComponentManager available for future requests getComponentManagers().put( descriptor.getComponentKey(), compon= entManager ); =20 return componentManager; @@ -231,24 +460,30 @@ * @return * @throws Exception */ - ComponentDescriptor createComponentDescriptor( Configuration configu= ration ) - throws Exception + ComponentDescriptor createComponentDescriptor( Configuration configu= ration )=20 + throws Exception { ComponentDescriptor componentDescriptor =3D new ComponentDescrip= tor(); =20 - componentDescriptor.setRole( configuration.getChild( ROLE ).getV= alue() ); + componentDescriptor.setRole( configuration.getChild( ROLE ).getV= alue()); componentDescriptor.setRoleHint( configuration.getChild( ROLE_HI= NT ).getValue( null ) ); componentDescriptor.setImplementation( configuration.getChild( I= MPLEMENTATION ).getValue() ); componentDescriptor.setId( configuration.getChild( ID ).getValue= ( null ) ); =20 componentDescriptor.setInstantiationStrategy( - configuration.getChild( INSTANTIATION_STRATEGY ).getValue( S= INGLETON_STRATEGY ) ); - + configuration.getChild( INSTANTIATION_STRATEGY ).getValue( n= ull ) ); + componentDescriptor.setLifecycleHandlerId( + configuration.getChild( LIFECYCLE_HANDLER ).getValue( null )= ); componentDescriptor.setConfiguration( configuration.getChild( CO= NFIGURATION ) ); =20 return componentDescriptor; } =20 + Map getInstanceManagerDescriptors() + { + return instanceManagerDescriptors; + } + /** * Adds a component to the ServiceBroker. If the component has a * ServiceSelector, the appropriate action is taken. @@ -257,73 +492,145 @@ */ protected void addComponentDescriptor( ComponentDescriptor descripto= r ) { + if( getLogger().isDebugEnabled() ) + { + StringBuffer buff =3D new StringBuffer(); =09 + buff.append( "Adding ComponentDescriptor. role=3D" ); + buff.append( descriptor.getRole() ); + buff.append( ", id=3D" ); + buff.append( descriptor.getId() ); + buff.append( ",role-hint=3D" ); + buff.append( descriptor.getRoleHint() ); + buff.append( ",strategy=3D" ); + buff.append( descriptor.getInstantiationStrategy() ); + buff.append( ", impl=3D" ); + buff.append( descriptor.getImplementation() ); + =09 + getLogger().debug( buff.toString() ); + } getComponentDescriptors().put( descriptor.getComponentKey(), des= criptor ); } =20 + /** + * Adds a InstanceManager to this repository. + *=20 + * @param descriptor + */ + protected void addInstanceManagerDescriptor( ComponentDescriptor des= criptor ) + { + getLogger().info( + "Adding instance manager descriptor. strategy=3D" + + descriptor.getInstantiationStrategy() + + ", impl=3D" + + descriptor.getImplementation() ); + getInstanceManagerDescriptors().put( descriptor.getInstantiation= Strategy(), descriptor ); + } + // -----------------------------------------------------------------= ----- // Service lookup methods // -----------------------------------------------------------------= ----- =20 - public synchronized Object lookup( String key ) - throws ServiceException + public synchronized Object lookup( String key )=20 + throws ServiceException { // Attempt to lookup the componentManager by key. ComponentManager componentManager =3D getComponentManager( key )= ; =20 Object component =3D null; =20 - if ( componentManager =3D=3D null ) + //have todo some synchronization stuff here as two different thr= eads may + //try to create seperate instances of the same component manager= s. Need=20 + //to block one until the other has created it.Seeing this happen= s once + //per component it shouldn't be a drag on performance + if (componentManager =3D=3D null) { - // We need to create an instance of this componentManager. - - ComponentDescriptor descriptor =3D - (ComponentDescriptor) getComponentDescriptors().get( key= ); - - if ( descriptor =3D=3D null ) + //lock, and check for component manager again within + //synch block, as another thread may have just created one=20 + synchronized (lookupLock) { - getLogger().error( "Non existant component: " + key ); - throw new ServiceException( key, "Non existant component= for key " + key + "." ); + componentManager =3D getComponentManager(key); + if (componentManager !=3D null) + { + try + { + return componentManager.getComponent(); + } + catch (Exception e) + { + throw new ServiceException( + key, + "Error retrieving component from ComponentMa= nager"); + } + } + // We need to create an instance of this componentManage= r. + getLogger().debug( "Creating new ComponentDescriptor for= role: " + key ); + ComponentDescriptor descriptor =3D + (ComponentDescriptor) getComponentDescriptors().get(= key ); + + if ( descriptor =3D=3D null ) + { + getLogger().error( "Non existant component: " + key = ); + throw new ServiceException( key, "Non existant compo= nent for key " + key + "." ); + } + + try + { + componentManager =3D instantiateComponentManager( de= scriptor ); + } + catch ( Exception e ) + { + getLogger().error("Could not create component: " + k= ey, e); + throw new ServiceException( + key, + "Could not create component for key " + key + "!= ", + e); + } + try + { + component =3D componentManager.getComponent(); + } + catch (Exception e) + { + throw new ServiceException( + key, + "Error retrieving component from ComponentManage= r. cause=3D" + + Tracer.traceToString(e)); + } + if (getLogger().isDebugEnabled()) + { + StringBuffer buff =3D new StringBuffer(); + buff.append("Obtained new component :role=3D").appen= d(descriptor.getRole()); + buff.append(",impl=3D").append( descriptor.getImplem= entation()); + buff.append(",lifecycle-id=3D").append(descriptor.ge= tLifecycleHandlerId()); + buff.append(",strategy=3D").append(descriptor.getIns= tantiationStrategy()); + getLogger().debug(buff.toString()); + } + // We do this so we know what to do when releasing. Only= have to do it once + //per component class + compManagersByCompClass.put( component.getClass().getNam= e(), componentManager ); + + lookupLock.notifyAll(); } =20 + } + else + { try { - componentManager =3D instantiateComponentManager( descri= ptor ); + component =3D componentManager.getComponent(); } catch ( Exception e ) { - getLogger().error( "Could not create component: " + key,= e ); - throw new ServiceException( key, "Could not create compo= nent for key " + key + "!", e ); + throw new ServiceException( key, "Error retrieving compo= nent from ComponentManager" ); } - - // We do this so we know what to do when releasing. - ComponentHousing housing =3D componentManager.getComponentHo= using(); - - if ( housing =3D=3D null ) - { - throw new ServiceException( key, "ComponentHousing is nu= ll."); - } - - component =3D housing.getComponent(); - - if ( component =3D=3D null ) - { - throw new ServiceException( key, "Component is null."); - } - - getComponentHousings().put( component, housing ); } - else - { - component =3D componentManager.getComponentHousing().getComp= onent(); - } - return component; } =20 - public synchronized Object lookup( String role, String id ) - throws ServiceException + public synchronized Object lookup( String role, String id )=20 + throws ServiceException { - return lookup( role + id ); + return lookup( role + id ); } =20 /** @@ -346,37 +653,16 @@ */ public synchronized void release( Object component ) { - ComponentHousing housing =3D (ComponentHousing) getComponentHous= ings().get( component ); - - if ( housing !=3D null ) - { - // Only call the end of lifecyle events when there are - // no more users of this component, doing so otherwise - // might lead in plexus giving out a component that has - // been effectively extinguished or even worse, a client - // with an existing reference to the valid component may - // have the rug pulled out from under them by another - // client releasing the component. - - try - { - endComponentLifecycle( housing ); - } - catch ( Exception e ) - { - getLogger().error( "Error ending component lifecycle", e= ); - } + if ( component =3D=3D null ) + return; =20 - // This is where we need to track the count for pools and re= use. + ComponentManager cm =3D + (ComponentManager) compManagersByCompClass.get( component.ge= tClass().getName() ); =20 - // Now get rid of the Service capsule references. - String serviceKey =3D housing.getComponentManager().getCompo= nentDescriptor().getComponentKey(); - getComponentManagers().remove( serviceKey ); - getComponentHousings().remove( component ); - - housing =3D null; - component =3D null; - } + //this repository does not deal with this component + if ( cm =3D=3D null ) + return; + cm.release( component ); } =20 /** @@ -384,6 +670,7 @@ */ public synchronized void dispose() { + getLogger().info("Disposing ComponentRepository..."); disposeAllComponents(); } =20 @@ -392,66 +679,106 @@ */ protected void disposeAllComponents() { - // Use an array to get the list of components; otherwise we'll + // Use an array to get the list of componentManagers else we'll // end up with a ConcurrentModificationException if we use an // Iterator to cycle through the set because release() makes // changes to the set as well. + //<=3D=3D now not important as each component manager does this. =20 - Object components[] =3D getComponentHousings().keySet().toArray(= ); + Iterator iter =3D getComponentManagers().values().iterator(); =20 - for ( int i =3D 0; i < components.length; i++ ) + while ( iter.hasNext() ) { - release( components[ i ] ); + try + { + ( (ComponentManager) iter.next() ).dispose(); + } + catch ( Exception e ) + { + getLogger().error( + "Error while disposing component manager. Continuing= with the rest", + e ); + } } + + componentManagers.clear(); + getLogger().info( "...ComponentRepository disposed" ); } =20 // -----------------------------------------------------------------= ----- // Lifecycle Handling // -----------------------------------------------------------------= ----- =20 - protected LifecycleHandler getLifecycleHandler( String role ) + public LifecycleHandler getLifecycleHandler( String id ) throws UndefinedLifecycleHandlerException { - return getPlexusContainer().getLifecycleHandler(); + LifecycleHandlerHousing h =3D null; + if ( id !=3D null ) + { + h =3D (LifecycleHandlerHousing) lifecycleHandlers.get( id ); + } + if ( h =3D=3D null ) + { + throw new UndefinedLifecycleHandlerException( + "No LifecycleHandler defined for id: " + id); + } + return h.getHandler(); } =20 + /** + * @return + */ + protected Configuration getConfiguration() + { + return configuration; + } =20 - // I have made the lifecycle handlers public because the instance ma= nager is now responsible for running - // a component it deals with through its lifecyle. I was running the= component through its lifecycle - // in this class but that is not appropriate as we want the instanac= e manager to control the - // component. These are public for now but we need a little restruct= uring. + /** + * @return + */ + protected Configuration getDefaultConfiguration() + { + return defaultConfiguration; + } =20 - /** Start a component's lifecycle. - * + /** + * @see org.apache.plexus.service.repository.ComponentRepository#con= textualize(org.apache.avalon.framework.context.Context) */ - public void startComponentLifecycle( ComponentHousing housing ) + public void contextualize( Context context ) { - try - { - LifecycleHandler lh =3D getLifecycleHandler( housing.getComp= onentManager().getComponentDescriptor().getRole() ); - lh.startLifecycle( housing ); - } - catch ( Exception e ) - { - getLogger().error( "Cannot start component lifecycle with ro= le : " - + housing.getComponentManager().getCompon= entDescriptor().getRole(), e ); - } + this.context =3D context; } =20 - /** End a component's lifecycle. - * + /** + * @see org.apache.plexus.service.repository.ComponentRepository#get= DefaultLifecycleHandler() */ - public void endComponentLifecycle( ComponentHousing housing ) + public LifecycleHandler getDefaultLifecycleHandler() { - try - { - LifecycleHandler lh =3D getLifecycleHandler( housing.getComp= onentManager().getComponentDescriptor().getRole() ); - lh.endLifecycle( housing ); - } - catch ( Exception e ) - { - getLogger().error( "Cannot start component lifecycle with ro= le : " - + housing.getComponentManager().getCompon= entDescriptor().getRole(), e ); - } + return defaultLifecycleHandler; } + + /** + * @return + */ + Context getContext() + { + return context; + } + + /** + * @return + */ + public LoggerManager getComponnetLogManager() + { + return loggerManager; + } + + /** + * @param manager + */ + public void setComponentLogManager( LoggerManager manager ) + { + loggerManager =3D manager; + } + } Index: src/java/org/apache/plexus/service/repository/instance/AbstractIns= tanceManager.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/ser= vice/repository/instance/AbstractInstanceManager.java,v retrieving revision 1.2 diff -u -r1.2 AbstractInstanceManager.java --- src/java/org/apache/plexus/service/repository/instance/AbstractInstan= ceManager.java 12 May 2003 18:57:28 -0000 1.2 +++ src/java/org/apache/plexus/service/repository/instance/AbstractInstan= ceManager.java 25 Jul 2003 03:50:36 -0000 @@ -2,38 +2,68 @@ =20 import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.logger.Logger; +import org.apache.plexus.lifecycle.LifecycleHandler; import org.apache.plexus.service.repository.ComponentHousing; import org.apache.plexus.service.repository.ComponentManager; =20 /** - * + * Base InstanceManager * * @author <a href=3D"mailto:[email protected]">Jason van Zyl</a> * * @version $Id: AbstractInstanceManager.java,v 1.2 2003/05/12 18:57:28 = jvanzyl Exp $ */ -public abstract class - AbstractInstanceManager - implements InstanceManager +public abstract class AbstractInstanceManager implements InstanceManager { + /** ClassLoader used to load the component */ private ClassLoader classLoader; =20 + /** Component configuration */ private Configuration configuration; =20 + /** Component implementation */ private String implementation; =20 + /** ComponantManager which handles the component */ private ComponentManager componentManager; =20 + /** Lifecycle handler for this component type */ + private LifecycleHandler lifecycleHandler; + + private Logger logger; + /** + *=20 + */ + public AbstractInstanceManager() + { + super(); + =20 + } + + /** + * This currently does nothing. Subclasses should still call this if= they override this method + * as it may doing something useful in future. + *=20 + * @see org.apache.plexus.service.repository.instance.InstanceManage= r#initialize() + */ + public void initialize()=20 + throws Exception + { + + } // -----------------------------------------------------------------= ----- // Lifecylce Management // -----------------------------------------------------------------= ----- =20 - public void configure( Configuration configuration ) - throws ConfigurationException + /** + * make sure to call this if overriding + */ + public void configure(Configuration configuration)=20 + throws ConfigurationException { this.configuration =3D configuration; - - implementation =3D configuration.getChild( "implementation" ).ge= tValue(); + implementation =3D configuration.getChild("implementation").getV= alue(); } =20 // -----------------------------------------------------------------= ----- @@ -45,7 +75,7 @@ return configuration; } =20 - public void setConfiguration( Configuration configuration ) + public void setConfiguration(Configuration configuration) { this.configuration =3D configuration; } @@ -55,7 +85,15 @@ return implementation; } =20 - public void setImplementation( String implementation ) + /** + * @see org.apache.plexus.service.repository.instance.InstanceManage= r#setLifecycleHandler(org.apache.plexus.lifecycle.LifecycleHandler) + */ + public void setLifecycleHandler(LifecycleHandler handler) + { + this.lifecycleHandler =3D handler; + } + + public void setComponentImplementation(String implementation) { this.implementation =3D implementation; } @@ -65,7 +103,7 @@ return classLoader; } =20 - public void setClassLoader( ClassLoader classLoader ) + public void setClassLoader(ClassLoader classLoader) { this.classLoader =3D classLoader; } @@ -75,27 +113,84 @@ return componentManager; } =20 - public void setComponentManager( ComponentManager componentManager ) + public void setComponentManager(ComponentManager componentManager) { this.componentManager =3D componentManager; } =20 - // -----------------------------------------------------------------= ----- - // Implementation - // -----------------------------------------------------------------= ----- - - protected ComponentHousing createInstance() - throws Exception + protected LifecycleHandler getLifecycleHandler() { - ComponentHousing housing =3D new ComponentHousing(); + return lifecycleHandler; + } =20 - housing.setComponent( getClassLoader().loadClass( getImplementat= ion() ).newInstance() ); - housing.setComponentManager( getComponentManager() ); + /** + * @return + */ + protected Logger getLogger() + { + return logger; + } + + /** + * @see org.apache.plexus.service.repository.instance.InstanceManager#e= nableLogging(org.apache.avalon.framework.logger.Logger) + */ + public void enableLogging(Logger logger) + { + this.logger =3D logger; + } =20 - getComponentManager().getComponentRespository().startComponentLi= fecycle( housing ); + // -----------------------------------------------------------------= ----- + // Implementation + // -----------------------------------------------------------------= ----- =20 + protected void startComponentLifecycle(ComponentHousing housing) + { + try + { + getLifecycleHandler().endLifecycle(housing); + } + catch (Exception e) + { + getLogger().error( + "Cannot start component lifecycle with role : " + + getComponentManager().getComponentDescriptor().getRole(), + e); + } + } + + /** End a component's lifecycle. + * + */ + protected void endComponentLifecycle(ComponentHousing housing) + { + try + { + getLifecycleHandler().endLifecycle(housing); + } + catch (Exception e) + { + getLogger().error( + "Cannot start component lifecycle with role : " + + getComponentManager().getComponentDescriptor().getRole(), + e); + } + } + =09 + /** + * Create a new Component instance,and start it's lifecycle + */ + protected ComponentHousing newHousingInstance()=20 + throws Exception + { + ComponentHousing housing =3D new ComponentHousing(); + housing.setComponentManager(getComponentManager()); + housing.setComponent(getClassLoader().loadClass(getImplementatio= n()).newInstance()); + getLifecycleHandler().startLifecycle(housing); return housing; } + + public abstract void release(Object component); + =20 =20 } Index: src/java/org/apache/plexus/service/repository/instance/AbstractMul= tipleInstanceManager.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/java/org/apache/plexus/service/repository/instance/Abstract= MultipleInstanceManager.java diff -N src/java/org/apache/plexus/service/repository/instance/AbstractMu= ltipleInstanceManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/java/org/apache/plexus/service/repository/instance/AbstractMultip= leInstanceManager.java 25 Jul 2003 03:50:36 -0000 @@ -0,0 +1,45 @@ +package org.apache.plexus.service.repository.instance; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.plexus.service.repository.ComponentHousing; + +/** + *=20 + * <p>Created on 20/07/2003</p> + * + * @author <a href=3D"mailto:[email protected]">Bert van Brakel</a> + * @version $Revision$ + */ +public abstract class AbstractMultipleInstanceManager extends AbstractIn= stanceManager +{ +=09 + /** Component housings keyed by component. Used so we can dispose of + * components. Need a threadsafe map as we could be putting and sett= ing at the same + * time. Were are putting and getting in equals amounts so a synchro= nized map is best*/ + private Map housings; + /** + *=20 + */ + public AbstractMultipleInstanceManager() + { + super(); + housings =3D Collections.synchronizedMap(new HashMap()); + } + + protected ComponentHousing getHousing(Object component) + { + return (ComponentHousing) housings.get(component); + } + protected ComponentHousing removeHousing(Object component) + { + return (ComponentHousing) housings.remove(component); + } + protected void putHousing(Object component, ComponentHousing housing= ) + { + housings.put(component, housing); + } + +} Index: src/java/org/apache/plexus/service/repository/instance/ClassicSing= letonInstanceManager.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/java/org/apache/plexus/service/repository/instance/ClassicS= ingletonInstanceManager.java diff -N src/java/org/apache/plexus/service/repository/instance/ClassicSin= gletonInstanceManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/java/org/apache/plexus/service/repository/instance/ClassicSinglet= onInstanceManager.java 25 Jul 2003 03:50:36 -0000 @@ -0,0 +1,86 @@ +package org.apache.plexus.service.repository.instance; + +import org.apache.plexus.service.repository.ComponentHousing; + +/** + * This ensures only a single instance of a a component exists. Once no + * more connections for this component exists it is disposed. + *=20 + * @author <a href=3D"mailto:[email protected]">Jason van Zyl</a> + * @author <a href=3D"mailto:[email protected]">Bert van Brakel</a> + * + * @version $Id: SingletonInstanceManager.java,v 1.1 2003/05/01 19:35:36= jvanzyl Exp $ + */ +public class ClassicSingletonInstanceManager + extends AbstractInstanceManager +{ + private ComponentHousing singleton; + + /** Number of clients using this component */ + private int connections =3D 0; +=09 + /** + *=20 + */ + public ClassicSingletonInstanceManager() + { + super(); + } + + /** + * @see org.apache.plexus.service.repository.instance.InstanceManager#r= elease(java.lang.Object) + */ + public void release(Object component) + { + //Only accept it if it is the same instance.=20 + if( singleton.getComponent() =3D=3D component) + { + connections--; + if(connections =3D=3D 0) + { + endComponentLifecycle( singleton ); + } + singleton =3D null; =09 + } + else + { + getLogger().warn("Component returned which is not the same instance. = Ignored. component=3D" + component); + } + } + + /** + * @see org.apache.plexus.service.repository.instance.InstanceManager#d= ispose() + */ + public void dispose() + { + //wait for all the clients to return all the components + //Do we do this in a seperate thread? or block the current thread?? + //TODO + if( singleton!=3Dnull) + { + endComponentLifecycle(singleton); + }=20 + } + + /** + * @see org.apache.plexus.service.repository.instance.InstanceManager#g= etComponent() + */ + public Object getComponent() throws Exception + { + if( singleton =3D=3D null) + { + singleton =3D newHousingInstance(); + } + connections++; + return singleton.getComponent(); + } + + /** + * @see org.apache.plexus.service.repository.instance.InstanceManager#g= etConnections() + */ + public int getConnections() + { + return connections; + } + +} \ No newline at end of file Index: src/java/org/apache/plexus/service/repository/instance/InstanceMan= ager.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/ser= vice/repository/instance/InstanceManager.java,v retrieving revision 1.1 diff -u -r1.1 InstanceManager.java --- src/java/org/apache/plexus/service/repository/instance/InstanceManage= r.java 1 May 2003 19:35:36 -0000 1.1 +++ src/java/org/apache/plexus/service/repository/instance/InstanceManage= r.java 25 Jul 2003 03:50:37 -0000 @@ -1,12 +1,17 @@ package org.apache.plexus.service.repository.instance; =20 + import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; -import org.apache.plexus.service.repository.ComponentHousing; +import org.apache.avalon.framework.logger.Logger; +import org.apache.plexus.lifecycle.LifecycleHandler; import org.apache.plexus.service.repository.ComponentManager; =20 /** - * + * Manages a component instance.=20 + * Determines when a component is shutdown, and when it's started up. Ea= ch + * instance deals with only one component class, though may handle multi= ple=20 + * instances of this class. * * @author <a href=3D"mailto:[email protected]">Jason van Zyl</a> * @@ -16,9 +21,9 @@ { static String ROLE =3D InstanceManager.class.getName(); =20 - ComponentHousing getInstance() + /* ComponentHousing newHousingInstance() throws Exception; - +*/ void configure( Configuration configuration ) throws ConfigurationException; =20 @@ -27,7 +32,40 @@ =20 void setClassLoader( ClassLoader classLoader ); =20 - void setImplementation( String implementation ); + void setComponentImplementation( String implementation ); =20 void setComponentManager( ComponentManager manager ); -} + =20 + int getConnections(); + /** + * Set the lifecycle handler to use. This is determined by the compo= nent. + */ + void setLifecycleHandler(LifecycleHandler handler); + /** + * Dispose this manager. Instance manager should take any components= it holds + * through their shutdown lifecycle. + * + */ + void dispose(); + /** + * Release the component back to this manager. The manager may decid= e to + * end the components lifecycle, put it back in a pool, or just keep= it alive. It can + * be safely assumed the component is never null. + *=20 + * @param component + */ + void release(Object component); + =20 + /** + * Set this managers logger + *=20 + * @param logger + */ + void enableLogging(Logger logger); + /** + * Retrieve a component instance + *=20 + * @return + */ + Object getComponent() throws Exception; +} \ No newline at end of file Index: src/java/org/apache/plexus/service/repository/instance/KeepAliveSi= ngletonInstanceManager.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/java/org/apache/plexus/service/repository/instance/KeepAliv= eSingletonInstanceManager.java diff -N src/java/org/apache/plexus/service/repository/instance/KeepAliveS= ingletonInstanceManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/java/org/apache/plexus/service/repository/instance/KeepAliveSingl= etonInstanceManager.java 25 Jul 2003 03:50:37 -0000 @@ -0,0 +1,78 @@ +package org.apache.plexus.service.repository.instance; + +import org.apache.plexus.service.repository.ComponentHousing; + +/** + * This ensures a component is only used as a singleton, and is only shu= tdown when + * the container shuts down. + *=20 + * @author <a href=3D"mailto:[email protected]">Bert van Brakel</a> + * + * @version $Id: SingletonInstanceManager.java,v 1.1 2003/05/01 19:35:36= jvanzyl Exp $ + */ +public class KeepAliveSingletonInstanceManager + extends AbstractInstanceManager +{ + private ComponentHousing singleton; + + /** Number of clients using this component */ + private int connections =3D 0; +=09 + /** + *=20 + */ + public KeepAliveSingletonInstanceManager() + { + super(); + } + + /** + * @see org.apache.plexus.service.repository.instance.InstanceManager#r= elease(java.lang.Object) + */ + public void release(Object component) + { + //Only accept it if it is the same instance.=20 + if( singleton.getComponent() =3D=3D component) + { + connections--; + } + else + { + getLogger().warn("Component returned which is not the same instance. = Ignored. component=3D" + component); + } + } + + /** + * @see org.apache.plexus.service.repository.instance.InstanceManager#d= ispose() + */ + public void dispose() + { + //wait for all the clients to return all the components + //Do we do this in a seperate thread? or block the current thread?? + //TODO + if( singleton!=3Dnull) + endComponentLifecycle(singleton); + } + + /** + * @see org.apache.plexus.service.repository.instance.InstanceManager#g= etComponent() + */ + public Object getComponent() throws Exception + { + if( singleton =3D=3D null) + { + singleton =3D newHousingInstance(); + } + connections++; + return singleton.getComponent(); + } + + /** + * @see org.apache.plexus.service.repository.instance.InstanceManager#g= etConnections() + */ + public int getConnections() + { + return connections; + } + +} \ No newline at end of file Index: src/java/org/apache/plexus/service/repository/instance/PerLookupIn= stanceManager.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/ser= vice/repository/instance/PerLookupInstanceManager.java,v retrieving revision 1.1 diff -u -r1.1 PerLookupInstanceManager.java --- src/java/org/apache/plexus/service/repository/instance/PerLookupInsta= nceManager.java 1 May 2003 19:35:36 -0000 1.1 +++ src/java/org/apache/plexus/service/repository/instance/PerLookupInsta= nceManager.java 25 Jul 2003 03:50:37 -0000 @@ -3,23 +3,64 @@ import org.apache.plexus.service.repository.ComponentHousing; =20 /** - * + * Creates a new component instance for every lookup *=20 * @author <a href=3D"mailto:[email protected]">Jason van Zyl</a> * * @version $Id: PerLookupInstanceManager.java,v 1.1 2003/05/01 19:35:36= jvanzyl Exp $ */ -public class PerLookupInstanceManager - extends AbstractInstanceManager +public class PerLookupInstanceManager extends AbstractMultipleInstanceMa= nager { - public void initialize() - throws Exception + private int connections =3D 0; + /** + *=20 + */ + public PerLookupInstanceManager() + { + super(); + } + + public void dispose() + { + //nothing todo as component has lifecycle + //ended on release + } + =20 + /** + * Return the current number of components this manager has given ou= t + * which have not yet been returned. + *=20 + * @return + */ + public int getConnections() + { + return connections; + } =20 + + /* (non-Javadoc) + * @see org.apache.plexus.service.repository.instance.InstanceManage= r#getComponent() + */ + public Object getComponent() throws Exception { + ComponentHousing h =3D newHousingInstance(); + putHousing(h.getComponent(), h); + connections++; + return h.getComponent(); } =20 - public ComponentHousing getInstance() - throws Exception + /** + * @see org.apache.plexus.service.repository.instance.InstanceManage= r#release(java.lang.Object) + */ + public void release(Object component) { - return createInstance(); + ComponentHousing h =3DremoveHousing(component); + if (h !=3D null) + { + connections--; + endComponentLifecycle( h );=09 + } } + + =20 + } Index: src/java/org/apache/plexus/service/repository/instance/PoolableIns= tanceManager.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/ser= vice/repository/instance/PoolableInstanceManager.java,v retrieving revision 1.1 diff -u -r1.1 PoolableInstanceManager.java --- src/java/org/apache/plexus/service/repository/instance/PoolableInstan= ceManager.java 1 May 2003 19:35:36 -0000 1.1 +++ src/java/org/apache/plexus/service/repository/instance/PoolableInstan= ceManager.java 25 Jul 2003 03:50:38 -0000 @@ -1,35 +1,165 @@ package org.apache.plexus.service.repository.instance; =20 +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.plexus.configuration.DefaultConfiguration; import org.apache.plexus.service.repository.ComponentHousing; +import org.apache.plexus.util.SweeperPool; =20 /** - * + * Pools comnponents * * @author <a href=3D"mailto:[email protected]">Jason van Zyl</a> * * @version $Id: PoolableInstanceManager.java,v 1.1 2003/05/01 19:35:36 = jvanzyl Exp $ */ -public class PoolableInstanceManager - extends AbstractInstanceManager +public class PoolableInstanceManager extends AbstractMultipleInstanceMan= ager { - private SimplePool pool; + private SweeperPool pool; =20 - private int size =3D 6; + private int connections =3D 0; +=09 + /** + *=20 + */ + public PoolableInstanceManager() + { + super(); + } =20 - public void initialize() - throws Exception + public void initialize() throws Exception { - pool =3D new SimplePool( size ); + pool =3D newSeeperPool(getConfiguration(), null); + } + /** + * @see org.apache.plexus.service.repository.instance.InstanceManage= r#configure(org.apache.avalon.framework.configuration.Configuration) + */ + public void configure(Configuration configuration) throws Configurat= ionException + { + super.configure(configuration); + } =20 - for ( int i =3D 0; i < size; i++ ) + /** + * @see org.apache.plexus.service.repository.instance.InstanceManage= r#release(java.lang.Object) + */ + public void release(Object component) + { + ComponentHousing housing =3D removeHousing( component); + if( housing =3D=3D null ) + { + getLogger().warn("Component attempted to be returned to pool, but = this object does no appear to be from this pool. Component class=3D" + co= mponent.getClass()); + return; + } + pool.put( housing ); + connections --; + } + + /** + * @see org.apache.plexus.service.repository.instance.InstanceManage= r#dispose() + */ + public void dispose() + { + //@todo really need to wait for all components to be returned. + //however blocking on this call may prevent plexus servicing + //other requests and hence prevent cleanup. Have to look + //at this. For now just assume all connections have been + //released. + pool.dispose(); + =20 + } + + /** + * @see org.apache.plexus.service.repository.instance.InstanceManage= r#getComponent() + */ + public Object getComponent() throws Exception + { + ComponentHousing housing =3D (ComponentHousing)pool.get(); + if( housing =3D=3D null) { - pool.put( createInstance() ); + housing =3D newHousingInstance(); } + putHousing(housing.getComponent(), housing); + connections ++; + return housing.getComponent(); } =20 - public ComponentHousing getInstance() - throws Exception + /** + * @see org.apache.plexus.service.repository.instance.InstanceManage= r#getConnections() + */ + public int getConnections() { - return (ComponentHousing) pool.get(); + return connections; + } + + /** + * Create a new ObjectPool based on the provided configurations. De= fault + * hardcoded values are used if neither configurations have a value + * for a particular setting. + *=20 + *=20 + * @param config the custom configuration for the pool + * @param defaultConfig the configuration used to fill out any gaps= in + * the custom configuration.=20 + * @return a new ObjectPool + * @throws ConfigurationException + */ + private SweeperPool newSeeperPool(Configuration config, Configuratio= n defaultConfig) + throws ConfigurationException + { + if( config=3D=3Dnull) + config =3D new DefaultConfiguration(""); + if (defaultConfig =3D=3D null) + defaultConfig =3D new DefaultConfiguration(""); + int sweepInterval =3D + config.getChild("sweep-interval").getValueAsInteger( + defaultConfig.getChild("sweep-interval").getValueAsInteg= er(5)); + int minCapacity =3D + config.getChild("min-capacity").getValueAsInteger( + defaultConfig.getChild("min-capacity").getValueAsInteger= (3)); + int maxCapacity =3D + config.getChild("max-capacity").getValueAsInteger( + defaultConfig.getChild("max-capacity").getValueAsInteger= (30)); + int triggerSize =3D + config.getChild("trigger-size").getValueAsInteger( + defaultConfig.getChild("trigger-size").getValueAsInteger= (15)); + int initialCapacity =3D + config.getChild("initial-capacity").getValueAsInteger( + defaultConfig.getChild("initial-capacity").getValueAsInt= eger(10)); + return new SweeperPool( + maxCapacity, + minCapacity, + initialCapacity, + sweepInterval, + triggerSize); + } + + class ComponentPool extends SweeperPool + { + + /** + * @param maxSize + * @param minSize + * @param intialCapacity + * @param sweepInterval + * @param triggerSize + */ + public ComponentPool( + int maxSize, + int minSize, + int intialCapacity, + int sweepInterval, + int triggerSize) + { + super(maxSize, minSize, intialCapacity, sweepInterval, trigg= erSize); + } + + /** + * @see org.apache.plexus.util.SweeperPool#objectDisposed(java.l= ang.Object) + */ + public void objectDisposed(Object obj) + { + endComponentLifecycle((ComponentHousing) obj); + } + } } Index: src/java/org/apache/plexus/service/repository/instance/SingletonIn= stanceManager.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/java/org/apache/plexus/service/repository/instance/Singleto= nInstanceManager.java diff -N src/java/org/apache/plexus/service/repository/instance/SingletonI= nstanceManager.java --- src/java/org/apache/plexus/service/repository/instance/SingletonInsta= nceManager.java 1 May 2003 19:35:36 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,32 +0,0 @@ -package org.apache.plexus.service.repository.instance; - -import org.apache.plexus.service.repository.ComponentHousing; - -/** - * - *=20 - * @author <a href=3D"mailto:[email protected]">Jason van Zyl</a> - * - * @version $Id: SingletonInstanceManager.java,v 1.1 2003/05/01 19:35:36= jvanzyl Exp $ - */ -public class SingletonInstanceManager - extends AbstractInstanceManager -{ - private ComponentHousing instance; - - public void initialize() - throws Exception - { - } - - public ComponentHousing getInstance() - throws Exception - { - if ( instance =3D=3D null ) - { - instance =3D createInstance(); - } - - return instance; - } -} \ No newline at end of file Index: src/java/org/apache/plexus/servlet/PlexusLoaderServlet.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/java/org/apache/plexus/ser= vlet/PlexusLoaderServlet.java,v retrieving revision 1.4 diff -u -r1.4 PlexusLoaderServlet.java --- src/java/org/apache/plexus/servlet/PlexusLoaderServlet.java 1 May 200= 3 19:35:36 -0000 1.4 +++ src/java/org/apache/plexus/servlet/PlexusLoaderServlet.java 25 Jul 20= 03 03:50:39 -0000 @@ -118,6 +118,7 @@ container =3D new DefaultPlexusContainer(); try { + container.addContextValue("plexus.home", applicationRoot + "= /WEB-INF"); container.setConfigurationResource( config ); container.initialize(); container.start(); @@ -142,7 +143,9 @@ { try { - container.dispose(); + log( "Shutting down plexus!..."); + container.dispose(); =20 + log( "...plexus shutdown. goodbye" );=20 } catch ( Exception e ) { Index: src/java/org/apache/plexus/util/SweeperPool.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/java/org/apache/plexus/util/SweeperPool.java diff -N src/java/org/apache/plexus/util/SweeperPool.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/java/org/apache/plexus/util/SweeperPool.java 25 Jul 2003 03:50:39= -0000 @@ -0,0 +1,302 @@ +package org.apache.plexus.util; + +import java.util.ArrayList; + + +/** + * Pools a bunch of objects . Runs a sweeper periodically to + * keep it down to size. The objects in the pool first get disposed firs= t. + * + * + * @author <a href=3D"mailto:[email protected]">Bert van Brakel</a> + */ +public class SweeperPool +{ + /***/ + private static final boolean DEBUG =3D false; + + /** Sweeps the pool periodically to trim it's size */ + private transient Sweeper sweeper; + + /** Absolute maxiumuim size of the pool.*/ + private transient int maxSize; + + /** The size the pool gets trimmed down to */ + private transient int minSize; + + /** When the sweeper runs + * and the pool is over this size, then the pool is trimmed */ + private int triggerSize; + + /** Holds the pooled objects */ + private ArrayList pooledObjects; + + /** Flag indicating this pool is shuting down */ + private boolean shuttingDown =3D false; + + //private Vector used; + + /** + * + * <p>There are a number of settings to control how the pool operate= s. + * <ul> + * <li><code>minSize</code> - this is the size the pool is trimmed t= o</li> + * <li><code>triggerSize</code> - this determines if the pool is tri= mmed when + * the sweeper runs. If the pool size is greater or equal than this v= alue then + * the pool is trimmed to <code>minSize</code>.</lie> + * <li><code>maxSize</code> - if the pool has reached this size, any = objects added + * are immediatley disposed. If the pool is this size when the sweepe= r runs, then + * the pool is also trimmed to <code>minSize</code> irrespective of t= he triggerSize. + * </li> + * <li><code>sweepInterval</code> - how often the sweeper runs. Is ac= tually the + * time since the sweeper last finished a pass. 0 if the sweeper shou= ld not run. + * </li> + * </ul> + * </p> + * + * <p>Any value less than 0 is automatically converted to 0</p> + */ + public SweeperPool( int maxSize, int minSize, int intialCapacity, + int sweepInterval, int triggerSize ) + { + super( ); + this.maxSize =3D saneConvert( maxSize ); + this.minSize =3D saneConvert( minSize ); + this.triggerSize =3D saneConvert( triggerSize ); + pooledObjects =3D new ArrayList( intialCapacity ); + + if( sweepInterval > 0 ) + { + sweeper =3D new Sweeper( this, sweepInterval ); + sweeper.start( ); + } + } + + private int saneConvert( int value ) + { + if( value < 0 ) + { + return 0; + } + else + { + return value; + } + } + + /** + * Return the pooled object + */ + public synchronized Object get( ) + { + if( ( pooledObjects.size( ) =3D=3D 0 ) || shuttingDown ) + { + return null; + } + else + { + Object obj =3D pooledObjects.remove( 0 ); + objectRetrieved( obj ); + + //used.add(obj); + return obj; + } + } + + /** + * Add an object to the pool + * + * @param obj the object to pool. Can be null. + * + * @return true if the object was added to the pool, false if it was= disposed or null + * + */ + public synchronized boolean put( Object obj ) + { + objectAdded( obj ); + + if( ( obj !=3D null ) && ( pooledObjects.size( ) < maxSize ) + && ( shuttingDown =3D=3D false ) ) + { + pooledObjects.add( obj ); + + return true; + } + else if( obj !=3D null ) + { + //no longer need the object, so dispose it =20 + objectDisposed( obj ); + } + + return false; + } + + /** + * Return the number of pooled objects. This is never + * greater than t maximuim size of the pool + * + * @return the number of pooled objects + */ + public int getSize( ) + { + return pooledObjects.size( ); + } + + /** + * Dispose of this pool. Stops the sweeper and disposes each object = in the pool + * + */ + public synchronized void dispose( ) + { + shuttingDown =3D true; + + if( sweeper !=3D null ) + { + sweeper.stop( ); + } + + //use an array here as objects may still be being put back in th= e pool + //and we don't want to throw a ConcurrentModificationException + Object[] objects =3D pooledObjects.toArray( ); + + for( int i =3D 0; i < objects.length; i++ ) + { + objectDisposed( objects[i] ); + } + + pooledObjects.clear( ); + } + + /** + * Trim the pool down to min size + * + */ + public void trim( ) + { + if( ( ( triggerSize > 0 ) && ( pooledObjects.size( ) >=3D trigg= erSize ) ) + || ( ( maxSize > 0 ) && ( pooledObjects.size( ) >=3D ma= xSize ) ) ) + { + while( pooledObjects.size( ) > minSize ) + { + objectDisposed( pooledObjects.remove( 0 ) ); + } + } + } + + /** + * Override this to be notified of object disposal. Called + * after the object has been removed. Occurs when the pool + * is trimmed. + * + * @param obj + */ + public void objectDisposed( Object obj ) + { + } + + /** + * Override this to be notified of object addition. + * Called before object is to be added. + * + * @param obj + */ + public void objectAdded( Object obj ) + { + } + + /** + * Override this to be notified of object retrieval. + * Called after object removed from the pool, but + * before returned to the client. + * + * @param obj + */ + public void objectRetrieved( Object obj ) + { + } + + /** + * Periodically at <code>sweepInterval</code> goes through + * and tests if the pool should be trimmed. + * + * @author bert + * + */ + class Sweeper implements Runnable + { + private final transient SweeperPool pool; + private transient boolean service =3D false; + private final transient int sweepInterval; + + /** + * + */ + public Sweeper( SweeperPool pool, int sweepInterval ) + { + super( ); + this.sweepInterval =3D sweepInterval; + this.pool =3D pool; + } + + /** + * Run the seeper. + * + * @see java.lang.Runnable#run() + */ + public void run( ) + { + debug( "started" ); + + synchronized( this ) + { + while( service ) + { + if( sweepInterval > 0 ) + { + try + { + wait( sweepInterval * 1000 ); + } + catch( InterruptedException e ) + { + } + + runSweep( ); + } + } + } + + debug( "stopped" ); + } + + public void start( ) + { + if( ! service ) + { + Thread t =3D new Thread( this ); + t.start( ); + service =3D true; + } + } + + public synchronized void stop( ) + { + service =3D false; + notifyAll( ); + } + + private final void debug( String msg ) + { + if( DEBUG ) + { + System.err.println( this + ":" + msg ); + } + } + + private void runSweep( ) + { + debug( "runningSweep. time=3D" + System.currentTimeMillis( = ) ); + pool.trim( ); + } + } +} Index: src/java/org/apache/plexus/util/ThreadSafeMap.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/java/org/apache/plexus/util/ThreadSafeMap.java diff -N src/java/org/apache/plexus/util/ThreadSafeMap.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/java/org/apache/plexus/util/ThreadSafeMap.java 25 Jul 2003 03:50:= 41 -0000 @@ -0,0 +1,837 @@ +package org.apache.plexus.util; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + + +/** + * Concurrent reads, but synchronized writes. Wraps a <code>HashMap</cod= e> + * + * <p>Writes will block new reads, and current reads will block new writ= es<p> + * + * <p>Due to the extra overhead of locks, this map should only be used i= f there are + * far more reads then writes. If the ratio is about equal then just cre= ating a + * synchronized Map would be faster</p> + * + * <p>The iterators returned by all of this class's "collection view met= hods" are + * fail-fast: if the map is structurally modified at any time after the = iterator is + * created, in any way except through the iterator's own remove or add m= ethods, + * the iterator will throw a ConcurrentModificationException.</p> + * + * <p>Created on 17/06/2003</p> + * + * + * @author <a href=3D"mailto:[email protected]">Bert van Brakel</a> + * @version $Revision$ + */ +public class ThreadSafeMap implements Map +{ + /** + * The Map holding the entries. + */ + private Map objects; + + /** + * How many readers are currently reading the Map + */ + private long readers =3D 0; + + /** + * Whether a write lock, or write request is active + */ + private boolean writeLock =3D false; + + /** + * The object synchronized against. Seperate object used and not thi= s + * Map instance because we don't know if external code is going to + * synchronize on this Map and stuff things up. + */ + private Object lock =3D new Object( ); + private ThreadSafeSet keySet =3D null; + private ThreadSafeSet entrySet =3D null; + private ThreadSafeCollection values =3D null; + + /** + * Constructor + * + * + */ + public ThreadSafeMap( ) + { + super( ); + objects =3D new HashMap( ); + } + + public Set entrySet( ) + { + if( entrySet =3D=3D null ) + { + entrySet =3D new ThreadSafeSet( this, objects.entrySet( ) )= ; + } + + return entrySet; + } + + public Set keySet( ) + { + if( keySet =3D=3D null ) + { + keySet =3D new ThreadSafeSet( this, objects.keySet( ) ); + } + + return keySet; + } + + /** + * Constructor + * + * + */ + public ThreadSafeMap( int initializeSize ) + { + super( ); + objects =3D new HashMap( initializeSize ); + } + + /** + * Return the object which we lock against. Useful + * if we want to call multiple methods on this + * object and we want to have exclusive access during + * that time. + * + * <p>NOTE: not yet implementetd!!</p> + * + * @return + */ + public Object getWriteLock( ) + { + return lock; + } + + /** + * If a write is currently underway, or is waiting for readers to fi= nish, + * this method will block until the write has completed. + * + */ + private void enteringRead( ) + { + if( writeLock ) + { + synchronized( lock ) + { + while( writeLock ) + { + try + { + lock.wait( ); + } + catch( InterruptedException e ) + { + } + } + } + } + + readers++; + } + + /** + * Called when a read has finished. If it is the last reader, notify= the + * waiting writer. + * + */ + private void exitingRead( ) + { + readers--; + + if( readers =3D=3D 0 ) + { + //notify waiting write lock... + synchronized( lock ) + { + lock.notifyAll( ); + } + } + } + + public Object[] getValues( ) + { + enteringRead( ); + + Object[] values =3D objects.values( ).toArray( ); + exitingRead( ); + + return values; + } + + public Object get( Object key ) + { + if( key =3D=3D null ) + { + return null; + } + + enteringRead( ); + + Object obj =3D objects.get( key ); + exitingRead( ); + + return obj; + } + + public Object put( Object key, Object obj ) + { + if( key =3D=3D null ) + { + return null; + } + + obtainWriteLock( ); + + Object prev =3D objects.put( key, obj ); + releaseWriteLock( ); + + return prev; + } + + public Object remove( Object key ) + { + if( key =3D=3D null ) + { + return null; + } + + obtainWriteLock( ); + + Object obj =3D objects.remove( key ); + releaseWriteLock( ); + + return obj; + } + + public void removeAll( Object[] keys ) + { + obtainWriteLock( ); + + for( int i =3D 0; i < keys.length; i++ ) + { + objects.remove( keys[i] ); + } + + releaseWriteLock( ); + } + + /** + * @see java.util.Map#containsKey(java.lang.Object) + */ + public boolean containsKey( Object key ) + { + enteringRead( ); + + boolean ret =3D objects.containsKey( key ); + exitingRead( ); + + return ret; + } + + /** + * @see java.util.Map#containsValue(java.lang.Object) + */ + public boolean containsValue( Object value ) + { + enteringRead( ); + + boolean ret =3D objects.containsValue( value ); + exitingRead( ); + + return ret; + } + + /** + * @see java.util.Map#isEmpty() + */ + public boolean isEmpty( ) + { + if( objects.size( ) =3D=3D 0 ) + { + return true; + } + else + { + return false; + } + } + + /** + * @see java.util.Map#putAll(java.util.Map) + */ + public void putAll( Map map ) + { + if( map =3D=3D null ) + { + return; + } + + obtainWriteLock( ); + + //put this in a try block as the underlying map may + //throw an exception (for example if the given Map is modified, + //contains erroneuous values), and we want to ensure the=20 + //writelock is released + try + { + objects.putAll( map ); + } + finally + { + releaseWriteLock( ); + } + } + + /** + * @see java.util.Map#size() + */ + public int size( ) + { + return objects.size( ); + } + + /** + * @todo : return a non modifiable or locking Collection?? + * @see java.util.Map#values() + */ + public Collection values( ) + { + if( values =3D=3D null ) + { + values =3D new ThreadSafeCollection( this, objects.values( = ) ); + } + + return values; + } + + public void clear( ) + { + obtainWriteLock( ); + objects.clear( ); + releaseWriteLock( ); + } + + /** + * Obtain a writelock. This method will block until all current read= ers + * have finished. Any attempted reads once this lock is obtained wil= l + * also block until this write has completed. + * + */ + private void obtainWriteLock( ) + { + synchronized( lock ) + { + while( writeLock ) + { + //wait till the current writer has finished + try + { + lock.wait( ); + } + catch( InterruptedException e ) + { + } + } + + //only thread which got this far, + //notify intention to all to do + //a write + writeLock =3D true; + + //wait till all the readers have finished. + //Need to do this as some reads may take a long + //time if the Map is large. + while( readers > 0 ) + { + try + { + lock.wait( ); + } + catch( InterruptedException e ) + { + } + } + } + } + + /** + * Release the write lock and notify and waiting readers to continue. + * + */ + private synchronized void releaseWriteLock( ) + { + //only the current thread which holds + //the lock can do this + synchronized( lock ) + { + writeLock =3D false; + + //and notify waiting readers and=20 + //writers. + lock.notifyAll( ); + } + } + + /** + * Takes part in the read/write locking of the ThreadedMap + * + * <p>Created on 17/06/2003</p> + * + * @author <a href=3D"mailto:[email protected]">Bert van Brakel</a= > + * + * @version $Revision$ + */ + class ThreadSafeSet implements Set + { + private final Set set; + private final ThreadSafeMap map; + + ThreadSafeSet( ThreadSafeMap parent, Set set ) + { + this.set =3D set; + this.map =3D parent; + } + + /** + * @param o + * @return + */ + public boolean add( Object o ) + { + map.obtainWriteLock( ); + + boolean ret =3D set.add( o ); + map.releaseWriteLock( ); + + return ret; + } + + /** + * @param c + * @return + */ + public boolean addAll( Collection c ) + { + map.obtainWriteLock( ); + + boolean ret =3D set.addAll( c ); + map.releaseWriteLock( ); + + return ret; + } + + /** + * + */ + public void clear( ) + { + map.obtainWriteLock( ); + set.clear( ); + map.releaseWriteLock( ); + } + + /** + * @param o + * @return + */ + public boolean contains( Object o ) + { + map.enteringRead( ); + + boolean result =3D set.contains( o ); + map.exitingRead( ); + + return result; + } + + /** + * @param c + * @return + */ + public boolean containsAll( Collection c ) + { + map.enteringRead( ); + + boolean result =3D set.containsAll( c ); + map.exitingRead( ); + + return result; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals( Object obj ) + { + map.enteringRead( ); + + boolean result =3D set.equals( obj ); + map.exitingRead( ); + + return result; + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode( ) + { + map.enteringRead( ); + + int ret =3D set.hashCode( ); + map.exitingRead( ); + + return ret; + } + + /** + * @return + */ + public boolean isEmpty( ) + { + return set.isEmpty( ); + } + + /** + * @return + */ + public Iterator iterator( ) + { + return new ThreadSafeIterator( map, set.iterator( ) ); + } + + /** + * @param o + * @return + */ + public boolean remove( Object o ) + { + map.obtainWriteLock( ); + + boolean ret =3D set.remove( o ); + map.releaseWriteLock( ); + + return ret; + } + + /** + * @param c + * @return + */ + public boolean removeAll( Collection c ) + { + map.obtainWriteLock( ); + + boolean ret =3D set.removeAll( c ); + map.releaseWriteLock( ); + + return ret; + } + + /** + * @param c + * @return + */ + public boolean retainAll( Collection c ) + { + map.obtainWriteLock( ); + + boolean ret =3D set.retainAll( c ); + map.releaseWriteLock( ); + + return ret; + } + + /** + * @return + */ + public int size( ) + { + return set.size( ); + } + + /** + * @return + */ + public Object[] toArray( ) + { + return set.toArray( ); + } + + /** + * @param a + * @return + */ + public Object[] toArray( Object[] a ) + { + return set.toArray( a ); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString( ) + { + return set.toString( ); + } + } + + class ThreadSafeIterator implements Iterator + { + private final Iterator iter; + private final ThreadSafeMap map; + + /** + * Constructor + * + * + */ + public ThreadSafeIterator( ThreadSafeMap lockMap, Iterator deleg= ate ) + { + super( ); + this.iter =3D delegate; + this.map =3D lockMap; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals( Object obj ) + { + return iter.equals( obj ); + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode( ) + { + return iter.hashCode( ); + } + + /** + * @return + */ + public boolean hasNext( ) + { + return iter.hasNext( ); + } + + /** + * @return + */ + public Object next( ) + { + map.enteringRead( ); + + Object ret =3D null; + + try + { + //within try incase something gets modified and it + //throws a wobbly, though shouldn't happen with=20 + //the locks + ret =3D iter.next( ); + } + finally + { + map.exitingRead( ); + } + + return ret; + } + + /** + * + */ + public void remove( ) + { + try + { + map.obtainWriteLock( ); + iter.remove( ); + } + finally + { + map.releaseWriteLock( ); + } + } + + /** + * @see java.lang.Object#toString() + */ + public String toString( ) + { + return iter.toString( ); + } + } + + class ThreadSafeCollection implements Collection + { + private final ThreadSafeMap map; + private Collection col; + + ThreadSafeCollection( ThreadSafeMap map, Collection col ) + { + this.col =3D col; + this.map =3D map; + } + + /** + * @see java.util.Collection#add(java.lang.Object) + */ + public boolean add( Object o ) + { + // not supported + return false; + } + + /** + * @see java.util.Collection#addAll(java.util.Collection) + */ + public boolean addAll( Collection c ) + { + // not supported + return false; + } + + /** + * @see java.util.Collection#clear() + */ + public void clear( ) + { + map.clear( ); + } + + /** + * @see java.util.Collection#contains(java.lang.Object) + */ + public boolean contains( Object o ) + { + return col.contains( o ); + } + + /** + * @see java.util.Collection#containsAll(java.util.Collection) + */ + public boolean containsAll( Collection c ) + { + map.enteringRead( ); + + boolean ret =3D col.containsAll( c ); + map.exitingRead( ); + + return ret; + } + + /** + * @see java.util.Collection#isEmpty() + */ + public boolean isEmpty( ) + { + if( map.size( ) =3D=3D 0 ) + { + return true; + } + else + { + return false; + } + } + + /** + * @see java.util.Collection#iterator() + */ + public Iterator iterator( ) + { + map.enteringRead( ); + + Iterator iter =3D new ThreadSafeIterator( map, col.iterator(= ) ); + map.exitingRead( ); + + return iter; + } + + /** + * @see java.util.Collection#remove(java.lang.Object) + */ + public boolean remove( Object o ) + { + map.obtainWriteLock( ); + + boolean ret =3D col.remove( o ); + map.releaseWriteLock( ); + + return ret; + } + + /** + * @see java.util.Collection#removeAll(java.util.Collection) + */ + public boolean removeAll( Collection c ) + { + map.obtainWriteLock( ); + + boolean ret =3D col.removeAll( c ); + map.releaseWriteLock( ); + + return ret; + } + + /** + * @see java.util.Collection#retainAll(java.util.Collection) + */ + public boolean retainAll( Collection c ) + { + map.obtainWriteLock( ); + + boolean ret =3D col.retainAll( c ); + map.releaseWriteLock( ); + + return ret; + } + + /** + * @see java.util.Collection#size() + */ + public int size( ) + { + return map.size( ); + } + + /** + * @see java.util.Collection#toArray() + */ + public Object[] toArray( ) + { + map.enteringRead( ); + + Object[] ret =3D col.toArray( ); + map.exitingRead( ); + + return ret; + } + + /** + * @see java.util.Collection#toArray(java.lang.Object[]) + */ + public Object[] toArray( Object[] a ) + { + map.enteringRead( ); + + Object[] ret =3D col.toArray( a ); + map.exitingRead( ); + + return ret; + } + } +} Index: src/java/org/apache/plexus/util/Tracer.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/java/org/apache/plexus/util/Tracer.java diff -N src/java/org/apache/plexus/util/Tracer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/java/org/apache/plexus/util/Tracer.java 25 Jul 2003 03:50:41 -000= 0 @@ -0,0 +1,39 @@ +package org.apache.plexus.util; + +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * Convenience class to handle throwable stacktraces + *=20 + * <p>Created on 18/06/2003</p> + *=20 + * @author <a href=3D"mailto:[email protected]">Bert van Brakel</a> + * @version $Revision$ + */ +public class Tracer +{ + + /** + * Constructor + *=20 + *=20 + */ + private Tracer() + { + super(); + } + =20 + /** + * Return the throwable stack trace as a string + * */ + public static String traceToString(Throwable t) + { + if( t=3D=3D null) + return null; + StringWriter sw =3D new StringWriter(); + t.printStackTrace(new PrintWriter(sw)); + return sw.toString(); + } + +} Index: src/test/org/apache/plexus/DefaultPlexusContainerTest.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/test/org/apache/plexus/Def= aultPlexusContainerTest.java,v retrieving revision 1.6 diff -u -r1.6 DefaultPlexusContainerTest.java --- src/test/org/apache/plexus/DefaultPlexusContainerTest.java 18 Jul 200= 3 03:40:27 -0000 1.6 +++ src/test/org/apache/plexus/DefaultPlexusContainerTest.java 25 Jul 200= 3 03:50:43 -0000 @@ -4,9 +4,11 @@ =20 import java.io.InputStream; import java.io.InputStreamReader; +import java.util.Iterator; =20 -import org.apache.plexus.service.repository.instance.InstanceManager; import org.apache.plexus.service.repository.factory.ComponentFactory; +import org.apache.plexus.util.AbstractTestThread; +import org.apache.plexus.util.TestThreadManager; =20 /** * @author <a href=3D"mailto:[email protected]">Jason van Zyl</a> @@ -54,11 +56,13 @@ container.start(); =20 int defaultComponents =3D 0; - int testComponents =3D 6; + int testComponents =3D 7; =20 // These are some default components that we used internally. Th= ese components don't // usually need to be replaced but they can be if the user desir= es. =20 + //NOTE: these have now been included through a differnet method + /* // Per-lookup instance manager. InstanceManager plim =3D (InstanceManager) container.getComponentRepository().lookup(= InstanceManager.ROLE + "per-lookup" ); @@ -76,7 +80,7 @@ (InstanceManager) container.getComponentRepository().lookup(= InstanceManager.ROLE + "singleton" ); assertNotNull( sim ); defaultComponents++; - +*/ // Java Component factory. // Singleton instance manager. ComponentFactory jcf =3D @@ -94,6 +98,7 @@ assertEquals( true, container.getComponentRepository().hasServic= e( ServiceA.ROLE ) ); assertEquals( true, container.getComponentRepository().hasServic= e( ServiceB.ROLE ) ); assertEquals( true, container.getComponentRepository().hasServic= e( ServiceC.ROLE + "only-instance" ) ); + assertEquals( true, container.getComponentRepository().hasService( Ser= viceG.ROLE) ); =20 // -------------------------------------------------------------= --------- // ServiceA @@ -122,18 +127,20 @@ container.getComponentRepository().release( serviceA ); =20 // Now we have released the component so there should be no inst= antiated services. - assertEquals( 0 + defaultComponents, container.getComponentRepos= itory().instantiatedComponents() ); + //no longer correct! The instance managers may keep an instance = alive. +// assertEquals( 0 + defaultComponents, container.getComponentRep= ository().instantiatedComponents() ); =20 // Make sure the number of configured components is still 3. assertEquals( testComponents + defaultComponents, container.getC= omponentRepository().configuredComponents() ); =20 + // make sure we get the same instance back everytime DefaultServiceA a0 =3D (DefaultServiceA) container.getComponentR= epository().lookup( ServiceA.ROLE ); DefaultServiceA a1 =3D (DefaultServiceA) container.getComponentR= epository().lookup( ServiceA.ROLE ); DefaultServiceA a2 =3D (DefaultServiceA) container.getComponentR= epository().lookup( ServiceA.ROLE ); =20 assertTrue( a0.equals( a1 ) ); assertTrue( a1.equals( a2 ) ); - assertTrue( a2.equals( a0 ) ); + assertTrue( a2.equals( a0 ) ); =20 =20 // -------------------------------------------------------------= --------- // ServiceB @@ -199,6 +206,87 @@ assertNotSame( serviceD2, serviceD3 ); assertNotSame( serviceD1, serviceD3 ); =20 + + // -------------------------------------------------------------= --------- + // ServiceG - singleton-keep-alive + // + // Implements all the standard Avalon lifecycle phases. + // -------------------------------------------------------------= --------- + + // Retrieve an instance of service G. + DefaultServiceG serviceG =3D + (DefaultServiceG) container.getComponentRepository().lookup(= ServiceG.ROLE); + + // Make sure the service is alive. + assertNotNull(serviceG); + + // Make sure the component went through all the lifecycle phases + assertEquals(true, serviceG.enableLogging); + assertEquals(true, serviceG.contextualize); + assertEquals(true, serviceG.service); + assertEquals(true, serviceG.configure); + assertEquals(true, serviceG.initialize); + assertEquals(true, serviceG.start); + + // Now how do we make sure it has been released and decomissione= d + // properly. + container.getComponentRepository().release(serviceG); + + // make sure we get the same instance back everytime + DefaultServiceG g0 =3D + (DefaultServiceG) container.getComponentRepository().lookup(= ServiceG.ROLE); + DefaultServiceG g1 =3D + (DefaultServiceG) container.getComponentRepository().lookup(= ServiceG.ROLE); + DefaultServiceG g2 =3D + (DefaultServiceG) container.getComponentRepository().lookup(= ServiceG.ROLE); + + assertTrue(g0.equals(g1)); + assertTrue(g1.equals(g2)); + assertTrue(g2.equals(g0)); + + //Now try it again in seperate threads.Make sure the instance is= the same for all threads =20 + TestThreadManager reg =3D new TestThreadManager(this); + for (int i =3D 0; i < 5; i++) + { + SingletonComponentTestThread st =3D + new SingletonComponentTestThread(reg, container, Service= G.ROLE, g0); + reg.registerThread(st); + } + reg.runTestThreads(); + + while (reg.isStillRunningThreads()) + { + //wait until all threads have finished execution + synchronized (this) + { + try + { + wait(); + } + catch (InterruptedException e) + { + } + } + } + + assertEquals("Expected 5 test threads to of run", reg.getRunThre= ads().size(), 5); + //now test if any components were returned which was not the sam= e instance + if (reg.hasFailedThreads()) + { + //collect all failed tests + StringBuffer out =3D new StringBuffer(); + Iterator iter =3D reg.getFailedTests().iterator(); + String nl =3D System.getProperty("line.separator"); + while (iter.hasNext()) + { + out.append(nl); + out.append(((SingletonComponentTestThread) iter.next()).= getErrorMsg()); + } + fail( + "Singleton component 'ServiceG' being instantiated multi= ple times. Failed test threads: " + + out); + } + =09 // -------------------------------------------------------------= --------- // Per-lookup component // -------------------------------------------------------------= --------- @@ -232,5 +320,70 @@ assertEquals( true, serviceE2.start ); =20 assertNotSame( serviceE1, serviceE2 ); + =20 + container.dispose(); + } +} + +/** + * Thread which tests whether a singlton Component is actually treated a= s a singlton, or whether + * multiple instances are returned. + *=20 + * @author <a href=3D"mailto:[email protected]">Bert van Brakel</a> + */ +class SingletonComponentTestThread extends AbstractTestThread +{ + private Object expectedComponent; + private Object returnedComponent; + private PlexusContainer container; + private String role; + /** + *=20 + */ + public SingletonComponentTestThread(PlexusContainer container,String= role,Object expectedComponent) + { + super(); + this.expectedComponent =3D expectedComponent; + this.container =3D container; + this.role =3D role; + } + + /** + * @param registry + */ + public SingletonComponentTestThread(TestThreadManager registry,Plexu= sContainer container,String role,Object expectedComponent) + { + super(registry); + this.expectedComponent =3D expectedComponent; + this.container =3D container; + this.role =3D role; + } + + /* (non-Javadoc) + * @see org.apache.plexus.util.AbstractRegisteredThread#doRun() + */ + public void doRun() throws Throwable + { + try + { + returnedComponent =3D container.getComponentRepository().lookup( role= ); + if( returnedComponent =3D=3D null ) + { + setErrorMsg("Null component returned"); + } + else if( returnedComponent =3D=3D expectedComponent) + { + setPassed(true); + } + else + { + setErrorMsg("Returned component was a different instance. Expected=3D= " + expectedComponent + ", got=3D" + returnedComponent); + } + } + finally + { + container.getComponentRepository().release( returnedComponent ); + } } + } Index: src/test/org/apache/plexus/DefaultServiceG.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/test/org/apache/plexus/DefaultServiceG.java diff -N src/test/org/apache/plexus/DefaultServiceG.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/test/org/apache/plexus/DefaultServiceG.java 25 Jul 2003 03:50:43 = -0000 @@ -0,0 +1,77 @@ +package org.apache.plexus; + +import org.apache.plexus.logging.AbstractLogEnabled; +import org.apache.avalon.framework.context.Contextualizable; +import org.apache.avalon.framework.context.Context; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.Configurable; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.service.Serviceable; +import org.apache.avalon.framework.activity.Initializable; +import org.apache.avalon.framework.activity.Startable; +import org.apache.avalon.framework.logger.Logger; + +/** This service implements all the start phases: + * + * LogEnabled + * Contexualize + * Serviceable + * Configurable + * Initializable + * Startable + * + */ +public class DefaultServiceG + extends AbstractLogEnabled + implements ServiceG, Contextualizable, Serviceable, Configurable, In= itializable, Startable +{ + boolean enableLogging; + boolean contextualize; + boolean service; + boolean configure; + boolean initialize; + boolean start; + boolean stop; + + // -----------------------------------------------------------------= ----- + // Lifecylce Management + // -----------------------------------------------------------------= ----- + + public void enableLogging( Logger logger ) + { + enableLogging =3D true; + } + + public void contextualize( Context context ) + { + contextualize =3D true; + } + + public void service( ServiceManager serviceManager ) + { + service =3D true; + } + + public void configure( Configuration configuration ) + { + configure =3D true; + } + + public void initialize() + throws Exception + { + initialize =3D true; + } + + public void start() + throws Exception + { + start =3D true; + } + + public void stop() + throws Exception + { + stop =3D true; + } +} Index: src/test/org/apache/plexus/ServiceG.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/test/org/apache/plexus/ServiceG.java diff -N src/test/org/apache/plexus/ServiceG.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/test/org/apache/plexus/ServiceG.java 25 Jul 2003 03:50:43 -0000 @@ -0,0 +1,6 @@ +package org.apache.plexus; + +public interface ServiceG +{ + static String ROLE =3D ServiceG.class.getName(); +} Index: src/test/org/apache/plexus/configuration.xml =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/test/org/apache/plexus/con= figuration.xml,v retrieving revision 1.7 diff -u -r1.7 configuration.xml --- src/test/org/apache/plexus/configuration.xml 31 May 2003 22:02:43 -00= 00 1.7 +++ src/test/org/apache/plexus/configuration.xml 25 Jul 2003 03:50:43 -00= 00 @@ -1,7 +1,12 @@ <plexus> =20 <configurations-directory>${basedir}/src/test-input/configurations-dir= ectory</configurations-directory> - + <logging> + <implementation>org.apache.plexus.logging.ConsoleLoggerManager</implem= entation> + <logger> + <threshold>ERROR</threshold> + </logger> + </logging> <service-repository> <implementation>org.apache.plexus.service.repository.DefaultComponen= tRepository</implementation> </service-repository> @@ -79,6 +84,20 @@ <instantiation-strategy>per-lookup</instantiation-strategy> <configuration/> </component> + =20 + =20 + <!-- + | + | G Service + | + --> + <component> + <role>org.apache.plexus.ServiceG</role> + <implementation>org.apache.plexus.DefaultServiceG</implementation> + <instantiation-strategy>singleton-keep-alive</instantiation-strate= gy> + <configuration/> + </component> + =20 =20 </components> =20 Index: src/test/org/apache/plexus/lifecycle/avalon/AvalonServiceSelectorT= est.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/plexus/plexus-container/src/test/org/apache/plexus/lif= ecycle/avalon/AvalonServiceSelectorTest.java,v retrieving revision 1.1 diff -u -r1.1 AvalonServiceSelectorTest.java --- src/test/org/apache/plexus/lifecycle/avalon/AvalonServiceSelectorTest= .java 10 May 2003 16:39:30 -0000 1.1 +++ src/test/org/apache/plexus/lifecycle/avalon/AvalonServiceSelectorTest= .java 25 Jul 2003 03:50:43 -0000 @@ -22,7 +22,7 @@ =20 public void testSelector() throws Exception { - ServiceSelector selector =3D (ServiceSelector) getComponent( Ser= viceC.ROLE + "Selector" ); + ServiceSelector selector =3D (ServiceSelector) lookup( ServiceC.= ROLE + "Selector" ); =20 assertTrue( selector !=3D null ); assertTrue( selector.isSelectable( "only-instance" ) ); Index: src/test/org/apache/plexus/util/AbstractTestThread.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/test/org/apache/plexus/util/AbstractTestThread.java diff -N src/test/org/apache/plexus/util/AbstractTestThread.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/test/org/apache/plexus/util/AbstractTestThread.java 25 Jul 2003 0= 3:50:44 -0000 @@ -0,0 +1,248 @@ +package org.apache.plexus.util; + +/** + * A thread which is registered with a ThreadRegistry and notifies it wh= en it has completed + * running. Collects any errors and makes it available for analysis. =20 + *=20 + * <p>Created on 1/07/2003</p> + * + * @author <a href=3D"mailto:[email protected]">Bert van Brakel</a> + * @version $Revision$ + */ +public abstract class AbstractTestThread implements Runnable +{ + //~ Instance fields ------------------------------------------------= ---------------------------- + private String name; + + public static final boolean DEBUG =3D true; + + private boolean isRunning =3D false; + + /** Error msg provided by implementing class (of why the test failed= ) */ + private String errorMsg =3D null; + + /** The registry to notify on completion */ + private TestThreadManager registry; + + /** The error thrown when running the test. Not neccesarily a test f= ailuer as some tests + * may test for an exception */ + private Throwable error; + + /** If the thread has been run */ + private boolean hasRun =3D false; + + /** Flag indicating if the test has passed. Some test might require = an=20 + * exception so using the error to determine if the test has passed = is + * not sufficient. + */ + private boolean passed =3D false; + + //~ Constructors ---------------------------------------------------= ---------------------------- + + /** + * Constructor + *=20 + * <p>Remember to call <code>setThreadRegistry(ThreadRegistry)</code= > + */ + public AbstractTestThread() + { + super(); + } + + public AbstractTestThread(TestThreadManager registry) + { + super(); + setThreadRegistry(registry); + } + + //~ Methods --------------------------------------------------------= ---------------------------- + + /**=20 + * @return + */ + public Throwable getError() + { + return error; + } + + /**=20 + * Resets the test back to it's state before starting. If the test + * is currently running this method will block until the test has + * finished running. Subclasses should call this method if + * overriding it. + *=20 + * */ + public void reset() + { + //shouldn't reset until the test has finished running + synchronized (this) + { + while (isRunning) + { + try + { + wait(); + } + catch (InterruptedException e) + { + =20 + } =20 + } + errorMsg =3D null; + error =3D null; + hasRun =3D false; + passed =3D false; + } + } + + /** + * Start this TestThread running. If the test is currently running then + * this method does nothing. + * + */ + public final void start() + { + //shouldn't have multiple threads running this test at the same tim= e + synchronized (this) + { + if (isRunning =3D=3D false) + { + isRunning =3D true; + Thread t =3D new Thread(this); + t.start(); + } + } + } + + /**=20 + * @return + */ + public String getErrorMsg() + { + return errorMsg; + } + + /**=20 + * @return + */ + public boolean hasFailed() + { + return !passed; + } + + /**=20 + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean hasPassed() + { + return passed; + } + + /**=20 + * Don't override this. Calls <code>doRun()</code> + * + * @see java.lang.Runnable#run() + */ + public final void run() + { + if (registry =3D=3D null) + { + throw new IllegalArgumentException("The ThreadRegistry is nu= ll. Ensure this is set before running this thread"); + } + passed =3D false; + try + { + doRun(); + } + catch (Throwable t) + { + error =3D t; + } + + registry.completed(this); + hasRun =3D true; + isRunning =3D false; + //notify objects with blocked methods which are waiting + //on this test to complete running + synchronized( this) + { + notifyAll(); + } + } + + /**=20 + * Override this to run your custom test + * + * @throws Throwable + */ + public abstract void doRun() throws Throwable; + + /**=20 + * Set the registry this thread should notify when it has completed = running + * + * @param registry + */ + public void setThreadRegistry(TestThreadManager registry) + =20 + { + this.registry =3D registry; + } + + /**=20 + * Test if the test has run + * + * @return + */ + public boolean hasRun() + { + return hasRun; + } + /** + * @param throwable + */ + public void setError(Throwable throwable) + { + error =3D throwable; + } + + /** + * @param string + */ + public void setErrorMsg(String string) + { + errorMsg =3D string; + } + + /** + * @param b + */ + public void setPassed(boolean b) + { + passed =3D b; + } + /** + * @return + */ + public String getName() + { + return name; + } + + /** + * @param string + */ + public void setName(String string) + { + name =3D string; + } + + private final void debug(String msg) + { + if (DEBUG) + { + System.out.println(this +":" + msg); + } + } +} Index: src/test/org/apache/plexus/util/SweeperPoolTest.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/test/org/apache/plexus/util/SweeperPoolTest.java diff -N src/test/org/apache/plexus/util/SweeperPoolTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/test/org/apache/plexus/util/SweeperPoolTest.java 25 Jul 2003 03:5= 0:45 -0000 @@ -0,0 +1,190 @@ +package org.apache.plexus.util; + +import java.util.Vector; + +import junit.framework.TestCase; + +/** + * Created on 21/06/2003 + *=20 + * @author <a href=3D"mailto:[email protected]">Bert van Brakel</a> + * @version $Revision$ + */ +public class SweeperPoolTest extends TestCase { + /** The pool under test */ + TestObjectPool pool; + /** A bunch of object to pool */ + Object o1; + Object o2; + Object o3; + Object o4; + Object o5; + Object o6; + /** + * Constructor + *=20 + *=20 + */ + public SweeperPoolTest() { + super(); + } + + /** + * Constructor + *=20 + * @param arg0 + */ + public SweeperPoolTest(String arg0) { + super(arg0); + } + + /** + * Test the pool limits it's size, and disposes unneeded objects correc= tly + * + */ + public void testMaxSize() { + int sweepInterval =3D 0; + int initialCapacity =3D 5; + int maxSize =3D 2; + int minSize =3D 1; + int triggerSize =3D 2; + + pool =3D + new TestObjectPool( + maxSize, + minSize, + initialCapacity, + sweepInterval, + triggerSize); + + Object tmp =3D pool.get(); + assertNull("Expected object from pool to be null", tmp); + pool.put(o1); + assertEquals("Expected pool to contain 1 object", 1, pool.getSize()); + tmp =3D pool.get(); + assertSame( + "Expected returned pool object to be the same as the one put in", + tmp, + o1); + pool.put(o1); + pool.put(o2); + assertEquals("Expected pool to contain 2 objects", 2, pool.getSize()); + pool.put(o3); + assertEquals( + "Expected pool to contain only a maximuim of 2 objects.", + 2, + pool.getSize()); + assertEquals( + "Expected 1 disposed pool object", + 1, + pool.testGetDisposedObjects().size()); + tmp =3D pool.testGetDisposedObjects().iterator().next(); + + tmp =3D pool.get(); + assertEquals( + "Expected pool size to be 1 after removing one object", + 1, + pool.getSize()); + Object tmp2 =3D pool.get(); + assertEquals( + "Expected pool size to be 0 after removing 2 objects", + 0, + pool.getSize()); + assertNotSame("Expected returned objects to be differnet", tmp, tmp2); + + } + + public void testSweepAndTrim1() { + //test trigger=20 + int sweepInterval =3D 1; + int initialCapacity =3D 5; + int maxSize =3D 5; + int minSize =3D 1; + int triggerSize =3D 2; + + pool =3D + new TestObjectPool( + maxSize, + minSize, + initialCapacity, + sweepInterval, + triggerSize); + pool.put(o1); + pool.put(o2); + pool.put(o3); + pool.put(o4); + //give the seeper some time to run + synchronized (this) { + try { + wait(2 * 1000); + } catch (InterruptedException e) { + fail( + "Unexpected exception thrown. e=3D" + + Tracer.traceToString(e)); + } + } + assertEquals( + "Expected pool to only contain 1 object", + 1, + pool.getSize()); + assertEquals( + "Expected 3 diposed objects", + 3, + pool.testGetDisposedObjects().size()); + + } + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + + o1 =3D new Object(); + o2 =3D new Object(); + o3 =3D new Object(); + o4 =3D new Object(); + o5 =3D new Object(); + o6 =3D new Object(); + super.setUp(); + } + + /** + * @see junit.framework.TestCase#tearDown() + */ + protected void tearDown() throws Exception { + pool.dispose(); + pool =3D null; + super.tearDown(); + + } + + class TestObjectPool extends SweeperPool { + private Vector disposedObjects =3D new Vector(); + + public TestObjectPool( + int maxSize, + int minSize, + int intialCapacity, + int sweepInterval, + int triggerSize) { + super(maxSize, minSize, intialCapacity, sweepInterval, triggerSize); + } + + public void reset() { + disposedObjects.clear(); + } + + /** + * @see nz.co.bonzo.beans.castor.pool.ObjectPool#objectDisposed(java.l= ang.Object) + */ + public void objectDisposed(Object obj) { + disposedObjects.add(obj); + } + + public Vector testGetDisposedObjects() { + return disposedObjects; + } + + } + +} Index: src/test/org/apache/plexus/util/TestThreadManager.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/test/org/apache/plexus/util/TestThreadManager.java diff -N src/test/org/apache/plexus/util/TestThreadManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/test/org/apache/plexus/util/TestThreadManager.java 25 Jul 2003 03= :50:45 -0000 @@ -0,0 +1,170 @@ +package org.apache.plexus.util; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Vector; +import java.util.logging.Logger; +/** + * Manages a number of test threads, which notify this instance when th= ey have=20 + * completed. Allows TestCases to easily start and manage multiple test = threads. =20 + *=20 + * <p>Created on 9/06/2003</p> + * + * @author <a href=3D"mailto:[email protected]">Bert van Brakel</a> + * @version $Revision$ + *=20 + */ +public class TestThreadManager +{ + //~ Instance fields ---------------------------------------------------= ------------------------- + + /** Test threads which have completed running */ + private Collection runThreads =3D new Vector(); + /** Test threads still needing to be run, or are currently running*/ + private Collection toRunThreads =3D new Vector(); + private Logger logger =3D null; + /** Any test threads which failed */ + private Vector failedThreads =3D new Vector(); + + /**The object to notify when all the test threads have complleted. Clie= nts use this + * to lock on (wait) while waiting for the tests to complete*/ + private Object notify =3D null; + + //~ Constructors ------------------------------------------------------= ------------------------- + + public TestThreadManager(Object notify) + { + super(); + this.notify =3D notify; + } + + //~ Methods -----------------------------------------------------------= ------------------------- + + /**=20 + * @return + */ + public Collection getRunThreads() + { + return runThreads; + } + + public void runTestThreads() + { + failedThreads.clear(); + //use an array as the tests may run very quickly=20 + //and modify the toRunThreads vector and hence + //cause a Concurrent ModificationException on an + //iterator + Object[] threads =3D toRunThreads.toArray(); + for (int i =3D 0; i < threads.length; i++) + { + //System.out.println("Starting thread " + i +" ..." ); + ((AbstractTestThread) threads[i]).start(); + } + } + + public Collection getFailedTests() + { =20 + return failedThreads; + } + + + public boolean hasFailedThreads() + { + if( failedThreads.size() =3D=3D 0) + { + return false; + } + else + return true; + } + /**=20 + * Determine if any threads are still running! + * + * @return DOCUMENT ME! + */ + public boolean isStillRunningThreads() + { + return !toRunThreads.isEmpty(); + } + + /**=20 + * @return + */ + public Collection getToRunThreads() + { + return toRunThreads; + } + + /**=20 + * DOCUMENT ME! + */ + public void clear() + { + toRunThreads.clear(); + runThreads.clear(); + failedThreads.clear(); + } + + /* (non-Javadoc) + * @see java.util.Collection#remove(java.lang.Object) + */ + public void completed(AbstractTestThread thread) + { + toRunThreads.remove(thread); + runThreads.add(thread); + if (thread.hasFailed()) + { + failedThreads.add(thread); + } + //wakeup thread which is waiting for the threads to complete + //execution + if (toRunThreads.isEmpty()) + { + synchronized (notify) + { + notify.notify(); + } + } + } + + /**=20 + * Overide this to add your own stuff. Called after=20 + * <code>registerThread(Object)</code> + * + * @param thread DOCUMENT ME! + */ + public void doRegisterThread(AbstractTestThread thread) + { + } + + public final void registerThread(AbstractTestThread thread) + { + thread.setThreadRegistry( this ); + if( toRunThreads.contains( thread ) =3D=3D false ) + { =09 + toRunThreads.add(thread); + doRegisterThread(thread); + } + =20 + } + + /**=20 + * Put all the runThreads back in the que to be run again and + * clear the failedTest collection + */ + public void reset() + { + toRunThreads.clear(); + Iterator iter =3D runThreads.iterator(); =09 + while (iter.hasNext()) + { + AbstractTestThread test =3D (AbstractTestThread) iter.next(); + test.reset(); + registerThread( test ); + } + + runThreads.clear(); + failedThreads.clear(); + } +} Index: src/test/org/apache/plexus/util/ThreadSafeMapTest.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: src/test/org/apache/plexus/util/ThreadSafeMapTest.java diff -N src/test/org/apache/plexus/util/ThreadSafeMapTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/test/org/apache/plexus/util/ThreadSafeMapTest.java 25 Jul 2003 03= :50:46 -0000 @@ -0,0 +1,185 @@ +package org.apache.plexus.util; + +import java.util.Iterator; + +import junit.framework.TestCase; + +/** + * Created on 21/06/2003 + *=20 + * @author <a href=3D"mailto:[email protected]">Bert van Brakel</a> + * @version $Revision$ + */ +public class ThreadSafeMapTest extends TestCase +{ + private ThreadSafeMap map; + + /** + * Constructor + *=20 + *=20 + */ + public ThreadSafeMapTest() + { + super(); + } + + /** + * Constructor + *=20 + * @param arg0 + */ + public ThreadSafeMapTest(String name) + { + super(name); + } + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception + { + // TODO Auto-generated method stub + super.setUp(); + } + + /** + * @see junit.framework.TestCase#tearDown() + */ + protected void tearDown() throws Exception + { + // TODO Auto-generated method stub + super.tearDown(); + } + + public void test() + { + map =3D new ThreadSafeMap(); + + TestThreadManager registry =3D new TestThreadManager(this); + //make the readers and writers. + //mix them up incase VM gives startup times + //dependent on thread creation order + for (int i =3D 0; i < 20; i++) + { + //use the same key, but different values, so there will be c= ontention + Object key =3D Integer.toString(i); + //a writer + TestMapThread wTest =3D new TestMapThread(map, Integer.toStr= ing(i), new Object(), false); + registry.registerThread(wTest); + //a reader + TestMapThread rTest =3D new TestMapThread(map, key, new Obje= ct(), true); + registry.registerThread(rTest); + } + //now run the threads + registry.runTestThreads(); + + //now wait for the threads to finish.. + synchronized (this) + { + try + { + wait(); + } + catch (InterruptedException e) + { + //all threads have finished + } + } + //now test for failures... + if (registry.hasFailedThreads()) + { + StringBuffer out =3D new StringBuffer(); + Iterator iter =3D registry.getFailedTests().iterator(); + String nl =3D System.getProperty("line.separator"); + while (iter.hasNext()) + { + TestMapThread test =3D (TestMapThread) iter.next(); + out.append(nl); + out.append(test.getErrorMsg()); + out.append(" Exception=3D" + Tracer.traceToString(test.g= etError())); + } + fail("Failed test threads: " + out); + } + } +} + +class TestMapThread extends AbstractTestThread +{ + private ThreadSafeMap map; + /** Indicates whether to read or write to the map */ + private boolean reader =3D true; + + private Object key; + private Object value; + /** + * Constructor + *=20 + *=20 + */ + public TestMapThread(ThreadSafeMap map, Object key, Object value, bo= olean reader) + { + super(); + this.map =3D map; + this.key =3D key; + this.value =3D value; + this.reader =3D reader; + } + + /** + * @see java.lang.Runnable#run() + */ + public void doRun() + { + try + { + + if (reader) + { + value =3D map.get(key); + } + else + { + map.put(key, value); + } + setPassed(true); + } + catch (Throwable t) + { + if (reader) + { + setErrorMsg("Reader failed "); + } + else + { + setErrorMsg("Writer failed"); + } + setError(t); + } + } + + /** + * @return + */ + public Object getKey() + { + return key; + } + + /** + * @return + */ + public boolean isReader() + { + return reader; + } + + /** + * @return + */ + public Object getValue() + { + return value; + } + +} --=-opuB+PvQQ2sYLuPYhFxN--