/**
* Copyright (C) 2010-2017 Gordon Fraser, Andrea Arcuri and EvoSuite
* contributors
*
* This file is part of EvoSuite.
*
* EvoSuite is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* EvoSuite is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with EvoSuite. If not, see <http://www.gnu.org/licenses/>.
*/
package org.evosuite.runtime.javaee.javax.persistence;
import org.hibernate.dialect.HSQLDialect;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import javax.persistence.*;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.metamodel.Metamodel;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* A wrapper over an actual EntityManagerFactory.
* Needed to create and control wrapped instances of EntityManager
*
* Created by Andrea Arcuri on 16/06/15.
*/
public class EvoEntityManagerFactory implements EntityManagerFactory{
private final EntityManagerFactory factory;
private final List<EvoEntityManager> managers;
public EvoEntityManagerFactory(){
factory = createEMFWithSpring();
managers = new ArrayList<>();
}
private EntityManagerFactory createEMFWithSpring(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
// DriverManagerDataSource uses the context classloader for some reason...
ClassLoader cl1 = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(EvoEntityManagerFactory.class.getClassLoader());
dataSource.setDriverClassName(org.hsqldb.jdbcDriver.class.getName());
dataSource.setUrl("jdbc:hsqldb:mem:.");
dataSource.setUsername("sa");
dataSource.setPassword("");
Thread.currentThread().setContextClassLoader(cl1);
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan(""); //search everything on classpath
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
try {
/*
The code in this class works fine on Mac, but somehow it crashes on Debian (Lux cluster).
So, the following is just a workaround, although not fully understood while on Debian
it was behaving differently
*/
Field f = LocalContainerEntityManagerFactoryBean.class.getDeclaredField("internalPersistenceUnitManager");
f.setAccessible(true);
DefaultPersistenceUnitManager m = (DefaultPersistenceUnitManager)f.get(em);
m.setDefaultPersistenceUnitRootLocation(null);
} catch (Exception e) {
e.printStackTrace();
}
Properties properties = new Properties();
properties.setProperty("hibernate.show_sql", "true");
properties.setProperty("hibernate.dialect", HSQLDialect.class.getName());
properties.setProperty("hibernate.connection.shutdown", "true");
properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
properties.setProperty("hibernate.classloading.use_current_tccl_as_parent", "false");
em.setJpaProperties(properties);
em.afterPropertiesSet();
return em.getObject();
}
public void clearAllEntityManagers(){
for(EvoEntityManager em : managers){
if(em!=null){
if (em.isOpen() && !em.isJoinedToTransaction() && em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
if(em.isOpen()) {
em.close();
}
}
}
managers.clear();
}
//---------- EntityManagerFactory ---------------
@Override
public EntityManager createEntityManager() {
EntityManager em = factory.createEntityManager();
EvoEntityManager evo = new EvoEntityManager(em,this);
managers.add(evo);
return evo;
}
@Override
public EntityManager createEntityManager(Map map) {
EntityManager em = factory.createEntityManager(map);
EvoEntityManager evo = new EvoEntityManager(em,this);
managers.add(evo);
return evo;
}
@Override
public EntityManager createEntityManager(SynchronizationType synchronizationType) {
EntityManager em = factory.createEntityManager(synchronizationType);
EvoEntityManager evo = new EvoEntityManager(em,this);
managers.add(evo);
return evo;
}
@Override
public EntityManager createEntityManager(SynchronizationType synchronizationType, Map map) {
EntityManager em = factory.createEntityManager(synchronizationType,map);
EvoEntityManager evo = new EvoEntityManager(em,this);
managers.add(evo);
return evo;
}
@Override
public CriteriaBuilder getCriteriaBuilder() {
return factory.getCriteriaBuilder();
}
@Override
public Metamodel getMetamodel() {
return factory.getMetamodel();
}
@Override
public boolean isOpen() {
return factory.isOpen();
}
@Override
public void close() {
factory.close();
}
@Override
public Map<String, Object> getProperties() {
return factory.getProperties();
}
@Override
public Cache getCache() {
return factory.getCache();
}
@Override
public PersistenceUnitUtil getPersistenceUnitUtil() {
return factory.getPersistenceUnitUtil();
}
@Override
public void addNamedQuery(String name, Query query) {
factory.addNamedQuery(name,query);
}
@Override
public <T> T unwrap(Class<T> cls) {
return factory.unwrap(cls);
}
@Override
public <T> void addNamedEntityGraph(String graphName, EntityGraph<T> entityGraph) {
factory.addNamedEntityGraph(graphName,entityGraph);
}
}