Allow Builder clients to close the EMF, but not service clients
diff --git a/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/AriesEntityManagerFactoryBuilder.java b/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/AriesEntityManagerFactoryBuilder.java
index cdeb31d..56ad2c2 100644
--- a/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/AriesEntityManagerFactoryBuilder.java
+++ b/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/AriesEntityManagerFactoryBuilder.java
@@ -18,6 +18,9 @@
  */
 package org.apache.aries.jpa.container.impl;
 
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.Hashtable;
@@ -163,7 +166,22 @@
 		
 		closeEMF();
 		
-		return createAndPublishEMF(processedProperties);
+		final EntityManagerFactory toUse = createAndPublishEMF(processedProperties);
+		
+		return (EntityManagerFactory) Proxy.newProxyInstance(getClass().getClassLoader(), 
+				new Class<?>[] {EntityManagerFactory.class}, new InvocationHandler() {
+					
+					@Override
+					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+						if("close".equals(method.getName())) {
+							// Close the registration as per the spec
+							closeEMF();
+							// Do not delegate as the closeEMF call already closes
+							return null;
+						}
+						return method.invoke(toUse, args);
+					}
+				});
 	}
 
 	public String getPUName() {
@@ -336,7 +354,7 @@
 			}
 		}
 		
-		EntityManagerFactory tmp = provider.createContainerEntityManagerFactory(persistenceUnit, overrides);
+		final EntityManagerFactory tmp = provider.createContainerEntityManagerFactory(persistenceUnit, overrides);
 		boolean register = false;
 		synchronized (this) {
 			if(emf == null) {
@@ -349,7 +367,20 @@
 			Dictionary<String, Object> props = createBuilderProperties(overrides);
 			BundleContext uctx = bundle.getBundleContext();
 			ServiceRegistration<EntityManagerFactory> tmpReg = 
-					uctx.registerService(EntityManagerFactory.class, emf, props);
+					uctx.registerService(EntityManagerFactory.class, 
+							(EntityManagerFactory) Proxy.newProxyInstance(getClass().getClassLoader(), 
+									new Class<?>[] {EntityManagerFactory.class}, 
+									new InvocationHandler() {
+										
+										@Override
+										public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+											if("close".equals(method.getName())) {
+												// Ignore close as per the spec
+												return null;
+											}
+											return method.invoke(tmp, args);
+										}
+									}), props);
 			
 			synchronized (this) {
 				if(emf == tmp) {
diff --git a/jpa-container/src/test/java/org/apache/aries/jpa/container/impl/PropsConfigurationTest.java b/jpa-container/src/test/java/org/apache/aries/jpa/container/impl/PropsConfigurationTest.java
index 20cd2b9..b0f1f7e 100644
--- a/jpa-container/src/test/java/org/apache/aries/jpa/container/impl/PropsConfigurationTest.java
+++ b/jpa-container/src/test/java/org/apache/aries/jpa/container/impl/PropsConfigurationTest.java
@@ -29,6 +29,7 @@
 import static org.mockito.Matchers.anyMap;

 import static org.mockito.Matchers.argThat;

 import static org.mockito.Matchers.eq;

+import static org.mockito.Mockito.atLeastOnce;

 import static org.mockito.Mockito.verify;

 import static org.mockito.Mockito.verifyZeroInteractions;

 import static org.mockito.Mockito.when;

@@ -53,6 +54,7 @@
 import org.junit.Before;

 import org.junit.Test;

 import org.junit.runner.RunWith;

+import org.mockito.ArgumentCaptor;

 import org.mockito.Mock;

 import org.mockito.Mockito;

 import org.mockito.invocation.InvocationOnMock;

@@ -140,7 +142,7 @@
 				}

 			});

 		

-		when(punitContext.registerService(eq(EntityManagerFactory.class), eq(emf), 

+		when(punitContext.registerService(eq(EntityManagerFactory.class), any(EntityManagerFactory.class), 

 				any(Dictionary.class))).thenReturn(emfReg);

 		

 		when(emf.isOpen()).thenReturn(true);

@@ -234,7 +236,7 @@
 		

 		verify(punit).setNonJtaDataSource(ds);

 		verify(punitContext).registerService(eq(EntityManagerFactory.class),

-				eq(emf), argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")));

+				any(EntityManagerFactory.class), argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")));

 		

 		emfb.close();

 		

@@ -262,7 +264,7 @@
         

         

         verify(punitContext).registerService(eq(EntityManagerFactory.class),

-        		eq(emf), and(argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")),

+        		any(EntityManagerFactory.class), and(argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")),

         				argThat(servicePropsMatcher("hibernate.hbm2ddl.auto", "create-drop"))));

         

         emfb.close();

@@ -291,7 +293,7 @@
     	

     	verify(punit).setJtaDataSource(ds);

     	verify(punitContext).registerService(eq(EntityManagerFactory.class),

-    			eq(emf), argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")));

+    			any(EntityManagerFactory.class), argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")));

     	

     	emfb.close();

 		verify(emfReg).unregister();

@@ -319,7 +321,8 @@
     	

     	verify(punit).setJtaDataSource(ds);

     	verify(punitContext).registerService(eq(EntityManagerFactory.class),

-    			eq(emf), and(and(argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")),

+    			any(EntityManagerFactory.class), 

+    			and(and(argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")),

     					argThat(servicePropsMatcher("javax.persistence.jdbc.user", JDBC_USER))),

     					not(argThat(servicePropsMatcher("javax.persistence.jdbc.password", JDBC_PASSWORD)))));

     	

@@ -362,7 +365,7 @@
     	

     	verify(punit).setJtaDataSource(ds);

     	verify(punitContext).registerService(eq(EntityManagerFactory.class),

-    			eq(emf), argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")));

+    			any(EntityManagerFactory.class), argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")));

     	

     	

     	try {

@@ -394,7 +397,7 @@
     	

     	verify(punit).setJtaDataSource(ds);

     	verify(punitContext).registerService(eq(EntityManagerFactory.class),

-    			eq(emf), argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")));

+    			any(EntityManagerFactory.class), argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")));

     	

     	emfb.close();

     }

@@ -419,7 +422,63 @@
     	

     	verify(punit).setNonJtaDataSource(ds);

     	verify(punitContext).registerService(eq(EntityManagerFactory.class),

-    			eq(emf), argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")));

+    			any(EntityManagerFactory.class), argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")));

+    	

+    	emfb.close();

+    }

+    

+    @Test

+	public void testReturnedEmfClose() throws InvalidSyntaxException, ConfigurationException {

+		

+		when(provider.createContainerEntityManagerFactory(eq(punit), 

+				eq(singletonMap(PersistenceUnitTransactionType.class.getName(), JTA))))

+			.thenReturn(emf);

+		

+		Map<String, Object> props = new Hashtable<String, Object>();

+		props.put("javax.persistence.dataSource", ds);

+		

+		AriesEntityManagerFactoryBuilder emfb = new AriesEntityManagerFactoryBuilder(

+				containerContext, provider, punit);

+		

+		EntityManagerFactory returnedEMF = emfb.createEntityManagerFactory(props);

+		

+		

+		verify(punit).setNonJtaDataSource(ds);

+		verify(punitContext).registerService(eq(EntityManagerFactory.class),

+				any(EntityManagerFactory.class), argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")));

+		

+		returnedEMF.close();

+		

+		verify(emfReg).unregister();

+		verify(emf).close();

+		

+		emfb.close();

+	}

+

+    @Test

+    public void testServiceEmfClose() throws InvalidSyntaxException, ConfigurationException {

+    	

+    	when(provider.createContainerEntityManagerFactory(eq(punit), 

+    			eq(singletonMap(PersistenceUnitTransactionType.class.getName(), JTA))))

+    	.thenReturn(emf);

+    	

+    	Map<String, Object> props = new Hashtable<String, Object>();

+    	props.put("javax.persistence.dataSource", ds);

+    	

+    	AriesEntityManagerFactoryBuilder emfb = new AriesEntityManagerFactoryBuilder(

+    			containerContext, provider, punit);

+    	

+    	emfb.createEntityManagerFactory(props);

+    	

+    	ArgumentCaptor<EntityManagerFactory> emfCaptor = ArgumentCaptor.forClass(EntityManagerFactory.class);

+    	

+    	verify(punit).setNonJtaDataSource(ds);

+    	verify(punitContext).registerService(eq(EntityManagerFactory.class),

+    			emfCaptor.capture(), argThat(servicePropsMatcher(JPA_UNIT_NAME, "test-props")));

+    	

+    	emfCaptor.getValue().close();

+    	

+    	verifyZeroInteractions(emfReg, emf);

     	

     	emfb.close();

     }