org.sipfoundry.sipxconfig.test.IntegrationTestCase.java Source code

Java tutorial

Introduction

Here is the source code for org.sipfoundry.sipxconfig.test.IntegrationTestCase.java

Source

/*
 *
 *
 * Copyright (C) 2007 Pingtel Corp., certain elements licensed under a Contributor Agreement.
 * Contributors retain copyright to elements licensed under a Contributor Agreement.
 * Licensed to the User under the LGPL license.
 *
 * $
 */
package org.sipfoundry.sipxconfig.test;

import static org.easymock.EasyMock.createNiceMock;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ReplacementDataSet;
import org.dbunit.operation.DatabaseOperation;
import org.hibernate.SessionFactory;
import org.sipfoundry.commons.userdb.profile.UserProfileService;
import org.sipfoundry.sipxconfig.common.SpringHibernateInstantiator;
import org.sipfoundry.sipxconfig.common.event.DaoEventListener;
import org.sipfoundry.sipxconfig.common.event.DaoEventPublisherImpl;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests;

public abstract class IntegrationTestCase extends AbstractAnnotationAwareTransactionalTests {
    private static final String ROOT_RES_PATH = "/org/sipfoundry/sipxconfig/";
    private static final Log LOG = LogFactory.getLog(IntegrationTestCase.class);
    private static final String CANNOT_SET_PROP_MSG = "Unable to set property %s on target %s";

    private SessionFactory m_sessionFactory;
    private HibernateTemplate m_hibernateTemplate;
    private JdbcTemplate m_db;
    private Map<Object, Map<String, Object>> m_modifiedContextObjectMap;
    private DaoEventPublisherImpl m_daoEventPublisher;
    private SpringHibernateInstantiator m_entityInterceptor;
    private UserProfileService m_userProfileService;
    private MongoTemplate m_profilesDb;

    public IntegrationTestCase() {
        setAutowireMode(AUTOWIRE_BY_NAME);
    }

    @Override
    protected void onSetUpBeforeTransaction() throws Exception {
        // w/o this beans loaded from hibernate are not created from spring, therefore not dependency injected
        ((HibernateTransactionManager) transactionManager).setEntityInterceptor(m_entityInterceptor);
    }

    protected void sql(String resource) throws IOException {
        SqlFileReader sql = new SqlFileReader(getClass().getResourceAsStream(ROOT_RES_PATH + resource));
        m_db.batchUpdate(sql.parse().toArray(new String[0]));
    }

    protected void sql(InputStream in) throws IOException {
        SqlFileReader sql = new SqlFileReader(in);
        m_db.batchUpdate(sql.parse().toArray(new String[0]));
    }

    protected JdbcTemplate db() {
        return m_db;
    }

    protected void divertDaoEvents(DaoEventListener listener) {
        m_daoEventPublisher.divertEvents(listener);
    }

    protected void disableDaoEventPublishing() {
        DaoEventListener stub = createNiceMock(DaoEventListener.class);
        m_daoEventPublisher.divertEvents(stub);
    }

    @Override
    protected void onSetUpInTransaction() throws Exception {
        super.onSetUpInTransaction();
        m_modifiedContextObjectMap = new HashMap<Object, Map<String, Object>>();
    }

    @Override
    protected void onTearDownInTransaction() throws Exception {
        super.onTearDownInTransaction();
        if (m_modifiedContextObjectMap != null) {
            resetContext();
        }
        m_profilesDb.dropCollection("userProfile");
    }

    @Override
    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = m_db;
    }

    public void setConfigJdbcTemplate(JdbcTemplate db) {
        m_db = db;
    }

    @Override
    protected String[] getConfigLocations() {
        // There are many interdependencies between spring files so in general you need
        // to load them all. However, if you do have isolated spring file, this is definitely
        // overrideable
        return new String[] { "classpath*:**/*.beans.xml" };
    }

    @Override
    public void runBare() throws Throwable {
        try {
            super.runBare();
        } catch (SQLException e) {
            dumpSqlExceptionMessages(e);
            throw e;
        } catch (DataIntegrityViolationException e) {
            dumpSqlExceptionMessages(e);
            throw e;
        }
    }

    void dumpSqlExceptionMessages(SQLException e) {
        for (SQLException next = e; next != null; next = next.getNextException()) {
            LOG.info(next.getMessage());
        }
    }

    void dumpSqlExceptionMessages(DataIntegrityViolationException e) {
        if (e.getCause() instanceof SQLException) {
            dumpSqlExceptionMessages((SQLException) e.getCause());
        }
    }

    protected void loadDataSet(String resource) {
        IDatabaseConnection connection = getConnection();
        try {
            IDataSet dataSet = TestHelper.loadDataSetFlat(resource);
            DatabaseOperation.CLEAN_INSERT.execute(connection, dataSet);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    protected void loadDataSetXml(String resource) throws Exception {
        IDatabaseConnection connection = getConnection();
        IDataSet dataSet = TestHelper.loadDataSet(resource);
        DatabaseOperation.CLEAN_INSERT.execute(connection, dataSet);
    }

    protected ReplacementDataSet loadReplaceableDataSetFlat(String fileResource) throws Exception {
        IDataSet ds = TestHelper.loadDataSetFlat(fileResource);
        ReplacementDataSet relaceable = new ReplacementDataSet(ds);
        relaceable.addReplacementObject("[null]", null);
        return relaceable;
    }

    protected IDatabaseConnection getConnection() {
        // by getting the same connection, out dbunit operations happen in same transation
        // subsequently get rolled back automaticaly
        Connection jdbcConnection = m_sessionFactory.getCurrentSession().connection();
        IDatabaseConnection dbunitConnection = new DatabaseConnection(jdbcConnection);
        DatabaseConfig config = dbunitConnection.getConfig();
        config.setFeature("http://www.dbunit.org/features/batchedStatements", true);

        return dbunitConnection;
    }

    /**
     * Flush hibernate session.
     *
     * Flush need to be called after hibernate/spring operations, before testing the content of
     * the database with jdbcTemplate or DBUnit assertions.
     */
    protected void flush() {
        m_hibernateTemplate.flush();
    }

    protected void evict(Object o) {
        m_hibernateTemplate.evict(o);
    }

    /**
     * Commit everything to database. useful when debugging and want to run queries from another app. Also
     * useful in some circumstances when subsequent sql requires it.  Note, tests are allowed to leave
     * data in database after execution.  It's up to each test to clear all existing data before execution.
     */
    protected void commit() {
        transactionManager.commit(transactionStatus);
    }

    protected void clear() {
        db().execute("select truncate_all()");
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        m_sessionFactory = sessionFactory;
        m_hibernateTemplate = new HibernateTemplate();
        m_hibernateTemplate.setSessionFactory(m_sessionFactory);
    }

    public void setSpringInstantiator(SpringHibernateInstantiator entityInterceptor) {
        m_entityInterceptor = entityInterceptor;
    }

    /**
     * Modifies a concrete object from the spring context.  Any modifications will be be
     * rolled back in the tearDown
     * @param target The context object to modify
     * @param propertyName The property of the the target to modify
     * @param originalValue The original value, used to roll back in the tearDown
     * @param valueForTest The value to be set in the target for this test
     */
    protected void modifyContext(Object target, String propertyName, Object originalValue, Object valueForTest) {
        if (!m_modifiedContextObjectMap.containsKey(target)) {
            m_modifiedContextObjectMap.put(target, new HashMap<String, Object>());
        }

        Map<String, Object> originalContextObjectValueMap = m_modifiedContextObjectMap.get(target);
        originalContextObjectValueMap.put(propertyName, originalValue);

        try {
            BeanUtils.setProperty(target, propertyName, valueForTest);
        } catch (IllegalAccessException e) {
            LOG.error(format(CANNOT_SET_PROP_MSG, propertyName, target), e);
        } catch (InvocationTargetException e) {
            LOG.error(format(CANNOT_SET_PROP_MSG, propertyName, target), e);
        }
    }

    /**
     * Roll back any changes made to context objects via the modifyContext method
     */
    private void resetContext() {
        for (Object target : m_modifiedContextObjectMap.keySet()) {
            Map<String, Object> originalValueMap = m_modifiedContextObjectMap.get(target);
            for (String propertyName : originalValueMap.keySet()) {
                Object originalValue = originalValueMap.get(propertyName);
                try {
                    BeanUtils.setProperty(target, propertyName, originalValue);
                    originalValueMap.remove(propertyName);
                } catch (IllegalAccessException e) {
                    LOG.error(format(CANNOT_SET_PROP_MSG, propertyName, target), e);
                } catch (InvocationTargetException e) {
                    LOG.error(format(CANNOT_SET_PROP_MSG, propertyName, target), e);
                }
            }

            m_modifiedContextObjectMap.remove(target);
        }

        assertTrue(m_modifiedContextObjectMap.isEmpty());
        m_daoEventPublisher.stopDivertingEvents();
    }

    public void setDaoEventPublisherImpl(DaoEventPublisherImpl daoEventPublisher) {
        m_daoEventPublisher = daoEventPublisher;
    }

    public DaoEventPublisherImpl getDaoEventPublisher() {
        return m_daoEventPublisher;
    }

    public SessionFactory getSessionFactory() {
        return m_sessionFactory;
    }

    public HibernateTemplate getHibernateTemplate() {
        return m_hibernateTemplate;
    }

    public UserProfileService getUserProfileService() {
        return m_userProfileService;
    }

    public void setUserProfileService(UserProfileService service) {
        m_userProfileService = service;
    }

    public MongoTemplate getProfilesDb() {
        return m_profilesDb;
    }

    public void setProfilesDb(MongoTemplate template) {
        m_profilesDb = template;
    }
}