package org.wso2.carbon.humantask.core.dao.jpa.openjpa;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.humantask.core.dao.Constants;
import org.wso2.carbon.humantask.core.dao.HumanTaskDAOConnection;
import org.wso2.carbon.humantask.core.dao.HumanTaskDAOConnectionFactoryJDBC;
import org.wso2.carbon.humantask.core.dao.jpa.JPAVendorAdapter;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.sql.DataSource;
import javax.transaction.*;
import java.util.HashMap;
import java.util.Map;
/**
* JPA Implementation
*/
public class HumanTaskDAOConnectionFactoryImpl implements HumanTaskDAOConnectionFactoryJDBC {
private static Log log = LogFactory.getLog(HumanTaskDAOConnectionFactoryImpl.class);
private EntityManagerFactory entityManagerFactory;
private DataSource dataSource;
private TransactionManager tnxManager;
private Map<String, Object> jpaPropertiesMap;
private static ThreadLocal<HumanTaskDAOConnectionImpl> connections = new ThreadLocal<HumanTaskDAOConnectionImpl>();
public HumanTaskDAOConnectionFactoryImpl() {
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setTransactionManager(TransactionManager tnxManager) {
this.tnxManager = tnxManager;
}
public void setDAOConnectionFactoryProperties(Map<String, Object> propertiesMap) {
this.jpaPropertiesMap = propertiesMap;
}
private boolean isInTransaction() throws SystemException{
return tnxManager.getTransaction() != null && tnxManager.getTransaction().getStatus() == Status.STATUS_ACTIVE;
}
public HumanTaskDAOConnection getConnection() {
if (connections.get() != null) {
return connections.get();
} else {
try {
if (this.isInTransaction()) {
HashMap propMap = new HashMap();
// propMap.put("openjpa.TransactionMode", "managed");
EntityManager em = entityManagerFactory.createEntityManager(propMap);
em.getTransaction().begin();
HumanTaskDAOConnectionImpl conn = createHumanTaskDAOConnection(em);
connections.set(conn);
tnxManager.getTransaction().registerSynchronization(new Synchronization() {
public void afterCompletion(int i) {
if (connections.get() != null) {
if (i == Status.STATUS_COMMITTED) {
if(log.isDebugEnabled()) {
log.debug(" Transaction is successfully committed");
}
connections.get().getEntityManager().getTransaction().commit();
connections.get().getEntityManager().close();
connections.set(null);
} else if (i == Status.STATUS_ROLLEDBACK) {
if(log.isDebugEnabled()) {
log.debug(" Transaction is successfully rolled back ");
}
connections.get().getEntityManager().getTransaction().rollback();
connections.get().getEntityManager().close();
connections.set(null);
}
}
}
public void beforeCompletion() {
}
});
return conn;
}
} catch (RollbackException e) {
throw new RuntimeException("Could not register synchronizer!", e);
} catch (SystemException e) {
throw new RuntimeException("Could not register synchronizer!", e);
}
return null;
}
}
protected HumanTaskDAOConnectionImpl createHumanTaskDAOConnection(EntityManager entityManager) {
return new HumanTaskDAOConnectionImpl(entityManager);
}
public void init() {
JPAVendorAdapter vendorAdapter = getJPAVendorAdapter();
this.entityManagerFactory = Persistence.createEntityManagerFactory("HT-PU",
vendorAdapter.getJpaPropertyMap(tnxManager));
}
/**
* Returns the JPA Vendor adapter based on user preference
* <p/>
* Note: Currently we only support one JPA vendor(OpenJPA), so I have omitted vendor selection
* logic.
*
* @return JPAVendorAdapter implementation
*/
private JPAVendorAdapter getJPAVendorAdapter() {
JPAVendorAdapter vendorAdapter = new OpenJPAVendorAdapter();
vendorAdapter.setDataSource(dataSource);
// TODO: Investigate whether this could be moved to upper layer. Directly put bool into prop map.
Object generateDDL = jpaPropertiesMap.get(Constants.PROP_ENABLE_DDL_GENERATION);
Object showSQL = jpaPropertiesMap.get(Constants.PROP_ENABLE_SQL_TRACING);
if (generateDDL == null) {
generateDDL = Boolean.FALSE.toString();
}
if (showSQL == null) {
showSQL = Boolean.FALSE.toString();
}
vendorAdapter.setGenerateDdl((Boolean) generateDDL);
vendorAdapter.setShowSql((Boolean) showSQL);
return vendorAdapter;
}
public DataSource getDataSource() {
return this.dataSource;
}
public void shutdown() {
this.entityManagerFactory.close();
}
}