[tx-control] Update the JPA resource provider to support plugins when using the EntityManagerFactoryBuilder

git-svn-id: https://svn.apache.org/repos/asf/aries/trunk/tx-control@1809330 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractJPATransactionTest.java b/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractJPATransactionTest.java
index 3bab3b4..34a911f 100644
--- a/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractJPATransactionTest.java
+++ b/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractJPATransactionTest.java
@@ -27,14 +27,20 @@
 

 import java.io.File;

 import java.io.IOException;

+import java.sql.SQLException;

 import java.util.ArrayList;

+import java.util.Collections;

 import java.util.Dictionary;

+import java.util.HashMap;

 import java.util.Hashtable;

 import java.util.List;

+import java.util.Map;

 import java.util.NoSuchElementException;

+import java.util.Properties;

 

 import javax.inject.Inject;

 import javax.persistence.EntityManager;

+import javax.sql.CommonDataSource;

 

 import org.h2.tools.Server;

 import org.junit.After;

@@ -58,6 +64,7 @@
 import org.osgi.service.jpa.EntityManagerFactoryBuilder;

 import org.osgi.service.transaction.control.TransactionControl;

 import org.osgi.service.transaction.control.jpa.JPAEntityManagerProvider;

+import org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory;

 import org.osgi.util.tracker.ServiceTracker;

 

 @RunWith(PaxExam.class)

@@ -67,18 +74,24 @@
 	protected static final String TX_CONTROL_FILTER = "tx.control.filter";

 	protected static final String ARIES_EMF_BUILDER_TARGET_FILTER = "aries.emf.builder.target.filter";

 	protected static final String IS_XA = "aries.test.is.xa";

+	protected static final String CONFIGURED_PROVIDER_PROPERTY = "org.apache.aries.tx.control.itests.configured";

 

 	@Inject

 	BundleContext context;

 	

 	protected TransactionControl txControl;

 

+	protected JPAEntityManagerProvider provider;

 	protected EntityManager em;

+	

+	// Set when using programmatic creation

+	protected EntityManagerFactoryBuilder builder;

+	protected Map<String, Object> jpaProps;

+	protected Map<String, Object> providerProps;

 

 	private Server server;

 	

-	private final List<ServiceTracker<?,?>> trackers = new ArrayList<>();

-

+	protected final List<ServiceTracker<?,?>> trackers = new ArrayList<>();

 	@Before

 	public void setUp() throws Exception {

 		

@@ -89,9 +102,15 @@
 		

 		String jdbcUrl = "jdbc:h2:tcp://127.0.0.1:" + server.getPort() + "/" + getRemoteDBPath();

 		

-		em = configuredEntityManager(jdbcUrl);

+		boolean configuredProvider = isConfigured();

+		

+		em = configuredProvider ? configuredEntityManager(jdbcUrl) : programaticEntityManager(jdbcUrl);

 	}

 

+	public boolean isConfigured() {

+		return Boolean.getBoolean(CONFIGURED_PROVIDER_PROPERTY);

+	}

+	

 	protected <T> T getService(Class<T> clazz, long timeout) {

 		try {

 			return getService(clazz, null, timeout);

@@ -161,7 +180,34 @@
 		

 		return getService(JPAEntityManagerProvider.class, 5000).getResource(txControl);

 	}

+	

+	private EntityManager programaticEntityManager(String jdbcURL) throws SQLException {

+		

+		JPAEntityManagerProviderFactory resourceProviderFactory = getService(JPAEntityManagerProviderFactory.class, 5000);

+		

+		DataSourceFactory dsf = getService(DataSourceFactory.class, 5000);

+		

+		Properties props = new Properties();

+		props.put(DataSourceFactory.JDBC_URL, jdbcURL);

+		CommonDataSource dataSource = getBoolean(IS_XA) ? dsf.createXADataSource(props) :

+			dsf.createDataSource(props);

+		

+		providerProps = new HashMap<>();

+		Dictionary<String,Object> baseProperties = getBaseProperties();

+		for (String string : Collections.list(baseProperties.keys())) {

+			providerProps.put(string, baseProperties.get(string));

+		}

 

+		jpaProps = new HashMap<>(providerProps);

+		jpaProps.put("javax.persistence.dataSource", dataSource);

+		

+		

+		builder = getService(EntityManagerFactoryBuilder.class, 5000);

+		

+		provider = resourceProviderFactory.getProviderFor(builder, jpaProps, providerProps);

+		return provider.getResource(txControl);

+	}

+	

 	protected Dictionary<String, Object> getBaseProperties() {

 		return new Hashtable<>();

 	}

@@ -176,8 +222,14 @@
 		}

 

 		trackers.stream().forEach(ServiceTracker::close);

+		trackers.clear();

 		

+		txControl = null;

+		provider = null;

 		em = null;

+		builder = null;

+		jpaProps = null;

+		providerProps = null;

 	}

 

 	private void clearConfiguration() {

@@ -213,6 +265,51 @@
 	}

 	

 	@Configuration

+	public Option[] localTxFactory() {

+		String localRepo = System.getProperty("maven.repo.local");

+		if (localRepo == null) {

+			localRepo = System.getProperty("org.ops4j.pax.url.mvn.localRepository");

+		}

+		

+		return options(junitBundles(), systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("INFO"),

+				when(localRepo != null)

+				.useOptions(CoreOptions.vmOption("-Dorg.ops4j.pax.url.mvn.localRepository=" + localRepo)),

+				localTxControlService(),

+				localJpaResourceProviderWithH2(),

+				jpaProvider(),

+				ariesJPA(),

+				mavenBundle("org.apache.felix", "org.apache.felix.configadmin").versionAsInProject(),

+				mavenBundle("org.ops4j.pax.logging", "pax-logging-api").versionAsInProject(),

+				mavenBundle("org.ops4j.pax.logging", "pax-logging-service").versionAsInProject()

+				

+//				,CoreOptions.vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005")

+				);

+	}

+	

+	@Configuration

+	public Option[] xaTxFactory() {

+		String localRepo = System.getProperty("maven.repo.local");

+		if (localRepo == null) {

+			localRepo = System.getProperty("org.ops4j.pax.url.mvn.localRepository");

+		}

+		

+		return options(junitBundles(), systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("INFO"),

+				when(localRepo != null)

+				.useOptions(CoreOptions.vmOption("-Dorg.ops4j.pax.url.mvn.localRepository=" + localRepo)),

+				systemProperty(IS_XA).value(Boolean.TRUE.toString()),

+				xaTxControlService(),

+				xaJpaResourceProviderWithH2(),

+				jpaProvider(),

+				ariesJPA(),

+				mavenBundle("org.apache.felix", "org.apache.felix.configadmin").versionAsInProject(),

+				mavenBundle("org.ops4j.pax.logging", "pax-logging-api").versionAsInProject(),

+				mavenBundle("org.ops4j.pax.logging", "pax-logging-service").versionAsInProject()

+				

+//				,CoreOptions.vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005")

+				);

+	}

+	

+	@Configuration

 	public Option[] localTxConfiguration() {

 		String localRepo = System.getProperty("maven.repo.local");

 		if (localRepo == null) {

@@ -222,6 +319,7 @@
 		return options(junitBundles(), systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("INFO"),

 				when(localRepo != null)

 				.useOptions(CoreOptions.vmOption("-Dorg.ops4j.pax.url.mvn.localRepository=" + localRepo)),

+				systemProperty(CONFIGURED_PROVIDER_PROPERTY).value(Boolean.TRUE.toString()),

 				localTxControlService(),

 				localJpaResourceProviderWithH2(),

 				jpaProvider(),

@@ -245,6 +343,7 @@
 				when(localRepo != null)

 				.useOptions(CoreOptions.vmOption("-Dorg.ops4j.pax.url.mvn.localRepository=" + localRepo)),

 				systemProperty(IS_XA).value(Boolean.TRUE.toString()),

+				systemProperty(CONFIGURED_PROVIDER_PROPERTY).value(Boolean.TRUE.toString()),

 				xaTxControlService(),

 				xaJpaResourceProviderWithH2(),

 				jpaProvider(),

diff --git a/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractSimpleTransactionTest.java b/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractSimpleTransactionTest.java
index 4653c9d..29187ae 100644
--- a/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractSimpleTransactionTest.java
+++ b/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/AbstractSimpleTransactionTest.java
@@ -28,11 +28,11 @@
 import javax.persistence.criteria.CriteriaQuery;

 

 import org.apache.aries.tx.control.itests.entity.Message;

-import org.junit.Assume;

 import org.junit.Test;

 import org.osgi.framework.Bundle;

 import org.osgi.service.transaction.control.TransactionControl;

 import org.osgi.service.transaction.control.jpa.JPAEntityManagerProvider;

+import org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory;

 

 public abstract class AbstractSimpleTransactionTest extends AbstractJPATransactionTest {

 

@@ -242,9 +242,8 @@
 	public void reassignTxControl() throws Exception {

 		

 		Optional<Bundle> bundle = stream(context.getBundles())

-				.filter(b -> b.getSymbolicName().equals("tx-control-provider-jpa-xa"))

+				.filter(b -> b.getSymbolicName().startsWith("tx-control-provider-jpa"))

 				.findAny();

-		Assume.assumeTrue(bundle.isPresent());

 		

 		bundle.get().stop();

 		bundle.get().start();

@@ -252,7 +251,12 @@
 		txControl = getService(TransactionControl.class, 

 				System.getProperty(TX_CONTROL_FILTER), 5000);

 		

-		em = getService(JPAEntityManagerProvider.class, 5000).getResource(txControl); 

+		if(isConfigured()) {

+			em = getService(JPAEntityManagerProvider.class, 5000).getResource(txControl); 

+		} else {

+			em = getService(JPAEntityManagerProviderFactory.class, 5000)

+					.getProviderFor(builder, jpaProps, providerProps).getResource(txControl);

+		}

 		

 		testTx();

 	}

diff --git a/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/JPALifecycleTest.java b/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/JPALifecycleTest.java
index 7ddd8f5..23b825e 100644
--- a/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/JPALifecycleTest.java
+++ b/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/JPALifecycleTest.java
@@ -35,6 +35,7 @@
 import java.util.function.Predicate;

 

 import org.apache.aries.tx.control.itests.entity.Message;

+import org.junit.Assume;

 import org.junit.Test;

 import org.junit.runner.RunWith;

 import org.ops4j.pax.exam.CoreOptions;

@@ -49,7 +50,7 @@
 import org.osgi.service.transaction.control.ScopedWorkException;

 import org.osgi.service.transaction.control.TransactionException;

 import org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory;

-import org.osgi.service.transaction.control.jpa.JPAEntityManagerProvider;

+import org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory;

 

 @RunWith(PaxExam.class)

 @ExamReactorStrategy(PerMethod.class)

@@ -146,12 +147,13 @@
 				} catch (BundleException e) {

 				}

 			});

-			getService(JPAEntityManagerProvider.class, 5000);

+			getService(JPAEntityManagerProviderFactory.class, 5000);

 		}

 	}

 

 	@Test

 	public void testDeleteOfConfig() throws Exception {

+		Assume.assumeTrue("Not a config test", isConfigured());

 		

 		Message m = new Message();

 		m.message = "Hello World";

@@ -183,6 +185,8 @@
 	@Test

 	public void testUpdateOfConfig() throws Exception {

 		

+		Assume.assumeTrue("Not a config test", isConfigured());

+		

 		Message m = new Message();

 		m.message = "Hello World";

 		txControl.required(() -> {em.persist(m); return null;});

@@ -209,34 +213,34 @@
 			assertEquals("There was a problem getting hold of a database connection", swe.getCause().getMessage());

 		}

 	}

-//

-//	@Test

-//	public void testReleaseOfFactoryService() {

-//		Assume.assumeFalse("Not a factory test", isConfigured());

-//

-//		txControl.required(

-//				() -> connection.createStatement().execute("Insert into TEST_TABLE values ( 'Hello World!' )"));

-//

-//		assertEquals("Hello World!", txControl.notSupported(() -> {

-//			ResultSet rs = connection.createStatement().executeQuery("Select * from TEST_TABLE");

-//			rs.next();

-//			return rs.getString(1);

-//		}));

-//

-//		trackers.stream().filter(t -> t.getService() instanceof JDBCConnectionProviderFactory).findFirst().get()

-//				.close();

-//		;

-//

-//		try {

-//			assertEquals("Hello World!", txControl.notSupported(() -> {

-//				ResultSet rs = connection.createStatement().executeQuery("Select * from TEST_TABLE");

-//				rs.next();

-//				return rs.getString(1);

-//			}));

-//			fail("Should not be accessible");

-//		} catch (ScopedWorkException swe) {

-//			assertTrue(swe.getCause().toString(), swe.getCause() instanceof TransactionException);

-//			assertEquals("There was a problem getting hold of a database connection", swe.getCause().getMessage());

-//		}

-//	}

+

+	@Test

+	public void testReleaseOfFactoryService() {

+		Assume.assumeFalse("Not a factory test", isConfigured());

+

+		Message m = new Message();

+		m.message = "Hello World!";

+		

+		txControl.required(

+				() -> { em.persist(m); return null;});

+

+		assertEquals("Hello World!", txControl.notSupported(() -> em.find(Message.class, m.id).message));

+

+		JPAEntityManagerProviderFactory factory = trackers.stream()

+				.map(t -> t.getService())

+				.filter(s -> s instanceof JPAEntityManagerProviderFactory)

+				.map(s -> (JPAEntityManagerProviderFactory) s)

+				.findFirst()

+				.get();

+

+		factory.releaseProvider(provider);

+

+		try {

+			assertEquals("Hello World!", txControl.notSupported(() -> em.find(Message.class, m.id).message));

+			fail("Should not be accessible");

+		} catch (ScopedWorkException swe) {

+			assertTrue(swe.getCause().toString(), swe.getCause() instanceof TransactionException);

+			assertEquals("There was a problem getting hold of a database connection", swe.getCause().getMessage());

+		}

+	}

 }

diff --git a/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/XAJPATransactionTest.java b/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/XAJPATransactionTest.java
index b800ff7..e9fe65c 100644
--- a/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/XAJPATransactionTest.java
+++ b/tx-control-providers/jpa/tx-control-jpa-itests/src/test/java/org/apache/aries/tx/control/itests/XAJPATransactionTest.java
@@ -18,8 +18,11 @@
  */

 package org.apache.aries.tx.control.itests;

 

+import static java.lang.Boolean.FALSE;

+import static java.lang.Boolean.TRUE;

 import static org.junit.Assert.assertEquals;

 import static org.junit.Assert.fail;

+import static org.ops4j.pax.exam.CoreOptions.composite;

 import static org.ops4j.pax.exam.CoreOptions.junitBundles;

 import static org.ops4j.pax.exam.CoreOptions.mavenBundle;

 import static org.ops4j.pax.exam.CoreOptions.options;

@@ -32,15 +35,20 @@
 import java.lang.reflect.Field;

 import java.util.ArrayList;

 import java.util.Arrays;

+import java.util.Collections;

 import java.util.Dictionary;

+import java.util.HashMap;

 import java.util.Hashtable;

 import java.util.List;

+import java.util.Map;

 import java.util.NoSuchElementException;

+import java.util.Properties;

 

 import javax.inject.Inject;

 import javax.persistence.EntityManager;

 import javax.persistence.criteria.CriteriaBuilder;

 import javax.persistence.criteria.CriteriaQuery;

+import javax.sql.XADataSource;

 import javax.transaction.xa.XAException;

 import javax.transaction.xa.XAResource;

 import javax.transaction.xa.Xid;

@@ -71,6 +79,7 @@
 import org.osgi.service.transaction.control.TransactionControl;

 import org.osgi.service.transaction.control.TransactionRolledBackException;

 import org.osgi.service.transaction.control.jpa.JPAEntityManagerProvider;

+import org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory;

 import org.osgi.util.promise.Deferred;

 import org.osgi.util.tracker.ServiceTracker;

 

@@ -82,6 +91,7 @@
 	static final String XA_TEST_UNIT_2 = "xa-test-unit-2";

 

 	protected static final String ARIES_EMF_BUILDER_TARGET_FILTER = "aries.emf.builder.target.filter";

+	protected static final String CONFIGURED_PROVIDER_PROPERTY = "org.apache.aries.tx.control.itests.configured";

 	

 	@Inject

 	BundleContext context;

@@ -109,8 +119,14 @@
 		String jdbcUrl1 = "jdbc:h2:tcp://127.0.0.1:" + server1.getPort() + "/" + getRemoteDBPath("db1");

 		String jdbcUrl2 = "jdbc:h2:tcp://127.0.0.1:" + server2.getPort() + "/" + getRemoteDBPath("db2");

 		

-		em1 = configuredEntityManager(jdbcUrl1, XA_TEST_UNIT_1);

-		em2 = configuredEntityManager(jdbcUrl2, XA_TEST_UNIT_2);

+		em1 = isConfigured() ? configuredEntityManager(jdbcUrl1, XA_TEST_UNIT_1) :

+			factoryEntityManager(jdbcUrl1, XA_TEST_UNIT_1);

+		em2 = isConfigured() ? configuredEntityManager(jdbcUrl2, XA_TEST_UNIT_2) :

+			factoryEntityManager(jdbcUrl2, XA_TEST_UNIT_2);

+	}

+	

+	public boolean isConfigured() {

+		return Boolean.getBoolean(CONFIGURED_PROVIDER_PROPERTY);

 	}

 

 	private String getRemoteDBPath(String dbName) {

@@ -148,6 +164,32 @@
 				5000).getResource(txControl);

 	}

 

+	private EntityManager factoryEntityManager(String jdbcUrl, String unit) throws Exception {

+		

+		JPAEntityManagerProviderFactory resourceProviderFactory = getService(JPAEntityManagerProviderFactory.class, 5000);

+		

+		DataSourceFactory dsf = getService(DataSourceFactory.class, 5000);

+		

+		Properties props = new Properties();

+		props.put(DataSourceFactory.JDBC_URL, jdbcUrl);

+		XADataSource dataSource = dsf.createXADataSource(props);

+		

+		Map<String, Object> providerProps = new HashMap<>();

+		Dictionary<String,Object> baseProperties = getBaseProperties();

+		for (String string : Collections.list(baseProperties.keys())) {

+			providerProps.put(string, baseProperties.get(string));

+		}

+

+		providerProps.put("javax.persistence.dataSource", dataSource);

+		

+		

+		EntityManagerFactoryBuilder builder = getService(EntityManagerFactoryBuilder.class, 

+				"(osgi.unit.name=" + unit + ")",5000);

+		

+		return resourceProviderFactory.getProviderFor(builder, providerProps, providerProps)

+				.getResource(txControl);

+	}

+

 	private <T> T getService(Class<T> clazz, long timeout) {

 		try {

 			return getService(clazz, null, timeout);

@@ -197,6 +239,7 @@
 		}

 

 		trackers.stream().forEach(ServiceTracker::close);

+		trackers.clear();

 		

 		em1 = null;

 		em2 = null;

@@ -234,6 +277,21 @@
 	

 	@Configuration

 	public Option[] xaTxConfiguration() {

+		return options(

+				composite(xaTx()),

+				systemProperty(CONFIGURED_PROVIDER_PROPERTY).value(TRUE.toString())

+			);

+	}

+	

+	@Configuration

+	public Option[] xaTxFactory() {

+		return options(

+				composite(xaTx()),

+				systemProperty(CONFIGURED_PROVIDER_PROPERTY).value(FALSE.toString())

+				);

+	}

+	

+	private Option[] xaTx() {

 		String localRepo = System.getProperty("maven.repo.local");

 		if (localRepo == null) {

 			localRepo = System.getProperty("org.ops4j.pax.url.mvn.localRepository");

diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/AbstractManagedJPADataSourceSetup.java b/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/AbstractManagedJPADataSourceSetup.java
index 76fae7c..1324a39 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/AbstractManagedJPADataSourceSetup.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/AbstractManagedJPADataSourceSetup.java
@@ -19,27 +19,15 @@
 package org.apache.aries.tx.control.jpa.common.impl;
 
 import static java.util.Collections.unmodifiableMap;
-import static java.util.Optional.ofNullable;
-import static java.util.concurrent.TimeUnit.HOURS;
-import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.osgi.framework.Constants.OBJECTCLASS;
 import static org.osgi.service.jdbc.DataSourceFactory.OSGI_JDBC_DRIVER_CLASS;
-import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.CONNECTION_LIFETIME;
-import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.CONNECTION_POOLING_ENABLED;
-import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.CONNECTION_TIMEOUT;
-import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.IDLE_TIMEOUT;
-import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.MAX_CONNECTIONS;
-import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.MIN_CONNECTIONS;
 
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 
-import javax.sql.DataSource;
-
 import org.apache.aries.tx.control.resource.common.impl.LifecycleAware;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
@@ -51,17 +39,11 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.zaxxer.hikari.HikariConfig;
-import com.zaxxer.hikari.HikariDataSource;
-
 public abstract class AbstractManagedJPADataSourceSetup implements LifecycleAware,
 		ServiceTrackerCustomizer<DataSourceFactory, AbstractManagedJPAEMFLocator> {
 
 	private static final Logger LOG = LoggerFactory.getLogger(AbstractManagedJPADataSourceSetup.class);
 	
-	// TODO - where should this go?
-	private static final String CONNECTION_TEST_QUERY = "aries.connection.test.query";
-	
 	private final BundleContext context;
 	private final String pid;
 	private final Properties jdbcProperties;
@@ -163,75 +145,4 @@
 			}
 		}
 	}
-	
-	protected DataSource poolIfNecessary(Map<String, Object> resourceProviderProperties, DataSource unpooled) {
-		DataSource toUse;
-
-		if (toBoolean(resourceProviderProperties, CONNECTION_POOLING_ENABLED, true)) {
-			HikariConfig hcfg = new HikariConfig();
-			hcfg.setDataSource(unpooled);
-
-			// Sizes
-			hcfg.setMaximumPoolSize(toInt(resourceProviderProperties, MAX_CONNECTIONS, 10));
-			hcfg.setMinimumIdle(toInt(resourceProviderProperties, MIN_CONNECTIONS, 10));
-
-			// Timeouts
-			hcfg.setConnectionTimeout(toLong(resourceProviderProperties, CONNECTION_TIMEOUT, SECONDS.toMillis(30)));
-			hcfg.setIdleTimeout(toLong(resourceProviderProperties, IDLE_TIMEOUT, TimeUnit.MINUTES.toMillis(3)));
-			hcfg.setMaxLifetime(toLong(resourceProviderProperties, CONNECTION_LIFETIME, HOURS.toMillis(3)));
-	
-			hcfg.setConnectionTestQuery((String)resourceProviderProperties.get(CONNECTION_TEST_QUERY));
-			
-			toUse = new HikariDataSource(hcfg);
-
-		} else {
-			toUse = unpooled;
-		}
-		return toUse;
-	}
-
-	protected boolean toBoolean(Map<String, Object> props, String key, boolean defaultValue) {
-		Object o =  ofNullable(props)
-			.map(m -> m.get(key))
-			.orElse(defaultValue);
-		
-		if (o instanceof Boolean) {
-			return ((Boolean) o).booleanValue();
-		} else if(o instanceof String) {
-			return Boolean.parseBoolean((String) o);
-		} else {
-			throw new IllegalArgumentException("The property " + key + " cannot be converted to a boolean");
-		}
-	}
-
-	protected int toInt(Map<String, Object> props, String key, int defaultValue) {
-		
-		Object o =  ofNullable(props)
-				.map(m -> m.get(key))
-				.orElse(defaultValue);
-		
-		if (o instanceof Number) {
-			return ((Number) o).intValue();
-		} else if(o instanceof String) {
-			return Integer.parseInt((String) o);
-		} else {
-			throw new IllegalArgumentException("The property " + key + " cannot be converted to an int");
-		}
-	}
-
-	private long toLong(Map<String, Object> props, String key, long defaultValue) {
-		
-		Object o =  ofNullable(props)
-				.map(m -> m.get(key))
-				.orElse(defaultValue);
-		
-		if (o instanceof Number) {
-			return ((Number) o).longValue();
-		} else if(o instanceof String) {
-			return Long.parseLong((String) o);
-		} else {
-			throw new IllegalArgumentException("The property " + key + " cannot be converted to a long");
-		}
-	}
-
 }
\ No newline at end of file
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/JPADataSourceHelper.java b/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/JPADataSourceHelper.java
new file mode 100644
index 0000000..d5e335b
--- /dev/null
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-common/src/main/java/org/apache/aries/tx/control/jpa/common/impl/JPADataSourceHelper.java
@@ -0,0 +1,94 @@
+package org.apache.aries.tx.control.jpa.common.impl;
+
+import static java.util.Optional.ofNullable;
+import static java.util.concurrent.TimeUnit.HOURS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.CONNECTION_LIFETIME;
+import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.CONNECTION_POOLING_ENABLED;
+import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.CONNECTION_TIMEOUT;
+import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.IDLE_TIMEOUT;
+import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.MAX_CONNECTIONS;
+import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.MIN_CONNECTIONS;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import javax.sql.DataSource;
+
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+
+public class JPADataSourceHelper {
+	
+	public static final String CONNECTION_TEST_QUERY = "aries.connection.test.query";
+	
+	public static DataSource poolIfNecessary(Map<String, Object> resourceProviderProperties, DataSource unpooled) {
+		DataSource toUse;
+
+		if (toBoolean(resourceProviderProperties, CONNECTION_POOLING_ENABLED, true)) {
+			HikariConfig hcfg = new HikariConfig();
+			hcfg.setDataSource(unpooled);
+
+			// Sizes
+			hcfg.setMaximumPoolSize(toInt(resourceProviderProperties, MAX_CONNECTIONS, 10));
+			hcfg.setMinimumIdle(toInt(resourceProviderProperties, MIN_CONNECTIONS, 10));
+
+			// Timeouts
+			hcfg.setConnectionTimeout(toLong(resourceProviderProperties, CONNECTION_TIMEOUT, SECONDS.toMillis(30)));
+			hcfg.setIdleTimeout(toLong(resourceProviderProperties, IDLE_TIMEOUT, TimeUnit.MINUTES.toMillis(3)));
+			hcfg.setMaxLifetime(toLong(resourceProviderProperties, CONNECTION_LIFETIME, HOURS.toMillis(3)));
+	
+			hcfg.setConnectionTestQuery((String)resourceProviderProperties.get(CONNECTION_TEST_QUERY));
+			
+			toUse = new HikariDataSource(hcfg);
+
+		} else {
+			toUse = unpooled;
+		}
+		return toUse;
+	}
+
+	public static boolean toBoolean(Map<String, Object> props, String key, boolean defaultValue) {
+		Object o =  ofNullable(props)
+			.map(m -> m.get(key))
+			.orElse(defaultValue);
+		
+		if (o instanceof Boolean) {
+			return ((Boolean) o).booleanValue();
+		} else if(o instanceof String) {
+			return Boolean.parseBoolean((String) o);
+		} else {
+			throw new IllegalArgumentException("The property " + key + " cannot be converted to a boolean");
+		}
+	}
+
+	public static int toInt(Map<String, Object> props, String key, int defaultValue) {
+		
+		Object o =  ofNullable(props)
+				.map(m -> m.get(key))
+				.orElse(defaultValue);
+		
+		if (o instanceof Number) {
+			return ((Number) o).intValue();
+		} else if(o instanceof String) {
+			return Integer.parseInt((String) o);
+		} else {
+			throw new IllegalArgumentException("The property " + key + " cannot be converted to an int");
+		}
+	}
+
+	public static long toLong(Map<String, Object> props, String key, long defaultValue) {
+		
+		Object o =  ofNullable(props)
+				.map(m -> m.get(key))
+				.orElse(defaultValue);
+		
+		if (o instanceof Number) {
+			return ((Number) o).longValue();
+		} else if(o instanceof String) {
+			return Long.parseLong((String) o);
+		} else {
+			throw new IllegalArgumentException("The property " + key + " cannot be converted to a long");
+		}
+	}
+}
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderFactoryImpl.java b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderFactoryImpl.java
index fd5f4aa..4f6673a 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderFactoryImpl.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/JPAEntityManagerProviderFactoryImpl.java
@@ -23,16 +23,21 @@
 import static org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory.LOCAL_ENLISTMENT_ENABLED;
 import static org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory.XA_ENLISTMENT_ENABLED;
 
+import java.util.HashMap;
 import java.util.Map;
 
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.spi.PersistenceUnitTransactionType;
+import javax.sql.DataSource;
 
 import org.apache.aries.tx.control.jpa.common.impl.AbstractJPAEntityManagerProvider;
 import org.apache.aries.tx.control.jpa.common.impl.InternalJPAEntityManagerProviderFactory;
+import org.apache.aries.tx.control.jpa.common.impl.JPADataSourceHelper;
 import org.osgi.service.jpa.EntityManagerFactoryBuilder;
 import org.osgi.service.transaction.control.TransactionException;
 
+import com.zaxxer.hikari.HikariDataSource;
+
 public class JPAEntityManagerProviderFactoryImpl implements InternalJPAEntityManagerProviderFactory {
 
 	@Override
@@ -40,11 +45,38 @@
 			Map<String, Object> resourceProviderProperties) {
 		checkEnlistment(resourceProviderProperties);
 		
-		EntityManagerFactory emf = emfb.createEntityManagerFactory(jpaProperties);
+		Object found = jpaProperties.get("javax.persistence.dataSource");
+		
+		if(found == null) {
+			found = jpaProperties.get("javax.persistence.nonJtaDataSource");
+		}
+		
+		if(found == null) {
+			throw new IllegalArgumentException("No datasource was found when checking the javax.persistence.dataSource and javax.persistence.nonJtaDataSource.");
+		}
+		
+		DataSource unpooled;
+		if(found instanceof DataSource) {
+			unpooled = (DataSource) found;
+		} else {
+			throw new IllegalArgumentException("The object found when checking the javax.persistence.dataSource and javax.persistence.nonJtaDataSource properties was not a DataSource.");
+		}
+		
+		Map<String, Object> jpaPropsToUse = new HashMap<>(jpaProperties);
+		DataSource toUse = JPADataSourceHelper.poolIfNecessary(resourceProviderProperties, unpooled);
+		jpaPropsToUse.put("javax.persistence.dataSource", toUse);
+		jpaPropsToUse.put("javax.persistence.nonJtaDataSource", toUse);
+		
+		EntityManagerFactory emf = emfb.createEntityManagerFactory(jpaPropsToUse);
 		
 		validateEMF(emf);
 		
-		return new JPAEntityManagerProviderImpl(emf, () -> emf.close());
+		return new JPAEntityManagerProviderImpl(emf, () -> {
+				emf.close();
+				if (toUse instanceof HikariDataSource) {
+					((HikariDataSource)toUse).close();
+				}
+			});
 	}
 
 	public AbstractJPAEntityManagerProvider getProviderFor(EntityManagerFactoryBuilder emfb, 
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/LocalJPADataSourceSetup.java b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/LocalJPADataSourceSetup.java
index 94d8956..c77f38b 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/LocalJPADataSourceSetup.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-local/src/main/java/org/apache/aries/tx/control/jpa/local/impl/LocalJPADataSourceSetup.java
@@ -18,6 +18,8 @@
  */
 package org.apache.aries.tx.control.jpa.local.impl;
 
+import static org.apache.aries.tx.control.jpa.common.impl.JPADataSourceHelper.poolIfNecessary;
+import static org.apache.aries.tx.control.jpa.common.impl.JPADataSourceHelper.toBoolean;
 import static org.osgi.service.jdbc.DataSourceFactory.JDBC_URL;
 import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.USE_DRIVER;
 
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-parent/pom.xml b/tx-control-providers/jpa/tx-control-provider-jpa-parent/pom.xml
index e326b28..e6633a4 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-parent/pom.xml
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-parent/pom.xml
@@ -54,7 +54,7 @@
 			<dependency>
 				<groupId>org.osgi</groupId>
 				<artifactId>org.osgi.service.jpa</artifactId>
-				<version>1.0.0</version>
+				<version>1.1.0-SNAPSHOT</version>
 				<scope>provided</scope>
 			</dependency>
             <dependency>
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/Activator.java b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/Activator.java
index 6146843..9686e7f 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/Activator.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/Activator.java
@@ -36,7 +36,7 @@
 	protected ResourceProviderFactoryServiceFactory<AbstractJPAEntityManagerProvider, ResourceTrackingJPAEntityManagerProviderFactory> getServiceFactory(
 			BundleContext context) {
 		
-		InternalJPAEntityManagerProviderFactory ijempf = new JPAEntityManagerProviderFactoryImpl();
+		InternalJPAEntityManagerProviderFactory ijempf = new JPAEntityManagerProviderFactoryImpl(context);
 		return new ResourceProviderFactoryServiceFactory<AbstractJPAEntityManagerProvider, ResourceTrackingJPAEntityManagerProviderFactory>() {
 			@Override
 			protected TrackingResourceProviderFactory<AbstractJPAEntityManagerProvider> getTrackingResourceManagerProviderFactory() {
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java
index 25ddb28..c4ce8f9 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java
@@ -20,42 +20,173 @@
 
 import static java.util.Optional.ofNullable;
 import static javax.persistence.spi.PersistenceUnitTransactionType.JTA;
+import static org.apache.aries.tx.control.jpa.xa.impl.XAJPADataSourceSetup.JTA_DATA_SOURCE;
+import static org.apache.aries.tx.control.jpa.xa.impl.XAJPADataSourceSetup.NON_JTA_DATA_SOURCE;
 import static org.osgi.service.transaction.control.TransactionStatus.NO_TRANSACTION;
 import static org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory.LOCAL_ENLISTMENT_ENABLED;
 import static org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory.PRE_ENLISTED_DB_CONNECTION;
 import static org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory.XA_ENLISTMENT_ENABLED;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintWriter;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
+import java.sql.Wrapper;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.Callable;
-import java.util.logging.Logger;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
 
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.spi.PersistenceUnitTransactionType;
 import javax.sql.DataSource;
+import javax.sql.XADataSource;
 import javax.transaction.xa.XAResource;
 
 import org.apache.aries.tx.control.jdbc.common.impl.ScopedConnectionWrapper;
 import org.apache.aries.tx.control.jdbc.common.impl.TxConnectionWrapper;
 import org.apache.aries.tx.control.jdbc.xa.connection.impl.XAConnectionWrapper;
+import org.apache.aries.tx.control.jdbc.xa.connection.impl.XADataSourceMapper;
 import org.apache.aries.tx.control.jpa.common.impl.AbstractJPAEntityManagerProvider;
 import org.apache.aries.tx.control.jpa.common.impl.InternalJPAEntityManagerProviderFactory;
+import org.apache.aries.tx.control.jpa.common.impl.JPADataSourceHelper;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
 import org.osgi.service.jpa.EntityManagerFactoryBuilder;
 import org.osgi.service.transaction.control.TransactionContext;
 import org.osgi.service.transaction.control.TransactionControl;
 import org.osgi.service.transaction.control.TransactionException;
+import org.osgi.service.transaction.control.jdbc.JDBCConnectionProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.zaxxer.hikari.HikariDataSource;
 
 public class JPAEntityManagerProviderFactoryImpl implements InternalJPAEntityManagerProviderFactory {
 
+	private static final String TRANSACTION_TYPE = "javax.persistence.transactionType";
+	private static final Logger LOGGER = LoggerFactory.getLogger(JPAEntityManagerProviderFactoryImpl.class);
+	private final BundleContext context;
+	
+	public JPAEntityManagerProviderFactoryImpl(BundleContext context) {
+		this.context = context;
+	}
+
 	@Override
 	public AbstractJPAEntityManagerProvider getProviderFor(EntityManagerFactoryBuilder emfb, Map<String, Object> jpaProperties,
 			Map<String, Object> resourceProviderProperties) {
-		return new DelayedJPAEntityManagerProvider(tx -> getProviderFor(emfb, jpaProperties, resourceProviderProperties, tx, null));
+		
+		Map<String, Object> jpaPropsToUse = new HashMap<>(jpaProperties);
+		jpaPropsToUse.put(TRANSACTION_TYPE, JTA.name());
+		
+		Function<ThreadLocal<TransactionControl>, AbstractJPAEntityManagerProvider> create;
+		if(jpaProperties.containsKey("osgi.jdbc.provider")) {
+			create = handleJDBCResourceProvider(emfb, resourceProviderProperties, jpaPropsToUse);			
+		} else if(toBoolean(jpaPropsToUse, PRE_ENLISTED_DB_CONNECTION, false)) {
+			create = handlePreEnlistedConnection(emfb, resourceProviderProperties, jpaPropsToUse);
+		} else {
+			create = handleNormalDataSource(emfb, resourceProviderProperties, jpaPropsToUse);
+		}
+			
+		return new DelayedJPAEntityManagerProvider(create);
+	}
+
+	private Function<ThreadLocal<TransactionControl>, AbstractJPAEntityManagerProvider> handleJDBCResourceProvider(
+			EntityManagerFactoryBuilder emfb, Map<String, Object> resourceProviderProperties,
+			Map<String, Object> jpaPropsToUse) {
+		Function<ThreadLocal<TransactionControl>, AbstractJPAEntityManagerProvider> create;
+		JDBCConnectionProvider provider = (JDBCConnectionProvider) jpaPropsToUse.get("osgi.jdbc.provider");
+		
+		create = tx -> {
+				jpaPropsToUse.put(JTA_DATA_SOURCE, 
+					new ScopedConnectionDataSource(provider.getResource(tx.get())));
+				jpaPropsToUse.put(PRE_ENLISTED_DB_CONNECTION, Boolean.TRUE);
+				
+				return getProviderFor(emfb, jpaPropsToUse, resourceProviderProperties, tx, null); 
+			};
+		return create;
+	}
+
+	private Function<ThreadLocal<TransactionControl>, AbstractJPAEntityManagerProvider> handlePreEnlistedConnection(
+			EntityManagerFactoryBuilder emfb, Map<String, Object> resourceProviderProperties,
+			Map<String, Object> jpaPropsToUse) {
+		Function<ThreadLocal<TransactionControl>, AbstractJPAEntityManagerProvider> create;
+		Object supplied = jpaPropsToUse.get(JTA_DATA_SOURCE);
+		if(supplied == null) {
+			LOGGER.error("No datasource supplied in the configuration");
+			throw new IllegalArgumentException("No pre-enlisted datasource could be found to create the EntityManagerFactory. Please provide either a javax.persistence.jtaDataSource");
+		}
+		create = tx -> {
+			DataSource toUse = JPADataSourceHelper.poolIfNecessary(resourceProviderProperties, (DataSource) supplied);
+			jpaPropsToUse.put(JTA_DATA_SOURCE, toUse);
+			return getProviderFor(emfb, jpaPropsToUse, resourceProviderProperties, tx, () -> {
+					if (toUse instanceof HikariDataSource) {
+						((HikariDataSource)toUse).close();
+					}
+				});
+		};
+		return create;
+	}
+
+	private Function<ThreadLocal<TransactionControl>, AbstractJPAEntityManagerProvider> handleNormalDataSource(
+			EntityManagerFactoryBuilder emfb, Map<String, Object> resourceProviderProperties,
+			Map<String, Object> jpaPropsToUse) {
+		Function<ThreadLocal<TransactionControl>, AbstractJPAEntityManagerProvider> create;
+		Object supplied = jpaPropsToUse.get(JTA_DATA_SOURCE);
+		if(supplied == null) {
+			supplied = jpaPropsToUse.get("javax.persistence.dataSource");
+		}
+		if(supplied == null) {
+			supplied = jpaPropsToUse.get(NON_JTA_DATA_SOURCE);
+		}
+
+		if(supplied == null) {
+			LOGGER.error("No datasource supplied in the configuration");
+			throw new IllegalArgumentException("No datasource could be found to create the EntityManagerFactory. Please provide either a javax.persistence.jtaDataSource, a javax.persistence.nonJtaDataSource, or a javax.persistence.dataSource");
+		}
+		
+		DataSource ds;
+		
+		try {
+			if (supplied instanceof XADataSource) {
+				ds = new XADataSourceMapper((XADataSource)supplied);
+			} else if (supplied instanceof Wrapper && ((Wrapper)supplied).isWrapperFor(XADataSource.class)) {
+				ds = new XADataSourceMapper(((Wrapper)supplied).unwrap(XADataSource.class));
+			} else {
+				LOGGER.error("The datasource supplied was not XA capable");
+				throw new IllegalArgumentException("The datasource supplied to create the EntityManagerFactory is not an XADataSource and so cannot be enlisted. Please provide either a javax.persistence.jtaDataSource, a javax.persistence.nonJtaDataSource, or a javax.persistence.dataSource which implements XADataSource");
+			}
+		} catch (SQLException sqle) {
+			LOGGER.error("Unable to obtain an XA DataSource for the JPAEntityManagerProvider", sqle);
+			throw new IllegalArgumentException("The supplied DataSource could not be enlisted with XA transactions", sqle);
+		}
+
+		
+		create = tx -> {
+			DataSource toUse = JPADataSourceHelper.poolIfNecessary(resourceProviderProperties, ds);
+			jpaPropsToUse.put(JTA_DATA_SOURCE, toUse);
+			Object o = jpaPropsToUse.get(NON_JTA_DATA_SOURCE);
+			if(o == null) {
+				jpaPropsToUse.put(NON_JTA_DATA_SOURCE, toUse);
+			} else if (o instanceof DataSource) {
+				jpaPropsToUse.put(NON_JTA_DATA_SOURCE, JPADataSourceHelper
+						.poolIfNecessary(resourceProviderProperties, (DataSource) o));
+			}
+			return getProviderFor(emfb, jpaPropsToUse, resourceProviderProperties, tx, () -> {
+					if (toUse instanceof HikariDataSource) {
+						((HikariDataSource)toUse).close();
+					}
+				});
+		};
+		return create;
 	}
 
 	public AbstractJPAEntityManagerProvider getProviderFor(EntityManagerFactoryBuilder emfb, Map<String, Object> jpaProperties,
@@ -66,23 +197,157 @@
 		} else {
 			toUse = jpaProperties;
 		}
+		
+		setupTransactionManager(context, toUse, localStore, emfb);
+		
 		return localStore.get().notSupported(() -> internalBuilderCreate(emfb, toUse, localStore, onClose));
 	}
 
+	private boolean checkEnlistment(Map<String, Object> resourceProviderProperties) {
+		if (toBoolean(resourceProviderProperties, LOCAL_ENLISTMENT_ENABLED, false)) {
+			throw new TransactionException("This Resource Provider does not support Local transactions");
+		} else if (!toBoolean(resourceProviderProperties, XA_ENLISTMENT_ENABLED, true)) {
+			throw new TransactionException(
+					"This Resource Provider always enlists in XA transactions as it does not support local transactions");
+		}
+		
+		return !toBoolean(resourceProviderProperties, PRE_ENLISTED_DB_CONNECTION, false);
+	}
+
 	private Map<String, Object> enlistDataSource(ThreadLocal<TransactionControl> tx, Map<String, Object> jpaProperties) {
 		Map<String, Object> toReturn = new HashMap<>(jpaProperties);
 		
-		DataSource ds = (DataSource) jpaProperties.get("javax.persistence.jtaDataSource");
-
-		if(!jpaProperties.containsKey("javax.persistence.nonJtaDataSource")) {
-			toReturn.put("javax.persistence.nonJtaDataSource", ds);
-		}
+		DataSource enlistedDS = new EnlistingDataSource(tx, 
+				(DataSource)jpaProperties.get(JTA_DATA_SOURCE));
 		
-		toReturn.put("javax.persistence.jtaDataSource", new EnlistingDataSource(tx, ds));
+		toReturn.put(JTA_DATA_SOURCE, enlistedDS);
 		
 		return toReturn;
 	}
 
+	private void setupTransactionManager(BundleContext context, Map<String, Object> props, 
+			ThreadLocal<TransactionControl> t, EntityManagerFactoryBuilder builder) {
+		String provider = builder.getPersistenceProviderName();
+		Bundle providerBundle = builder.getPersistenceProviderBundle();
+		
+		if(providerBundle == null) {
+			LOGGER.warn("Unable to find a Persistence Provider for the provider named {}, so no XA plugin can be registered. XA transactions are unlikely to function properly.", provider);
+			return;
+		}
+	
+		Bundle txControlProviderBundle = context.getBundle();
+		
+		try {
+			if("org.hibernate.jpa.HibernatePersistenceProvider".equals(provider)) {
+				
+				if(props.containsKey("hibernate.transaction.coordinator_class")) {
+					LOGGER.warn("The JPA configuration properties already define a Hibernate transaction coordinator. This resource provider will not install its own plugin.");
+					return;
+				}
+				
+				String pluginClass;
+				
+				Bundle toUse = findSource(providerBundle, "org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder");
+				
+				if(toUse != null) {
+					
+					try {
+						toUse.loadClass("org.hibernate.resource.transaction.spi.DdlTransactionIsolator");
+						LOGGER.debug("Detected Hibernate 5.2.2 or above when attempting to install the XA plugin.");
+						pluginClass = "org.apache.aries.tx.control.jpa.xa.plugin.hibernate.impl.Hibernate522TxControlPlatform";
+					} catch (Exception e) {
+						LOGGER.debug("Detected Hibernate 5.2.0 or 5.2.1 when attempting to install the XA plugin.");
+						pluginClass = "org.apache.aries.tx.control.jpa.xa.plugin.hibernate.impl.Hibernate520TxControlPlatform";
+					}
+				} else {
+					toUse = findSource(providerBundle, "org.hibernate.resource.transaction.TransactionCoordinatorBuilder");
+					if(toUse != null) {
+						LOGGER.debug("Detected Hibernate 5.0.x or 5.1.x or above when attempting to install the XA plugin.");
+						pluginClass = "org.apache.aries.tx.control.jpa.xa.plugin.hibernate.impl.HibernateTxControlPlatform";
+					} else {
+						LOGGER.warn("Detected a Hibernate provider, but we were unable to load an appropriate XA plugin");
+						return;
+					}
+				}
+				
+				ClassLoader pluginLoader = getPluginLoader(toUse, txControlProviderBundle);
+				
+				Class<?> pluginClazz = pluginLoader.loadClass(pluginClass);
+				Object plugin = pluginClazz.getConstructor(ThreadLocal.class)
+					.newInstance(t);
+				
+				props.put("hibernate.transaction.coordinator_class", plugin);
+				
+			} else if("org.apache.openjpa.persistence.PersistenceProviderImpl".equals(provider)) {
+				
+				if(props.containsKey("openjpa.ManagedRuntime")) {
+					LOGGER.warn("The JPA configuration properties already define an OpenJPA transaction runtime. This resource provider will not install its own plugin.");
+					return;
+				}
+				
+				ClassLoader pluginLoader = getPluginLoader(providerBundle, txControlProviderBundle);
+					
+				Class<?> pluginClazz = pluginLoader.loadClass("org.apache.aries.tx.control.jpa.xa.plugin.openjpa.impl.OpenJPATxControlPlatform");
+				Object plugin = pluginClazz.getConstructor(ThreadLocal.class)
+						.newInstance(t);
+					
+				props.put("openjpa.ManagedRuntime", plugin);
+				props.put("openjpa.ConnectionFactoryMode", "managed");
+				props.put("openjpa.TransactionMode", "managed");
+					
+			} else if("org.eclipse.persistence.jpa.PersistenceProvider".equals(provider)) {
+				
+				if(props.containsKey("eclipselink.target-server")) {
+					LOGGER.warn("The JPA configuration properties already define an EclipseLink transaction target. This resource provider will not install its own plugin.");
+					return;
+				}
+				
+				ClassLoader pluginLoader = getPluginLoader(providerBundle, txControlProviderBundle);
+				
+				Class<?> pluginClazz = pluginLoader.loadClass("org.apache.aries.tx.control.jpa.xa.plugin.eclipse.impl.EclipseTxControlPlatform");
+				
+				pluginClazz.getMethod("setTransactionControl", ThreadLocal.class)
+						.invoke(null, t);
+				
+				props.put("eclipselink.target-server", pluginClazz.getName());
+				props.put("org.apache.aries.jpa.eclipselink.plugin.types", pluginClazz);
+				// This is needed to ensure that sequences can be generated in nested
+				// transactions without blowing up.
+				if(!props.containsKey("eclipselink.jdbc.sequence-connection-pool")) {
+					props.put("eclipselink.jdbc.sequence-connection-pool", "true");
+				}
+				
+			} else {
+				LOGGER.warn("The persistence provider {} is not recognised, so no adapter plugin can be registered with it. XA transactions are unlikely to work properly", provider);
+				return;
+			} 
+		} catch (Exception e) {
+			LOGGER.error("There was a problem trying to install a transaction integration plugin for the JPA provider {}.", provider, e);
+		}
+	}
+
+	private Bundle findSource(Bundle providerBundle, String toFind) {
+		try{
+			providerBundle.loadClass(toFind);
+			return providerBundle;
+		} catch (Exception e) {
+			BundleWiring wiring = providerBundle.adapt(BundleWiring.class);
+			return wiring.getRequiredWires("osgi.wiring.package").stream()
+						.filter(bw -> "org.hibernate".equals(bw.getCapability().getAttributes().get("osgi.wiring.package")))
+						.map(BundleWire::getProviderWiring)
+						.map(BundleWiring::getBundle)
+						.findFirst()
+						.filter(b -> {
+								try {
+									b.loadClass(toFind);
+									return true;
+								} catch (Exception e2) {
+									return false;
+								}
+							}).orElse(null);
+		}
+	}
+
 	private AbstractJPAEntityManagerProvider internalBuilderCreate(EntityManagerFactoryBuilder emfb,
 			Map<String, Object> jpaProperties, ThreadLocal<TransactionControl> tx, Runnable onClose) {
 		EntityManagerFactory emf = emfb.createEntityManagerFactory(jpaProperties);
@@ -101,7 +366,7 @@
 	}
 
 	private void validateEMF(EntityManagerFactory emf) {
-		Object o = emf.getProperties().get("javax.persistence.transactionType");
+		Object o = emf.getProperties().get(TRANSACTION_TYPE);
 		
 		PersistenceUnitTransactionType tranType;
 		if(o instanceof PersistenceUnitTransactionType) {
@@ -114,7 +379,7 @@
 		}
 		
 		if(JTA != tranType) {
-			throw new IllegalArgumentException("The supplied EntityManagerFactory is not declared RESOURCE_LOCAL");
+			throw new IllegalArgumentException("The supplied EntityManagerFactory is not declared JTA");
 		}
 	}
 
@@ -127,17 +392,6 @@
 		return new JPAEntityManagerProviderImpl(emf, new ThreadLocal<>(), null);
 	}
 
-	private boolean checkEnlistment(Map<String, Object> resourceProviderProperties) {
-		if (toBoolean(resourceProviderProperties, LOCAL_ENLISTMENT_ENABLED, false)) {
-			throw new TransactionException("This Resource Provider does not support Local transactions");
-		} else if (!toBoolean(resourceProviderProperties, XA_ENLISTMENT_ENABLED, true)) {
-			throw new TransactionException(
-					"This Resource Provider always enlists in XA transactions as it does not support local transactions");
-		}
-		
-		return !toBoolean(resourceProviderProperties, PRE_ENLISTED_DB_CONNECTION, false);
-	}
-	
 	public static boolean toBoolean(Map<String, Object> props, String key, boolean defaultValue) {
 		Object o =  ofNullable(props)
 			.map(m -> m.get(key))
@@ -152,6 +406,50 @@
 		}
 	}
 	
+	private ClassLoader getPluginLoader(Bundle providerBundle, Bundle txControlProviderBundle) {
+		return new ClassLoader() {
+
+			ConcurrentMap<String, Class<?>> loaded = new ConcurrentHashMap<>();
+			
+			@Override
+			public Class<?> loadClass(String name) throws ClassNotFoundException {
+				if(name.startsWith("org.apache.aries.tx.control.jpa.xa.plugin")) {
+					
+					Class<?> c = loaded.get(name);
+					
+					if(c != null) {
+						return c;
+					}
+					
+					String resource = name.replace('.', '/') + ".class";
+					
+					try (InputStream is = txControlProviderBundle.getResource(resource).openStream()) {
+						ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
+						byte[] b = new byte[4096];
+						int read;
+						while ((read = is.read(b)) != -1) {
+							baos.write(b, 0, read);
+						}
+						byte[] clazzBytes = baos.toByteArray();
+						c = defineClass(name, clazzBytes, 0, clazzBytes.length, 
+								XAJPAEMFLocator.class.getProtectionDomain());
+						loaded.putIfAbsent(name, c);
+						return c;
+					} catch (IOException e) {
+						throw new ClassNotFoundException("Unable to load class " + name, e);
+					}
+				}
+				
+				if(name.startsWith("org.apache.aries.tx.control") ||
+				   name.startsWith("org.osgi.service.transaction.control") ||
+						name.startsWith("org.slf4j")) {
+					return txControlProviderBundle.loadClass(name);
+				}
+				return providerBundle.loadClass(name);
+			}
+		};
+	}
+	
 	public static class EnlistingDataSource implements DataSource {
 		
 		private final DataSource delegate;
@@ -205,7 +503,7 @@
 			return delegate.getLoginTimeout();
 		}
 
-		public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+		public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
 			return delegate.getParentLogger();
 		}
 		
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/ScopedConnectionDataSource.java b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/ScopedConnectionDataSource.java
new file mode 100644
index 0000000..11fcfa5
--- /dev/null
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/ScopedConnectionDataSource.java
@@ -0,0 +1,70 @@
+package org.apache.aries.tx.control.jpa.xa.impl;
+
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.logging.Logger;
+
+import javax.sql.DataSource;
+
+public class ScopedConnectionDataSource implements DataSource {
+
+	private final Connection scoped;
+	
+	public ScopedConnectionDataSource(Connection scoped) {
+		this.scoped = scoped;
+	}
+
+	@Override
+	public PrintWriter getLogWriter() throws SQLException {
+		return null;
+	}
+
+	@Override
+	public void setLogWriter(PrintWriter out) throws SQLException {
+		// A no-op
+
+	}
+
+	@Override
+	public void setLoginTimeout(int seconds) throws SQLException {
+		// A no-op
+	}
+
+	@Override
+	public int getLoginTimeout() throws SQLException {
+		return 0;
+	}
+
+	@Override
+	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+		return Logger.getGlobal();
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public <T> T unwrap(Class<T> iface) throws SQLException {
+		if (iface.isInstance(scoped)) {
+			return (T) scoped;
+		} else {
+			return scoped.unwrap(iface);
+		}
+	}
+
+	@Override
+	public boolean isWrapperFor(Class<?> iface) throws SQLException {
+		return iface.isInstance(scoped) || scoped.isWrapperFor(iface);
+	}
+
+	@Override
+	public Connection getConnection() throws SQLException {
+		return scoped;
+	}
+
+	@Override
+	public Connection getConnection(String username, String password) throws SQLException {
+		return scoped;
+	}
+
+}
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XAJPADataSourceSetup.java b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XAJPADataSourceSetup.java
index 876c0bc..e6cb6cf 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XAJPADataSourceSetup.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XAJPADataSourceSetup.java
@@ -18,6 +18,8 @@
  */
 package org.apache.aries.tx.control.jpa.xa.impl;
 
+import static org.apache.aries.tx.control.jpa.common.impl.JPADataSourceHelper.poolIfNecessary;
+import static org.apache.aries.tx.control.jpa.common.impl.JPADataSourceHelper.toBoolean;
 import static org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory.USE_DRIVER;
 
 import java.sql.SQLException;
@@ -39,7 +41,8 @@
 
 public class XAJPADataSourceSetup extends AbstractManagedJPADataSourceSetup {
 
-	private static final String JAVAX_PERSISTENCE_NON_JTA_DATA_SOURCE = "javax.persistence.nonJtaDataSource";
+	static final String JTA_DATA_SOURCE = "javax.persistence.jtaDataSource";
+	static final String NON_JTA_DATA_SOURCE = "javax.persistence.nonJtaDataSource";
 	
 	public XAJPADataSourceSetup(BundleContext context, String pid, Properties jdbcProperties,
 			Map<String, Object> baseJPAProperties, Map<String, Object> providerProperties) throws InvalidSyntaxException, ConfigurationException {
@@ -62,14 +65,15 @@
 
 		DataSource toUse = poolIfNecessary(providerProperties, unpooled);
 		
-		jpaProperties.put("javax.persistence.jtaDataSource", toUse);
+		jpaProperties.put(JTA_DATA_SOURCE, toUse);
+		jpaProperties.put(NON_JTA_DATA_SOURCE, toUse);
 		
 		return jpaProperties;
 	}
 
 	@Override
 	protected void cleanupOnClose(Map<String, Object> jpaProperties) {
-		Object o = jpaProperties.get(JAVAX_PERSISTENCE_NON_JTA_DATA_SOURCE);
+		Object o = jpaProperties.get(NON_JTA_DATA_SOURCE);
 		if (o instanceof HikariDataSource) {
 			((HikariDataSource)o).close();
 		}
diff --git a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XAJPAEMFLocator.java b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XAJPAEMFLocator.java
index a8bbb6b..4b1a1b5 100644
--- a/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XAJPAEMFLocator.java
+++ b/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XAJPAEMFLocator.java
@@ -18,36 +18,19 @@
  */
 package org.apache.aries.tx.control.jpa.xa.impl;
 
-import static org.osgi.service.jpa.EntityManagerFactoryBuilder.JPA_UNIT_PROVIDER;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import javax.persistence.spi.PersistenceProvider;
 
 import org.apache.aries.tx.control.jpa.common.impl.AbstractJPAEntityManagerProvider;
 import org.apache.aries.tx.control.jpa.common.impl.AbstractManagedJPAEMFLocator;
-import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.framework.wiring.BundleWire;
-import org.osgi.framework.wiring.BundleWiring;
 import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.jpa.EntityManagerFactoryBuilder;
-import org.osgi.service.transaction.control.TransactionControl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public class XAJPAEMFLocator extends AbstractManagedJPAEMFLocator {
 
-	private static final Logger LOGGER = LoggerFactory.getLogger(XAJPAEMFLocator.class);
-	
 	public XAJPAEMFLocator(BundleContext context, String pid, Map<String, Object> jpaProperties,
 			Map<String, Object> providerProperties, Runnable onClose) throws InvalidSyntaxException, ConfigurationException {
 		super(context, pid, jpaProperties, providerProperties, onClose);
@@ -57,183 +40,13 @@
 	protected AbstractJPAEntityManagerProvider getResourceProvider(BundleContext context,
 			EntityManagerFactoryBuilder service, ServiceReference<EntityManagerFactoryBuilder> reference,
 			Map<String, Object> jpaProperties, Map<String, Object> providerProperties, Runnable onClose) {
+		
+		Map<String, Object> jpaProps = new HashMap<String, Object>(jpaProperties);
+		Map<String, Object> providerProps = new HashMap<String, Object>(providerProperties);
+
 		return new DelayedJPAEntityManagerProvider(t -> {
-			
-			Map<String, Object> jpaProps = new HashMap<String, Object>(jpaProperties);
-			Map<String, Object> providerProps = new HashMap<String, Object>(providerProperties);
-			
-			setupTransactionManager(context, jpaProps, providerProps, t, reference);
-			
-			return new JPAEntityManagerProviderFactoryImpl().getProviderFor(service,
+			return new JPAEntityManagerProviderFactoryImpl(context).getProviderFor(service,
 					jpaProps, providerProps, t, onClose);
 		});
 	}
-
-	private void setupTransactionManager(BundleContext context, Map<String, Object> props, 
-			Map<String, Object> providerProps, ThreadLocal<TransactionControl> t, ServiceReference<EntityManagerFactoryBuilder> reference) {
-		String provider = (String) reference.getProperty(JPA_UNIT_PROVIDER);
-		
-		ServiceReference<PersistenceProvider> providerRef = getPersistenceProvider(provider, context);
-		
-		if(providerRef == null) {
-			LOGGER.warn("Unable to find a Persistence Provider for the provider named {}, so no XA plugin can be registered. XA transactions are unlikely to function properly.", provider);
-			return;
-		}
-
-		Bundle providerBundle = providerRef.getBundle();
-		Bundle txControlProviderBundle = context.getBundle();
-		
-		try {
-			if("org.hibernate.jpa.HibernatePersistenceProvider".equals(provider)) {
-				
-				String pluginClass;
-				
-				Bundle toUse = findSource(providerBundle, "org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder");
-				
-				if(toUse != null) {
-					
-					try {
-						toUse.loadClass("org.hibernate.resource.transaction.spi.DdlTransactionIsolator");
-						LOGGER.debug("Detected Hibernate 5.2.2 or above when attempting to install the XA plugin.");
-						pluginClass = "org.apache.aries.tx.control.jpa.xa.plugin.hibernate.impl.Hibernate522TxControlPlatform";
-					} catch (Exception e) {
-						LOGGER.debug("Detected Hibernate 5.2.0 or 5.2.1 when attempting to install the XA plugin.");
-						pluginClass = "org.apache.aries.tx.control.jpa.xa.plugin.hibernate.impl.Hibernate520TxControlPlatform";
-					}
-				} else {
-					toUse = findSource(providerBundle, "org.hibernate.resource.transaction.TransactionCoordinatorBuilder");
-					if(toUse != null) {
-						LOGGER.debug("Detected Hibernate 5.0.x or 5.1.x or above when attempting to install the XA plugin.");
-						pluginClass = "org.apache.aries.tx.control.jpa.xa.plugin.hibernate.impl.HibernateTxControlPlatform";
-					} else {
-						LOGGER.warn("Detected a Hibernate provider, but we were unable to load an appropriate XA plugin");
-						return;
-					}
-				}
-				
-				ClassLoader pluginLoader = getPluginLoader(toUse, txControlProviderBundle);
-				
-				Class<?> pluginClazz = pluginLoader.loadClass(pluginClass);
-				Object plugin = pluginClazz.getConstructor(ThreadLocal.class)
-					.newInstance(t);
-				
-				props.put("hibernate.transaction.coordinator_class", plugin);
-				
-			} else if("org.apache.openjpa.persistence.PersistenceProviderImpl".equals(provider)) {
-					
-				ClassLoader pluginLoader = getPluginLoader(providerBundle, txControlProviderBundle);
-					
-				Class<?> pluginClazz = pluginLoader.loadClass("org.apache.aries.tx.control.jpa.xa.plugin.openjpa.impl.OpenJPATxControlPlatform");
-				Object plugin = pluginClazz.getConstructor(ThreadLocal.class)
-						.newInstance(t);
-					
-				props.put("openjpa.ManagedRuntime", plugin);
-					
-			} else if("org.eclipse.persistence.jpa.PersistenceProvider".equals(provider)) {
-				
-				ClassLoader pluginLoader = getPluginLoader(providerBundle, txControlProviderBundle);
-				
-				Class<?> pluginClazz = pluginLoader.loadClass("org.apache.aries.tx.control.jpa.xa.plugin.eclipse.impl.EclipseTxControlPlatform");
-				
-				pluginClazz.getMethod("setTransactionControl", ThreadLocal.class)
-						.invoke(null, t);
-				
-				props.put("eclipselink.target-server", pluginClazz.getName());
-				props.put("org.apache.aries.jpa.eclipselink.plugin.types", pluginClazz);
-				// This is needed to ensure that sequences can be generated in nested
-				// transactions without blowing up.
-				if(!props.containsKey("eclipselink.jdbc.sequence-connection-pool")) {
-					props.put("eclipselink.jdbc.sequence-connection-pool", "true");
-				}
-				
-			} else {
-				LOGGER.warn("The persistence provider {} is not recognised, so no adapter plugin can be registered with it. XA transactions are unlikely to work properly", provider);
-				return;
-			} 
-		} catch (Exception e) {
-			//TODO log a warning and give up
-			e.printStackTrace();
-		}
-	}
-
-	private Bundle findSource(Bundle providerBundle, String toFind) {
-		try{
-			providerBundle.loadClass(toFind);
-			return providerBundle;
-		} catch (Exception e) {
-			BundleWiring wiring = providerBundle.adapt(BundleWiring.class);
-			return wiring.getRequiredWires("osgi.wiring.package").stream()
-						.filter(bw -> "org.hibernate".equals(bw.getCapability().getAttributes().get("osgi.wiring.package")))
-						.map(BundleWire::getProviderWiring)
-						.map(BundleWiring::getBundle)
-						.findFirst()
-						.filter(b -> {
-								try {
-									b.loadClass(toFind);
-									return true;
-								} catch (Exception e2) {
-									return false;
-								}
-							}).orElse(null);
-		}
-	}
-
-	private ClassLoader getPluginLoader(Bundle providerBundle, Bundle txControlProviderBundle) {
-		return new ClassLoader() {
-
-			ConcurrentMap<String, Class<?>> loaded = new ConcurrentHashMap<>();
-			
-			@Override
-			public Class<?> loadClass(String name) throws ClassNotFoundException {
-				if(name.startsWith("org.apache.aries.tx.control.jpa.xa.plugin")) {
-					
-					Class<?> c = loaded.get(name);
-					
-					if(c != null) {
-						return c;
-					}
-					
-					String resource = name.replace('.', '/') + ".class";
-					
-					try (InputStream is = txControlProviderBundle.getResource(resource).openStream()) {
-						ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
-						byte[] b = new byte[4096];
-						int read;
-						while ((read = is.read(b)) != -1) {
-							baos.write(b, 0, read);
-						}
-						byte[] clazzBytes = baos.toByteArray();
-						c = defineClass(name, clazzBytes, 0, clazzBytes.length, 
-								XAJPAEMFLocator.class.getProtectionDomain());
-						loaded.putIfAbsent(name, c);
-						return c;
-					} catch (IOException e) {
-						throw new ClassNotFoundException("Unable to load class " + name, e);
-					}
-				}
-				
-				if(name.startsWith("org.apache.aries.tx.control") ||
-				   name.startsWith("org.osgi.service.transaction.control") ||
-						name.startsWith("org.slf4j")) {
-					return txControlProviderBundle.loadClass(name);
-				}
-				return providerBundle.loadClass(name);
-			}
-		};
-	}
-
-	private ServiceReference<PersistenceProvider> getPersistenceProvider(String provider, BundleContext context) {
-		if(provider == null) {
-			return null;
-		}
-		try {
-			return context.getServiceReferences(PersistenceProvider.class, 
-							"(javax.persistence.provider=" + provider + ")").stream()
-								.findFirst()
-								.orElse(null);
-		} catch (InvalidSyntaxException e) {
-			//TODO log a warning
-			return null;
-		} 
-	}
 }
\ No newline at end of file