svn commit: rev 46037 - in avalon/trunk/runtime: . composition/api/src/java/org/apache/avalon/composition/model composition/impl composition/impl/etc/test composition/impl/src/java/org/apache/avalon/composition/model/impl composition/impl/src/test/org/apache/avalon/composition/model/impl composition/impl/src/test/org/apache/avalon/composition/model/test test/testcyclic test/testcyclic/src test/testcyclic/src/main test/testcyclic/src/main/org test/testcyclic/src/main/org/apache test/testcyclic/src/main/org/apache/avalon test/testcyclic/src/main/org/apache/avalon/test test/testcyclic/src/main/org/apache/avalon/test/testcyclic
[email protected] 14 Sep 2004 21:04:41 -0000
| Newsgroups | gmane.comp.jakarta.avalon.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: niclas
Date: Tue Sep 14 14:04:40 2004
New Revision: 46037
Added:
avalon/trunk/runtime/composition/api/src/java/org/apache/avalon/composition/model/CyclicDependencyException.java (contents, props changed)
avalon/trunk/runtime/composition/impl/etc/test/cyclicdeps.xml (contents, props changed)
avalon/trunk/runtime/composition/impl/src/test/org/apache/avalon/composition/model/impl/CyclicDepsTestCase.java (contents, props changed)
avalon/trunk/runtime/test/testcyclic/
avalon/trunk/runtime/test/testcyclic/build.properties (contents, props changed)
avalon/trunk/runtime/test/testcyclic/build.xml (contents, props changed)
avalon/trunk/runtime/test/testcyclic/src/
avalon/trunk/runtime/test/testcyclic/src/main/
avalon/trunk/runtime/test/testcyclic/src/main/org/
avalon/trunk/runtime/test/testcyclic/src/main/org/apache/
avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/
avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/
avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/testcyclic/
avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/testcyclic/A.java (contents, props changed)
avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/testcyclic/B.java (contents, props changed)
avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/testcyclic/TestCyclicA.java (contents, props changed)
avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/testcyclic/TestCyclicB.java (contents, props changed)
Modified:
avalon/trunk/runtime/build.properties
avalon/trunk/runtime/build.xml
avalon/trunk/runtime/composition/api/src/java/org/apache/avalon/composition/model/DependencyGraph.java
avalon/trunk/runtime/composition/impl/build.properties
avalon/trunk/runtime/composition/impl/src/java/org/apache/avalon/composition/model/impl/DefaultContainmentModelAssemblyHelper.java
avalon/trunk/runtime/composition/impl/src/test/org/apache/avalon/composition/model/test/AbstractTestCase.java
avalon/trunk/runtime/index.xml
Log:
Patch sent in by Peter Neubauer that detects cyclic dependencies in the composition model.
Modified: avalon/trunk/runtime/build.properties
==============================================================================
--- avalon/trunk/runtime/build.properties (original)
+++ avalon/trunk/runtime/build.properties Tue Sep 14 14:04:40 2004
@@ -1,2 +1,2 @@
project.system = ../central/system
-project.home = .
\ No newline at end of file
+project.home = .
Modified: avalon/trunk/runtime/build.xml
==============================================================================
--- avalon/trunk/runtime/build.xml (original)
+++ avalon/trunk/runtime/build.xml Tue Sep 14 14:04:40 2004
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?>
-
<project name="runtime" default="default" basedir="." xmlns:x="antlib:org.apache.avalon.tools">
<property file="build.properties"/>
Added: avalon/trunk/runtime/composition/api/src/java/org/apache/avalon/composition/model/CyclicDependencyException.java
==============================================================================
--- (empty file)
+++ avalon/trunk/runtime/composition/api/src/java/org/apache/avalon/composition/model/CyclicDependencyException.java Tue Sep 14 14:04:40 2004
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2004 Apache Software Foundation
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.avalon.composition.model;
+
+/**
+ * indicates a cyclic dependency problem in e.g. the assembly of models.
+ */
+public class CyclicDependencyException extends RuntimeException
+{
+
+ /**
+ * Default contructor
+ */
+ public CyclicDependencyException()
+ {
+ super();
+ }
+
+ /**
+ * @see RuntimeException
+ */
+ public CyclicDependencyException( String arg0 )
+ {
+ super( arg0 );
+ }
+
+ /**
+ * @see RuntimeException
+ */
+ public CyclicDependencyException( Throwable arg0 )
+ {
+ super( arg0 );
+ }
+
+ /**
+ * @see RuntimeException
+ */
+ public CyclicDependencyException( String arg0, Throwable arg1 )
+ {
+ super( arg0, arg1 );
+ }
+
+}
Modified: avalon/trunk/runtime/composition/api/src/java/org/apache/avalon/composition/model/DependencyGraph.java
==============================================================================
--- avalon/trunk/runtime/composition/api/src/java/org/apache/avalon/composition/model/DependencyGraph.java (original)
+++ avalon/trunk/runtime/composition/api/src/java/org/apache/avalon/composition/model/DependencyGraph.java Tue Sep 14 14:04:40 2004
@@ -29,25 +29,28 @@
public class DependencyGraph
{
/**
- * Parent Map. Components in the parent
- * Map are potential Providers for services
- * if no model in the current graph satisfies
- * a dependency.
+ * Parent Map. Components in the parent Map are potential Providers for
+ * services if no model in the current graph satisfies a dependency.
*/
private final DependencyGraph m_parent;
/**
- * The set of models declared by the container as available.
- * Used when searching for providers/consumers.
+ * The set of models declared by the container as available. Used when
+ * searching for providers/consumers.
*/
private final ArrayList m_models = new ArrayList();
/**
- * The child {@link DependencyGraph} objects.
- * Possible consumers of services in this assembly.
+ * The child {@link DependencyGraph}objects. Possible consumers of services
+ * in this assembly.
*/
private final ArrayList m_children = new ArrayList();
+ /**
+ * holds the models assembled in order to track circular deps etc.
+ */
+ private ArrayList m_modelsInProgress = new ArrayList();
+
/**
* Creation of a new empty dependency graph.
*/
@@ -57,11 +60,12 @@
}
/**
- * Creation of a new dependecy graph holding a reference to a parent
- * graph. DeploymentModel instances in the parent graph are potential providers
- * for services if no model in current assembly satisfies a dependency.
- *
- * @param parent the parent graph
+ * Creation of a new dependecy graph holding a reference to a parent graph.
+ * DeploymentModel instances in the parent graph are potential providers for
+ * services if no model in current assembly satisfies a dependency.
+ *
+ * @param parent
+ * the parent graph
*/
public DependencyGraph( final DependencyGraph parent )
{
@@ -70,8 +74,9 @@
/**
* Addition of a consumer dependency graph.
- *
- * @param child the child map
+ *
+ * @param child
+ * the child map
*/
public void addChild( final DependencyGraph child )
{
@@ -80,8 +85,9 @@
/**
* Removal of a consumer dependency graph.
- *
- * @param child the child map
+ *
+ * @param child
+ * the child map
*/
public void removeChild( final DependencyGraph child )
{
@@ -90,8 +96,9 @@
/**
* Add a model to current dependency graph.
- *
- * @param model the model to add to the graph
+ *
+ * @param model
+ * the model to add to the graph
*/
public void add( final DeploymentModel model )
{
@@ -103,8 +110,9 @@
/**
* Remove a model from the dependency graph.
- *
- * @param model the model to remove
+ *
+ * @param model
+ * the model to remove
*/
public void remove( final DeploymentModel model )
{
@@ -112,11 +120,10 @@
}
/**
- * Get the serilized graph of {@link DeploymentModel} objects
- * required when starting up the target. This makes sure
- * that all providers are established before their coresponding
- * consumers in the graph.
- *
+ * Get the serilized graph of {@link DeploymentModel}objects required when
+ * starting up the target. This makes sure that all providers are
+ * established before their coresponding consumers in the graph.
+ *
* @return the ordered list of models
*/
public DeploymentModel[] getStartupGraph()
@@ -125,20 +132,18 @@
{
return walkGraph( true );
}
- catch( Throwable e )
+ catch ( Throwable e )
{
- final String error =
- "Unexpect error while resolving startup graph.";
+ final String error = "Unexpect error while resolving startup graph.";
throw new ModelRuntimeException( error, e );
}
}
/**
- * Get the serilized graph of {@link DeploymentModel} instances
- * required when shutting down all the components. This makes
- * sure that all consumer shutdown actions occur before their
- * coresponding providers in graph.
- *
+ * Get the serilized graph of {@link DeploymentModel}instances required
+ * when shutting down all the components. This makes sure that all consumer
+ * shutdown actions occur before their coresponding providers in graph.
+ *
* @return the ordered list of model instances
*/
public DeploymentModel[] getShutdownGraph()
@@ -146,8 +151,8 @@
try
{
return walkGraph( false );
- }
- catch( Throwable e )
+ }
+ catch ( Throwable e )
{
final String error = "Unexpect error while resolving shutdown graph.";
throw new ModelRuntimeException( error, e );
@@ -155,34 +160,38 @@
}
/**
- * Get the serilized graph of {@link DeploymentModel} instances
- * that use services of the specified model.
- *
- * @param model the model
+ * Get the serilized graph of {@link DeploymentModel}instances that use
+ * services of the specified model.
+ *
+ * @param model
+ * the model
* @return the ordered list of consumer model instances
*/
public DeploymentModel[] getConsumerGraph( final DeploymentModel model )
{
- if( m_parent != null ) return m_parent.getConsumerGraph( model );
-
+ if( m_parent != null )
+ {
+ return m_parent.getConsumerGraph( model );
+ }
try
{
DeploymentModel[] graph = getComponentGraph( model, false );
return referencedModels( model, graph );
- }
- catch( Throwable e )
+ }
+ catch ( Throwable e )
{
- final String error =
- "Unexpect error while resolving consumer graph for model: " + model;
+ final String error = "Unexpect error while resolving consumer graph for model: "
+ + model;
throw new ModelRuntimeException( error, e );
}
}
/**
- * Get the serilized graph of {@link DeploymentModel} istances
- * that provide specified model with services.
- *
- * @param model the model
+ * Get the serilized graph of {@link DeploymentModel}istances that provide
+ * specified model with services.
+ *
+ * @param model
+ * the model
* @return the ordered list of providers
*/
public DeploymentModel[] getProviderGraph( final DeploymentModel model )
@@ -190,11 +199,11 @@
try
{
return referencedModels( model, getComponentGraph( model, true ) );
- }
- catch( Throwable e )
+ }
+ catch ( Throwable e )
{
- final String error =
- "Unexpect error while resolving provider graph for: " + model;
+ final String error = "Unexpect error while resolving provider graph for: "
+ + model;
throw new ModelRuntimeException( error, e );
}
}
@@ -202,11 +211,11 @@
/**
* Return an model array that does not include the provided model.
*/
- private DeploymentModel[] referencedModels(
- final DeploymentModel model, DeploymentModel[] models )
+ private DeploymentModel[] referencedModels( final DeploymentModel model,
+ DeploymentModel[] models )
{
ArrayList list = new ArrayList();
- for( int i = 0; i < models.length; i++ )
+ for ( int i = 0; i < models.length; i++ )
{
if( !models[i].equals( model ) )
{
@@ -218,31 +227,31 @@
/**
* Get the graph of a single model.
- *
- * @param model the target model
- * @param providers true if traversing providers, false if consumers
- * @return the list of models
+ *
+ * @param model
+ * the target model
+ * @param providers
+ * true if traversing providers, false if consumers
+ * @return the list of models
*/
- private DeploymentModel[] getComponentGraph(
- final DeploymentModel model, final boolean providers )
+ private DeploymentModel[] getComponentGraph( final DeploymentModel model,
+ final boolean providers )
{
final ArrayList result = new ArrayList();
- visitcomponent( model,
- providers,
- new ArrayList(),
- result );
+ visitcomponent( model, providers, new ArrayList(), result );
final DeploymentModel[] returnValue = new DeploymentModel[result.size()];
return (DeploymentModel[]) result.toArray( returnValue );
}
/**
- * Method to generate an ordering of nodes to traverse.
- * It is expected that the specified components have passed
- * verification tests and are well formed.
- *
- * @param direction true if forward dependencys traced, false if
- * dependencies reversed
+ * Method to generate an ordering of nodes to traverse. It is expected that
+ * the specified components have passed verification tests and are well
+ * formed.
+ *
+ * @param direction
+ * true if forward dependencys traced, false if dependencies
+ * reversed
* @return the ordered model list
*/
private DeploymentModel[] walkGraph( final boolean direction )
@@ -251,87 +260,109 @@
final ArrayList done = new ArrayList();
final int size = m_models.size();
- for( int i = 0; i < size; i++ )
+ for ( int i = 0; i < size; i++ )
{
- final DeploymentModel model =
- (DeploymentModel) m_models.get( i );
+ final DeploymentModel model = (DeploymentModel) m_models.get( i );
- visitcomponent( model,
- direction,
- done,
- result );
+ visitcomponent( model, direction, done, result );
}
final DeploymentModel[] returnValue = new DeploymentModel[result.size()];
+ if( m_modelsInProgress.size() != 0 )
+ {
+ throw new RuntimeException( "there where non-assembled models: "
+ + m_modelsInProgress );
+ }
return (DeploymentModel[]) result.toArray( returnValue );
}
/**
* Visit a model when traversing dependencies.
- *
- * @param model the model
- * @param direction true if walking tree looking for providers, else false
- * @param done those nodes already traversed
- * @param order the order in which nodes have already been
- * traversed
+ *
+ * @param model
+ * the model
+ * @param direction
+ * true if walking tree looking for providers, else false
+ * @param done
+ * those nodes already traversed
+ * @param order
+ * the order in which nodes have already been traversed
*/
private void visitcomponent( final DeploymentModel model,
- final boolean direction,
- final ArrayList done,
- final ArrayList order )
+ final boolean direction, final ArrayList done, final ArrayList order )
{
+ //if circular dependency
+ if( ( model instanceof ComponentModel )
+ && m_modelsInProgress.contains( model ) )
+ {
+ throw new CyclicDependencyException(
+ "Cyclic dependency encoutered in assembly:" + model
+ + "is already in progress stack: "
+ + m_modelsInProgress );
+ }
//If already visited this model return
- if( done.contains( model ) ) return;
-
+ if( done.contains( model ) )
+ {
+ return;
+ }
done.add( model );
-
+ m_modelsInProgress.add( model );
if( direction )
{
visitProviders( model, done, order );
- }
+
+ }
else
{
visitConsumers( model, done, order );
}
+ m_modelsInProgress.remove( model );
order.add( model );
}
/**
- * Traverse graph of components that provide services to
- * the specified model.
- *
- * @param model the model
+ * Traverse graph of components that provide services to the specified
+ * model.
+ *
+ * @param model
+ * the model to be checked
+ * @param done
+ * the list of already checked models
+ * @param order
+ * the order
*/
private void visitProviders( final DeploymentModel model,
- final ArrayList done,
- final ArrayList order )
+ final ArrayList done, final ArrayList order )
{
DeploymentModel[] providers = model.getProviders();
- for( int i = (providers.length - 1); i > -1; i-- )
+ for ( int i = ( providers.length - 1 ); i > -1; i-- )
{
visitcomponent( providers[i], true, done, order );
}
}
/**
- * Traverse all consumers of a model. I.e. all models that use
- * service provided by the supplied model.
- *
- * @param model the DeploymentModel
+ * Traverse all consumers of a model. I.e. all models that use service
+ * provided by the supplied model.
+ *
+ * @param model
+ * the model to be checked
+ * @param done
+ * the list of already checked models
+ * @param order
+ * the order
*/
private void visitConsumers( final DeploymentModel model,
- final ArrayList done,
- final ArrayList order )
+ final ArrayList done, final ArrayList order )
{
final int size = m_models.size();
- for( int i = 0; i < size; i++ )
+ for ( int i = 0; i < size; i++ )
{
- final DeploymentModel other =
- (DeploymentModel) m_models.get( i );
+ final DeploymentModel other = (DeploymentModel) m_models.get( i );
final DeploymentModel[] providers = other.getProviders();
- for( int j = 0; j < providers.length; j++ )
+ for ( int j = 0; j < providers.length; j++ )
{
DeploymentModel provider = providers[j];
if( provider.equals( model ) )
@@ -341,7 +372,7 @@
}
}
final int childCount = m_children.size();
- for( int i = 0; i < childCount; i++ )
+ for ( int i = 0; i < childCount; i++ )
{
final DependencyGraph map = (DependencyGraph) m_children.get( i );
map.visitConsumers( model, done, order );
Modified: avalon/trunk/runtime/composition/impl/build.properties
==============================================================================
--- avalon/trunk/runtime/composition/impl/build.properties (original)
+++ avalon/trunk/runtime/composition/impl/build.properties Tue Sep 14 14:04:40 2004
@@ -1,4 +1,4 @@
project.name = avalon-composition-impl
project.src.main = java
project.home = ../..
-project.system = ../../../central/system
+project.system = ../../../central/system
\ No newline at end of file
Added: avalon/trunk/runtime/composition/impl/etc/test/cyclicdeps.xml
==============================================================================
--- (empty file)
+++ avalon/trunk/runtime/composition/impl/etc/test/cyclicdeps.xml Tue Sep 14 14:04:40 2004
@@ -0,0 +1,11 @@
+
+<container>
+<classloader>
+ <classpath>
+ <artifact>artifact:jar:avalon/test/avalon-test-testcyclic</artifact>
+ </classpath>
+ </classloader>
+ <container name="sub">
+ <component name="test-a" class="org.apache.avalon.test.testcyclic.TestCyclicA"/>
+ </container>
+</container>
Modified: avalon/trunk/runtime/composition/impl/src/java/org/apache/avalon/composition/model/impl/DefaultContainmentModelAssemblyHelper.java
==============================================================================
--- avalon/trunk/runtime/composition/impl/src/java/org/apache/avalon/composition/model/impl/DefaultContainmentModelAssemblyHelper.java (original)
+++ avalon/trunk/runtime/composition/impl/src/java/org/apache/avalon/composition/model/impl/DefaultContainmentModelAssemblyHelper.java Tue Sep 14 14:04:40 2004
@@ -17,6 +17,8 @@
package org.apache.avalon.composition.model.impl;
+import java.util.HashMap;
+import java.util.Hashtable;
import java.util.List;
import java.util.ArrayList;
@@ -61,71 +63,30 @@
// static
//-------------------------------------------------------------------
- private static final Resources REZ =
- ResourceManager.getPackageResources(
- DefaultContainmentModelAssemblyHelper.class );
+ private static final Resources REZ = ResourceManager
+ .getPackageResources( DefaultContainmentModelAssemblyHelper.class );
//-------------------------------------------------------------------
// immutable state
//-------------------------------------------------------------------
private final ContainmentContext m_context;
+
private final DefaultContainmentModel m_model;
//-------------------------------------------------------------------
// constructor
//-------------------------------------------------------------------
- public DefaultContainmentModelAssemblyHelper(
- ContainmentContext context, DefaultContainmentModel model )
+ public DefaultContainmentModelAssemblyHelper( ContainmentContext context,
+ DefaultContainmentModel model )
{
m_context = context;
m_model = model;
}
- //-------------------------------------------------------------------
- // implementation
- //-------------------------------------------------------------------
-
- /**
- * Assemble a target model during which all deployment and runtime
- * dependencies are assigned a provider model.
- *
- * @param model the target model to be assembled
- * @param subject the model requesting the assembly
- */
- public void assembleModel( DeploymentModel model, List subjects )
- throws AssemblyException
- {
- if( null == model )
- {
- throw new NullPointerException( "model" );
- }
- if( null == subjects )
- {
- throw new NullPointerException( "subjects" );
- }
- if( subjects.contains( model ) )
- {
- return;
- }
- if( model.isAssembled() )
- {
- return;
- }
-
- if( model instanceof ComponentModel )
- {
- assembleComponent( (ComponentModel) model, subjects );
- }
- else
- {
- ContainmentModel containment = (ContainmentModel) model;
- containment.assemble( subjects );
- }
- }
-
- private void assembleComponent( ComponentModel model, List subjects ) throws AssemblyException
+ private void assembleComponent( ComponentModel model, List subjects )
+ throws AssemblyException
{
ModelRepository repository = m_context.getModelRepository();
@@ -141,25 +102,23 @@
{
if( null == context.getProvider() )
{
- StagedDeliveryDescriptor phased =
- (StagedDeliveryDescriptor) delivery;
+ StagedDeliveryDescriptor phased = (StagedDeliveryDescriptor) delivery;
Class clazz = phased.getDeliveryInterfaceClass();
try
{
subjects.add( model );
- StageDescriptor stage =
- new StageDescriptor( clazz.getName() );
- DeploymentModel provider =
- findExtensionProvider( repository, stage, subjects );
+ StageDescriptor stage = new StageDescriptor( clazz
+ .getName() );
+ DeploymentModel provider = findExtensionProvider(
+ repository, stage, subjects );
context.setProvider( provider );
}
- catch( Throwable e )
+ catch ( Throwable e )
{
- final String error =
- "Unable to assemble component: "
- + model
- + " due to a component context phase handler establishment failure.";
+ final String error = "Unable to assemble component: "
+ + model
+ + " due to a component context phase handler establishment failure.";
throw new AssemblyException( error, e );
}
finally
@@ -175,7 +134,7 @@
//
StageModel[] stages = model.getStageModels();
- for( int i=0; i<stages.length; i++ )
+ for ( int i = 0; i < stages.length; i++ )
{
StageModel stage = stages[i];
if( null == stage.getProvider() )
@@ -183,16 +142,15 @@
try
{
subjects.add( model );
- DeploymentModel provider =
- findExtensionProvider( repository, stage, subjects );
+ DeploymentModel provider = findExtensionProvider(
+ repository, stage, subjects );
stage.setProvider( provider );
}
- catch( Throwable e )
+ catch ( Throwable e )
{
- final String error =
- "Unable to assemble component: "
- + model
- + " due to a component extension handler establishment failure.";
+ final String error = "Unable to assemble component: "
+ + model
+ + " due to a component extension handler establishment failure.";
throw new AssemblyException( error, e );
}
finally
@@ -207,7 +165,7 @@
//
DependencyModel[] dependencies = model.getDependencyModels();
- for( int i=0; i < dependencies.length; i++ )
+ for ( int i = 0; i < dependencies.length; i++ )
{
DependencyModel dependency = dependencies[i];
if( null == dependency.getProvider() )
@@ -215,17 +173,17 @@
try
{
subjects.add( model );
- DeploymentModel provider =
- findDependencyProvider( repository, dependency, subjects );
+ DeploymentModel provider = findDependencyProvider(
+ repository, dependency, subjects );
dependency.setProvider( provider );
}
- catch( Throwable e )
+ catch ( Throwable e )
{
if( dependency.getDependency().isRequired() )
{
- final String error =
- "Unable to assemble component: " + model
- + " due to a service provider establishment failure.";
+ final String error = "Unable to assemble component: "
+ + model
+ + " due to a service provider establishment failure.";
throw new AssemblyException( error, e );
}
}
@@ -237,47 +195,102 @@
}
}
- private DeploymentModel findDependencyProvider(
- ModelRepository repository, DependencyModel dependency, List subjects )
- throws AssemblyException
+ //-------------------------------------------------------------------
+ // implementation
+ //-------------------------------------------------------------------
+
+ /**
+ * Assemble a target model during which all deployment and runtime
+ * dependencies are assigned a provider model.
+ *
+ * @param model
+ * the target model to be assembled
+ * @param subject
+ * the model requesting the assembly
+ */
+ public void assembleModel( DeploymentModel model, List subjects )
+ throws AssemblyException
{
- String path = dependency.getPath();
- if( null != path )
+ if( null == model )
{
- DeploymentModel model = m_model.getModel( path );
- if( null == model )
- {
- final String error =
- "Could not locate a model at the address: ["
- + path + "] in " + this + ".";
- throw new AssemblyException( error );
- }
- assembleModel( model, subjects );
- return model;
+ throw new NullPointerException( "model" );
+ }
+ if( null == subjects )
+ {
+ throw new NullPointerException( "subjects" );
+ }
+ if( subjects.contains( model ) )
+ {
+ return;
+ }
+ if( model.isAssembled() )
+ {
+ return;
+ }
+
+ if( model instanceof ComponentModel )
+ {
+ assembleComponent( (ComponentModel) model, subjects );
}
else
{
- return findDependencyProvider(
- repository, dependency.getDependency(), subjects );
+ ContainmentModel containment = (ContainmentModel) model;
+ containment.assemble( subjects );
+ }
+ }
+
+ /**
+ * @param dependency
+ * the dependency to check for
+ * @param subjects
+ * the subjects needing the dependency
+ * @throws AssemblyException
+ */
+ private void checkCyclic( DeploymentModel dependency, List subjects )
+ throws AssemblyException
+ {
+ if( subjects.contains( dependency ) )
+ {
+ throw new AssemblyException( "Cyclic Dependency: " + dependency
+ + "is already in subject list " + subjects );
+ }
+ }
+
+ private DeploymentProfile[] findDependencyProfiles(
+ DependencyDescriptor dependency )
+ {
+ TypeRepository repository = m_context.getClassLoaderModel()
+ .getTypeRepository();
+ Type[] types = repository.getTypes( dependency );
+ try
+ {
+ return getProfiles( repository, types );
+ }
+ catch ( TypeUnknownException tue )
+ {
+ // will not happen
+ final String error = "An irrational condition has occured.";
+ throw new ModelRuntimeException( error, tue );
}
}
DeploymentModel findDependencyProvider( DependencyDescriptor dependency )
- throws AssemblyException
+ throws AssemblyException
{
ArrayList list = new ArrayList();
ModelRepository repository = m_context.getModelRepository();
return findDependencyProvider( repository, dependency, list );
}
- private DeploymentModel findDependencyProvider(
- ModelRepository repository, DependencyDescriptor dependency, List subjects )
- throws AssemblyException
+ private DeploymentModel findDependencyProvider( ModelRepository repository,
+ DependencyDescriptor dependency, List subjects )
+ throws AssemblyException
{
- DeploymentModel[] candidates =
- repository.getCandidateProviders( dependency );
+ DeploymentModel[] candidates = repository
+ .getCandidateProviders( dependency );
ModelSelector selector = new DefaultModelSelector();
DeploymentModel model = selector.select( candidates, dependency );
+ //checkCyclic( model, subjects );
if( model != null )
{
assembleModel( model, subjects );
@@ -285,64 +298,96 @@
}
//
- // otherwise, check for any packaged profiles that
+ // otherwise, check for any packaged profiles that
// we could use to construct the model
//
DeploymentProfile[] profiles = findDependencyProfiles( dependency );
ProfileSelector profileSelector = new DefaultProfileSelector();
- DeploymentProfile profile = profileSelector.select( profiles, dependency );
- if( profile != null )
+ DeploymentProfile profile = profileSelector.select( profiles,
+ dependency );
+ if( profile != null )
{
try
{
- DeploymentModel solution = m_model.createDeploymentModel( profile );
+ DeploymentModel solution = m_model
+ .createDeploymentModel( profile );
assembleModel( solution, subjects );
m_model.addModel( solution );
return solution;
}
- catch( AssemblyException ae )
+ catch ( AssemblyException ae )
{
- final String error =
- "Nested assembly failure while attempting to construct model"
- + " for the profile: " + profile + " for the dependency: ["
- + dependency + "].";
+ final String error = "Nested assembly failure while attempting to construct model"
+ + " for the profile: "
+ + profile
+ + " for the dependency: [" + dependency + "].";
throw new AssemblyException( error, ae );
}
- catch( ModelException me )
+ catch ( ModelException me )
{
- final String error =
- "Nested model failure while attempting to add model"
- + " for the profile: " + profile + " for the dependency: ["
- + dependency + "].";
+ final String error = "Nested model failure while attempting to add model"
+ + " for the profile: "
+ + profile
+ + " for the dependency: [" + dependency + "].";
throw new AssemblyException( error, me );
}
}
else
{
- final String error =
- "Unable to locate a service provider for the dependency: [ "
- + dependency + "].";
+ final String error = "Unable to locate a service provider for the dependency: [ "
+ + dependency + "].";
throw new AssemblyException( error );
}
}
- DeploymentModel findServiceProvider( ReferenceDescriptor reference )
- throws AssemblyException
+ private DeploymentModel findDependencyProvider( ModelRepository repository,
+ DependencyModel dependency, List subjects )
+ throws AssemblyException
{
- ArrayList list = new ArrayList();
- ModelRepository repository = m_context.getModelRepository();
- return findServiceProvider( repository, reference, list );
+ String path = dependency.getPath();
+ if( null != path )
+ {
+ DeploymentModel model = m_model.getModel( path );
+ if( null == model )
+ {
+ final String error = "Could not locate a model at the address: ["
+ + path + "] in " + this + ".";
+ throw new AssemblyException( error );
+ }
+ assembleModel( model, subjects );
+ return model;
+ }
+ else
+ {
+ return findDependencyProvider( repository, dependency
+ .getDependency(), subjects );
+ }
+ }
+
+ private DeploymentProfile[] findExtensionProfiles( StageDescriptor stage )
+ {
+ TypeRepository repository = m_context.getClassLoaderModel()
+ .getTypeRepository();
+ Type[] types = repository.getTypes( stage );
+ try
+ {
+ return getProfiles( repository, types );
+ }
+ catch ( TypeUnknownException tue )
+ {
+ // will not happen
+ final String error = "An irrational condition has occured.";
+ throw new ModelRuntimeException( error, tue );
+ }
}
- private DeploymentModel findServiceProvider(
- ModelRepository repository, ReferenceDescriptor reference, List subjects )
- throws AssemblyException
+ private DeploymentModel findExtensionProvider( ModelRepository repository,
+ StageDescriptor stage, List subjects ) throws AssemblyException
{
- DeploymentModel[] candidates =
- repository.getCandidateProviders( reference );
+ DeploymentModel[] candidates = repository.getCandidateProviders( stage );
ModelSelector selector = new DefaultModelSelector();
- DeploymentModel model = selector.select( candidates, reference );
+ DeploymentModel model = selector.select( candidates, stage );
if( model != null )
{
assembleModel( model, subjects );
@@ -350,52 +395,50 @@
}
//
- // otherwise, check for any packaged profiles that
+ // otherwise, check for any packaged profiles that
// we could use to construct the model
//
- DeploymentProfile[] profiles = findServiceProfiles( reference );
+ DeploymentProfile[] profiles = findExtensionProfiles( stage );
ProfileSelector profileSelector = new DefaultProfileSelector();
- DeploymentProfile profile = profileSelector.select( profiles, reference );
- if( profile != null )
+ DeploymentProfile profile = profileSelector.select( profiles, stage );
+ if( profile != null )
{
try
{
- DeploymentModel solution = m_model.createDeploymentModel( profile );
+ DeploymentModel solution = m_model
+ .createDeploymentModel( profile );
assembleModel( solution, subjects );
m_model.addModel( solution );
return solution;
}
- catch( AssemblyException ae )
+ catch ( AssemblyException ae )
{
- final String error =
- "Nested assembly failure while attempting to construct model"
- + " for the profile: [" + profile + "] for the reference: ["
- + reference + "].";
+ final String error = "Nested assembly failure while attempting to construct model"
+ + " for the extension profile: ["
+ + profile
+ + "] for the stage dependency: [" + stage + "].";
throw new AssemblyException( error, ae );
}
- catch( ModelException me )
+ catch ( ModelException me )
{
- final String error =
- "Nested model failure while attempting to add model"
- + " for the profile: " + profile + " for the reference: ["
- + reference + "].";
+ final String error = "Nested model failure while attempting to add model"
+ + " for the extension profile: "
+ + profile
+ + " for the stage dependency: [" + stage + "].";
throw new AssemblyException( error, me );
}
}
else
{
- final String error =
- "Unable to locate a service provider for the reference: [ "
- + reference + "].";
+ final String error = "Unable to locate a extension provider for the stage: [ "
+ + stage + "].";
throw new ProviderNotFoundException( error );
}
}
-
- private DeploymentModel findExtensionProvider(
- ModelRepository repository, StageModel stage, List subjects )
- throws AssemblyException
+ private DeploymentModel findExtensionProvider( ModelRepository repository,
+ StageModel stage, List subjects ) throws AssemblyException
{
String path = stage.getPath();
if( null != path )
@@ -403,9 +446,8 @@
DeploymentModel model = m_model.getModel( path );
if( null == model )
{
- final String error =
- "Could not locate a model at the address: ["
- + path + "] in " + this + ".";
+ final String error = "Could not locate a model at the address: ["
+ + path + "] in " + this + ".";
throw new AssemblyException( error );
}
assembleModel( model, subjects );
@@ -413,18 +455,37 @@
}
else
{
- return findExtensionProvider( repository, stage.getStage(), subjects );
+ return findExtensionProvider( repository, stage.getStage(),
+ subjects );
+ }
+ }
+
+ private DeploymentProfile[] findServiceProfiles(
+ ReferenceDescriptor reference )
+ {
+ TypeRepository repository = m_context.getClassLoaderModel()
+ .getTypeRepository();
+ Type[] types = repository.getTypes( reference );
+ try
+ {
+ return getProfiles( repository, types );
+ }
+ catch ( TypeUnknownException tue )
+ {
+ // will not happen
+ final String error = "An irrational condition has occured.";
+ throw new ModelRuntimeException( error, tue );
}
}
- private DeploymentModel findExtensionProvider(
- ModelRepository repository, StageDescriptor stage, List subjects )
- throws AssemblyException
+ private DeploymentModel findServiceProvider( ModelRepository repository,
+ ReferenceDescriptor reference, List subjects )
+ throws AssemblyException
{
- DeploymentModel[] candidates =
- repository.getCandidateProviders( stage );
+ DeploymentModel[] candidates = repository
+ .getCandidateProviders( reference );
ModelSelector selector = new DefaultModelSelector();
- DeploymentModel model = selector.select( candidates, stage );
+ DeploymentModel model = selector.select( candidates, reference );
if( model != null )
{
assembleModel( model, subjects );
@@ -432,107 +493,65 @@
}
//
- // otherwise, check for any packaged profiles that
+ // otherwise, check for any packaged profiles that
// we could use to construct the model
//
- DeploymentProfile[] profiles = findExtensionProfiles( stage );
+ DeploymentProfile[] profiles = findServiceProfiles( reference );
ProfileSelector profileSelector = new DefaultProfileSelector();
- DeploymentProfile profile = profileSelector.select( profiles, stage );
- if( profile != null )
+ DeploymentProfile profile = profileSelector
+ .select( profiles, reference );
+ if( profile != null )
{
try
{
- DeploymentModel solution = m_model.createDeploymentModel( profile );
+ DeploymentModel solution = m_model
+ .createDeploymentModel( profile );
assembleModel( solution, subjects );
m_model.addModel( solution );
return solution;
}
- catch( AssemblyException ae )
+ catch ( AssemblyException ae )
{
- final String error =
- "Nested assembly failure while attempting to construct model"
- + " for the extension profile: [" + profile
- + "] for the stage dependency: ["
- + stage + "].";
+ final String error = "Nested assembly failure while attempting to construct model"
+ + " for the profile: ["
+ + profile
+ + "] for the reference: [" + reference + "].";
throw new AssemblyException( error, ae );
}
- catch( ModelException me )
+ catch ( ModelException me )
{
- final String error =
- "Nested model failure while attempting to add model"
- + " for the extension profile: " + profile
- + " for the stage dependency: ["
- + stage + "].";
+ final String error = "Nested model failure while attempting to add model"
+ + " for the profile: "
+ + profile
+ + " for the reference: [" + reference + "].";
throw new AssemblyException( error, me );
}
}
else
{
- final String error =
- "Unable to locate a extension provider for the stage: [ "
- + stage + "].";
+ final String error = "Unable to locate a service provider for the reference: [ "
+ + reference + "].";
throw new ProviderNotFoundException( error );
}
}
- private DeploymentProfile[] findExtensionProfiles( StageDescriptor stage )
- {
- TypeRepository repository = m_context.getClassLoaderModel().getTypeRepository();
- Type[] types = repository.getTypes( stage );
- try
- {
- return getProfiles( repository, types );
- }
- catch( TypeUnknownException tue )
- {
- // will not happen
- final String error = "An irrational condition has occured.";
- throw new ModelRuntimeException( error, tue );
- }
- }
-
- private DeploymentProfile[] findDependencyProfiles( DependencyDescriptor dependency )
- {
- TypeRepository repository = m_context.getClassLoaderModel().getTypeRepository();
- Type[] types = repository.getTypes( dependency );
- try
- {
- return getProfiles( repository, types );
- }
- catch( TypeUnknownException tue )
- {
- // will not happen
- final String error = "An irrational condition has occured.";
- throw new ModelRuntimeException( error, tue );
- }
- }
-
- private DeploymentProfile[] findServiceProfiles( ReferenceDescriptor reference )
+ DeploymentModel findServiceProvider( ReferenceDescriptor reference )
+ throws AssemblyException
{
- TypeRepository repository = m_context.getClassLoaderModel().getTypeRepository();
- Type[] types = repository.getTypes( reference );
- try
- {
- return getProfiles( repository, types );
- }
- catch( TypeUnknownException tue )
- {
- // will not happen
- final String error = "An irrational condition has occured.";
- throw new ModelRuntimeException( error, tue );
- }
+ ArrayList list = new ArrayList();
+ ModelRepository repository = m_context.getModelRepository();
+ return findServiceProvider( repository, reference, list );
}
- private DeploymentProfile[] getProfiles( TypeRepository repository, Type[] types )
- throws TypeUnknownException
+ private DeploymentProfile[] getProfiles( TypeRepository repository,
+ Type[] types ) throws TypeUnknownException
{
ArrayList list = new ArrayList();
- for( int i=0; i<types.length; i++ )
+ for ( int i = 0; i < types.length; i++ )
{
- DeploymentProfile[] profiles =
- repository.getProfiles( types[i] );
- for( int j=0; j<profiles.length; j++ )
+ DeploymentProfile[] profiles = repository.getProfiles( types[i] );
+ for ( int j = 0; j < profiles.length; j++ )
{
list.add( profiles[j] );
}
Added: avalon/trunk/runtime/composition/impl/src/test/org/apache/avalon/composition/model/impl/CyclicDepsTestCase.java
==============================================================================
--- (empty file)
+++ avalon/trunk/runtime/composition/impl/src/test/org/apache/avalon/composition/model/impl/CyclicDepsTestCase.java Tue Sep 14 14:04:40 2004
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2004 Apache Software Foundation
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.avalon.composition.model.impl;
+
+import org.apache.avalon.composition.model.AssemblyException;
+import org.apache.avalon.composition.model.ContainmentModel;
+import org.apache.avalon.composition.model.CyclicDependencyException;
+import org.apache.avalon.composition.model.DeploymentModel;
+import org.apache.avalon.composition.model.ModelRuntimeException;
+import org.apache.avalon.composition.model.test.AbstractTestCase;
+import org.apache.avalon.framework.logger.ConsoleLogger;
+
+/**
+ * checks that cyclic dependencies in the service declarations are properlly
+ * found and notified.
+ */
+public class CyclicDepsTestCase extends AbstractTestCase
+{
+ //-------------------------------------------------------
+ // constructor
+ //-------------------------------------------------------
+ /**
+ * the contructor
+ */
+ public CyclicDepsTestCase()
+ {
+ super();
+ }
+
+ /**
+ * @param container
+ * the container to be printed
+ */
+ private void printStartup( ContainmentModel container )
+ {
+ DeploymentModel[] startup = container.getStartupGraph();
+ for ( int i = 0; i < startup.length; i++ )
+ {
+ DeploymentModel current = startup[i];
+ if( current instanceof ContainmentModel )
+ {
+ ContainmentModel currentContainer = (ContainmentModel) current;
+ try
+ {
+ currentContainer.assemble();
+ printStartup( currentContainer );
+ }
+ catch ( AssemblyException e )
+ {
+ e.printStackTrace();
+ }
+
+ }
+ System.out.println( current.getPath() + current.getName() );
+ DeploymentModel[] deps = current.getProviders();
+
+ for ( int j = 0; j < deps.length; j++ )
+ {
+
+ System.out.println( "\tdep<-" + deps[j].getPath()
+ + deps[j].getName() );
+
+ }
+ }
+ }
+
+ public void setUp() throws Exception
+ {
+ m_model = super.setUp( "cyclicdeps.xml" );
+ ConsoleLogger logger = new ConsoleLogger( ConsoleLogger.LEVEL_INFO );
+ }
+
+ //-------------------------------------------------------
+ // tests
+ //-------------------------------------------------------
+
+ /**
+ * Validate the the included block was created.
+ */
+ public void testCyclicDependency() throws Throwable
+ {
+ try
+ {
+
+ ContainmentModel root = (ContainmentModel) m_model.getModel( "/" );
+
+ root.assemble();
+ printStartup( root );
+ fail( "an exception should have been thrown" );
+
+ }
+ catch ( ModelRuntimeException e )
+ {
+ //this should be thrown.
+ }
+ }
+}
\ No newline at end of file
Modified: avalon/trunk/runtime/composition/impl/src/test/org/apache/avalon/composition/model/test/AbstractTestCase.java
==============================================================================
--- avalon/trunk/runtime/composition/impl/src/test/org/apache/avalon/composition/model/test/AbstractTestCase.java (original)
+++ avalon/trunk/runtime/composition/impl/src/test/org/apache/avalon/composition/model/test/AbstractTestCase.java Tue Sep 14 14:04:40 2004
@@ -74,7 +74,6 @@
BASEDIR = getWorkDir();
SYS_CONF = new File( BASEDIR, "system/kernel.xml" ).getAbsoluteFile();
SECURITY_BUILDER = new XMLSecurityProfileBuilder();
- System.out.println( "security.policy=" + System.getProperty( "java.security.policy" ) );
}
private static File getWorkDir()
@@ -84,12 +83,22 @@
{
return new File( path );
}
- else
+ path = System.getProperty( "basedir" );
+ if( path != null )
{
- path = System.getProperty( "basedir" );
File root = new File( path );
return new File( root, "target/test-classes" );
}
+
+ //still no success resort to user.dir
+ if( !(path != null) )
+ {
+ path = System.getProperty( "user.dir" );
+ }
+ if( null != path )
+ {
+ return new File( path );
+ } return null;
}
//-------------------------------------------------------
@@ -174,7 +183,7 @@
//
File source = new File( BASEDIR, path );
-
+ System.out.println("loading " + source.toURL());
return modelFactory.createRootContainmentModel( source.toURL() );
}
Modified: avalon/trunk/runtime/index.xml
==============================================================================
--- avalon/trunk/runtime/index.xml (original)
+++ avalon/trunk/runtime/index.xml Tue Sep 14 14:04:40 2004
@@ -389,6 +389,19 @@
</plugins>
</project>
+ <project basedir="test/testcyclic">
+ <info>
+ <group>avalon/test</group>
+ <name>avalon-test-testcyclic</name>
+ </info>
+ <dependencies>
+ <include key="avalon-framework-api"/>
+ </dependencies>
+ <plugins>
+ <include key="avalon-meta-tools"/>
+ </plugins>
+ </project>
+
<project basedir="test/includes">
<info>
<group>avalon/test</group>
@@ -689,9 +702,10 @@
<include key="avalon-util-extension-impl"/>
<include key="avalon-util-lifecycle"/>
<include key="avalon-logging-impl" build="false" test="true"/>
- <include key="avalon-test-dynamics" build="false" test="false"/>
- <include key="avalon-test-includes" build="false" test="true"/>
- <include key="avalon-logging-test" build="false" test="false"/>
+ <include key="avalon-test-dynamics" build="false" runtime="false" test="false"/>
+ <include key="avalon-test-includes" build="false" runtime="false" test="true"/>
+ <include key="avalon-test-testcyclic" build="false" runtime="false" test="false"/>
+ <include key="avalon-logging-test" build="false" runtime="false" test="false"/>
</dependencies>
</project>
Added: avalon/trunk/runtime/test/testcyclic/build.properties
==============================================================================
--- (empty file)
+++ avalon/trunk/runtime/test/testcyclic/build.properties Tue Sep 14 14:04:40 2004
@@ -0,0 +1,3 @@
+
+project.home = ../..
+project.system = ../../../central/system
Added: avalon/trunk/runtime/test/testcyclic/build.xml
==============================================================================
--- (empty file)
+++ avalon/trunk/runtime/test/testcyclic/build.xml Tue Sep 14 14:04:40 2004
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<project name="avalon-test-testcyclic" default="install" basedir="."
+ xmlns:x="antlib:org.apache.avalon.tools" >
+
+ <property file="build.properties"/>
+ <import file="${project.system}/build/standard.xml"/>
+
+</project>
Added: avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/testcyclic/A.java
==============================================================================
--- (empty file)
+++ avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/testcyclic/A.java Tue Sep 14 14:04:40 2004
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2004 Apache Software Foundation
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.avalon.test.testcyclic;
+
+public interface A
+{
+}
Added: avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/testcyclic/B.java
==============================================================================
--- (empty file)
+++ avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/testcyclic/B.java Tue Sep 14 14:04:40 2004
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2004 Apache Software Foundation
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.avalon.test.testcyclic;
+
+public interface B
+{
+}
Added: avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/testcyclic/TestCyclicA.java
==============================================================================
--- (empty file)
+++ avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/testcyclic/TestCyclicA.java Tue Sep 14 14:04:40 2004
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2004 Apache Software Foundation
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.avalon.test.testcyclic;
+
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+
+/**
+ * @avalon.component name="testcyclic" lifestyle="singleton"
+ * @avalon.service type="org.apache.avalon.test.testcyclic.A"
+ */
+public class TestCyclicA extends AbstractLogEnabled
+ implements A
+{
+ /**
+ * @avalon.dependency key="CyclicB" type="org.apache.avalon.test.testcyclic.B"
+ */
+ public void service( ServiceManager manager ) throws ServiceException
+ {
+ getLogger().info( "service stage" );
+ Logger logger = getLogger().getChildLogger( "service" );
+ logger.info( "lookup B" );
+ manager.lookup( "CyclicB" );
+ logger.info( "ok" );
+ }
+}
Added: avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/testcyclic/TestCyclicB.java
==============================================================================
--- (empty file)
+++ avalon/trunk/runtime/test/testcyclic/src/main/org/apache/avalon/test/testcyclic/TestCyclicB.java Tue Sep 14 14:04:40 2004
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2004 Apache Software Foundation
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.avalon.test.testcyclic;
+
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+
+/**
+ * @avalon.component name="cyclic-b" lifestyle="singleton"
+ * @avalon.service type="org.apache.avalon.test.testcyclic.B"
+ */
+public class TestCyclicB extends AbstractLogEnabled
+ implements B
+{
+ /**
+ * @avalon.dependency key="CyclicA" type="org.apache.avalon.test.testcyclic.A"
+ */
+ public void service( ServiceManager manager ) throws ServiceException
+ {
+ getLogger().info( "service stage" );
+ Logger logger = getLogger().getChildLogger( "service" );
+ logger.info( "lookup A" );
+ manager.lookup( "CyclicA" );
+ logger.info( "ok" );
+ }
+}