[ARIES-1689] added test to reproduce the problem

git-svn-id: https://svn.apache.org/repos/asf/aries/trunk/jpa@1785768 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/jpa-blueprint/src/test/java/org/apache/aries/jpa/blueprint/impl/BlueprintContainerStub.java b/jpa-blueprint/src/test/java/org/apache/aries/jpa/blueprint/impl/BlueprintContainerStub.java
new file mode 100644
index 0000000..85c20b5
--- /dev/null
+++ b/jpa-blueprint/src/test/java/org/apache/aries/jpa/blueprint/impl/BlueprintContainerStub.java
@@ -0,0 +1,51 @@
+package org.apache.aries.jpa.blueprint.impl;

+

+import java.util.Collection;

+import java.util.HashMap;

+import java.util.Map;

+import java.util.Set;

+

+import org.osgi.service.blueprint.container.BlueprintContainer;

+import org.osgi.service.blueprint.reflect.ComponentMetadata;

+

+public class BlueprintContainerStub implements BlueprintContainer {

+

+    private Map<String, Object> instances;

+

+    public BlueprintContainerStub() {

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

+        instances.put("coordinator", new CoordinatorStub());

+        instances.put("em", new EntityManagerStub());

+    }

+

+    @Override

+    public Set<String> getComponentIds() {

+        // TODO Auto-generated method stub

+        return null;

+    }

+

+    @Override

+    public Object getComponentInstance(String id) {

+        if ("em".equals(id)) {

+            try {

+                Thread.sleep(3000);

+            } catch (InterruptedException e) {

+                e.printStackTrace();

+            }

+        }

+        return instances.get(id);

+    }

+

+    @Override

+    public ComponentMetadata getComponentMetadata(String id) {

+        // TODO Auto-generated method stub

+        return null;

+    }

+

+    @Override

+    public <T extends ComponentMetadata> Collection<T> getMetadata(Class<T> type) {

+        // TODO Auto-generated method stub

+        return null;

+    }

+

+}

diff --git a/jpa-blueprint/src/test/java/org/apache/aries/jpa/blueprint/impl/CoordinatorStub.java b/jpa-blueprint/src/test/java/org/apache/aries/jpa/blueprint/impl/CoordinatorStub.java
new file mode 100644
index 0000000..fe7b40e
--- /dev/null
+++ b/jpa-blueprint/src/test/java/org/apache/aries/jpa/blueprint/impl/CoordinatorStub.java
@@ -0,0 +1,50 @@
+package org.apache.aries.jpa.blueprint.impl;

+

+import java.util.Collection;

+

+import org.osgi.service.coordinator.Coordination;

+import org.osgi.service.coordinator.Coordinator;

+import org.osgi.service.coordinator.Participant;

+

+public class CoordinatorStub implements Coordinator {

+

+    @Override

+    public Coordination create(String name, long timeMillis) {

+        return null;

+    }

+

+    @Override

+    public Coordination begin(String name, long timeMillis) {

+        return null;

+    }

+

+    @Override

+    public Coordination peek() {

+        return null;

+    }

+

+    @Override

+    public Coordination pop() {

+        return null;

+    }

+

+    @Override

+    public boolean fail(Throwable cause) {

+        return false;

+    }

+

+    @Override

+    public boolean addParticipant(Participant participant) {

+        return false;

+    }

+

+    @Override

+    public Collection<Coordination> getCoordinations() {

+        return null;

+    }

+

+    @Override

+    public Coordination getCoordination(long id) {

+        return null;

+    }

+}

diff --git a/jpa-blueprint/src/test/java/org/apache/aries/jpa/blueprint/impl/EntityManagerStub.java b/jpa-blueprint/src/test/java/org/apache/aries/jpa/blueprint/impl/EntityManagerStub.java
new file mode 100644
index 0000000..ce51a33
--- /dev/null
+++ b/jpa-blueprint/src/test/java/org/apache/aries/jpa/blueprint/impl/EntityManagerStub.java
@@ -0,0 +1,206 @@
+package org.apache.aries.jpa.blueprint.impl;

+

+import java.util.HashMap;

+import java.util.Map;

+

+import javax.persistence.EntityManager;

+import javax.persistence.EntityManagerFactory;

+import javax.persistence.EntityTransaction;

+import javax.persistence.FlushModeType;

+import javax.persistence.LockModeType;

+import javax.persistence.Query;

+import javax.persistence.TypedQuery;

+import javax.persistence.criteria.CriteriaBuilder;

+import javax.persistence.criteria.CriteriaQuery;

+import javax.persistence.metamodel.Metamodel;

+import javax.persistence.spi.PersistenceUnitTransactionType;

+

+public class EntityManagerStub implements EntityManager {

+

+    @Override

+    public void clear() {

+    }

+

+    @Override

+    public void close() {

+    }

+

+    @Override

+    public boolean contains(Object arg0) {

+        return false;

+    }

+

+    @Override

+    public Query createNamedQuery(String arg0) {

+        return null;

+    }

+

+    @Override

+    public <T> TypedQuery<T> createNamedQuery(String arg0, Class<T> arg1) {

+        return null;

+    }

+

+    @Override

+    public Query createNativeQuery(String arg0) {

+        return null;

+    }

+

+    @Override

+    public Query createNativeQuery(String arg0, Class arg1) {

+        return null;

+    }

+

+    @Override

+    public Query createNativeQuery(String arg0, String arg1) {

+        return null;

+    }

+

+    @Override

+    public Query createQuery(String arg0) {

+        return null;

+    }

+

+    @Override

+    public <T> TypedQuery<T> createQuery(CriteriaQuery<T> arg0) {

+        return null;

+    }

+

+    @Override

+    public <T> TypedQuery<T> createQuery(String arg0, Class<T> arg1) {

+        return null;

+    }

+

+    @Override

+    public void detach(Object arg0) {

+    }

+

+    @Override

+    public <T> T find(Class<T> arg0, Object arg1) {

+        return null;

+    }

+

+    @Override

+    public <T> T find(Class<T> arg0, Object arg1, Map<String, Object> arg2) {

+        return null;

+    }

+

+    @Override

+    public <T> T find(Class<T> arg0, Object arg1, LockModeType arg2) {

+        return null;

+    }

+

+    @Override

+    public <T> T find(Class<T> arg0, Object arg1, LockModeType arg2, Map<String, Object> arg3) {

+        return null;

+    }

+

+    @Override

+    public void flush() {

+    }

+

+    @Override

+    public CriteriaBuilder getCriteriaBuilder() {

+        return null;

+    }

+

+    @Override

+    public Object getDelegate() {

+        return null;

+    }

+

+    @Override

+    public EntityManagerFactory getEntityManagerFactory() {

+        return null;

+    }

+

+    @Override

+    public FlushModeType getFlushMode() {

+        return null;

+    }

+

+    @Override

+    public LockModeType getLockMode(Object arg0) {

+        return null;

+    }

+

+    @Override

+    public Metamodel getMetamodel() {

+        return null;

+    }

+

+    @Override

+    public Map<String, Object> getProperties() {

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

+        ret.put(PersistenceUnitTransactionType.class.getName(), PersistenceUnitTransactionType.JTA);

+        return ret;

+    }

+

+    @Override

+    public <T> T getReference(Class<T> arg0, Object arg1) {

+        return null;

+    }

+

+    @Override

+    public EntityTransaction getTransaction() {

+        return null;

+    }

+

+    @Override

+    public boolean isOpen() {

+        return false;

+    }

+

+    @Override

+    public void joinTransaction() {

+    }

+

+    @Override

+    public void lock(Object arg0, LockModeType arg1) {

+    }

+

+    @Override

+    public void lock(Object arg0, LockModeType arg1, Map<String, Object> arg2) {

+    }

+

+    @Override

+    public <T> T merge(T arg0) {

+        return null;

+    }

+

+    @Override

+    public void persist(Object arg0) {

+    }

+

+    @Override

+    public void refresh(Object arg0) {

+    }

+

+    @Override

+    public void refresh(Object arg0, Map<String, Object> arg1) {

+    }

+

+    @Override

+    public void refresh(Object arg0, LockModeType arg1) {

+    }

+

+    @Override

+    public void refresh(Object arg0, LockModeType arg1, Map<String, Object> arg2) {

+    }

+

+    @Override

+    public void remove(Object arg0) {

+    }

+

+    @Override

+    public void setFlushMode(FlushModeType arg0) {

+    }

+

+    @Override

+    public void setProperty(String arg0, Object arg1) {

+    }

+

+    @Override

+    public <T> T unwrap(Class<T> arg0) {

+        return null;

+    }

+}

diff --git a/jpa-blueprint/src/test/java/org/apache/aries/jpa/blueprint/impl/JpaInterceptorTest.java b/jpa-blueprint/src/test/java/org/apache/aries/jpa/blueprint/impl/JpaInterceptorTest.java
new file mode 100644
index 0000000..43f16de
--- /dev/null
+++ b/jpa-blueprint/src/test/java/org/apache/aries/jpa/blueprint/impl/JpaInterceptorTest.java
@@ -0,0 +1,70 @@
+package org.apache.aries.jpa.blueprint.impl;

+

+import java.lang.reflect.Method;

+import java.util.List;

+import java.util.concurrent.atomic.AtomicBoolean;

+

+import org.junit.Assert;

+import org.junit.Test;

+import org.osgi.service.blueprint.container.BlueprintContainer;

+import org.osgi.service.blueprint.reflect.ComponentMetadata;

+

+public class JpaInterceptorTest implements Runnable {

+    private JpaInterceptor interceptor;

+    private AtomicBoolean result = new AtomicBoolean(true);

+

+    @Test

+    public void testThreadSafePreCall() throws InterruptedException {

+        BlueprintContainer container = new BlueprintContainerStub();

+        interceptor = new JpaInterceptor(container, "coordinator", "em");

+

+        Thread t1 = new Thread(this);

+        Thread t2 = new Thread(this);

+

+        t1.start();

+        try {

+            Thread.sleep(1000);

+        } catch (InterruptedException e) {

+            e.printStackTrace();

+        }

+        t2.start();

+        synchronized (result) {

+            result.wait();

+        }

+        Assert.assertTrue(result.get());

+    }

+

+    @Override

+    public void run() {

+        ComponentMetadata cm = new ComponentMetadata() {

+

+            @Override

+            public String getId() {

+                return "testMetadata";

+            }

+

+            @Override

+            public List<String> getDependsOn() {

+                return null;

+            }

+

+            @Override

+            public int getActivation() {

+                return 0;

+            }

+        };

+        Method m;

+        try {

+            m = this.getClass().getMethod("run", null);

+            interceptor.preCall(cm, m, null);

+        } catch (Throwable e) {

+            synchronized (result) {

+                result.set(false);

+            }

+        } finally {

+            synchronized (result) {

+                result.notifyAll();

+            }

+        }

+    }

+}