You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by cu...@apache.org on 2010/09/10 16:08:35 UTC

svn commit: r995797 - in /incubator/aries/trunk/blueprint: ./ blueprint-annotation-itest/src/test/java/org/apache/aries/blueprint/itests/ blueprint-bundle/ blueprint-core/ blueprint-core/src/main/java/org/apache/aries/blueprint/container/ blueprint-ite...

Author: cumminsh
Date: Fri Sep 10 14:08:34 2010
New Revision: 995797

URL: http://svn.apache.org/viewvc?rev=995797&view=rev
Log:
ARIES-383: Committing patch from Hannah Ramlee and Simon Maple for blueprint quiesce participant.

Added:
    incubator/aries/trunk/blueprint/blueprint-core/maven-eclipse.xml
    incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintQuiesceParticipant.java
    incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/DestroyCallback.java
    incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/QuiesceInterceptor.java
    incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/QuiesceBlueprintTest.java
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/pom.xml
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/Activator.java
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/TestBean.java
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/blueprint/
    incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/blueprint/config.xml
Modified:
    incubator/aries/trunk/blueprint/blueprint-annotation-itest/src/test/java/org/apache/aries/blueprint/itests/BlueprintAnnotationTest.java
    incubator/aries/trunk/blueprint/blueprint-bundle/pom.xml
    incubator/aries/trunk/blueprint/blueprint-core/pom.xml
    incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
    incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java
    incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java
    incubator/aries/trunk/blueprint/blueprint-itests/pom.xml
    incubator/aries/trunk/blueprint/pom.xml

Modified: incubator/aries/trunk/blueprint/blueprint-annotation-itest/src/test/java/org/apache/aries/blueprint/itests/BlueprintAnnotationTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-annotation-itest/src/test/java/org/apache/aries/blueprint/itests/BlueprintAnnotationTest.java?rev=995797&r1=995796&r2=995797&view=diff
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-annotation-itest/src/test/java/org/apache/aries/blueprint/itests/BlueprintAnnotationTest.java (original)
+++ incubator/aries/trunk/blueprint/blueprint-annotation-itest/src/test/java/org/apache/aries/blueprint/itests/BlueprintAnnotationTest.java Fri Sep 10 14:08:34 2010
@@ -77,7 +77,7 @@ public class BlueprintAnnotationTest ext
 
        obj = getOsgiService(bundleContext, Foo.class, null, 5000);
         assertNotNull(obj);
-        assertSame(foo, obj);
+        assertEquals(foo.toString(), obj.toString());
     }
 
     @org.ops4j.pax.exam.junit.Configuration

Modified: incubator/aries/trunk/blueprint/blueprint-bundle/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-bundle/pom.xml?rev=995797&r1=995796&r2=995797&view=diff
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-bundle/pom.xml (original)
+++ incubator/aries/trunk/blueprint/blueprint-bundle/pom.xml Fri Sep 10 14:08:34 2010
@@ -46,6 +46,8 @@
             org.objectweb.asm*;version="[3.1,4)";resolution:=optional,
             org.osgi.service.cm;version="[1.2.0,2.0.0)",
             org.apache.aries.blueprint.annotation.service;resolution:=optional,
+            org.apache.aries.quiesce.manager;version="[0.2,1.0)";resolution:=optional,
+            org.apache.aries.quiesce.participant;version="[0.2,1.0)";resolution:=optional,
             *
         </aries.osgi.import>
         <aries.osgi.export>
@@ -107,6 +109,11 @@
             <artifactId>org.osgi.compendium</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.aries.quiesce</groupId>
+            <artifactId>org.apache.aries.quiesce.api</artifactId>
+            <scope>provided</scope>
+        </dependency>
 
     </dependencies>
 

Added: incubator/aries/trunk/blueprint/blueprint-core/maven-eclipse.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/maven-eclipse.xml?rev=995797&view=auto
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-core/maven-eclipse.xml (added)
+++ incubator/aries/trunk/blueprint/blueprint-core/maven-eclipse.xml Fri Sep 10 14:08:34 2010
@@ -0,0 +1,8 @@
+<project default="copy-resources">
+  <target name="init"/>
+  <target name="copy-resources" depends="init">
+    <copy todir="target/classes/org/apache/aries/blueprint" filtering="false">
+      <fileset dir="/home/cumminsh/projects/aries/apache-workspace/aries/blueprint/blueprint-api/src/main/resources/org/osgi/service/blueprint" includes="blueprint.xsd" excludes="**/*.java"/>
+    </copy>
+  </target>
+</project>
\ No newline at end of file

Modified: incubator/aries/trunk/blueprint/blueprint-core/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/pom.xml?rev=995797&r1=995796&r2=995797&view=diff
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-core/pom.xml (original)
+++ incubator/aries/trunk/blueprint/blueprint-core/pom.xml Fri Sep 10 14:08:34 2010
@@ -46,6 +46,8 @@
         org.osgi.service.event*;resolution:=optional,
         org.osgi.service.framework;resolution:=optional,
         org.apache.aries.blueprint.annotation.service;resolution:=optional,
+        org.apache.aries.quiesce.manager;version="[0.2,1.0)";resolution:=optional,
+        org.apache.aries.quiesce.participant;version="[0.2,1.0)";resolution:=optional,
         *
       </aries.osgi.import>
       <aries.osgi.export.service>
@@ -101,6 +103,12 @@
           <artifactId>asm-all</artifactId>
           <optional>true</optional>
       </dependency>
+      <dependency>
+      	<groupId>org.apache.aries.quiesce</groupId>
+      	<artifactId>org.apache.aries.quiesce.api</artifactId>
+      	<version>0.3-incubating-SNAPSHOT</version>
+      	<scope>provided</scope>
+      </dependency>
   </dependencies>
 
     <build>

Modified: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java?rev=995797&r1=995796&r2=995797&view=diff
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java (original)
+++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java Fri Sep 10 14:08:34 2010
@@ -648,7 +648,7 @@ public class BlueprintContainerImpl impl
         }
     }
 
-    private void unregisterServices() {
+    protected void unregisterServices() {
         if (repository != null) {
             List<ServiceRecipe> recipes = this.services;
             this.services = null;
@@ -821,6 +821,23 @@ public class BlueprintContainerImpl impl
         eventDispatcher.blueprintEvent(new BlueprintEvent(BlueprintEvent.DESTROYED, getBundleContext().getBundle(), getExtenderBundle()));
         LOGGER.debug("Blueprint container destroyed: {}", this.bundleContext);
     }
+    
+    protected void quiesce() {
+        destroyed = true;
+        eventDispatcher.blueprintEvent(new BlueprintEvent(BlueprintEvent.DESTROYING, getBundleContext().getBundle(), getExtenderBundle()));
+
+        if (timeoutFuture != null) {
+            timeoutFuture.cancel(false);
+        }
+        if (registration != null) {
+            registration.unregister();
+        }
+        if (handlerSet != null) {
+            handlerSet.removeListener(this);
+            handlerSet.destroy();
+        }
+        LOGGER.debug("Blueprint container quiesced: {}", this.bundleContext);
+    }
 
     public void namespaceHandlerRegistered(URI uri) {
         if (namespaces != null && namespaces.contains(uri)) {

Modified: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java?rev=995797&r1=995796&r2=995797&view=diff
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java (original)
+++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java Fri Sep 10 14:08:34 2010
@@ -49,9 +49,7 @@ import org.osgi.framework.ServiceRegistr
 import org.osgi.framework.SynchronousBundleListener;
 import org.osgi.service.blueprint.container.BlueprintContainer;
 import org.osgi.service.blueprint.container.BlueprintEvent;
-import org.osgi.util.tracker.BundleTracker;
 import org.osgi.util.tracker.BundleTrackerCustomizer;
-import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -62,6 +60,8 @@ import org.slf4j.LoggerFactory;
  */
 public class BlueprintExtender implements BundleActivator, SynchronousBundleListener {
 
+	/** The QuiesceParticipant implementation class name */
+	private static final String QUIESCE_PARTICIPANT_CLASS = "org.apache.aries.quiesce.participant.QuiesceParticipant";
     private static final Logger LOGGER = LoggerFactory.getLogger(BlueprintExtender.class);
 
     private BundleContext context;
@@ -71,6 +71,7 @@ public class BlueprintExtender implement
     private NamespaceHandlerRegistry handlers;
     private RecursiveBundleTracker bt;
     private ServiceRegistration parserServiceReg;
+    private ServiceRegistration quiesceParticipantReg;
 
     public void start(BundleContext context) {
         LOGGER.debug("Starting blueprint extender...");
@@ -90,6 +91,19 @@ public class BlueprintExtender implement
         parserServiceReg = context.registerService(ParserService.class.getName(), 
             new ParserServiceImpl (handlers), 
             new Hashtable<Object, Object>()); 
+
+        try{
+            context.getBundle().loadClass(QUIESCE_PARTICIPANT_CLASS);
+            //Class was loaded, register
+
+            quiesceParticipantReg = context.registerService(QUIESCE_PARTICIPANT_CLASS, 
+              new BlueprintQuiesceParticipant(context, this), 
+              new Hashtable<Object, Object>()); 
+        } 
+        catch (ClassNotFoundException e) 
+        {
+            LOGGER.info("No quiesce support is available, so blueprint components will not participate in quiesce operations", e);
+        }
         
         LOGGER.debug("Blueprint extender started");
     }
@@ -123,6 +137,9 @@ public class BlueprintExtender implement
         }
         
         parserServiceReg.unregister();
+        
+        if (quiesceParticipantReg != null) 
+          	quiesceParticipantReg.unregister();
 
         // Orderly shutdown of containers
         while (!containers.isEmpty()) {
@@ -392,4 +409,9 @@ public class BlueprintExtender implement
         }
     }
     
+    protected BlueprintContainerImpl getBlueprintContainerImpl(Bundle bundle)
+    {
+    	return (BlueprintContainerImpl) containers.get(bundle);
+    }
+    
 }

Added: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintQuiesceParticipant.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintQuiesceParticipant.java?rev=995797&view=auto
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintQuiesceParticipant.java (added)
+++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintQuiesceParticipant.java Fri Sep 10 14:08:34 2010
@@ -0,0 +1,160 @@
+/*
+ * 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.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.aries.blueprint.di.Recipe;
+import org.apache.aries.quiesce.manager.QuiesceCallback;
+import org.apache.aries.quiesce.participant.QuiesceParticipant;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public class BlueprintQuiesceParticipant implements QuiesceParticipant 
+{
+	private BundleContext ctx;
+	private BlueprintExtender extender;
+	
+	public BlueprintQuiesceParticipant(BundleContext context, BlueprintExtender extender)
+	{
+		this.ctx = context;
+		this.extender = extender;
+	}
+
+	/**
+	 * A Threadpool for running quiesce operations
+	 */
+	private final ExecutorService executor = new ThreadPoolExecutor(0, 10, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadFactory() 
+	{
+		public Thread newThread(Runnable r) 
+		{
+	        Thread t = new Thread(r, "Blueprint-Container-ThreadPool");
+	        t.setDaemon(true);
+	        return t;
+		}
+    });
+	
+	public void quiesce(QuiesceCallback callback, List<Bundle> bundlesToQuiesce) 
+	{
+		for(Bundle b : bundlesToQuiesce) 
+		{
+		  try 
+		  {
+		    executor.execute(new QuiesceBundle(callback, b, extender));
+		  } 
+		  catch (RejectedExecutionException re) {
+		  }
+		  
+		  //If we are quiescing, then we need to quiesce this threadpool!
+		  if(b.equals(ctx.getBundle()))
+		    executor.shutdown();
+		}
+	}
+
+  /**
+   * A runnable Quiesce operation for a single bundle
+   */
+	private static final class QuiesceBundle implements Runnable 
+	{
+		/** The bundle being quiesced */
+		private final Bundle bundleToQuiesce;
+		private QuiesceCallback callback;
+		private BlueprintExtender extender;
+		
+		public QuiesceBundle(QuiesceCallback callback, Bundle bundleToQuiesce, 
+				BlueprintExtender extender) 
+		{	
+			super();
+			this.callback = callback;
+			this.bundleToQuiesce = bundleToQuiesce;
+			this.extender = extender;
+		}
+
+		public void run() 
+		{
+			BlueprintContainerImpl container = extender.getBlueprintContainerImpl(bundleToQuiesce);
+						
+			BlueprintRepository repository = container.getRepository();
+			Set<String> names = repository.getNames();
+			container.quiesce();
+			boolean hasServices = false;
+			
+			for (String name: names)
+			{
+				Recipe recipe = repository.getRecipe(name);
+				if (recipe instanceof ServiceRecipe)
+				{
+					hasServices = true;
+					((ServiceRecipe)recipe).quiesce(new QuiesceDelegatingCallback(callback, bundleToQuiesce));
+				}
+			}
+			//If the bundle has no services we can quiesce immediately
+			if (!hasServices)
+			{
+				callback.bundleQuiesced(bundleToQuiesce);
+			}
+		}
+	}
+	
+    /**
+	 * A wrapper to protect our internals from the Quiesce API so that we can make it
+	 * an optional dependency
+	 */
+	private static final class QuiesceDelegatingCallback implements DestroyCallback 
+	{
+	  
+	  /** The callback to delegate to */
+	  private final QuiesceCallback callback;
+	
+	  /** The single bundle being quiesced by this DestroyCallback */
+	  private final Bundle toQuiesce;
+	
+	  private Set<String> services = new HashSet<String>();
+	    
+	  public QuiesceDelegatingCallback(QuiesceCallback cbk, Bundle b) 
+	  {
+	    callback = cbk;
+	    toQuiesce = b;
+	      
+	    ServiceReference[] serviceRefs = b.getRegisteredServices();
+	    
+	    for (ServiceReference ref : serviceRefs)
+	    {
+	  	  services.add(b.getBundleContext().getService(ref).toString());
+	    }
+	  }
+	    
+	  public void callback(Object key) 
+	  {
+	    if (key != null && services.remove(key.toString()) && services.isEmpty())
+	    {
+	 	  	callback.bundleQuiesced(toQuiesce);
+	    }
+	  }
+	}
+}

Added: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/DestroyCallback.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/DestroyCallback.java?rev=995797&view=auto
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/DestroyCallback.java (added)
+++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/DestroyCallback.java Fri Sep 10 14:08:34 2010
@@ -0,0 +1,26 @@
+/**
+ * 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;
+
+/**
+ * A callback to indicate that a destroy operation has completed
+ */
+public interface DestroyCallback {
+  public void callback(Object key);
+}

Added: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/QuiesceInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/QuiesceInterceptor.java?rev=995797&view=auto
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/QuiesceInterceptor.java (added)
+++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/QuiesceInterceptor.java Fri Sep 10 14:08:34 2010
@@ -0,0 +1,56 @@
+/*
+ * 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.lang.reflect.Method;
+
+import org.apache.aries.blueprint.Interceptor;
+import org.osgi.service.blueprint.reflect.ComponentMetadata;
+
+public class QuiesceInterceptor implements Interceptor{
+
+	private ServiceRecipe serviceRecipe;
+	
+	public QuiesceInterceptor(ServiceRecipe serviceRecipe)
+	{
+		this.serviceRecipe = serviceRecipe;
+	}
+	
+    public Object preCall(ComponentMetadata cm, Method m, Object... parameters) throws Throwable
+    {
+   		serviceRecipe.incrementActiveCalls();
+    	
+    	return null;
+    }
+    
+    public void postCallWithReturn(ComponentMetadata cm, Method m, Object returnType, Object preCallToken) throws Throwable
+    {
+    	serviceRecipe.decrementActiveCalls();
+    }
+
+    public void postCallWithException(ComponentMetadata cm, Method m, Throwable ex, Object preCallToken) throws Throwable
+    {
+    	serviceRecipe.decrementActiveCalls();
+    }
+   
+    public int getRank()
+    {
+    	return 0;
+    }
+}

Modified: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java?rev=995797&r1=995796&r2=995797&view=diff
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java (original)
+++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java Fri Sep 10 14:08:34 2010
@@ -16,6 +16,7 @@
  */
 package org.apache.aries.blueprint.container;
 
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Dictionary;
@@ -29,12 +30,15 @@ import java.util.concurrent.atomic.Atomi
 
 import org.apache.aries.blueprint.BlueprintConstants;
 import org.apache.aries.blueprint.ExtendedBlueprintContainer;
+import org.apache.aries.blueprint.Interceptor;
 import org.apache.aries.blueprint.ServiceProcessor;
 import org.apache.aries.blueprint.di.AbstractRecipe;
 import org.apache.aries.blueprint.di.CollectionRecipe;
 import org.apache.aries.blueprint.di.MapRecipe;
 import org.apache.aries.blueprint.di.Recipe;
 import org.apache.aries.blueprint.di.Repository;
+import org.apache.aries.blueprint.proxy.AsmInterceptorWrapper;
+import org.apache.aries.blueprint.proxy.CgLibInterceptorWrapper;
 import org.apache.aries.blueprint.utils.JavaUtils;
 import org.apache.aries.blueprint.utils.ReflectionUtils;
 import org.osgi.framework.Bundle;
@@ -43,6 +47,7 @@ import org.osgi.framework.ServiceFactory
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.blueprint.container.ComponentDefinitionException;
+import org.osgi.service.blueprint.reflect.ComponentMetadata;
 import org.osgi.service.blueprint.reflect.RefMetadata;
 import org.osgi.service.blueprint.reflect.ServiceMetadata;
 import org.slf4j.Logger;
@@ -70,6 +75,9 @@ public class ServiceRecipe extends Abstr
     private Map registrationProperties;
     private List<ServiceListener> listeners;
     private volatile Object service;
+    private int activeCalls;
+    private boolean quiesce;
+    private DestroyCallback destroyCallback;
     
     public ServiceRecipe(String name,
                          ExtendedBlueprintContainer blueprintContainer,
@@ -163,7 +171,7 @@ public class ServiceRecipe extends Abstr
             LOGGER.debug("Registering service {} with interfaces {} and properties {}",
                          new Object[] { name, classes, props });
 
-            registration.set(blueprintContainer.registerService(classArray, new TriggerServiceFactory(), props));            
+            registration.set(blueprintContainer.registerService(classArray, new TriggerServiceFactory(this, metadata), props));            
         }
     }
 
@@ -361,10 +369,124 @@ public class ServiceRecipe extends Abstr
         }
     }
 
-    private class TriggerServiceFactory implements ServiceFactory {
+    protected void incrementActiveCalls()
+    {
+    	synchronized(this) 
+    	{
+    		activeCalls++;	
+		}
+    }
+    
+	protected void decrementActiveCalls() 
+	{
+		
+    	synchronized(this) 
+    	{
+    		activeCalls--;
+
+			if (quiesce && activeCalls == 0)
+			{
+				destroyCallback.callback(service);
+			}
+    	}
+	}
+	
+    public void quiesce(DestroyCallback destroyCallback)
+    {
+    	this.destroyCallback = destroyCallback;
+    	quiesce = true;
+    	unregister();
+    	if(activeCalls == 0)
+		{
+			destroyCallback.callback(service);
+		}
+    }
+     
+    private class TriggerServiceFactory implements ServiceFactory 
+    {
+    	private QuiesceInterceptor interceptor;
+    	private ServiceRecipe serviceRecipe;
+    	private ComponentMetadata cm;
+    	public TriggerServiceFactory(ServiceRecipe serviceRecipe, ComponentMetadata cm)
+    	{
+    		this.serviceRecipe = serviceRecipe;
+    		this.cm = cm;
+    	}
+    	
+        public Object getService(Bundle bundle, ServiceRegistration registration) 
+        {
+        	Object original = ServiceRecipe.this.getService(bundle, registration);
+        	Object intercepted = null;
+            boolean asmAvailable = false;
+            boolean cglibAvailable = false;
+            
+            if (interceptor == null)
+            {
+            	interceptor = new QuiesceInterceptor(serviceRecipe);
+            }
+            
+            List<Interceptor> interceptors = new ArrayList<Interceptor>();
+            interceptors.add(interceptor);
+            
+            try 
+            {
+                // Try load load an asm class (to make sure it's actually
+                // available)
+                getClass().getClassLoader().loadClass(
+                        "org.objectweb.asm.ClassVisitor");
+                LOGGER.debug("asm available for interceptors");
+                asmAvailable = true;
+            } 
+            catch (Throwable t) 
+            {
+                try 
+                {
+                    // Try load load a cglib class (to make sure it's actually
+                    // available)
+                    getClass().getClassLoader().loadClass(
+                            "net.sf.cglib.proxy.Enhancer");
+                    cglibAvailable = true;
+                } 
+                catch (Throwable u) 
+                {
+                	LOGGER.info("No quiesce support is available, so blueprint components will not participate in quiesce operations");
+                	return original;
+                }
+            }
+            
+            try
+            {
+	            if (asmAvailable) 
+	            {
+	                // if asm is available we can proxy the original object with the
+	                // AsmInterceptorWrapper
+	                intercepted = AsmInterceptorWrapper.createProxyObject(original
+	                        .getClass().getClassLoader(), cm, interceptors,
+	                        original, original.getClass());
+	            } 
+	            else if (cglibAvailable)
+	            {
+	                LOGGER.debug("cglib available for interceptors");
+	                // otherwise we're using cglib and need to use the interfaces
+	                // with the CgLibInterceptorWrapper
+	                intercepted = CgLibInterceptorWrapper.createProxyObject(
+	                        original.getClass().getClassLoader(), cm,
+	                        interceptors, original, original.getClass()
+	                                .getInterfaces());
+	            }
+	            else
+	            {
+	            	return original;
+	            }
+            }
+            catch (Throwable u) 
+            {
+            	LOGGER.info("No quiesce support is available, so blueprint components will not participate in quiesce operations");
+            	return original;
+            }
+            
+            return intercepted;
 
-        public Object getService(Bundle bundle, ServiceRegistration registration) {
-            return ServiceRecipe.this.getService(bundle, registration);
         }
 
         public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {

Modified: incubator/aries/trunk/blueprint/blueprint-itests/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-itests/pom.xml?rev=995797&r1=995796&r2=995797&view=diff
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-itests/pom.xml (original)
+++ incubator/aries/trunk/blueprint/blueprint-itests/pom.xml Fri Sep 10 14:08:34 2010
@@ -131,6 +131,34 @@
             <artifactId>asm-all</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+        	<groupId>org.apache.aries.quiesce</groupId>
+        	<artifactId>org.apache.aries.quiesce.api</artifactId>
+        	<version>0.3-incubating-SNAPSHOT</version>
+        	<type>bundle</type>
+        	<scope>provided</scope>
+        </dependency>
+        <dependency>
+        	<groupId>org.apache.aries.blueprint</groupId>
+        	<artifactId>org.apache.aries.blueprint.testquiescebundle</artifactId>
+        	<version>0.3-incubating-SNAPSHOT</version>
+        	<type>bundle</type>
+        	<scope>compile</scope>
+        </dependency>
+        <dependency>
+        	<groupId>org.apache.aries.blueprint</groupId>
+        	<artifactId>org.apache.aries.blueprint.core</artifactId>
+        	<version>0.3-incubating-SNAPSHOT</version>
+        	<type>bundle</type>
+        	<scope>compile</scope>
+        </dependency>
+        <dependency>
+        	<groupId>org.apache.aries.blueprint</groupId>
+        	<artifactId>org.apache.aries.blueprint.cm</artifactId>
+        	<version>0.3-incubating-SNAPSHOT</version>
+        	<type>bundle</type>
+        	<scope>compile</scope>
+        </dependency>
 
     </dependencies>
 

Added: incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/QuiesceBlueprintTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/QuiesceBlueprintTest.java?rev=995797&view=auto
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/QuiesceBlueprintTest.java (added)
+++ incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/QuiesceBlueprintTest.java Fri Sep 10 14:08:34 2010
@@ -0,0 +1,469 @@
+/*  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.itests;
+
+import static org.junit.Assert.assertNotNull;
+import static org.ops4j.pax.exam.CoreOptions.bootDelegationPackages;
+import static org.ops4j.pax.exam.CoreOptions.equinox;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
+import static org.ops4j.pax.exam.OptionUtils.combine;
+import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.vmOption;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.apache.aries.blueprint.testquiescebundle.TestBean;
+import org.apache.aries.quiesce.manager.QuiesceCallback;
+import org.apache.aries.quiesce.participant.QuiesceParticipant;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Inject;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.container.def.options.VMOption;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.ops4j.pax.exam.options.BootDelegationOption;
+import org.ops4j.pax.exam.options.MavenArtifactProvisionOption;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.util.tracker.ServiceTracker;
+
+@RunWith(JUnit4TestRunner.class)
+public class QuiesceBlueprintTest extends AbstractIntegrationTest{
+
+  private static class TestQuiesceCallback implements QuiesceCallback
+  {
+    private int calls = 0;
+
+	public void bundleQuiesced(Bundle... bundlesQuiesced) {
+		System.out.println("bundleQuiesced "+ bundlesQuiesced);
+	      calls++;
+	}
+	
+	public int getCalls() {
+		return calls;
+	}
+  }
+
+  private static final int DEFAULT_TIMEOUT = 30000;
+  
+  @Inject
+  protected BundleContext bundleContext;
+ 
+  
+  private QuiesceParticipant getParticipant(String bundleName) throws InvalidSyntaxException {
+    ServiceReference[] refs = bundleContext.getServiceReferences(QuiesceParticipant.class.getName(), null);
+    
+    if(refs != null) {
+      for(ServiceReference ref : refs) {
+        if(ref.getBundle().getSymbolicName().equals(bundleName))
+          return (QuiesceParticipant) bundleContext.getService(ref);
+        else System.out.println(ref.getBundle().getSymbolicName());
+      }
+    }
+    
+    
+    return null;
+  }
+
+  @org.ops4j.pax.exam.junit.Configuration
+  public static Option[] configuration() {
+    Option[] options = options(
+        bootDelegationPackages("javax.transaction", "javax.transaction.*"),
+        vmOption("-Dorg.osgi.framework.system.packages=javax.accessibility,javax.activation,javax.activity,javax.annotation,javax.annotation.processing,javax.crypto,javax.crypto.interfaces,javax.crypto.spec,javax.imageio,javax.imageio.event,javax.imageio.metadata,javax.imageio.plugins.bmp,javax.imageio.plugins.jpeg,javax.imageio.spi,javax.imageio.stream,javax.jws,javax.jws.soap,javax.lang.model,javax.lang.model.element,javax.lang.model.type,javax.lang.model.util,javax.management,javax.management.loading,javax.management.modelmbean,javax.management.monitor,javax.management.openmbean,javax.management.relation,javax.management.remote,javax.management.remote.rmi,javax.management.timer,javax.naming,javax.naming.directory,javax.naming.event,javax.naming.ldap,javax.naming.spi,javax.net,javax.net.ssl,javax.print,javax.print.attribute,javax.print.attribute.standard,javax.print.event,javax.rmi,javax.rmi.CORBA,javax.rmi.ssl,javax.script,javax.security.auth,javax.security.auth.callback,
 javax.security.auth.kerberos,javax.security.auth.login,javax.security.auth.spi,javax.security.auth.x500,javax.security.cert,javax.security.sasl,javax.sound.midi,javax.sound.midi.spi,javax.sound.sampled,javax.sound.sampled.spi,javax.sql,javax.sql.rowset,javax.sql.rowset.serial,javax.sql.rowset.spi,javax.swing,javax.swing.border,javax.swing.colorchooser,javax.swing.event,javax.swing.filechooser,javax.swing.plaf,javax.swing.plaf.basic,javax.swing.plaf.metal,javax.swing.plaf.multi,javax.swing.plaf.synth,javax.swing.table,javax.swing.text,javax.swing.text.html,javax.swing.text.html.parser,javax.swing.text.rtf,javax.swing.tree,javax.swing.undo,javax.tools,javax.xml,javax.xml.bind,javax.xml.bind.annotation,javax.xml.bind.annotation.adapters,javax.xml.bind.attachment,javax.xml.bind.helpers,javax.xml.bind.util,javax.xml.crypto,javax.xml.crypto.dom,javax.xml.crypto.dsig,javax.xml.crypto.dsig.dom,javax.xml.crypto.dsig.keyinfo,javax.xml.crypto.dsig.spec,javax.xml.datatype,javax.xml.name
 space,javax.xml.parsers,javax.xml.soap,javax.xml.stream,javax.xml.stream.events,javax.xml.stream.util,javax.xml.transform,javax.xml.transform.dom,javax.xml.transform.sax,javax.xml.transform.stax,javax.xml.transform.stream,javax.xml.validation,javax.xml.ws,javax.xml.ws.handler,javax.xml.ws.handler.soap,javax.xml.ws.http,javax.xml.ws.soap,javax.xml.ws.spi,javax.xml.xpath,org.ietf.jgss,org.omg.CORBA,org.omg.CORBA.DynAnyPackage,org.omg.CORBA.ORBPackage,org.omg.CORBA.TypeCodePackage,org.omg.CORBA.portable,org.omg.CORBA_2_3,org.omg.CORBA_2_3.portable,org.omg.CosNaming,org.omg.CosNaming.NamingContextExtPackage,org.omg.CosNaming.NamingContextPackage,org.omg.Dynamic,org.omg.DynamicAny,org.omg.DynamicAny.DynAnyFactoryPackage,org.omg.DynamicAny.DynAnyPackage,org.omg.IOP,org.omg.IOP.CodecFactoryPackage,org.omg.IOP.CodecPackage,org.omg.Messaging,org.omg.PortableInterceptor,org.omg.PortableInterceptor.ORBInitInfoPackage,org.omg.PortableServer,org.omg.PortableServer.CurrentPackage,org.omg.
 PortableServer.POAManagerPackage,org.omg.PortableServer.POAPackage,org.omg.PortableServer.ServantLocatorPackage,org.omg.PortableServer.portable,org.omg.SendingContext,org.omg.stub.java.rmi,org.w3c.dom,org.w3c.dom.bootstrap,org.w3c.dom.css,org.w3c.dom.events,org.w3c.dom.html,org.w3c.dom.ls,org.w3c.dom.ranges,org.w3c.dom.stylesheets,org.w3c.dom.traversal,org.w3c.dom.views,org.xml.sax,org.xml.sax.ext,org.xml.sax.helpers,javax.transaction;partial=true;mandatory:=partial,javax.transaction.xa;partial=true;mandatory:=partial"),
+        
+        // Log
+        mavenBundle("org.ops4j.pax.logging", "pax-logging-api"),
+        mavenBundle("org.ops4j.pax.logging", "pax-logging-service"),
+        // Felix Config Admin
+        mavenBundle("org.apache.felix", "org.apache.felix.configadmin"),
+        // Felix mvn url handler
+        mavenBundle("org.ops4j.pax.url", "pax-url-mvn"),
+
+        // this is how you set the default log level when using pax
+        // logging (logProfile)
+        systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("DEBUG"),
+
+        // Bundles
+        mavenBundle("asm","asm-all"),
+        mavenBundle("org.apache.servicemix.bundles", "org.apache.servicemix.bundles.cglib"),
+        
+        mavenBundle("org.apache.aries.quiesce", "org.apache.aries.quiesce.api"),
+        mavenBundle("org.apache.aries", "org.apache.aries.util"),
+        mavenBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint"), 
+        mavenBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint.testbundlea").noStart(),
+        mavenBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint.testbundleb").noStart(),
+        mavenBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint.testquiescebundle"),
+        mavenBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint.cm"),
+        mavenBundle("org.osgi", "org.osgi.compendium"),
+        
+        //new VMOption( "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000" ),
+        
+        equinox().version("3.5.0"));
+    options = updateOptions(options);
+    return options;
+  }
+  
+  
+  protected Bundle getBundle(String symbolicName) {
+    return getBundle(symbolicName, null);
+  }
+
+  protected Bundle getBundle(String bundleSymbolicName, String version) {
+    Bundle result = null;
+    for (Bundle b : bundleContext.getBundles()) {
+      if (b.getSymbolicName().equals(bundleSymbolicName)) {
+        if (version == null
+            || b.getVersion().equals(Version.parseVersion(version))) {
+          result = b;
+          break;
+        }
+      }
+    }
+    return result;
+  }
+
+  public static BootDelegationOption bootDelegation() {
+    return new BootDelegationOption("org.apache.aries.unittest.fixture");
+  }
+  
+  public static MavenArtifactProvisionOption mavenBundle(String groupId,
+      String artifactId) {
+    return CoreOptions.mavenBundle().groupId(groupId).artifactId(artifactId)
+        .versionAsInProject();
+  }
+
+  protected static Option[] updateOptions(Option[] options) {
+    // We need to add pax-exam-junit here when running with the ibm
+    // jdk to avoid the following exception during the test run:
+    // ClassNotFoundException: org.ops4j.pax.exam.junit.Configuration
+    if ("IBM Corporation".equals(System.getProperty("java.vendor"))) {
+      Option[] ibmOptions = options(wrappedBundle(mavenBundle(
+          "org.ops4j.pax.exam", "pax-exam-junit")));
+      options = combine(ibmOptions, options);
+    }
+
+    return options;
+  }
+
+  protected <T> T getOsgiService(Class<T> type, long timeout) {
+    return getOsgiService(type, null, timeout);
+  }
+
+  protected <T> T getOsgiService(Class<T> type) {
+    return getOsgiService(type, null, DEFAULT_TIMEOUT);
+  }
+  
+  protected <T> T getOsgiService(Class<T> type, String filter, long timeout) {
+    return getOsgiService(null, type, filter, timeout);
+  }
+
+  protected <T> T getOsgiService(BundleContext bc, Class<T> type,
+      String filter, long timeout) {
+    ServiceTracker tracker = null;
+    try {
+      String flt;
+      if (filter != null) {
+        if (filter.startsWith("(")) {
+          flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")"
+              + filter + ")";
+        } else {
+          flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")("
+              + filter + "))";
+        }
+      } else {
+        flt = "(" + Constants.OBJECTCLASS + "=" + type.getName() + ")";
+      }
+      Filter osgiFilter = FrameworkUtil.createFilter(flt);
+      tracker = new ServiceTracker(bc == null ? bundleContext : bc, osgiFilter,
+          null);
+      tracker.open();
+      // Note that the tracker is not closed to keep the reference
+      // This is buggy, has the service reference may change i think
+      Object svc = type.cast(tracker.waitForService(timeout));
+      if (svc == null) {
+        throw new RuntimeException("Gave up waiting for service " + flt);
+      }
+      return type.cast(svc);
+    } catch (InvalidSyntaxException e) {
+      throw new IllegalArgumentException("Invalid filter", e);
+    } catch (InterruptedException e) {
+      throw new RuntimeException(e);
+    }
+  }
+  
+  @Test
+  public void testBasicQuieseEmptyCounter() throws Exception 
+  {
+	  //This test checks that a single bundle when called will not quiesce while 
+	  //there is an active request (method sleeps), but will quiesce after the 
+	  //request is completed. 
+	  
+	System.out.println("In testBasicQuieseEmptyCounter");
+	Object obj = getOsgiService(TestBean.class);
+	
+	if (obj != null)
+	{
+	  QuiesceParticipant participant = getParticipant("org.apache.aries.blueprint");
+	  
+	  if (participant != null)
+	  {
+	    System.out.println(obj.getClass().getName());
+
+	    TestQuiesceCallback callback = new TestQuiesceCallback();
+	    
+	    Bundle bundle = getBundle("org.apache.aries.blueprint.testquiescebundle");
+	    
+	    System.out.println("Got the bundle");
+	    
+	    List<Bundle> bundles = new ArrayList<Bundle>();
+	    bundles.add(bundle);
+	    
+	    Thread t = new Thread(new TestBeanClient((TestBean)obj, 1500));
+	    t.start();
+
+	    System.out.println("Thread Started");
+	    
+	    participant.quiesce(callback, bundles);
+	    
+	    System.out.println("Called Quiesce");
+	    
+	    Thread.sleep(1000);
+	    
+	    Assert.assertTrue("Quiesce callback should not have occurred yet; calls should be 0, but it is "+callback.getCalls(), callback.getCalls()==0);
+	    
+	    Thread.sleep(1500);
+	    
+	    System.out.println("After second sleep");
+	    
+	    Assert.assertTrue("Quiesce callback should have occurred once; calls should be 1, but it is "+callback.getCalls(), callback.getCalls()==1);
+	    
+ 	  }
+  	  else
+	  {
+		throw new Exception("No Quiesce Participant found for the blueprint service");
+	  }
+  
+	  System.out.println("done");
+	}
+	else
+	{
+		throw new Exception("No Service returned for " + TestBean.class);
+	}
+  }
+  
+  @Test
+  public void testNoServicesQuiesce() throws Exception {
+   
+   //This test covers the case where one of the bundles being asked to quiesce has no 
+   //services. It should be quiesced immediately.
+	  
+   System.out.println("In testNoServicesQuiesce");
+	Object obj = getOsgiService(TestBean.class);
+	
+	if (obj != null)
+	{    
+		QuiesceParticipant participant = getParticipant("org.apache.aries.blueprint");
+		
+		if (participant != null)
+		{
+			TestQuiesceCallback callbackA = new TestQuiesceCallback();
+			TestQuiesceCallback callbackB = new TestQuiesceCallback();
+		    
+			//bundlea provides the ns handlers, bean processors, interceptors etc for this test.
+	        Bundle bundlea = getBundle("org.apache.aries.blueprint.testbundlea");
+	        assertNotNull(bundlea);
+	        bundlea.start();
+	        
+	        //bundleb has no services and makes use of the extensions provided by bundlea
+	        Bundle bundleb = getBundle("org.apache.aries.blueprint.testbundleb");
+	        assertNotNull(bundleb);
+	        bundleb.start();
+	        
+			participant.quiesce(callbackB, Collections.singletonList(getBundle(
+				"org.apache.aries.blueprint.testbundleb")));
+			
+		    System.out.println("Called Quiesce");
+		    
+		    Thread.sleep(200);
+		    
+		    Assert.assertTrue("Quiesce callback B should have occurred; calls should be 1, but it is "+callbackB.getCalls(), callbackB.getCalls()==1);
+		    Assert.assertTrue("Quiesce callback A should not have occurred yet; calls should be 0, but it is "+callbackA.getCalls(), callbackA.getCalls()==0);
+		    
+		    participant.quiesce(callbackA, Collections.singletonList(getBundle(
+			"org.apache.aries.blueprint.testbundlea")));
+				    
+		    Thread.sleep(1000);
+		    
+		    System.out.println("After second sleep");
+		    
+		    Assert.assertTrue("Quiesce callback A should have occurred once; calls should be 1, but it is "+callbackA.getCalls(), callbackA.getCalls()==1);
+		    Assert.assertTrue("Quiesce callback B should have occurred once; calls should be 1, but it is "+callbackB.getCalls(), callbackB.getCalls()==1);
+		    
+		}else{
+			throw new Exception("No Quiesce Participant found for the blueprint service");
+		}
+	}else{
+		throw new Exception("No Service returned for " + TestBean.class);
+	}
+  }
+
+  @Test
+  public void testMultiBundleQuiesce() throws Exception {
+   
+   //This test covers the case where two bundles are quiesced at the same time. 
+   //Bundle A should quiesce immediately, quiesce bundle should quiesce after the 
+   //request has completed.
+	  
+   System.out.println("In testMultiBundleQuiesce");
+	Object obj = getOsgiService(TestBean.class);
+	
+	if (obj != null)
+	{    
+		QuiesceParticipant participant = getParticipant("org.apache.aries.blueprint");
+		
+		if (participant != null)
+		{
+			TestQuiesceCallback callback = new TestQuiesceCallback();
+		    
+			//bundlea provides the ns handlers, bean processors, interceptors etc for this test.
+	        Bundle bundlea = getBundle("org.apache.aries.blueprint.testbundlea");
+	        assertNotNull(bundlea);
+	        bundlea.start();
+	        
+	        //quiesce bundle will sleep for a second so will quiesce after that
+		    Bundle bundleq = getBundle("org.apache.aries.blueprint.testquiescebundle");
+		    
+		    System.out.println("Got the bundle");
+		    
+		    List<Bundle> bundles = new ArrayList<Bundle>();
+		    bundles.add(bundlea);
+		    bundles.add(bundleq);
+		    
+		    Thread t = new Thread(new TestBeanClient((TestBean)obj, 1500));
+		    t.start();
+	        
+			participant.quiesce(callback, bundles);
+			
+		    System.out.println("Called Quiesce");
+		    
+		    Thread.sleep(500);
+		    
+		    Assert.assertTrue("Quiesce callback should have occurred once for bundle a but not for bundle q; calls should be 1, but it is "+callback.getCalls(), callback.getCalls()==1);
+		    
+		    Thread.sleep(1500);
+		    
+		    System.out.println("After second sleep");
+		    
+		    Assert.assertTrue("Quiesce callback should have occurred twice, once for bundle a and q respectively; calls should be 2, but it is "+callback.getCalls(), callback.getCalls()==2);
+		    
+		}else{
+			throw new Exception("No Quiesce Participant found for the blueprint service");
+		}
+	}else{
+		throw new Exception("No Service returned for " + TestBean.class);
+	}
+  }
+  
+  @Test
+  public void testMultiRequestQuiesce() throws Exception {
+   
+   //This test covers the case where we have two active requests when 
+   //the bundle is being quiesced.
+	  
+   System.out.println("In testMultiRequestQuiesce");
+	Object obj = getOsgiService(TestBean.class);
+	
+	if (obj != null)
+	{    
+		QuiesceParticipant participant = getParticipant("org.apache.aries.blueprint");
+		
+		if (participant != null)
+		{
+			TestQuiesceCallback callback = new TestQuiesceCallback();
+			TestBeanClient client =  new TestBeanClient((TestBean)obj, 1500);
+		    
+
+	        //quiesce bundle will sleep for a second so will quiesce after that
+		    Bundle bundle = getBundle("org.apache.aries.blueprint.testquiescebundle");
+		    
+		    System.out.println("Got the bundle");
+		    
+		    List<Bundle> bundles = new ArrayList<Bundle>();
+		    bundles.add(bundle);
+		    
+		    Thread t = new Thread(client);
+		    t.start();
+	        
+			participant.quiesce(callback, bundles);
+			
+		    System.out.println("Called Quiesce, putting in a new request");
+		    
+		    Thread t2 = new Thread(client);
+		    t2.start();
+		    
+		    Thread.sleep(5000);
+		    
+		    Assert.assertTrue("Quiesce callback should have occurred once; calls should be 1, but it is "+callback.getCalls(), callback.getCalls()==1);
+		    
+   
+		}else{
+			throw new Exception("No Quiesce Participant found for the blueprint service");
+		}
+	}else{
+		throw new Exception("No Service returned for " + TestBean.class);
+	}
+  }
+  
+  
+  private class TestBeanClient implements Runnable
+  {
+    private TestBean myService;
+    private int time;
+    
+    public TestBeanClient(TestBean myService, int time)
+    {
+      this.myService = myService;
+      this.time = time;
+    }
+	  
+	public void run() 
+	{
+	  try
+	  {
+		System.out.println("In Test Bean Client - Sleeping zzzzzzz");
+		myService.sleep(time);
+		System.out.println("Woken up");
+	  }
+	  catch (InterruptedException ie)
+	  {
+		  ie.printStackTrace();
+	  }
+	}
+	  
+  }
+}

Added: incubator/aries/trunk/blueprint/blueprint-testquiescebundle/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-testquiescebundle/pom.xml?rev=995797&view=auto
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-testquiescebundle/pom.xml (added)
+++ incubator/aries/trunk/blueprint/blueprint-testquiescebundle/pom.xml Fri Sep 10 14:08:34 2010
@@ -0,0 +1,52 @@
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <description>Blueprint Test Quiesce Bundle, tests the blueprint participant for the quiesce functionality.</description>
+    <parent>
+        <groupId>org.apache.aries.blueprint</groupId>
+        <artifactId>blueprint</artifactId>
+        <version>0.3-incubating-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>org.apache.aries.blueprint.testquiescebundle</artifactId>
+    <name>Apache Aries Blueprint Test Quiesce Bundle</name>
+    <packaging>bundle</packaging>
+
+    <properties>
+        <aries.osgi.activator>
+            org.apache.aries.blueprint.testquiescebundle.Activator
+        </aries.osgi.activator>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.eclipse</groupId>
+            <artifactId>osgi</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.aries.blueprint</groupId>
+            <artifactId>org.apache.aries.blueprint.api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.aries.blueprint</groupId>
+            <artifactId>org.apache.aries.blueprint.core</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

Added: incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/Activator.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/Activator.java?rev=995797&view=auto
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/Activator.java (added)
+++ incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/Activator.java Fri Sep 10 14:08:34 2010
@@ -0,0 +1,30 @@
+/**
+ *  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.testquiescebundle;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+    public void start(BundleContext context) {
+    }
+
+    public void stop(BundleContext context) {
+    }
+   
+}

Added: incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/TestBean.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/TestBean.java?rev=995797&view=auto
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/TestBean.java (added)
+++ incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/TestBean.java Fri Sep 10 14:08:34 2010
@@ -0,0 +1,25 @@
+/**
+ *  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.testquiescebundle;
+
+public class TestBean 
+{
+    public void sleep(int time) throws InterruptedException
+    {
+		Thread.sleep(time);
+     }
+}

Added: incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/blueprint/config.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/blueprint/config.xml?rev=995797&view=auto
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/blueprint/config.xml (added)
+++ incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/blueprint/config.xml Fri Sep 10 14:08:34 2010
@@ -0,0 +1,31 @@
+<?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.
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
+           xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
+
+           default-availability="optional">
+
+  <bean id="TestBean" class="org.apache.aries.blueprint.testquiescebundle.TestBean" scope="singleton">
+  </bean>
+
+ <service interface="org.apache.aries.blueprint.testquiescebundle.TestBean" ref="TestBean">
+ </service>
+  
+</blueprint>
+

Modified: incubator/aries/trunk/blueprint/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/pom.xml?rev=995797&r1=995796&r2=995797&view=diff
==============================================================================
--- incubator/aries/trunk/blueprint/pom.xml (original)
+++ incubator/aries/trunk/blueprint/pom.xml Fri Sep 10 14:08:34 2010
@@ -91,6 +91,11 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.aries.blueprint</groupId>
+                <artifactId>org.apache.aries.blueprint.testquiescebundle</artifactId>
+                <version>${version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.aries.blueprint</groupId>
                 <artifactId>org.apache.aries.blueprint.itests</artifactId>
                 <version>${version}</version>
             </dependency>
@@ -140,6 +145,18 @@
                 <artifactId>xbean-finder</artifactId>
                 <version>3.7</version>
             </dependency>
+            <dependency>
+            	<groupId>org.apache.aries.blueprint</groupId>
+            	<artifactId>org.apache.aries.blueprint.testquiescebundle</artifactId>
+            	<version>0.3-incubating-SNAPSHOT</version>
+            	<type>bundle</type>
+            	<scope>compile</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.aries.quiesce</groupId>
+                <artifactId>org.apache.aries.quiesce.api</artifactId>
+                <version>0.3-incubating-SNAPSHOT</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
@@ -180,6 +197,7 @@
         <module>blueprint-annotation-itest</module>
         <module>blueprint-testbundlea</module>
         <module>blueprint-testbundleb</module>
+        <module>blueprint-testquiescebundle</module>
         <module>blueprint-itests</module>
     </modules>
 



Re: svn commit: r995797 - in /incubator/aries/trunk/blueprint: ./ blueprint-annotation-itest/src/test/java/org/apache/aries/blueprint/itests/ blueprint-bundle/ blueprint-core/ blueprint-core/src/main/java/org/apache/aries/blueprint/container/ blueprint-ite...

Posted by Joe Bohn <jo...@gmail.com>.
Hi Holly,

Can you delete the maven-eclipse.xml file added below which I presume 
was added by mistake?

Thanks,
Joe


On 9/10/10 10:08 AM, cumminsh@apache.org wrote:
> Author: cumminsh
> Date: Fri Sep 10 14:08:34 2010
> New Revision: 995797
>
> URL: http://svn.apache.org/viewvc?rev=995797&view=rev
> Log:
> ARIES-383: Committing patch from Hannah Ramlee and Simon Maple for blueprint quiesce participant.
>
> Added:
>      incubator/aries/trunk/blueprint/blueprint-core/maven-eclipse.xml
>      incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintQuiesceParticipant.java
>      incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/DestroyCallback.java
>      incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/QuiesceInterceptor.java
>      incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/QuiesceBlueprintTest.java
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/pom.xml
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/Activator.java
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/TestBean.java
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/blueprint/
>      incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/blueprint/config.xml
> Modified:
>      incubator/aries/trunk/blueprint/blueprint-annotation-itest/src/test/java/org/apache/aries/blueprint/itests/BlueprintAnnotationTest.java
>      incubator/aries/trunk/blueprint/blueprint-bundle/pom.xml
>      incubator/aries/trunk/blueprint/blueprint-core/pom.xml
>      incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
>      incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java
>      incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java
>      incubator/aries/trunk/blueprint/blueprint-itests/pom.xml
>      incubator/aries/trunk/blueprint/pom.xml
>
> Modified: incubator/aries/trunk/blueprint/blueprint-annotation-itest/src/test/java/org/apache/aries/blueprint/itests/BlueprintAnnotationTest.java
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-annotation-itest/src/test/java/org/apache/aries/blueprint/itests/BlueprintAnnotationTest.java?rev=995797&r1=995796&r2=995797&view=diff
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-annotation-itest/src/test/java/org/apache/aries/blueprint/itests/BlueprintAnnotationTest.java (original)
> +++ incubator/aries/trunk/blueprint/blueprint-annotation-itest/src/test/java/org/apache/aries/blueprint/itests/BlueprintAnnotationTest.java Fri Sep 10 14:08:34 2010
> @@ -77,7 +77,7 @@ public class BlueprintAnnotationTest ext
>
>          obj = getOsgiService(bundleContext, Foo.class, null, 5000);
>           assertNotNull(obj);
> -        assertSame(foo, obj);
> +        assertEquals(foo.toString(), obj.toString());
>       }
>
>       @org.ops4j.pax.exam.junit.Configuration
>
> Modified: incubator/aries/trunk/blueprint/blueprint-bundle/pom.xml
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-bundle/pom.xml?rev=995797&r1=995796&r2=995797&view=diff
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-bundle/pom.xml (original)
> +++ incubator/aries/trunk/blueprint/blueprint-bundle/pom.xml Fri Sep 10 14:08:34 2010
> @@ -46,6 +46,8 @@
>               org.objectweb.asm*;version="[3.1,4)";resolution:=optional,
>               org.osgi.service.cm;version="[1.2.0,2.0.0)",
>               org.apache.aries.blueprint.annotation.service;resolution:=optional,
> +            org.apache.aries.quiesce.manager;version="[0.2,1.0)";resolution:=optional,
> +            org.apache.aries.quiesce.participant;version="[0.2,1.0)";resolution:=optional,
>               *
>           </aries.osgi.import>
>           <aries.osgi.export>
> @@ -107,6 +109,11 @@
>               <artifactId>org.osgi.compendium</artifactId>
>               <scope>provided</scope>
>           </dependency>
> +<dependency>
> +<groupId>org.apache.aries.quiesce</groupId>
> +<artifactId>org.apache.aries.quiesce.api</artifactId>
> +<scope>provided</scope>
> +</dependency>
>
>       </dependencies>
>
>
> Added: incubator/aries/trunk/blueprint/blueprint-core/maven-eclipse.xml
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/maven-eclipse.xml?rev=995797&view=auto
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-core/maven-eclipse.xml (added)
> +++ incubator/aries/trunk/blueprint/blueprint-core/maven-eclipse.xml Fri Sep 10 14:08:34 2010
> @@ -0,0 +1,8 @@
> +<project default="copy-resources">
> +<target name="init"/>
> +<target name="copy-resources" depends="init">
> +<copy todir="target/classes/org/apache/aries/blueprint" filtering="false">
> +<fileset dir="/home/cumminsh/projects/aries/apache-workspace/aries/blueprint/blueprint-api/src/main/resources/org/osgi/service/blueprint" includes="blueprint.xsd" excludes="**/*.java"/>
> +</copy>
> +</target>
> +</project>
> \ No newline at end of file
>
> Modified: incubator/aries/trunk/blueprint/blueprint-core/pom.xml
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/pom.xml?rev=995797&r1=995796&r2=995797&view=diff
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-core/pom.xml (original)
> +++ incubator/aries/trunk/blueprint/blueprint-core/pom.xml Fri Sep 10 14:08:34 2010
> @@ -46,6 +46,8 @@
>           org.osgi.service.event*;resolution:=optional,
>           org.osgi.service.framework;resolution:=optional,
>           org.apache.aries.blueprint.annotation.service;resolution:=optional,
> +        org.apache.aries.quiesce.manager;version="[0.2,1.0)";resolution:=optional,
> +        org.apache.aries.quiesce.participant;version="[0.2,1.0)";resolution:=optional,
>           *
>         </aries.osgi.import>
>         <aries.osgi.export.service>
> @@ -101,6 +103,12 @@
>             <artifactId>asm-all</artifactId>
>             <optional>true</optional>
>         </dependency>
> +<dependency>
> +      	<groupId>org.apache.aries.quiesce</groupId>
> +      	<artifactId>org.apache.aries.quiesce.api</artifactId>
> +      	<version>0.3-incubating-SNAPSHOT</version>
> +      	<scope>provided</scope>
> +</dependency>
>     </dependencies>
>
>       <build>
>
> Modified: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java?rev=995797&r1=995796&r2=995797&view=diff
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java (original)
> +++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java Fri Sep 10 14:08:34 2010
> @@ -648,7 +648,7 @@ public class BlueprintContainerImpl impl
>           }
>       }
>
> -    private void unregisterServices() {
> +    protected void unregisterServices() {
>           if (repository != null) {
>               List<ServiceRecipe>  recipes = this.services;
>               this.services = null;
> @@ -821,6 +821,23 @@ public class BlueprintContainerImpl impl
>           eventDispatcher.blueprintEvent(new BlueprintEvent(BlueprintEvent.DESTROYED, getBundleContext().getBundle(), getExtenderBundle()));
>           LOGGER.debug("Blueprint container destroyed: {}", this.bundleContext);
>       }
> +
> +    protected void quiesce() {
> +        destroyed = true;
> +        eventDispatcher.blueprintEvent(new BlueprintEvent(BlueprintEvent.DESTROYING, getBundleContext().getBundle(), getExtenderBundle()));
> +
> +        if (timeoutFuture != null) {
> +            timeoutFuture.cancel(false);
> +        }
> +        if (registration != null) {
> +            registration.unregister();
> +        }
> +        if (handlerSet != null) {
> +            handlerSet.removeListener(this);
> +            handlerSet.destroy();
> +        }
> +        LOGGER.debug("Blueprint container quiesced: {}", this.bundleContext);
> +    }
>
>       public void namespaceHandlerRegistered(URI uri) {
>           if (namespaces != null&&  namespaces.contains(uri)) {
>
> Modified: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java?rev=995797&r1=995796&r2=995797&view=diff
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java (original)
> +++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java Fri Sep 10 14:08:34 2010
> @@ -49,9 +49,7 @@ import org.osgi.framework.ServiceRegistr
>   import org.osgi.framework.SynchronousBundleListener;
>   import org.osgi.service.blueprint.container.BlueprintContainer;
>   import org.osgi.service.blueprint.container.BlueprintEvent;
> -import org.osgi.util.tracker.BundleTracker;
>   import org.osgi.util.tracker.BundleTrackerCustomizer;
> -import org.osgi.util.tracker.ServiceTracker;
>   import org.slf4j.Logger;
>   import org.slf4j.LoggerFactory;
>
> @@ -62,6 +60,8 @@ import org.slf4j.LoggerFactory;
>    */
>   public class BlueprintExtender implements BundleActivator, SynchronousBundleListener {
>
> +	/** The QuiesceParticipant implementation class name */
> +	private static final String QUIESCE_PARTICIPANT_CLASS = "org.apache.aries.quiesce.participant.QuiesceParticipant";
>       private static final Logger LOGGER = LoggerFactory.getLogger(BlueprintExtender.class);
>
>       private BundleContext context;
> @@ -71,6 +71,7 @@ public class BlueprintExtender implement
>       private NamespaceHandlerRegistry handlers;
>       private RecursiveBundleTracker bt;
>       private ServiceRegistration parserServiceReg;
> +    private ServiceRegistration quiesceParticipantReg;
>
>       public void start(BundleContext context) {
>           LOGGER.debug("Starting blueprint extender...");
> @@ -90,6 +91,19 @@ public class BlueprintExtender implement
>           parserServiceReg = context.registerService(ParserService.class.getName(),
>               new ParserServiceImpl (handlers),
>               new Hashtable<Object, Object>());
> +
> +        try{
> +            context.getBundle().loadClass(QUIESCE_PARTICIPANT_CLASS);
> +            //Class was loaded, register
> +
> +            quiesceParticipantReg = context.registerService(QUIESCE_PARTICIPANT_CLASS,
> +              new BlueprintQuiesceParticipant(context, this),
> +              new Hashtable<Object, Object>());
> +        }
> +        catch (ClassNotFoundException e)
> +        {
> +            LOGGER.info("No quiesce support is available, so blueprint components will not participate in quiesce operations", e);
> +        }
>
>           LOGGER.debug("Blueprint extender started");
>       }
> @@ -123,6 +137,9 @@ public class BlueprintExtender implement
>           }
>
>           parserServiceReg.unregister();
> +
> +        if (quiesceParticipantReg != null)
> +          	quiesceParticipantReg.unregister();
>
>           // Orderly shutdown of containers
>           while (!containers.isEmpty()) {
> @@ -392,4 +409,9 @@ public class BlueprintExtender implement
>           }
>       }
>
> +    protected BlueprintContainerImpl getBlueprintContainerImpl(Bundle bundle)
> +    {
> +    	return (BlueprintContainerImpl) containers.get(bundle);
> +    }
> +
>   }
>
> Added: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintQuiesceParticipant.java
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintQuiesceParticipant.java?rev=995797&view=auto
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintQuiesceParticipant.java (added)
> +++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintQuiesceParticipant.java Fri Sep 10 14:08:34 2010
> @@ -0,0 +1,160 @@
> +/*
> + * 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.HashSet;
> +import java.util.List;
> +import java.util.Set;
> +import java.util.concurrent.ExecutorService;
> +import java.util.concurrent.LinkedBlockingQueue;
> +import java.util.concurrent.RejectedExecutionException;
> +import java.util.concurrent.ThreadFactory;
> +import java.util.concurrent.ThreadPoolExecutor;
> +import java.util.concurrent.TimeUnit;
> +
> +import org.apache.aries.blueprint.di.Recipe;
> +import org.apache.aries.quiesce.manager.QuiesceCallback;
> +import org.apache.aries.quiesce.participant.QuiesceParticipant;
> +import org.osgi.framework.Bundle;
> +import org.osgi.framework.BundleContext;
> +import org.osgi.framework.ServiceReference;
> +
> +public class BlueprintQuiesceParticipant implements QuiesceParticipant
> +{
> +	private BundleContext ctx;
> +	private BlueprintExtender extender;
> +	
> +	public BlueprintQuiesceParticipant(BundleContext context, BlueprintExtender extender)
> +	{
> +		this.ctx = context;
> +		this.extender = extender;
> +	}
> +
> +	/**
> +	 * A Threadpool for running quiesce operations
> +	 */
> +	private final ExecutorService executor = new ThreadPoolExecutor(0, 10, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadFactory()
> +	{
> +		public Thread newThread(Runnable r)
> +		{
> +	        Thread t = new Thread(r, "Blueprint-Container-ThreadPool");
> +	        t.setDaemon(true);
> +	        return t;
> +		}
> +    });
> +	
> +	public void quiesce(QuiesceCallback callback, List<Bundle>  bundlesToQuiesce)
> +	{
> +		for(Bundle b : bundlesToQuiesce)
> +		{
> +		  try
> +		  {
> +		    executor.execute(new QuiesceBundle(callback, b, extender));
> +		  }
> +		  catch (RejectedExecutionException re) {
> +		  }
> +		
> +		  //If we are quiescing, then we need to quiesce this threadpool!
> +		  if(b.equals(ctx.getBundle()))
> +		    executor.shutdown();
> +		}
> +	}
> +
> +  /**
> +   * A runnable Quiesce operation for a single bundle
> +   */
> +	private static final class QuiesceBundle implements Runnable
> +	{
> +		/** The bundle being quiesced */
> +		private final Bundle bundleToQuiesce;
> +		private QuiesceCallback callback;
> +		private BlueprintExtender extender;
> +		
> +		public QuiesceBundle(QuiesceCallback callback, Bundle bundleToQuiesce,
> +				BlueprintExtender extender)
> +		{	
> +			super();
> +			this.callback = callback;
> +			this.bundleToQuiesce = bundleToQuiesce;
> +			this.extender = extender;
> +		}
> +
> +		public void run()
> +		{
> +			BlueprintContainerImpl container = extender.getBlueprintContainerImpl(bundleToQuiesce);
> +						
> +			BlueprintRepository repository = container.getRepository();
> +			Set<String>  names = repository.getNames();
> +			container.quiesce();
> +			boolean hasServices = false;
> +			
> +			for (String name: names)
> +			{
> +				Recipe recipe = repository.getRecipe(name);
> +				if (recipe instanceof ServiceRecipe)
> +				{
> +					hasServices = true;
> +					((ServiceRecipe)recipe).quiesce(new QuiesceDelegatingCallback(callback, bundleToQuiesce));
> +				}
> +			}
> +			//If the bundle has no services we can quiesce immediately
> +			if (!hasServices)
> +			{
> +				callback.bundleQuiesced(bundleToQuiesce);
> +			}
> +		}
> +	}
> +	
> +    /**
> +	 * A wrapper to protect our internals from the Quiesce API so that we can make it
> +	 * an optional dependency
> +	 */
> +	private static final class QuiesceDelegatingCallback implements DestroyCallback
> +	{
> +	
> +	  /** The callback to delegate to */
> +	  private final QuiesceCallback callback;
> +	
> +	  /** The single bundle being quiesced by this DestroyCallback */
> +	  private final Bundle toQuiesce;
> +	
> +	  private Set<String>  services = new HashSet<String>();
> +	
> +	  public QuiesceDelegatingCallback(QuiesceCallback cbk, Bundle b)
> +	  {
> +	    callback = cbk;
> +	    toQuiesce = b;
> +	
> +	    ServiceReference[] serviceRefs = b.getRegisteredServices();
> +	
> +	    for (ServiceReference ref : serviceRefs)
> +	    {
> +	  	  services.add(b.getBundleContext().getService(ref).toString());
> +	    }
> +	  }
> +	
> +	  public void callback(Object key)
> +	  {
> +	    if (key != null&&  services.remove(key.toString())&&  services.isEmpty())
> +	    {
> +	 	  	callback.bundleQuiesced(toQuiesce);
> +	    }
> +	  }
> +	}
> +}
>
> Added: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/DestroyCallback.java
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/DestroyCallback.java?rev=995797&view=auto
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/DestroyCallback.java (added)
> +++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/DestroyCallback.java Fri Sep 10 14:08:34 2010
> @@ -0,0 +1,26 @@
> +/**
> + * 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;
> +
> +/**
> + * A callback to indicate that a destroy operation has completed
> + */
> +public interface DestroyCallback {
> +  public void callback(Object key);
> +}
>
> Added: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/QuiesceInterceptor.java
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/QuiesceInterceptor.java?rev=995797&view=auto
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/QuiesceInterceptor.java (added)
> +++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/QuiesceInterceptor.java Fri Sep 10 14:08:34 2010
> @@ -0,0 +1,56 @@
> +/*
> + * 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.lang.reflect.Method;
> +
> +import org.apache.aries.blueprint.Interceptor;
> +import org.osgi.service.blueprint.reflect.ComponentMetadata;
> +
> +public class QuiesceInterceptor implements Interceptor{
> +
> +	private ServiceRecipe serviceRecipe;
> +	
> +	public QuiesceInterceptor(ServiceRecipe serviceRecipe)
> +	{
> +		this.serviceRecipe = serviceRecipe;
> +	}
> +	
> +    public Object preCall(ComponentMetadata cm, Method m, Object... parameters) throws Throwable
> +    {
> +   		serviceRecipe.incrementActiveCalls();
> +    	
> +    	return null;
> +    }
> +
> +    public void postCallWithReturn(ComponentMetadata cm, Method m, Object returnType, Object preCallToken) throws Throwable
> +    {
> +    	serviceRecipe.decrementActiveCalls();
> +    }
> +
> +    public void postCallWithException(ComponentMetadata cm, Method m, Throwable ex, Object preCallToken) throws Throwable
> +    {
> +    	serviceRecipe.decrementActiveCalls();
> +    }
> +
> +    public int getRank()
> +    {
> +    	return 0;
> +    }
> +}
>
> Modified: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java?rev=995797&r1=995796&r2=995797&view=diff
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java (original)
> +++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java Fri Sep 10 14:08:34 2010
> @@ -16,6 +16,7 @@
>    */
>   package org.apache.aries.blueprint.container;
>
> +
>   import java.util.ArrayList;
>   import java.util.Collections;
>   import java.util.Dictionary;
> @@ -29,12 +30,15 @@ import java.util.concurrent.atomic.Atomi
>
>   import org.apache.aries.blueprint.BlueprintConstants;
>   import org.apache.aries.blueprint.ExtendedBlueprintContainer;
> +import org.apache.aries.blueprint.Interceptor;
>   import org.apache.aries.blueprint.ServiceProcessor;
>   import org.apache.aries.blueprint.di.AbstractRecipe;
>   import org.apache.aries.blueprint.di.CollectionRecipe;
>   import org.apache.aries.blueprint.di.MapRecipe;
>   import org.apache.aries.blueprint.di.Recipe;
>   import org.apache.aries.blueprint.di.Repository;
> +import org.apache.aries.blueprint.proxy.AsmInterceptorWrapper;
> +import org.apache.aries.blueprint.proxy.CgLibInterceptorWrapper;
>   import org.apache.aries.blueprint.utils.JavaUtils;
>   import org.apache.aries.blueprint.utils.ReflectionUtils;
>   import org.osgi.framework.Bundle;
> @@ -43,6 +47,7 @@ import org.osgi.framework.ServiceFactory
>   import org.osgi.framework.ServiceReference;
>   import org.osgi.framework.ServiceRegistration;
>   import org.osgi.service.blueprint.container.ComponentDefinitionException;
> +import org.osgi.service.blueprint.reflect.ComponentMetadata;
>   import org.osgi.service.blueprint.reflect.RefMetadata;
>   import org.osgi.service.blueprint.reflect.ServiceMetadata;
>   import org.slf4j.Logger;
> @@ -70,6 +75,9 @@ public class ServiceRecipe extends Abstr
>       private Map registrationProperties;
>       private List<ServiceListener>  listeners;
>       private volatile Object service;
> +    private int activeCalls;
> +    private boolean quiesce;
> +    private DestroyCallback destroyCallback;
>
>       public ServiceRecipe(String name,
>                            ExtendedBlueprintContainer blueprintContainer,
> @@ -163,7 +171,7 @@ public class ServiceRecipe extends Abstr
>               LOGGER.debug("Registering service {} with interfaces {} and properties {}",
>                            new Object[] { name, classes, props });
>
> -            registration.set(blueprintContainer.registerService(classArray, new TriggerServiceFactory(), props));
> +            registration.set(blueprintContainer.registerService(classArray, new TriggerServiceFactory(this, metadata), props));
>           }
>       }
>
> @@ -361,10 +369,124 @@ public class ServiceRecipe extends Abstr
>           }
>       }
>
> -    private class TriggerServiceFactory implements ServiceFactory {
> +    protected void incrementActiveCalls()
> +    {
> +    	synchronized(this)
> +    	{
> +    		activeCalls++;	
> +		}
> +    }
> +
> +	protected void decrementActiveCalls()
> +	{
> +		
> +    	synchronized(this)
> +    	{
> +    		activeCalls--;
> +
> +			if (quiesce&&  activeCalls == 0)
> +			{
> +				destroyCallback.callback(service);
> +			}
> +    	}
> +	}
> +	
> +    public void quiesce(DestroyCallback destroyCallback)
> +    {
> +    	this.destroyCallback = destroyCallback;
> +    	quiesce = true;
> +    	unregister();
> +    	if(activeCalls == 0)
> +		{
> +			destroyCallback.callback(service);
> +		}
> +    }
> +
> +    private class TriggerServiceFactory implements ServiceFactory
> +    {
> +    	private QuiesceInterceptor interceptor;
> +    	private ServiceRecipe serviceRecipe;
> +    	private ComponentMetadata cm;
> +    	public TriggerServiceFactory(ServiceRecipe serviceRecipe, ComponentMetadata cm)
> +    	{
> +    		this.serviceRecipe = serviceRecipe;
> +    		this.cm = cm;
> +    	}
> +    	
> +        public Object getService(Bundle bundle, ServiceRegistration registration)
> +        {
> +        	Object original = ServiceRecipe.this.getService(bundle, registration);
> +        	Object intercepted = null;
> +            boolean asmAvailable = false;
> +            boolean cglibAvailable = false;
> +
> +            if (interceptor == null)
> +            {
> +            	interceptor = new QuiesceInterceptor(serviceRecipe);
> +            }
> +
> +            List<Interceptor>  interceptors = new ArrayList<Interceptor>();
> +            interceptors.add(interceptor);
> +
> +            try
> +            {
> +                // Try load load an asm class (to make sure it's actually
> +                // available)
> +                getClass().getClassLoader().loadClass(
> +                        "org.objectweb.asm.ClassVisitor");
> +                LOGGER.debug("asm available for interceptors");
> +                asmAvailable = true;
> +            }
> +            catch (Throwable t)
> +            {
> +                try
> +                {
> +                    // Try load load a cglib class (to make sure it's actually
> +                    // available)
> +                    getClass().getClassLoader().loadClass(
> +                            "net.sf.cglib.proxy.Enhancer");
> +                    cglibAvailable = true;
> +                }
> +                catch (Throwable u)
> +                {
> +                	LOGGER.info("No quiesce support is available, so blueprint components will not participate in quiesce operations");
> +                	return original;
> +                }
> +            }
> +
> +            try
> +            {
> +	            if (asmAvailable)
> +	            {
> +	                // if asm is available we can proxy the original object with the
> +	                // AsmInterceptorWrapper
> +	                intercepted = AsmInterceptorWrapper.createProxyObject(original
> +	                        .getClass().getClassLoader(), cm, interceptors,
> +	                        original, original.getClass());
> +	            }
> +	            else if (cglibAvailable)
> +	            {
> +	                LOGGER.debug("cglib available for interceptors");
> +	                // otherwise we're using cglib and need to use the interfaces
> +	                // with the CgLibInterceptorWrapper
> +	                intercepted = CgLibInterceptorWrapper.createProxyObject(
> +	                        original.getClass().getClassLoader(), cm,
> +	                        interceptors, original, original.getClass()
> +	                                .getInterfaces());
> +	            }
> +	            else
> +	            {
> +	            	return original;
> +	            }
> +            }
> +            catch (Throwable u)
> +            {
> +            	LOGGER.info("No quiesce support is available, so blueprint components will not participate in quiesce operations");
> +            	return original;
> +            }
> +
> +            return intercepted;
>
> -        public Object getService(Bundle bundle, ServiceRegistration registration) {
> -            return ServiceRecipe.this.getService(bundle, registration);
>           }
>
>           public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
>
> Modified: incubator/aries/trunk/blueprint/blueprint-itests/pom.xml
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-itests/pom.xml?rev=995797&r1=995796&r2=995797&view=diff
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-itests/pom.xml (original)
> +++ incubator/aries/trunk/blueprint/blueprint-itests/pom.xml Fri Sep 10 14:08:34 2010
> @@ -131,6 +131,34 @@
>               <artifactId>asm-all</artifactId>
>               <scope>test</scope>
>           </dependency>
> +<dependency>
> +        	<groupId>org.apache.aries.quiesce</groupId>
> +        	<artifactId>org.apache.aries.quiesce.api</artifactId>
> +        	<version>0.3-incubating-SNAPSHOT</version>
> +        	<type>bundle</type>
> +        	<scope>provided</scope>
> +</dependency>
> +<dependency>
> +        	<groupId>org.apache.aries.blueprint</groupId>
> +        	<artifactId>org.apache.aries.blueprint.testquiescebundle</artifactId>
> +        	<version>0.3-incubating-SNAPSHOT</version>
> +        	<type>bundle</type>
> +        	<scope>compile</scope>
> +</dependency>
> +<dependency>
> +        	<groupId>org.apache.aries.blueprint</groupId>
> +        	<artifactId>org.apache.aries.blueprint.core</artifactId>
> +        	<version>0.3-incubating-SNAPSHOT</version>
> +        	<type>bundle</type>
> +        	<scope>compile</scope>
> +</dependency>
> +<dependency>
> +        	<groupId>org.apache.aries.blueprint</groupId>
> +        	<artifactId>org.apache.aries.blueprint.cm</artifactId>
> +        	<version>0.3-incubating-SNAPSHOT</version>
> +        	<type>bundle</type>
> +        	<scope>compile</scope>
> +</dependency>
>
>       </dependencies>
>
>
> Added: incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/QuiesceBlueprintTest.java
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/QuiesceBlueprintTest.java?rev=995797&view=auto
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/QuiesceBlueprintTest.java (added)
> +++ incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/QuiesceBlueprintTest.java Fri Sep 10 14:08:34 2010
> @@ -0,0 +1,469 @@
> +/*  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.itests;
> +
> +import static org.junit.Assert.assertNotNull;
> +import static org.ops4j.pax.exam.CoreOptions.bootDelegationPackages;
> +import static org.ops4j.pax.exam.CoreOptions.equinox;
> +import static org.ops4j.pax.exam.CoreOptions.options;
> +import static org.ops4j.pax.exam.CoreOptions.systemProperty;
> +import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
> +import static org.ops4j.pax.exam.OptionUtils.combine;
> +import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.vmOption;
> +
> +import java.util.ArrayList;
> +import java.util.Collections;
> +import java.util.List;
> +
> +import junit.framework.Assert;
> +
> +import org.apache.aries.blueprint.testquiescebundle.TestBean;
> +import org.apache.aries.quiesce.manager.QuiesceCallback;
> +import org.apache.aries.quiesce.participant.QuiesceParticipant;
> +import org.junit.Test;
> +import org.junit.runner.RunWith;
> +import org.ops4j.pax.exam.CoreOptions;
> +import org.ops4j.pax.exam.Inject;
> +import org.ops4j.pax.exam.Option;
> +import org.ops4j.pax.exam.container.def.options.VMOption;
> +import org.ops4j.pax.exam.junit.JUnit4TestRunner;
> +import org.ops4j.pax.exam.options.BootDelegationOption;
> +import org.ops4j.pax.exam.options.MavenArtifactProvisionOption;
> +import org.osgi.framework.Bundle;
> +import org.osgi.framework.BundleContext;
> +import org.osgi.framework.Constants;
> +import org.osgi.framework.Filter;
> +import org.osgi.framework.FrameworkUtil;
> +import org.osgi.framework.InvalidSyntaxException;
> +import org.osgi.framework.ServiceReference;
> +import org.osgi.framework.Version;
> +import org.osgi.util.tracker.ServiceTracker;
> +
> +@RunWith(JUnit4TestRunner.class)
> +public class QuiesceBlueprintTest extends AbstractIntegrationTest{
> +
> +  private static class TestQuiesceCallback implements QuiesceCallback
> +  {
> +    private int calls = 0;
> +
> +	public void bundleQuiesced(Bundle... bundlesQuiesced) {
> +		System.out.println("bundleQuiesced "+ bundlesQuiesced);
> +	      calls++;
> +	}
> +	
> +	public int getCalls() {
> +		return calls;
> +	}
> +  }
> +
> +  private static final int DEFAULT_TIMEOUT = 30000;
> +
> +  @Inject
> +  protected BundleContext bundleContext;
> +
> +
> +  private QuiesceParticipant getParticipant(String bundleName) throws InvalidSyntaxException {
> +    ServiceReference[] refs = bundleContext.getServiceReferences(QuiesceParticipant.class.getName(), null);
> +
> +    if(refs != null) {
> +      for(ServiceReference ref : refs) {
> +        if(ref.getBundle().getSymbolicName().equals(bundleName))
> +          return (QuiesceParticipant) bundleContext.getService(ref);
> +        else System.out.println(ref.getBundle().getSymbolicName());
> +      }
> +    }
> +
> +
> +    return null;
> +  }
> +
> +  @org.ops4j.pax.exam.junit.Configuration
> +  public static Option[] configuration() {
> +    Option[] options = options(
> +        bootDelegationPackages("javax.transaction", "javax.transaction.*"),
> +        vmOption("-Dorg.osgi.framework.system.packages=javax.accessibility,javax.activation,javax.activity,javax.annotation,javax.annotation.processing,javax.crypto,javax.crypto.interfaces,javax.crypto.spec,javax.imageio,javax.imageio.event,javax.imageio.metadata,javax.imageio.plugins.bmp,javax.imageio.plugins.jpeg,javax.imageio.spi,javax.imageio.stream,javax.jws,javax.jws.soap,javax.lang.model,javax.lang.model.element,javax.lang.model.type,javax.lang.model.util,javax.management,javax.management.loading,javax.management.modelmbean,javax.management.monitor,javax.management.openmbean,javax.management.relation,javax.management.remote,javax.management.remote.rmi,javax.management.timer,javax.naming,javax.naming.directory,javax.naming.event,javax.naming.ldap,javax.naming.spi,javax.net,javax.net.ssl,javax.print,javax.print.attribute,javax.print.attribute.standard,javax.print.event,javax.rmi,javax.rmi.CORBA,javax.rmi.ssl,javax.script,javax.security.auth,javax.security.auth.callbac
k,
>   javax.security.auth.kerberos,javax.security.auth.login,javax.security.auth.spi,javax.security.auth.x500,javax.security.cert,javax.security.sasl,javax.sound.midi,javax.sound.midi.spi,javax.sound.sampled,javax.sound.sampled.spi,javax.sql,javax.sql.rowset,javax.sql.rowset.serial,javax.sql.rowset.spi,javax.swing,javax.swing.border,javax.swing.colorchooser,javax.swing.event,javax.swing.filechooser,javax.swing.plaf,javax.swing.plaf.basic,javax.swing.plaf.metal,javax.swing.plaf.multi,javax.swing.plaf.synth,javax.swing.table,javax.swing.text,javax.swing.text.html,javax.swing.text.html.parser,javax.swing.text.rtf,javax.swing.tree,javax.swing.undo,javax.tools,javax.xml,javax.xml.bind,javax.xml.bind.annotation,javax.xml.bind.annotation.adapters,javax.xml.bind.attachment,javax.xml.bind.helpers,javax.xml.bind.util,javax.xml.crypto,javax.xml.crypto.dom,javax.xml.crypto.dsig,javax.xml.crypto.dsig.dom,javax.xml.crypto.dsig.keyinfo,javax.xml.crypto.dsig.spec,javax.xml.datatype,javax.xml.n
ame
>   space,javax.xml.parsers,javax.xml.soap,javax.xml.stream,javax.xml.stream.events,javax.xml.stream.util,javax.xml.transform,javax.xml.transform.dom,javax.xml.transform.sax,javax.xml.transform.stax,javax.xml.transform.stream,javax.xml.validation,javax.xml.ws,javax.xml.ws.handler,javax.xml.ws.handler.soap,javax.xml.ws.http,javax.xml.ws.soap,javax.xml.ws.spi,javax.xml.xpath,org.ietf.jgss,org.omg.CORBA,org.omg.CORBA.DynAnyPackage,org.omg.CORBA.ORBPackage,org.omg.CORBA.TypeCodePackage,org.omg.CORBA.portable,org.omg.CORBA_2_3,org.omg.CORBA_2_3.portable,org.omg.CosNaming,org.omg.CosNaming.NamingContextExtPackage,org.omg.CosNaming.NamingContextPackage,org.omg.Dynamic,org.omg.DynamicAny,org.omg.DynamicAny.DynAnyFactoryPackage,org.omg.DynamicAny.DynAnyPackage,org.omg.IOP,org.omg.IOP.CodecFactoryPackage,org.omg.IOP.CodecPackage,org.omg.Messaging,org.omg.PortableInterceptor,org.omg.PortableInterceptor.ORBInitInfoPackage,org.omg.PortableServer,org.omg.PortableServer.CurrentPackage,org.o
mg.
>   PortableServer.POAManagerPackage,org.omg.PortableServer.POAPackage,org.omg.PortableServer.ServantLocatorPackage,org.omg.PortableServer.portable,org.omg.SendingContext,org.omg.stub.java.rmi,org.w3c.dom,org.w3c.dom.bootstrap,org.w3c.dom.css,org.w3c.dom.events,org.w3c.dom.html,org.w3c.dom.ls,org.w3c.dom.ranges,org.w3c.dom.stylesheets,org.w3c.dom.traversal,org.w3c.dom.views,org.xml.sax,org.xml.sax.ext,org.xml.sax.helpers,javax.transaction;partial=true;mandatory:=partial,javax.transaction.xa;partial=true;mandatory:=partial"),
> +
> +        // Log
> +        mavenBundle("org.ops4j.pax.logging", "pax-logging-api"),
> +        mavenBundle("org.ops4j.pax.logging", "pax-logging-service"),
> +        // Felix Config Admin
> +        mavenBundle("org.apache.felix", "org.apache.felix.configadmin"),
> +        // Felix mvn url handler
> +        mavenBundle("org.ops4j.pax.url", "pax-url-mvn"),
> +
> +        // this is how you set the default log level when using pax
> +        // logging (logProfile)
> +        systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("DEBUG"),
> +
> +        // Bundles
> +        mavenBundle("asm","asm-all"),
> +        mavenBundle("org.apache.servicemix.bundles", "org.apache.servicemix.bundles.cglib"),
> +
> +        mavenBundle("org.apache.aries.quiesce", "org.apache.aries.quiesce.api"),
> +        mavenBundle("org.apache.aries", "org.apache.aries.util"),
> +        mavenBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint"),
> +        mavenBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint.testbundlea").noStart(),
> +        mavenBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint.testbundleb").noStart(),
> +        mavenBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint.testquiescebundle"),
> +        mavenBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint.cm"),
> +        mavenBundle("org.osgi", "org.osgi.compendium"),
> +
> +        //new VMOption( "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000" ),
> +
> +        equinox().version("3.5.0"));
> +    options = updateOptions(options);
> +    return options;
> +  }
> +
> +
> +  protected Bundle getBundle(String symbolicName) {
> +    return getBundle(symbolicName, null);
> +  }
> +
> +  protected Bundle getBundle(String bundleSymbolicName, String version) {
> +    Bundle result = null;
> +    for (Bundle b : bundleContext.getBundles()) {
> +      if (b.getSymbolicName().equals(bundleSymbolicName)) {
> +        if (version == null
> +            || b.getVersion().equals(Version.parseVersion(version))) {
> +          result = b;
> +          break;
> +        }
> +      }
> +    }
> +    return result;
> +  }
> +
> +  public static BootDelegationOption bootDelegation() {
> +    return new BootDelegationOption("org.apache.aries.unittest.fixture");
> +  }
> +
> +  public static MavenArtifactProvisionOption mavenBundle(String groupId,
> +      String artifactId) {
> +    return CoreOptions.mavenBundle().groupId(groupId).artifactId(artifactId)
> +        .versionAsInProject();
> +  }
> +
> +  protected static Option[] updateOptions(Option[] options) {
> +    // We need to add pax-exam-junit here when running with the ibm
> +    // jdk to avoid the following exception during the test run:
> +    // ClassNotFoundException: org.ops4j.pax.exam.junit.Configuration
> +    if ("IBM Corporation".equals(System.getProperty("java.vendor"))) {
> +      Option[] ibmOptions = options(wrappedBundle(mavenBundle(
> +          "org.ops4j.pax.exam", "pax-exam-junit")));
> +      options = combine(ibmOptions, options);
> +    }
> +
> +    return options;
> +  }
> +
> +  protected<T>  T getOsgiService(Class<T>  type, long timeout) {
> +    return getOsgiService(type, null, timeout);
> +  }
> +
> +  protected<T>  T getOsgiService(Class<T>  type) {
> +    return getOsgiService(type, null, DEFAULT_TIMEOUT);
> +  }
> +
> +  protected<T>  T getOsgiService(Class<T>  type, String filter, long timeout) {
> +    return getOsgiService(null, type, filter, timeout);
> +  }
> +
> +  protected<T>  T getOsgiService(BundleContext bc, Class<T>  type,
> +      String filter, long timeout) {
> +    ServiceTracker tracker = null;
> +    try {
> +      String flt;
> +      if (filter != null) {
> +        if (filter.startsWith("(")) {
> +          flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")"
> +              + filter + ")";
> +        } else {
> +          flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")("
> +              + filter + "))";
> +        }
> +      } else {
> +        flt = "(" + Constants.OBJECTCLASS + "=" + type.getName() + ")";
> +      }
> +      Filter osgiFilter = FrameworkUtil.createFilter(flt);
> +      tracker = new ServiceTracker(bc == null ? bundleContext : bc, osgiFilter,
> +          null);
> +      tracker.open();
> +      // Note that the tracker is not closed to keep the reference
> +      // This is buggy, has the service reference may change i think
> +      Object svc = type.cast(tracker.waitForService(timeout));
> +      if (svc == null) {
> +        throw new RuntimeException("Gave up waiting for service " + flt);
> +      }
> +      return type.cast(svc);
> +    } catch (InvalidSyntaxException e) {
> +      throw new IllegalArgumentException("Invalid filter", e);
> +    } catch (InterruptedException e) {
> +      throw new RuntimeException(e);
> +    }
> +  }
> +
> +  @Test
> +  public void testBasicQuieseEmptyCounter() throws Exception
> +  {
> +	  //This test checks that a single bundle when called will not quiesce while
> +	  //there is an active request (method sleeps), but will quiesce after the
> +	  //request is completed.
> +	
> +	System.out.println("In testBasicQuieseEmptyCounter");
> +	Object obj = getOsgiService(TestBean.class);
> +	
> +	if (obj != null)
> +	{
> +	  QuiesceParticipant participant = getParticipant("org.apache.aries.blueprint");
> +	
> +	  if (participant != null)
> +	  {
> +	    System.out.println(obj.getClass().getName());
> +
> +	    TestQuiesceCallback callback = new TestQuiesceCallback();
> +	
> +	    Bundle bundle = getBundle("org.apache.aries.blueprint.testquiescebundle");
> +	
> +	    System.out.println("Got the bundle");
> +	
> +	    List<Bundle>  bundles = new ArrayList<Bundle>();
> +	    bundles.add(bundle);
> +	
> +	    Thread t = new Thread(new TestBeanClient((TestBean)obj, 1500));
> +	    t.start();
> +
> +	    System.out.println("Thread Started");
> +	
> +	    participant.quiesce(callback, bundles);
> +	
> +	    System.out.println("Called Quiesce");
> +	
> +	    Thread.sleep(1000);
> +	
> +	    Assert.assertTrue("Quiesce callback should not have occurred yet; calls should be 0, but it is "+callback.getCalls(), callback.getCalls()==0);
> +	
> +	    Thread.sleep(1500);
> +	
> +	    System.out.println("After second sleep");
> +	
> +	    Assert.assertTrue("Quiesce callback should have occurred once; calls should be 1, but it is "+callback.getCalls(), callback.getCalls()==1);
> +	
> + 	  }
> +  	  else
> +	  {
> +		throw new Exception("No Quiesce Participant found for the blueprint service");
> +	  }
> +
> +	  System.out.println("done");
> +	}
> +	else
> +	{
> +		throw new Exception("No Service returned for " + TestBean.class);
> +	}
> +  }
> +
> +  @Test
> +  public void testNoServicesQuiesce() throws Exception {
> +
> +   //This test covers the case where one of the bundles being asked to quiesce has no
> +   //services. It should be quiesced immediately.
> +	
> +   System.out.println("In testNoServicesQuiesce");
> +	Object obj = getOsgiService(TestBean.class);
> +	
> +	if (obj != null)
> +	{
> +		QuiesceParticipant participant = getParticipant("org.apache.aries.blueprint");
> +		
> +		if (participant != null)
> +		{
> +			TestQuiesceCallback callbackA = new TestQuiesceCallback();
> +			TestQuiesceCallback callbackB = new TestQuiesceCallback();
> +		
> +			//bundlea provides the ns handlers, bean processors, interceptors etc for this test.
> +	        Bundle bundlea = getBundle("org.apache.aries.blueprint.testbundlea");
> +	        assertNotNull(bundlea);
> +	        bundlea.start();
> +	
> +	        //bundleb has no services and makes use of the extensions provided by bundlea
> +	        Bundle bundleb = getBundle("org.apache.aries.blueprint.testbundleb");
> +	        assertNotNull(bundleb);
> +	        bundleb.start();
> +	
> +			participant.quiesce(callbackB, Collections.singletonList(getBundle(
> +				"org.apache.aries.blueprint.testbundleb")));
> +			
> +		    System.out.println("Called Quiesce");
> +		
> +		    Thread.sleep(200);
> +		
> +		    Assert.assertTrue("Quiesce callback B should have occurred; calls should be 1, but it is "+callbackB.getCalls(), callbackB.getCalls()==1);
> +		    Assert.assertTrue("Quiesce callback A should not have occurred yet; calls should be 0, but it is "+callbackA.getCalls(), callbackA.getCalls()==0);
> +		
> +		    participant.quiesce(callbackA, Collections.singletonList(getBundle(
> +			"org.apache.aries.blueprint.testbundlea")));
> +				
> +		    Thread.sleep(1000);
> +		
> +		    System.out.println("After second sleep");
> +		
> +		    Assert.assertTrue("Quiesce callback A should have occurred once; calls should be 1, but it is "+callbackA.getCalls(), callbackA.getCalls()==1);
> +		    Assert.assertTrue("Quiesce callback B should have occurred once; calls should be 1, but it is "+callbackB.getCalls(), callbackB.getCalls()==1);
> +		
> +		}else{
> +			throw new Exception("No Quiesce Participant found for the blueprint service");
> +		}
> +	}else{
> +		throw new Exception("No Service returned for " + TestBean.class);
> +	}
> +  }
> +
> +  @Test
> +  public void testMultiBundleQuiesce() throws Exception {
> +
> +   //This test covers the case where two bundles are quiesced at the same time.
> +   //Bundle A should quiesce immediately, quiesce bundle should quiesce after the
> +   //request has completed.
> +	
> +   System.out.println("In testMultiBundleQuiesce");
> +	Object obj = getOsgiService(TestBean.class);
> +	
> +	if (obj != null)
> +	{
> +		QuiesceParticipant participant = getParticipant("org.apache.aries.blueprint");
> +		
> +		if (participant != null)
> +		{
> +			TestQuiesceCallback callback = new TestQuiesceCallback();
> +		
> +			//bundlea provides the ns handlers, bean processors, interceptors etc for this test.
> +	        Bundle bundlea = getBundle("org.apache.aries.blueprint.testbundlea");
> +	        assertNotNull(bundlea);
> +	        bundlea.start();
> +	
> +	        //quiesce bundle will sleep for a second so will quiesce after that
> +		    Bundle bundleq = getBundle("org.apache.aries.blueprint.testquiescebundle");
> +		
> +		    System.out.println("Got the bundle");
> +		
> +		    List<Bundle>  bundles = new ArrayList<Bundle>();
> +		    bundles.add(bundlea);
> +		    bundles.add(bundleq);
> +		
> +		    Thread t = new Thread(new TestBeanClient((TestBean)obj, 1500));
> +		    t.start();
> +	
> +			participant.quiesce(callback, bundles);
> +			
> +		    System.out.println("Called Quiesce");
> +		
> +		    Thread.sleep(500);
> +		
> +		    Assert.assertTrue("Quiesce callback should have occurred once for bundle a but not for bundle q; calls should be 1, but it is "+callback.getCalls(), callback.getCalls()==1);
> +		
> +		    Thread.sleep(1500);
> +		
> +		    System.out.println("After second sleep");
> +		
> +		    Assert.assertTrue("Quiesce callback should have occurred twice, once for bundle a and q respectively; calls should be 2, but it is "+callback.getCalls(), callback.getCalls()==2);
> +		
> +		}else{
> +			throw new Exception("No Quiesce Participant found for the blueprint service");
> +		}
> +	}else{
> +		throw new Exception("No Service returned for " + TestBean.class);
> +	}
> +  }
> +
> +  @Test
> +  public void testMultiRequestQuiesce() throws Exception {
> +
> +   //This test covers the case where we have two active requests when
> +   //the bundle is being quiesced.
> +	
> +   System.out.println("In testMultiRequestQuiesce");
> +	Object obj = getOsgiService(TestBean.class);
> +	
> +	if (obj != null)
> +	{
> +		QuiesceParticipant participant = getParticipant("org.apache.aries.blueprint");
> +		
> +		if (participant != null)
> +		{
> +			TestQuiesceCallback callback = new TestQuiesceCallback();
> +			TestBeanClient client =  new TestBeanClient((TestBean)obj, 1500);
> +		
> +
> +	        //quiesce bundle will sleep for a second so will quiesce after that
> +		    Bundle bundle = getBundle("org.apache.aries.blueprint.testquiescebundle");
> +		
> +		    System.out.println("Got the bundle");
> +		
> +		    List<Bundle>  bundles = new ArrayList<Bundle>();
> +		    bundles.add(bundle);
> +		
> +		    Thread t = new Thread(client);
> +		    t.start();
> +	
> +			participant.quiesce(callback, bundles);
> +			
> +		    System.out.println("Called Quiesce, putting in a new request");
> +		
> +		    Thread t2 = new Thread(client);
> +		    t2.start();
> +		
> +		    Thread.sleep(5000);
> +		
> +		    Assert.assertTrue("Quiesce callback should have occurred once; calls should be 1, but it is "+callback.getCalls(), callback.getCalls()==1);
> +		
> +
> +		}else{
> +			throw new Exception("No Quiesce Participant found for the blueprint service");
> +		}
> +	}else{
> +		throw new Exception("No Service returned for " + TestBean.class);
> +	}
> +  }
> +
> +
> +  private class TestBeanClient implements Runnable
> +  {
> +    private TestBean myService;
> +    private int time;
> +
> +    public TestBeanClient(TestBean myService, int time)
> +    {
> +      this.myService = myService;
> +      this.time = time;
> +    }
> +	
> +	public void run()
> +	{
> +	  try
> +	  {
> +		System.out.println("In Test Bean Client - Sleeping zzzzzzz");
> +		myService.sleep(time);
> +		System.out.println("Woken up");
> +	  }
> +	  catch (InterruptedException ie)
> +	  {
> +		  ie.printStackTrace();
> +	  }
> +	}
> +	
> +  }
> +}
>
> Added: incubator/aries/trunk/blueprint/blueprint-testquiescebundle/pom.xml
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-testquiescebundle/pom.xml?rev=995797&view=auto
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-testquiescebundle/pom.xml (added)
> +++ incubator/aries/trunk/blueprint/blueprint-testquiescebundle/pom.xml Fri Sep 10 14:08:34 2010
> @@ -0,0 +1,52 @@
> +<!--
> +    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.
> +-->
> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
> +<modelVersion>4.0.0</modelVersion>
> +<description>Blueprint Test Quiesce Bundle, tests the blueprint participant for the quiesce functionality.</description>
> +<parent>
> +<groupId>org.apache.aries.blueprint</groupId>
> +<artifactId>blueprint</artifactId>
> +<version>0.3-incubating-SNAPSHOT</version>
> +</parent>
> +
> +<artifactId>org.apache.aries.blueprint.testquiescebundle</artifactId>
> +<name>Apache Aries Blueprint Test Quiesce Bundle</name>
> +<packaging>bundle</packaging>
> +
> +<properties>
> +<aries.osgi.activator>
> +            org.apache.aries.blueprint.testquiescebundle.Activator
> +</aries.osgi.activator>
> +</properties>
> +
> +<dependencies>
> +<dependency>
> +<groupId>org.eclipse</groupId>
> +<artifactId>osgi</artifactId>
> +<scope>provided</scope>
> +</dependency>
> +<dependency>
> +<groupId>org.apache.aries.blueprint</groupId>
> +<artifactId>org.apache.aries.blueprint.api</artifactId>
> +</dependency>
> +<dependency>
> +<groupId>org.apache.aries.blueprint</groupId>
> +<artifactId>org.apache.aries.blueprint.core</artifactId>
> +</dependency>
> +</dependencies>
> +
> +</project>
>
> Added: incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/Activator.java
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/Activator.java?rev=995797&view=auto
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/Activator.java (added)
> +++ incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/Activator.java Fri Sep 10 14:08:34 2010
> @@ -0,0 +1,30 @@
> +/**
> + *  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.testquiescebundle;
> +
> +import org.osgi.framework.BundleActivator;
> +import org.osgi.framework.BundleContext;
> +
> +public class Activator implements BundleActivator {
> +
> +    public void start(BundleContext context) {
> +    }
> +
> +    public void stop(BundleContext context) {
> +    }
> +
> +}
>
> Added: incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/TestBean.java
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/TestBean.java?rev=995797&view=auto
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/TestBean.java (added)
> +++ incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/java/org/apache/aries/blueprint/testquiescebundle/TestBean.java Fri Sep 10 14:08:34 2010
> @@ -0,0 +1,25 @@
> +/**
> + *  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.testquiescebundle;
> +
> +public class TestBean
> +{
> +    public void sleep(int time) throws InterruptedException
> +    {
> +		Thread.sleep(time);
> +     }
> +}
>
> Added: incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/blueprint/config.xml
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/blueprint/config.xml?rev=995797&view=auto
> ==============================================================================
> --- incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/blueprint/config.xml (added)
> +++ incubator/aries/trunk/blueprint/blueprint-testquiescebundle/src/main/resources/OSGI-INF/blueprint/config.xml Fri Sep 10 14:08:34 2010
> @@ -0,0 +1,31 @@
> +<?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.
> +-->
> +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
> +           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
> +           xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
> +
> +           default-availability="optional">
> +
> +<bean id="TestBean" class="org.apache.aries.blueprint.testquiescebundle.TestBean" scope="singleton">
> +</bean>
> +
> +<service interface="org.apache.aries.blueprint.testquiescebundle.TestBean" ref="TestBean">
> +</service>
> +
> +</blueprint>
> +
>
> Modified: incubator/aries/trunk/blueprint/pom.xml
> URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/pom.xml?rev=995797&r1=995796&r2=995797&view=diff
> ==============================================================================
> --- incubator/aries/trunk/blueprint/pom.xml (original)
> +++ incubator/aries/trunk/blueprint/pom.xml Fri Sep 10 14:08:34 2010
> @@ -91,6 +91,11 @@
>               </dependency>
>               <dependency>
>                   <groupId>org.apache.aries.blueprint</groupId>
> +<artifactId>org.apache.aries.blueprint.testquiescebundle</artifactId>
> +<version>${version}</version>
> +</dependency>
> +<dependency>
> +<groupId>org.apache.aries.blueprint</groupId>
>                   <artifactId>org.apache.aries.blueprint.itests</artifactId>
>                   <version>${version}</version>
>               </dependency>
> @@ -140,6 +145,18 @@
>                   <artifactId>xbean-finder</artifactId>
>                   <version>3.7</version>
>               </dependency>
> +<dependency>
> +            	<groupId>org.apache.aries.blueprint</groupId>
> +            	<artifactId>org.apache.aries.blueprint.testquiescebundle</artifactId>
> +            	<version>0.3-incubating-SNAPSHOT</version>
> +            	<type>bundle</type>
> +            	<scope>compile</scope>
> +</dependency>
> +<dependency>
> +<groupId>org.apache.aries.quiesce</groupId>
> +<artifactId>org.apache.aries.quiesce.api</artifactId>
> +<version>0.3-incubating-SNAPSHOT</version>
> +</dependency>
>           </dependencies>
>       </dependencyManagement>
>
> @@ -180,6 +197,7 @@
>           <module>blueprint-annotation-itest</module>
>           <module>blueprint-testbundlea</module>
>           <module>blueprint-testbundleb</module>
> +<module>blueprint-testquiescebundle</module>
>           <module>blueprint-itests</module>
>       </modules>
>
>
>
>


-- 
Joe