You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by mc...@apache.org on 2002/08/12 10:11:09 UTC
cvs commit: jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource AbstractExtension.java AbstractLifestyleHandler.java DefaultComponentManager.java DefaultManager.java DefaultResource.java DefaultServiceManager.java Extension.java LifecycleException.java LifecycleHelper.java LifestyleHandler.java ResourceException.java ResourceProvider.java ResourceRuntimeException.java Resources.properties SingletonLifestyleHandler.java TransientLifestyleHandler.java package.html
mcconnell 2002/08/12 01:11:09
Modified: assembly build.xml
assembly/demo/src/java/org/apache/excalibur/playground
DemoManager.java ExploitationManager.java
assembly/src/java/org/apache/excalibur/merlin/assembly
ContainerManager.java ProfileRegistry.java
assembly/src/java/org/apache/excalibur/merlin/container
StructuralExtension.java
Added: assembly/src/java/org/apache/excalibur/merlin/resource
AbstractExtension.java
AbstractLifestyleHandler.java
DefaultComponentManager.java DefaultManager.java
DefaultResource.java DefaultServiceManager.java
Extension.java LifecycleException.java
LifecycleHelper.java LifestyleHandler.java
ResourceException.java ResourceProvider.java
ResourceRuntimeException.java Resources.properties
SingletonLifestyleHandler.java
TransientLifestyleHandler.java package.html
Removed: assembly/src/java/org/apache/excalibur/merlin/assembly/resource
AbstractExtension.java DefaultComponentManager.java
DefaultManager.java DefaultResource.java
DefaultServiceManager.java Extension.java
LifecycleException.java LifecycleHelper.java
LifestyleHandler.java ResourceException.java
ResourceProvider.java ResourceRuntimeException.java
Resources.properties SingletonLifestyleHandler.java
package.html
Log:
Upgrading support for lifecycle and lifestyle management.
Revision Changes Path
1.40 +4 -4 jakarta-avalon-excalibur/assembly/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/build.xml,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- build.xml 12 Aug 2002 06:08:54 -0000 1.39
+++ build.xml 12 Aug 2002 08:11:08 -0000 1.40
@@ -295,10 +295,10 @@
</target>
<target name="patch">
- <replace dir="${src.dir}/java"
- token="ProfileDesignator"
- value="DefaultResource" >
- <include name="org/apache/excalibur/merlin/**/*.*"/>
+ <replace dir="demo"
+ token="org.apache.excalibur.merlin.assembly.resource"
+ value="org.apache.excalibur.merlin.resource" >
+ <include name="**/*.*"/>
</replace>
</target>
1.3 +2 -2 jakarta-avalon-excalibur/assembly/demo/src/java/org/apache/excalibur/playground/DemoManager.java
Index: DemoManager.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/demo/src/java/org/apache/excalibur/playground/DemoManager.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- DemoManager.java 2 Aug 2002 06:29:20 -0000 1.2
+++ DemoManager.java 12 Aug 2002 08:11:08 -0000 1.3
@@ -4,8 +4,8 @@
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.excalibur.merlin.assembly.resource.Extension;
-import org.apache.excalibur.merlin.assembly.resource.AbstractExtension;
+import org.apache.excalibur.merlin.resource.Extension;
+import org.apache.excalibur.merlin.resource.AbstractExtension;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Disposable;
1.5 +2 -2 jakarta-avalon-excalibur/assembly/demo/src/java/org/apache/excalibur/playground/ExploitationManager.java
Index: ExploitationManager.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/demo/src/java/org/apache/excalibur/playground/ExploitationManager.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- ExploitationManager.java 2 Aug 2002 06:29:20 -0000 1.4
+++ ExploitationManager.java 12 Aug 2002 08:11:08 -0000 1.5
@@ -4,8 +4,8 @@
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.excalibur.merlin.assembly.resource.Extension;
-import org.apache.excalibur.merlin.assembly.resource.AbstractExtension;
+import org.apache.excalibur.merlin.resource.Extension;
+import org.apache.excalibur.merlin.resource.AbstractExtension;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Disposable;
1.12 +25 -9 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly/ContainerManager.java
Index: ContainerManager.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly/ContainerManager.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- ContainerManager.java 12 Aug 2002 06:08:54 -0000 1.11
+++ ContainerManager.java 12 Aug 2002 08:11:08 -0000 1.12
@@ -34,16 +34,17 @@
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.excalibur.configuration.ConfigurationUtil;
-import org.apache.excalibur.merlin.assembly.resource.LifecycleHelper;
-import org.apache.excalibur.merlin.assembly.resource.ResourceProvider;
-import org.apache.excalibur.merlin.assembly.resource.ResourceException;
-import org.apache.excalibur.merlin.assembly.resource.DefaultResource;
-import org.apache.excalibur.merlin.assembly.resource.LifestyleHandler;
-import org.apache.excalibur.merlin.assembly.resource.SingletonLifestyleHandler;
-import org.apache.excalibur.merlin.model.ContainerDescriptor;
-import org.apache.excalibur.merlin.model.ClasspathDescriptor;
+import org.apache.excalibur.merlin.resource.ResourceException;
+import org.apache.excalibur.merlin.resource.DefaultResource;
import org.apache.excalibur.merlin.container.Container;
import org.apache.excalibur.merlin.container.DefaultContainer;
+import org.apache.excalibur.merlin.resource.LifestyleHandler;
+import org.apache.excalibur.merlin.resource.SingletonLifestyleHandler;
+import org.apache.excalibur.merlin.resource.TransientLifestyleHandler;
+import org.apache.excalibur.merlin.resource.LifecycleHelper;
+import org.apache.excalibur.merlin.resource.ResourceProvider;
+import org.apache.excalibur.merlin.model.ContainerDescriptor;
+import org.apache.excalibur.merlin.model.ClasspathDescriptor;
import org.apache.excalibur.merlin.model.LoggingDescriptor;
import org.apache.excalibur.merlin.model.builder.XMLContainerUtil;
import org.apache.excalibur.merlin.model.Category;
@@ -728,7 +729,7 @@
}
/**
- * Returns an existing or new resource using the supplied local profile and context.
+ * Returns a new or existing resource using the supplied local profile and context.
*
* @param profile the profile
* @param the deployment context
@@ -746,6 +747,21 @@
// ## assemble it before supplying it to the default resource instance. #
// ## #
// ######################################################################
+
+ String policy = profile.getType().getInfo().getAttribute("avalon:lifestyle", "transient" );
+ if( policy.equals( "transient" ) )
+ {
+ }
+ else if( policy.equalsIgnoreCase( "singleton" ) )
+ {
+ }
+ else if( policy.equalsIgnoreCase( "per-thread" ) )
+ {
+ }
+ else if( policy.equalsIgnoreCase( "pooled" ) )
+ {
+ }
+
SingletonLifestyleHandler handler =
new SingletonLifestyleHandler( this, m_provider, m_helper, profile, context );
1.11 +3 -17 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly/ProfileRegistry.java
Index: ProfileRegistry.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/assembly/ProfileRegistry.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- ProfileRegistry.java 12 Aug 2002 06:08:54 -0000 1.10
+++ ProfileRegistry.java 12 Aug 2002 08:11:08 -0000 1.11
@@ -32,10 +32,8 @@
import org.apache.excalibur.meta.info.Facility;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.Resource;
-import org.apache.excalibur.merlin.assembly.resource.LifecycleHelper;
-import org.apache.excalibur.merlin.assembly.resource.ResourceProvider;
-import org.apache.excalibur.merlin.assembly.resource.ResourceException;
-import org.apache.excalibur.merlin.assembly.resource.DefaultResource;
+import org.apache.excalibur.merlin.resource.ResourceException;
+import org.apache.excalibur.merlin.resource.DefaultResource;
/**
* Internal table that holds available component type keyed relative
@@ -61,18 +59,6 @@
* The dependency map that is populated during the assembly process.
*/
private DependencyGraph m_map;
-
- /**
- * The lifecycle helper.
- */
- private LifecycleHelper m_helper;
-
- /**
- * Utility class that manages supply of context, config, services, etc. during
- * startup of a profile.
- */
- private ResourceProvider m_provider;
-
//=======================================================================
// constructor
1.2 +5 -5 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/StructuralExtension.java
Index: StructuralExtension.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/StructuralExtension.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- StructuralExtension.java 12 Aug 2002 01:56:37 -0000 1.1
+++ StructuralExtension.java 12 Aug 2002 08:11:09 -0000 1.2
@@ -6,16 +6,16 @@
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.excalibur.merlin.container.Container;
-import org.apache.excalibur.merlin.container.Structural;
import org.apache.excalibur.merlin.assembly.TypeException;
import org.apache.excalibur.merlin.assembly.ContainerManager;
-import org.apache.excalibur.merlin.assembly.resource.Extension;
-import org.apache.excalibur.merlin.assembly.resource.AbstractExtension;
+import org.apache.excalibur.merlin.container.Container;
+import org.apache.excalibur.merlin.container.Structural;
+import org.apache.excalibur.merlin.resource.Extension;
+import org.apache.excalibur.merlin.resource.AbstractExtension;
import org.apache.excalibur.merlin.model.builder.XMLContainerUtil;
import org.apache.excalibur.merlin.model.ContainerDescriptor;
-import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.merlin.model.Profile;
+import org.apache.excalibur.meta.info.Type;
/**
* Extension that supplorts the assembly of a container structure.
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/AbstractExtension.java
Index: AbstractExtension.java
===================================================================
package org.apache.excalibur.merlin.resource;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Disposable;
/**
* Definition of an extension type.
* @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
*/
public class AbstractExtension extends AbstractLogEnabled implements Extension
{
//=======================================================================
// Extension
//=======================================================================
/**
* Invoked by a container to request the application of a custom lifecycle
* phase on the supplied object.
*
* @param int lifecycle stage
* @param object the object to apply the extension to
* @param context the context
* @exception Exception if an error occurs
*/
public void extend( int stage, Object object, Context context )
throws Exception
{
if( getLogger().isDebugEnabled() )
getLogger().debug(
"extending " + object.getClass().getName()
+ "#" + System.identityHashCode( object )
+ " for stage " + stageToString( stage ) );
}
/**
* Utility method to return a string representation of the lifecycle stage.
* @param stage the lifecycle stage
* @return the string representation of the stage
*/
public static String stageToString( int stage )
{
if( stage == CREATE )
{
return "CREATE";
}
else if( stage == ACCESS )
{
return "ACCESS";
}
else if( stage == RELEASE )
{
return "RELEASE";
}
else if( stage == DESTROY )
{
return "DESTROY";
}
else
{
throw new IllegalArgumentException( "stage: " + stage );
}
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/AbstractLifestyleHandler.java
Index: AbstractLifestyleHandler.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.TXT file.
*
* Original contribution by OSM SARL, http://www.osm.net
*/
package org.apache.excalibur.merlin.resource;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.context.Context;
import org.apache.excalibur.merlin.assembly.ContainerManager;
import org.apache.excalibur.merlin.resource.ResourceException;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.Resource;
import org.apache.excalibur.meta.info.PhaseDescriptor;
import org.apache.excalibur.meta.info.ExtensionDescriptor;
import org.apache.excalibur.meta.info.Facility;
/**
* Lifestyle implementation that provides suppport for the singleton
* policy. Request for a single instance will allways return the
* same instance for each request.
*
* @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
*/
public abstract class AbstractLifestyleHandler extends AbstractLogEnabled
implements LifestyleHandler, Disposable
{
private Profile m_profile;
private ContainerManager m_manager;
private ResourceProvider m_provider;
private LifecycleHelper m_helper;
private Context m_context;
/**
* Creation of a new singleton lifecycle manager.
* @param manager the type manager
* @param provider the resource provider
* @param helper the lifecycle helper
* @param profile the profile defining the object type
* @param context the establishment context
*/
public AbstractLifestyleHandler(
final ContainerManager manager,
final ResourceProvider provider,
final LifecycleHelper helper,
final Profile profile,
final Context context )
{
if( profile == null )
throw new NullPointerException("profile");
if( manager == null )
throw new NullPointerException("manager");
m_profile = profile;
m_manager = manager;
m_provider = provider;
m_helper = helper;
m_context = context;
}
/**
* Returns an instance of the object type supported by the
* manager to the client.
*
* @return an instance of the type defined by the profile
*/
public abstract Object get() throws Exception;
/**
* Invoked by a client to return an instance of the object type previously
* supported by the manager. The singleton manager does nothing as the
* object may be used across an arbitary number of clients.
*
* @param object the object to return
*/
public abstract void put( Object object ) throws Exception;
/**
* Handle the access phase extensions as declared by the profile type.
* @param object the object to process
* @param Exception if a stage procesing exception occurs
*/
protected void processAccessStage( Object object ) throws Exception
{
DefaultContext context = new DefaultContext();
PhaseDescriptor[] phases = m_profile.getType().getPhases();
for( int i=0; i<phases.length; i++ )
{
processExtension( ExtensionDescriptor.RELEASE, phases[i], object, context );
}
}
/**
* Handle the access phase extensions as declared by the profile type.
* @param object the object to process
* @param Exception if a stage procesing exception occurs
*/
protected void processReleaseStage( Object object ) throws Exception
{
DefaultContext context = new DefaultContext();
PhaseDescriptor[] phases = m_profile.getType().getPhases();
for( int i=(phases.length-1); i>-1; i-- )
{
processExtension( ExtensionDescriptor.RELEASE, phases[i], object, context );
}
}
private void processExtension( int stage, PhaseDescriptor phase, Object object, Context context ) throws Exception
{
final Facility facility = m_profile.getFacility( phase );
final ExtensionDescriptor ext = facility.getExtension( phase );
if( ext.isApplicable( stage ) )
{
Resource resource = m_profile.getExtension( phase );
Extension extension = (Extension) resource.access();
try
{
extension.extend( stage, object, context );
}
catch( Throwable e )
{
final String error =
"Extension " + extension.getClass().getName()
+ " raised an exception " + e.getClass().getName()
+ " while processing the "
+ ExtensionDescriptor.stageToString( stage )
+ " phase for the component "
+ m_profile.getName();
throw new LifecycleException( error, e );
}
}
}
/**
* Instantiate an instance of the type.
*
* @return an instance of the type defined by the profile
*/
protected Object createInstance() throws Exception
{
getLogger().debug("create");
//
// load the class
//
Class clazz = null;
String classname = null;
try
{
classname = m_profile.getType().getInfo().getImplementationKey();
clazz = m_manager.loadClass( classname );
}
catch( Throwable e )
{
final String error =
"Unexpected exception while attempting to load class '"
+ classname + "' for the profile: " + m_profile;
throw new ResourceException( error, e );
}
//
// create a new instance of the class
//
Object object;
try
{
object = clazz.newInstance();
}
catch( Throwable e )
{
final String error =
"Unexpected exception while attempting to instantiate an instance from profile: "
+ m_profile;
throw new ResourceException( error, e );
}
final String path = m_manager.getPath() + "/" + m_profile.getName();
m_helper.startup( object, path, m_profile, m_provider, m_context );
return object;
}
/**
* Request for disposal of the manager. This operation is normally invoked
* by the client that initialy instantiated the manager. The implementation
* handles the disposal of the associated profile.
*/
public void dispose()
{
m_profile = null;
m_manager = null;
m_provider = null;
m_helper = null;
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DefaultComponentManager.java
Index: DefaultComponentManager.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.TXT file.
*
* Original contribution by OSM SARL, http://www.osm.net
*/
package org.apache.excalibur.merlin.resource;
import java.util.Map;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
/**
* Internal helper class the implements the <code>ComponentLocator</code> interface and
* is supplied to dynamically created componets during lifecycle pipeline processing.
* @author Stephen McConnell <mc...@osm.net>
*/
class DefaultComponentManager
extends DefaultManager
implements ComponentManager
{
public DefaultComponentManager( Map providers )
{
super( providers );
}
public boolean hasComponent( String role )
{
return super.has( role );
}
public Component lookup( String role ) throws ComponentException
{
Object object = null;
try
{
object = super.get( role );
if( object instanceof Component )
{
return (Component)object;
}
throw new ComponentException( role, "Service provider returned a non-Component." );
}
catch( ResourceException e )
{
final String error = "Provider related error during service resolution.";
throw new ComponentException( role, error, e );
}
}
/**
* Release a pooled object.
*
* @param component a pooled object
*/
public void release( Component component )
{
super.put( component );
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DefaultManager.java
Index: DefaultManager.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.TXT file.
*
* Original contribution by OSM SARL, http://www.osm.net
*/
package org.apache.excalibur.merlin.resource;
import java.util.Map;
import java.util.Hashtable;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.excalibur.merlin.model.Resource;
/**
* Internal helper class the handles the functional requirements of
* both ComponetManager and ComponentLocator.
* @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
*/
class DefaultManager
{
/**
* A map of resources keyed by lookup role.
*/
private Map m_providers;
/**
* A mappiong of resource instances keyed by the object is provided
* and to which the object should be released.
*/
private Hashtable m_mapping = new Hashtable();
/**
* Creation of a new manager.
* @param providers the resource map
*/
public DefaultManager( Map providers )
{
m_providers = providers;
}
/**
* Return TRUE is the manager has a resoruce for the role.
* @param role the role name to look for in the resource map
* @return TRUE is a resource exists for the role
*/
public boolean has( String role )
{
return ( m_providers.get( role ) != null );
}
/**
* Returns the service object.
* @return the service instance
*/
public Object get( String role ) throws ResourceException
{
Resource resource = (Resource) m_providers.get( role );
if( resource == null )
{
throw new ResourceException(
"Could not locate a provider for the role: " + role );
}
else
{
try
{
Object object = resource.access();
m_mapping.put( object, resource );
return object;
}
catch( Throwable e )
{
final String error = "Unexpected exception while resolving the service from "
+ resource.getPath() + " for the role: " + role;
throw new ResourceException( error, e );
}
}
}
/**
* Release a pooled object.
* @param object a pooled object
* @exception ResourceRuntimeException is an error occurs during release
*/
public void put( Object object ) throws ResourceRuntimeException
{
final Resource resource = (Resource) m_mapping.get( object );
try
{
resource.release( object );
m_mapping.remove( object );
}
catch( Throwable e )
{
final String error = "Unexpected error while attempting to release resource: " + resource;
throw new ResourceRuntimeException( error, e );
}
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DefaultResource.java
Index: DefaultResource.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.excalibur.merlin.resource;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.excalibur.merlin.resource.LifecycleHelper;
import org.apache.excalibur.merlin.resource.LifestyleHandler;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.Resource;
import org.apache.excalibur.meta.info.ServiceDescriptor;
import org.apache.excalibur.meta.info.PhaseDescriptor;
import org.apache.excalibur.meta.info.ExtensionDescriptor;
import org.apache.excalibur.meta.info.Facility;
/**
* Opaque type that maps a path to a profile.
*
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/08/12 08:11:09 $
*/
public class DefaultResource extends AbstractLogEnabled implements Resource
{
public static final String HEADER = "service:";
/**
* The path of the profile designator.
*/
private final String m_path;
/**
* The profile that disignator refers to.
*/
private final Profile m_profile;
/**
* The deployment context.
*/
private final Context m_context;
/**
* The lifestyle manager.
*/
private LifestyleHandler m_handler;
/**
* Create a new resoruce instance.
*
* @param path the container path
* @param profile the resource's profile
* @param context the deployment context
* @param factory the lifestyle manager
*/
public DefaultResource( final String path,
final Profile profile,
final Context context,
final LifestyleHandler handler )
{
if( null == path )
throw new NullPointerException( "path" );
if( null == profile )
throw new NullPointerException( "profile" );
if( null == context )
throw new NullPointerException( "context" );
if( null == handler )
throw new NullPointerException( "handler" );
m_path = path;
m_profile = profile;
m_context = context;
m_handler = handler;
}
/**
* Returns the path of the resource.
*
* @return the symbolic path of the resource
*/
public String getPath()
{
return HEADER + m_path;
}
/**
* Returns the service descriptor.
*
* @return the service descriptor
*/
public ServiceDescriptor[] getServices()
{
return m_profile.getType().getServices();
}
/**
* Access an instance.
*
* @return the service instance.
* @exception Exception if an error occurs while establishing the object
*/
public Object access() throws Exception
{
getLogger().debug("access");
return m_handler.get();
}
/**
* Release a service instance.
*/
public void release( Object object ) throws Exception
{
getLogger().debug("release");
m_handler.put( object );
}
/**
* Dispose of the reference and any consumed resources.
*/
public void dispose()
{
getLogger().debug("dispose");
if( m_handler instanceof Disposable )
{
((Disposable)m_handler).dispose();
}
m_handler = null;
}
/**
* Return the profile.
*
* @return the profile
*/
public Profile getProfile()
{
return m_profile;
}
public String toString()
{
return "DefaultResource - profile:" + m_profile;
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/DefaultServiceManager.java
Index: DefaultServiceManager.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.TXT file.
*
* Original contribution by OSM SARL, http://www.osm.net
*/
package org.apache.excalibur.merlin.resource;
import java.util.Map;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
/**
* Internal helper class the implements the <code>ServiceManager</code> interface and
* is supplied to dynamically created componets during lifecyle pipeline processing.
* @author Stephen McConnell <mc...@osm.net>
*/
class DefaultServiceManager
extends DefaultManager
implements ServiceManager
{
/**
* Construct a new ServiceManager.
*/
public DefaultServiceManager( Map providers )
{
super( providers );
}
/**
* Returns true if a provider exists for the supplied role.
* @param role the service identifier
* @return boolean TRUE if the service is available else FALSE
*/
public boolean hasService( String role )
{
return super.has( role );
}
/**
* Retrieve Object by role from ComponentLocator.
* @param role the role
* @return the Object
* @throws ServiceException if an error occurs
*/
public Object lookup( String role ) throws ServiceException
{
try
{
return super.get( role );
}
catch( ResourceException e )
{
final String error = "Service resolution failure for role: " + role;
throw new ServiceException( error, e );
}
}
/**
* Release a pooled object.
* @param object a pooled object
*/
public void release( Object object )
{
super.put( object );
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/Extension.java
Index: Extension.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.excalibur.merlin.resource;
import org.apache.avalon.framework.context.Context;
/**
* <code>PhaseExtension</code> interface. This interface defines the methods that
* a container can invoke on a phase handler extension.
*
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @author <a href="mailto:crafterm@apache.org">Marcus Crafter</a>
* @version CVS $Revision: 1.1 $ $Date: 2002/08/12 08:11:09 $
*/
public interface Extension
{
public static final int CREATE = 0;
public static final int ACCESS = 1;
public static final int RELEASE = 2;
public static final int DESTROY = 3;
/**
* Apply lifecycle phase extension.
*
* @param stage the lifecycle stage
* @param object the object to apply the extension to
* @param context the context
* @exception Exception if an error occurs
*/
void extend( int stage, Object object, Context context )
throws Exception;
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/LifecycleException.java
Index: LifecycleException.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.excalibur.merlin.resource;
import org.apache.avalon.framework.CascadingException;
import org.apache.excalibur.meta.verifier.VerifyException;
/**
* Exception to indicate error processing a component through its lifecycle.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/08/12 08:11:09 $
*/
public final class LifecycleException
extends CascadingException
{
/**
* Construct a new <code>VerifyException</code> instance.
*
* @param message The detail message for this exception.
*/
public LifecycleException( final String message )
{
this( message, null );
}
/**
* Construct a new <code>VerifyException</code> instance.
*
* @param message The detail message for this exception.
* @param throwable the root cause of the exception
*/
public LifecycleException( final String message, final Throwable throwable )
{
super( message, throwable );
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/LifecycleHelper.java
Index: LifecycleHelper.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.excalibur.merlin.resource;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.configuration.Configurable;
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.Contextualizable;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.excalibur.merlin.container.Container;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.Resource;
import org.apache.excalibur.merlin.model.ContextDirective;
import org.apache.excalibur.meta.info.ContextDescriptor;
import org.apache.excalibur.meta.info.PhaseDescriptor;
import org.apache.excalibur.meta.info.ExtensionDescriptor;
import org.apache.excalibur.meta.info.Facility;
/**
* This is a class to help an Application manage the lifecycle of a component.
* The implementation provides support for the processing of a component through
* each lifecycle stage, and manage errors in a consistent way.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
*/
public class LifecycleHelper
extends AbstractLogEnabled
{
private static final Resources REZ =
ResourceManager.getPackageResources( LifecycleHelper.class );
//Constants to designate stages
private static final int STAGE_CREATE = 0;
private static final int STAGE_LOGGER = 1;
private static final int STAGE_CONTEXT = 2;
private static final int STAGE_COMPOSE = 3;
private static final int STAGE_CONFIG = 4;
private static final int STAGE_PARAMETER = 5;
private static final int STAGE_EXTENSION_PRE = 6;
private static final int STAGE_INIT = 7;
private static final int STAGE_START = 8;
private static final int STAGE_STOP = 9;
private static final int STAGE_DISPOSE = 10;
private static final int STAGE_EXTENSION_POST = 11;
private static final int STAGE_DESTROY = 12;
/**
* Method to run a component through it's startup phase.
* Errors that occur during startup will be logged appropriately and
* cause exceptions with useful messages to be raised.
*
* @param name the name of the component
* @param profile representing the instance criteria
* @param provider the resource provider
* @param phaseContext the phase context
*
* @throws LifecycleException if an error occurs when the component passes
* through a specific lifecycle stage
*/
public Object startup( final Object object,
final String path,
final Profile profile,
final ResourceProvider provider,
final Context phaseContext )
throws LifecycleException
{
if( object == null )
throw new NullPointerException("object");
if( path == null )
throw new NullPointerException("path");
if( profile == null )
throw new NullPointerException("profile");
if( provider == null )
throw new NullPointerException("provider");
if( phaseContext == null )
throw new NullPointerException("phaseContext");
getLogger().info("startup initiated for '" + path + "'." );
int stage = 0;
try
{
//Creation stage
//stage = STAGE_CREATE;
//notice( path, stage );
//final Object object = provider.createObject( profile );
//LogEnabled stage
stage = STAGE_LOGGER;
if( object instanceof LogEnabled )
{
notice( path, stage );
final Logger logger = provider.createLogger( profile );
ContainerUtil.enableLogging( object, logger );
}
//Contextualize stage
stage = STAGE_CONTEXT;
if( object instanceof Contextualizable )
{
notice( path, stage );
final Context context = provider.createContext( profile, phaseContext );
ContainerUtil.contextualize( object, context );
}
//Composition stage
stage = STAGE_COMPOSE;
if( object instanceof Serviceable )
{
notice( path, stage );
final ServiceManager manager =
provider.createServiceManager( profile );
ContainerUtil.service( object, manager );
}
else if( object instanceof Composable )
{
notice( path, stage );
final ComponentManager componentManager =
provider.createComponentManager( profile );
ContainerUtil.compose( object, componentManager );
}
//Configuring stage
stage = STAGE_CONFIG;
if( object instanceof Configurable )
{
notice( path, stage );
final Configuration configuration =
provider.createConfiguration( profile );
ContainerUtil.configure( object, configuration );
}
//Parameterizing stage
stage = STAGE_PARAMETER;
if( object instanceof Parameterizable )
{
notice( path, stage );
final Parameters parameters =
provider.createParameters( profile );
ContainerUtil.parameterize( object, parameters );
}
//
// apply creation phase extensions
//
stage = STAGE_EXTENSION_PRE;
PhaseDescriptor[] phases = profile.getType().getPhases();
if( phases.length > 0 )
notice( path, stage );
for( int i=0; i<phases.length; i++ )
{
PhaseDescriptor phase = phases[i];
final Facility facility = profile.getFacility( phase );
final ExtensionDescriptor ext = facility.getExtension( phase );
if( ext.isApplicable( ExtensionDescriptor.CREATE ) )
{
Resource resource = profile.getExtension( phase );
Extension extension = (Extension) resource.access();
try
{
getLogger().info("applying phase " + phase.getReference() + " to " + path );
Context extContext = provider.createContext( ext, phaseContext );
extension.extend( Extension.CREATE, object, extContext );
}
catch( Throwable e )
{
final String error =
"Extension " + extension.getClass().getName()
+ " raised an exception " + e.getClass().getName()
+ " while processing the creation phase for the component "
+ path;
throw new LifecycleException( error, e );
}
}
}
//Initialize stage
stage = STAGE_INIT;
if( object instanceof Initializable )
{
notice( path, stage );
ContainerUtil.initialize( object );
}
//Start stage
stage = STAGE_START;
if( !(object instanceof Container) )
{
if( object instanceof Startable )
{
notice( path, stage );
ContainerUtil.start( object );
}
}
return object;
}
catch( final Throwable t )
{
fail( path, stage, t );
//fail() throws an exception so next
//line will never be executed
return null;
}
}
/**
* Method to run a component through it's shutdown phase.
* Errors that occur during shutdown will be logged appropriately.
*
* @param name the name of the component
* @param object the component to shutdown
*/
public void shutdown( final String name,
final Profile profile,
final Object object )
throws LifecycleException
{
getLogger().info("shutdown initiated for '" + name + "'." );
//Stage at which failure occured
int stage = 0;
//Failure exception
Throwable failure = null;
//Stoppable stage
if( object instanceof Startable )
{
notice( name, STAGE_STOP );
try
{
ContainerUtil.stop( object );
}
catch( final Throwable t )
{
safeFail( name, STAGE_STOP, t );
failure = t;
stage = STAGE_STOP;
}
}
//
// apply disposal extensions
// ### TO-DO context ###
//
stage = STAGE_EXTENSION_POST;
PhaseDescriptor[] phases = profile.getType().getPhases();
if( phases.length > 0 )
notice( name, stage );
for( int i=(phases.length-1); i>-1; i-- )
{
PhaseDescriptor phase = phases[i];
final Facility facility = profile.getFacility( phase );
final ExtensionDescriptor ext = facility.getExtension( phase );
if( ext.isApplicable( ExtensionDescriptor.DESTROY ) )
{
try
{
Resource resource = profile.getExtension( phase );
Extension extension = (Extension) resource.access();
getLogger().info("applying '" + phase.getReference()
+ "' to '" + name + "'.");
extension.extend( Extension.DESTROY, object, new DefaultContext() );
}
catch( Throwable e )
{
safeFail( name, STAGE_EXTENSION_POST, e );
failure = e;
stage = STAGE_EXTENSION_POST;
}
}
}
//Disposable stage
if( object instanceof Disposable )
{
notice( name, STAGE_DISPOSE );
try
{
ContainerUtil.dispose( object );
}
catch( final Throwable t )
{
safeFail( name, STAGE_DISPOSE, t );
failure = t;
stage = STAGE_DISPOSE;
}
}
notice( name, STAGE_DESTROY );
if( null != failure )
{
fail( name, stage, failure );
}
}
/**
* Utility method to report that a lifecycle stage is about to be processed.
*
* @param name the name of component that is the subject of the notice
* @param stage the lifecycle processing stage
*/
private void notice( final String name, final int stage )
{
if( getLogger().isDebugEnabled() )
{
final String message =
REZ.getString( "lifecycle.stage.notice",
name,
new Integer( stage ) );
getLogger().debug( message );
}
}
/**
* Utility method to report that there was an error processing
* specified lifecycle stage.
*
* @param name the name of component that caused failure
* @param stage the lefecycle stage
* @param t the exception thrown
*/
private void safeFail( final String name,
final int stage,
final Throwable t )
{
final String reason = t.toString();
final String message =
REZ.getString( "lifecycle.fail.error",
name,
new Integer( stage ),
reason );
getLogger().error( message );
}
/**
* Utility method to report that there was an error processing
* specified lifecycle stage. It will also re-throw an exception
* with a better error message.
*
* @param name the name of block that caused failure
* @param stage the stage
* @param t the exception thrown
* @throws LifecycleException containing error
*/
private void fail( final String name,
final int stage,
final Throwable t )
throws LifecycleException
{
//final String reason = t.getMessage();
final String reason = t.toString();
final String message =
REZ.getString( "lifecycle.fail.error",
name,
new Integer( stage ), reason );
getLogger().error( message );
throw new LifecycleException( message, t );
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/LifestyleHandler.java
Index: LifestyleHandler.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.TXT file.
*
* Original contribution by OSM SARL, http://www.osm.net
*/
package org.apache.excalibur.merlin.resource;
import java.util.Map;
import java.util.Hashtable;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.excalibur.merlin.model.Resource;
/**
* Interface implemented by a component lifestyle handler.
*
* @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
*/
public interface LifestyleHandler
{
/**
* Returns an instance of the object type supported by the
* manager to the client.
*
* @return an instance
* @exception Exception if an error occurs during object aquisition
*/
public Object get() throws Exception;
/**
* Invoked by a client to return an instance of the object type previously
* supplied by a manager implementation.
*
* @param object the object to return
* @exception Exception if an error occurs during object release
*/
public void put( Object object ) throws Exception;
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/ResourceException.java
Index: ResourceException.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.excalibur.merlin.resource;
import java.util.Enumeration;
import java.util.Dictionary;
import java.util.Hashtable;
import org.apache.avalon.framework.CascadingException;
/**
* Exception to indicate that there was an error relating to resource management.
*
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/08/12 08:11:09 $
*/
public final class ResourceException
extends CascadingException
{
/**
* Construct a new <code>ResourceException</code> instance.
*
* @param message The detail message for this exception.
*/
public ResourceException( final String message )
{
this( message, null );
}
/**
* Construct a new <code>ResourceException</code> instance.
*
* @param message The detail message for this exception.
* @param throwable the root cause of the exception
*/
public ResourceException( final String message, final Throwable throwable )
{
super( message, throwable );
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/ResourceProvider.java
Index: ResourceProvider.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.excalibur.merlin.resource;
import java.io.InputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.JarURLConnection;
import java.net.URLClassLoader;
import java.util.Map;
import java.util.List;
import java.util.LinkedList;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;
import java.util.Iterator;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.security.Policy;
import java.io.FileInputStream;
import java.util.HashMap;
import java.lang.reflect.Constructor;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.Version;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.AvalonFormatter;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Executable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.parameters.Parameters;
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.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.excalibur.configuration.ConfigurationUtil;
import org.apache.excalibur.meta.verifier.VerifyException;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.info.ServiceDescriptor;
import org.apache.excalibur.meta.info.DependencyDescriptor;
import org.apache.excalibur.meta.info.ReferenceDescriptor;
import org.apache.excalibur.meta.info.ContextDescriptor;
import org.apache.excalibur.meta.info.EntryDescriptor;
import org.apache.excalibur.meta.info.ExtensionDescriptor;
import org.apache.excalibur.merlin.resource.ResourceException;
import org.apache.excalibur.merlin.assembly.KernelManager;
import org.apache.excalibur.merlin.assembly.ContainerManager;
import org.apache.excalibur.merlin.assembly.DefaultLoggerManager;
import org.apache.excalibur.merlin.resource.DefaultComponentManager;
import org.apache.excalibur.merlin.resource.DefaultServiceManager;
import org.apache.excalibur.merlin.model.ContainerDescriptor;
import org.apache.excalibur.merlin.model.ContextDirective;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.Association;
import org.apache.excalibur.merlin.model.Resource;
import org.apache.excalibur.merlin.model.Import;
import org.apache.excalibur.merlin.model.Entry;
/**
* Internal class that handles the establishment of component instances based on a supplied
* type profile.
*
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/08/12 08:11:09 $
*/
public class ResourceProvider extends AbstractLogEnabled
{
//=======================================================================
// state
//=======================================================================
private final static Resources REZ =
ResourceManager.getPackageResources( ResourceProvider.class );
//=======================================================================
// state
//=======================================================================
/**
* The log manager.
*/
private DefaultLoggerManager m_logging;
/**
* The classloader to use when servicing object creation requests.
*/
private ContainerManager m_classloader;
/**
* Context object containing system level values that is used
* as a sources for import directives.
*/
private DefaultContext m_dictionary;
//=======================================================================
// constructor
//=======================================================================
/**
* Creation of a new resource provider.
*
* @param logger the parent logger to use when creating loggers for services.
* @param loader the class loader
* @param dictionary the parent dictionary
*/
public ResourceProvider( ContainerManager loader, Context dictionary, DefaultLoggerManager logging )
{
m_classloader = loader;
m_logging = logging;
m_dictionary = new DefaultContext( dictionary );
m_dictionary.put( "classloader", loader );
m_dictionary.makeReadOnly();
}
//=======================================================================
// ResourceProvider
//=======================================================================
/**
* Create a new Logger for component.
*
* @param profile the profile
* @return a new Logger for service
* @throws Exception if unable to create the logger
*/
public Logger createLogger( Profile profile )
throws Exception
{
String root;
if( m_classloader instanceof KernelManager )
{
root = m_classloader.getPath().replace('/','.').substring(1);
}
else
{
root = m_classloader.getPath().replace('/','.').substring(1) + "." + profile.getName();
}
m_logging.addCategories( root, profile.getCategories() );
return m_logging.getLoggerForCategory( root );
}
/**
* Create a new Context for component.
*
* @param profile the profile
* @param a supplimentary context usable during import resolution
* @return a new Context for service
* @throws Exception if unable to create context
*/
public Context createContext( Profile profile, Context context )
throws Exception
{
ContextDescriptor descriptor = profile.getType().getContext();
ContextDirective directive = profile.getContext();
return buildContext( descriptor, directive, context );
}
/**
* Create a new Context for an extension.
*
* @param profile the profile
* @param a supplimentary context usable during import resolution
* @return a new Context for service
* @throws Exception if unable to create context
*/
public Context createContext( ExtensionDescriptor extension, Context context )
throws Exception
{
ContextDescriptor descriptor = extension.getContext();
return buildContext( descriptor, null, context );
}
/**
* Internal utility to construct a context instance using a descriptor, directive and source
* context instances.
*
* @param descriptor the descriptor containing the context dependency declarations
* @param directive an optional context directive containing import and context value
* creation parameters
* @param context a supplimentary context object to used during value resolution
* @return a context object containing only those context entries desribed under the
* supplied descriptor
* @exception Exception if a required context value cannot be resolved or an error
* occurs during context value creation
*/
private Context buildContext(
ContextDescriptor descriptors,
ContextDirective directive,
Context context )
throws Exception
{
Map map = new HashMap();
Context result;
if( directive != null )
{
final String classname = directive.getClassname();
Class clazz;
try
{
clazz = m_classloader.loadClass( classname );
}
catch( ClassNotFoundException cnfe )
{
throw new ResourceException(
"Could not find context class " + classname, cnfe );
}
try
{
Constructor constructor = clazz.getConstructor(
new Class[]{ Map.class, Context.class } );
result = (Context)constructor.newInstance( new Object[]{ map, null } );
}
catch( Throwable e )
{
throw new ResourceException(
"Unexpected exception while creating context form "
+ classname, e );
}
}
else
{
result = new DefaultContext( map );
}
Context dictionary = m_dictionary;
EntryDescriptor[] entries = descriptors.getEntrys();
for( int i=0; i<entries.length; i++ )
{
EntryDescriptor entry = entries[i];
String key = entry.getKey();
//
// if the entry is already in the supplied context then use it
//
Object object = getContextValue( context, key );
if( object == null )
{
object = getContextValue( dictionary, key );
}
//
// If the context value is unresolved, try to handle resolution
// using an import directive supplied under the directive
//
if( object == null )
{
//
// check if the profile declares an import directive
// for the context
//
if( directive != null )
{
Import imp = directive.getImport( key );
if( imp != null )
{
String name = imp.getImportName();
object = getContextValue( context, name );
if( object == null )
{
object = getContextValue( dictionary, name );
}
if( object == null )
{
final String error =
"Import directive for key: " + key + " via name: " + name
+ " cannot be resolved.";
getLogger().warn( error );
}
}
//
// if the context value is unresolved, try to construct a context
// value using an entry constructor directive
//
if( object == null )
{
//
// check if the directive declares a context value constructor
//
Entry ent = directive.getEntry( key );
if( ent != null )
{
object = ent.getValue( m_classloader, map );
}
}
}
}
//
// finally, if the object is still null, and its not optional, then
// throw an exception, otherwise, add the object to the context
//
if( object != null )
{
try
{
boolean ok = objectImplementsType( object, entry.getType() );
if( ok )
{
map.put( key, object );
}
else
{
final String error =
"Object resolved for the key '" + key + "' of class '"
+ object.getClass().getName() + "' does not implement the type '"
+ entry.getType();
throw new ResourceException( error );
}
}
catch( ClassNotFoundException cnfe )
{
final String error =
"Context criteria for the key '" + key + "' specifies an unknown type '"
+ entry.getType() + "'.";
throw new ResourceException( error );
}
}
else
{
if( entry.isRequired() )
{
final String error =
"Unable to resolve a context value for the entry: " + key;
throw new ResourceException( error );
}
}
}
if( result instanceof DefaultContext )
{
((DefaultContext)result).makeReadOnly();
}
return result;
}
private Object getContextValue( Context context, String key )
{
if( context == null ) return null;
try
{
return context.get( key );
}
catch( ContextException e )
{
return null;
}
}
/**
* Create a new ComponentManager for component.
*
* @param profile the profile
* @return a new ComponentManager for component
* @throws Exception if unable to create the component manager
*/
public ComponentManager createComponentManager( Profile profile )
throws Exception
{
final Map services = getServices( profile );
final DefaultComponentManager componentManager = new DefaultComponentManager( services );
return componentManager;
}
/**
* Create a new ServiceManager for component.
*
* @param entry the entry
* @return a new ServiceManager for component
* @throws Exception if unable to create resource
*/
public ServiceManager createServiceManager( Profile profile )
throws Exception
{
final Map services = getServices( profile );
final DefaultServiceManager serviceManager = new DefaultServiceManager( services );
return serviceManager;
}
/**
* Create a new Configuration object for component.
*
* @param entry the entry
* @return a new Configuration object for component
* @throws Exception if unable to create resource
*/
public Configuration createConfiguration( Profile profile )
throws Exception
{
Configuration config = profile.getConfiguration( m_classloader );
if( config == null )
config = new DefaultConfiguration("configuration", null );
return config;
}
/**
* Create a new Parameters object for component.
*
* @param entry the entry
* @return a new Parameters object for component
* @throws Exception if unable to create resource
*/
public Parameters createParameters( Profile profile )
throws Exception
{
final Parameters parameters = profile.getParameters();
if( null == parameters )
{
final String message =
REZ.getString( "resource.missing-parameters.error",
profile.getName() );
throw new Exception( message );
}
parameters.makeReadOnly();
return parameters;
}
/**
* Prepare a map of the dependent services keyed by role name.
* @param profile the profile referencing a type declaring dependecies
* @return a map of the services
*/
private Map getServices( Profile profile ) throws Exception
{
getLogger().debug("preparing services for profile: " + profile );
final Type type = profile.getType();
final DependencyDescriptor[] dependencies = type.getDependencies();
final HashMap services = new HashMap();
for( int i = 0; i < dependencies.length; i++ )
{
DependencyDescriptor dependency = dependencies[i];
final String role = dependency.getRole();
try
{
final Association association = profile.getAssociation( role );
Object resource = association.getProvider();
services.put( role, resource );
}
catch( Throwable e )
{
final String error =
"Unexpected exception while attempting to locate a service to fulfill a dependency for "
+ "the role: " + role + " in profile: " + profile.getName() + ".";
throw new ResourceException( error, e );
}
}
return services;
}
/**
* Check whether the specified value is compatible with specified type.
*
* @param value the value
* @param type the desired type
* @return true if value is compatible with type, false otherwise
*/
private boolean objectImplementsType( final Object value, final String type )
throws ClassNotFoundException
{
if( type == null )
throw new NullPointerException("type");
if( value == null )
throw new NullPointerException("value");
final Class clazz = value.getClass();
final Class typeClass = m_classloader.loadClass( type );
return typeClass.isAssignableFrom( clazz );
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/ResourceRuntimeException.java
Index: ResourceRuntimeException.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.excalibur.merlin.resource;
import java.util.Enumeration;
import java.util.Dictionary;
import java.util.Hashtable;
import org.apache.avalon.framework.CascadingRuntimeException;
/**
* Exception to indicate that there was an error relating to resource management.
*
* @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/08/12 08:11:09 $
*/
public final class ResourceRuntimeException
extends CascadingRuntimeException
{
/**
* Construct a new <code>ResourceRuntimeException</code> instance.
*
* @param message The detail message for this exception.
*/
public ResourceRuntimeException( final String message )
{
this( message, null );
}
/**
* Construct a new <code>ResourceRuntimeException</code> instance.
*
* @param message The detail message for this exception.
* @param throwable the root cause of the exception
*/
public ResourceRuntimeException( final String message, final Throwable throwable )
{
super( message, throwable );
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/Resources.properties
Index: Resources.properties
===================================================================
lifecycle.stage.notice=Component named "{0}" is passing through the {1,choice,0#Creation|1#Logger initialization|2#Contextualization|3#Composing|4#Configuration|5#Parameterizing|6#Extension-CREATE|7#Initialization|8#Starting|9#Stopping|10#Extension-DESTROY|11#Disposing|12#Destruction} stage.
lifecycle.fail.error=Component named "{0}" failed to pass through the {1,choice,0#Creation|1#Logger initialization|2#Contextualization|3#Composing|4#Configuration|5#Parameterizing|6#Extension-CREATE|7#Initialization|8#Starting|9#Stopping|10#Extension-DESTROY|11#Disposing|12#Destruction} stage. (Reason: {2}).
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/SingletonLifestyleHandler.java
Index: SingletonLifestyleHandler.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.TXT file.
*
* Original contribution by OSM SARL, http://www.osm.net
*/
package org.apache.excalibur.merlin.resource;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.context.Context;
import org.apache.excalibur.merlin.assembly.ContainerManager;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.Resource;
import org.apache.excalibur.meta.info.PhaseDescriptor;
import org.apache.excalibur.meta.info.ExtensionDescriptor;
import org.apache.excalibur.meta.info.Facility;
/**
* Lifestyle implementation that provides suppport for the singleton
* policy. Request for a single instance will allways return the
* same instance for each request.
*
* @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
*/
public class SingletonLifestyleHandler extends AbstractLifestyleHandler
{
private Profile m_profile;
private ContainerManager m_manager;
private LifecycleHelper m_helper;
private Object m_object;
/**
* Creation of a new singleton lifecycle manager.
* @param manager the type manager
* @param provider the resource provider
* @param helper the lifecycle helper
* @param profile the profile defining the object type
* @param context the establishment context
*/
public SingletonLifestyleHandler(
final ContainerManager manager,
final ResourceProvider provider,
final LifecycleHelper helper,
final Profile profile,
final Context context )
{
super( manager, provider, helper, profile, context );
m_profile = profile;
m_manager = manager;
m_helper = helper;
}
/**
* Returns an instance of the object type supported by the
* manager to the client.
*
* @return an instance of the type defined by the profile
*/
public Object get() throws Exception
{
getLogger().debug("get");
if( m_object == null )
m_object = super.createInstance();
super.processAccessStage( m_object );
return m_object;
}
/**
* Invoked by a client to return an instance of the object type previously
* supported by the manager. The singleton manager does nothing as the
* object may be used across an arbitary number of clients.
*
* @param object the object to return
*/
public void put( Object object ) throws Exception
{
getLogger().debug("put");
super.processReleaseStage( m_object );
}
/**
* Request for disposal of the manager. This operation is normally invoked
* by the client that initialy instantiated the manager. The implementation
* handles the disposal of the singleton resoruce and release of associated
* references.
*/
public void dispose()
{
if( m_object != null )
{
final String path = m_manager.getPath() + "/" + m_profile.getName();
try
{
m_helper.shutdown( path, m_profile, m_object );
}
catch( Throwable e )
{
getLogger().warn("Ignoring shutdown error raised by resource: " + path );
}
}
m_object = null;
m_profile = null;
m_manager = null;
m_helper = null;
super.dispose();
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/TransientLifestyleHandler.java
Index: TransientLifestyleHandler.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.TXT file.
*
* Original contribution by OSM SARL, http://www.osm.net
*/
package org.apache.excalibur.merlin.resource;
import java.util.ArrayList;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.context.Context;
import org.apache.excalibur.merlin.assembly.ContainerManager;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.Resource;
import org.apache.excalibur.meta.info.PhaseDescriptor;
import org.apache.excalibur.meta.info.ExtensionDescriptor;
import org.apache.excalibur.meta.info.Facility;
/**
* Lifestyle implementation that provides suppport for the transient
* lifestyle policy. Request for a single instance will return
* an new instance for each request.
*
* @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
*/
public class TransientLifestyleHandler extends AbstractLifestyleHandler
{
private Profile m_profile;
private ContainerManager m_manager;
private LifecycleHelper m_helper;
private ArrayList m_objects = new ArrayList();
/**
* Creation of a new singleton lifecycle manager.
* @param manager the type manager
* @param provider the resource provider
* @param helper the lifecycle helper
* @param profile the profile defining the object type
* @param context the establishment context
*/
public TransientLifestyleHandler(
final ContainerManager manager,
final ResourceProvider provider,
final LifecycleHelper helper,
final Profile profile,
final Context context )
{
super( manager, provider, helper, profile, context );
m_profile = profile;
m_manager = manager;
m_helper = helper;
}
/**
* Returns an instance of the object type supported by the
* manager to the client.
*
* @return an instance of the type defined by the profile
*/
public Object get() throws Exception
{
getLogger().debug("get");
Object object = super.createInstance();
m_objects.add( object );
super.processAccessStage( object );
return object;
}
/**
* Invoked by a client to return an instance of the object type previously
* supported by the manager. The singleton manager does nothing as the
* object may be used across an arbitary number of clients.
*
* @param object the object to return
*/
public void put( Object object ) throws Exception
{
getLogger().debug("put");
if( m_objects.contains( object ) )
{
m_objects.remove( object );
final String path = m_manager.getPath() + "/" + m_profile.getName();
try
{
m_helper.shutdown( path, m_profile, object );
}
catch( Throwable e )
{
getLogger().warn("Ignoring shutdown error raised by transient resource: " + path );
}
}
super.processReleaseStage( object );
}
/**
* Request for disposal of the manager. This operation is normally invoked
* by the client that initialy instantiated the manager. The implementation
* handles the disposal of the singleton resoruce and release of associated
* references.
*/
public void dispose()
{
Object[] objects = m_objects.toArray();
for( int i=0; i<objects.length; i++ )
{
try
{
put( objects[i] );
}
catch( Throwable e )
{
//
}
}
m_profile = null;
m_manager = null;
m_helper = null;
m_objects = null;
super.dispose();
}
}
1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/resource/package.html
Index: package.html
===================================================================
<body>
Interfaces and classes supporting component lifecycle management.
</body>
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>