Package com.j256.ormlite

Source Code of com.j256.ormlite.BaseJdbcTest$PossibleExceptionRule

package com.j256.ormlite;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.internal.runners.model.MultipleFailureException;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;

import com.j256.ormlite.dao.BaseDaoImpl;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.db.DatabaseType;
import com.j256.ormlite.jdbc.JdbcConnectionSource;
import com.j256.ormlite.table.DatabaseTableConfig;
import com.j256.ormlite.table.TableUtils;

public abstract class BaseJdbcTest {

  private static final String DATASOURCE_ERROR = "Property 'dataSource' is required";
  @Rule
  public PossibleExceptionRule possibleException = new PossibleExceptionRule();

  protected static final String DEFAULT_DATABASE_URL = "jdbc:h2:mem:ormlite";

  protected String databaseHost = null;
  protected String databaseUrl = DEFAULT_DATABASE_URL;
  protected String userName = null;
  protected String password = null;

  protected JdbcConnectionSource connectionSource = null;
  protected boolean isConnectionExpected = false;
  protected DatabaseType databaseType = null;

  private Set<Class<?>> dropClassSet = new HashSet<Class<?>>();
  private Set<DatabaseTableConfig<?>> dropTableConfigSet = new HashSet<DatabaseTableConfig<?>>();

  @Before
  public void before() throws Exception {
    DaoManager.clearCache();
    if (connectionSource != null) {
      return;
    }
    // do this for everyone
    System.setProperty("derby.stream.error.file", "target/derby.log");
    setDatabaseParams();
    doOpenConnectionSource();
  }

  protected void openConnectionSource() throws Exception {
    if (connectionSource == null) {
      doOpenConnectionSource();
    }
  }

  /**
   * Set the database parameters for this db type.
   *
   * @throws SQLException
   *             For sub classes
   */
  protected void setDatabaseParams() throws SQLException {
    // noop here -- designed to be overridden
  }

  @After
  public void after() throws Exception {
    if (connectionSource != null) {
      for (Class<?> clazz : dropClassSet) {
        dropTable(clazz, true);
      }
      dropClassSet.clear();
      for (DatabaseTableConfig<?> tableConfig : dropTableConfigSet) {
        dropTable(tableConfig, true);
      }
      dropTableConfigSet.clear();
    }
    closeConnectionSource();
    DaoManager.clearCache();
  }

  /**
   * Return if this test was expecting to be able to load the driver class
   */
  protected boolean isDriverClassExpected() {
    return true;
  }

  /**
   * Return if this test was expecting to be able to connect to the database
   */
  protected boolean isConnectionExpected() throws IOException {
    try {
      if (databaseHost == null) {
        return true;
      } else {
        return InetAddress.getByName(databaseHost).isReachable(500);
      }
    } catch (UnknownHostException e) {
      return false;
    }
  }

  protected void closeConnectionSource() throws Exception {
    if (connectionSource != null) {
      connectionSource.close();
      connectionSource = null;
    }
  }

  protected <T, ID> Dao<T, ID> createDao(Class<T> clazz, boolean createTable) throws Exception {
    if (connectionSource == null) {
      throw new SQLException(DATASOURCE_ERROR);
    }
    @SuppressWarnings("unchecked")
    BaseDaoImpl<T, ID> dao = (BaseDaoImpl<T, ID>) DaoManager.createDao(connectionSource, clazz);
    return configDao(dao, createTable);
  }

  protected <T, ID> Dao<T, ID> createDao(DatabaseTableConfig<T> tableConfig, boolean createTable) throws Exception {
    if (connectionSource == null) {
      throw new SQLException(DATASOURCE_ERROR);
    }
    @SuppressWarnings("unchecked")
    BaseDaoImpl<T, ID> dao = (BaseDaoImpl<T, ID>) DaoManager.createDao(connectionSource, tableConfig);
    return configDao(dao, createTable);
  }

  protected <T> void createTable(Class<T> clazz, boolean dropAtEnd) throws Exception {
    try {
      // first we drop it in case it existed before
      dropTable(clazz, true);
    } catch (SQLException ignored) {
      // ignore any errors about missing tables
    }
    TableUtils.createTable(connectionSource, clazz);
    if (dropAtEnd) {
      dropClassSet.add(clazz);
    }
  }

  protected <T> void createTable(DatabaseTableConfig<T> tableConfig, boolean dropAtEnd) throws Exception {
    try {
      // first we drop it in case it existed before
      dropTable(tableConfig, true);
    } catch (SQLException ignored) {
      // ignore any errors about missing tables
    }
    TableUtils.createTable(connectionSource, tableConfig);
    if (dropAtEnd) {
      dropTableConfigSet.add(tableConfig);
    }
  }

  protected <T> void dropTable(Class<T> clazz, boolean ignoreErrors) throws Exception {
    // drop the table and ignore any errors along the way
    TableUtils.dropTable(connectionSource, clazz, ignoreErrors);
  }

  protected <T> void dropTable(DatabaseTableConfig<T> tableConfig, boolean ignoreErrors) throws Exception {
    // drop the table and ignore any errors along the way
    TableUtils.dropTable(connectionSource, tableConfig, ignoreErrors);
  }

  private void doOpenConnectionSource() throws Exception {
    if (connectionSource == null) {
      isConnectionExpected = isConnectionExpected();
      if (isConnectionExpected) {
        connectionSource = new JdbcConnectionSource(databaseUrl, userName, password);
      }
    }
    if (databaseType == null) {
      if (connectionSource != null) {
        databaseType = connectionSource.getDatabaseType();
      }
    } else {
      if (connectionSource != null) {
        connectionSource.setDatabaseType(databaseType);
      }
    }
  }

  private <T, ID> Dao<T, ID> configDao(BaseDaoImpl<T, ID> dao, boolean createTable) throws Exception {
    if (connectionSource == null) {
      throw new SQLException(DATASOURCE_ERROR);
    }
    dao.setConnectionSource(connectionSource);
    if (createTable) {
      DatabaseTableConfig<T> tableConfig = dao.getTableConfig();
      if (tableConfig == null) {
        tableConfig = DatabaseTableConfig.fromClass(connectionSource, dao.getDataClass());
      }
      createTable(tableConfig, true);
    }
    dao.initialize();
    return dao;
  }

  /**
   * Our own junit rule which adds in an optional exception matcher if the db host is not available.
   */
  public class PossibleExceptionRule implements MethodRule {

    private Class<? extends Throwable> tClass = null;

    public Statement apply(Statement statement, FrameworkMethod method, Object junitClassObject) {
      for (Annotation annotation : method.getAnnotations()) {
        if (annotation.annotationType() == ExpectedBehavior.class) {
          ExpectedBehavior test = (ExpectedBehavior) annotation;
          tClass = test.expected();
          break;
        }
      }
      return new StatementWrapper(statement);
    }

    /**
     * Specify the expected throwable class or you can use the {@link ExpectedBehavior} annotation.
     */
    public void expect(Class<? extends Throwable> tClass) {
      this.tClass = tClass;
    }

    private class StatementWrapper extends Statement {
      private final Statement statement;

      public StatementWrapper(Statement statement) {
        this.statement = statement;
      }

      @Override
      public void evaluate() throws Throwable {
        try {
          statement.evaluate();
        } catch (Throwable t) {
          if (t instanceof MultipleFailureException) {
            t = ((MultipleFailureException) t).getFailures().get(0);
          }
          if (t instanceof InvocationTargetException) {
            t = ((InvocationTargetException) t).getTargetException();
          }
          String assertMsg;
          if (t instanceof AssertionError) {
            throw t;
          } else if ((!isConnectionExpected) && t.getMessage() != null
              && t.getMessage().contains(DATASOURCE_ERROR)) {
            // if we throw because of missing data-source and the db server isn't available, ignore it
            return;
          } else if (tClass == null) {
            assertMsg = "Test threw unexpected exception: " + t;
          } else if (tClass == t.getClass()) {
            // we matched our expected exception
            return;
          } else {
            assertMsg = "Expected test to throw " + tClass + " but it threw: " + t;
          }
          Error error = new AssertionError(assertMsg);
          error.initCause(t);
          throw error;
        }
        // can't be in the throw block
        if (tClass != null) {
          throw new AssertionError("Expected test to throw " + tClass);
        }
      }
    }
  }

  /**
   * We can't use the @Test(expected) with the {@link PossibleExceptionRule} rule because it masks the exception and
   * doesn't pass it up to our statement wrapper.
   */
  @Target(METHOD)
  @Retention(RUNTIME)
  public @interface ExpectedBehavior {
    Class<? extends Throwable> expected();
  }
}
TOP

Related Classes of com.j256.ormlite.BaseJdbcTest$PossibleExceptionRule

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.