blob: 8b73a5bf7e2e94a186783b076f466407bbfbfcf6 [file] [log] [blame]
package org.apache.aries.tx.control.jpa.common.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import javax.persistence.EntityManagerFactory;
import org.osgi.service.jpa.EntityManagerFactoryBuilder;
import org.osgi.service.transaction.control.jpa.JPAEntityManagerProvider;
import org.osgi.service.transaction.control.jpa.JPAEntityManagerProviderFactory;
class ResourceTrackingJPAEntityManagerProviderFactory implements
JPAEntityManagerProviderFactory {
private final List<AbstractJPAEntityManagerProvider> toClose = new ArrayList<>();
private final InternalJPAEntityManagerProviderFactory factory;
private boolean closed;
public ResourceTrackingJPAEntityManagerProviderFactory(InternalJPAEntityManagerProviderFactory factory) {
this.factory = factory;
}
@Override
public JPAEntityManagerProvider getProviderFor(EntityManagerFactoryBuilder emfb, Map<String, Object> jpaProperties,
Map<String, Object> resourceProviderProperties) {
return doGetResult(() -> factory.getProviderFor(emfb,
jpaProperties, resourceProviderProperties));
}
@Override
public JPAEntityManagerProvider getProviderFor(EntityManagerFactory emf, Map<String, Object> resourceProviderProperties) {
return doGetResult(() -> factory.getProviderFor(emf,
resourceProviderProperties));
}
private AbstractJPAEntityManagerProvider doGetResult(Supplier<AbstractJPAEntityManagerProvider> getter) {
synchronized (getter) {
if (closed) {
throw new IllegalStateException("This ResourceProvider has been reclaimed because the factory service that provided it was released");
}
}
AbstractJPAEntityManagerProvider ajcp = getter.get();
boolean destroy = false;
synchronized (toClose) {
if (closed) {
destroy = true;
} else {
toClose.add(ajcp);
}
}
if(destroy) {
ajcp.close();
throw new IllegalStateException("This ResourceProvider has been reclaimed because the factory service that provided it was released");
}
return ajcp;
}
public void closeAll() {
synchronized (toClose) {
closed = true;
}
// toClose is now up to date and no other thread will write it
toClose.stream().forEach(ajcp -> {
try {
ajcp.close();
} catch (Exception e) {}
});
toClose.clear();
}
}