You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avalon.apache.org by Berin Loritsch <bl...@apache.org> on 2003/05/23 19:46:16 UTC

[Phase III Release] Postponed until we have a stable Fortress

Thanks to the efforts of Anton Tagunov and others, we have been
shaking out some bugs and other issues.  However until we get
them all resolved, I suggest that we wait until the patches
stop coming in.

In the mean time, Anton, don't stop with bug fixes.  What else
are you seeing?


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


[Patch] #12

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello, Berin!

I have examined more closely what is in CVS and found that all
of the patch #11 is there - wow! I like that! I'm aware that
the value of my patches varies widely, and some are only
marginally usefull, still it honores my vanity :-)

Now, [Patch] #10.1 is still pending, meanwhile here goes one
more my (the very last?) pass over ContextManager.

------Patch #12----------
Files affected: ContextManager.java

removed unused
    ServiceManager m_manager;

remove
    double null-ing of RoleManager.ROLE in m_childContext

moved
    comment on RoleManager not being passed to Container
    to initializeServiceManager

wrapped
    severl lines to fit into 100 characters limit

made a first pass on teaching initializeLoggerManager to
create Log4JLoggerManager alternatively to LogKitLoggerManager

    as I haven't been advised any other way I have implemented
    two ways to detect it's a Log4J conf, not a LogKit one:

    <any-root-element version="log4j">

    (I've accidentially seen on users@ that this is used in Phoenix)

    <log4j:configuration>

    (looks like Log4J native configuration files look like this)

    Now, I'm sure that my section that really creates a Log4J logger
    manager is very weak: I've never really worked with logger
    managers in detail, neither am I familiar with Log4J beyond
    reading Log4J[Conf]LoggerManager.java. See the comments inline
    the code for more details on what I cosidere unimplemented there.
    I have also signed these comments with my name so that everyone
    knows that it's my ignorance not yours :-). Hope these comments
    will go away with time - I understand it's no good to have my
    humble ;-) name there.

    Nevertheless I consider it would be usefull to put in
    any support of Log4J into ContextManager and I believe
    that once it there someone who will actually use it
    will probably further develop it.

    No testcase available with the same reasoning.

    I hope that once (and if :-) this gets to the CVS or release
    cadidate probably

    Peter Severin <ps...@infologic.fr>

    who has expressed interest in it and who has pushed me into
    this patch will help us to test this. Currently the code
    is totally untested - I do not "speak" Log4J :-(

WBR, Anton Tagunov

--- ContextManager.orig 2003-05-29 09:59:36.000000000 +0400
+++ ContextManager.java 2003-05-29 11:13:14.000000000 +0400
@@ -50,6 +50,7 @@
 package org.apache.avalon.fortress.util;
 
 import org.apache.avalon.excalibur.logger.LogKitLoggerManager;
+import org.apache.avalon.excalibur.logger.Log4JConfLoggerManager;
 import org.apache.avalon.excalibur.logger.LoggerManager;
 import org.apache.avalon.fortress.MetaInfoManager;
 import org.apache.avalon.fortress.RoleManager;
@@ -161,8 +162,6 @@
      */
     protected SourceResolver m_defaultSourceResolver;
 
-    protected ServiceManager m_manager;
-
     /**
      * The logger manager in use.
      * Either supplied via rootContext, or created locally.
@@ -292,7 +291,8 @@
         }
         catch ( ContextException ce )
         {
-            final Configuration containerConfig = getConfiguration( CONFIGURATION, CONFIGURATION_URI );
+            final Configuration containerConfig = 
+                    getConfiguration( CONFIGURATION, CONFIGURATION_URI );
 
             if ( containerConfig == null )
             {
@@ -551,10 +551,6 @@
          */
         if ( entryPresent( m_rootContext, RoleManager.ROLE ) )
         {
-            /* RoleManager is a compatibility mechanism to read in ECM roles files.  The role manager will be wrapped
-             * by a MetaInfoManager.  So we hide the RoleManager here from the contaienr implementation.
-             */
-            m_childContext.put( RoleManager.ROLE, null );
             return (RoleManager) m_rootContext.get( RoleManager.ROLE );
         }
 
@@ -574,7 +570,8 @@
         }
 
         // Lookup the context class loader
-        final ClassLoader classLoader = (ClassLoader) m_rootContext.get( ClassLoader.class.getName() );
+        final ClassLoader classLoader = 
+                (ClassLoader) m_rootContext.get( ClassLoader.class.getName() );
 
         // Create a logger for the role manager
         final Logger rmLogger = m_loggerManager.getLoggerForCategory(
@@ -622,18 +619,21 @@
         }
         else
         {
-            final ClassLoader classLoader = (ClassLoader) m_rootContext.get( ClassLoader.class.getName() );
+            final ClassLoader classLoader = 
+                    (ClassLoader) m_rootContext.get( ClassLoader.class.getName() );
 
             if ( !rmSupplied )
             {
-                final FortressRoleManager newRoleManager = new FortressRoleManager( null, classLoader );
+                final FortressRoleManager newRoleManager = 
+                        new FortressRoleManager( null, classLoader );
                 newRoleManager.enableLogging( m_loggerManager.getLoggerForCategory( "system.roles" ) );
                 newRoleManager.initialize();
 
                 roleManager = newRoleManager;
             }
 
-            final ServiceMetaManager metaManager = new ServiceMetaManager( new Role2MetaInfoManager( roleManager ), classLoader );
+            final ServiceMetaManager metaManager = 
+                    new ServiceMetaManager( new Role2MetaInfoManager( roleManager ), classLoader );
 
             metaManager.enableLogging( m_loggerManager.getLoggerForCategory( "system.meta" ) );
             metaManager.initialize();
@@ -694,6 +694,10 @@
             manager.put( SourceResolver.ROLE, m_defaultSourceResolver );
         }
 
+        /**
+         * Role manager won't be passed here as it is now only
+         * an utility for reading ECM role files.
+         */
         manager.put( LoggerManager.ROLE, m_loggerManager );
         manager.put( Sink.ROLE, m_sink );
         manager.put( MetaInfoManager.ROLE, m_metaInfoManager );
@@ -816,42 +820,95 @@
         {
             // Should we set one up?
             // Try to get a configuration for it...
-            Configuration loggerManagerConfig =
-                    getConfiguration( LOGGER_MANAGER_CONFIGURATION, LOGGER_MANAGER_CONFIGURATION_URI );
+            Configuration loggerManagerConfig = getConfiguration( LOGGER_MANAGER_CONFIGURATION,
+                    LOGGER_MANAGER_CONFIGURATION_URI );
+
+            boolean log4j = false;
+
             if ( loggerManagerConfig == null )
             {
                 // Create an empty configuration so that
                 // a default logger can be created.
                 loggerManagerConfig = EMPTY_CONFIG;
             }
+            else
+            {
+                /**
+                 * We rely on namespace handing being turned off in DefaultConfiguration
+                 * builder here. TODO: add code that test
+                 * root element for name "configuration" and for the correct Log4J
+                 * configuration namespace (not currently known to me - Anton Tagunov)
+                 * to survive if a namespace-enabled configuration has been passed to us.
+                 */
+                final String version = loggerManagerConfig.getAttribute( "version", null );
+                if ( "log4j".equals( version ) )
+                {
+                    log4j = true;
+                }
+                else if ( "log4j:configuration".equals( loggerManagerConfig.getName() ) )
+                {
+                    log4j = true;
+                }
+            }
 
             // Resolve a name for the logger, taking the logPrefix into account
-            final String lmDefaultLoggerName = (String) m_rootContext.get( ContextManagerConstants.LOG_CATEGORY );
-            final String lmLoggerName = loggerManagerConfig.getAttribute( "logger", lmDefaultLoggerName + ".system.logkit" );
-
-            // Create the default logger for the Logger Manager.
-            final org.apache.log.Logger lmDefaultLogger =
-                    Hierarchy.getDefaultHierarchy().getLoggerFor( lmDefaultLoggerName );
-            // The default logger is not used until after the logger conf has been loaded
-            //  so it is possible to configure the priority there.
-            lmDefaultLogger.setPriority( Priority.DEBUG );
-
-            // Create the logger for use internally by the Logger Manager.
-            final org.apache.log.Logger lmLogger =
-                    Hierarchy.getDefaultHierarchy().getLoggerFor( lmLoggerName );
-            lmLogger.setPriority( Priority.getPriorityForName(
-                    loggerManagerConfig.getAttribute( "log-level", "DEBUG" ) ) );
-
-            // Setup the Logger Manager
-            final LoggerManager logManager = new LogKitLoggerManager(
-                    lmDefaultLoggerName, Hierarchy.getDefaultHierarchy(),
-                    new LogKitLogger( lmDefaultLogger ), new LogKitLogger( lmLogger ) );
-            ContainerUtil.contextualize( logManager, m_rootContext );
-            ContainerUtil.configure( logManager, loggerManagerConfig );
-
-            assumeOwnership( logManager );
+            final String lmDefaultLoggerName = 
+                    (String) m_rootContext.get( ContextManagerConstants.LOG_CATEGORY );
+            final String lmLoggerName = loggerManagerConfig.getAttribute( "logger", 
+                    lmDefaultLoggerName + ( log4j ? ".system.log4j" : ".system.logkit" ) );
+            
+            if ( log4j )
+            {
+                // this section totally not debuged, just written - Anton Tagunov
+                final Log4JConfLoggerManager logManager = new Log4JConfLoggerManager();
+                logManager.configure( loggerManagerConfig );
+                // Create the logger for use internally by the Logger Manager.
+                Logger lmLogger = logManager.getLoggerForCategory( lmLoggerName );
+                /**
+                 * We rely here on specifics of Log4JConfLoggerManager implementation:
+                 * enableLogging may be called _after_ configure.
+                 */
+                logManager.enableLogging( lmLogger );
+
+                /**
+                 * Now let's compare this immature section with the mature one
+                 * bellow: we haven't made sure the default logger is at DEBUG
+                 * priority level, we haven't considered log-level attribute
+                 * on the root element to set the priority of the logger
+                 * servicing Log4LoggerManager itself. Moreover we have
+                 * enableLogging called after configure on Log4ConfLoggerManager
+                 * which is potentially explosive. Conclusion: this section
+                 * is just a scetch and needs further work. - Anton Tagunov
+                 */
 
-            m_loggerManager = logManager;
+                m_loggerManager = logManager;
+            }
+            else // LogKitLoggerManager
+            {
+                // Create the default logger for the Logger Manager.
+                final org.apache.log.Logger lmDefaultLogger =
+                        Hierarchy.getDefaultHierarchy().getLoggerFor( lmDefaultLoggerName );
+                // The default logger is not used until after the logger conf has been loaded
+                //  so it is possible to configure the priority there.
+                lmDefaultLogger.setPriority( Priority.DEBUG );
+            
+                // Create the logger for use internally by the Logger Manager.
+                final org.apache.log.Logger lmLogger =
+                        Hierarchy.getDefaultHierarchy().getLoggerFor( lmLoggerName );
+                lmLogger.setPriority( Priority.getPriorityForName(
+                        loggerManagerConfig.getAttribute( "log-level", "DEBUG" ) ) );
+
+                // Setup the Logger Manager
+                final LoggerManager logManager = new LogKitLoggerManager(
+                        lmDefaultLoggerName, Hierarchy.getDefaultHierarchy(),
+                        new LogKitLogger( lmDefaultLogger ), new LogKitLogger( lmLogger ) );
+                ContainerUtil.contextualize( logManager, m_rootContext );
+                ContainerUtil.configure( logManager, loggerManagerConfig );
+            
+                assumeOwnership( logManager );
+            
+                m_loggerManager = logManager;
+            }
         }
 
         // Since we now have a LoggerManager, we can update the this.logger field
@@ -889,7 +946,8 @@
         {
             // Should we set one up?
             // Try to get a configuration for it...
-            Configuration instrumentConfig = getConfiguration( INSTRUMENT_MANAGER_CONFIGURATION, INSTRUMENT_MANAGER_CONFIGURATION_URI );
+            Configuration instrumentConfig = getConfiguration( INSTRUMENT_MANAGER_CONFIGURATION, 
+                    INSTRUMENT_MANAGER_CONFIGURATION_URI );
             if ( instrumentConfig == null )
             {
                 // No config.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Patch] #9

Posted by Berin Loritsch <bl...@apache.org>.
Anton Tagunov wrote:
> Hello Berin!
> Hello Developers!
> 
> Uff.. This patch really does several things.
> 


<snip/>

I did not apply all of this patch, because there are some things
about it I don't completely agree with.  Please review the comments
I posted in another mail (which seems to be taking a long time to
get to the list--unless I sent it directly to you for some reason).

Essentially the differences lie here:

Using ServiceManager, not ContextManager to access container services.
That means container services are the things you wanted to grab out
of the context object.

Using a private source resolver.  If the provided source resolver is
not good enough for users of Fortress, they can override it when they
extend the AbstractContainer.  The truth is that what we have is good
enough for most users.  There are some early adopters of Fortress where
this would break what they have.

If we need to apply a patch to what we have, it should be done on what
is in CVS now.  That means that Patch #10 needs to be reimplemented.


-- 
"You know the world is going crazy when the best
rapper is a white guy, the best golfer is a black guy,
The Swiss hold the America's Cup, France is
accusing the US of arrogance, and Germany doesn't want
to go to war. And the 3 most powerful men in America
are named 'Bush', 'Dick', and 'Colon' (sic)".

-----Chris Rock


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


[Patch] #9

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Berin!
Hello Developers!

Uff.. This patch really does several things.

1. ContextManager

1.1 m_privateSourceResolver

The sourceresolver used to grab the configuration is no longer
passed to the container implementation insed the create
ServiceManager.

Justification: the user should have total control on the
sourceresolver that is available to his application: he should
be able to create sourceresolver with only file factory, or
only resouce, be able to deside which factory is the default,
etc.

Implementation: the sourceresolver needed to read the configurations
has been made private to ContextManager.

1.2 initializeMetaInfoManager

We have had a round of discussion on this on the list, and a series
of my own patches has already been applied on this. Now I'm proposing
to sort of return to the original code (it's a bit different but the
spirit is exactly what it was.)

Justification: we have desided on the list that child containers
should have access to the parent's MetaInfoManager. It is more
convinient to achieve this if the MetaInfoManager is created in
ContextManager not in AbstractContianer (less code, more efficient
code). Moreover, it is good practice if the Container does not
manage itself but gets all it needs (including MetaInfoManager)
from outside.

Nevertheless our patching round has not been useless: we have
sharpened the contract of providing MetaInfoManager for the container
and we have shaken out some inefficiency from the code
(creating ServiceMetaManager twice).
I believe in general the code has become simpler.

Implementation: as we desided that RoleManager is a going-away
concept, even if the user has supplied a RoleManager or a
roles file we do not expose them to the container implementation --
RoleManager is never visible via m_childContext.

1.3 intializeServiceManager

I have proposed to add a NoopServiceManager to fortress.

I have also moved the newly created ServiceManager
from m_childContext to m_containerManagerContext,
as it is the ContainerManager that needs to fetch
it to stuff into the service() method of the Container.

1.4 InitializeInstrumentManager

I propose with this patch to create a NoopInstrumentManager
if the user has supplied no DefaultInstrumentConfiguration.

Justification: it looks like if we have specified
no port numbers to listen on (the case when there is no
configuration) the DefaultInstrumentManager does nothing
usefull.

Moreover, I beleive that this is a security issue:
in fact, we should not listen on any ports unless
explicitly ordered too.

1.5 FortressRoleManager

As patch #8 has not been approved yet, ContextManager
is still creating FortressRoleManager, but as soon as
we have Fortress Meta Descriptors in datasource, xmlutil
and monitor (Patch #8) it will be the right time to
finally decomission FortressRoleManager :-)

2. AbstractContainer

I propose to remove the code that creates the default
MetaInfoManager from this class completely.
This makes the MetaInfoManager a required dependecy
that the invoker should provide.

Justification:

This makes the code simplier.
We have only one place where a default
MetaInfoManager is created - the ContextManager.

It's better to do it outside the container because
we want this newly created default MetaInfoManager to be available not
only to the container itself but to its children too (they can
be containers themselves and can need it).

So it looks simpler to

* create the default MetaInfoManager outside the container
* put it to the Context and/or ServiceManager passed to the
  container
* have the container pass the same context to its children unchanged

The alternative is to create the default MetaInfoManager
internally inside the contianer and wrap the passed-in
context with one more Context, put the new MetaInfoManger
into that new context and pass it context to our children.

Besides,
taking this code out makes AbstractContainer slimmer
and better undertandable :-)

3. Removal of Context/ServiceManager overlap

This probably the steepest part of the patch.
However I would like you very much to really look into it :-)

I have found that

  * LoggerManager
  * PoolManager
  * InstrumentManager
  * MetaInfoManager
  * LifecycleExtensionsManager
  * Queue
  
are passed to the Container twice by the current DefaultContainerManager:

  * as entries in the Context passed to the Container via
    contextualize()
  * as components passed to the Container via
    service()

In general unnecessary duplication is not a desired thing,
  for example we change one copy and not the other
  - and voi'la - a change for a bug to slip in
  ( for instance if our users start creating nesting containers
  overriding the passed-in values )

If we agree on eliminating this duplication we have two alternatives:
* pass these objects via contextualize() only
* or pass them via service() only

I propose the following ground for making this desing decision

  * ServiceManager's user contract is that

    ater we have .lookup()-ed something from it we shoud release() it

    this is because we do not know if we're going to get ThreadSafe
    object, or a new one is going to be created each time for us,
    or it is going to be gaken out of a pool

  * Context's user contract

    we just .get() something from it and use it. We never care about
    release()-ing it. We're sure that it will exist for the duration
    of our life. We're sure that every time we get() it we get the
    same object.

This measure applied, we see that the
LoggerManager, PoolManager, InstrumentManager, MetaInfoManager,
LifecycleExtensionsManager and Queue are used by the Container
in the Context-like fashion. We just grab them and use them.

Therefore I propose to pass these objects via the Context.
This is what my patch does. The classes involved are

  DefaultContainerManager
  AbstractContainer
  AbstractComponentHandler
  PoolableComponentHandler


In fact, after I have done this change the code has become simpler.

* One method was gone from DefaultContainerManager.

* We have one level less nesting in the ServiceManager hierarchy.
  (In fact I even have proposed a tiny optimization that allowes
  to have only 1 level of nesting - no nesting - instead of 3)

I had also to switch the handler from fetching their arguments
from a DefaultServiceManager to a DefaultContextManager but
this change looks quite natural: as we never intend
to release() what AbstractHandler and PoolableHandler have
grabbed via a get() or a lookup(), get() looks more natural.

In short I beleive that the design becomes nicer, the code
shorter and system easier to understand :-)

Hope you will like this patch despite it has united several
orthogonal concernds ;-)

WBR, Anton

Here goes the

    org.apache.avalon.fortress.impl.lookup.NoopServiceManager.java

that is used by my patch.

/*

 ============================================================================
                   The Apache Software License, Version 1.1
 ============================================================================

 Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.

 Redistribution and use in source and binary forms, with or without modifica-
 tion, are permitted provided that the following conditions are met:

 1. Redistributions of  source code must  retain the above copyright  notice,
    this list of conditions and the following disclaimer.

 2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

 3. The end-user documentation included with the redistribution, if any, must
    include  the following  acknowledgment:  "This product includes  software
    developed  by the  Apache Software Foundation  (http://www.apache.org/)."
    Alternately, this  acknowledgment may  appear in the software itself,  if
    and wherever such third-party acknowledgments normally appear.

 4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation"
    must not be used to endorse or promote products derived from this  software
    without  prior written permission. For written permission, please contact
    apache@apache.org.

 5. Products  derived from this software may not  be called "Apache", nor may
    "Apache" appear  in their name,  without prior written permission  of the
    Apache Software Foundation.

 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
 APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
 INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
 DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
 OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
 ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
 (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 This software  consists of voluntary contributions made  by many individuals
 on  behalf of the Apache Software  Foundation. For more  information on the
 Apache Software Foundation, please see <http://www.apache.org/>.

*/
package org.apache.avalon.fortress.impl.lookup;

import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.ServiceException;

/**
 * No-op ServiceManager.
 *
 * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
 * @version CVS $Revision: 1.17 $ $Date: 2003/05/14 15:54:46 $
 */
public class NoopServiceManager
    implements ServiceManager
{
    private static final String MESSAGE = "Could not return a reference to the Component";

    /**
     *  Always throw ServiceException.
     */
    public Object lookup( final String role )
        throws ServiceException
    {
        throw new ServiceException( role, MESSAGE );
    }

    /**
     * Always return false.
     */
    public boolean hasService( final String role )
    {
        return false;
    }

    /**
     * Do nothing.
     */
    public void release( final Object component )
    {
    }

}

And here goes Patch #9 ===================================================

diff -rU12 src.0/java/org/apache/avalon/fortress/impl/AbstractContainer.java src/java/org/apache/avalon/fortress/impl/AbstractContainer.java
--- src.0/java/org/apache/avalon/fortress/impl/AbstractContainer.java   2003-05-21 11:00:00.000000000 +0400
+++ src/java/org/apache/avalon/fortress/impl/AbstractContainer.java     2003-05-26 13:06:01.000000000 +0400
@@ -49,42 +49,42 @@
 */
 package org.apache.avalon.fortress.impl;
 
 import org.apache.avalon.excalibur.logger.LoggerManager;
 import org.apache.avalon.fortress.Container;
 import org.apache.avalon.fortress.MetaInfoEntry;
 import org.apache.avalon.fortress.MetaInfoManager;
 import org.apache.avalon.fortress.RoleManager;
 import org.apache.avalon.fortress.impl.extensions.InstrumentableCreator;
 import org.apache.avalon.fortress.impl.handler.*;
 import org.apache.avalon.fortress.impl.lookup.FortressServiceManager;
 import org.apache.avalon.fortress.impl.lookup.FortressServiceSelector;
+import org.apache.avalon.fortress.impl.lookup.NoopServiceManager;
 import org.apache.avalon.fortress.impl.role.FortressRoleManager;
 import org.apache.avalon.fortress.impl.role.Role2MetaInfoManager;
-import org.apache.avalon.fortress.impl.role.ServiceMetaManager;
 import org.apache.avalon.fortress.impl.factory.ProxyManager;
 import org.apache.avalon.fortress.impl.handler.ComponentFactory;
 import org.apache.avalon.fortress.util.CompositeException;
 import org.apache.avalon.fortress.util.LifecycleExtensionManager;
 import org.apache.avalon.fortress.util.dag.*;
 import org.apache.avalon.framework.activity.Disposable;
 import org.apache.avalon.framework.activity.Initializable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.avalon.framework.context.Context;
 import org.apache.avalon.framework.context.ContextException;
 import org.apache.avalon.framework.context.Contextualizable;
+import org.apache.avalon.framework.context.DefaultContext;
 import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.avalon.framework.logger.Logger;
-import org.apache.avalon.framework.service.DefaultServiceManager;
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.avalon.framework.service.Serviceable;
 import org.apache.commons.collections.BoundedFifoBuffer;
 import org.apache.commons.collections.StaticBucketMap;
 import org.apache.excalibur.event.Queue;
 import org.apache.excalibur.instrument.InstrumentManager;
 import org.apache.excalibur.instrument.Instrumentable;
 import org.apache.excalibur.mpool.ObjectFactory;
 import org.apache.excalibur.mpool.PoolManager;
 
 import java.util.*;
@@ -133,185 +133,148 @@
     /** Contains an entry for each ComponentHandler */
     protected List m_components = new ArrayList( 10 );
 
     protected List m_shutDownOrder;
 
     private ProxyManager m_proxyManager = new ProxyManager(true);
 
     /**
      * Pull the manager items from the context so we can use them to set up
      * the system.
      *
      * @avalon.context type="ClassLoader" optional="true"
+     * @avalon.context type="LoggerManager"
+     * @avalon.context type="PoolManager"
+     * @avalon.context type="InstrumentManager"
+     * @avalon.context type="MetaInfoManager"
+     * @avalon.context type="LifecycleExtensionManager" optional="true"
+     * @avalon.context type="Queue" optional="true"
      *
      * @param context the impl context
      * @throws ContextException if a contexaulization error occurs
      */
     public void contextualize( final Context context )
         throws ContextException
     {
         m_context = context;
         try
         {
             m_classLoader = (ClassLoader) context.get( ClassLoader.class.getName() );
         }
         catch ( ContextException ce )
         {
             m_classLoader = Thread.currentThread().getContextClassLoader();
         }
-    }
 
-    /**
-     * Root ServiceManager.  The Container may choose to have it's
-     * ServiceManager delegate to the root manager, or it may choose to be
-     * entirely self contained.
-     *
-     * @param serviceManager the service manager to apply to the impl
-     * @throws ServiceException is a servicing related error occurs
-     *
-     * @avalon.dependency type="LoggerManager"
-     * @avalon.dependency type="PoolManager"
-     * @avalon.dependency type="InstrumentManager"
-     * @avalon.dependency type="LifecycleExtensionManager" optional="true"
-     * @avalon.dependency type="RoleManager" optional="true"
-     * @avalon.dependency type="Queue" optional="true"
-     */
-    public void service( final ServiceManager serviceManager )
-        throws ServiceException
-    {
         // get non-optional services
-
-        m_loggerManager = (LoggerManager) serviceManager.lookup( LoggerManager.ROLE );
-        m_poolManager = (PoolManager) serviceManager.lookup( PoolManager.ROLE );
-        m_instrumentManager = (InstrumentManager) serviceManager.lookup( InstrumentManager.ROLE );
+        m_loggerManager     =     (LoggerManager) context.get( LoggerManager.ROLE );
+        m_poolManager       =       (PoolManager) context.get( PoolManager.ROLE );
+        m_instrumentManager = (InstrumentManager) context.get( InstrumentManager.ROLE );
+        m_metaManager       =   (MetaInfoManager) context.get( MetaInfoManager.ROLE );
 
         // get optional services, or a default if the service isn't provided
-
-        if ( serviceManager.hasService( LifecycleExtensionManager.ROLE ) )
+        try
         {
-            m_extManager =
-                (LifecycleExtensionManager) serviceManager.lookup( LifecycleExtensionManager.ROLE );
+            m_commandQueue = (Queue) context.get( Queue.ROLE );
         }
-        else
+        catch( ContextException ce )
         {
-            m_extManager = new LifecycleExtensionManager();
-            m_extManager.enableLogging( getLogger() );
-
-            if ( getLogger().isDebugEnabled() )
-            {
-                final String message =
-                    "No Container.LIFECYCLE_EXTENSION_MANAGER is given, " +
-                    "installing default lifecycle extension manager with " +
-                    "1 extensions";
-                getLogger().debug( message );
-            }
-        }
-
-        /* Add all the standard extensions if they have not already been
-         * done.
-         */
-        boolean isInstrumentEnabled = false;
-        final Iterator it = m_extManager.creatorExtensionsIterator();
-        while ( it.hasNext() )
-        {
-            if ( it.next() instanceof InstrumentableCreator )
-            {
-                isInstrumentEnabled = true;
-            }
+            final String message =  "No " + Queue.ROLE + " is given, all " +
+                                    "management will be performed synchronously";
+            getLogger().warn( message );
         }
 
-        if ( !isInstrumentEnabled )
-        {
-            m_extManager.addCreatorExtension( new InstrumentableCreator( m_instrumentManager ) );
-        }
+        setupExtensionManager( context );
+    }
 
-        if ( serviceManager.hasService( Queue.ROLE ) )
-        {
-            m_commandQueue = (Queue) serviceManager.lookup( Queue.ROLE );
-        }
-        else
-        {
-            final String message =
-                "No Container.COMMAND_QUEUE is given, all " +
-                "management will be performed synchronously";
-            getLogger().warn( message );
-        }
+    /**
+     * Add an InstrumentableCreator to ExtensionsManager
+     * creating our private ExtensionsManager if one has not been provided.
+     * Note that our child components will never see this private ExtensionsManager
+     * as it won't be put into the context passed to their contextualize().
+     */
+    protected void setupExtensionManager( final Context context )
+    {
+        final Logger eLogger = m_loggerManager.getLoggerForCategory( "system.extensions" );
 
         try
         {
-            if ( serviceManager.hasService( MetaInfoManager.ROLE ) )
-            {
-                m_metaManager = (MetaInfoManager) serviceManager.lookup( MetaInfoManager.ROLE );
+            m_extManager =
+                (LifecycleExtensionManager) context.get( LifecycleExtensionManager.ROLE );
 
-                if ( serviceManager.hasService( RoleManager.ROLE ) )
-                {
-                    getLogger().warn( "MetaInfoManager found, ignoring RoleManager" );
-                }
+            if ( eLogger.isDebugEnabled() ) 
+            { 
+                eLogger.debug( LifecycleExtensionManager.ROLE + "found" ); 
             }
-            else if ( serviceManager.hasService( RoleManager.ROLE ) )
+
+            /* Add all the standard extensions if they have not been already been added */
+            boolean isInstrumentEnabled = false;
+
+            final Iterator it = m_extManager.creatorExtensionsIterator();
+            while ( it.hasNext() )
             {
-                m_metaManager = createMetaManager(
-                    new Role2MetaInfoManager(
-                        (RoleManager) serviceManager.lookup( RoleManager.ROLE ) ) );
+                if ( it.next() instanceof InstrumentableCreator )
+                {
+                    isInstrumentEnabled = true;
+                }
             }
-            else
+        
+            if ( !isInstrumentEnabled )
             {
-                m_metaManager = createDefaultMetaManager();
+                if ( eLogger.isDebugEnabled() )
+                {
+                    eLogger.debug( "No " + InstrumentableCreator.class.getName() + 
+                        " yet, adding a new one" );
+                }
+                m_extManager.addCreatorExtension( new InstrumentableCreator( m_instrumentManager ) );
             }
         }
-        catch ( ServiceException se )
+        catch( ContextException ce )
         {
-            throw se;
-        }
-        catch ( Exception e )
-        {
-            final String message = "Unable to create default role manager";
-            throw new ServiceException( MetaInfoManager.ROLE, message, e );
+            if ( eLogger.isDebugEnabled() )
+            {
+                final String message =
+                    "No " + LifecycleExtensionManager.ROLE + " is given, " +
+                    "installing a default lifecycle extension manager with " +
+                    "1 extension";
+                eLogger.debug( message );
+            }
+            m_extManager = new LifecycleExtensionManager();
+            m_extManager.enableLogging( eLogger );
+            m_extManager.addCreatorExtension( new InstrumentableCreator( m_instrumentManager ) );
         }
-
-        // set up our ServiceManager
-        m_serviceManager = new FortressServiceManager( this, serviceManager );
     }
 
     /**
-     * Create a default RoleManager that can be used to addRole system.
+     * Root ServiceManager.  The Container may choose to have it's
+     * ServiceManager delegate to the root manager, or it may choose to be
+     * entirely self contained.
      *
-     * @return the default role manager
-     * @throws Exception if unable to create role manager
-     */
-    private MetaInfoManager createDefaultMetaManager()
-        throws Exception
-    {
-        final FortressRoleManager roleManager =
-            new FortressRoleManager( null, m_classLoader );
-        ContainerUtil.enableLogging( roleManager, getLogger().getChildLogger( "roles" ) );
-        ContainerUtil.initialize( roleManager );
-        return createMetaManager( new Role2MetaInfoManager( roleManager ) );
-    }
-
-    /**
-     * Create a default RoleManager that can be used to addRole system.
+     * @param serviceManager the service manager to apply to the impl
+     * @throws ServiceException is a servicing related error occurs
      *
-     * @return the default role manager
-     * @throws Exception if unable to create role manager
      */
-    private ServiceMetaManager createMetaManager( final MetaInfoManager root )
-        throws Exception
+    public void service( final ServiceManager serviceManager )
+        throws ServiceException
     {
-        final ServiceMetaManager metaManager =
-            new ServiceMetaManager( root, m_classLoader );
-        final Logger mmLogger = m_loggerManager.getLoggerForCategory( "system.meta" );
-        ContainerUtil.enableLogging( metaManager, mmLogger );
-        ContainerUtil.initialize( metaManager );
-        return metaManager;
+        // set up our ServiceManager
+        if ( serviceManager instanceof NoopServiceManager )
+        {
+            // tiny optimization
+            m_serviceManager = new FortressServiceManager( this, (ServiceManager) null );
+        }
+        else
+        {
+            m_serviceManager = new FortressServiceManager( this, serviceManager );
+        }
     }
 
     /**
      * Add a Component into the impl. This sets the component up for management
      * by the impl by creating an appropriate {@link ComponentHandler}.
      *
      * @param metaData the information needed to construct a ComponentHandler for the component
      * @throws IllegalArgumentException if the classname defined by the meta data
      *         argument is undefined within the scope of the role manager
      * @throws Exception if unable to create a Handler for the component
      */
     protected void addComponent( final ComponentHandlerMetaData metaData )
@@ -386,31 +349,30 @@
         final Configuration configuration = metaData.getConfiguration();
 
         try
         {
             final ObjectFactory factory =
                 createObjectFactory( classname, configuration );
 
             // create the appropriate handler instance
             final ComponentHandler targetHandler =
                 (ComponentHandler) metaEntry.getHandlerClass().newInstance();
 
             // do the handler lifecycle
-            ContainerUtil.contextualize( targetHandler, m_context );
-            final DefaultServiceManager serviceManager =
-                new DefaultServiceManager( getServiceManager() );
-            serviceManager.put( ObjectFactory.ROLE, factory );
-            serviceManager.makeReadOnly();
+            final DefaultContext context =
+                new DefaultContext( m_context );
+            context.put( ObjectFactory.ROLE, factory );
+            context.makeReadOnly();
 
-            ContainerUtil.service( targetHandler, serviceManager );
+            ContainerUtil.contextualize( targetHandler, context );
             ContainerUtil.configure( targetHandler, configuration );
             ContainerUtil.initialize( targetHandler );
 
             if ( targetHandler instanceof Instrumentable )
             {
                 final Instrumentable instrumentable = (Instrumentable) targetHandler;
                 final String name = instrumentable.getInstrumentableName();
                 m_instrumentManager.registerInstrumentable( instrumentable, name );
             }
 
             // no other lifecycle stages supported for ComponentHandler;
             // ComponentHandler is not a "true" avalon component
diff -rU12 src.0/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java
--- src.0/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java     2003-05-24 10:16:54.000000000 +0400
+++ src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java       2003-05-26 11:35:43.000000000 +0400
@@ -72,25 +72,26 @@
 import org.apache.excalibur.instrument.InstrumentManager;
 import org.apache.excalibur.mpool.PoolManager;
 
 /**
  * This is the default implementation of the
  * {@link org.apache.avalon.fortress.ContainerManager} interface.
  * See that interface for a description.
  *
  * @author <a href="mailto:dev@avalon.apache.org">The Avalon Team</a>
  * @version CVS $Revision: 1.19 $ $Date: 2003/05/23 17:31:20 $
  */
 public class DefaultContainerManager
-    implements Initializable, Disposable, org.apache.avalon.fortress.ContainerManager, org.apache.avalon.fortress.ContainerManagerConstants
+    implements Initializable, Disposable, org.apache.avalon.fortress.ContainerManager, 
+    org.apache.avalon.fortress.ContainerManagerConstants
 {
     private final ContextManager m_contextManager;
     private final Logger m_logger;
     private Object m_containerInstance;
 
     public DefaultContainerManager( final ContextManager contextManager )
     {
         this( contextManager, null );
     }
 
     public DefaultContainerManager( final ContextManager contextManager,
                                     final Logger logger )
@@ -198,81 +199,49 @@
 
         if ( instance instanceof Composable )
         {
             throw new InitializationException( "Composable containers are not supported" );
         }
 
         try
         {
             final Context implContext = m_contextManager.getChildContext();
             ContainerUtil.enableLogging( instance, m_logger );
             ContainerUtil.contextualize( instance, implContext );
 
-            final ServiceManager serviceManager = createServiceManager( implContext );
-
+            final ServiceManager serviceManager =
+                (ServiceManager) getContextEntry( managerContext, SERVICE_MANAGER );
             ContainerUtil.service( instance, serviceManager );
 
             final Configuration config =
                 (Configuration) getContextEntry( managerContext, CONFIGURATION );
             ContainerUtil.configure( instance, config );
 
             final Parameters parameters =
                 (Parameters) getContextEntry( managerContext, PARAMETERS );
             ContainerUtil.parameterize( instance, parameters );
 
             ContainerUtil.initialize( instance );
             ContainerUtil.start( instance );
 
             m_containerInstance = instance;
         }
         catch ( Exception e )
         {
             final String message =
                 "Cannot set up Container. Startup lifecycle failure";
             throw new InitializationException( message, e );
         }
     }
 
-    private ServiceManager createServiceManager( final Context managerContext )
-    {
-        final ServiceManager smanager =
-            (ServiceManager) getContextEntry( managerContext, SERVICE_MANAGER );
-        final DefaultServiceManager serviceManager = new DefaultServiceManager( smanager );
-
-        addService( Queue.ROLE, managerContext, serviceManager );
-        addService( LoggerManager.ROLE, managerContext, serviceManager );
-        addService( PoolManager.ROLE, managerContext, serviceManager );
-        addService( InstrumentManager.ROLE, managerContext, serviceManager );
-        addService( MetaInfoManager.ROLE, managerContext, serviceManager );
-        addService( RoleManager.ROLE, managerContext, serviceManager );
-        addService( LifecycleExtensionManager.ROLE, managerContext, serviceManager );
-        serviceManager.makeReadOnly();
-
-        return serviceManager;
-    }
-
-    private void addService( final String role,
-                             final Context context,
-                             final DefaultServiceManager serviceManager )
-    {
-        try
-        {
-            final Object object = context.get( role );
-            serviceManager.put( role, object );
-        }
-        catch ( ContextException e )
-        {
-        }
-    }
-
     /**
      * Retrieve an entry from context if it exists, else return null.
      *
      * @param context the context
      * @param key the key
      * @return the entry
      */
     private Object getContextEntry( final Context context, final String key )
     {
         try
         {
             return context.get( key );
diff -rU12 src.0/java/org/apache/avalon/fortress/impl/handler/AbstractComponentHandler.java src/java/org/apache/avalon/fortress/impl/handler/AbstractComponentHandler.java
--- src.0/java/org/apache/avalon/fortress/impl/handler/AbstractComponentHandler.java    2003-05-15 12:11:16.000000000 +0400
+++ src/java/org/apache/avalon/fortress/impl/handler/AbstractComponentHandler.java      2003-05-26 12:54:48.000000000 +0400
@@ -45,43 +45,43 @@
  This software  consists of voluntary contributions made  by many individuals
  on  behalf of the Apache Software  Foundation. For more  information on the
  Apache Software Foundation, please see <http://www.apache.org/>.
 
 */
 package org.apache.avalon.fortress.impl.handler;
 
 import org.apache.avalon.excalibur.logger.LoggerManager;
 import org.apache.avalon.framework.activity.Disposable;
 import org.apache.avalon.framework.activity.Initializable;
 import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.avalon.framework.logger.Logger;
-import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.context.ContextException;
+import org.apache.avalon.framework.context.Contextualizable;
+import org.apache.avalon.framework.context.Context;
 import org.apache.excalibur.instrument.AbstractLogEnabledInstrumentable;
 import org.apache.excalibur.instrument.CounterInstrument;
 import org.apache.excalibur.instrument.Instrumentable;
 import org.apache.excalibur.mpool.ObjectFactory;
 
 /**
  * AbstractComponentHandler class, ensures components are initialized
  * and destroyed correctly.
  *
  * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
  * @version CVS $Revision: 1.15 $ $Date: 2003/05/14 15:54:45 $
  * @since 4.0
  */
 public abstract class AbstractComponentHandler
     extends AbstractLogEnabledInstrumentable
-    implements Serviceable, Initializable, Disposable, ComponentHandler
+    implements Contextualizable, Initializable, Disposable, ComponentHandler
 {
     private CounterInstrument m_request = new CounterInstrument( "requests" );
     private CounterInstrument m_release = new CounterInstrument( "releases" );
 
     /**
      * The instance of the ComponentFactory that creates and disposes of the
      * Component
      */
     protected ObjectFactory m_factory;
 
     /**
      * State management boolean stating whether the Handler is initialized or
@@ -93,33 +93,34 @@
      * State management boolean stating whether the Handler is disposed or
      * not
      */
     protected boolean m_disposed;
 
     /** Logger for factory */
     protected Logger m_logger;
 
     /** Logger Manager */
     protected LoggerManager m_loggerManager;
 
     /**
-     * @avalon.dependency type="LoggerManager"
+     * @avalon.context type="LoggerManager"
+     * @avalon.context type="ObjectFactory"
      */
-    public void service( final ServiceManager manager )
-        throws ServiceException
+    public void contextualize( final Context context )
+        throws ContextException
     {
         m_loggerManager =
-            (LoggerManager) manager.lookup( LoggerManager.ROLE );
+            (LoggerManager) context.get( LoggerManager.ROLE );
         m_factory =
-            (ObjectFactory) manager.lookup( ObjectFactory.ROLE );
+            (ObjectFactory) context.get( ObjectFactory.ROLE );
     }
 
     public void initialize()
         throws Exception
     {
         final String classname = getClass().getName();
         final int index = classname.lastIndexOf( '.' );
         final String name = classname.substring( index + 1 );
 
         String loggerName = name.toLowerCase();
         if ( name.endsWith( "ComponentHandler" ) )
         {
diff -rU12 src.0/java/org/apache/avalon/fortress/impl/handler/PoolableComponentHandler.java src/java/org/apache/avalon/fortress/impl/handler/PoolableComponentHandler.java
--- src.0/java/org/apache/avalon/fortress/impl/handler/PoolableComponentHandler.java    2003-04-19 00:02:30.000000000 +0400
+++ src/java/org/apache/avalon/fortress/impl/handler/PoolableComponentHandler.java      2003-05-26 12:59:02.000000000 +0400
@@ -43,26 +43,26 @@
  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  This software  consists of voluntary contributions made  by many individuals
  on  behalf of the Apache Software  Foundation. For more  information on the
  Apache Software Foundation, please see <http://www.apache.org/>.
 
 */
 package org.apache.avalon.fortress.impl.handler;
 
 import org.apache.avalon.framework.configuration.Configurable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.context.ContextException;
+import org.apache.avalon.framework.context.Context;
 import org.apache.excalibur.mpool.Pool;
 import org.apache.excalibur.mpool.PoolManager;
 
 /**
  * The PoolableComponentHandler to make sure components are initialized
  * and destroyed correctly.
  *
  * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
  * @version CVS $Revision: 1.8 $ $Date: 2003/04/18 20:02:29 $
  * @since 4.0
  */
 public final class PoolableComponentHandler
@@ -71,34 +71,34 @@
 {
     /** The instance of the PoolManager to create the Pool for the Handler */
     private PoolManager m_poolManager;
 
     /** The pool of components for <code>Poolable</code> Components */
     private Pool m_pool;
 
     /** The Config element for the poolable */
     private int m_poolMin;
 
     /**
      * Application of suporting services to the handler.
-     * @param serviceManager the service manager
+     * @param context the context
      * @exception ServiceException if a service related error occurs
-     * @avalon.dependency type="PoolManager"
+     * @avalon.context type="PoolManager"
      */
-    public void service( final ServiceManager serviceManager )
-        throws ServiceException
+    public void contextualize( final Context context )
+        throws ContextException
     {
-        super.service( serviceManager );
+        super.contextualize( context );
         m_poolManager =
-            (PoolManager) serviceManager.lookup( PoolManager.ROLE );
+            (PoolManager) context.get( PoolManager.ROLE );
     }
 
     /**
      * Configuration of the handler under which the minimum pool size
      * is established.
      * @param configuration the configuration fragment
      * @exception ConfigurationException if the supplied configuration attribute
      *    for 'pool-min' cannot be resolved to an integer value
      */
     public void configure( final Configuration configuration )
         throws ConfigurationException
     {
diff -rU12 src.0/java/org/apache/avalon/fortress/impl/lookup/FortressServiceManager.java src/java/org/apache/avalon/fortress/impl/lookup/FortressServiceManager.java
--- src.0/java/org/apache/avalon/fortress/impl/lookup/FortressServiceManager.java       2003-05-15 12:11:18.000000000 +0400
+++ src/java/org/apache/avalon/fortress/impl/lookup/FortressServiceManager.java 2003-05-26 12:35:16.000000000 +0400
@@ -92,26 +92,30 @@
         }
 
         m_parent = parent;
         m_container = container;
         m_used = new StaticBucketMap();
     }
 
     public Object lookup( final String role )
         throws ServiceException
     {
         final Lookup lookup = parseRole( role );
 
+        final String failMessage =
+            "Could not return a reference to the Component";
+
         if ( !m_container.has( lookup.m_role, lookup.m_hint ) )
         {
+            if ( m_parent == null ) throw new ServiceException( role, failMessage );
             return m_parent.lookup( role );
         }
 
         final Object result = m_container.get( lookup.m_role, lookup.m_hint );
         if ( result instanceof ServiceSelector )
         {
             return result;
         }
 
         if ( result instanceof ComponentSelector )
         {
             return new WrapperServiceSelector( lookup.m_role, (ComponentSelector) result );
@@ -128,27 +132,25 @@
             final ComponentHandler handler = (ComponentHandler) result;
             final Object component = handler.get();
 
             m_used.put( new ComponentKey( component ), handler );
             return component;
         }
         catch ( final ServiceException ce )
         {
             throw ce; // rethrow
         }
         catch ( final Exception e )
         {
-            final String message =
-                "Could not return a reference to the Component";
-            throw new ServiceException( role, message, e );
+            throw new ServiceException( role, failMessage, e );
         }
     }
 
     public boolean hasService( final String role )
     {
         final Lookup lookup = parseRole( role );
 
         if ( m_container.has( lookup.m_role, lookup.m_hint ) )
         {
             return true;
         }
         else
Only in src/java/org/apache/avalon/fortress/impl/lookup: NoopServiceManager.java
diff -rU12 src.0/java/org/apache/avalon/fortress/util/ContextManager.java src/java/org/apache/avalon/fortress/util/ContextManager.java
--- src.0/java/org/apache/avalon/fortress/util/ContextManager.java      2003-05-23 21:00:14.000000000 +0400
+++ src/java/org/apache/avalon/fortress/util/ContextManager.java        2003-05-26 13:26:02.000000000 +0400
@@ -43,48 +43,53 @@
  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  This software  consists of voluntary contributions made  by many individuals
  on  behalf of the Apache Software  Foundation. For more  information on the
  Apache Software Foundation, please see <http://www.apache.org/>.
 
 */
 package org.apache.avalon.fortress.util;
 
 import org.apache.avalon.excalibur.logger.LogKitLoggerManager;
 import org.apache.avalon.excalibur.logger.LoggerManager;
 import org.apache.avalon.fortress.RoleManager;
+import org.apache.avalon.fortress.MetaInfoManager;
 import org.apache.avalon.fortress.impl.role.ConfigurableRoleManager;
 import org.apache.avalon.fortress.impl.role.FortressRoleManager;
+import org.apache.avalon.fortress.impl.role.ServiceMetaManager;
+import org.apache.avalon.fortress.impl.role.Role2MetaInfoManager;
+import org.apache.avalon.fortress.impl.lookup.NoopServiceManager;
 import org.apache.avalon.framework.activity.Disposable;
 import org.apache.avalon.framework.activity.Initializable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.DefaultConfiguration;
 import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
 import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.avalon.framework.context.Context;
 import org.apache.avalon.framework.context.ContextException;
 import org.apache.avalon.framework.context.DefaultContext;
 import org.apache.avalon.framework.logger.ConsoleLogger;
 import org.apache.avalon.framework.logger.LogKitLogger;
 import org.apache.avalon.framework.logger.Logger;
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.avalon.framework.service.DefaultServiceManager;
 import org.apache.avalon.framework.service.DefaultServiceSelector;
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.excalibur.event.Queue;
 import org.apache.excalibur.event.Sink;
 import org.apache.excalibur.event.command.CommandManager;
 import org.apache.excalibur.event.command.TPCThreadManager;
 import org.apache.excalibur.event.command.ThreadManager;
 import org.apache.excalibur.instrument.InstrumentManager;
+import org.apache.excalibur.instrument.NoopInstrumentManager;
 import org.apache.excalibur.instrument.manager.DefaultInstrumentManager;
 import org.apache.excalibur.mpool.DefaultPoolManager;
 import org.apache.excalibur.mpool.PoolManager;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceResolver;
 import org.apache.excalibur.source.impl.ResourceSourceFactory;
 import org.apache.excalibur.source.impl.SourceResolverImpl;
 import org.apache.excalibur.source.impl.URLSourceFactory;
 import org.apache.log.Hierarchy;
 import org.apache.log.Priority;
 
 import java.util.ArrayList;
@@ -150,28 +155,33 @@
      * as parent. Put things here that you want the impl manager
      * to see, but do not wish to expose to the impl.
      */
     private final DefaultContext m_containerManagerContext;
 
     /**
      * New context passed in, maybe from a FortressConfig.
      * This context may not have objects, but rather URI's or
      * other pointers. The ContextManager inspects it for
      * elements it can use to create component managers etc.
      */
     private Logger m_logger;
-    private final Logger m_primordialLogger;
+    private Logger m_primordialLogger;
     private ServiceManager m_manager;
 
     /**
+     * Source resolver used for reading configurations.
+     */
+    private SourceResolver m_privateSourceResolver;
+
+    /**
      * The components that are "owned" by this context and should
      * be disposed by it. Any manager that is created as a result
      * of it not being in the rootContext, or having been created
      * by the ContextManager should go in here.
      */
     private final ArrayList ownedComponents = new ArrayList();
 
     /**
      * The ConfigurationBuilder is instantiated lazilly in getConfiguration
      * to avoid LinkageErrors in some environments.
      */
     private DefaultConfigurationBuilder configBuilder;
@@ -187,25 +197,28 @@
         m_rootContext = rootContext;
         m_childContext = new OverridableContext( m_rootContext );
         m_containerManagerContext = new OverridableContext( m_childContext );
         m_logger = logger;
 
         // The primordial logger is used for all output up until the point where
         //  the logger manager has been initialized.  However it is set into
         //  two objects used to load the configuration resource files within
         //  the ContextManager.  Any problems loading these files will result in
         //  warning or error messages.  However in most cases, the debug
         //  information should not be displayed, so turn it off by default.
         //  Unfortunately, there is not a very good place to make this settable.
-        m_primordialLogger = new ConsoleLogger( ConsoleLogger.LEVEL_INFO );
+        if ( m_logger == null )
+        {
+            m_primordialLogger = new ConsoleLogger( ConsoleLogger.LEVEL_INFO );
+        }
     }
 
     /**
      * Method to assume ownership of one of the managers the
      * <code>ContextManager</code> created.  Ownership means that the
      * <code>ContextManager</code> is responsible for destroying the
      * manager when the <code>ContextManager</code> is destroyed.
      *
      * @param object  The object being claimed
      *
      * @throws IllegalArgumentException if the object is null.
      */
@@ -218,33 +231,37 @@
         ownedComponents.add( object );
     }
 
     /**
      * Initialize the <code>ContextManager</code>.  This will cause the
      * <code>ContextManager</code> to create any managers it needs.
      *
      * @throws Exception if there is a problem at any point in the
      *         initialization.
      */
     public void initialize() throws Exception
     {
+        createPrivateSourceResolver();
+
         initializeServiceManager();
         initializeLoggerManager();
-        initializeRoleManager();
+        initializeMetaInfoManager();
         initializeCommandQueue();
         initializePoolManager();
         initializeContext();
         initializeInstrumentManager();
         initializeConfiguration();
 
+        disposePrivateSourceResolver();
+
         m_childContext.makeReadOnly();
         m_containerManagerContext.makeReadOnly();
     }
 
     /**
      * Load the configuration file that the Container will need to operate.
      */
     protected void initializeConfiguration()
     {
         try
         {
             copyEntry(CONFIGURATION);
@@ -294,31 +311,31 @@
      * @throws ContextException if the parameter does not exist
      */
     protected void copyEntry( final String key ) throws ContextException
     {
         m_containerManagerContext.put( key, m_rootContext.get( key ) );
         m_childContext.put( key, null );
     }
     
     /**
      * Checks if a specified entry in <code>rootContext</code>
      * has been supplied by the invoker.
      */
-    protected boolean entryPresent( final String key )
+    protected boolean entryPresent( final Context context, final String key )
     {
         boolean isPresent = false;
         
         try
         {
-            m_rootContext.get( key );
+            context.get( key );
             isPresent = true;
         }
         catch( ContextException ce )
         {
             // It is not present, so the value remains false
         }
         
         return isPresent;
     }
 
     /**
      * Disposes all items that this ContextManager has created.
@@ -483,103 +500,196 @@
 
         final PoolManager pm = new DefaultPoolManager( (Sink) m_childContext.get( Queue.ROLE ) );
         assumeOwnership( pm );
         m_childContext.put( PoolManager.ROLE, pm );
     }
 
     /**
      * Set up a RoleManager for the Container if configuration for
      * it has been supplied.
      *
      * @throws Exception if there is an error.
      */
-    protected void initializeRoleManager() throws Exception
+    protected RoleManager initializeRoleManager() throws Exception
     {
         /* we don't want an error message from getConfiguration, so
          * check if there is job to do first
          */
-        if ( entryPresent(RoleManager.ROLE) ) return;
-        if ( !entryPresent(  ROLE_MANAGER_CONFIGURATION     ) &&
-             !entryPresent(  ROLE_MANAGER_CONFIGURATION_URI )    ) return;
+        if ( entryPresent( m_rootContext, RoleManager.ROLE) )
+        {
+            // RoleManager is a compatibility mechanism to
+            // read in ECM roles files. The role manager
+            // will be wrapped by a MetaInfoManager.
+            // So we hide the RoleManager here from the 
+            // container implementation.
+            m_childContext.put( RoleManager.ROLE, null );
+            return (RoleManager)m_rootContext.get( RoleManager.ROLE );
+        }
+
+        if ( !entryPresent( m_rootContext, ROLE_MANAGER_CONFIGURATION     ) &&
+             !entryPresent( m_rootContext, ROLE_MANAGER_CONFIGURATION_URI ) ) 
+        {
+            return null;
+        }
 
         Configuration roleConfig =
             getConfiguration( ROLE_MANAGER_CONFIGURATION, ROLE_MANAGER_CONFIGURATION_URI );
 
         if ( roleConfig == null )
         {
             // Something went wrong, but the error has already been reported
-            return;
+            return null;
         }
 
         // Get the context Logger Manager
-        final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+        final LoggerManager loggerManager = (LoggerManager)m_childContext.get( LoggerManager.ROLE );
+
+        // Get our main classLoader
+        final ClassLoader classLoader = (ClassLoader)m_rootContext.get( ClassLoader.class.getName() );
 
         // Create a logger for the role manager
         final Logger rmLogger = loggerManager.getLoggerForCategory(
             roleConfig.getAttribute( "logger", "system.roles" ) );
 
-        // Lookup the context class loader
-        final ClassLoader classLoader = (ClassLoader) m_rootContext.get( ClassLoader.class.getName() );
-
         // Create a parent role manager with all the default roles
         final FortressRoleManager frm = new FortressRoleManager( null, classLoader );
         frm.enableLogging( rmLogger.getChildLogger( "defaults" ) );
         frm.initialize();
 
         // Create a role manager with the configured roles
-        final ConfigurableRoleManager rm = new ConfigurableRoleManager(frm);
+        final ConfigurableRoleManager rm = new ConfigurableRoleManager(frm, classLoader );
         rm.enableLogging( rmLogger );
         rm.configure( roleConfig );
 
         assumeOwnership( rm );
-        m_childContext.put( RoleManager.ROLE, rm );
+
+        return rm;
+    }
+
+    /**
+     * Set up the MetaInfoManager for the Container.
+     *
+     * @throws Exception if there is an error.
+     */
+    protected void initializeMetaInfoManager() throws Exception
+    {
+        RoleManager rm = initializeRoleManager();
+
+        final boolean rmSupplied = rm != null;
+        final boolean mmSupplied = entryPresent( m_rootContext,  MetaInfoManager.ROLE );
+
+        if ( rmSupplied && mmSupplied )
+        {
+            getLogger().warn( "MetaInfoManager found, ignoring RoleManager" );
+        }
+
+        if ( mmSupplied )
+        {
+            return;
+        }
+
+        // Get the context Logger Manager
+        final LoggerManager loggerManager = (LoggerManager)m_childContext.get( LoggerManager.ROLE );
+
+        // Get the context classLoader
+        final ClassLoader classLoader = (ClassLoader)m_rootContext.get( ClassLoader.class.getName() );
+
+        ServiceMetaManager smm;        
+ 
+        if ( rmSupplied )
+        {
+            // won't catch the exception: should be okay, but if not
+            // let the exception pop up
+            smm = new ServiceMetaManager( new Role2MetaInfoManager( rm ), classLoader );
+        }
+        else
+        {
+            final FortressRoleManager frm = new FortressRoleManager( null, classLoader );
+            final Logger frmLogger = loggerManager.getLoggerForCategory( "system.roles" );
+            frm.enableLogging( frmLogger );
+            frm.initialize();
+
+            smm = new ServiceMetaManager( new Role2MetaInfoManager( frm ), classLoader );
+        }
+
+        Logger smmLogger = loggerManager.getLoggerForCategory( "system.meta" );
+        ContainerUtil.enableLogging( smm, smmLogger );
+        ContainerUtil.initialize( smm );
+        assumeOwnership( smm );
+        m_childContext.put( MetaInfoManager.ROLE, smm );
     }
 
+
     /**
      * Get a reference to the initial ComponentLocator used by the
      * ContainerManager to hold the Components used for parsing the config
      * files and setting up the environment.
      *
      * @throws Exception when there is an error.
      */
     protected void initializeServiceManager() throws Exception
     {
-        final ServiceManager parent = (ServiceManager) get( m_rootContext, SERVICE_MANAGER, null );
-        final DefaultServiceManager manager = new DefaultServiceManager( parent );
+        try
+        {
+            // make the user-supplied ServiceManager available to the
+            // container manager to pass it later to the contianer via
+            // it's service() method
+            copyEntry( ContextManagerConstants.SERVICE_MANAGER );
+        }
+        catch( ContextException ce )
+        {
+            // the container expects some ServiceManager
+            final ServiceManager sm = new NoopServiceManager();
+            m_containerManagerContext.put( ContextManagerConstants.SERVICE_MANAGER, sm );
+        }
+    }
+
+    /**
+     *  Set variables commonly used by severl initialize*
+     *  methods.
+     */
+
+    protected void createPrivateSourceResolver() throws Exception
+    {
+        final DefaultServiceManager manager = new DefaultServiceManager();
         final DefaultServiceSelector selector = new DefaultServiceSelector();
         final URLSourceFactory file = new URLSourceFactory();
         file.enableLogging( getLogger() );
         selector.put( "*", file );
         final ResourceSourceFactory resource = new ResourceSourceFactory();
         resource.enableLogging( getLogger() );
         selector.put( "resource", resource );
 
         manager.put( ResourceSourceFactory.ROLE + "Selector", selector );
 
         final SourceResolverImpl resolver = new SourceResolverImpl();
         ContainerUtil.enableLogging( resolver, getLogger() );
         ContainerUtil.contextualize( resolver, m_childContext );
         ContainerUtil.service( resolver, manager );
         ContainerUtil.parameterize( resolver, new Parameters() );
 
         manager.put( SourceResolver.ROLE, resolver );
 
         manager.makeReadOnly();
 
-        assumeOwnership( manager );
-
-        m_manager = manager;
+        m_privateSourceResolver = resolver;
+    }
 
-        m_childContext.put( ContextManagerConstants.SERVICE_MANAGER, m_manager );
+    protected void disposePrivateSourceResolver() throws Exception
+    {
+        m_privateSourceResolver = null;
+        /** the classes used are so simple that no extra dispose
+            work is needed **/
     }
+        
 
     /**
      * Get a configuration based on a config and URI key.
      *
      * @param configKey  Get the <code>Configuration</code> object directly
      *                   from the context.
      * @param uriKey     Get the uri from the context.
      */
     protected Configuration getConfiguration( final String configKey, final String uriKey )
     {
         try
         {
@@ -593,51 +703,44 @@
 
         final String configUri;
         try
         {
             configUri = (String) m_rootContext.get( uriKey );
         }
         catch ( ContextException ce )
         {
             getLogger().debug( "A configuration URI was not specified: " + uriKey );
             return null;
         }
 
-        SourceResolver resolver = null;
         Source src = null;
         try
         {
-            resolver = (SourceResolver) m_manager.lookup( SourceResolver.ROLE );
-            src = resolver.resolveURI( configUri );
+            src = m_privateSourceResolver.resolveURI( configUri );
             if ( configBuilder == null )
             {
                 configBuilder = new DefaultConfigurationBuilder();
             }
 
             return configBuilder.build( src.getInputStream() );
         }
         catch ( Exception e )
         {
             getLogger().warn( "Could not read configuration file: " + configUri, e );
 
             return null;
         }
         finally
         {
-            if ( null != resolver )
-            {
-                resolver.release( src );
-            }
-
-            m_manager.release( resolver );
+            m_privateSourceResolver.release( src );
         }
     }
 
     /**
      * Finalizes and returns the context.
      *
      * @return a <code>Context</code>
      */
     public Context getContainerManagerContext()
     {
         return m_containerManagerContext;
     }
@@ -674,27 +777,27 @@
      * overridden if you don't want a LogKitLoggerManager.
      *
      * <p>The postcondition is that
      * <code>childContext.get( LoggerManager.ROLE )</code> should
      * return a valid logger manager.</p>
      *
      * @throws Exception if it cannot instantiate the LoggerManager
      */
     protected void initializeLoggerManager() throws Exception
     {
         try
         {
-            // Try copying an already existing logger manager from the override context.
+            // See if we already have s LoggerManager supplied
 
-            m_childContext.put( LoggerManager.ROLE, m_rootContext.get( LoggerManager.ROLE ) );
+            m_rootContext.get( LoggerManager.ROLE );
         }
         catch ( ContextException ce )
         {
             // Should we set one up?
             // Try to get a configuration for it...
             Configuration loggerManagerConfig =
                 getConfiguration( LOGGER_MANAGER_CONFIGURATION, LOGGER_MANAGER_CONFIGURATION_URI );
             if ( loggerManagerConfig == null )
             {
                 // Create an empty configuration so that
                 // a default logger can be created.
                 loggerManagerConfig = EMPTY_CONFIG;
@@ -744,58 +847,57 @@
     /**
      * Will set up a LogKitLoggerManager if none is supplied.  This can be
      * overridden if you don't want a LogKitLoggerManager.
      *
      * <p>The postcondition is that
      * <code>childContext.get( LoggerManager.ROLE )</code> should
      * return a valid logger manager.</p>
      *
      * @throws Exception if it cannot instantiate the LoggerManager
      */
     protected void initializeInstrumentManager() throws Exception
     {
-        try
+        if ( entryPresent( m_rootContext, InstrumentManager.ROLE ) )
         {
-            // Try copying an already existing instrument manager from the override context.
-
-            m_rootContext.get( InstrumentManager.ROLE );
+            // We already have got one
+            return;
         }
-        catch ( ContextException ce )
-        {
-            // Should we set one up?
-            // Try to get a configuration for it...
-            Configuration instrumentConfig = getConfiguration( INSTRUMENT_MANAGER_CONFIGURATION, INSTRUMENT_MANAGER_CONFIGURATION_URI );
-            if ( instrumentConfig == null )
-            {
-                // No config.
-                instrumentConfig = EMPTY_CONFIG;
-            }
 
-            // Get the context Logger Manager
-            final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+        // We should set one up
+        // Try to get a configuration for it...
+        Configuration instrumentConfig = 
+            getConfiguration( INSTRUMENT_MANAGER_CONFIGURATION, INSTRUMENT_MANAGER_CONFIGURATION_URI );
+
+        if ( instrumentConfig == null )
+        {
+            m_childContext.put( InstrumentManager.ROLE, new NoopInstrumentManager() );
+            return;
+        }
+        
+        // Get the context Logger Manager
+        final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
 
-            // Get the logger for the instrument manager
-            final Logger imLogger = loggerManager.getLoggerForCategory(
-                instrumentConfig.getAttribute( "logger", "system.instrument" ) );
-
-            // Set up the Instrument Manager
-            final DefaultInstrumentManager instrumentManager = new DefaultInstrumentManager();
-            instrumentManager.enableLogging( imLogger );
-            instrumentManager.configure( instrumentConfig );
-            instrumentManager.initialize();
+        // Get the logger for the instrument manager
+        final Logger imLogger = loggerManager.getLoggerForCategory(
+            instrumentConfig.getAttribute( "logger", "system.instrument" ) );
+
+        // Set up the Instrument Manager
+        final DefaultInstrumentManager instrumentManager = new DefaultInstrumentManager();
+        instrumentManager.enableLogging( imLogger );
+        instrumentManager.configure( instrumentConfig );
+        instrumentManager.initialize();
 
-            assumeOwnership( instrumentManager );
+        assumeOwnership( instrumentManager );
 
-            m_childContext.put( InstrumentManager.ROLE, instrumentManager );
-        }
+        m_childContext.put( InstrumentManager.ROLE, instrumentManager );
     }
 
     private final class DestroyOrderComparator implements Comparator
     {
         public boolean equals( final Object other )
         {
             return other instanceof DestroyOrderComparator;
         }
 
         public int hashCode()
         {
             return DestroyOrderComparator.class.hashCode();


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


[Patch] #10

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello, Berin!

This is patch that provides one possible solution
of the problems related to the LifecycleExtensionManager.

1)

It adds makeReadOnly() and copyFrom( LifecycleExtensionManager )
to LifeCycleExtensionManager and copies the LifecycleExtensionManager
inside AbstractContainer instead of modifying the passed-in one.

This is the part of the patch that I like.

2)

Note that the patch should be applied on top of [Patch] #9)

3)

The patch also passes the newly created LifecycleExtensionManager
to child components. This is the part of the patch that
I do not like that much.
It is not elegant.
But the best I could think of.

And besides we _need_ to provide a way to create new containers
derived from AbstractContainer and these containers may wish
to modify the context passed to children. So probably we need
to adopt the machinery proposed in this patch anyway.

The machinery is quite flexible: if the component wants the
new context _not_ to be child of its own, it can do it.

If it _wants_ it to be it also can do it.

As for the LifecycleExtensionManager the question remains open
for me wether we should pass the newly created ExtensionManager
to our child components. _IF_ we should, this patch does this.

My best regards, Anton
:-)

diff -rU12 src.0/org/apache/avalon/fortress/impl/AbstractContainer.java src/org/apache/avalon/fortress/impl/AbstractContainer.java
--- src.0/org/apache/avalon/fortress/impl/AbstractContainer.java        2003-05-26 13:06:02.000000000 +0400
+++ src/org/apache/avalon/fortress/impl/AbstractContainer.java  2003-05-26 16:11:58.000000000 +0400
@@ -128,24 +128,31 @@
     /**
      * Contains entries mapping roles to hint maps, where the hint map contains
      * mappings from hints to ComponentHandlers.
      */
     protected Map m_mapper = new StaticBucketMap();
     /** Contains an entry for each ComponentHandler */
     protected List m_components = new ArrayList( 10 );
 
     protected List m_shutDownOrder;
 
     private ProxyManager m_proxyManager = new ProxyManager(true);
 
+    /** track whether we have created a new extensions manager or have used one
+     *  supplied in our context. */
+    private   boolean m_extManagerNew = false;
+    /** the context manager passed to our children. Override the
+     *  getChildContext() method to change its value. */
+    private   Context m_childContext;
+
     /**
      * Pull the manager items from the context so we can use them to set up
      * the system.
      *
      * @avalon.context type="ClassLoader" optional="true"
      * @avalon.context type="LoggerManager"
      * @avalon.context type="PoolManager"
      * @avalon.context type="InstrumentManager"
      * @avalon.context type="MetaInfoManager"
      * @avalon.context type="LifecycleExtensionManager" optional="true"
      * @avalon.context type="Queue" optional="true"
      *
@@ -189,67 +196,80 @@
     /**
      * Add an InstrumentableCreator to ExtensionsManager
      * creating our private ExtensionsManager if one has not been provided.
      * Note that our child components will never see this private ExtensionsManager
      * as it won't be put into the context passed to their contextualize().
      */
     protected void setupExtensionManager( final Context context )
     {
         final Logger eLogger = m_loggerManager.getLoggerForCategory( "system.extensions" );
 
         try
         {
-            m_extManager =
+            final LifecycleExtensionManager extManager =
                 (LifecycleExtensionManager) context.get( LifecycleExtensionManager.ROLE );
 
             if ( eLogger.isDebugEnabled() ) 
             { 
                 eLogger.debug( LifecycleExtensionManager.ROLE + "found" ); 
             }
 
             /* Add all the standard extensions if they have not been already been added */
             boolean isInstrumentEnabled = false;
 
-            final Iterator it = m_extManager.creatorExtensionsIterator();
+            final Iterator it = extManager.creatorExtensionsIterator();
             while ( it.hasNext() )
             {
                 if ( it.next() instanceof InstrumentableCreator )
                 {
                     isInstrumentEnabled = true;
                 }
             }
         
-            if ( !isInstrumentEnabled )
+            if ( isInstrumentEnabled )
+            {
+                // ok, use this LifecycleExtensionManager instance
+                m_extManager = extManager;
+            }
+            else
             {
                 if ( eLogger.isDebugEnabled() )
                 {
-                    eLogger.debug( "No " + InstrumentableCreator.class.getName() + 
-                        " yet, adding a new one" );
+                    final String message =  "No " + InstrumentableCreator.class.getName() + 
+                        " yet, creating a copy of "+LifecycleExtensionManager.ROLE +
+                        ", adding a new " + InstrumentableCreator.class.getName() +
+                        " to it";
+                    eLogger.debug( message );
                 }
+                m_extManager = extManager.writableCopy();
                 m_extManager.addCreatorExtension( new InstrumentableCreator( m_instrumentManager ) );
+                m_extManager.makeReadOnly();
+                m_extManagerNew = true;
             }
         }
         catch( ContextException ce )
         {
             if ( eLogger.isDebugEnabled() )
             {
                 final String message =
                     "No " + LifecycleExtensionManager.ROLE + " is given, " +
                     "installing a default lifecycle extension manager with " +
                     "1 extension";
                 eLogger.debug( message );
             }
             m_extManager = new LifecycleExtensionManager();
             m_extManager.enableLogging( eLogger );
             m_extManager.addCreatorExtension( new InstrumentableCreator( m_instrumentManager ) );
+            m_extManager.makeReadOnly();
+            m_extManagerNew = true;
         }
     }
 
     /**
      * Root ServiceManager.  The Container may choose to have it's
      * ServiceManager delegate to the root manager, or it may choose to be
      * entirely self contained.
      *
      * @param serviceManager the service manager to apply to the impl
      * @throws ServiceException is a servicing related error occurs
      *
      */
@@ -415,28 +435,31 @@
     /**
      * Create an objectFactory for specified Object configuration.
      *
      * @param classname the classname of object
      * @param configuration the objests configuration
      * @return the ObjectFactory
      * @throws ClassNotFoundException if the specified class does not exist
      */
     protected ObjectFactory createObjectFactory( final String classname,
                                                  final Configuration configuration )
         throws Exception
     {
+        // invoke this for when the first component is being added
+        if ( m_childContext == null ) m_childContext = getChildContext();
+
         final Class clazz = m_classLoader.loadClass( classname );
         final ComponentFactory componentFactory =
             new ComponentFactory( clazz, configuration,
-                m_serviceManager, m_context,
+                m_serviceManager, m_childContext,
                 m_loggerManager, m_extManager );
         return m_proxyManager.getWrappedObjectFactory( componentFactory );
     }
 
     /**
      * This is the method that the ContainerComponentManager and Selector use
      * to gain access to the ComponentHandlers and ComponentSelectors.  The
      * actual access of the ComponentHandler is delegated to the Container.
      *
      * @param  role  The role we intend to access a Component for.
      * @param  hint  The hint that we use as a qualifier
      *         (note: if null, the default implementation is returned).
@@ -719,13 +742,36 @@
      * Exposes to subclasses the service manager which this impl
      * uses to manage its child components.
      * The returned ServiceManager <i>is</i> aware of the services passed
      * in to <i>this</i> impl, and services that were passed in through
      * service() are hence available to subclasses.
      *
      * @return the service manager that contains the child components.
      */
     protected ServiceManager getServiceManager()
     {
         return m_serviceManager;
     }
+
+    /**
+     *  Create a context for our child components. Derived containers may
+     *  override this method to their preference. Invoked once when the
+     *  first component is added.
+     *  The type of returned object will be dynamically tested against
+     *  DefaultContext. In case of a match makeReadOnly will be called.
+     *  Otherwise the context will be wrapped into a read-only DefaultContext.
+     */
+    protected Context getChildContext()
+    {
+        if ( m_extManagerNew )
+        {
+            DefaultContext context = new DefaultContext( m_context );
+            /* we have created a new extensions manager */
+            context.put( LifecycleExtensionManager.ROLE, m_extManager );
+            return context;
+        }
+        else
+        {
+            return m_context;
+        }
+    }
 }
diff -rU12 src.0/org/apache/avalon/fortress/util/LifecycleExtensionManager.java src/org/apache/avalon/fortress/util/LifecycleExtensionManager.java
--- src.0/org/apache/avalon/fortress/util/LifecycleExtensionManager.java        2003-04-22 16:37:10.000000000 +0400
+++ src/org/apache/avalon/fortress/util/LifecycleExtensionManager.java  2003-05-26 16:08:32.000000000 +0400
@@ -80,24 +80,42 @@
  * @author <a href="mailto:crafterm@apache.org">Marcus Crafter</a>
  * @version CVS $Revision: 1.8 $ $Date: 2003/04/22 12:37:09 $
  */
 public final class LifecycleExtensionManager
     extends AbstractLogEnabled
 {
     public static final String ROLE = LifecycleExtensionManager.class.getName();
 
     // extensions objects
     private final CachedArrayList m_accessorExtensions = new CachedArrayList();
     private final CachedArrayList m_creatorExtensions = new CachedArrayList();
 
+    private boolean m_readOnly = false;
+
+    public void makeReadOnly()
+    {
+        m_readOnly = true;
+    }
+
+    /**
+     * Create a copy; it will be writable even if the original was not.
+     */
+    public LifecycleExtensionManager writableCopy()
+    {
+        final LifecycleExtensionManager copy = new LifecycleExtensionManager();
+        copy.m_accessorExtensions.copyFrom( m_accessorExtensions );
+        copy.m_creatorExtensions.copyFrom( m_creatorExtensions );
+        return copy;
+    }
+    
     /**
      * <code>executeAccessExtensions</code> method, executes all access
      * level extensions on the given component.
      *
      * @param component a <code>Component</code> instance
      * @param context a <code>Context</code> instance
      * @exception Exception if an error occurs
      */
     public void executeAccessExtensions( final Object component, final Context context )
         throws Exception
     {
         executeExtensions( m_accessorExtensions.toArray(), component, context, ACCESS );
@@ -159,78 +177,84 @@
     //    execute operation)
     // 4. The book 'Refactoring' says we shouldn't do it :-)
     //
     // I'm open to suggestions though if there's any better ideas ?
 
     /**
      * Adds an accessor extension to the manager
      *
      * @param extension a <code>Accessor</code> instance
      */
     public void addAccessorExtension( final Accessor extension )
     {
+        checkWriteable();
         m_accessorExtensions.add( extension );
     }
 
     /**
      * Adds a creator extension to the manager
      *
      * @param extension a <code>Creator</code> instance
      */
     public void addCreatorExtension( final Creator extension )
     {
+        checkWriteable();
         m_creatorExtensions.add( extension );
     }
 
     /**
      * Inserts an accessor extension at a given index in the manager
      *
      * @param position an <code>int</code> index value
      * @param extension a <code>Accessor</code> instance
      */
     public void insertAccessorExtension( final int position, final Accessor extension )
     {
+        checkWriteable();
         m_accessorExtensions.insert( position, extension );
     }
 
     /**
      * Inserts a creator extension at a given index in the manager
      *
      * @param position an <code>int</code> index value
      * @param extension a <code>Creator</code> instance
      */
     public void insertCreatorExtension( final int position, final Creator extension )
     {
+        checkWriteable();
         m_creatorExtensions.insert( position, extension );
     }
 
     /**
      * Removes a particular accessor extension from the manager
      *
      * @param position an <code>int</code> index value
      * @return a <code>Accessor</code> instance
      */
     public Accessor removeAccessorExtension( final int position )
     {
+        checkWriteable();
         return (Accessor) m_accessorExtensions.remove( position );
     }
 
     /**
      * Removes a particular creator extension from the manager
      *
      * @param position an <code>int</code> index value
      * @return a <code>Creator</code> instance
      */
     public Creator removeCreatorExtension( final int position )
     {
+        checkWriteable();
         return (Creator) m_creatorExtensions.remove( position );
     }
 
     /**
      * Obtain an iterator.
      *
      * @return an <code>Iterator</code> instance
      */
     public Iterator accessorExtensionsIterator()
     {
         return m_accessorExtensions.iterator();
     }
@@ -283,32 +307,34 @@
      * @return a <code>Creator</code> instance
      */
     public Creator getCreatorExtension( final int index )
     {
         return (Creator) m_creatorExtensions.get( index );
     }
 
     /**
      * Clears all accessor extensions registered with this manager
      */
     public void clearAccessorExtensions()
     {
+        checkWriteable();
         m_accessorExtensions.clear();
     }
 
     /**
      * Clears all creator extensions registered with this manager
      */
     public void clearCreatorExtensions()
     {
+        checkWriteable();
         m_creatorExtensions.clear();
     }
 
     // Lifecycle method constants, these are passed to executeExtensions()
     protected static final int ACCESS = 0;
     protected static final int RELEASE = 1;
     protected static final int CREATE = 2;
     protected static final int DESTROY = 3;
 
     /**
      * <code>executeExtensions</code> method, executes a given array of
      * lifecycle interfaces on a given component.
@@ -358,24 +384,40 @@
 
             default:
                 if ( getLogger().isErrorEnabled() )
                 {
                     final String message =
                         "Incorrect extension phase specified: " + type;
                     getLogger().error( message );
                 }
         }
     }
 
     /**
+     * Utility method to check if LifecycleExtensionsManager
+     * is writeable and if not throw exception.
+     *
+     * @throws IllegalStateException if context is read only
+     */
+    protected final void checkWriteable()
+        throws IllegalStateException
+    {
+        if( m_readOnly )
+        {
+            final String message =
+                "LifecycleExtensionsManager is read only and can not be modified";
+            throw new IllegalStateException( message );
+        }
+    }
+    /**
      * <code>CachedArrayList</code> class.
      *
      * <p>
      * This class wraps a synchronized ArrayList to provide an optimized
      * <code>toArray()</code> method that returns an internally cached array,
      * rather than a new array generated per <code>toArray()</code>
      * invocation.
      * </p>
      *
      * <p>
      * Use of the class by the Manager results in <code>toArray()</code>
      * being invoked far more often than any other method. Caching the value
@@ -395,24 +437,34 @@
     private final class CachedArrayList
     {
         // Empty array constant
         private final Object[] EMPTY_ARRAY = new Object[0];
 
         // Actual list for storing elements
         private final List m_proxy = Collections.synchronizedList( new ArrayList() );
 
         // Proxy cache, saves unnecessary conversions from List to Array
         private Object[] m_cache = EMPTY_ARRAY;
 
         /**
+         *  Become a copy of another CachedArrayList.
+         */
+        public void copyFrom( final CachedArrayList original )
+        {
+            m_proxy.clear();
+            m_proxy.addAll( original.m_proxy );
+            m_cache = original.m_cache; // it won't mutate anyway :-)
+        }
+
+        /**
          * Add an object to the list
          *
          * @param object an <code>Object</code> value
          */
         public void add( final Object object )
         {
             m_proxy.add( object );
             m_cache = m_proxy.toArray();
         }
 
         /**
          * Insert an object into a particular position in the list
@@ -431,31 +483,32 @@
          *
          * @param position an <code>int</code> value
          * @return a <code>Object</code> value
          */
         public Object remove( final int position )
         {
             final Object object = m_proxy.remove( position );
             m_cache = m_proxy.toArray();
             return object;
         }
 
         /**
-         * Obtain an iterator
+         * Obtain an iterator. This iterator is read-only.
          *
          * @return an <code>Iterator</code> value
          */
         public Iterator iterator()
         {
-            return m_proxy.iterator();
+            final Iterator base = m_proxy.iterator();
+            return new UnmodifiableIterator( base );
         }
 
         /**
          * Obtain the size of the list
          *
          * @return an <code>int</code> value
          */
         public int size()
         {
             return m_proxy.size();
         }
 
@@ -493,13 +546,35 @@
         /**
          * Obtain the list as an array. Subsequents calls to this method
          * will return the same array object, until a write operation is
          * performed on the list.
          *
          * @return an <code>Object[]</code> value
          */
         public Object[] toArray()
         {
             return m_cache;
         }
     }
+
+    private static class UnmodifiableIterator implements Iterator
+    {
+        private final Iterator m_base;
+        UnmodifiableIterator( final Iterator base )
+        {
+            if ( base == null ) throw new NullPointerException( "base can not be null" );
+            m_base = base;
+        }
+        public boolean hasNext()
+        {
+            return m_base.hasNext();
+        }
+        public Object next()
+        {
+            return m_base.next();
+        }
+        public void remove()
+        {
+            throw new IllegalStateException( "Unmodifiable iterator" );
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


[Patch] #10.1 Part II

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Berin!

This patch hopefully completes my patching series
on Fortress. This is the second and last part of
the #10.1 that used to be pending for a while.

This patch

1.===================InstrumentManager stuff===

isolates the change in the LifecycleExtensionManager
done by the container from the LifecycleExtensionManager
possibly passed in for the "master".

This patch stops testing if an InstrumentableCreator is
already in the LifecycleExtensionManager: indeed we want
_our_ instrumentManager to be engaged not just any
instrumentManager. Hence we always add a new InstrumentableCreator.

As I write in the code comments, we assume that there is none
InstrumentableCreator already in the LifecycleExtensionManager
if we receive any because otherwise we will get double
invocation of setInstrumentManager which is probably a bug.

Abstract container might even test that there is _none_
InstrumentableCreator in the LifecycleExtensionManager, but
I haven't written this because I consider that anyone can
write another CreatorExtension, with a different class but
doing the same -- invoking setInstrumentManager.

So I think it is better to safeguard our components in
some other way: test that an instrumentManager is not
assigned twice to us if it really makes us uset.

So I do not test this in the code proposed.

2. =============================================

provideComponentContext method is added to allow
derived containers control what context is passed
to the compnents they create, the default just
returns m_context.

3. =============================================

provideServiceMethod is an override point that
allowes derived contianers to optionally block
part of services available from the parent
service manager - and otherwise change
the serviceManager creation procedure

4. =============================================
excluded RoleManager from @avalon.dependecy on
service()

---------------

BTW, ContextManagerTestCase has started outputting a lot
of stuff to the console when invoked. The current CVS
state (without my latest #12, #10.1 parts I and II)
behaves the same.

- WBR, Anton

--- AbstractContainer.orig      2003-05-29 09:59:26.000000000 +0400
+++ AbstractContainer.java      2003-05-29 12:21:12.000000000 +0400
@@ -126,6 +126,12 @@
     /** contains the impl's LifecycleExtensionManager, which is extracted from m_serviceManager. */
     protected LifecycleExtensionManager m_extManager;
     /**
+     * contains the context that will be passed to the components we will create.  
+     * initialized the first time a component handler is created by a call to
+     * provideComponentContext -- override this method to affect the value of this object.
+     */
+    protected Context m_componentContext;
+    /**
      * Contains entries mapping roles to hint maps, where the hint map contains
      * mappings from hints to ComponentHandlers.
      */
@@ -172,7 +178,6 @@
      * @avalon.dependency type="PoolManager"
      * @avalon.dependency type="InstrumentManager"
      * @avalon.dependency type="LifecycleExtensionManager" optional="true"
-     * @avalon.dependency type="RoleManager" optional="true"
      * @avalon.dependency type="Sink" optional="true"
      */
     public void service( final ServiceManager serviceManager )
@@ -203,7 +208,7 @@
         m_metaManager = (MetaInfoManager) serviceManager.lookup( MetaInfoManager.ROLE );
 
         // set up our ServiceManager
-        m_serviceManager = new FortressServiceManager( this, serviceManager );
+        m_serviceManager = provideServiceManager( serviceManager );
     }
 
     /**
@@ -217,45 +222,49 @@
         final Logger extLogger = m_loggerManager.getLoggerForCategory( "system.extensions" );
         if ( serviceManager.hasService( LifecycleExtensionManager.ROLE ) )
         {
-            m_extManager =
-                (LifecycleExtensionManager) serviceManager.lookup( LifecycleExtensionManager.ROLE );
-
-            extLogger.debug( "Found the LifecycleExtensionManager" );
-        }
-        else
-        {
-            m_extManager = new LifecycleExtensionManager();
-            m_extManager.enableLogging( extLogger );
-            m_extManager.addCreatorExtension( new InstrumentableCreator( m_instrumentManager ) );
+            final LifecycleExtensionManager parent = (LifecycleExtensionManager)
+                    serviceManager.lookup( LifecycleExtensionManager.ROLE );
 
-            if ( getLogger().isDebugEnabled() )
+            if ( extLogger.isDebugEnabled() )
             {
-                final String message =
-                    "No Container.LIFECYCLE_EXTENSION_MANAGER is given, " +
-                    "installing default lifecycle extension manager with " +
-                    "1 extensions";
-                getLogger().debug( message );
+                final String message = "Found the LifecycleExtensionManager, creating a copy.";
+                extLogger.debug( message );
             }
-        }
 
-        /* Add all the standard extensions if they have not already been
-         * done.
-         */
-        boolean isInstrumentEnabled = false;
-        final Iterator it = m_extManager.creatorExtensionsIterator();
-        while ( it.hasNext() )
+            m_extManager = parent.writeableCopy();
+        }
+        else
         {
-            if ( it.next() instanceof InstrumentableCreator )
+            if ( extLogger.isDebugEnabled() )
             {
-                isInstrumentEnabled = true;
+                final String message = "No LifecycleExtensionManager found, creating a new one.";
+                extLogger.debug( message );
             }
+            m_extManager = new LifecycleExtensionManager();
         }
 
-        if ( !isInstrumentEnabled )
+        /** LifecycleExtensionManager.writeableCopy() does not copy the logger. */
+        m_extManager.enableLogging( extLogger );
+
+        if ( extLogger.isDebugEnabled() )
         {
-            extLogger.debug("No Instrumentable Creator was found.  We are adding a new one.");
-            m_extManager.addCreatorExtension( new InstrumentableCreator( m_instrumentManager ) );
-        }
+            final String message = 
+                    "Adding an InstrumentableCreator to support our InstrumentManager";
+            extLogger.debug( message );
+        }
+
+        /**
+         * We do need a new InstrumentableCreator, as we want strictly our
+         * m_instrumentManager to be engaged. We assume there is no 
+         * InstrumentableCreator in the LifecycleExtensionManager passed to us 
+         * already. If there is one this is probably a bug. Not testing this currently, 
+         * although might test this in the future in order to
+         * throw something like an IllegalArgumentException.
+         */
+        m_extManager.addCreatorExtension( new InstrumentableCreator( m_instrumentManager ) );
+
+        // just to be on the safe side
+        m_extManager.makeReadOnly();
     }
 
     /**
@@ -415,10 +424,19 @@
                                                  final Configuration configuration )
         throws Exception
     {
+        if ( m_componentContext == null )
+        {
+            m_componentContext = provideComponentContext( m_context );
+            if ( m_componentContext == null )
+            {
+                throw new IllegalStateException( "provideComponentContext() has returned null" );
+            }
+        }
+
         final Class clazz = m_classLoader.loadClass( classname );
         final ComponentFactory componentFactory =
             new ComponentFactory( clazz, configuration,
-                m_serviceManager, m_context,
+                m_serviceManager, m_componentContext,
                 m_loggerManager, m_extManager );
         return m_proxyManager.getWrappedObjectFactory( componentFactory );
     }
@@ -763,4 +781,43 @@
     {
         return m_serviceManager;
     }
+
+    /**
+     * Override this method to control creation of the serviceManager
+     * belonging to this container. This serviceManager is passed to
+     * child components as they are being created and is exposed via
+     * the getServiceManager() method.
+     * Invoked from the service() method.
+     *
+     * However even a self-contained container should be carefull about
+     * cutting access to parent serviceManager completely, as important 
+     * (and required) system services including Sink, LoggerManager, 
+     * InstrumentManager, PoolManager and LifecycleExtensionManager 
+     * are passed via ServiceManager also. SourceResolver hangs somewhere
+     * in between system and "user space" services.
+     *
+     * It's more or less okay to cut access to them if our child
+     * components do not need them and are not containers themselves,
+     * but if we have containers as our children they will require these
+     * services.
+     */
+    protected ServiceManager provideServiceManager( final ServiceManager parent ) 
+            throws Exception
+    {
+        return new FortressServiceManager( this, parent );
+    }
+
+    /**
+     * Override this method to control what context will be passed to
+     * the components created by this container. Called the first time
+     * a component being created - withing this implementation it is
+     * a part of the configure() stage.
+     * You may derive your context from m_context or create a new one.
+     */
+    protected Context provideComponentContext( final Context parent ) 
+            throws Exception
+    {
+        /* the default implementation: just use the same as for container itself */
+        return parent;
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


[Patch] #8

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello, Berin! Hello, Developers!

This patch introduces fortress meta descriptors generation into
  * datasource
  * monitor
  * store
  * xmlutil

It works with all except for Store.
There are two issues with Store:

  a) util/dag in Fortress probably needs a bit more work:
     Berin, try applying the patch on Store to your local
     copy and see what happens: instead of a CyclicDependencyException
     we currently get a StackOverflow

  b) even after Fortress is fixed to throw a CyclicDependencyException
     it won't be possible to generate Fortress meta descriptors for
     Store:

     MRUMemoryStore
     
         implements o.a.e.store.Store;

     it also looks up

         Store.PersistentStore

     which I understand should be another component
     also implementing o.a.e.store.Store (with a different hint).

     As we know, such granularity of dependency support is
     planned only for future development of Fortress.

     What shall we do?
     Store won't be released tomorrow, but still?

WBR, Anton

So, here goes [Patch] #8
that should probably be applied except for the part on Store.
===============

diff -ru avalon-excalibur.0/datasource/build.xml avalon-excalibur/datasource/build.xml
--- avalon-excalibur.0/datasource/build.xml     2003-05-21 10:59:32.000000000 +0400
+++ avalon-excalibur/datasource/build.xml       2003-05-25 13:22:16.000000000 +0400
@@ -25,6 +25,8 @@
         <pathelement location="${comons-collections.jar}"/>
         <pathelement location="${util.concurrent.jar}"/>
         <pathelement location="${excalibur-i18n.jar}"/>
+        <pathelement location="${avalon-fortress-tools.jar}"/>
+        <pathelement location="${qdox.jar}"/>
         <pathelement path="${java.class.path}"/>
     </path>
 
@@ -56,6 +58,7 @@
         <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkInstrument"/>
         <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkPool"/>
         <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkI18n"/>
+        <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkFortressTools"/>
     </target>
 
     <target name="dependencies-test" depends="dist-jar, dependencies"
@@ -121,6 +124,16 @@
                 unless="j2ee.present"/>
         </javac>
 
+        <!-- generate fortress meta descriptors -->
+        <taskdef name="fortress-collect-meta"
+            classname="org.apache.avalon.fortress.tools.ComponentMetaInfoCollector">
+            <classpath refid="project.class.path"/>
+        </taskdef>
+
+        <fortress-collect-meta destdir="${build.classes}">
+            <fileset dir="${java.dir}"/>
+        </fortress-collect-meta>
+
         <!-- copy resources to same location as .class files -->
         <copy todir="${build.classes}">
             <fileset dir="${java.dir}">
diff -ru avalon-excalibur.0/datasource/default.properties avalon-excalibur/datasource/default.properties
--- avalon-excalibur.0/datasource/default.properties    2003-05-21 10:59:32.000000000 +0400
+++ avalon-excalibur/datasource/default.properties      2003-05-25 12:29:00.000000000 +0400
@@ -41,6 +41,15 @@
 excalibur-i18n.lib=${excalibur-i18n.home}
 excalibur-i18n.jar=${excalibur-i18n.lib}/excalibur-i18n-1.0.jar
 
+# ----- Avalon Fortress, version 1.0 or later  -----
+avalon-fortress.home=${basedir}/../fortress
+avalon-fortress.lib=${avalon-fortress.home}/dist
+avalon-fortress-tools.jar=${avalon-fortress.lib}/excalibur-fortress-tools-1.0.jar
+
+# ----- QDox Jar ----
+qdox.jar=${basedir}/../lib/qdox-1.1.jar
+
+
 
 # ----- Commons Collections, version 2.1 or later -----
 comons-collections.jar=../lib/commons-collections-2.1.jar
diff -ru avalon-excalibur.0/depchecker.xml avalon-excalibur/depchecker.xml
--- avalon-excalibur.0/depchecker.xml   2003-04-05 23:39:34.000000000 +0400
+++ avalon-excalibur/depchecker.xml     2003-05-25 12:23:52.000000000 +0400
@@ -265,6 +265,27 @@
         </ant>
     </target>
 
+    <!-- Fortress Tools -->
+    <target name="checkFortressTools">
+        <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkRequiredFile">
+            <property name="proj.jar.name" value="excalibur-fortress-tools-1.0.jar"/>
+            <property name="path" value="${avalon-fortress-tools.jar}"/>
+            <property name="proj.home" value="${basedir}/../fortress"/>
+        </ant>
+        <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkRequiredClass">
+            <property name="proj.jar.name" value="qdox.jar"/>
+            <property name="class" value="com.thoughtworks.qdox.ant.AbstractQdoxTask"/>
+            <property name="classpath" value="${cp}"/>
+            <property name="remedy" value="1) Download and unpack qdox from ${nl}
+           | http://qdox.codehaus.org/ ${nl}
+           |   2) Copy the project's ant.properties.sample to ant.properties ${nl}
+           |   3) In ant.properties, redefine the qdox.jar property ${nl}
+           |      to point to the path of qdox.jar in your ${nl}
+           |      downloaded distribution."/>
+        </ant>
+
+    </target>
+
     <!-- Altrmi -->
     <target name="checkAltrmiCommon">
         <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkRequiredFile">
diff -ru avalon-excalibur.0/libraries.properties avalon-excalibur/libraries.properties
--- avalon-excalibur.0/libraries.properties     2003-05-21 10:59:22.000000000 +0400
+++ avalon-excalibur/libraries.properties       2003-05-25 12:08:58.000000000 +0400
@@ -119,6 +119,11 @@
 #                BUILD ARTIFACTS
 # --------------------------------------------------
 
+# ----- fortress ------
+avalon-fortress.home=${basedir}/../fortress
+avalon-fortress.lib=${avalon-fortress.home}/dist
+avalon-fortress-tools.jar=${avalon-fortress.lib}/excalibur-fortress-tools-1.0.jar
+
 # ----- compatibility -------------
 excalibur-compatibility.home=${basedir}/../compatibility
 excalibur-compatibility.lib=${excalibur-compatibility.home}/build/lib
diff -ru avalon-excalibur.0/monitor/build.xml avalon-excalibur/monitor/build.xml
--- avalon-excalibur.0/monitor/build.xml        2003-05-21 11:00:24.000000000 +0400
+++ avalon-excalibur/monitor/build.xml  2003-05-25 13:22:02.000000000 +0400
@@ -19,6 +19,8 @@
         <pathelement location="${checkstyle.jar}"/>
         <pathelement location="${excalibur-logger.jar}"/>
         <pathelement location="${excalibur-sourceresolve.jar}"/>
+        <pathelement location="${avalon-fortress-tools.jar}"/>
+        <pathelement location="${qdox.jar}"/>
         <pathelement path="${java.class.path}"/>
     </path>
 
@@ -53,6 +55,7 @@
         <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkLogkit"/>
         <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkFramework"/>
         <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkSourceResolve"/>
+        <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkFortressTools"/>
    </target>
 
     <target name="dependencies-test" depends="dist-jar, dependencies"
@@ -85,6 +88,16 @@
             <include name="**/*.java"/>
         </javac>
 
+        <!-- generate fortress meta descriptors -->
+        <taskdef name="fortress-collect-meta"
+            classname="org.apache.avalon.fortress.tools.ComponentMetaInfoCollector">
+            <classpath refid="project.class.path"/>
+        </taskdef>
+
+        <fortress-collect-meta destdir="${build.classes}">
+            <fileset dir="${java.dir}"/>
+        </fortress-collect-meta>
+
         <!-- copy resources to same location as .class files -->
         <copy todir="${build.classes}">
             <fileset dir="${java.dir}">
diff -ru avalon-excalibur.0/monitor/default.properties avalon-excalibur/monitor/default.properties
--- avalon-excalibur.0/monitor/default.properties       2003-05-21 11:00:26.000000000 +0400
+++ avalon-excalibur/monitor/default.properties 2003-05-25 13:16:08.000000000 +0400
@@ -74,6 +74,14 @@
 excalibur-i18n.lib=${excalibur-i18n.home}
 excalibur-i18n.jar=${excalibur-i18n.lib}/excalibur-i18n-1.0.jar
 
+# ----- Avalon Fortress, version 1.0 or later  -----
+avalon-fortress.home=${basedir}/../fortress
+avalon-fortress.lib=${avalon-fortress.home}/dist
+avalon-fortress-tools.jar=${avalon-fortress.lib}/excalibur-fortress-tools-1.0.jar
+
+# ----- QDox Jar ----
+qdox.jar=${basedir}/../lib/qdox-1.1.jar
+
 # ----- Commons Collections -----
 commons-collections.home=${basedir}/../lib
 commons-collections.lib=${commons-collections.home}
diff -ru avalon-excalibur.0/store/build.xml avalon-excalibur/store/build.xml
--- avalon-excalibur.0/store/build.xml  2003-05-21 11:00:46.000000000 +0400
+++ avalon-excalibur/store/build.xml    2003-05-26 10:49:48.000000000 +0400
@@ -15,6 +15,8 @@
         <pathelement location="${build.classes}"/>
         <pathelement location="${avalon-framework.jar}"/>
         <pathelement location="${checkstyle.jar}"/>
+        <pathelement location="${avalon-fortress-tools.jar}"/>
+        <pathelement location="${qdox.jar}"/>
         <pathelement location="${jisp.jar}"/>
         <pathelement path="${java.class.path}"/>
     </path>
@@ -39,6 +41,7 @@
     <target name="dependencies" description="Check dependencies" unless="skip.dependencies">
         <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkCommon"/>
         <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkFramework"/>
+        <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkFortressTools"/>
     </target>
 
     <target name="dependencies-test" depends="dist-jar, dependencies"
@@ -65,6 +68,16 @@
             <include name="**/*.java"/>
         </javac>
 
+        <!-- generate fortress meta descriptors -->
+        <taskdef name="fortress-collect-meta"
+            classname="org.apache.avalon.fortress.tools.ComponentMetaInfoCollector">
+            <classpath refid="project.class.path"/>
+        </taskdef>
+
+        <fortress-collect-meta destdir="${build.classes}">
+            <fileset dir="${java.dir}"/>
+        </fortress-collect-meta>
+
         <!-- copy resources to same location as .class files -->
         <copy todir="${build.classes}">
             <fileset dir="${java.dir}">
diff -ru avalon-excalibur.0/xmlutil/build.xml avalon-excalibur/xmlutil/build.xml
--- avalon-excalibur.0/xmlutil/build.xml        2003-05-08 21:11:20.000000000 +0400
+++ avalon-excalibur/xmlutil/build.xml  2003-05-25 13:27:32.000000000 +0400
@@ -30,6 +30,8 @@
         <pathelement location="${jaxen.jar}"/>
         <pathelement location="${resolver.jar}"/>
         <pathelement location="${jtidy.jar}"/>
+        <pathelement location="${avalon-fortress-tools.jar}"/>
+        <pathelement location="${qdox.jar}"/>
         <pathelement path="${java.class.path}"/>
     </path>
 
@@ -66,6 +68,7 @@
         <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkPool"/>
         <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkSourceResolve"/>
         <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkStore"/>
+        <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkFortressTools"/>
         <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkRequiredFile">
             <property name="proj.jar.name" value="xerces.jar"/>
             <property name="path" value="${xerces.jar}"/>
@@ -106,6 +109,16 @@
             <exclude name="**/test/**"/>
         </javac>
 
+        <!-- generate fortress meta descriptors -->
+        <taskdef name="fortress-collect-meta"
+            classname="org.apache.avalon.fortress.tools.ComponentMetaInfoCollector">
+            <classpath refid="project.class.path"/>
+        </taskdef>
+
+        <fortress-collect-meta destdir="${build.classes}">
+            <fileset dir="${java.dir}"/>
+        </fortress-collect-meta>
+
         <!-- copy resources to same location as .class files -->
         <copy todir="${build.classes}">
             <fileset dir="${java.dir}">
diff -ru avalon-excalibur.0/xmlutil/default.properties avalon-excalibur/xmlutil/default.properties
--- avalon-excalibur.0/xmlutil/default.properties       2003-05-08 21:11:20.000000000 +0400
+++ avalon-excalibur/xmlutil/default.properties 2003-05-25 13:23:18.000000000 +0400
@@ -61,6 +61,14 @@
 excalibur-store.lib=${excalibur-store.home}
 excalibur-store.jar=${excalibur-store.lib}/excalibur-store-1.0.jar
 
+# ----- Avalon Fortress, version 1.0 or later  -----
+avalon-fortress.home=${basedir}/../fortress
+avalon-fortress.lib=${avalon-fortress.home}/dist
+avalon-fortress-tools.jar=${avalon-fortress.lib}/excalibur-fortress-tools-1.0.jar
+
+# ----- QDox Jar ----
+qdox.jar=${basedir}/../lib/qdox-1.1.jar
+
 # ----- Commons collections, version 2.1 or later -----
 commons-collections.jar=${basedir}/../lib/commons-collections-2.1.jar


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re[2]: [Patch] #13 resubmitted

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Berin!


AT> +    public void setContextDirectory( final URL url )
AT> Further investigation has shown that this patch _is_ needed.

BL> You can bind a File object directly like this:

BL> FortressConfig.setContextDirectory(
BL>      servletContext.getRealPath( "/WEB-INF/avalon" ) );

Yup, but as you say

BL> The thing is that some vendors like IBM
BL> WebSphere relocate everything and use a "classloader:" protocol.

I was speaking about exactly that!

In fact Servlet spec allowes everything to be run from an unpacked
.war file. It's a perfectly legitimate approach.

BL> We need to make it simple to work with--and either work with
BL> Files or URLs.

Justification for having both:

BL> SourceResolver--which can handle both URL and File.

:-)

BL> If you use the context root as a relative location for the
BL> log file (as is the default case), then you need a File, and
BL> not a URL.

A direct hit! That's why I would never use it for anything
not read-only.

We have a
    (File) servletContext.getAttribute( "javax.servlet.context.tempdir" )
for read-write access (and it's a guarateed File!) but it's not good for
logs either since the servlet container is allowed to wipe tempdir
on its restart.

So, I beleive that the location of the logs should be configured
some other way. Probably directly in a .xlog file or somewhere
in web.xml via some init parameter.

BL> The thing is I believe Fortress expects a File root, although
BL> it is primarily for the
BL> SourceResolver--which can handle both
BL> URL and File.

Well, I beleive that if a developer creates a web application
he should be aware that the applicatoin tree may probably be
read-only for him at runtime. (Or his webapp is not portable.).
If he makes a URL that may be readonly at runtime the context-root,
well, he's asked for it himself. He should know what he is doing.
Shouldn't he?

AT> and I get something like (writing by memory)
AT>     file:/C:/file/D:\goj\t331ah\webapps\tst\WEB-INF\avalon

BL> The problem here is a bug in the toExternalForm() method.
BL> This is most likely from your J2EE servlet container vendor.
BL> Notice that there is no colon after the second file?  There
BL> is also no protocol named "file/D" so that is why it fails.

Sorry about misleading you, Berin :-(
I beleive that it rather the following effect:

import java.io.File;

public class A{
    public static void main(String[] args) throws Exception
    {
        final File inner = new File( "d:/foo.txt" );
        final String innerURL = inner.toURL().toExternalForm();
        final File doubleFile = new File( innerURL );
        System.out.println( doubleFile.toURL() );
    }
}

this outputs
    file:/d:/temp/file:/d:/foo.txt

I have misleaded you by missing one colon in the offending output
(indeed I was in too a hurry and wrote that string by memory).

So it's all about
* Tomcat 3.1.1 (that's what my employer requires)
  returning file:D:<some-path> and FortressConfig
* me casting it to a string via .toExternalForm()
* FortressConfig creating new File( string )

============================

Conclusion:

    public void setContextDirectory( final String directory )
    {
        m_context.put( ContextManagerConstants.CONTEXT_DIRECTORY, new File( directory ) );
    }

will probably do something wrong with "classloader:...",
so I propose to have a

    public void setContextDirectory( final URL url )
    {
        m_context.put( ContextManagerConstants.CONTEXT_DIRECTORY, url );
    }

:-)


Maybe setContextDirectory() is not the best name as proposed in this
patch, maybe we should better to have

setContextDirectory( File )
setContextDirectory( String s ) { .. new File( s ) .. }
setContextURL( URL )
setContextURL( String u ){ .. new URL( u ) .. }

?

or maybe it would be better to stress we it's a context _root_

setContextRootURL( URL )
setContextRootURL( String url )

?

- Anton

P.S.
Currently I do

        final Context defaultContext = FortressConfig.createDefaultConfig();
        
        m_initialFortressContext = new DefaultContext( defaultContext );
        
        final URL contextRoot = getOurContextRoot();
        m_initialFortressContext.put( ContainerConstants.CONTEXT_DIRECTORY, contextRoot );
        
        m_initialFortressContext.put( SERVLET_CONTEXT_CONTEXT_KEY, servletContext );
        
        m_initialFortressContext.makeReadOnly();
        
        final FortressConfig fortressConfig = new FortressConfig( m_initialFortressContext );

so a workaround exists, moreover, it is necessary to do this to get
the servletContext in ( servlet logger factory from logkit will need
it), but still I beleive that it will be cleaner to add two
setContextURL() to FortressConfig

P.P.S.
If approved will send a new patch - with two methods instead of one
and named setContextContextRoot( URL )

P.P.P.S.
No compelling reason to do that before release,
(although servlet-writers like are likely to spend some time guessing
what they really should do :-)
just as the discussion continues
I'm sending in my replies :-)

-- 
Best regards,
 Anton                            mailto:atagunov@mail.cnt.ru


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Patch] #13 resubmitted

Posted by Berin Loritsch <bl...@apache.org>.
Anton Tagunov wrote:
> Hello Berin!
> 
> AT> +    public void setContextDirectory( final URL url )
> 
> Further investigation has shown that this patch _is_ needed.
> In fact, in a servlet I do
> 
> URL urlRoot = servletContext.getResource( "/WEB-INF/avalon" );
> String stringRoot = urlRoot.toExternalFort();
> FortressConfig.setContextDirectory( stringRoot );

You can bind a File object directly like this:

FortressConfig.setContextDirectory(
     servletContext.getRealPath( "/WEB-INF/avalon" ) );

> and I get something like (writing by memory)
>     file:/C:/file/D:\goj\t331ah\webapps\tst\WEB-INF\avalon
> on Windows.
> 
> When however I first create a DefaultContext() and bind in
> urlRoot as "context-root" to it and create FortressContext
> on it then all is ok
>     file:D:\goj\t331ah\webapps\tst\WEB-INF\avalon
> 
> So, I'm resending the patch.


The problem here is a bug in the toExternalForm() method.
This is most likely from your J2EE servlet container vendor.
Notice that there is no colon after the second file?  There
is also no protocol named "file/D" so that is why it fails.
The thing is I believe Fortress expects a File root, although
it is primarily for the SourceResolver--which can handle both
URL and File.

We need to make it simple to work with--and either work with
Files or URLs.  The thing is that some vendors like IBM
WebSphere relocate everything and use a "classloader:" protocol.
If you use the context root as a relative location for the
log file (as is the default case), then you need a File, and
not a URL.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re[2]: [Patch] #13 resubmitted

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Berin!

AT> +    public void setContextDirectory( final URL url )

Further investigation has shown that this patch _is_ needed.
In fact, in a servlet I do

URL urlRoot = servletContext.getResource( "/WEB-INF/avalon" );
String stringRoot = urlRoot.toExternalFort();
FortressConfig.setContextDirectory( stringRoot );

and I get something like (writing by memory)
    file:/C:/file/D:\goj\t331ah\webapps\tst\WEB-INF\avalon
on Windows.

When however I first create a DefaultContext() and bind in
urlRoot as "context-root" to it and create FortressContext
on it then all is ok
    file:D:\goj\t331ah\webapps\tst\WEB-INF\avalon

So, I'm resending the patch.

- Anton

--- FortressConfig.orig 2003-05-29 09:59:36.000000000 +0400
+++ FortressConfig.java 2003-05-29 16:22:59.000000000 +0400
@@ -61,6 +61,7 @@
 import org.apache.excalibur.mpool.PoolManager;
 
 import java.io.File;
+import java.io.URL;
 
 /**
  * Helper class to create a m_context for the ContextManager.
@@ -212,6 +213,11 @@
         m_context.put( ContextManagerConstants.CONTEXT_DIRECTORY, new File( directory ) );
     }
 
+    public void setContextDirectory( final URL url )
+    {
+        m_context.put( ContextManagerConstants.CONTEXT_DIRECTORY, url );
+    }
+
     public void setLoggerCategory( final String category )
     {
         m_context.put( ContextManagerConstants.LOG_CATEGORY, category );


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Patch] #13 revoked

Posted by Anton Tagunov <at...@mail.cnt.ru>.
AT> +    public void setContextDirectory( final URL url )

I must have worked to hard and overheated in the sun.
Sorry.

Whar URL-s can be when we do all the resolution ourselves
in SourceResolver?

- Anton


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


[Patch] #13

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Berin and All!

Anybody afraid of Patch #13
(a wickid black night was closing in ... woo-woooooo... )

Just being practical now I'm putting Fortress inside a servlet,
so it occured to me this might be usefull.

Admittedly the name of the method does not fit its purpose very well.
I considered setContextRoot but then it falls out of the row with
other peer methods.

- Anton


--- FortressConfig.orig 2003-05-29 09:59:36.000000000 +0400
+++ FortressConfig.java 2003-05-29 16:22:59.000000000 +0400
@@ -61,6 +61,7 @@
 import org.apache.excalibur.mpool.PoolManager;
 
 import java.io.File;
+import java.io.URL;
 
 /**
  * Helper class to create a m_context for the ContextManager.
@@ -212,6 +213,11 @@
         m_context.put( ContextManagerConstants.CONTEXT_DIRECTORY, new File( directory ) );
     }
 
+    public void setContextDirectory( final URL url )
+    {
+        m_context.put( ContextManagerConstants.CONTEXT_DIRECTORY, url );
+    }
+
     public void setLoggerCategory( final String category )
     {
         m_context.put( ContextManagerConstants.LOG_CATEGORY, category );


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Phase III Release] Postponed until we have a stable Fortress

Posted by Berin Loritsch <bl...@apache.org>.
Berin Loritsch wrote:
> 
> Thanks to the efforts of Anton Tagunov and others, we have been
> shaking out some bugs and other issues.  However until we get
> them all resolved, I suggest that we wait until the patches
> stop coming in.
> 
> In the mean time, Anton, don't stop with bug fixes.  What else
> are you seeing?


BTW, I would like to get this resolved by Tuesday/Wednesday
next week.  We have had an RC for a long time for this, and our
users need something.  Right now what is in CVS is pretty good.



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Patch] #11-bis - there was a typo in the inline docs

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Sorry to double post. An incorrectly placed "the" in the inline doc
has made me resend the patch.

diff -ru src.orig/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java
--- src.orig/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java  2003-05-28 10:20:10.000000000 +0400
+++ src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java       2003-05-28 12:33:30.000000000 +0400
@@ -205,7 +205,7 @@
             ContainerUtil.enableLogging( instance, m_logger );
             ContainerUtil.contextualize( instance, implContext );
 
-            final ServiceManager serviceManager = createServiceManager( implContext );
+            final ServiceManager serviceManager = createServiceManager( managerContext );
 
             ContainerUtil.service( instance, serviceManager );
 
diff -ru src.orig/java/org/apache/avalon/fortress/util/ContextManager.java src/java/org/apache/avalon/fortress/util/ContextManager.java
--- src.orig/java/org/apache/avalon/fortress/util/ContextManager.java   2003-05-28 10:20:26.000000000 +0400
+++ src/java/org/apache/avalon/fortress/util/ContextManager.java        2003-05-28 12:53:45.000000000 +0400
@@ -103,20 +103,16 @@
  * get an instance of the Context, it is made read-only and returned.  No
  * further operations will be possible on it.</p>
  *
- * <p>You can get two different contexts from the ContextManager: the child
- * context and the impl manager context. The former contains all
- * managers, such as the pool manager etc. necessary for a child impl to
- * create additional child containers. The impl manager context contains
- * all of the child context, but also initialization parameters for the
- * impl, such as a Configuration object, a ComponentLocator, etc., that
- * the impl wants, but does not want to pass on to its children.</p>
+ * <p>You can get two different contexts from the ContextManager: 
+ * the container context (m_childContext) 
+ * and the container manager context (m_contaimerManagerContext).
  *
- * <p>You would typically use the impl manager context to initialize
- * the impl manager, and let it pass the child context on to the
- * impl.</p>
+ * <p>The container manager context is used to provide the container manager
+ * with all the data needed to initialize the container.</p>
+ * <p>The container context is passed directly to the container.</p>
  *
- * <p>The ContextManager will sometimes create new components, such as a
- * component manager, a pool manager, etc. It will manage these components
+ * <p>The ContextManager will sometimes create new components, such as
+ * a service manager, a pool manager, etc. It will manage these components
  * and dispose of them properly when it itself is disposed .</p>
  *
  * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
@@ -163,7 +159,6 @@
      */
     private Logger m_logger;
     private final Logger m_primordialLogger;
-    private ServiceManager m_manager;
 
     /**
      * The components that are "owned" by this context and should
@@ -237,6 +232,7 @@
      */
     public void initialize() throws Exception
     {
+        initializeDefaultSourceResolver();
         initializeServiceManager();
         initializeLoggerManager();
         initializeMetaInfoManager();
@@ -248,6 +244,8 @@
 
         m_childContext.makeReadOnly();
         m_containerManagerContext.makeReadOnly();
+
+        m_defaultSourceResolver = null;
     }
 
     /**
@@ -295,6 +293,16 @@
             getLogger().debug( "Could not copy Context parameters.  This may be Ok depending on "
                 + "other configured context values." );
         }
+       
+        // hide from the container implementation what it does not need
+        m_childContext.put( CONFIGURATION, null );
+        m_childContext.put( CONFIGURATION_URI, null );
+        m_childContext.put( ROLE_MANAGER_CONFIGURATION, null );
+        m_childContext.put( ROLE_MANAGER_CONFIGURATION_URI, null );
+        m_childContext.put( LOGGER_MANAGER_CONFIGURATION, null );
+        m_childContext.put( LOGGER_MANAGER_CONFIGURATION_URI, null );
+        m_childContext.put( INSTRUMENT_MANAGER_CONFIGURATION, null );
+        m_childContext.put( INSTRUMENT_MANAGER_CONFIGURATION_URI, null );
     }
 
     /**
@@ -392,7 +400,7 @@
     {
         try
         {
-            m_rootContext.get( Queue.ROLE );
+            copyEntry( Queue.ROLE );
             return;
         }
         catch ( ContextException ce )
@@ -400,7 +408,7 @@
         }
 
         // No CommandQueue specified, create a default one
-        m_childContext.put( Queue.ROLE, createCommandSink() );
+        m_containerManagerContext.put( Queue.ROLE, createCommandSink() );
     }
 
     /**
@@ -418,7 +426,7 @@
         assumeOwnership( tm );
 
         // Get the context Logger Manager
-        final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+        final LoggerManager loggerManager = (LoggerManager) m_containerManagerContext.get( LoggerManager.ROLE );
 
         // Get the logger for the thread manager
         final Logger tmLogger = loggerManager.getLoggerForCategory( "system.threadmgr" );
@@ -487,16 +495,16 @@
     {
         try
         {
-            m_rootContext.get( PoolManager.ROLE );
+            copyEntry( PoolManager.ROLE );
             return;
         }
         catch ( ContextException ce )
         {
         }
 
-        final PoolManager pm = new DefaultPoolManager( (Sink) m_childContext.get( Queue.ROLE ) );
+        final PoolManager pm = new DefaultPoolManager( (Sink) m_containerManagerContext.get( Queue.ROLE ) );
         assumeOwnership( pm );
-        m_childContext.put( PoolManager.ROLE, pm );
+        m_containerManagerContext.put( PoolManager.ROLE, pm );
     }
 
     /**
@@ -535,7 +543,7 @@
         }
 
         // Get the context Logger Manager
-        final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+        final LoggerManager loggerManager = (LoggerManager) m_containerManagerContext.get( LoggerManager.ROLE );
 
         // Lookup the context class loader
         final ClassLoader classLoader = (ClassLoader) m_rootContext.get( ClassLoader.class.getName() );
@@ -560,7 +568,17 @@
 
     protected void initializeMetaInfoManager() throws Exception
     {
-        final boolean mmSupplied = entryPresent( m_rootContext, MetaInfoManager.ROLE );
+        boolean mmSupplied = false;
+        try
+        {
+            copyEntry( MetaInfoManager.ROLE );
+            mmSupplied = true;
+        }
+        catch( ContextException ce )
+        {
+            // okay, we will create one
+        }
+
         RoleManager roleManager = obtainRoleManager();
         final boolean rmSupplied = roleManager != null;
 
@@ -575,7 +593,7 @@
         }
         else
         {
-            final LoggerManager loggerManager = (LoggerManager)m_childContext.get( LoggerManager.ROLE );
+            final LoggerManager loggerManager = (LoggerManager)m_containerManagerContext.get( LoggerManager.ROLE );
             final ClassLoader classLoader = (ClassLoader)m_rootContext.get( ClassLoader.class.getName() );
 
             if ( ! rmSupplied )
@@ -592,21 +610,25 @@
             metaManager.enableLogging( loggerManager.getLoggerForCategory("system.meta") );
             metaManager.initialize();
             assumeOwnership( metaManager );
-            m_childContext.put( MetaInfoManager.ROLE, metaManager );
+            m_containerManagerContext.put( MetaInfoManager.ROLE, metaManager );
         }
     }
 
     /**
-     * Get a reference to the initial ComponentLocator used by the
-     * ContainerManager to hold the Components used for parsing the config
-     * files and setting up the environment.
-     *
-     * @throws Exception when there is an error.
+     *  Source resolver used to read-in the configurations.
+     *  and provided as a default source resolver if the
+     *  user has not supplied a ServiceManager.
+     *  (Otherwise it or an overriding sourceresolver
+     *  is probably available from that.)
      */
-    protected void initializeServiceManager() throws Exception
+    protected SourceResolver m_defaultSourceResolver;
+
+    /**
+     *  Initialize the default SrouceResolver.
+     */
+    protected void initializeDefaultSourceResolver() throws Exception
     {
-        final ServiceManager parent = (ServiceManager) get( m_rootContext, SERVICE_MANAGER, null );
-        final DefaultServiceManager manager = new DefaultServiceManager( parent );
+        final DefaultServiceManager manager = new DefaultServiceManager();
         final DefaultServiceSelector selector = new DefaultServiceSelector();
         final URLSourceFactory file = new URLSourceFactory();
         file.enableLogging( getLogger() );
@@ -623,15 +645,32 @@
         ContainerUtil.service( resolver, manager );
         ContainerUtil.parameterize( resolver, new Parameters() );
 
-        manager.put( SourceResolver.ROLE, resolver );
-
-        manager.makeReadOnly();
-
-        assumeOwnership( manager );
-
-        m_manager = manager;
-
-        m_childContext.put( ContextManagerConstants.SERVICE_MANAGER, m_manager );
+        m_defaultSourceResolver = resolver;
+    }
+    /**
+     * Get a reference to the initial ComponentLocator used by the
+     * ContainerManager to hold the Components used for parsing the config
+     * files and setting up the environment.
+     *
+     * @throws Exception when there is an error.
+     */
+    protected void initializeServiceManager() throws Exception
+    {
+        try
+        {
+             copyEntry( SERVICE_MANAGER );
+        }
+        catch( ContextException ce )
+        {
+            final DefaultServiceManager manager = new DefaultServiceManager();
+        
+            // provide a default source resolver good in many situations
+            manager.put( SourceResolver.ROLE, m_defaultSourceResolver );
+        
+            manager.makeReadOnly();
+        
+            m_containerManagerContext.put( ContextManagerConstants.SERVICE_MANAGER, manager );
+        }
     }
 
     /**
@@ -668,8 +707,7 @@
         Source src = null;
         try
         {
-            resolver = (SourceResolver) m_manager.lookup( SourceResolver.ROLE );
-            src = resolver.resolveURI( configUri );
+            src = m_defaultSourceResolver.resolveURI( configUri );
             if ( configBuilder == null )
             {
                 configBuilder = new DefaultConfigurationBuilder();
@@ -685,12 +723,7 @@
         }
         finally
         {
-            if ( null != resolver )
-            {
-                resolver.release( src );
-            }
-
-            m_manager.release( resolver );
+            m_defaultSourceResolver.release( src );
         }
     }
 
@@ -747,7 +780,7 @@
         {
             // Try copying an already existing logger manager from the override context.
 
-            m_childContext.put( LoggerManager.ROLE, m_rootContext.get( LoggerManager.ROLE ) );
+            copyEntry( LoggerManager.ROLE );
         }
         catch ( ContextException ce )
         {
@@ -788,7 +821,7 @@
 
             assumeOwnership( logManager );
 
-            m_childContext.put( LoggerManager.ROLE, logManager );
+            m_containerManagerContext.put( LoggerManager.ROLE, logManager );
         }
 
         // Since we now have a LoggerManager, we can update the this.logger field
@@ -798,7 +831,7 @@
         {
             getLogger().debug( "Switching to default Logger provided by LoggerManager." );
 
-            final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+            final LoggerManager loggerManager = (LoggerManager) m_containerManagerContext.get( LoggerManager.ROLE );
             m_logger = loggerManager.getDefaultLogger();
         }
     }
@@ -819,7 +852,7 @@
         {
             // Try copying an already existing instrument manager from the override context.
 
-            m_rootContext.get( InstrumentManager.ROLE );
+            copyEntry( InstrumentManager.ROLE );
         }
         catch ( ContextException ce )
         {
@@ -833,7 +866,7 @@
             }
 
             // Get the context Logger Manager
-            final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+            final LoggerManager loggerManager = (LoggerManager) m_containerManagerContext.get( LoggerManager.ROLE );
 
             // Get the logger for the instrument manager
             final Logger imLogger = loggerManager.getLoggerForCategory(
@@ -847,7 +880,7 @@
 
             assumeOwnership( instrumentManager );
 
-            m_childContext.put( InstrumentManager.ROLE, instrumentManager );
+            m_containerManagerContext.put( InstrumentManager.ROLE, instrumentManager );
         }
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


[Patch] #11.3

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Uff.. More nuts -- more taste :)

1. ===============

I just couldn't resist this refactoring of
DefaultContainerManager/ContextManager.

I beleive that this patch as compared to #11-bis-2
improves code simplicity. The difference is the following:

  loggerManager
  queue
  metaInfoManager
  poolManager
  instrumentManager

etc. -- all that AbstractContainer fetches from
its ServiceManager -- are now stuffed into the
serviceManager directly by ContextManager.

This has required the introduction of

  m_loggerManager
  m_queue
  m_metaInfoManager
  m_poolManager
  m_instrumentManager

variables into ContextManager, but this is all the
overhead we get.

In return DefaultContainerManager
has become two methods shorter and we do not need
to fetch loggerManager and queue back from
m_containerManagerContext when we need them again in
ContextManager/initialize*.

As an additional bonus this makes the ServiceManager
hierarchy one level shorter in the common usage scenario.

2. ===============

On my way I have found that a change would be desirable
to event//CommandManager, we were calling
    Sink getCommandSink()
on it and after that coerced the result to Queue (as
really a queue was returned)

This patch adds a getCommandQueue() method to CommandManager.

3. ==============

Naturally this patch includes all that is included into
#11
#11-bis-2
so the comments in the respective comments apply.

Sorry about scattering them among severl mails :-/

WBR, Anton


diff -ru avalon-excalibur.0/event/src/java/org/apache/excalibur/event/command/CommandManager.java avalon-excalibur/event/src/java/org/apache/excalibur/event/command/CommandManager.java
--- avalon-excalibur.0/event/src/java/org/apache/excalibur/event/command/CommandManager.java    2003-03-22 15:46:28.000000000 +0300
+++ avalon-excalibur/event/src/java/org/apache/excalibur/event/command/CommandManager.java      2003-05-28 14:09:50.000000000 +0400
@@ -130,6 +130,16 @@
     }
 
     /**
+     * Get the Command Queue so that you can enqueue and dequeue commands.
+     *
+     * @return the Sink that feeds the CommandManager
+     */
+    public final Queue getCommandQueue()
+    {
+        return m_queue;
+    }
+
+    /**
      * Register a Signal with an EventHandler.  The Signal is a special object
      * that implements the {@link Signal} interface.  When CommandManager recieves
      * events that match the Signal, it will send a copy of it to all the
diff -ru avalon-excalibur.0/fortress/src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java avalon-excalibur/fortress/src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java
--- avalon-excalibur.0/fortress/src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java   2003-05-28 10:20:10.000000000 +0400
+++ avalon-excalibur/fortress/src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java     2003-05-28 14:00:12.000000000 +0400
@@ -205,7 +205,8 @@
             ContainerUtil.enableLogging( instance, m_logger );
             ContainerUtil.contextualize( instance, implContext );
 
-            final ServiceManager serviceManager = createServiceManager( implContext );
+            final ServiceManager serviceManager = 
+                (ServiceManager) getContextEntry( managerContext, SERVICE_MANAGER );
 
             ContainerUtil.service( instance, serviceManager );
 
@@ -230,38 +231,6 @@
         }
     }
 
-    private ServiceManager createServiceManager( final Context managerContext )
-    {
-        final ServiceManager smanager =
-            (ServiceManager) getContextEntry( managerContext, SERVICE_MANAGER );
-        final DefaultServiceManager serviceManager = new DefaultServiceManager( smanager );
-
-        addService( Queue.ROLE, managerContext, serviceManager );
-        addService( LoggerManager.ROLE, managerContext, serviceManager );
-        addService( PoolManager.ROLE, managerContext, serviceManager );
-        addService( InstrumentManager.ROLE, managerContext, serviceManager );
-        addService( MetaInfoManager.ROLE, managerContext, serviceManager );
-        addService( RoleManager.ROLE, managerContext, serviceManager );
-        addService( LifecycleExtensionManager.ROLE, managerContext, serviceManager );
-        serviceManager.makeReadOnly();
-
-        return serviceManager;
-    }
-
-    private void addService( final String role,
-                             final Context context,
-                             final DefaultServiceManager serviceManager )
-    {
-        try
-        {
-            final Object object = context.get( role );
-            serviceManager.put( role, object );
-        }
-        catch ( ContextException e )
-        {
-        }
-    }
-
     /**
      * Retrieve an entry from context if it exists, else return null.
      *
diff -ru avalon-excalibur.0/fortress/src/java/org/apache/avalon/fortress/util/ContextManager.java avalon-excalibur/fortress/src/java/org/apache/avalon/fortress/util/ContextManager.java
--- avalon-excalibur.0/fortress/src/java/org/apache/avalon/fortress/util/ContextManager.java    2003-05-28 10:20:26.000000000 +0400
+++ avalon-excalibur/fortress/src/java/org/apache/avalon/fortress/util/ContextManager.java      2003-05-28 14:34:54.000000000 +0400
@@ -74,7 +74,6 @@
 import org.apache.avalon.framework.service.DefaultServiceSelector;
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.excalibur.event.Queue;
-import org.apache.excalibur.event.Sink;
 import org.apache.excalibur.event.command.CommandManager;
 import org.apache.excalibur.event.command.TPCThreadManager;
 import org.apache.excalibur.event.command.ThreadManager;
@@ -103,20 +102,16 @@
  * get an instance of the Context, it is made read-only and returned.  No
  * further operations will be possible on it.</p>
  *
- * <p>You can get two different contexts from the ContextManager: the child
- * context and the impl manager context. The former contains all
- * managers, such as the pool manager etc. necessary for a child impl to
- * create additional child containers. The impl manager context contains
- * all of the child context, but also initialization parameters for the
- * impl, such as a Configuration object, a ComponentLocator, etc., that
- * the impl wants, but does not want to pass on to its children.</p>
+ * <p>You can get two different contexts from the ContextManager: 
+ * the container context (m_childContext) 
+ * and the container manager context (m_contaimerManagerContext).
  *
- * <p>You would typically use the impl manager context to initialize
- * the impl manager, and let it pass the child context on to the
- * impl.</p>
+ * <p>The container manager context is used to provide the container manager
+ * with all the data needed to initialize the container.</p>
+ * <p>The container context is passed directly to the container.</p>
  *
- * <p>The ContextManager will sometimes create new components, such as a
- * component manager, a pool manager, etc. It will manage these components
+ * <p>The ContextManager will sometimes create new components, such as
+ * a service manager, a pool manager, etc. It will manage these components
  * and dispose of them properly when it itself is disposed .</p>
  *
  * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
@@ -139,21 +134,21 @@
     /**
      * The root context.
      */
-    private final Context m_rootContext;
+    protected final Context m_rootContext;
 
     /**
      * The context of the new impl. This context has the rootContext
      * as its parent. Put everything here that you want the new impl
      * to have in its own context.
      */
-    private final DefaultContext m_childContext;
+    protected final DefaultContext m_childContext;
 
     /**
      * Container manager's context. This context has the child context
      * as parent. Put things here that you want the impl manager
      * to see, but do not wish to expose to the impl.
      */
-    private final DefaultContext m_containerManagerContext;
+    protected final DefaultContext m_containerManagerContext;
 
     /**
      * New context passed in, maybe from a FortressConfig.
@@ -161,9 +156,45 @@
      * other pointers. The ContextManager inspects it for
      * elements it can use to create component managers etc.
      */
-    private Logger m_logger;
-    private final Logger m_primordialLogger;
-    private ServiceManager m_manager;
+    protected Logger m_logger;
+    protected final Logger m_primordialLogger;
+
+    /**
+     * Source resolver used to read-in the configurations.
+     * and provided as a default source resolver if the
+     * user has not supplied a ServiceManager.
+     */
+    protected SourceResolver m_defaultSourceResolver;
+
+    /**
+     * The logger manager in use. 
+     * Either supplied via rootContext, or created locally.
+     */ 
+    protected LoggerManager m_loggerManager;
+
+    /**
+     * The Queue in use. 
+     * Either supplied via rootContext or created locally.
+     */
+    protected Queue m_queue;
+
+    /**
+     * The MetaInfoManager to be used by the container.
+     * Either supplied via rootContext or created locally.
+     */
+    protected MetaInfoManager m_metaInfoManager;
+
+    /**
+     * The PoolManager to be used by the container.
+     * Either supplied via rootContext or created locally.
+     */
+    protected PoolManager m_poolManager;
+
+    /**
+     * The InstrumentManager to be used by the container.
+     * Either supplied via rootContext or created locally.
+     */
+    protected InstrumentManager m_instrumentManager;
 
     /**
      * The components that are "owned" by this context and should
@@ -219,7 +250,7 @@
      *
      * @throws IllegalArgumentException if the object is null.
      */
-    private void assumeOwnership( final Object object )
+    protected void assumeOwnership( final Object object )
     {
         if ( object == null )
         {
@@ -237,7 +268,7 @@
      */
     public void initialize() throws Exception
     {
-        initializeServiceManager();
+        initializeDefaultSourceResolver();
         initializeLoggerManager();
         initializeMetaInfoManager();
         initializeCommandQueue();
@@ -245,9 +276,12 @@
         initializeContext();
         initializeInstrumentManager();
         initializeConfiguration();
+        initializeServiceManager();
 
         m_childContext.makeReadOnly();
         m_containerManagerContext.makeReadOnly();
+
+        m_defaultSourceResolver = null;
     }
 
     /**
@@ -295,6 +329,22 @@
             getLogger().debug( "Could not copy Context parameters.  This may be Ok depending on "
                 + "other configured context values." );
         }
+       
+        // hide from the container implementation what it does not need
+        m_childContext.put( CONFIGURATION, null );
+        m_childContext.put( CONFIGURATION_URI, null );
+        m_childContext.put( RoleManager.ROLE, null );
+        m_childContext.put( ROLE_MANAGER_CONFIGURATION, null );
+        m_childContext.put( ROLE_MANAGER_CONFIGURATION_URI, null );
+        m_childContext.put( LoggerManager.ROLE, null );
+        m_childContext.put( LOGGER_MANAGER_CONFIGURATION, null );
+        m_childContext.put( LOGGER_MANAGER_CONFIGURATION_URI, null );
+        m_childContext.put( InstrumentManager.ROLE, null );
+        m_childContext.put( INSTRUMENT_MANAGER_CONFIGURATION, null );
+        m_childContext.put( INSTRUMENT_MANAGER_CONFIGURATION_URI, null );
+        m_childContext.put( Queue.ROLE, null );
+        m_childContext.put( MetaInfoManager.ROLE, null );
+        m_childContext.put( PoolManager.ROLE, null );
     }
 
     /**
@@ -392,15 +442,13 @@
     {
         try
         {
-            m_rootContext.get( Queue.ROLE );
-            return;
+            m_queue = (Queue) m_rootContext.get( Queue.ROLE );
         }
         catch ( ContextException ce )
         {
+            // No CommandQueue specified, create a default one
+            m_queue = createCommandQueue();
         }
-
-        // No CommandQueue specified, create a default one
-        m_childContext.put( Queue.ROLE, createCommandSink() );
     }
 
     /**
@@ -409,7 +457,7 @@
      * @return a default <code>CommandQueue</code>
      * @throws Exception if an error occurs
      */
-    private Sink createCommandSink() throws Exception
+    private Queue createCommandQueue() throws Exception
     {
         final CommandManager cm = new CommandManager();
         final ThreadManager tm = new TPCThreadManager();
@@ -417,11 +465,8 @@
         assumeOwnership( cm );
         assumeOwnership( tm );
 
-        // Get the context Logger Manager
-        final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
-
         // Get the logger for the thread manager
-        final Logger tmLogger = loggerManager.getLoggerForCategory( "system.threadmgr" );
+        final Logger tmLogger = m_loggerManager.getLoggerForCategory( "system.threadmgr" );
 
         ContainerUtil.enableLogging( tm, tmLogger );
         ContainerUtil.parameterize( tm, buildCommandQueueConfig() );
@@ -429,7 +474,7 @@
 
         tm.register( cm );
 
-        return cm.getCommandSink();
+        return cm.getCommandQueue();
     }
 
     /**
@@ -487,16 +532,14 @@
     {
         try
         {
-            m_rootContext.get( PoolManager.ROLE );
-            return;
+            m_poolManager = (PoolManager) m_rootContext.get( PoolManager.ROLE );
         }
         catch ( ContextException ce )
         {
+            final PoolManager pm = new DefaultPoolManager( m_queue );
+            assumeOwnership( pm );
+            m_poolManager = pm;
         }
-
-        final PoolManager pm = new DefaultPoolManager( (Sink) m_childContext.get( Queue.ROLE ) );
-        assumeOwnership( pm );
-        m_childContext.put( PoolManager.ROLE, pm );
     }
 
     /**
@@ -534,14 +577,11 @@
             return null;
         }
 
-        // Get the context Logger Manager
-        final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
-
         // Lookup the context class loader
         final ClassLoader classLoader = (ClassLoader) m_rootContext.get( ClassLoader.class.getName() );
 
         // Create a logger for the role manager
-        final Logger rmLogger = loggerManager.getLoggerForCategory(
+        final Logger rmLogger = m_loggerManager.getLoggerForCategory(
             roleConfig.getAttribute( "logger", "system.roles" ) );
 
         // Create a parent role manager with all the default roles
@@ -560,7 +600,17 @@
 
     protected void initializeMetaInfoManager() throws Exception
     {
-        final boolean mmSupplied = entryPresent( m_rootContext, MetaInfoManager.ROLE );
+        boolean mmSupplied = false;
+        try
+        {
+            m_metaInfoManager = (MetaInfoManager) m_rootContext.get( MetaInfoManager.ROLE );
+            mmSupplied = true;
+        }
+        catch( ContextException ce )
+        {
+            // okay, we will create one
+        }
+
         RoleManager roleManager = obtainRoleManager();
         final boolean rmSupplied = roleManager != null;
 
@@ -575,13 +625,12 @@
         }
         else
         {
-            final LoggerManager loggerManager = (LoggerManager)m_childContext.get( LoggerManager.ROLE );
             final ClassLoader classLoader = (ClassLoader)m_rootContext.get( ClassLoader.class.getName() );
 
             if ( ! rmSupplied )
             {
                 final FortressRoleManager newRoleManager = new FortressRoleManager( null, classLoader );
-                newRoleManager.enableLogging(loggerManager.getLoggerForCategory("system.roles"));
+                newRoleManager.enableLogging(m_loggerManager.getLoggerForCategory("system.roles"));
                 newRoleManager.initialize();
 
                 roleManager = newRoleManager;
@@ -589,24 +638,19 @@
 
             final ServiceMetaManager metaManager = new ServiceMetaManager( new Role2MetaInfoManager( roleManager ), classLoader );
 
-            metaManager.enableLogging( loggerManager.getLoggerForCategory("system.meta") );
+            metaManager.enableLogging( m_loggerManager.getLoggerForCategory("system.meta") );
             metaManager.initialize();
             assumeOwnership( metaManager );
-            m_childContext.put( MetaInfoManager.ROLE, metaManager );
+            m_metaInfoManager = metaManager;
         }
     }
 
     /**
-     * Get a reference to the initial ComponentLocator used by the
-     * ContainerManager to hold the Components used for parsing the config
-     * files and setting up the environment.
-     *
-     * @throws Exception when there is an error.
+     *  Initialize the default SrouceResolver.
      */
-    protected void initializeServiceManager() throws Exception
+    protected void initializeDefaultSourceResolver() throws Exception
     {
-        final ServiceManager parent = (ServiceManager) get( m_rootContext, SERVICE_MANAGER, null );
-        final DefaultServiceManager manager = new DefaultServiceManager( parent );
+        final DefaultServiceManager manager = new DefaultServiceManager();
         final DefaultServiceSelector selector = new DefaultServiceSelector();
         final URLSourceFactory file = new URLSourceFactory();
         file.enableLogging( getLogger() );
@@ -623,15 +667,41 @@
         ContainerUtil.service( resolver, manager );
         ContainerUtil.parameterize( resolver, new Parameters() );
 
-        manager.put( SourceResolver.ROLE, resolver );
-
-        manager.makeReadOnly();
-
-        assumeOwnership( manager );
+        m_defaultSourceResolver = resolver;
+    }
+    /**
+     * Get a reference to the initial ComponentLocator used by the
+     * ContainerManager to hold the Components used for parsing the config
+     * files and setting up the environment.
+     *
+     * @throws Exception when there is an error.
+     */
+    protected void initializeServiceManager() throws Exception
+    {
+        final ServiceManager parent = (ServiceManager) get( m_rootContext, SERVICE_MANAGER, null );
+        final DefaultServiceManager manager = new DefaultServiceManager( parent );
 
-        m_manager = manager;
+        /**
+         * We assume that if there is a parent ServiceManager provided,
+         * there is a SourceResolver mounted there. And if there
+         * is none, then it is the true caller's intetion.
+         * However it is hard to imagine how that could be usefull
+         * except for testing purposes.
+         */
+        if ( parent == null )
+        {
+            manager.put( SourceResolver.ROLE, m_defaultSourceResolver );
+        }
+        
+        manager.put( LoggerManager.ROLE, m_loggerManager );
+        manager.put( Queue.ROLE, m_queue );
+        manager.put( MetaInfoManager.ROLE, m_metaInfoManager );
+        manager.put( PoolManager.ROLE, m_poolManager );
+        manager.put( InstrumentManager.ROLE, m_instrumentManager );
 
-        m_childContext.put( ContextManagerConstants.SERVICE_MANAGER, m_manager );
+        manager.makeReadOnly();
+    
+        m_containerManagerContext.put( SERVICE_MANAGER, manager );
     }
 
     /**
@@ -668,8 +738,7 @@
         Source src = null;
         try
         {
-            resolver = (SourceResolver) m_manager.lookup( SourceResolver.ROLE );
-            src = resolver.resolveURI( configUri );
+            src = m_defaultSourceResolver.resolveURI( configUri );
             if ( configBuilder == null )
             {
                 configBuilder = new DefaultConfigurationBuilder();
@@ -685,12 +754,7 @@
         }
         finally
         {
-            if ( null != resolver )
-            {
-                resolver.release( src );
-            }
-
-            m_manager.release( resolver );
+            m_defaultSourceResolver.release( src );
         }
     }
 
@@ -747,7 +811,7 @@
         {
             // Try copying an already existing logger manager from the override context.
 
-            m_childContext.put( LoggerManager.ROLE, m_rootContext.get( LoggerManager.ROLE ) );
+            m_loggerManager = (LoggerManager) m_rootContext.get( LoggerManager.ROLE );
         }
         catch ( ContextException ce )
         {
@@ -788,7 +852,7 @@
 
             assumeOwnership( logManager );
 
-            m_childContext.put( LoggerManager.ROLE, logManager );
+            m_loggerManager = logManager;
         }
 
         // Since we now have a LoggerManager, we can update the this.logger field
@@ -798,8 +862,7 @@
         {
             getLogger().debug( "Switching to default Logger provided by LoggerManager." );
 
-            final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
-            m_logger = loggerManager.getDefaultLogger();
+            m_logger = m_loggerManager.getDefaultLogger();
         }
     }
 
@@ -819,7 +882,7 @@
         {
             // Try copying an already existing instrument manager from the override context.
 
-            m_rootContext.get( InstrumentManager.ROLE );
+            m_instrumentManager = (InstrumentManager) m_rootContext.get( InstrumentManager.ROLE );
         }
         catch ( ContextException ce )
         {
@@ -832,11 +895,8 @@
                 instrumentConfig = EMPTY_CONFIG;
             }
 
-            // Get the context Logger Manager
-            final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
-
             // Get the logger for the instrument manager
-            final Logger imLogger = loggerManager.getLoggerForCategory(
+            final Logger imLogger = m_loggerManager.getLoggerForCategory(
                 instrumentConfig.getAttribute( "logger", "system.instrument" ) );
 
             // Set up the Instrument Manager
@@ -847,7 +907,7 @@
 
             assumeOwnership( instrumentManager );
 
-            m_childContext.put( InstrumentManager.ROLE, instrumentManager );
+            m_instrumentManager = instrumentManager;
         }
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Patch] #11

Posted by Berin Loritsch <bl...@apache.org>.
Anton Tagunov wrote:
> Hello Berin!
> 
> It great so much of my patches has been applied.
> 
> Hmm.. can ContextManager be used in a _nested_ container?
> Not likely, but theoretically possible.
> 
> Hence, this patch. Do you like what is in the patch on this subject?

I'll look more deeply at the patch in a bit.  For now, I am addressing
the other questions.

> 
> 2) =======================
> 
> AT> LoggerManager, PoolManager, InstrumentManager, MetaInfoManager
> AT> LifecycleExtensionsManager, Queue are passed to the Container
> AT> twice: via contextualize() and via service()
> 
> BL> This duplication originated from having them *originally* passed in as
> BL> context entries.  Later, after looking at what these things really were,
> BL> we determined that we were using a Context to access services.  We
> BL> should go the other way and make them only available via the service
> BL> mechanism.
> 
> I understand they are service because they have an interface and
> a ROLE in it? But we never really release them -- is not that an
> argument for accessing them via Context?

They are *services* because they are entities that perform a function.
They are logically services, and behaviorily services.  The purpose
of the Context is to pass constants to the client.

Admittedly there is some overlap between a Context and the
ServiceManager, and in a future version of Avalon we _might_ merge
the concepts.  However, we should be true to the purpose of these
objects.

> 
> And after all they are quite different from user services - these
> are system entities.
> 

Yes they are system entities, but they are services.

> If they are available via ServiceManager someone may configure a
> component implementing a PoolManager or a Queue interface or a
> MetaInfoManager in the normal .xconf file and have nested containers
> use that.

True.  They should be expected to know what they are doing.  I
purposely did not want to limit users of Fortress to *have* to use
the central PoolManager, etc. if they didn't want to.

Everything will be able to be overridden.  That is the beauty of
a heirarchical system.  You have your central container, and you
can have other containers put on top of that.  Your containers
would be allowed to replace any service passed to them within that
level of the hierarchy.

For example:

A-+B
   +C+D
     +E

The root container (A) defines all the core system services.  Container
B or C can simply use them, or define new ones.  If container C defines
new system services, it only affects itself (there is no way for it
to infect the root container).  If container C defines new system
services then it will affect containers D and E because they are C's
children.

Again, the developer who does this should know what they are doing.
9 times out of 10 most people will simply use what is available.

> 
> But should these things really be configured like that?
> I do not mean this is a security violation but rather that
> these things are so deep internal to system things ( like Queue )
> that it looks a bit of order to configure them where normal
> user components are configured.

What if I have a modularly written system like Cocoon?  One container
has a different set of components than the next, and I may want to
use a different pool to manage my component instances.

I think it should be like that.

> 
> So, I personally would have been more comfortable with accessing
> them from the Context. Mainly because we never release them.
> ServiceManager context contract is just to "heavy" in concept
> for such a simple thing as "take what I give you once and live on it".
> 

No its not.  The ServiceManager concept is very simple.  They are
services, not *constants*.  The Context should be a place for data,
not services.

Now, if those services were never in the context to begin with,
would you still be asking about it?  I doubt that, because most
people just go with what they have been given.  It is because
there was a duplication that we had a problem.

> Is there any use to discussion this topic?

I haven't had a convincing argument why services should be in a
context, and I am of the mindset that it was a mistake to use that
"contract" to begin with.

> 
> The patch supplied in this mail goes the ServiceManager
> way and removes the duplicated entities from m_childContext.

Good. :)  It will most likely be applied then.

> 
> 3) ===============================
> This patch also hides *CONFIGURAION and *CONFIGURATION_URI
> from the container implementation.

Ok.

> 
> 4) ===============================
> I have also updated the main section of the
> inline documentation on ContextManager a bit.
> The inline sections on separate methods still
> are outdated sometimes - but I think this is
> bearable at them moment.

Ok.

<snip type="patch"/>


-- 
"You know the world is going crazy when the best
rapper is a white guy, the best golfer is a black guy,
The Swiss hold the America's Cup, France is
accusing the US of arrogance, and Germany doesn't want
to go to war. And the 3 most powerful men in America
are named 'Bush', 'Dick', and 'Colon' (sic)".

-----Chris Rock


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Patch] #11-bis-2

Posted by Anton Tagunov <at...@mail.cnt.ru>.
This patch does all the same as [Patch] #11
but also it changes private to public in
ContextManager on several member variables
(m_childContext, m_contextManagerContext, etc)
and one function (assumeOwership).

As all of the initialize* methods are protected
this assumes that theoretically this class might
be switched from final to non-final in the future
and subclassed.

Well, I sort of felt embarassed the initialize*
methods are protected and the variables that
their overriden analogs would need to operate
upon (if the class was not final) are private.

I beleive that this change is otherwise useless,
except that it improves the style and readablity.

I beleive that this discrepance is really somthing
a Java developer may stumble upon reading the code and
burn his mind-cycles on solving an unexisting puzzle.

So I ask you to kindly accept these changes :)

Oh, BTW, I have also relocated m_localSourceResolver
to a more suitable location in the file.

- Anton

diff -ru src.orig/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java
--- src.orig/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java  2003-05-28 10:20:10.000000000 +0400
+++ src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java       2003-05-28 12:33:30.000000000 +0400
@@ -205,7 +205,7 @@
             ContainerUtil.enableLogging( instance, m_logger );
             ContainerUtil.contextualize( instance, implContext );
 
-            final ServiceManager serviceManager = createServiceManager( implContext );
+            final ServiceManager serviceManager = createServiceManager( managerContext );
 
             ContainerUtil.service( instance, serviceManager );
 
diff -ru src.orig/java/org/apache/avalon/fortress/util/ContextManager.java src/java/org/apache/avalon/fortress/util/ContextManager.java
--- src.orig/java/org/apache/avalon/fortress/util/ContextManager.java   2003-05-28 10:20:26.000000000 +0400
+++ src/java/org/apache/avalon/fortress/util/ContextManager.java        2003-05-28 13:29:43.000000000 +0400
@@ -103,20 +103,16 @@
  * get an instance of the Context, it is made read-only and returned.  No
  * further operations will be possible on it.</p>
  *
- * <p>You can get two different contexts from the ContextManager: the child
- * context and the impl manager context. The former contains all
- * managers, such as the pool manager etc. necessary for a child impl to
- * create additional child containers. The impl manager context contains
- * all of the child context, but also initialization parameters for the
- * impl, such as a Configuration object, a ComponentLocator, etc., that
- * the impl wants, but does not want to pass on to its children.</p>
+ * <p>You can get two different contexts from the ContextManager: 
+ * the container context (m_childContext) 
+ * and the container manager context (m_contaimerManagerContext).
  *
- * <p>You would typically use the impl manager context to initialize
- * the impl manager, and let it pass the child context on to the
- * impl.</p>
+ * <p>The container manager context is used to provide the container manager
+ * with all the data needed to initialize the container.</p>
+ * <p>The container context is passed directly to the container.</p>
  *
- * <p>The ContextManager will sometimes create new components, such as a
- * component manager, a pool manager, etc. It will manage these components
+ * <p>The ContextManager will sometimes create new components, such as
+ * a service manager, a pool manager, etc. It will manage these components
  * and dispose of them properly when it itself is disposed .</p>
  *
  * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
@@ -139,21 +135,21 @@
     /**
      * The root context.
      */
-    private final Context m_rootContext;
+    protected final Context m_rootContext;
 
     /**
      * The context of the new impl. This context has the rootContext
      * as its parent. Put everything here that you want the new impl
      * to have in its own context.
      */
-    private final DefaultContext m_childContext;
+    protected final DefaultContext m_childContext;
 
     /**
      * Container manager's context. This context has the child context
      * as parent. Put things here that you want the impl manager
      * to see, but do not wish to expose to the impl.
      */
-    private final DefaultContext m_containerManagerContext;
+    protected final DefaultContext m_containerManagerContext;
 
     /**
      * New context passed in, maybe from a FortressConfig.
@@ -161,9 +157,15 @@
      * other pointers. The ContextManager inspects it for
      * elements it can use to create component managers etc.
      */
-    private Logger m_logger;
-    private final Logger m_primordialLogger;
-    private ServiceManager m_manager;
+    protected Logger m_logger;
+    protected final Logger m_primordialLogger;
+
+    /**
+     *  Source resolver used to read-in the configurations.
+     *  and provided as a default source resolver if the
+     *  user has not supplied a ServiceManager.
+     */
+    protected SourceResolver m_defaultSourceResolver;
 
     /**
      * The components that are "owned" by this context and should
@@ -219,7 +221,7 @@
      *
      * @throws IllegalArgumentException if the object is null.
      */
-    private void assumeOwnership( final Object object )
+    protected void assumeOwnership( final Object object )
     {
         if ( object == null )
         {
@@ -237,6 +239,7 @@
      */
     public void initialize() throws Exception
     {
+        initializeDefaultSourceResolver();
         initializeServiceManager();
         initializeLoggerManager();
         initializeMetaInfoManager();
@@ -248,6 +251,8 @@
 
         m_childContext.makeReadOnly();
         m_containerManagerContext.makeReadOnly();
+
+        m_defaultSourceResolver = null;
     }
 
     /**
@@ -295,6 +300,16 @@
             getLogger().debug( "Could not copy Context parameters.  This may be Ok depending on "
                 + "other configured context values." );
         }
+       
+        // hide from the container implementation what it does not need
+        m_childContext.put( CONFIGURATION, null );
+        m_childContext.put( CONFIGURATION_URI, null );
+        m_childContext.put( ROLE_MANAGER_CONFIGURATION, null );
+        m_childContext.put( ROLE_MANAGER_CONFIGURATION_URI, null );
+        m_childContext.put( LOGGER_MANAGER_CONFIGURATION, null );
+        m_childContext.put( LOGGER_MANAGER_CONFIGURATION_URI, null );
+        m_childContext.put( INSTRUMENT_MANAGER_CONFIGURATION, null );
+        m_childContext.put( INSTRUMENT_MANAGER_CONFIGURATION_URI, null );
     }
 
     /**
@@ -392,7 +407,7 @@
     {
         try
         {
-            m_rootContext.get( Queue.ROLE );
+            copyEntry( Queue.ROLE );
             return;
         }
         catch ( ContextException ce )
@@ -400,7 +415,7 @@
         }
 
         // No CommandQueue specified, create a default one
-        m_childContext.put( Queue.ROLE, createCommandSink() );
+        m_containerManagerContext.put( Queue.ROLE, createCommandSink() );
     }
 
     /**
@@ -418,7 +433,7 @@
         assumeOwnership( tm );
 
         // Get the context Logger Manager
-        final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+        final LoggerManager loggerManager = (LoggerManager) m_containerManagerContext.get( LoggerManager.ROLE );
 
         // Get the logger for the thread manager
         final Logger tmLogger = loggerManager.getLoggerForCategory( "system.threadmgr" );
@@ -487,16 +502,16 @@
     {
         try
         {
-            m_rootContext.get( PoolManager.ROLE );
+            copyEntry( PoolManager.ROLE );
             return;
         }
         catch ( ContextException ce )
         {
         }
 
-        final PoolManager pm = new DefaultPoolManager( (Sink) m_childContext.get( Queue.ROLE ) );
+        final PoolManager pm = new DefaultPoolManager( (Sink) m_containerManagerContext.get( Queue.ROLE ) );
         assumeOwnership( pm );
-        m_childContext.put( PoolManager.ROLE, pm );
+        m_containerManagerContext.put( PoolManager.ROLE, pm );
     }
 
     /**
@@ -535,7 +550,7 @@
         }
 
         // Get the context Logger Manager
-        final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+        final LoggerManager loggerManager = (LoggerManager) m_containerManagerContext.get( LoggerManager.ROLE );
 
         // Lookup the context class loader
         final ClassLoader classLoader = (ClassLoader) m_rootContext.get( ClassLoader.class.getName() );
@@ -560,7 +575,17 @@
 
     protected void initializeMetaInfoManager() throws Exception
     {
-        final boolean mmSupplied = entryPresent( m_rootContext, MetaInfoManager.ROLE );
+        boolean mmSupplied = false;
+        try
+        {
+            copyEntry( MetaInfoManager.ROLE );
+            mmSupplied = true;
+        }
+        catch( ContextException ce )
+        {
+            // okay, we will create one
+        }
+
         RoleManager roleManager = obtainRoleManager();
         final boolean rmSupplied = roleManager != null;
 
@@ -575,7 +600,7 @@
         }
         else
         {
-            final LoggerManager loggerManager = (LoggerManager)m_childContext.get( LoggerManager.ROLE );
+            final LoggerManager loggerManager = (LoggerManager)m_containerManagerContext.get( LoggerManager.ROLE );
             final ClassLoader classLoader = (ClassLoader)m_rootContext.get( ClassLoader.class.getName() );
 
             if ( ! rmSupplied )
@@ -592,21 +617,16 @@
             metaManager.enableLogging( loggerManager.getLoggerForCategory("system.meta") );
             metaManager.initialize();
             assumeOwnership( metaManager );
-            m_childContext.put( MetaInfoManager.ROLE, metaManager );
+            m_containerManagerContext.put( MetaInfoManager.ROLE, metaManager );
         }
     }
 
     /**
-     * Get a reference to the initial ComponentLocator used by the
-     * ContainerManager to hold the Components used for parsing the config
-     * files and setting up the environment.
-     *
-     * @throws Exception when there is an error.
+     *  Initialize the default SrouceResolver.
      */
-    protected void initializeServiceManager() throws Exception
+    protected void initializeDefaultSourceResolver() throws Exception
     {
-        final ServiceManager parent = (ServiceManager) get( m_rootContext, SERVICE_MANAGER, null );
-        final DefaultServiceManager manager = new DefaultServiceManager( parent );
+        final DefaultServiceManager manager = new DefaultServiceManager();
         final DefaultServiceSelector selector = new DefaultServiceSelector();
         final URLSourceFactory file = new URLSourceFactory();
         file.enableLogging( getLogger() );
@@ -623,15 +643,32 @@
         ContainerUtil.service( resolver, manager );
         ContainerUtil.parameterize( resolver, new Parameters() );
 
-        manager.put( SourceResolver.ROLE, resolver );
-
-        manager.makeReadOnly();
-
-        assumeOwnership( manager );
-
-        m_manager = manager;
-
-        m_childContext.put( ContextManagerConstants.SERVICE_MANAGER, m_manager );
+        m_defaultSourceResolver = resolver;
+    }
+    /**
+     * Get a reference to the initial ComponentLocator used by the
+     * ContainerManager to hold the Components used for parsing the config
+     * files and setting up the environment.
+     *
+     * @throws Exception when there is an error.
+     */
+    protected void initializeServiceManager() throws Exception
+    {
+        try
+        {
+             copyEntry( SERVICE_MANAGER );
+        }
+        catch( ContextException ce )
+        {
+            final DefaultServiceManager manager = new DefaultServiceManager();
+        
+            // provide a default source resolver good in many situations
+            manager.put( SourceResolver.ROLE, m_defaultSourceResolver );
+        
+            manager.makeReadOnly();
+        
+            m_containerManagerContext.put( ContextManagerConstants.SERVICE_MANAGER, manager );
+        }
     }
 
     /**
@@ -668,8 +705,7 @@
         Source src = null;
         try
         {
-            resolver = (SourceResolver) m_manager.lookup( SourceResolver.ROLE );
-            src = resolver.resolveURI( configUri );
+            src = m_defaultSourceResolver.resolveURI( configUri );
             if ( configBuilder == null )
             {
                 configBuilder = new DefaultConfigurationBuilder();
@@ -685,12 +721,7 @@
         }
         finally
         {
-            if ( null != resolver )
-            {
-                resolver.release( src );
-            }
-
-            m_manager.release( resolver );
+            m_defaultSourceResolver.release( src );
         }
     }
 
@@ -747,7 +778,7 @@
         {
             // Try copying an already existing logger manager from the override context.
 
-            m_childContext.put( LoggerManager.ROLE, m_rootContext.get( LoggerManager.ROLE ) );
+            copyEntry( LoggerManager.ROLE );
         }
         catch ( ContextException ce )
         {
@@ -788,7 +819,7 @@
 
             assumeOwnership( logManager );
 
-            m_childContext.put( LoggerManager.ROLE, logManager );
+            m_containerManagerContext.put( LoggerManager.ROLE, logManager );
         }
 
         // Since we now have a LoggerManager, we can update the this.logger field
@@ -798,7 +829,7 @@
         {
             getLogger().debug( "Switching to default Logger provided by LoggerManager." );
 
-            final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+            final LoggerManager loggerManager = (LoggerManager) m_containerManagerContext.get( LoggerManager.ROLE );
             m_logger = loggerManager.getDefaultLogger();
         }
     }
@@ -819,7 +850,7 @@
         {
             // Try copying an already existing instrument manager from the override context.
 
-            m_rootContext.get( InstrumentManager.ROLE );
+            copyEntry( InstrumentManager.ROLE );
         }
         catch ( ContextException ce )
         {
@@ -833,7 +864,7 @@
             }
 
             // Get the context Logger Manager
-            final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+            final LoggerManager loggerManager = (LoggerManager) m_containerManagerContext.get( LoggerManager.ROLE );
 
             // Get the logger for the instrument manager
             final Logger imLogger = loggerManager.getLoggerForCategory(
@@ -847,7 +878,7 @@
 
             assumeOwnership( instrumentManager );
 
-            m_childContext.put( InstrumentManager.ROLE, instrumentManager );
+            m_containerManagerContext.put( InstrumentManager.ROLE, instrumentManager );
         }
     }
 
Only in src/java/org/apache/avalon/fortress/util: patch11-bis-2.diff


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re[2]: [Patch] #11.4 -- oops #11.3 blue up one of the tests

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Berin!

I see lots of "Ok" from you and this definetely rises my spirits!
:-)

BL> I am rapidly reaching the point of Fortress being "Good Enough" for
BL> release.  Unless you find any *bugs*, I suggest we hold off on the
BL> refactoring until after the release.

Here's what I think will be needed before release:

1) Patch #10 (a rewritten analog) is _definetely_ needed.

1.1) I see it like this: we always create a copy of
LifecycleExtensionManager in every container and add the
InstrumentableCreator to the copy (not to infect our parent
container).

1.2) And yes, I beleive we do need getChildContext() from that
patch badly too -- it is a means of allowing
containers to modify the context before handing it to
their children.

I will be able to send #10.1 tomorrow.

2)

Oh, one more thing we may want before release:
I've sent a mail to the list about teaching
ContextManager to alternatively create a Log4JLoggerManager
by duducting the type of the logger manager from the
logger manager configuration file.

I was asking in that mail how is it best to it.

2.1) One variant was to check the name of the root node in .xlog
     and if it is log4j:configuration go for Log4JConfLoggerManager.

2.2) There was also an issue of automatically propagating
     worker directory to Log4J configuration DOM tree if
     there isn't one already.

I beleive that anyone including me might easily implement
2.1 (but I won't be able to test it :-(

I think this will significantly add value to Fortress.
As I have said I will be able to send 1.1, 1.2 and 2.1
tomorrow.

As for 2.2 I need at least an advice. (Or this may wait
until 1.0.1)

- Anton


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Patch] #11.4 -- oops #11.3 blue up one of the tests

Posted by Berin Loritsch <bl...@apache.org>.
Anton Tagunov wrote:
> Really sorry about this - again a new version.

> 2. ==================
> 
> DefaultContainerManager was left without a logger as LoggerManager
> was no longer put to m_containerManagerContext.
> 
> This version of the patch adds a LOGGER constant to
> ContainerManagerConstants and makes ContextManager pass its
> own logger to DefaultContainerManager.

Ok.

> 
> This even looks a code simplification to me:
> 
> 1) we no longer deal with LoggerManager in DefaultContainerManager,
>    only with Logger

Ok.

> 
> 2) in the following rare situation
>    (usage scenario not promoted by any examples but
>    theoretically possible)
> 
>        ContextManager ctxm = new ContextManager( fortressConfig.getContext(),
>            my-unique-and-desired-logger );
> 
>        ContainerManager ctnm = new DefaultContainerManager( cm );
> 
>    ContainerManager will use the same logger as was
>    passed to the ContextManager, which is probably desirable
>    as ContextManager is only a spare part used by ContainerManager
>    and they should act as a one thing.
>    Without this change ContainerManager in this situation will use
>    loggerManager.getDefaultLogger().

Ok.  Sounds good so far.

> 
> P.S. Aren't you tired from my refactoring the code?
>      XP says it's a good thing, and what do you say? ;-)

I am rapidly reaching the point of Fortress being "Good Enough" for
release.  Unless you find any *bugs*, I suggest we hold off on the
refactoring until after the release.

> 
>      
> P.P.S.
> 
> Hopefully this has been my last pass on ContextManager,
> (unless someone says: oh, it was so nice to pass all the
> stuff to Container via Context, not ServiceManager :-)

No one will say that ;P



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: To Sink or to Queue

Posted by Berin Loritsch <bl...@apache.org>.
Anton Tagunov wrote:
> Hello Berin!
> 
> BL> As I mentioned earlier, the Sink is the real contract.  It should
> BL> be a Sink.  Now, the method does return a Queue (which includes
> BL> both a Sink and a Source).  For the time being it works, but if
> BL> we get more strict then it won't.
> 
> Just what I'm speaking about.
> Let's do one of
> 
> A. Make Sink a Role interface (add a ROLE there)
>    and go forward to switching to Sink from Queue.
> 
> B. Keep in mind that a Sink is kept under Queue.ROLE
>    and never coerce what we get from Queue.ROLE
>    to Queue, but only to Sink.
> 
> I understand that A. might upset someone already
> using Fortress, but isn't now the last moment to do A?


Yes it is, so that is what we *should* do.


-- 
"You know the world is going crazy when the best
rapper is a white guy, the best golfer is a black guy,
The Swiss hold the America's Cup, France is
accusing the US of arrogance, and Germany doesn't want
to go to war. And the 3 most powerful men in America
are named 'Bush', 'Dick', and 'Colon' (sic)".

-----Chris Rock


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


To Sink or to Queue (was: [Patch] #11.4 -- oops #11.3 blue up one of the tests)

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Berin!

BL> As I mentioned earlier, the Sink is the real contract.  It should
BL> be a Sink.  Now, the method does return a Queue (which includes
BL> both a Sink and a Source).  For the time being it works, but if
BL> we get more strict then it won't.

Just what I'm speaking about.
Let's do one of

A. Make Sink a Role interface (add a ROLE there)
   and go forward to switching to Sink from Queue.

B. Keep in mind that a Sink is kept under Queue.ROLE
   and never coerce what we get from Queue.ROLE
   to Queue, but only to Sink.

I understand that A. might upset someone already
using Fortress, but isn't now the last moment to do A?

- Anton


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Patch] #11.4 -- oops #11.3 blue up one of the tests

Posted by Berin Loritsch <bl...@apache.org>.
Anton Tagunov wrote:
> Hello Berin!
> 
> 
>>>     /**
>>>+     * Get the Command Queue so that you can enqueue and dequeue commands.
>>>+     *
>>>+     * @return the Sink that feeds the CommandManager
>>>+     */
>>>+    public final Queue getCommandQueue()
>>>+    {
>>>+        return m_queue;
>>>+    }
> 
> 
> BL> Already has a getCommandSink() which is the real contract.
> 
> 
> But we need a Queue!
> We do coerce like (Queue) after we invoke getCommandSink(),
> so I see two good ways out now:
> 
> a) change the return type (or introduce a new method, which
>    seemed less desctructive to me)
> 
> b) change our requirements and treat what we get only as
>    a Sink, not as a Queue
> 
> Which is what we really need?

As I mentioned earlier, the Sink is the real contract.  It should
be a Sink.  Now, the method does return a Queue (which includes
both a Sink and a Source).  For the time being it works, but if
we get more strict then it won't.


-- 
"You know the world is going crazy when the best
rapper is a white guy, the best golfer is a black guy,
The Swiss hold the America's Cup, France is
accusing the US of arrogance, and Germany doesn't want
to go to war. And the 3 most powerful men in America
are named 'Bush', 'Dick', and 'Colon' (sic)".

-----Chris Rock


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re[2]: [Patch] #11.4 -- oops #11.3 blue up one of the tests

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Berin!

>>      /**
>> +     * Get the Command Queue so that you can enqueue and dequeue commands.
>> +     *
>> +     * @return the Sink that feeds the CommandManager
>> +     */
>> +    public final Queue getCommandQueue()
>> +    {
>> +        return m_queue;
>> +    }

BL> Already has a getCommandSink() which is the real contract.


But we need a Queue!
We do coerce like (Queue) after we invoke getCommandSink(),
so I see two good ways out now:

a) change the return type (or introduce a new method, which
   seemed less desctructive to me)

b) change our requirements and treat what we get only as
   a Sink, not as a Queue

Which is what we really need?

- Anton


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Patch] #11.4 -- oops #11.3 blue up one of the tests

Posted by Berin Loritsch <bl...@apache.org>.
> 
> diff -ru avalon-excalibur.0/event/src/java/org/apache/excalibur/event/command/CommandManager.java avalon-excalibur/event/src/java/org/apache/excalibur/event/command/CommandManager.java
> --- avalon-excalibur.0/event/src/java/org/apache/excalibur/event/command/CommandManager.java    2003-03-22 15:46:28.000000000 +0300
> +++ avalon-excalibur/event/src/java/org/apache/excalibur/event/command/CommandManager.java      2003-05-28 14:09:50.000000000 +0400
> @@ -130,6 +130,16 @@
>      }
>  
>      /**
> +     * Get the Command Queue so that you can enqueue and dequeue commands.
> +     *
> +     * @return the Sink that feeds the CommandManager
> +     */
> +    public final Queue getCommandQueue()
> +    {
> +        return m_queue;
> +    }

Already has a getCommandSink() which is the real contract.

-- 
"You know the world is going crazy when the best
rapper is a white guy, the best golfer is a black guy,
The Swiss hold the America's Cup, France is
accusing the US of arrogance, and Germany doesn't want
to go to war. And the 3 most powerful men in America
are named 'Bush', 'Dick', and 'Colon' (sic)".

-----Chris Rock


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


[Patch] #11.4 -- oops #11.3 blue up one of the tests

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Really sorry about this - again a new version.

1. ==================
A test has been brought up to date with the changed contract
of ContextManager.

(Accidentially submitted the patch before the test series completed)

2. ==================

DefaultContainerManager was left without a logger as LoggerManager
was no longer put to m_containerManagerContext.

This version of the patch adds a LOGGER constant to
ContainerManagerConstants and makes ContextManager pass its
own logger to DefaultContainerManager.

This even looks a code simplification to me:

1) we no longer deal with LoggerManager in DefaultContainerManager,
   only with Logger

2) in the following rare situation
   (usage scenario not promoted by any examples but
   theoretically possible)

       ContextManager ctxm = new ContextManager( fortressConfig.getContext(),
           my-unique-and-desired-logger );

       ContainerManager ctnm = new DefaultContainerManager( cm );

   ContainerManager will use the same logger as was
   passed to the ContextManager, which is probably desirable
   as ContextManager is only a spare part used by ContainerManager
   and they should act as a one thing.
   Without this change ContainerManager in this situation will use
   loggerManager.getDefaultLogger().

   I agree the example above could be rewritten as

       ContextManager ctxm = new ContextManager( fortressConfig.getContext(),
                                            my-unique-and-desired-logger
                                            );

       ContainerManager ctnm = new DefaultContainerManager( cm,
           my-unique-and-desired-logger );

   In this situaion both Context and Container manager will use
   the desired logger even without the change, but still see
   this change as bringing a 0.001% enhancment to system behavior.

WBR, Anton

P.S. Aren't you tired from my refactoring the code?
     XP says it's a good thing, and what do you say? ;-)

     
P.P.S.

Hopefully this has been my last pass on ContextManager,
(unless someone says: oh, it was so nice to pass all the
stuff to Container via Context, not ServiceManager :-)

diff -ru avalon-excalibur.0/event/src/java/org/apache/excalibur/event/command/CommandManager.java avalon-excalibur/event/src/java/org/apache/excalibur/event/command/CommandManager.java
--- avalon-excalibur.0/event/src/java/org/apache/excalibur/event/command/CommandManager.java    2003-03-22 15:46:28.000000000 +0300
+++ avalon-excalibur/event/src/java/org/apache/excalibur/event/command/CommandManager.java      2003-05-28 14:09:50.000000000 +0400
@@ -130,6 +130,16 @@
     }
 
     /**
+     * Get the Command Queue so that you can enqueue and dequeue commands.
+     *
+     * @return the Sink that feeds the CommandManager
+     */
+    public final Queue getCommandQueue()
+    {
+        return m_queue;
+    }
+
+    /**
      * Register a Signal with an EventHandler.  The Signal is a special object
      * that implements the {@link Signal} interface.  When CommandManager recieves
      * events that match the Signal, it will send a copy of it to all the
diff -ru avalon-excalibur.0/fortress/src/java/org/apache/avalon/fortress/ContainerManagerConstants.java avalon-excalibur/fortress/src/java/org/apache/avalon/fortress/ContainerManagerConstants.java
--- avalon-excalibur.0/fortress/src/java/org/apache/avalon/fortress/ContainerManagerConstants.java      2003-04-22 16:37:08.000000000 +0400
+++ avalon-excalibur/fortress/src/java/org/apache/avalon/fortress/ContainerManagerConstants.java        2003-05-28 14:57:14.000000000 +0400
@@ -49,6 +49,7 @@
 */
 package org.apache.avalon.fortress;
 
+import org.apache.avalon.framework.logger.Logger;
 import org.apache.avalon.framework.service.ServiceManager;
 
 /**
@@ -72,6 +73,11 @@
     String SERVICE_MANAGER = ServiceManager.class.getName();
 
     /**
+     * Logger where to log our own messages.
+     */
+    String LOGGER = Logger.class.getName();
+
+    /**
      * Configuration: The configuration to give to the impl.
      */
     String CONFIGURATION = "impl.configuration";
diff -ru avalon-excalibur.0/fortress/src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java avalon-excalibur/fortress/src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java
--- avalon-excalibur.0/fortress/src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java   2003-05-28 10:20:10.000000000 +0400
+++ avalon-excalibur/fortress/src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java     2003-05-28 14:55:52.000000000 +0400
@@ -49,7 +49,6 @@
 */
 package org.apache.avalon.fortress.impl;
 
-import org.apache.avalon.excalibur.logger.LoggerManager;
 import org.apache.avalon.fortress.*;
 import org.apache.avalon.fortress.util.ContextManager;
 import org.apache.avalon.fortress.util.LifecycleExtensionManager;
@@ -143,8 +142,8 @@
     {
         try
         {
-            final LoggerManager loggerManager = (LoggerManager) initParameters.get( LoggerManager.ROLE );
-            return loggerManager.getDefaultLogger();
+            final Logger logger = (Logger) initParameters.get( LOGGER );
+            return logger;
         }
         catch ( ContextException ce )
         {
@@ -205,7 +204,8 @@
             ContainerUtil.enableLogging( instance, m_logger );
             ContainerUtil.contextualize( instance, implContext );
 
-            final ServiceManager serviceManager = createServiceManager( implContext );
+            final ServiceManager serviceManager = 
+                (ServiceManager) getContextEntry( managerContext, SERVICE_MANAGER );
 
             ContainerUtil.service( instance, serviceManager );
 
@@ -230,38 +230,6 @@
         }
     }
 
-    private ServiceManager createServiceManager( final Context managerContext )
-    {
-        final ServiceManager smanager =
-            (ServiceManager) getContextEntry( managerContext, SERVICE_MANAGER );
-        final DefaultServiceManager serviceManager = new DefaultServiceManager( smanager );
-
-        addService( Queue.ROLE, managerContext, serviceManager );
-        addService( LoggerManager.ROLE, managerContext, serviceManager );
-        addService( PoolManager.ROLE, managerContext, serviceManager );
-        addService( InstrumentManager.ROLE, managerContext, serviceManager );
-        addService( MetaInfoManager.ROLE, managerContext, serviceManager );
-        addService( RoleManager.ROLE, managerContext, serviceManager );
-        addService( LifecycleExtensionManager.ROLE, managerContext, serviceManager );
-        serviceManager.makeReadOnly();
-
-        return serviceManager;
-    }
-
-    private void addService( final String role,
-                             final Context context,
-                             final DefaultServiceManager serviceManager )
-    {
-        try
-        {
-            final Object object = context.get( role );
-            serviceManager.put( role, object );
-        }
-        catch ( ContextException e )
-        {
-        }
-    }
-
     /**
      * Retrieve an entry from context if it exists, else return null.
      *
diff -ru avalon-excalibur.0/fortress/src/java/org/apache/avalon/fortress/util/ContextManager.java avalon-excalibur/fortress/src/java/org/apache/avalon/fortress/util/ContextManager.java
--- avalon-excalibur.0/fortress/src/java/org/apache/avalon/fortress/util/ContextManager.java    2003-05-28 10:20:26.000000000 +0400
+++ avalon-excalibur/fortress/src/java/org/apache/avalon/fortress/util/ContextManager.java      2003-05-28 14:54:54.000000000 +0400
@@ -74,7 +74,6 @@
 import org.apache.avalon.framework.service.DefaultServiceSelector;
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.excalibur.event.Queue;
-import org.apache.excalibur.event.Sink;
 import org.apache.excalibur.event.command.CommandManager;
 import org.apache.excalibur.event.command.TPCThreadManager;
 import org.apache.excalibur.event.command.ThreadManager;
@@ -103,20 +102,16 @@
  * get an instance of the Context, it is made read-only and returned.  No
  * further operations will be possible on it.</p>
  *
- * <p>You can get two different contexts from the ContextManager: the child
- * context and the impl manager context. The former contains all
- * managers, such as the pool manager etc. necessary for a child impl to
- * create additional child containers. The impl manager context contains
- * all of the child context, but also initialization parameters for the
- * impl, such as a Configuration object, a ComponentLocator, etc., that
- * the impl wants, but does not want to pass on to its children.</p>
+ * <p>You can get two different contexts from the ContextManager: 
+ * the container context (m_childContext) 
+ * and the container manager context (m_contaimerManagerContext).
  *
- * <p>You would typically use the impl manager context to initialize
- * the impl manager, and let it pass the child context on to the
- * impl.</p>
+ * <p>The container manager context is used to provide the container manager
+ * with all the data needed to initialize the container.</p>
+ * <p>The container context is passed directly to the container.</p>
  *
- * <p>The ContextManager will sometimes create new components, such as a
- * component manager, a pool manager, etc. It will manage these components
+ * <p>The ContextManager will sometimes create new components, such as
+ * a service manager, a pool manager, etc. It will manage these components
  * and dispose of them properly when it itself is disposed .</p>
  *
  * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
@@ -139,21 +134,21 @@
     /**
      * The root context.
      */
-    private final Context m_rootContext;
+    protected final Context m_rootContext;
 
     /**
      * The context of the new impl. This context has the rootContext
      * as its parent. Put everything here that you want the new impl
      * to have in its own context.
      */
-    private final DefaultContext m_childContext;
+    protected final DefaultContext m_childContext;
 
     /**
      * Container manager's context. This context has the child context
      * as parent. Put things here that you want the impl manager
      * to see, but do not wish to expose to the impl.
      */
-    private final DefaultContext m_containerManagerContext;
+    protected final DefaultContext m_containerManagerContext;
 
     /**
      * New context passed in, maybe from a FortressConfig.
@@ -161,9 +156,45 @@
      * other pointers. The ContextManager inspects it for
      * elements it can use to create component managers etc.
      */
-    private Logger m_logger;
-    private final Logger m_primordialLogger;
-    private ServiceManager m_manager;
+    protected Logger m_logger;
+    protected final Logger m_primordialLogger;
+
+    /**
+     * Source resolver used to read-in the configurations.
+     * and provided as a default source resolver if the
+     * user has not supplied a ServiceManager.
+     */
+    protected SourceResolver m_defaultSourceResolver;
+
+    /**
+     * The logger manager in use. 
+     * Either supplied via rootContext, or created locally.
+     */ 
+    protected LoggerManager m_loggerManager;
+
+    /**
+     * The Queue in use. 
+     * Either supplied via rootContext or created locally.
+     */
+    protected Queue m_queue;
+
+    /**
+     * The MetaInfoManager to be used by the container.
+     * Either supplied via rootContext or created locally.
+     */
+    protected MetaInfoManager m_metaInfoManager;
+
+    /**
+     * The PoolManager to be used by the container.
+     * Either supplied via rootContext or created locally.
+     */
+    protected PoolManager m_poolManager;
+
+    /**
+     * The InstrumentManager to be used by the container.
+     * Either supplied via rootContext or created locally.
+     */
+    protected InstrumentManager m_instrumentManager;
 
     /**
      * The components that are "owned" by this context and should
@@ -219,7 +250,7 @@
      *
      * @throws IllegalArgumentException if the object is null.
      */
-    private void assumeOwnership( final Object object )
+    protected void assumeOwnership( final Object object )
     {
         if ( object == null )
         {
@@ -237,7 +268,7 @@
      */
     public void initialize() throws Exception
     {
-        initializeServiceManager();
+        initializeDefaultSourceResolver();
         initializeLoggerManager();
         initializeMetaInfoManager();
         initializeCommandQueue();
@@ -245,9 +276,12 @@
         initializeContext();
         initializeInstrumentManager();
         initializeConfiguration();
+        initializeServiceManager();
 
         m_childContext.makeReadOnly();
         m_containerManagerContext.makeReadOnly();
+
+        m_defaultSourceResolver = null;
     }
 
     /**
@@ -295,6 +329,22 @@
             getLogger().debug( "Could not copy Context parameters.  This may be Ok depending on "
                 + "other configured context values." );
         }
+       
+        // hide from the container implementation what it does not need
+        m_childContext.put( CONFIGURATION, null );
+        m_childContext.put( CONFIGURATION_URI, null );
+        m_childContext.put( RoleManager.ROLE, null );
+        m_childContext.put( ROLE_MANAGER_CONFIGURATION, null );
+        m_childContext.put( ROLE_MANAGER_CONFIGURATION_URI, null );
+        m_childContext.put( LoggerManager.ROLE, null );
+        m_childContext.put( LOGGER_MANAGER_CONFIGURATION, null );
+        m_childContext.put( LOGGER_MANAGER_CONFIGURATION_URI, null );
+        m_childContext.put( InstrumentManager.ROLE, null );
+        m_childContext.put( INSTRUMENT_MANAGER_CONFIGURATION, null );
+        m_childContext.put( INSTRUMENT_MANAGER_CONFIGURATION_URI, null );
+        m_childContext.put( Queue.ROLE, null );
+        m_childContext.put( MetaInfoManager.ROLE, null );
+        m_childContext.put( PoolManager.ROLE, null );
     }
 
     /**
@@ -392,15 +442,13 @@
     {
         try
         {
-            m_rootContext.get( Queue.ROLE );
-            return;
+            m_queue = (Queue) m_rootContext.get( Queue.ROLE );
         }
         catch ( ContextException ce )
         {
+            // No CommandQueue specified, create a default one
+            m_queue = createCommandQueue();
         }
-
-        // No CommandQueue specified, create a default one
-        m_childContext.put( Queue.ROLE, createCommandSink() );
     }
 
     /**
@@ -409,7 +457,7 @@
      * @return a default <code>CommandQueue</code>
      * @throws Exception if an error occurs
      */
-    private Sink createCommandSink() throws Exception
+    private Queue createCommandQueue() throws Exception
     {
         final CommandManager cm = new CommandManager();
         final ThreadManager tm = new TPCThreadManager();
@@ -417,11 +465,8 @@
         assumeOwnership( cm );
         assumeOwnership( tm );
 
-        // Get the context Logger Manager
-        final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
-
         // Get the logger for the thread manager
-        final Logger tmLogger = loggerManager.getLoggerForCategory( "system.threadmgr" );
+        final Logger tmLogger = m_loggerManager.getLoggerForCategory( "system.threadmgr" );
 
         ContainerUtil.enableLogging( tm, tmLogger );
         ContainerUtil.parameterize( tm, buildCommandQueueConfig() );
@@ -429,7 +474,7 @@
 
         tm.register( cm );
 
-        return cm.getCommandSink();
+        return cm.getCommandQueue();
     }
 
     /**
@@ -487,16 +532,14 @@
     {
         try
         {
-            m_rootContext.get( PoolManager.ROLE );
-            return;
+            m_poolManager = (PoolManager) m_rootContext.get( PoolManager.ROLE );
         }
         catch ( ContextException ce )
         {
+            final PoolManager pm = new DefaultPoolManager( m_queue );
+            assumeOwnership( pm );
+            m_poolManager = pm;
         }
-
-        final PoolManager pm = new DefaultPoolManager( (Sink) m_childContext.get( Queue.ROLE ) );
-        assumeOwnership( pm );
-        m_childContext.put( PoolManager.ROLE, pm );
     }
 
     /**
@@ -534,14 +577,11 @@
             return null;
         }
 
-        // Get the context Logger Manager
-        final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
-
         // Lookup the context class loader
         final ClassLoader classLoader = (ClassLoader) m_rootContext.get( ClassLoader.class.getName() );
 
         // Create a logger for the role manager
-        final Logger rmLogger = loggerManager.getLoggerForCategory(
+        final Logger rmLogger = m_loggerManager.getLoggerForCategory(
             roleConfig.getAttribute( "logger", "system.roles" ) );
 
         // Create a parent role manager with all the default roles
@@ -560,7 +600,17 @@
 
     protected void initializeMetaInfoManager() throws Exception
     {
-        final boolean mmSupplied = entryPresent( m_rootContext, MetaInfoManager.ROLE );
+        boolean mmSupplied = false;
+        try
+        {
+            m_metaInfoManager = (MetaInfoManager) m_rootContext.get( MetaInfoManager.ROLE );
+            mmSupplied = true;
+        }
+        catch( ContextException ce )
+        {
+            // okay, we will create one
+        }
+
         RoleManager roleManager = obtainRoleManager();
         final boolean rmSupplied = roleManager != null;
 
@@ -575,13 +625,12 @@
         }
         else
         {
-            final LoggerManager loggerManager = (LoggerManager)m_childContext.get( LoggerManager.ROLE );
             final ClassLoader classLoader = (ClassLoader)m_rootContext.get( ClassLoader.class.getName() );
 
             if ( ! rmSupplied )
             {
                 final FortressRoleManager newRoleManager = new FortressRoleManager( null, classLoader );
-                newRoleManager.enableLogging(loggerManager.getLoggerForCategory("system.roles"));
+                newRoleManager.enableLogging(m_loggerManager.getLoggerForCategory("system.roles"));
                 newRoleManager.initialize();
 
                 roleManager = newRoleManager;
@@ -589,24 +638,19 @@
 
             final ServiceMetaManager metaManager = new ServiceMetaManager( new Role2MetaInfoManager( roleManager ), classLoader );
 
-            metaManager.enableLogging( loggerManager.getLoggerForCategory("system.meta") );
+            metaManager.enableLogging( m_loggerManager.getLoggerForCategory("system.meta") );
             metaManager.initialize();
             assumeOwnership( metaManager );
-            m_childContext.put( MetaInfoManager.ROLE, metaManager );
+            m_metaInfoManager = metaManager;
         }
     }
 
     /**
-     * Get a reference to the initial ComponentLocator used by the
-     * ContainerManager to hold the Components used for parsing the config
-     * files and setting up the environment.
-     *
-     * @throws Exception when there is an error.
+     *  Initialize the default SrouceResolver.
      */
-    protected void initializeServiceManager() throws Exception
+    protected void initializeDefaultSourceResolver() throws Exception
     {
-        final ServiceManager parent = (ServiceManager) get( m_rootContext, SERVICE_MANAGER, null );
-        final DefaultServiceManager manager = new DefaultServiceManager( parent );
+        final DefaultServiceManager manager = new DefaultServiceManager();
         final DefaultServiceSelector selector = new DefaultServiceSelector();
         final URLSourceFactory file = new URLSourceFactory();
         file.enableLogging( getLogger() );
@@ -623,15 +667,41 @@
         ContainerUtil.service( resolver, manager );
         ContainerUtil.parameterize( resolver, new Parameters() );
 
-        manager.put( SourceResolver.ROLE, resolver );
-
-        manager.makeReadOnly();
-
-        assumeOwnership( manager );
+        m_defaultSourceResolver = resolver;
+    }
+    /**
+     * Get a reference to the initial ComponentLocator used by the
+     * ContainerManager to hold the Components used for parsing the config
+     * files and setting up the environment.
+     *
+     * @throws Exception when there is an error.
+     */
+    protected void initializeServiceManager() throws Exception
+    {
+        final ServiceManager parent = (ServiceManager) get( m_rootContext, SERVICE_MANAGER, null );
+        final DefaultServiceManager manager = new DefaultServiceManager( parent );
 
-        m_manager = manager;
+        /**
+         * We assume that if there is a parent ServiceManager provided,
+         * there is a SourceResolver mounted there. And if there
+         * is none, then it is the true caller's intetion.
+         * However it is hard to imagine how that could be usefull
+         * except for testing purposes.
+         */
+        if ( parent == null )
+        {
+            manager.put( SourceResolver.ROLE, m_defaultSourceResolver );
+        }
+        
+        manager.put( LoggerManager.ROLE, m_loggerManager );
+        manager.put( Queue.ROLE, m_queue );
+        manager.put( MetaInfoManager.ROLE, m_metaInfoManager );
+        manager.put( PoolManager.ROLE, m_poolManager );
+        manager.put( InstrumentManager.ROLE, m_instrumentManager );
 
-        m_childContext.put( ContextManagerConstants.SERVICE_MANAGER, m_manager );
+        manager.makeReadOnly();
+    
+        m_containerManagerContext.put( SERVICE_MANAGER, manager );
     }
 
     /**
@@ -668,8 +738,7 @@
         Source src = null;
         try
         {
-            resolver = (SourceResolver) m_manager.lookup( SourceResolver.ROLE );
-            src = resolver.resolveURI( configUri );
+            src = m_defaultSourceResolver.resolveURI( configUri );
             if ( configBuilder == null )
             {
                 configBuilder = new DefaultConfigurationBuilder();
@@ -685,12 +754,7 @@
         }
         finally
         {
-            if ( null != resolver )
-            {
-                resolver.release( src );
-            }
-
-            m_manager.release( resolver );
+            m_defaultSourceResolver.release( src );
         }
     }
 
@@ -747,7 +811,7 @@
         {
             // Try copying an already existing logger manager from the override context.
 
-            m_childContext.put( LoggerManager.ROLE, m_rootContext.get( LoggerManager.ROLE ) );
+            m_loggerManager = (LoggerManager) m_rootContext.get( LoggerManager.ROLE );
         }
         catch ( ContextException ce )
         {
@@ -788,7 +852,7 @@
 
             assumeOwnership( logManager );
 
-            m_childContext.put( LoggerManager.ROLE, logManager );
+            m_loggerManager = logManager;
         }
 
         // Since we now have a LoggerManager, we can update the this.logger field
@@ -798,9 +862,11 @@
         {
             getLogger().debug( "Switching to default Logger provided by LoggerManager." );
 
-            final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
-            m_logger = loggerManager.getDefaultLogger();
+            m_logger = m_loggerManager.getDefaultLogger();
         }
+
+        // pass our own logger to the ContainerManager
+        m_containerManagerContext.put( LOGGER, m_logger );
     }
 
     /**
@@ -819,7 +885,7 @@
         {
             // Try copying an already existing instrument manager from the override context.
 
-            m_rootContext.get( InstrumentManager.ROLE );
+            m_instrumentManager = (InstrumentManager) m_rootContext.get( InstrumentManager.ROLE );
         }
         catch ( ContextException ce )
         {
@@ -832,11 +898,8 @@
                 instrumentConfig = EMPTY_CONFIG;
             }
 
-            // Get the context Logger Manager
-            final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
-
             // Get the logger for the instrument manager
-            final Logger imLogger = loggerManager.getLoggerForCategory(
+            final Logger imLogger = m_loggerManager.getLoggerForCategory(
                 instrumentConfig.getAttribute( "logger", "system.instrument" ) );
 
             // Set up the Instrument Manager
@@ -847,7 +910,7 @@
 
             assumeOwnership( instrumentManager );
 
-            m_childContext.put( InstrumentManager.ROLE, instrumentManager );
+            m_instrumentManager = instrumentManager;
         }
     }
 
diff -ru avalon-excalibur.0/fortress/src/test/org/apache/avalon/fortress/util/test/ContextManagerTestCase.java avalon-excalibur/fortress/src/test/org/apache/avalon/fortress/util/test/ContextManagerTestCase.java
--- avalon-excalibur.0/fortress/src/test/org/apache/avalon/fortress/util/test/ContextManagerTestCase.java       2003-05-15 18:19:56.000000000 +0400
+++ avalon-excalibur/fortress/src/test/org/apache/avalon/fortress/util/test/ContextManagerTestCase.java 2003-05-28 14:47:38.000000000 +0400
@@ -50,10 +50,13 @@
 package org.apache.avalon.fortress.util.test;
 
 import junit.framework.TestCase;
+import org.apache.avalon.fortress.ContainerManagerConstants;
 import org.apache.avalon.fortress.util.ContextManager;
 import org.apache.avalon.fortress.util.FortressConfig;
 import org.apache.avalon.framework.logger.NullLogger;
 import org.apache.avalon.framework.container.ContainerUtil;
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.excalibur.instrument.manager.DefaultInstrumentManager;
 import org.apache.excalibur.instrument.InstrumentManager;
 
@@ -63,7 +66,7 @@
  * @author <a href="bloritsch.at.apache.org">Berin Loritsch</a>
  * @version CVS $ Revision: 1.1 $
  */
-public class ContextManagerTestCase extends TestCase
+public class ContextManagerTestCase extends TestCase implements ContainerManagerConstants
 {
     private ContextManager m_manager;
     private InstrumentManager m_instrManager;
@@ -91,9 +94,14 @@
     public void testContextManager() throws Exception
     {
         assertNotNull( m_manager.getChildContext() );
-        assertNotNull( m_manager.getContainerManagerContext() );
-        assertNotNull( m_manager.getContainerManagerContext().get(InstrumentManager.ROLE));
-        assertSame( m_instrManager, m_manager.getContainerManagerContext().get( InstrumentManager.ROLE ) );
+        final Context managerContext = m_manager.getContainerManagerContext();
+        assertNotNull( managerContext );
+        final ServiceManager serviceManager = (ServiceManager) managerContext.get(SERVICE_MANAGER);
+        assertNotNull( serviceManager );
+        final InstrumentManager instrumentManager = 
+            (InstrumentManager) serviceManager.lookup( InstrumentManager.ROLE );
+        assertNotNull( instrumentManager);
+        assertSame( m_instrManager, instrumentManager );
     }
 
     public void tearDown()


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


[Patch] #11

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Berin!

It great so much of my patches has been applied.

I'm particularly glad Patch #8 has made it through
and that you have even managed to make it work for store!

Cheers to you and us :)

AT> .. Now I'm proposing to ... return to the original code
BL> :)  I guess I'm smarter than I thought.  Although, humility just went
BL> out the window with that comment ;P

:) I've been always putting my hat down at you!
Especially when I managed to get a couple year old pdf of
"Developing With Apache Avalon", printed it out and kept reading
for a couple of days (it turned out to be a bit outdated version,
but that was okay). So, thank you, Berin! :-))

B> Patch #10 needs to be reimplemented.
Will do. It will be called Patch #10.1 then.
Is it okay tomorrow?

Now, about the current Patch (#11):

1) ========================

BL> Interestingly enough my thoughts on this was that if a container
BL> wanted to define its own SourceResolver, it would create its own to
BL> override what was passed in.

Okay, okay! You have persuaded me, it's great to have a default one :)
However, _if_ the invoker has supplied a ServiceManager, then we may
assume that _those_ service manager already contains a SourceResolver,
probably cofigured differently.

Hmm.. can ContextManager be used in a _nested_ container?
Not likely, but theoretically possible.

Hence, this patch. Do you like what is in the patch on this subject?

2) =======================

AT> LoggerManager, PoolManager, InstrumentManager, MetaInfoManager
AT> LifecycleExtensionsManager, Queue are passed to the Container
AT> twice: via contextualize() and via service()

BL> This duplication originated from having them *originally* passed in as
BL> context entries.  Later, after looking at what these things really were,
BL> we determined that we were using a Context to access services.  We
BL> should go the other way and make them only available via the service
BL> mechanism.

I understand they are service because they have an interface and
a ROLE in it? But we never really release them -- is not that an
argument for accessing them via Context?

And after all they are quite different from user services - these
are system entities.

If they are available via ServiceManager someone may configure a
component implementing a PoolManager or a Queue interface or a
MetaInfoManager in the normal .xconf file and have nested containers
use that.

But should these things really be configured like that?
I do not mean this is a security violation but rather that
these things are so deep internal to system things ( like Queue )
that it looks a bit of order to configure them where normal
user components are configured.

So, I personally would have been more comfortable with accessing
them from the Context. Mainly because we never release them.
ServiceManager context contract is just to "heavy" in concept
for such a simple thing as "take what I give you once and live on it".

Is there any use to discussion this topic?

The patch supplied in this mail goes the ServiceManager
way and removes the duplicated entities from m_childContext.

3) ===============================
This patch also hides *CONFIGURAION and *CONFIGURATION_URI
from the container implementation.

4) ===============================
I have also updated the main section of the
inline documentation on ContextManager a bit.
The inline sections on separate methods still
are outdated sometimes - but I think this is
bearable at them moment.

diff -ru src.orig/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java
--- src.orig/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java  2003-05-28 10:20:10.000000000 +0400
+++ src/java/org/apache/avalon/fortress/impl/DefaultContainerManager.java       2003-05-28 12:33:30.000000000 +0400
@@ -205,7 +205,7 @@
             ContainerUtil.enableLogging( instance, m_logger );
             ContainerUtil.contextualize( instance, implContext );
 
-            final ServiceManager serviceManager = createServiceManager( implContext );
+            final ServiceManager serviceManager = createServiceManager( managerContext );
 
             ContainerUtil.service( instance, serviceManager );
 
diff -ru src.orig/java/org/apache/avalon/fortress/util/ContextManager.java src/java/org/apache/avalon/fortress/util/ContextManager.java
--- src.orig/java/org/apache/avalon/fortress/util/ContextManager.java   2003-05-28 10:20:26.000000000 +0400
+++ src/java/org/apache/avalon/fortress/util/ContextManager.java        2003-05-28 12:45:06.000000000 +0400
@@ -103,20 +103,16 @@
  * get an instance of the Context, it is made read-only and returned.  No
  * further operations will be possible on it.</p>
  *
- * <p>You can get two different contexts from the ContextManager: the child
- * context and the impl manager context. The former contains all
- * managers, such as the pool manager etc. necessary for a child impl to
- * create additional child containers. The impl manager context contains
- * all of the child context, but also initialization parameters for the
- * impl, such as a Configuration object, a ComponentLocator, etc., that
- * the impl wants, but does not want to pass on to its children.</p>
+ * <p>You can get two different contexts from the ContextManager: 
+ * the container context (m_childContext) 
+ * and container the manager context (m_contaimerManagerContext).
  *
- * <p>You would typically use the impl manager context to initialize
- * the impl manager, and let it pass the child context on to the
- * impl.</p>
+ * <p>The container manager context is used to provide the container manager
+ * with all the data needed to initialize the container.</p>
+ * <p>The container context is passed directly to the container.</p>
  *
- * <p>The ContextManager will sometimes create new components, such as a
- * component manager, a pool manager, etc. It will manage these components
+ * <p>The ContextManager will sometimes create new components, such as
+ * a service manager, a pool manager, etc. It will manage these components
  * and dispose of them properly when it itself is disposed .</p>
  *
  * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
@@ -163,7 +159,6 @@
      */
     private Logger m_logger;
     private final Logger m_primordialLogger;
-    private ServiceManager m_manager;
 
     /**
      * The components that are "owned" by this context and should
@@ -237,6 +232,7 @@
      */
     public void initialize() throws Exception
     {
+        initializeDefaultSourceResolver();
         initializeServiceManager();
         initializeLoggerManager();
         initializeMetaInfoManager();
@@ -248,6 +244,8 @@
 
         m_childContext.makeReadOnly();
         m_containerManagerContext.makeReadOnly();
+
+        m_defaultSourceResolver = null;
     }
 
     /**
@@ -295,6 +293,16 @@
             getLogger().debug( "Could not copy Context parameters.  This may be Ok depending on "
                 + "other configured context values." );
         }
+       
+        // hide from the container implementation what it does not need
+        m_childContext.put( CONFIGURATION, null );
+        m_childContext.put( CONFIGURATION_URI, null );
+        m_childContext.put( ROLE_MANAGER_CONFIGURATION, null );
+        m_childContext.put( ROLE_MANAGER_CONFIGURATION_URI, null );
+        m_childContext.put( LOGGER_MANAGER_CONFIGURATION, null );
+        m_childContext.put( LOGGER_MANAGER_CONFIGURATION_URI, null );
+        m_childContext.put( INSTRUMENT_MANAGER_CONFIGURATION, null );
+        m_childContext.put( INSTRUMENT_MANAGER_CONFIGURATION_URI, null );
     }
 
     /**
@@ -392,7 +400,7 @@
     {
         try
         {
-            m_rootContext.get( Queue.ROLE );
+            copyEntry( Queue.ROLE );
             return;
         }
         catch ( ContextException ce )
@@ -400,7 +408,7 @@
         }
 
         // No CommandQueue specified, create a default one
-        m_childContext.put( Queue.ROLE, createCommandSink() );
+        m_containerManagerContext.put( Queue.ROLE, createCommandSink() );
     }
 
     /**
@@ -418,7 +426,7 @@
         assumeOwnership( tm );
 
         // Get the context Logger Manager
-        final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+        final LoggerManager loggerManager = (LoggerManager) m_containerManagerContext.get( LoggerManager.ROLE );
 
         // Get the logger for the thread manager
         final Logger tmLogger = loggerManager.getLoggerForCategory( "system.threadmgr" );
@@ -487,16 +495,16 @@
     {
         try
         {
-            m_rootContext.get( PoolManager.ROLE );
+            copyEntry( PoolManager.ROLE );
             return;
         }
         catch ( ContextException ce )
         {
         }
 
-        final PoolManager pm = new DefaultPoolManager( (Sink) m_childContext.get( Queue.ROLE ) );
+        final PoolManager pm = new DefaultPoolManager( (Sink) m_containerManagerContext.get( Queue.ROLE ) );
         assumeOwnership( pm );
-        m_childContext.put( PoolManager.ROLE, pm );
+        m_containerManagerContext.put( PoolManager.ROLE, pm );
     }
 
     /**
@@ -535,7 +543,7 @@
         }
 
         // Get the context Logger Manager
-        final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+        final LoggerManager loggerManager = (LoggerManager) m_containerManagerContext.get( LoggerManager.ROLE );
 
         // Lookup the context class loader
         final ClassLoader classLoader = (ClassLoader) m_rootContext.get( ClassLoader.class.getName() );
@@ -560,7 +568,17 @@
 
     protected void initializeMetaInfoManager() throws Exception
     {
-        final boolean mmSupplied = entryPresent( m_rootContext, MetaInfoManager.ROLE );
+        boolean mmSupplied = false;
+        try
+        {
+            copyEntry( MetaInfoManager.ROLE );
+            mmSupplied = true;
+        }
+        catch( ContextException ce )
+        {
+            // okay, we will create one
+        }
+
         RoleManager roleManager = obtainRoleManager();
         final boolean rmSupplied = roleManager != null;
 
@@ -575,7 +593,7 @@
         }
         else
         {
-            final LoggerManager loggerManager = (LoggerManager)m_childContext.get( LoggerManager.ROLE );
+            final LoggerManager loggerManager = (LoggerManager)m_containerManagerContext.get( LoggerManager.ROLE );
             final ClassLoader classLoader = (ClassLoader)m_rootContext.get( ClassLoader.class.getName() );
 
             if ( ! rmSupplied )
@@ -592,21 +610,25 @@
             metaManager.enableLogging( loggerManager.getLoggerForCategory("system.meta") );
             metaManager.initialize();
             assumeOwnership( metaManager );
-            m_childContext.put( MetaInfoManager.ROLE, metaManager );
+            m_containerManagerContext.put( MetaInfoManager.ROLE, metaManager );
         }
     }
 
     /**
-     * Get a reference to the initial ComponentLocator used by the
-     * ContainerManager to hold the Components used for parsing the config
-     * files and setting up the environment.
-     *
-     * @throws Exception when there is an error.
+     *  Source resolver used to read-in the configurations.
+     *  and provided as a default source resolver if the
+     *  user has not supplied a ServiceManager.
+     *  (Otherwise it or an overriding sourceresolver
+     *  is probably available from that.)
      */
-    protected void initializeServiceManager() throws Exception
+    protected SourceResolver m_defaultSourceResolver;
+
+    /**
+     *  Initialize the default SrouceResolver.
+     */
+    protected void initializeDefaultSourceResolver() throws Exception
     {
-        final ServiceManager parent = (ServiceManager) get( m_rootContext, SERVICE_MANAGER, null );
-        final DefaultServiceManager manager = new DefaultServiceManager( parent );
+        final DefaultServiceManager manager = new DefaultServiceManager();
         final DefaultServiceSelector selector = new DefaultServiceSelector();
         final URLSourceFactory file = new URLSourceFactory();
         file.enableLogging( getLogger() );
@@ -623,15 +645,32 @@
         ContainerUtil.service( resolver, manager );
         ContainerUtil.parameterize( resolver, new Parameters() );
 
-        manager.put( SourceResolver.ROLE, resolver );
-
-        manager.makeReadOnly();
-
-        assumeOwnership( manager );
-
-        m_manager = manager;
-
-        m_childContext.put( ContextManagerConstants.SERVICE_MANAGER, m_manager );
+        m_defaultSourceResolver = resolver;
+    }
+    /**
+     * Get a reference to the initial ComponentLocator used by the
+     * ContainerManager to hold the Components used for parsing the config
+     * files and setting up the environment.
+     *
+     * @throws Exception when there is an error.
+     */
+    protected void initializeServiceManager() throws Exception
+    {
+        try
+        {
+             copyEntry( SERVICE_MANAGER );
+        }
+        catch( ContextException ce )
+        {
+            final DefaultServiceManager manager = new DefaultServiceManager();
+        
+            // provide a default source resolver good in many situations
+            manager.put( SourceResolver.ROLE, m_defaultSourceResolver );
+        
+            manager.makeReadOnly();
+        
+            m_containerManagerContext.put( ContextManagerConstants.SERVICE_MANAGER, manager );
+        }
     }
 
     /**
@@ -668,8 +707,7 @@
         Source src = null;
         try
         {
-            resolver = (SourceResolver) m_manager.lookup( SourceResolver.ROLE );
-            src = resolver.resolveURI( configUri );
+            src = m_defaultSourceResolver.resolveURI( configUri );
             if ( configBuilder == null )
             {
                 configBuilder = new DefaultConfigurationBuilder();
@@ -685,12 +723,7 @@
         }
         finally
         {
-            if ( null != resolver )
-            {
-                resolver.release( src );
-            }
-
-            m_manager.release( resolver );
+            m_defaultSourceResolver.release( src );
         }
     }
 
@@ -747,7 +780,7 @@
         {
             // Try copying an already existing logger manager from the override context.
 
-            m_childContext.put( LoggerManager.ROLE, m_rootContext.get( LoggerManager.ROLE ) );
+            copyEntry( LoggerManager.ROLE );
         }
         catch ( ContextException ce )
         {
@@ -788,7 +821,7 @@
 
             assumeOwnership( logManager );
 
-            m_childContext.put( LoggerManager.ROLE, logManager );
+            m_containerManagerContext.put( LoggerManager.ROLE, logManager );
         }
 
         // Since we now have a LoggerManager, we can update the this.logger field
@@ -798,7 +831,7 @@
         {
             getLogger().debug( "Switching to default Logger provided by LoggerManager." );
 
-            final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+            final LoggerManager loggerManager = (LoggerManager) m_containerManagerContext.get( LoggerManager.ROLE );
             m_logger = loggerManager.getDefaultLogger();
         }
     }
@@ -819,7 +852,7 @@
         {
             // Try copying an already existing instrument manager from the override context.
 
-            m_rootContext.get( InstrumentManager.ROLE );
+            copyEntry( InstrumentManager.ROLE );
         }
         catch ( ContextException ce )
         {
@@ -833,7 +866,7 @@
             }
 
             // Get the context Logger Manager
-            final LoggerManager loggerManager = (LoggerManager) m_childContext.get( LoggerManager.ROLE );
+            final LoggerManager loggerManager = (LoggerManager) m_containerManagerContext.get( LoggerManager.ROLE );
 
             // Get the logger for the instrument manager
             final Logger imLogger = loggerManager.getLoggerForCategory(
@@ -847,7 +880,7 @@
 
             assumeOwnership( instrumentManager );
 
-            m_childContext.put( InstrumentManager.ROLE, instrumentManager );
+            m_containerManagerContext.put( InstrumentManager.ROLE, instrumentManager );
         }
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


[Patch] #10.1 Part I

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Berin!

This is the part of Patch #10 that may be applied right away.
It adds makeReadOnly() and writeableCopy() to
util/LifecycleExtensionManager - this will used by Part II

--- LifecycleExtensionManager.orig      2003-04-22 16:37:10.000000000 +0400
+++ LifecycleExtensionManager.java      2003-05-29 12:24:19.000000000 +0400
@@ -89,6 +89,24 @@
     private final CachedArrayList m_accessorExtensions = new CachedArrayList();
     private final CachedArrayList m_creatorExtensions = new CachedArrayList();
 
+    private boolean m_readOnly = false;
+
+    public void makeReadOnly()
+    {
+        m_readOnly = true;
+    }
+
+    /**
+     * Create a copy; it will be writeable even if the original was not.
+     */
+    public LifecycleExtensionManager writeableCopy()
+    {
+        final LifecycleExtensionManager copy = new LifecycleExtensionManager();
+        copy.m_accessorExtensions.copyFrom( m_accessorExtensions );
+        copy.m_creatorExtensions.copyFrom( m_creatorExtensions );
+        return copy;
+    }
+    
     /**
      * <code>executeAccessExtensions</code> method, executes all access
      * level extensions on the given component.
@@ -168,6 +186,7 @@
      */
     public void addAccessorExtension( final Accessor extension )
     {
+        checkWriteable();
         m_accessorExtensions.add( extension );
     }
 
@@ -178,6 +197,7 @@
      */
     public void addCreatorExtension( final Creator extension )
     {
+        checkWriteable();
         m_creatorExtensions.add( extension );
     }
 
@@ -189,6 +209,7 @@
      */
     public void insertAccessorExtension( final int position, final Accessor extension )
     {
+        checkWriteable();
         m_accessorExtensions.insert( position, extension );
     }
 
@@ -200,6 +221,7 @@
      */
     public void insertCreatorExtension( final int position, final Creator extension )
     {
+        checkWriteable();
         m_creatorExtensions.insert( position, extension );
     }
 
@@ -211,6 +233,7 @@
      */
     public Accessor removeAccessorExtension( final int position )
     {
+        checkWriteable();
         return (Accessor) m_accessorExtensions.remove( position );
     }
 
@@ -222,6 +245,7 @@
      */
     public Creator removeCreatorExtension( final int position )
     {
+        checkWriteable();
         return (Creator) m_creatorExtensions.remove( position );
     }
 
@@ -292,6 +316,7 @@
      */
     public void clearAccessorExtensions()
     {
+        checkWriteable();
         m_accessorExtensions.clear();
     }
 
@@ -300,6 +325,7 @@
      */
     public void clearCreatorExtensions()
     {
+        checkWriteable();
         m_creatorExtensions.clear();
     }
 
@@ -367,6 +393,22 @@
     }
 
     /**
+     * Utility method to check if LifecycleExtensionsManager
+     * is writeable and if not throw exception.
+     *
+     * @throws IllegalStateException if context is read only
+     */
+    protected final void checkWriteable()
+        throws IllegalStateException
+    {
+        if( m_readOnly )
+        {
+            final String message =
+                "LifecycleExtensionsManager is read only and can not be modified";
+            throw new IllegalStateException( message );
+        }
+    }
+    /**
      * <code>CachedArrayList</code> class.
      *
      * <p>
@@ -404,6 +446,16 @@
         private Object[] m_cache = EMPTY_ARRAY;
 
         /**
+         *  Become a copy of another CachedArrayList.
+         */
+        public void copyFrom( final CachedArrayList original )
+        {
+            m_proxy.clear();
+            m_proxy.addAll( original.m_proxy );
+            m_cache = original.m_cache; // it won't mutate anyway :-)
+        }
+
+        /**
          * Add an object to the list
          *
          * @param object an <code>Object</code> value
@@ -440,13 +492,14 @@
         }
 
         /**
-         * Obtain an iterator
+         * Obtain an iterator. This iterator is read-only.
          *
          * @return an <code>Iterator</code> value
          */
         public Iterator iterator()
         {
-            return m_proxy.iterator();
+            final Iterator base = m_proxy.iterator();
+            return new UnmodifiableIterator( base );
         }
 
         /**
@@ -502,4 +555,26 @@
             return m_cache;
         }
     }
+
+    private static class UnmodifiableIterator implements Iterator
+    {
+        private final Iterator m_base;
+        UnmodifiableIterator( final Iterator base )
+        {
+            if ( base == null ) throw new NullPointerException( "base can not be null" );
+            m_base = base;
+        }
+        public boolean hasNext()
+        {
+            return m_base.hasNext();
+        }
+        public Object next()
+        {
+            return m_base.next();
+        }
+        public void remove()
+        {
+            throw new IllegalStateException( "Unmodifiable iterator" );
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Patch] #7

Posted by Berin Loritsch <bl...@apache.org>.
Anton Tagunov wrote:
> Hello Berin!
> 
> Yes, I do have a pair of patches being prepared, #8 and #9, they
> will come soon.
> 
> Meanwhile I have found that fortress-tools.jar
> needs MetaInfoEntry.class and all the classes it wants.
> 
> Let's call it Patch #7


I applied this a bit differently.  I ensured all the class names were
used as strings--but the function did have to be included, so I included
that class name.


-- 
"You know the world is going crazy when the best
rapper is a white guy, the best golfer is a black guy,
The Swiss hold the America's Cup, France is
accusing the US of arrogance, and Germany doesn't want
to go to war. And the 3 most powerful men in America
are named 'Bush', 'Dick', and 'Colon' (sic)".

-----Chris Rock


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


[Patch] #7

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Berin!

Yes, I do have a pair of patches being prepared, #8 and #9, they
will come soon.

Meanwhile I have found that fortress-tools.jar
needs MetaInfoEntry.class and all the classes it wants.

Let's call it Patch #7

- Anton

--- build.orig  2003-05-23 21:00:00.000000000 +0400
+++ build.xml   2003-05-25 14:37:48.000000000 +0400
@@ -260,6 +260,13 @@
             <fileset dir="${build.classes}">
                 <include name="**/util/Service*"/>
                 <include name="**/role/Service*"/>
+                <include name="**/MetaInfoEntry*"/>
+                <include name="**/handler/FactoryComponentHandler*"/>
+                <include name="**/handler/PoolableComponentHandler*"/>
+                <include name="**/handler/PerThreadComponentHandler*"/>
+                <include name="**/handler/ThreadSafeComponentHandler*"/>
+                <include name="**/handler/AbstractComponentHandler*"/>
+                <include name="**/handler/ComponentHandler*"/>
                 <include name="**/dag/*"/>
             </fileset>
         </jar>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [VOTE] Is Fortress Good Enough (tm) (was Re: Patch #14 -- providing one more extension point)

Posted by Leo Simons <le...@apache.org>.
Berin Loritsch wrote:
> All, I think we are reaching the point where we are delaying Fortress
> without resolving bugs.  While all the patches are generally good, and
> we would like to make it into Fortress, do we think that Fortress is
> Good Enough(TM) to release now?

+1

I think it is a good idea to release early, release often. It is okay if 
a first release contains a bug or two.

- Leo



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Fortress] Proposed algorithm to fix shutdown order when using a roles file. (Was [VOTE] Is Fortress Good Enough )

Posted by Leif Mortenson <le...@tanukisoftware.com>.
Berin Loritsch wrote:

> So what you are saying is to build the dependency list at run time? 

Yes, That is the only way I could think of other than using that 
counting method
we had implemented for the ECM.

By building up a dependency list at runtime, it will allow for the 
calculation
of an optimal shutdown order that is not dependent on whether or not the
user code correctly releases components.

If we called the Vertex.resolveOrder() method whenever a new
dependency was discovered, this would even make it possible to
throw an exception when a circular dependency is encountered.
Currently, Fortress will look through the circular dependency list,
recursively trying to initialize the components until you finally get an
OutOfMemoryException.  I found out about that the hard way.  This
is only a problem if the roles file is used, If meta data is used, then
circular dependencies are correctly detected.

> I like that idea, but we should log any dependency that is found at run
> time so that we can account for missed dependencies even if the user is
> using meta-info. 

Great, I am glad you like it.
The question then is: when should this get fixed?  I also want to get
Fortress out the door.  But the majority of our users are still using roles
files so I think it would be worth fixing the shutdown problems before
the release.   Unfortunately, I have a long list of deadlines next week, so
I can't promise to be the one to implement this.  If you know where to
to implement it, I don't think it should take all that much code to get this
implemented though.  Without more time digging though, I am not yet sure
where exactly in the code the ThreadLocal code should go.

Cheers,
Leif



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Fortress] Proposed algorithm to fix shutdown order when using a roles file. (Was [VOTE] Is Fortress Good Enough )

Posted by Berin Loritsch <bl...@apache.org>.
Leif Mortenson wrote:
> Now that the shutdown ordering is working correctly when using meta data,
> I have been quite happy with it.  At first I was a little worried about 
> the idea
> of using "meta" tags that were specific to Avalon.  But after just a couple
> days of using them, I am in love with them.  Kudos to whomever first came
> up with the idea.

That would be Peter D. for applying them here in Avalon.  The concept
came from the XDoclet folks.

> I personally will be using Meta data without any plans to go back.  But 
> I am
> a little worried about the fact that Fortress currently is ignoring
> dependencies completely when shutting down applications which are
> using a roles file and no meta data.   The rats nest of problems this was
> causing with my application is what forced me to start looking at using
> meta tags in the first place.

It really can't be solved using the RoleManager approach.

> In my opinion, Fortress, using a roles file is just plain broken in its
> shutdown cycle.  What is the plan long term.   It is really not very 
> difficult
> to migrate your components over to support meta data once you know
> how to do it, so Fortress on the whole seems to be quite ready for a
> release, but we should probably be warning users that the use of roles
> files is not fully supported in the shutdown cycle.  Coming from the ECM
> where this just worked.  It took me a while to track down the problems I
> was having when my application was shutting down because I was going
> on faith that Fortress was honoring its contracts.

ECM used a reference counting scheme, so if you did not release every
component you looked up, then ECM was broken.

> To fix this, I was thinking of doing the following.  See what you think:
> 

<snip/>

> 
> By following the above algorithm, it should be possible to build up a very
> accurate list of dependencies as the application runs.

So what you are saying is to build the dependency list at run time?


I like that idea, but we should log any dependency that is found at run
time so that we can account for missed dependencies even if the user is
using meta-info.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


[Fortress] Proposed algorithm to fix shutdown order when using a roles file. (Was [VOTE] Is Fortress Good Enough )

Posted by Leif Mortenson <le...@tanukisoftware.com>.
Now that the shutdown ordering is working correctly when using meta data,
I have been quite happy with it.  At first I was a little worried about 
the idea
of using "meta" tags that were specific to Avalon.  But after just a couple
days of using them, I am in love with them.  Kudos to whomever first came
up with the idea.
The ROLE/hint method of looking up components without directly using a
selector has also ben working great.

I personally will be using Meta data without any plans to go back.  But I am
a little worried about the fact that Fortress currently is ignoring
dependencies completely when shutting down applications which are
using a roles file and no meta data.   The rats nest of problems this was
causing with my application is what forced me to start looking at using
meta tags in the first place.

In my opinion, Fortress, using a roles file is just plain broken in its
shutdown cycle.  What is the plan long term.   It is really not very 
difficult
to migrate your components over to support meta data once you know
how to do it, so Fortress on the whole seems to be quite ready for a
release, but we should probably be warning users that the use of roles
files is not fully supported in the shutdown cycle.  Coming from the ECM
where this just worked.  It took me a while to track down the problems I
was having when my application was shutting down because I was going
on faith that Fortress was honoring its contracts.


To fix this, I was thinking of doing the following.  See what you think:

Whenever a component is about to be initialized, store a reference to
it in a ThreadLocal variable.  When the initialization completes, remove the
reference.

Then whenever a component is looked up, we would check to see if
the above ThreadLocal has a component reference.  If so, then we
know that is the component which "depends" on the component being
looked up.   At this point we can verify that the meta information for the
first component contains a reference to the second component in its
dependency list.  If not, add it.

If the looked up component has not yet been initialized, then it will
store any existing reference in the ThreadLocal to the first component
into a local variable.  The component would then repeat the same
cycle as above.  When initialization is complete, the stored reference
to the first component will be placed back into the thread local before
continuing.

Note that the only time that a reference to a component will be found in
the ThreadLocal  will be if the component is being looked up during
initialization.   If a component looks up another component after it has
been initialized, then the ThreadLocal will be empty.

By following the above algorithm, it should be possible to build up a very
accurate list of dependencies as the application runs.

Currently the shutdown order is being computed before the first
component ever initialized.  But if it was to be recalculated just before
starting the shutdown cycle then the dependencies resolved during
execution could be taken into account and the components would always
be shutdown in the correct order.

Note that because the above algorithm used ThreadLocals, no
synchronization is required, so this should be able to be implemented
very efficiently.

For example:
---
private static ThreadLocal m_initializingComponent = new ThreadLocal();
public void initializeComponent( ... )
{
Object parentComponent = m_initializingComponent.get();
try
{
m_initializingComponent.set( thisComponent );
thisComponent.initialize(...);
}
finally
{
m_initializingComponent.set( parentComponent );
}
}
---
Then when looking up a component
---
public Object lookup( String role )
{
Object thisComponent = lookupInner( role );
Object parentComponent = m_initializingComponent.get();
if ( parentComponent != null )
{
parentComponent.addDependency( thisComponent );
}
return thisComponent
}
---

If the above didn't make any sense, let me know and I'll try to explain it
a little better :-)  Its late here and I forced myself to go out and have a
few beers for the first time in a month :-)  Need to do that a little more.

Thoughts?

Cheers,
Leif



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


RE: [VOTE] Is Fortress Good Enough (tm) (was Re: Patch #14 -- providing one more extension point)

Posted by Leo Sutic <le...@inspireinfrastructure.com>.
+1

No point in waiting for perfection, and releasing it to a wider
audience might actually accellerate the movement toward perfection.

/LS


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [VOTE] Is Fortress Good Enough (tm) (was Re: Patch #14 -- providing one more extension point)

Posted by Peter Royal <pr...@apache.org>.
On Thursday, May 29, 2003, at 04:01 PM, Berin Loritsch wrote:
> All, I think we are reaching the point where we are delaying Fortress
> without resolving bugs.  While all the patches are generally good, and
> we would like to make it into Fortress, do we think that Fortress is
> Good Enough(TM) to release now?

+1
-pete


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


[VOTE] Is Fortress Good Enough (tm) (was Re: Patch #14 -- providing one more extension point)

Posted by Berin Loritsch <bl...@apache.org>.
Anton Tagunov wrote:
> Hello Berin!
> 
> BL> If we don't get any more patches in 24 hours, I will put it up for vote again.
> 
> Plz don't cout this one, it's quite cosmetic, but something that I
> personally will probably use in the future. Yes, and Shash seems to
> have reported that they have been quite active with producing
> additional lifecycle interfaces, so this may really find people who
> will use it, I think.
> 

As this does not refer to a bug, I think I would like to focus on a
Fortress 1.0 release.  We can apply this and whatever other patches
for the next release (which can be soon afterwards if we want).

All, I think we are reaching the point where we are delaying Fortress
without resolving bugs.  While all the patches are generally good, and
we would like to make it into Fortress, do we think that Fortress is
Good Enough(TM) to release now?


Place your votes, please.

+1 from me.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Patch #14 -- providing one more extension point

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Berin!

BL> If we don't get any more patches in 24 hours, I will put it up for vote again.

Plz don't cout this one, it's quite cosmetic, but something that I
personally will probably use in the future. Yes, and Shash seems to
have reported that they have been quite active with producing
additional lifecycle interfaces, so this may really find people who
will use it, I think.

--- AbstractContainer.orig      2003-05-29 22:09:54.000000000 +0400
+++ AbstractContainer.java      2003-05-29 23:28:48.000000000 +0400
@@ -285,18 +285,8 @@
             extLogger.debug( message );
         }
 
-        /**
-         * We do need a new InstrumentableCreator, as we want strictly our
-         * m_instrumentManager to be engaged. We assume there is no
-         * InstrumentableCreator in the LifecycleExtensionManager passed to us
-         * already. If there is one this is probably a bug. Not testing this currently,
-         * although might test this in the future in order to
-         * throw something like an IllegalArgumentException.
-         */
-        m_extManager.addCreatorExtension( new InstrumentableCreator( m_instrumentManager ) );
-
-        // just to be on the safe side
-        m_extManager.makeReadOnly();
+        // m_extManager will intentionally remain writeable until
+        // made read-only in initialize()
     }
 
     /**
@@ -615,6 +605,12 @@
     public void initialize()
             throws CompositeException, Exception
     {
+        // let derived containers add their own lifecycle extensions
+        provideLifecycleExtensions( m_extManager );
+
+        // make m_extManager read-only to be on the safe side
+        m_extManager.makeReadOnly();
+
         // go over all components
         final Iterator i = m_components.iterator();
         final BoundedFifoBuffer buffer = new BoundedFifoBuffer( Math.max( m_components.size(), 1 ) );
@@ -852,4 +848,33 @@
         /* the default implementation: just use the same as for container itself */
         return parent;
     }
+
+    /**
+     * Override his method to manage the set of lifecycle extensions.
+     * As the contract of managing lifecycle extensions has not solidified
+     * yet this method allowes you do anything with the set of extensions
+     * supplied by our manager (container manager or parent container):
+     * add and remove them as you like. Note however that
+     * InstrumentableCreatro should always be added as in this default
+     * implementation not to upset the Instrumentable and InstrumentManageable
+     * components we will create.
+     * This method is called from withing initialize().
+     * @param extManager a copy of the LifecycleExtensionManager provided by
+     *                   our manager (container manager or parent container)
+     *                   or a new empty one if none has been provided.
+     */
+    protected void provideLifecycleExtensions( final LifecycleExtensionManager extManager )
+            throws Exception
+    {
+        /** 
+         * AbstractContainer adds only one extension, the InstrumentableCreator.
+         * We do need a new InstrumentableCreator, as we want strictly our
+         * m_instrumentManager to be engaged. We assume there is no
+         * InstrumentableCreator in the LifecycleExtensionManager passed to us
+         * already. If there is one this is probably a bug. Not testing this currently,
+         * although might test this in the future in order to
+         * throw something like an IllegalArgumentException.
+         */
+        extManager.addCreatorExtension( new InstrumentableCreator( m_instrumentManager ) );
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Patch queue contents

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Berin!

BL> In the mean time, Anton, don't stop with bug fixes.  What else
BL> are you seeing?

Well, now except for the patches I have submitted, only two
things still continue to worry me:

1  LifecycleExtensions

1.1

   Tough issue:

   I'm a little bit uncomfortable with how the standard
   LifecycleExtensions are handled by the AbstractContainer.

   Currently there is only one such extension: InstrumentableCreator.

   Look into the code: the LifecycleExtensionManager if passed-in
   to the container is the only thing that is not read-only.

   Instead, we browse through it and if we do not find an
   InstrumentableCreator we add it there.

   We're modifying something that does not belong to us!

   What should we do?
   Maybe create a copy of the LifecycleExtensions manager?
   
   Add a makeReadOnly method to LifecycleExtensionsManager?

1.2

   The current implementation is that if we create a new
   LifecycleExtensions object internally inside the AbstractContainer
   we do not pass it to our children. In general, should we pass it
   to our children? If the invoker has supplied his extensions?
   If we have modified the supplied extensins list?
   If we have created our own?

   If we do want to pass it to our children then
   after we create a copy or a new LifecycleExtensManager
   inside a Container there still is no nice way to pass
   it to our children: the same we had with MetaInfoManager
   (see Patch #9 comments).

   Shall we wrap context passed to us vai contextualize()
   into our own context and put the new LifecycleExtensions
   there and pass _that_ context to our children?

   (Something I tried to avoid in Patch #9)

2
   I expect I will want to hide the CONFIGURATION and CONFIGURATION
   uri-s from the Continaer in ContextManager, something like
   
   m_childContext.put( CONFIGURATION, null )

   It's a very simple change, but I have just submitted a huge
   patch, so not to clatter the matters this is still pending.

   Or, the question I have asked before: maybe m_childContext
   shouldn't be a child of m_rootContext?

   Maybe it's better to copy what we need instead of hiding what
   we do not need?

   The price of question is whether the caller will be allowed
   to pass context entries unforseen when we write this code,
   custom context entries to his custom containers.

   If we cut m_childContext from m_rootContext users won't be
   able to do that.

   Or, alternatively we could have in ContextManager

   initializeContext()
   {
       Context customContext = m_rootContext.get( CUSTOM_CONTEXT );
       m_childContext = new DefaultContext( customContext );
       ...
   }

Okay, except for these two issues: LifecycleExtensions and context
entries in m_childContext, my patch queue is empty.

- Anton


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org