/** * junit-rules: JUnit Rules Library * * Copyright (c) 2009-2011 by Alistair A. Israel. * This software is made available under the terms of the MIT License. * * Created Oct 16, 2009 */ package junit.rules.jpa.hibernate; import static junit.rules.util.Reflection.invoke; import static junit.rules.util.Reflection.set; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import javax.annotation.PostConstruct; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.PersistenceContext; import junit.rules.TestFixture; import junit.rules.dbunit.Fixtures; import junit.rules.util.Reflection; import org.apache.derby.jdbc.EmbeddedDriver; import org.dbunit.JdbcDatabaseTester; import org.dbunit.dataset.CompositeDataSet; import org.dbunit.dataset.DataSetException; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.xml.XmlDataSet; import org.hibernate.ejb.Ejb3Configuration; import org.junit.runner.Description; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Alistair A. Israel * @since 0.3 */ public class HibernatePersistenceContext extends TestFixture implements junit.rules.jpa.PersistenceContext { private static final Logger logger = LoggerFactory.getLogger(HibernatePersistenceContext.class); private final List<String> fixtureNames = new ArrayList<String>(); private EntityManagerFactory entityManagerFactory; private EntityManager entityManager; private JdbcDatabaseTester jdbcDatabaseTester; /** * @param classes * the annotated classes */ public HibernatePersistenceContext(final Class<?>... classes) { final Ejb3Configuration cfg = DerbyHibernateUtil.configureDerbyHibernateJpa(classes); entityManagerFactory = cfg.buildEntityManagerFactory(); entityManager = entityManagerFactory.createEntityManager(); } /** * @param object * an object to which we will apply EJB 3.0 style @PersistenceContext and @PostConstruct handling */ @Override public final void injectAndPostConstruct(final Object object) { final Class<? extends Object> clazz = object.getClass(); for (final Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(PersistenceContext.class)) { final Class<?> type = field.getType(); if (type.equals(EntityManager.class)) { set(field).of(object).to(entityManager); } else { logger.warn("Found field \"{}\" annotated with @PersistenceContext but is of type {}", field .getName(), type.getName()); } } } for (final Method method : clazz.getDeclaredMethods()) { if (method.isAnnotationPresent(PostConstruct.class)) { final int nParameters = method.getParameterTypes().length; if (nParameters == 0) { invoke(method).on(object); } else { logger.warn("Found method \"{}\" annotated @PostConstruct " + "but don't know how to invoke with {} parameters", method.getName(), nParameters); } } } } /** * {@inheritDoc} * * @see junit.rules.TestFixture#inspect(org.junit.runner.Description) */ @Override protected final void inspect(final Description description) { final Class<? extends Object> testClass = description.getTestClass(); if (testClass.isAnnotationPresent(Fixtures.class)) { addFixturesFromAnnotation(testClass.getAnnotation(Fixtures.class)); } final Method method = Reflection.quietlyGetMethod(testClass, description.getMethodName()); if (method.isAnnotationPresent(Fixtures.class)) { addFixturesFromAnnotation(method.getAnnotation(Fixtures.class)); } } /** * @param annotation * the {@link Fixtures} annotation */ private void addFixturesFromAnnotation(final Fixtures annotation) { for (final String fixtureName : annotation.value()) { fixtureNames.add(fixtureName); } } /** * {@inheritDoc} * * @see junit.rules.TestFixture#setUp() */ @Override protected final void setUp() throws Throwable { jdbcDatabaseTester = new JdbcDatabaseTester(EmbeddedDriver.class.getName(), DerbyHibernateUtil.JDBC_DERBY_URL); if (fixtureNames.isEmpty()) { logger.warn("No fixtures to load! Specify fixtures using @Fixtures."); } else { loadFixtures(); } jdbcDatabaseTester.onSetup(); } /** * @throws DataSetException * on any exception */ private void loadFixtures() throws DataSetException { final List<IDataSet> dataSets = new ArrayList<IDataSet>(); for (final String fixtureName : fixtureNames) { logger.trace("Attempting to load database fixture \"" + fixtureName + "\""); final IDataSet dataSet = attemptToLoadFixture(fixtureName); if (dataSet != null) { dataSets.add(dataSet); } } if (dataSets.isEmpty()) { logger.warn("Found 0 data sets!"); } else { final CompositeDataSet compositeDataSet = new CompositeDataSet(dataSets.toArray(new IDataSet[dataSets .size()])); jdbcDatabaseTester.setDataSet(compositeDataSet); } } /** * @param fixtureName * the fixture name * @return {@link IDataSet} */ private IDataSet attemptToLoadFixture(final String fixtureName) { IDataSet dataSet = null; try { final InputStream in = ClassLoader.getSystemResourceAsStream(fixtureName); try { if (in != null) { if (fixtureName.endsWith(".xml")) { dataSet = new XmlDataSet(in); } } } finally { in.close(); } } catch (final Exception e) { logger.warn(e.getMessage(), e); } return dataSet; } /** * {@inheritDoc} * * @see junit.rules.TestFixture#tearDown() */ @Override protected final void tearDown() throws Throwable { jdbcDatabaseTester.onTearDown(); entityManagerFactory.close(); } /** * @return {@link EntityManager} * @see javax.persistence.EntityManagerFactory#createEntityManager() */ public final EntityManager getEntityManager() { return this.entityManager; } }