You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by gn...@apache.org on 2018/01/19 09:44:58 UTC

svn commit: r1821610 - in /aries/trunk/blueprint: blueprint-bundle/ blueprint-core/ blueprint-core/src/main/java/org/apache/aries/blueprint/container/ blueprint-core/src/main/java/org/apache/aries/blueprint/di/ blueprint-core/src/main/java/org/apache/a...

Author: gnodet
Date: Fri Jan 19 09:44:57 2018
New Revision: 1821610

URL: http://svn.apache.org/viewvc?rev=1821610&view=rev
Log:
[ARIES-1535][ARIES-1536] Implement new policies for reference lifecycle and damping

Added:
    aries/trunk/blueprint/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/impl/blueprint-ext-1.6.xsd
    aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/DampingPolicyTest.java
    aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/LifecyclePolicyTest.java
Modified:
    aries/trunk/blueprint/blueprint-bundle/pom.xml
    aries/trunk/blueprint/blueprint-core/pom.xml
    aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AbstractServiceReferenceRecipe.java
    aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
    aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintRepository.java
    aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ReferenceListRecipe.java
    aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ReferenceRecipe.java
    aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/SatisfiableRecipe.java
    aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/di/DependentComponentFactoryRecipe.java
    aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/ext/impl/ExtNamespaceHandler.java
    aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/services/ExtendedBlueprintContainer.java
    aries/trunk/blueprint/blueprint-core/src/main/resources/OSGI-INF/blueprint/blueprint-ext.xml
    aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/ExtendedReferenceMetadata.java
    aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/mutable/MutableReferenceMetadata.java
    aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/reflect/ReferenceMetadataImpl.java
    aries/trunk/blueprint/itests/blueprint-itests/pom.xml

Modified: aries/trunk/blueprint/blueprint-bundle/pom.xml
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-bundle/pom.xml?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-bundle/pom.xml (original)
+++ aries/trunk/blueprint/blueprint-bundle/pom.xml Fri Jan 19 09:44:57 2018
@@ -122,7 +122,7 @@
         <dependency>
             <groupId>org.apache.aries.blueprint</groupId>
             <artifactId>org.apache.aries.blueprint.core</artifactId>
-            <version>1.8.3-SNAPSHOT</version>
+            <version>1.9.0-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

Modified: aries/trunk/blueprint/blueprint-core/pom.xml
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/pom.xml?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/pom.xml (original)
+++ aries/trunk/blueprint/blueprint-core/pom.xml Fri Jan 19 09:44:57 2018
@@ -32,7 +32,7 @@
     <artifactId>org.apache.aries.blueprint.core</artifactId>
     <packaging>bundle</packaging>
     <name>Apache Aries Blueprint Core</name>
-    <version>1.8.4-SNAPSHOT</version>
+    <version>1.9.0-SNAPSHOT</version>
     <description>
         This bundle contains the core implementation of Blueprint
         along with the "ext" namespace handler.
@@ -92,7 +92,7 @@
         </aries.osgi.include.resource>
         <blueprint.annotation.api.version>1.0.0</blueprint.annotation.api.version>
         <blueprint.api.version>1.0.0</blueprint.api.version>
-        <blueprint.parser.version>1.4.0</blueprint.parser.version>
+        <blueprint.parser.version>1.5.0-SNAPSHOT</blueprint.parser.version>
         <proxy.api.version>1.1.0</proxy.api.version>
         <proxy.impl.version>1.1.0</proxy.impl.version>
         <quiesce.api.version>1.0.0</quiesce.api.version>
@@ -106,7 +106,7 @@
             <properties>
                 <blueprint.annotation.api.version>1.0.1</blueprint.annotation.api.version>
                 <blueprint.api.version>1.0.1</blueprint.api.version>
-                <blueprint.parser.version>1.4.0</blueprint.parser.version>
+                <blueprint.parser.version>1.5.0-SNAPSHOT</blueprint.parser.version>
                 <proxy.api.version>1.1.0</proxy.api.version>
                 <proxy.impl.version>1.1.0</proxy.impl.version>
                 <quiesce.api.version>1.0.0</quiesce.api.version>

Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AbstractServiceReferenceRecipe.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AbstractServiceReferenceRecipe.java?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AbstractServiceReferenceRecipe.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AbstractServiceReferenceRecipe.java Fri Jan 19 09:44:57 2018
@@ -358,8 +358,8 @@ public abstract class AbstractServiceRef
             synchronized (tracked) {
                 satisfied = optional || !tracked.isEmpty();
             }
-            setSatisfied(satisfied);
             track(ref);
+            setSatisfied(satisfied);
         }
     }
 

Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java Fri Jan 19 09:44:57 2018
@@ -656,7 +656,16 @@ public class BlueprintContainerImpl
         }
         LOGGER.debug("Notified satisfaction {} in bundle {}/{}: {}",
                 satisfiable.getName(), bundle.getSymbolicName(), getBundle().getVersion(), satisfiable.isSatisfied());
-        if (state == State.Create || state == State.Created ) {
+
+        if ((state == State.Create || state == State.Created) && satisfiable.isStaticLifecycle()) {
+            if (satisfiable.isSatisfied()) {
+                repository.reCreateInstance(satisfiable.getName());
+            }
+            else {
+                repository.destroyInstance(satisfiable.getName());
+            }
+        }
+        else if (state == State.Create || state == State.Created) {
             Map<String, List<SatisfiableRecipe>> dependencies = getSatisfiableDependenciesMap();
             for (Map.Entry<String, List<SatisfiableRecipe>> entry : dependencies.entrySet()) {
                 String name = entry.getKey();

Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintRepository.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintRepository.java?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintRepository.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintRepository.java Fri Jan 19 09:44:57 2018
@@ -87,6 +87,8 @@ public class BlueprintRepository impleme
      * stack is used to detect circular dependencies.
      */
     private final ThreadLocal<LinkedList<Recipe>> stack = new ThreadLocal<LinkedList<Recipe>>();
+
+    private Map<String, Set<String>> invertedDependencies;
     
     public BlueprintRepository(ExtendedBlueprintContainer container) {
         blueprintContainer = container;
@@ -124,6 +126,7 @@ public class BlueprintRepository impleme
             throw new ComponentDefinitionException("Name " + name + " is already registered to instance " + getInstance(name));
         }
         recipes.put(name, recipe);
+        invertedDependencies = null;
     }
     
     public void removeRecipe(String name) {
@@ -131,6 +134,7 @@ public class BlueprintRepository impleme
             throw new ComponentDefinitionException("Name " + name + " is already instanciated as " + getInstance(name) + " and cannot be removed.");
 
         recipes.remove(name);
+        invertedDependencies = null;
     }
 
     private Object convert(String name, Object instance) throws ComponentDefinitionException {
@@ -214,6 +218,107 @@ public class BlueprintRepository impleme
         }
     }
 
+    private static <S, T> void addToMapSet(Map<S, Set<T>> map, S key, T value) {
+        Set<T> values = map.get(key);
+        if (values == null) {
+            values = new HashSet<T>();
+            map.put(key, values);
+        }
+        values.add(value);
+    }
+
+    private Map<String, Set<String>> getInvertedDependencies() {
+        if (invertedDependencies == null) {
+            Map<String, Set<String>> deps = new HashMap<String, Set<String>>();
+            for (String n : recipes.keySet()) {
+                Recipe r = recipes.get(n);
+                Set<Recipe> d = new HashSet<Recipe>();
+                internalGetAllRecipes(d, r);
+                for (Recipe e : d) {
+                    addToMapSet(deps, e.getName(), r.getName());
+                }
+            }
+            invertedDependencies = deps;
+        }
+        return invertedDependencies;
+    }
+
+    public void reCreateInstance(String name) {
+        ExecutionContext oldContext = ExecutionContext.Holder.setContext(this);
+        try {
+            Set<String> toCreate = new HashSet<String>();
+            Set<String> deps = getInvertedDependencies().get(name);
+            if (deps == null) {
+                throw new NoSuchComponentException(name);
+            }
+            for (String dep : deps) {
+                boolean ok = true;
+                for (SatisfiableRecipe r : getAllRecipes(SatisfiableRecipe.class, dep)) {
+                    if (!r.isSatisfied()) {
+                        ok = false;
+                        break;
+                    }
+                }
+                if (ok) {
+                    toCreate.add(dep);
+                }
+            }
+            createInstances(toCreate);
+            for (String n : toCreate) {
+                Recipe r = recipes.get(n);
+                if (r instanceof ServiceRecipe) {
+                    ServiceRecipe sr = (ServiceRecipe) r;
+                    if (!sr.isRegistered()) {
+                        sr.register();
+                    }
+                }
+            }
+        } finally {
+            ExecutionContext.Holder.setContext(oldContext);
+        }
+    }
+
+    public void destroyInstance(String name) {
+        ExecutionContext oldContext = ExecutionContext.Holder.setContext(this);
+        try {
+            Map<Recipe, Future<Object>> toDestroy = new LinkedHashMap<Recipe, Future<Object>>();
+            doGetInstancesToDestroy(toDestroy, name);
+            for (Map.Entry<Recipe, Future<Object>> entry : toDestroy.entrySet()) {
+                try {
+                    Recipe recipe = entry.getKey();
+                    Future<Object> future = entry.getValue();
+                    Object instance = future.get();
+                    if (instance != null) {
+                        recipe.destroy(instance);
+                    }
+                } catch (Exception e) {
+                    throw new ComponentDefinitionException("Error destroying instance", e);
+                }
+            }
+        } finally {
+            ExecutionContext.Holder.setContext(oldContext);
+        }
+    }
+
+    protected void doGetInstancesToDestroy(Map<Recipe, Future<Object>> toDestroy, String name) {
+        Recipe recipe = recipes.get(name);
+        if (recipe != null) {
+            if (recipe instanceof ServiceRecipe) {
+                ((ServiceRecipe) recipe).unregister();
+            }
+            Future<Object> future = instances.remove(name);
+            if (future != null && future.isDone()) {
+                Set<String> deps = getInvertedDependencies().get(name);
+                for (String dep : deps) {
+                    doGetInstancesToDestroy(toDestroy, dep);
+                }
+                toDestroy.put(recipe, future);
+            }
+        } else {
+            throw new NoSuchComponentException(name);
+        }
+    }
+
     /*
      * This method should not be called directly, only from one of the getAllRecipes() methods.
      */

Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ReferenceListRecipe.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ReferenceListRecipe.java?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ReferenceListRecipe.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ReferenceListRecipe.java Fri Jan 19 09:44:57 2018
@@ -64,6 +64,11 @@ public class ReferenceListRecipe extends
     }
 
     @Override
+    public boolean isStaticLifecycle() {
+        return false;
+    }
+
+    @Override
     protected Object internalCreate() throws ComponentDefinitionException {
         try {
             if (explicitDependencies != null) {

Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ReferenceRecipe.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ReferenceRecipe.java?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ReferenceRecipe.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ReferenceRecipe.java Fri Jan 19 09:44:57 2018
@@ -67,6 +67,8 @@ public class ReferenceRecipe extends Abs
 
     private final Collection<Class<?>> proxyChildBeanClasses;
     private final Collection<WeakReference<Voidable>> proxiedChildren;
+
+    private final boolean staticLifecycle;
     
     public ReferenceRecipe(String name,
                            ExtendedBlueprintContainer blueprintContainer,
@@ -76,15 +78,25 @@ public class ReferenceRecipe extends Abs
                            List<Recipe> explicitDependencies) {
         super(name, blueprintContainer, metadata, filterRecipe, listenersRecipe, explicitDependencies);
         this.metadata = metadata;
-        if(metadata instanceof ExtendedReferenceMetadata) 
-            proxyChildBeanClasses = ((ExtendedReferenceMetadata) metadata).getProxyChildBeanClasses();
-        else 
+        if (metadata instanceof ExtendedReferenceMetadata) {
+            staticLifecycle = ((ExtendedReferenceMetadata) metadata).getLifecycle()
+                    == ExtendedReferenceMetadata.LIFECYCLE_STATIC;
+            if (!staticLifecycle) {
+                proxyChildBeanClasses = ((ExtendedReferenceMetadata) metadata).getProxyChildBeanClasses();
+                if (proxyChildBeanClasses != null) {
+                    proxiedChildren = new ArrayList<WeakReference<Voidable>>();
+                } else {
+                    proxiedChildren = null;
+                }
+            } else {
+                proxyChildBeanClasses = null;
+                proxiedChildren = null;
+            }
+        } else {
+            staticLifecycle = false;
             proxyChildBeanClasses = null;
-        
-        if (proxyChildBeanClasses != null)
-            proxiedChildren = new ArrayList<WeakReference<Voidable>>();
-        else
             proxiedChildren = null;
+        }
     }
 
     @Override
@@ -104,19 +116,24 @@ public class ReferenceRecipe extends Abs
                 interfaces.addAll(loadAllClasses(((ExtendedReferenceMetadata)metadata).getExtraInterfaces()));
             }
 
-            proxy = createProxy(new ServiceDispatcher(), interfaces);
+            Object result;
+            if (isStaticLifecycle()) {
+                result = getService();
+            }
+            else {
+                proxy = createProxy(new ServiceDispatcher(), interfaces);
 
-            // Add partially created proxy to the context
-            ServiceProxyWrapper wrapper = new ServiceProxyWrapper();
+                // Add partially created proxy to the context
+                result = new ServiceProxyWrapper();
+            }
 
-            addPartialObject(wrapper);
+            addPartialObject(result);
 
             // Handle initial references
             createListeners();
             updateListeners();            
 
-            // Return a ServiceProxy that can injection of references or proxies can be done correctly
-            return wrapper;
+            return result;
         } catch (ComponentDefinitionException e) {
             throw e;
         } catch (Throwable t) {
@@ -141,18 +158,21 @@ public class ReferenceRecipe extends Abs
     }
 
     protected void track(ServiceReference ref) {
-        // TODO: make this behavior configurable through a custom attribute
-        // TODO:      policy = sticky | replace
+        boolean replace;
+        if (metadata instanceof ExtendedReferenceMetadata) {
+            replace = ((ExtendedReferenceMetadata) metadata).getDamping()
+                        == ExtendedReferenceMetadata.DAMPING_GREEDY;
+        } else {
+            replace = false;
+        }
         synchronized (monitor) {
-            if (trackedServiceReference == null) {
+            if (trackedServiceReference == null || replace) {
                 retrack();
             }
         }
     }
 
     protected void untrack(ServiceReference ref) {
-        // TODO: make this behavior configurable through a custom attribute
-        // TODO:      policy = sticky | replace
         synchronized (monitor) {
             if (trackedServiceReference == ref) {
                 retrack();
@@ -160,7 +180,12 @@ public class ReferenceRecipe extends Abs
         }
     }
 
-    private void bind(ServiceReference ref) {
+    @Override
+    public boolean isStaticLifecycle() {
+        return staticLifecycle;
+    }
+
+    protected void bind(ServiceReference ref) {
         LOGGER.debug("Binding reference {} to {}", getName(), ref);
         synchronized (monitor) {
             ServiceReference oldReference = trackedServiceReference;

Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/SatisfiableRecipe.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/SatisfiableRecipe.java?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/SatisfiableRecipe.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/SatisfiableRecipe.java Fri Jan 19 09:44:57 2018
@@ -49,4 +49,6 @@ public interface SatisfiableRecipe exten
 
     String getOsgiFilter();
 
+    boolean isStaticLifecycle();
+
 }

Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/di/DependentComponentFactoryRecipe.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/di/DependentComponentFactoryRecipe.java?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/di/DependentComponentFactoryRecipe.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/di/DependentComponentFactoryRecipe.java Fri Jan 19 09:44:57 2018
@@ -41,6 +41,11 @@ public class DependentComponentFactoryRe
         super(name, metadata, container, dependencies);
     }
 
+    @Override
+    public boolean isStaticLifecycle() {
+        return false;
+    }
+
     public String getOsgiFilter() {
         return getMetadata().getDependencyDescriptor();
     }

Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/ext/impl/ExtNamespaceHandler.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/ext/impl/ExtNamespaceHandler.java?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/ext/impl/ExtNamespaceHandler.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/ext/impl/ExtNamespaceHandler.java Fri Jan 19 09:44:57 2018
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.aries.blueprint.ExtendedReferenceListMetadata;
+import org.apache.aries.blueprint.ExtendedReferenceMetadata;
 import org.apache.aries.blueprint.ParserContext;
 import org.apache.aries.blueprint.ext.PlaceholdersUtils;
 import org.apache.aries.blueprint.ext.PropertyPlaceholder;
@@ -76,6 +77,7 @@ public class ExtNamespaceHandler impleme
     public static final String BLUEPRINT_EXT_NAMESPACE_V1_3 = "http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.3.0";
     public static final String BLUEPRINT_EXT_NAMESPACE_V1_4 = "http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.4.0";
     public static final String BLUEPRINT_EXT_NAMESPACE_V1_5 = "http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.5.0";
+    public static final String BLUEPRINT_EXT_NAMESPACE_V1_6 = "http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.6.0";
 
     public static final String PROPERTY_PLACEHOLDER_ELEMENT = "property-placeholder";
     public static final String DEFAULT_PROPERTIES_ELEMENT = "default-properties";
@@ -114,7 +116,16 @@ public class ExtNamespaceHandler impleme
     
     public static final String BEAN = "bean";
     public static final String REFERENCE = "reference";
-    
+
+    public static final String DAMPING_ATTRIBUTE = "damping";
+
+    public static final String DAMPING_RELUCTANT = "reluctant";
+    public static final String DAMPING_GREEDY = "greedy";
+
+    public static final String LIFECYCLE_ATTRIBUTE = "lifecycle";
+
+    public static final String LIFECYCLE_DYNAMIC = "dynamic";
+    public static final String LIFECYCLE_STATIC = "static";
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ExtNamespaceHandler.class);
 
@@ -139,6 +150,8 @@ public class ExtNamespaceHandler impleme
             return getClass().getResource("blueprint-ext-1.4.xsd");
         } else if (BLUEPRINT_EXT_NAMESPACE_V1_5.equals(namespace)) {
             return getClass().getResource("blueprint-ext-1.5.xsd");
+        } else if (BLUEPRINT_EXT_NAMESPACE_V1_6.equals(namespace)) {
+            return getClass().getResource("blueprint-ext-1.6.xsd");
         } else if ("http://www.w3.org/XML/1998/namespace".equals(namespace)) {
             return getClass().getResource("xml.xsd");
         }
@@ -150,7 +163,8 @@ public class ExtNamespaceHandler impleme
             || BLUEPRINT_EXT_NAMESPACE_V1_2.equals(e)
             || BLUEPRINT_EXT_NAMESPACE_V1_3.equals(e)
             || BLUEPRINT_EXT_NAMESPACE_V1_4.equals(e)
-            || BLUEPRINT_EXT_NAMESPACE_V1_5.equals(e);            
+            || BLUEPRINT_EXT_NAMESPACE_V1_5.equals(e)
+            || BLUEPRINT_EXT_NAMESPACE_V1_6.equals(e);
     }
 
     public Set<Class> getManagedClasses() {
@@ -191,6 +205,10 @@ public class ExtNamespaceHandler impleme
         } else if (node instanceof Element && nodeNameEquals(node, REFERENCE)) {
             RefMetadata rd = context.parseElement(RefMetadata.class, component, (Element)node);
             return createReference(context, rd.getComponentId());
+        } else if (node instanceof Attr && nodeNameEquals(node, DAMPING_ATTRIBUTE)) {
+            return decorateDamping(node, component, context);
+        } else if (node instanceof Attr && nodeNameEquals(node, LIFECYCLE_ATTRIBUTE)) {
+            return decorateLifecycle(node, component, context);
         } else {
             throw new ComponentDefinitionException("Unsupported node: " + node.getNodeName());
         }
@@ -309,6 +327,42 @@ public class ExtNamespaceHandler impleme
         return component;
     }
 
+    private ComponentMetadata decorateDamping(Node node, ComponentMetadata component, ParserContext context) {
+        if (!(component instanceof ReferenceMetadata)) {
+            throw new ComponentDefinitionException("Attribute " + node.getNodeName() + " can only be used on a <reference> element");
+        }
+        if (!(component instanceof MutableReferenceMetadata)) {
+            throw new ComponentDefinitionException("Expected an instance of MutableReferenceMetadata");
+        }
+        int damping = ExtendedReferenceMetadata.DAMPING_GREEDY;
+        String value = ((Attr) node).getValue();
+        if (DAMPING_RELUCTANT.equals(value)) {
+            damping = ExtendedReferenceMetadata.DAMPING_RELUCTANT;
+        } else if (!DAMPING_GREEDY.equals(value)) {
+            throw new ComponentDefinitionException("Unknown damping method: " + value);
+        }
+        ((MutableReferenceMetadata) component).setDamping(damping);
+        return component;
+    }
+
+    private ComponentMetadata decorateLifecycle(Node node, ComponentMetadata component, ParserContext context) {
+        if (!(component instanceof ReferenceMetadata)) {
+            throw new ComponentDefinitionException("Attribute " + node.getNodeName() + " can only be used on a <reference> element");
+        }
+        if (!(component instanceof MutableReferenceMetadata)) {
+            throw new ComponentDefinitionException("Expected an instance of MutableReferenceMetadata");
+        }
+        int lifecycle = ExtendedReferenceMetadata.LIFECYCLE_DYNAMIC;
+        String value = ((Attr) node).getValue();
+        if (LIFECYCLE_STATIC.equals(value)) {
+            lifecycle = ExtendedReferenceMetadata.LIFECYCLE_STATIC;
+        } else if (!LIFECYCLE_DYNAMIC.equals(value)) {
+            throw new ComponentDefinitionException("Unknown lifecycle method: " + value);
+        }
+        ((MutableReferenceMetadata) component).setLifecycle(lifecycle);
+        return component;
+    }
+
     private Metadata parsePropertyPlaceholder(ParserContext context, Element element) {
         MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
         metadata.setProcessor(true);

Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/services/ExtendedBlueprintContainer.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/services/ExtendedBlueprintContainer.java?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/services/ExtendedBlueprintContainer.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/services/ExtendedBlueprintContainer.java Fri Jan 19 09:44:57 2018
@@ -23,7 +23,6 @@ import java.util.concurrent.ExecutorServ
 
 import org.apache.aries.blueprint.ComponentDefinitionRegistry;
 import org.apache.aries.blueprint.Processor;
-import org.apache.aries.blueprint.di.Repository;
 import org.apache.aries.proxy.ProxyManager;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;

Modified: aries/trunk/blueprint/blueprint-core/src/main/resources/OSGI-INF/blueprint/blueprint-ext.xml
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/resources/OSGI-INF/blueprint/blueprint-ext.xml?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/resources/OSGI-INF/blueprint/blueprint-ext.xml (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/resources/OSGI-INF/blueprint/blueprint-ext.xml Fri Jan 19 09:44:57 2018
@@ -52,7 +52,12 @@
             <entry key="osgi.service.blueprint.namespace" value="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.5.0"/>
         </service-properties>
     </service>
-    
+    <service ref="ExtNamespaceHandler" interface="org.apache.aries.blueprint.NamespaceHandler">
+        <service-properties>
+            <entry key="osgi.service.blueprint.namespace" value="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.6.0"/>
+        </service-properties>
+    </service>
+
     <!-- Also provide the "xml" namespace as a core functionality to avoid many bundles registering a handler for this -->
     <service ref="ExtNamespaceHandler" interface="org.apache.aries.blueprint.NamespaceHandler">
         <service-properties>

Added: aries/trunk/blueprint/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/impl/blueprint-ext-1.6.xsd
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/impl/blueprint-ext-1.6.xsd?rev=1821610&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/impl/blueprint-ext-1.6.xsd (added)
+++ aries/trunk/blueprint/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/impl/blueprint-ext-1.6.xsd Fri Jan 19 09:44:57 2018
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<xsd:schema xmlns="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.6.0"
+	xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
+	attributeFormDefault="unqualified" elementFormDefault="qualified" 
+	targetNamespace="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.6.0" version="1.0.0">
+
+    <xsd:import namespace="http://www.osgi.org/xmlns/blueprint/v1.0.0"/>
+
+    <!-- property placeholder -->
+
+    <xsd:element name="property-placeholder" type="TpropertyPlaceholder"/>
+
+    <xsd:complexType name="TpropertyPlaceholder">
+        <xsd:complexContent>
+            <xsd:extension base="bp:Tcomponent">
+                <xsd:sequence>
+                    <!-- nested properties declaration -->
+                    <xsd:element maxOccurs="1" minOccurs="0" name="default-properties" type="TdefaultProperties"/>
+                    <xsd:element maxOccurs="unbounded" minOccurs="0" name="location" type="xsd:string"/>
+                </xsd:sequence>
+                <xsd:attribute default="${" name="placeholder-prefix" type="xsd:string" use="optional"/>
+                <xsd:attribute default="}" name="placeholder-suffix" type="xsd:string" use="optional"/>
+                <xsd:attribute name="defaults-ref" type="bp:Tidref" use="optional"/>
+                <xsd:attribute default="false" name="ignore-missing-locations" type="xsd:boolean" use="optional"/>
+                <xsd:attribute default="fallback" name="system-properties" use="optional">
+                    <xsd:simpleType>
+                        <xsd:restriction base="xsd:NMTOKEN">
+                            <xsd:enumeration value="never"/>
+                            <xsd:enumeration value="fallback"/>
+                            <xsd:enumeration value="override"/>
+                        </xsd:restriction>
+                    </xsd:simpleType>
+                </xsd:attribute>
+                <xsd:attribute name="evaluator" type="xsd:string" use="optional"/>
+            </xsd:extension>
+        </xsd:complexContent>
+    </xsd:complexType>
+
+    <xsd:complexType name="TdefaultProperties">
+        <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+            <xsd:element name="property" type="bp:Tproperty"/>
+        </xsd:sequence>
+    </xsd:complexType>
+
+    <!-- proxy method -->
+
+    <xsd:attribute default="default" name="proxy-method">
+        <xsd:simpleType>
+            <xsd:restriction>
+                <xsd:simpleType>
+                    <xsd:list>
+                        <xsd:simpleType>
+                            <xsd:restriction base="xsd:NMTOKEN">
+                                <xsd:enumeration value="default"/>
+                                <xsd:enumeration value="classes"/>
+                                <xsd:enumeration value="greedy"/>
+                            </xsd:restriction>
+                        </xsd:simpleType>
+                    </xsd:list>
+                </xsd:simpleType>
+                <xsd:minLength value="1"/>
+            </xsd:restriction>
+        </xsd:simpleType>
+    </xsd:attribute>
+
+    <!-- role -->
+
+    <xsd:attribute name="role">
+        <xsd:simpleType>
+            <xsd:restriction>
+                <xsd:simpleType>
+                    <xsd:list>
+                        <xsd:simpleType>
+                            <xsd:restriction base="xsd:NMTOKEN">
+                                <xsd:enumeration value="processor"/>
+                            </xsd:restriction>
+                        </xsd:simpleType>
+                    </xsd:list>
+                </xsd:simpleType>
+            </xsd:restriction>
+        </xsd:simpleType>
+    </xsd:attribute>
+
+    <!-- CM property placeholder extenstion -->
+
+    <xsd:element name="location" type="xsd:string"/>
+    <xsd:attribute default="false" name="ignore-missing-locations" type="xsd:boolean"/>
+    <xsd:attribute default="fallback" name="system-properties">
+        <xsd:simpleType>
+            <xsd:restriction base="xsd:NMTOKEN">
+                <xsd:enumeration value="never"/>
+                <xsd:enumeration value="fallback"/>
+                <xsd:enumeration value="override"/>
+            </xsd:restriction>
+        </xsd:simpleType>
+    </xsd:attribute>
+    
+    <xsd:attribute default="false" name="field-injection" type="xsd:boolean"/>
+
+    <!-- Default reference bean -->
+    <xsd:attribute name="default" type="bp:Tidref"/>
+
+    <!-- Filter attribute -->
+    <xsd:attribute name="filter" type="xsd:normalizedString"/>
+    
+    <!-- Additional interfaces for references -->
+    <xsd:element name="additional-interfaces" type="bp:Tinterfaces"/>
+    
+    <!-- ARIES-1293, provide a way to create or reference beans from within -->
+    <!-- custom namespace handlers and other locations. (blueprint.xsd does  -->
+    <!-- not provide top level element definitions for these) -->
+    <xsd:element name="bean" type="bp:Tinlined-bean"/>
+    <xsd:element name="reference" type="bp:Tref"/>
+
+    <xsd:attribute default="reluctant" name="damping">
+        <xsd:simpleType>
+            <xsd:restriction base="xsd:NMTOKEN">
+                <xsd:enumeration value="reluctant"/>
+                <xsd:enumeration value="greedy"/>
+            </xsd:restriction>
+        </xsd:simpleType>
+    </xsd:attribute>
+
+    <xsd:attribute default="dynamic" name="lifecycle">
+        <xsd:simpleType>
+            <xsd:restriction base="xsd:NMTOKEN">
+                <xsd:enumeration value="dynamic"/>
+                <xsd:enumeration value="static"/>
+            </xsd:restriction>
+        </xsd:simpleType>
+    </xsd:attribute>
+
+</xsd:schema>

Added: aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/DampingPolicyTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/DampingPolicyTest.java?rev=1821610&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/DampingPolicyTest.java (added)
+++ aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/DampingPolicyTest.java Fri Jan 19 09:44:57 2018
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.aries.blueprint.container;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.aries.blueprint.ExtendedReferenceMetadata;
+import org.apache.aries.blueprint.container.SatisfiableRecipe.SatisfactionListener;
+import org.apache.aries.blueprint.reflect.ReferenceMetadataImpl;
+import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+
+public class DampingPolicyTest {
+
+    @Test
+    public void testGreedy() throws InvalidSyntaxException {
+        ExtendedBlueprintContainer container = EasyMock.createMock(ExtendedBlueprintContainer.class);
+        BundleContext containerContext = EasyMock.createMock(BundleContext.class);
+
+        ReferenceMetadataImpl metadata = new ReferenceMetadataImpl();
+        metadata.setInterface("my.interface");
+        metadata.setDamping(ExtendedReferenceMetadata.DAMPING_GREEDY);
+
+        final AtomicReference<ServiceReference> currentReference = new AtomicReference<ServiceReference>();
+
+        ReferenceRecipe recipe = new ReferenceRecipe(
+                "myref",
+                container,
+                metadata,
+                null, null, null
+        ) {
+            @Override
+            protected void bind(ServiceReference ref) {
+                currentReference.set(ref);
+                super.bind(ref);
+            }
+        };
+
+        SatisfactionListener listener = new SatisfactionListener() {
+            @Override
+            public void notifySatisfaction(SatisfiableRecipe satisfiable) {
+
+            }
+        };
+        ServiceReference svcRef1 = EasyMock.createMock(ServiceReference.class);
+
+        EasyMock.expect(container.getBundleContext()).andReturn(containerContext).anyTimes();
+        containerContext.addServiceListener(recipe, "(objectClass=my.interface)");
+        EasyMock.expectLastCall();
+        EasyMock.expect(containerContext.getServiceReferences((String) null, "(objectClass=my.interface)"))
+                .andReturn(new ServiceReference[] { svcRef1 });
+        EasyMock.replay(container, containerContext, svcRef1);
+
+        recipe.start(listener);
+        Assert.assertSame(svcRef1, currentReference.get());
+        EasyMock.verify(container, containerContext, svcRef1);
+
+        EasyMock.reset(container, containerContext, svcRef1);
+
+
+        ServiceReference svcRef2 = EasyMock.createMock(ServiceReference.class);
+        ServiceEvent event2 = new ServiceEvent(ServiceEvent.REGISTERED, svcRef2);
+
+        EasyMock.expect(svcRef1.getProperty(Constants.SERVICE_ID)).andReturn(0L).anyTimes();
+        EasyMock.expect(svcRef1.getProperty(Constants.SERVICE_RANKING)).andReturn(0).anyTimes();
+        EasyMock.expect(svcRef2.getProperty(Constants.SERVICE_ID)).andReturn(1L).anyTimes();
+        EasyMock.expect(svcRef2.getProperty(Constants.SERVICE_RANKING)).andReturn(1).anyTimes();
+        EasyMock.replay(container, containerContext, svcRef1, svcRef2);
+
+        recipe.serviceChanged(event2);
+        Assert.assertSame(svcRef2, currentReference.get());
+        EasyMock.verify(container, containerContext, svcRef1, svcRef2);
+
+    }
+}

Added: aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/LifecyclePolicyTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/LifecyclePolicyTest.java?rev=1821610&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/LifecyclePolicyTest.java (added)
+++ aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/LifecyclePolicyTest.java Fri Jan 19 09:44:57 2018
@@ -0,0 +1,248 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.aries.blueprint.container;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.apache.aries.blueprint.ExtendedReferenceMetadata;
+import org.apache.aries.blueprint.parser.NamespaceHandlerSet;
+import org.apache.aries.blueprint.reflect.BeanMetadataImpl;
+import org.apache.aries.blueprint.reflect.RefMetadataImpl;
+import org.apache.aries.blueprint.reflect.ReferenceMetadataImpl;
+import org.apache.aries.proxy.ProxyManager;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.Version;
+import org.osgi.service.blueprint.container.BlueprintContainer;
+import org.osgi.service.blueprint.container.BlueprintEvent;
+import org.osgi.service.blueprint.container.BlueprintListener;
+
+public class LifecyclePolicyTest {
+
+    @Test
+    public void testStatic() throws Exception {
+        final ReferenceMetadataImpl ref = new ReferenceMetadataImpl();
+        ref.setId("ref");
+        ref.setRuntimeInterface(TestItf.class);
+        ref.setLifecycle(ExtendedReferenceMetadata.LIFECYCLE_STATIC);
+
+        final BeanMetadataImpl bean1 = new BeanMetadataImpl();
+        bean1.setId("bean1");
+        bean1.setRuntimeClass(Bean1.class);
+        bean1.setInitMethod("init");
+        bean1.setDestroyMethod("destroy");
+        bean1.addProperty("itf", new RefMetadataImpl("ref"));
+
+        final BeanMetadataImpl bean2 = new BeanMetadataImpl();
+        bean2.setId("bean2");
+        bean2.setRuntimeClass(Bean2.class);
+        bean2.setInitMethod("init");
+        bean2.setDestroyMethod("destroy");
+        bean2.addProperty("bean1", new RefMetadataImpl("bean1"));
+
+        Bundle bundle = EasyMock.createMock(Bundle.class);
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+        Bundle extenderBundle = EasyMock.createMock(Bundle.class);
+        BundleContext extenderBundleContext = EasyMock.createMock(BundleContext.class);
+        BlueprintListener eventDispatcher = EasyMock.createMock(BlueprintListener.class);
+        NamespaceHandlerRegistry namespaceHandlerRegistry = EasyMock.createMock(NamespaceHandlerRegistry.class);
+        ProxyManager proxyManager = EasyMock.createMock(ProxyManager.class);
+        NamespaceHandlerSet namespaceHandlerSet = EasyMock.createMock(NamespaceHandlerSet.class);
+        TestItf itf = EasyMock.createMock(TestItf.class);
+        ServiceRegistration registration = EasyMock.createMock(ServiceRegistration.class);
+        ExecutorService executorService = Executors.newFixedThreadPool(1);
+        ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
+        List<URL> pathList = new ArrayList<URL>();
+        Set<URI> namespaces = new HashSet<URI>();
+
+        BlueprintContainerImpl container = new BlueprintContainerImpl(
+                bundle, bundleContext, extenderBundle, eventDispatcher, namespaceHandlerRegistry,
+                executorService, timer, pathList, proxyManager, namespaces
+        ) {
+            private boolean repoCreated = false;
+            @Override
+            public BlueprintRepository getRepository() {
+                if (!repoCreated) {
+                    getComponentDefinitionRegistry().registerComponentDefinition(ref);
+                    getComponentDefinitionRegistry().registerComponentDefinition(bean1);
+                    getComponentDefinitionRegistry().registerComponentDefinition(bean2);
+                    repoCreated = true;
+                }
+                return super.getRepository();
+            }
+        };
+
+        ServiceReference svcRef1 = EasyMock.createMock(ServiceReference.class);
+
+        EasyMock.expect(bundle.getSymbolicName()).andReturn("bundleSymbolicName").anyTimes();
+        EasyMock.expect(bundle.getVersion()).andReturn(Version.emptyVersion).anyTimes();
+        EasyMock.expect(bundle.getState()).andReturn(Bundle.ACTIVE).anyTimes();
+        EasyMock.expect(bundle.getBundleContext()).andReturn(bundleContext).anyTimes();
+        Hashtable<String, String> headers = new Hashtable<String, String>();
+        headers.put(Constants.BUNDLE_SYMBOLICNAME, "bundleSymbolicName;blueprint.aries.xml-validation:=false");
+        EasyMock.expect(bundle.getHeaders()).andReturn(headers).anyTimes();
+        eventDispatcher.blueprintEvent(EasyMock.<BlueprintEvent>anyObject());
+        EasyMock.expectLastCall().anyTimes();
+        EasyMock.expect(namespaceHandlerRegistry.getNamespaceHandlers(namespaces, bundle))
+                .andReturn(namespaceHandlerSet).anyTimes();
+        EasyMock.expect(namespaceHandlerSet.getNamespaces()).andReturn(namespaces).anyTimes();
+        namespaceHandlerSet.addListener(container);
+        EasyMock.expectLastCall();
+        Properties props = new Properties();
+        props.put("osgi.blueprint.container.version", Version.emptyVersion);
+        props.put("osgi.blueprint.container.symbolicname", "bundleSymbolicName");
+        EasyMock.expect(bundleContext.registerService(
+                EasyMock.aryEq(new String[] {BlueprintContainer.class.getName()}),
+                EasyMock.same(container),
+                EasyMock.eq((Dictionary)props))).andReturn(registration);
+        bundleContext.addServiceListener(EasyMock.<org.osgi.framework.ServiceListener>anyObject(), EasyMock.<String>anyObject());
+        EasyMock.expectLastCall();
+        EasyMock.expect(bundleContext.getServiceReferences((String) null, "(objectClass=" + TestItf.class.getName() + ")"))
+                .andReturn(new ServiceReference[] { svcRef1 });
+
+        EasyMock.expect(bundleContext.getService(svcRef1)).andReturn(itf);
+        EasyMock.expect(bundle.loadClass("java.lang.Object")).andReturn((Class) Object.class).anyTimes();
+
+        EasyMock.replay(bundle, bundleContext, extenderBundle, extenderBundleContext,
+                eventDispatcher, namespaceHandlerRegistry, namespaceHandlerSet, proxyManager,
+                svcRef1, registration);
+
+        container.run();
+        ReferenceRecipe recipe = (ReferenceRecipe) container.getRepository().getRecipe("ref");
+        recipe.start(container);
+
+        Bean2 bean2i = (Bean2) container.getRepository().create("bean2");
+        Assert.assertNotNull(bean2i);
+        Assert.assertEquals(1, Bean2.initialized);
+        Assert.assertEquals(0, Bean2.destroyed);
+
+        EasyMock.verify(bundle, bundleContext, extenderBundle, extenderBundleContext,
+                eventDispatcher, namespaceHandlerRegistry, namespaceHandlerSet, proxyManager,
+                svcRef1, registration);
+
+        //
+        // Unregister the service
+        //
+        // Given the lifecycle is 'static', this should cause the Bean1 and Bean2
+        // to be destroyed
+        //
+
+        EasyMock.reset(bundle, bundleContext, extenderBundle, extenderBundleContext,
+                eventDispatcher, namespaceHandlerRegistry, namespaceHandlerSet, proxyManager,
+                svcRef1, registration);
+
+        EasyMock.expect(bundle.getSymbolicName()).andReturn("bundleSymbolicName").anyTimes();
+        EasyMock.expect(bundle.getVersion()).andReturn(Version.emptyVersion).anyTimes();
+        EasyMock.expect(bundleContext.ungetService(svcRef1)).andReturn(false);
+
+        EasyMock.replay(bundle, bundleContext, extenderBundle, extenderBundleContext,
+                eventDispatcher, namespaceHandlerRegistry, namespaceHandlerSet, proxyManager,
+                svcRef1, registration);
+
+        recipe.serviceChanged(new ServiceEvent(ServiceEvent.UNREGISTERING, svcRef1));
+        Assert.assertEquals(1, Bean2.initialized);
+        Assert.assertEquals(1, Bean2.destroyed);
+
+        EasyMock.verify(bundle, bundleContext, extenderBundle, extenderBundleContext,
+                eventDispatcher, namespaceHandlerRegistry, namespaceHandlerSet, proxyManager,
+                svcRef1, registration);
+
+        //
+        // Re-register the service
+        //
+        // Given the lifecycle is 'static', this should cause the Bean1 and Bean2
+        // to be recreated
+        //
+
+        EasyMock.reset(bundle, bundleContext, extenderBundle, extenderBundleContext,
+                eventDispatcher, namespaceHandlerRegistry, namespaceHandlerSet, proxyManager,
+                svcRef1, registration);
+
+        EasyMock.expect(bundle.getSymbolicName()).andReturn("bundleSymbolicName").anyTimes();
+        EasyMock.expect(bundle.getVersion()).andReturn(Version.emptyVersion).anyTimes();
+        EasyMock.expect(bundleContext.getService(svcRef1)).andReturn(itf);
+        EasyMock.expect(bundle.loadClass("java.lang.Object")).andReturn((Class) Object.class).anyTimes();
+
+        EasyMock.replay(bundle, bundleContext, extenderBundle, extenderBundleContext,
+                eventDispatcher, namespaceHandlerRegistry, namespaceHandlerSet, proxyManager,
+                svcRef1, registration);
+
+        recipe.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, svcRef1));
+        Assert.assertEquals(2, Bean2.initialized);
+        Assert.assertEquals(1, Bean2.destroyed);
+
+        EasyMock.verify(bundle, bundleContext, extenderBundle, extenderBundleContext,
+                eventDispatcher, namespaceHandlerRegistry, namespaceHandlerSet, proxyManager,
+                svcRef1, registration);
+    }
+
+    public interface TestItf {
+
+    }
+
+    public static class Bean1 {
+        private TestItf itf;
+        public TestItf getItf() {
+            return itf;
+        }
+        public void setItf(TestItf itf) {
+            this.itf = itf;
+        }
+        public void init() {
+        }
+        public void destroy() {
+        }
+    }
+
+    public static class Bean2 {
+        private Bean1 bean1;
+        static int initialized = 0;
+        static int destroyed = 0;
+        public Bean1 getBean1() {
+            return bean1;
+        }
+        public void setBean1(Bean1 bean1) {
+            this.bean1 = bean1;
+        }
+        public void init() {
+            initialized++;
+        }
+        public void destroy() {
+            destroyed++;
+        }
+    }
+}

Modified: aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/ExtendedReferenceMetadata.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/ExtendedReferenceMetadata.java?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/ExtendedReferenceMetadata.java (original)
+++ aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/ExtendedReferenceMetadata.java Fri Jan 19 09:44:57 2018
@@ -24,9 +24,22 @@ import org.osgi.service.blueprint.reflec
 
 public interface ExtendedReferenceMetadata extends ReferenceMetadata 
 {
+    public int DAMPING_RELUCTANT = 0;
+
+    public int DAMPING_GREEDY = 1;
+
+    public int LIFECYCLE_DYNAMIC = 0;
+
+    public int LIFECYCLE_STATIC = 1;
+
     public String getDefaultBean();
     
     public Collection<Class<?>> getProxyChildBeanClasses();
     
     public Collection<String> getExtraInterfaces();
+
+    public int getDamping();
+
+    public int getLifecycle();
+
 }
\ No newline at end of file

Modified: aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/mutable/MutableReferenceMetadata.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/mutable/MutableReferenceMetadata.java?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/mutable/MutableReferenceMetadata.java (original)
+++ aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/mutable/MutableReferenceMetadata.java Fri Jan 19 09:44:57 2018
@@ -36,4 +36,8 @@ public interface MutableReferenceMetadat
     void setProxyChildBeanClasses(Collection<Class<?>> classes);
 
     void setExtraInterfaces(Collection<String> interfaces);
+
+    void setDamping(int damping);
+
+    void setLifecycle(int lifecycle);
 }
\ No newline at end of file

Modified: aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/reflect/ReferenceMetadataImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/reflect/ReferenceMetadataImpl.java?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/reflect/ReferenceMetadataImpl.java (original)
+++ aries/trunk/blueprint/blueprint-parser/src/main/java/org/apache/aries/blueprint/reflect/ReferenceMetadataImpl.java Fri Jan 19 09:44:57 2018
@@ -35,6 +35,8 @@ public class ReferenceMetadataImpl exten
     private String defaultBeanId;
     private Collection<Class<?>> proxyChildBeanClasses;
     private Collection<String> extraInterfaces;
+    private int damping;
+    private int lifecycle;
 
     public ReferenceMetadataImpl() {
     }
@@ -73,6 +75,8 @@ public class ReferenceMetadataImpl exten
                 ", referenceListeners=" + referenceListeners +
                 ", timeout=" + timeout +
                 ", additonalInterfaces=" + getExtraInterfaces() +
+                ", damping=" + getDamping() +
+                ", lifecycle=" + getLifecycle() +
                 ']';
     }
 
@@ -94,4 +98,20 @@ public class ReferenceMetadataImpl exten
     public void setExtraInterfaces(Collection<String> interfaces) {
         extraInterfaces = interfaces;
     }
+
+    public int getDamping() {
+        return damping;
+    }
+
+    public void setDamping(int damping) {
+        this.damping = damping;
+    }
+
+    public int getLifecycle() {
+        return lifecycle;
+    }
+
+    public void setLifecycle(int lifecycle) {
+        this.lifecycle = lifecycle;
+    }
 }

Modified: aries/trunk/blueprint/itests/blueprint-itests/pom.xml
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/itests/blueprint-itests/pom.xml?rev=1821610&r1=1821609&r2=1821610&view=diff
==============================================================================
--- aries/trunk/blueprint/itests/blueprint-itests/pom.xml (original)
+++ aries/trunk/blueprint/itests/blueprint-itests/pom.xml Fri Jan 19 09:44:57 2018
@@ -56,7 +56,7 @@
         <dependency>
             <groupId>org.apache.aries.blueprint</groupId>
             <artifactId>org.apache.aries.blueprint.core</artifactId>
-            <version>1.8.3-SNAPSHOT</version>
+            <version>1.9.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.aries.blueprint</groupId>
@@ -71,7 +71,7 @@
         <dependency>
             <groupId>org.apache.aries.blueprint</groupId>
             <artifactId>org.apache.aries.blueprint.spring</artifactId>
-            <version>1.0.0-SNAPSHOT</version>
+            <version>0.6.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.aries.blueprint</groupId>
@@ -194,7 +194,7 @@
         <dependency>
             <groupId>org.apache.aries.blueprint</groupId>
             <artifactId>org.apache.aries.blueprint.testquiescebundle</artifactId>
-            <version>1.0.1-SNAPSHOT</version>
+            <version>${project.version}</version>
         </dependency>
 
         <!-- pax exam -->