You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by cs...@apache.org on 2014/11/10 15:43:57 UTC

svn commit: r1637878 - in /aries/trunk/jpa/jpa-container/src: main/java/org/apache/aries/jpa/container/impl/ main/java/org/apache/aries/jpa/container/quiesce/ main/java/org/apache/aries/jpa/container/quiesce/impl/ test/java/org/apache/aries/jpa/container/

Author: cschneider
Date: Mon Nov 10 14:43:56 2014
New Revision: 1637878

URL: http://svn.apache.org/r1637878
Log:
Moving quiesce support into separate package

Added:
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/CountdownCallback.java
      - copied, changed from r1637390, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/CoundownCallback.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/DestroyCallback.java
      - copied, changed from r1637390, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/DestroyCallback.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/EMFProxyFactory.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/EntityManagerProxyFactory.java
      - copied, changed from r1637390, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/EntityManagerProxyFactory.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/NamedCallback.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceEMF.java
      - copied, changed from r1637390, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceEMF.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceEMFHandler.java
      - copied, changed from r1637390, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceEMFHandler.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceHandler.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceParticipantFactory.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceParticipantImpl.java
      - copied, changed from r1637390, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceParticipantImpl.java
Removed:
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/CoundownCallback.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/DestroyCallback.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/EntityManagerProxyFactory.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceEMF.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceEMFHandler.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceParticipantImpl.java
Modified:
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/EntityManagerFactoryManager.java
    aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleManager.java
    aries/trunk/jpa/jpa-container/src/test/java/org/apache/aries/jpa/container/PersistenceBundleLifecycleTest.java

Modified: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/EntityManagerFactoryManager.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/EntityManagerFactoryManager.java?rev=1637878&r1=1637877&r2=1637878&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/EntityManagerFactoryManager.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/EntityManagerFactoryManager.java Mon Nov 10 14:43:56 2014
@@ -18,15 +18,12 @@
  */
 package org.apache.aries.jpa.container.impl;
 
-import java.lang.reflect.Proxy;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Map;
-import java.util.Set;
 import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -38,6 +35,10 @@ import javax.persistence.spi.Persistence
 import org.apache.aries.jpa.container.ManagedPersistenceUnitInfo;
 import org.apache.aries.jpa.container.PersistenceUnitConstants;
 import org.apache.aries.jpa.container.parsing.ParsedPersistenceUnit;
+import org.apache.aries.jpa.container.quiesce.impl.DestroyCallback;
+import org.apache.aries.jpa.container.quiesce.impl.EMFProxyFactory;
+import org.apache.aries.jpa.container.quiesce.impl.NamedCallback;
+import org.apache.aries.jpa.container.quiesce.impl.QuiesceEMF;
 import org.apache.aries.util.AriesFrameworkUtil;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -56,27 +57,6 @@ import org.slf4j.LoggerFactory;
 })
 public class EntityManagerFactoryManager implements ServiceTrackerCustomizer {
 
-  /**
-   * A callback for a named persistence units
-   */
-  class NamedCallback {
-    private final Set<String> names;
-    private final DestroyCallback callback;
-    public NamedCallback(Collection<String> names, DestroyCallback countdown) {
-      this.names = new HashSet<String>(names);
-      callback = countdown;
-    }
-
-    public void callback(String name) {
-      boolean winner;
-      synchronized (this) {
-        winner = !!!names.isEmpty() && names.remove(name) && names.isEmpty();
-      }
-      if(winner)
-        callback.callback();
-    }
-  }
-
   /** The container's {@link BundleContext} */
   private final BundleContext containerContext;
   /** The persistence bundle */
@@ -88,7 +68,7 @@ public class EntityManagerFactoryManager
   /** The original parsed data */
   private Collection<ParsedPersistenceUnit> parsedData;
   /** A Map of created {@link EntityManagerFactory}s */
-  private Map<String, QuiesceEMF> emfs = null;
+  private Map<String, EntityManagerFactory> emfs = null;
   /** The {@link ServiceRegistration} objects for the {@link EntityManagerFactory}s */
   private ConcurrentMap<String, ServiceRegistration> registrations = null;
   /** Quiesce this Manager */
@@ -205,7 +185,7 @@ public class EntityManagerFactoryManager
     if(registrations != null) {
       for(Entry<String, ServiceRegistration> entry : registrations.entrySet()) {
         AriesFrameworkUtil.safeUnregisterService(entry.getValue());
-        emfs.get(entry.getKey()).clearQuiesce();
+        clearQuiesce(emfs.get(entry.getKey()));
         persistenceUnits.get(entry.getKey()).unregistered();
       }
       // remember to set registrations to be null
@@ -213,14 +193,21 @@ public class EntityManagerFactoryManager
     }
   }
 
+
   private void unregisterEntityManagerFactory(String unit) {
     if(registrations != null) {
       AriesFrameworkUtil.safeUnregisterService(registrations.remove(unit));
-      emfs.get(unit).clearQuiesce();
+      clearQuiesce(emfs.get(unit));
       persistenceUnits.get(unit).unregistered();
     }
   }
-
+  
+  private void clearQuiesce(EntityManagerFactory emf) {
+      if (emf instanceof QuiesceEMF) {
+          ((QuiesceEMF) emf).clearQuiesce();
+      }
+  }
+  
   /**
    * Register {@link EntityManagerFactory} services
    * 
@@ -245,7 +232,7 @@ public class EntityManagerFactoryManager
                       PersistenceUnitConstants.OSGI_UNIT_PROVIDER, provider));
       }
       //Register each EMF
-      for(Entry<String, QuiesceEMF> entry : emfs.entrySet())
+      for(Entry<String, EntityManagerFactory> entry : emfs.entrySet())
       {
         
         Hashtable<String,Object> props = new Hashtable<String, Object>();
@@ -300,14 +287,6 @@ public class EntityManagerFactoryManager
     }
   }
   
-  private QuiesceEMF createCountingProxy(EntityManagerFactory delegate, String name) {
-      ClassLoader cl = this.getClass().getClassLoader();
-      Class<?>[] ifAr = new Class[] {
-          QuiesceEMF.class
-      };
-      return (QuiesceEMF)Proxy.newProxyInstance(cl, ifAr, new QuiesceEMFHandler(delegate, name));
-  }
-
   /**
    * Create {@link EntityManagerFactory} services for this peristence unit
    * throws InvalidPersistenceUnitException if this {@link EntityManagerFactory} is no longer
@@ -315,7 +294,7 @@ public class EntityManagerFactoryManager
    */
   private void createEntityManagerFactories() throws InvalidPersistenceUnitException {
     if (emfs == null) {  
-      emfs = new HashMap<String, QuiesceEMF>();
+      emfs = new HashMap<String, EntityManagerFactory>();
     }
     //Only try if we have a provider and EMFs
     if(provider == null || !emfs.isEmpty() || quiesce) {
@@ -334,7 +313,7 @@ public class EntityManagerFactoryManager
         ManagedPersistenceUnitInfo mpui = persistenceUnits.get(unitName);
         try {
           EntityManagerFactory emf = providerService.createContainerEntityManagerFactory(mpui.getPersistenceUnitInfo(), mpui.getContainerProperties());
-          QuiesceEMF emfProxy = createCountingProxy(emf, unitName);
+          EntityManagerFactory emfProxy = EMFProxyFactory.createProxy(emf, unitName);
           emfs.put(unitName, emfProxy);
         } catch (Exception e) {
           _logger.warn("Error creating EntityManagerFactory", e);
@@ -345,6 +324,8 @@ public class EntityManagerFactoryManager
       containerContext.ungetService(provider);
     }
   }
+  
+
 
   /**
    * Manage the EntityManagerFactories for the following
@@ -401,7 +382,7 @@ public class EntityManagerFactoryManager
     if(registrations != null)
       unregisterEntityManagerFactories();
     if(emfs != null) {
-      for(Entry<String, QuiesceEMF> entry : emfs.entrySet()) {
+      for(Entry<String, EntityManagerFactory> entry : emfs.entrySet()) {
         try {
           entry.getValue().close();
         } catch (Exception e) {
@@ -420,11 +401,12 @@ public class EntityManagerFactoryManager
   {
     return parsedData;
   }
+
   /** Quiesce this Manager */
   public void quiesce(DestroyCallback countdown) {
     
     //Find the EMFs to quiesce, and their Service registrations
-    Map<QuiesceEMF, ServiceRegistration> entries = new HashMap<QuiesceEMF, ServiceRegistration>();
+    Map<EntityManagerFactory, ServiceRegistration> entries = new HashMap<EntityManagerFactory, ServiceRegistration>();
     Collection<String> names = new ArrayList<String>();
     synchronized(this) {
       if((bundle.getState() & (Bundle.ACTIVE | Bundle.STARTING)) != 0)
@@ -440,14 +422,19 @@ public class EntityManagerFactoryManager
     if(entries.isEmpty())
       countdown.callback();
     else {
-    NamedCallback callback = new NamedCallback(names, countdown);
-      for(Entry<QuiesceEMF, ServiceRegistration> entry : entries.entrySet()) {
-        QuiesceEMF emf = entry.getKey();
-        emf.quiesce(callback, entry.getValue());
+      NamedCallback callback = new NamedCallback(names, countdown);
+      for(Entry<EntityManagerFactory, ServiceRegistration> entry : entries.entrySet()) {
+        quiesce(entry.getKey(), callback, entry.getValue());
       }
     }
   }
-
+  
+  private void quiesce(EntityManagerFactory emf, NamedCallback callback, ServiceRegistration reg) {
+      if (emf instanceof QuiesceEMF) {
+          ((QuiesceEMF) emf).quiesce(callback, reg);
+      }
+  }
+  
   @Override
   public StringBuffer addingService(ServiceReference reference) {
     //Use String.valueOf to save us from nulls
@@ -520,4 +507,5 @@ public class EntityManagerFactoryManager
       } 
     }
   }
+
 }

Modified: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleManager.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleManager.java?rev=1637878&r1=1637877&r2=1637878&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleManager.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleManager.java Mon Nov 10 14:43:56 2014
@@ -19,6 +19,7 @@
 
 package org.apache.aries.jpa.container.impl;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -46,10 +47,15 @@ import org.apache.aries.jpa.container.pa
 import org.apache.aries.jpa.container.parsing.PersistenceDescriptorParser;
 import org.apache.aries.jpa.container.parsing.PersistenceDescriptorParserException;
 import org.apache.aries.jpa.container.parsing.impl.PersistenceDescriptorParserImpl;
+import org.apache.aries.jpa.container.quiesce.impl.CountdownCallback;
+import org.apache.aries.jpa.container.quiesce.impl.DestroyCallback;
+import org.apache.aries.jpa.container.quiesce.impl.QuiesceHandler;
+import org.apache.aries.jpa.container.quiesce.impl.QuiesceParticipantFactory;
 import org.apache.aries.jpa.container.tx.impl.OSGiTransactionManager;
 import org.apache.aries.jpa.container.unit.impl.ManagedPersistenceUnitInfoFactoryImpl;
 import org.apache.aries.util.AriesFrameworkUtil;
 import org.apache.aries.util.VersionRange;
+import org.apache.aries.util.io.IOUtils;
 import org.apache.aries.util.tracker.RecursiveBundleTracker;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
@@ -71,11 +77,8 @@ import org.slf4j.LoggerFactory;
  * matching PersistenceProvider
  */
 @SuppressWarnings("rawtypes")
-public class PersistenceBundleManager implements BundleTrackerCustomizer, ServiceTrackerCustomizer, BundleActivator
+public class PersistenceBundleManager implements BundleTrackerCustomizer, ServiceTrackerCustomizer, BundleActivator, QuiesceHandler
 {
-  /** The QuiesceParticipant implementation class name */
-  private static final String QUIESCE_PARTICIPANT_CLASS = "org.apache.aries.quiesce.participant.QuiesceParticipant";
-  
   /** Logger */
   private static final Logger _logger = LoggerFactory.getLogger("org.apache.aries.jpa.container");
   
@@ -111,10 +114,8 @@ public class PersistenceBundleManager im
   private RecursiveBundleTracker tracker;
   private ServiceTracker serviceTracker;
 
-  /** The quiesce participant service */
-  private ServiceRegistration quiesceReg;
   /** A callback to shutdown the quiesce participant when it is done */
-  private DestroyCallback quiesceParticipant;
+  private Closeable quiesceParticipant;
   /** Are we quiescing */
   private AtomicBoolean quiesce = new AtomicBoolean(false);
   
@@ -655,15 +656,7 @@ public class PersistenceBundleManager im
     
     open();
     
-    try{
-      context.getBundle().loadClass(QUIESCE_PARTICIPANT_CLASS);
-      //Class was loaded, register
-      quiesceParticipant = new QuiesceParticipantImpl(this);
-      quiesceReg = context.registerService(QUIESCE_PARTICIPANT_CLASS,
-         quiesceParticipant, null);
-    } catch (ClassNotFoundException e) {
-      _logger.info(NLS.MESSAGES.getMessage("quiesce.manager.not.there"));
-    }
+    QuiesceParticipantFactory.create(context, this);
   }
 
   private void initParser() {
@@ -674,22 +667,21 @@ public class PersistenceBundleManager im
   public void stop(BundleContext context) throws Exception {
     close();
     AriesFrameworkUtil.safeUnregisterService(parserReg);
-    AriesFrameworkUtil.safeUnregisterService(quiesceReg);
-    if(quiesceParticipant != null)
-      quiesceParticipant.callback();
+    IOUtils.close(quiesceParticipant);
   }
   
   public BundleContext getCtx() {
     return ctx;
   }
 
+  @Override
   public void quiesceBundle(Bundle bundleToQuiesce, final DestroyCallback callback) {
     
     boolean thisBundle =  bundleToQuiesce.equals(ctx.getBundle());
     
     if(thisBundle) {
       quiesce.compareAndSet(false, true);
-      AriesFrameworkUtil.safeUnregisterService(quiesceReg);
+      
     }
     
     Collection<EntityManagerFactoryManager> toDestroyNow = new ArrayList<EntityManagerFactoryManager>();
@@ -719,7 +711,7 @@ public class PersistenceBundleManager im
     if(quiesceNow.isEmpty()) {
       callback.callback();
     } else {
-      DestroyCallback countdown = new CoundownCallback(quiesceNow.size(), callback);
+      DestroyCallback countdown = new CountdownCallback(quiesceNow.size(), callback);
       
       for(EntityManagerFactoryManager emfm : quiesceNow)
         emfm.quiesce(countdown);

Copied: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/CountdownCallback.java (from r1637390, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/CoundownCallback.java)
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/CountdownCallback.java?p2=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/CountdownCallback.java&p1=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/CoundownCallback.java&r1=1637390&r2=1637878&rev=1637878&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/CoundownCallback.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/CountdownCallback.java Mon Nov 10 14:43:56 2014
@@ -16,17 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.aries.jpa.container.impl;
+package org.apache.aries.jpa.container.quiesce.impl;
+
 
 /**
  * A {@link DestroyCallback} that delegates after the correct
  * number of calls 
  */
-public final class CoundownCallback implements DestroyCallback {
+public final class CountdownCallback implements DestroyCallback {
   private final DestroyCallback callback;
   private int counter;
 
-  public CoundownCallback(int count,
+  public CountdownCallback(int count,
       DestroyCallback callback) {
     this.callback = callback;
     counter = count;

Copied: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/DestroyCallback.java (from r1637390, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/DestroyCallback.java)
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/DestroyCallback.java?p2=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/DestroyCallback.java&p1=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/DestroyCallback.java&r1=1637390&r2=1637878&rev=1637878&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/DestroyCallback.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/DestroyCallback.java Mon Nov 10 14:43:56 2014
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.aries.jpa.container.impl;
+package org.apache.aries.jpa.container.quiesce.impl;
 
 /**
  * An asynchronous callback for destroying something

Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/EMFProxyFactory.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/EMFProxyFactory.java?rev=1637878&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/EMFProxyFactory.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/EMFProxyFactory.java Mon Nov 10 14:43:56 2014
@@ -0,0 +1,13 @@
+package org.apache.aries.jpa.container.quiesce.impl;
+
+import java.lang.reflect.Proxy;
+
+import javax.persistence.EntityManagerFactory;
+
+public class EMFProxyFactory {
+    public static EntityManagerFactory createProxy(EntityManagerFactory delegate, String name) {
+        ClassLoader cl = QuiesceEMF.class.getClassLoader();
+        Class<?>[] ifAr = new Class[] { QuiesceEMF.class };
+        return (QuiesceEMF) Proxy.newProxyInstance(cl, ifAr, new QuiesceEMFHandler(delegate, name));
+    }
+}

Copied: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/EntityManagerProxyFactory.java (from r1637390, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/EntityManagerProxyFactory.java)
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/EntityManagerProxyFactory.java?p2=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/EntityManagerProxyFactory.java&p1=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/EntityManagerProxyFactory.java&r1=1637390&r2=1637878&rev=1637878&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/EntityManagerProxyFactory.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/EntityManagerProxyFactory.java Mon Nov 10 14:43:56 2014
@@ -1,4 +1,4 @@
-package org.apache.aries.jpa.container.impl;
+package org.apache.aries.jpa.container.quiesce.impl;
 
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
@@ -7,7 +7,9 @@ import java.lang.reflect.Proxy;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceException;
 
-public class EntityManagerProxyFactory {
+import org.apache.aries.jpa.container.impl.NLS;
+
+class EntityManagerProxyFactory {
     static EntityManager create(EntityManager delegate, DestroyCallback destroyCallback) {
         ClassLoader cl = delegate.getClass().getClassLoader();
         Class<?>[] ifAr = new Class[]{EntityManager.class};

Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/NamedCallback.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/NamedCallback.java?rev=1637878&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/NamedCallback.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/NamedCallback.java Mon Nov 10 14:43:56 2014
@@ -0,0 +1,27 @@
+package org.apache.aries.jpa.container.quiesce.impl;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A callback for a named persistence units
+ */
+public class NamedCallback {
+    private final Set<String> names;
+    private final DestroyCallback callback;
+
+    public NamedCallback(Collection<String> names, DestroyCallback countdown) {
+        this.names = new HashSet<String>(names);
+        callback = countdown;
+    }
+
+    public void callback(String name) {
+        boolean winner;
+        synchronized (this) {
+            winner = !!!names.isEmpty() && names.remove(name) && names.isEmpty();
+        }
+        if (winner)
+            callback.callback();
+    }
+}
\ No newline at end of file

Copied: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceEMF.java (from r1637390, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceEMF.java)
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceEMF.java?p2=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceEMF.java&p1=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceEMF.java&r1=1637390&r2=1637878&rev=1637878&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceEMF.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceEMF.java Mon Nov 10 14:43:56 2014
@@ -1,8 +1,7 @@
-package org.apache.aries.jpa.container.impl;
+package org.apache.aries.jpa.container.quiesce.impl;
 
 import javax.persistence.EntityManagerFactory;
 
-import org.apache.aries.jpa.container.impl.EntityManagerFactoryManager.NamedCallback;
 import org.osgi.framework.ServiceRegistration;
 
 public interface QuiesceEMF extends EntityManagerFactory {

Copied: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceEMFHandler.java (from r1637390, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceEMFHandler.java)
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceEMFHandler.java?p2=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceEMFHandler.java&p1=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceEMFHandler.java&r1=1637390&r2=1637878&rev=1637878&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceEMFHandler.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceEMFHandler.java Mon Nov 10 14:43:56 2014
@@ -1,4 +1,4 @@
-package org.apache.aries.jpa.container.impl;
+package org.apache.aries.jpa.container.quiesce.impl;
 
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
@@ -9,7 +9,7 @@ import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.PersistenceException;
 
-import org.apache.aries.jpa.container.impl.EntityManagerFactoryManager.NamedCallback;
+import org.apache.aries.jpa.container.impl.NLS;
 import org.apache.aries.util.AriesFrameworkUtil;
 import org.osgi.framework.ServiceRegistration;
 
@@ -82,6 +82,9 @@ class QuiesceEMFHandler implements Invoc
         }
     }
     
+    /**
+     * Called on EntityManager.close()
+     */
     public void callback() {
         if (count.decrementAndGet() == 0) {
             NamedCallback c = callback.getAndSet(null);

Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceHandler.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceHandler.java?rev=1637878&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceHandler.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceHandler.java Mon Nov 10 14:43:56 2014
@@ -0,0 +1,7 @@
+package org.apache.aries.jpa.container.quiesce.impl;
+
+import org.osgi.framework.Bundle;
+
+public interface QuiesceHandler {
+    void quiesceBundle(Bundle bundleToQuiesce, final DestroyCallback callback);
+}

Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceParticipantFactory.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceParticipantFactory.java?rev=1637878&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceParticipantFactory.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceParticipantFactory.java Mon Nov 10 14:43:56 2014
@@ -0,0 +1,28 @@
+package org.apache.aries.jpa.container.quiesce.impl;
+
+import java.io.Closeable;
+
+import org.apache.aries.jpa.container.impl.NLS;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class QuiesceParticipantFactory {
+    /** The QuiesceParticipant implementation class name */
+    private static final String QUIESCE_PARTICIPANT_CLASS = "org.apache.aries.quiesce.participant.QuiesceParticipant";
+
+    /** Logger */
+    private static final Logger _logger = LoggerFactory.getLogger("org.apache.aries.jpa.container");
+
+    public static Closeable create(BundleContext context, QuiesceHandler quiesceHandler) {
+        try {
+            context.getBundle().loadClass(QUIESCE_PARTICIPANT_CLASS);
+            // Class was loaded, register
+            return new QuiesceParticipantImpl(context, quiesceHandler);
+        } catch (ClassNotFoundException e) {
+            _logger.info(NLS.MESSAGES.getMessage("quiesce.manager.not.there"));
+            return null;
+        }
+    }
+
+}

Copied: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceParticipantImpl.java (from r1637390, aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceParticipantImpl.java)
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceParticipantImpl.java?p2=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceParticipantImpl.java&p1=aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceParticipantImpl.java&r1=1637390&r2=1637878&rev=1637878&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/QuiesceParticipantImpl.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/quiesce/impl/QuiesceParticipantImpl.java Mon Nov 10 14:43:56 2014
@@ -16,8 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.aries.jpa.container.impl;
+package org.apache.aries.jpa.container.quiesce.impl;
 
+import java.io.Closeable;
+import java.io.IOException;
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ExecutorService;
@@ -27,9 +29,14 @@ import java.util.concurrent.ThreadFactor
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.aries.jpa.container.impl.PersistenceBundleManager;
 import org.apache.aries.quiesce.manager.QuiesceCallback;
 import org.apache.aries.quiesce.participant.QuiesceParticipant;
+import org.apache.aries.util.AriesFrameworkUtil;
+import org.apache.aries.util.io.IOUtils;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
 
 /**
  * This class provides Quiesce Participant support for JPA managed units. It is the only
@@ -37,7 +44,7 @@ import org.osgi.framework.Bundle;
  * optionally depend on the API. If no Quiesce API is available then this class will not be
  * loaded and no Quiesce support will be available.
  */
-public class QuiesceParticipantImpl implements QuiesceParticipant, DestroyCallback {
+public class QuiesceParticipantImpl implements QuiesceParticipant, Closeable {
   
   /**
    * A wrapper to protect our internals from the Quiesce API so that we can make it
@@ -72,18 +79,18 @@ public class QuiesceParticipantImpl impl
     /** The bundle being quiesced */
     private final Bundle bundleToQuiesce;
     /** The {@link PersistenceBundleManager} instance */
-    private final PersistenceBundleManager mgr; 
+    private final QuiesceHandler quiesceHandler; 
 
     public QuiesceBundle(QuiesceCallback callback, Bundle bundleToQuiesce,
-        PersistenceBundleManager mgr) {
+        QuiesceHandler quiesceHandler) {
       super();
       this.callback = new QuiesceDelegatingCallback(callback, bundleToQuiesce);
       this.bundleToQuiesce = bundleToQuiesce;
-      this.mgr = mgr;
+      this.quiesceHandler = quiesceHandler;
     }
 
     public void run() {
-      mgr.quiesceBundle(bundleToQuiesce, callback);
+      quiesceHandler.quiesceBundle(bundleToQuiesce, callback);
     }
   }
 
@@ -100,19 +107,23 @@ public class QuiesceParticipantImpl impl
       return t;
     }
   });
-  
-  /** The manager for persistence bundles */
-  private final PersistenceBundleManager mgr;
+
+  private QuiesceHandler quiesceHandler;
+  private final BundleContext context;
+  private ServiceRegistration quiesceReg;
   
   /** Some events that we need to tidy up */
-  private final BlockingQueue<DestroyCallback> unhandledQuiesces = new LinkedBlockingQueue<DestroyCallback>(); 
+  private final BlockingQueue<DestroyCallback> unhandledQuiesces = new LinkedBlockingQueue<DestroyCallback>();
   
-  public QuiesceParticipantImpl(PersistenceBundleManager mgr) {
-    this.mgr = mgr;
+  public QuiesceParticipantImpl(BundleContext context, QuiesceHandler quiesceHandler) {
+    this.context = context;
+    this.quiesceHandler = quiesceHandler;
+    context.registerService(QuiesceParticipant.class.getName(), this, null);
   }
 
 
   public void quiesce(QuiesceCallback qc, List<Bundle> arg1) {
+    boolean closeSelf = false;
     //Run a quiesce operation for each bundle being quiesced
     for(Bundle b : arg1) {
       try {
@@ -120,30 +131,33 @@ public class QuiesceParticipantImpl impl
           //This bundle is not in an "ACTIVE" state (or starting or stopping)
           qc.bundleQuiesced(b);
         } else {
-          executor.execute(new QuiesceBundle(qc, b, mgr));
+          executor.execute(new QuiesceBundle(qc, b, quiesceHandler));
         }
       } catch (RejectedExecutionException re) {
         unhandledQuiesces.add(new QuiesceDelegatingCallback(qc, b));
       }
       //If we are quiescing, then we need to quiesce this threadpool!
-      if(b.equals(mgr.getCtx().getBundle()))
-        executor.shutdown();
+      if(b.equals(context.getBundle())) {
+          closeSelf = true;
+      }
+    }
+    if (closeSelf) {
+        IOUtils.close(this);
     }
   }
   
-  /**
-   * Close down this object
-   */
-  public void callback() {
-    executor.shutdown();
-    try {
-      for(DestroyCallback cbk : unhandledQuiesces) {
-        cbk.callback();
+  @Override
+  public void close() throws IOException {
+      executor.shutdown();
+      try {
+        for(DestroyCallback cbk : unhandledQuiesces) {
+          cbk.callback();
+        }
+        executor.awaitTermination(5, TimeUnit.SECONDS);
+      } catch (InterruptedException e) {
+        //We don't care
       }
-      executor.awaitTermination(5, TimeUnit.SECONDS);
-    } catch (InterruptedException e) {
-      //We don't care
-    }
-    executor.shutdownNow();
+      executor.shutdownNow();
+      AriesFrameworkUtil.safeUnregisterService(quiesceReg);
   }
 }

Modified: aries/trunk/jpa/jpa-container/src/test/java/org/apache/aries/jpa/container/PersistenceBundleLifecycleTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/test/java/org/apache/aries/jpa/container/PersistenceBundleLifecycleTest.java?rev=1637878&r1=1637877&r2=1637878&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/test/java/org/apache/aries/jpa/container/PersistenceBundleLifecycleTest.java (original)
+++ aries/trunk/jpa/jpa-container/src/test/java/org/apache/aries/jpa/container/PersistenceBundleLifecycleTest.java Mon Nov 10 14:43:56 2014
@@ -961,7 +961,7 @@ private void assertCloseCalled() {
     
     QuiesceCallback cbk = Skeleton.newMock(QuiesceCallback.class);
     
-    QuiesceParticipant p = (QuiesceParticipant) ctx.getService(ctx.getServiceReference(QuiesceParticipant.class.getName()));
+    QuiesceParticipant p = getQuiesceParticipant(ctx);
   
     p.quiesce(cbk, Collections.singletonList(persistenceBundle));
     
@@ -970,7 +970,7 @@ private void assertCloseCalled() {
     Skeleton.getSkeleton(cbk).assertCalledExactNumberOfTimes(new MethodCall(QuiesceCallback.class,
         "bundleQuiesced", Bundle[].class), 1);
   }
-  
+
   /**
    * Quiesce a JPA bundle that is not active
    * @throws Exception
@@ -990,7 +990,7 @@ private void assertCloseCalled() {
     
     QuiesceCallback cbk = Skeleton.newMock(QuiesceCallback.class);
     
-    QuiesceParticipant p = (QuiesceParticipant) ctx.getService(ctx.getServiceReference(QuiesceParticipant.class.getName()));
+    QuiesceParticipant p = getQuiesceParticipant(ctx);
   
     p.quiesce(cbk, Collections.singletonList(persistenceBundle));
     
@@ -1027,7 +1027,7 @@ private void assertCloseCalled() {
     
     QuiesceCallback cbk = Skeleton.newMock(QuiesceCallback.class);
     
-    QuiesceParticipant p = (QuiesceParticipant) ctx.getService(ctx.getServiceReference(QuiesceParticipant.class.getName()));
+    QuiesceParticipant p = getQuiesceParticipant(ctx);
   
     p.quiesce(cbk, Collections.singletonList(persistenceBundle));
     
@@ -1073,7 +1073,7 @@ private void assertCloseCalled() {
     
     QuiesceCallback cbk = Skeleton.newMock(QuiesceCallback.class);
     
-    QuiesceParticipant p = (QuiesceParticipant) ctx.getService(ctx.getServiceReference(QuiesceParticipant.class.getName()));
+    QuiesceParticipant p = getQuiesceParticipant(ctx);
   
     p.quiesce(cbk, Collections.singletonList(extenderBundle));
     
@@ -1101,7 +1101,7 @@ private void assertCloseCalled() {
     
     QuiesceCallback cbk = Skeleton.newMock(QuiesceCallback.class);
     
-    QuiesceParticipant p = (QuiesceParticipant) ctx.getService(ctx.getServiceReference(QuiesceParticipant.class.getName()));
+    QuiesceParticipant p = getQuiesceParticipant(ctx);
   
     p.quiesce(cbk, Collections.singletonList(extenderBundle));
     
@@ -1158,7 +1158,7 @@ private void assertCloseCalled() {
     
     QuiesceCallback cbk = Skeleton.newMock(QuiesceCallback.class);
     
-    QuiesceParticipant p = (QuiesceParticipant) ctx.getService(ctx.getServiceReference(QuiesceParticipant.class.getName()));
+    QuiesceParticipant p = getQuiesceParticipant(ctx);
   
     p.quiesce(cbk, Collections.singletonList(extenderBundle));
     
@@ -1485,5 +1485,11 @@ private void assertCloseCalled() {
     
     return map.get(persistenceBundle);
   }
+  
+
+  private QuiesceParticipant getQuiesceParticipant(BundleContext ctx) {
+    return (QuiesceParticipant) ctx.getService(ctx.getServiceReference(QuiesceParticipant.class.getName()));
+  }
+  
 }