/******************************************************************************* * Copyright (c) 2005, 2015 SAP, Oracle. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * SAP - initial API and implementation ******************************************************************************/ package org.eclipse.persistence.testing.framework.wdf; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.LockModeType; import javax.persistence.Persistence; import javax.sql.DataSource; import org.eclipse.persistence.config.PersistenceUnitProperties; import org.eclipse.persistence.testing.framework.junit.JUnitTestCaseHelper; import org.eclipse.persistence.testing.framework.server.JEEPlatform; import org.eclipse.persistence.testing.framework.server.ServerPlatform; import org.eclipse.persistence.testing.tests.feature.TestDataSource; import org.junit.Assert; import org.junit.Before; import org.junit.runner.RunWith; import org.junit.runners.Parameterized.Parameters; @SuppressWarnings("unchecked") @RunWith(SkipBugzillaTestRunner.class) public abstract class AbstractBaseTest { // /** System variable to set the tests to run on the server. */ // public static final String RUN_ON_SERVER = "server.run"; // private static Map<String, EntityManagerFactory> emfNamedPersistenceUnits = new Hashtable<String, EntityManagerFactory>(); /** Determine if the test is running on a JEE server, or in JSE. */ private static ServerPlatform serverPlatform; private final JPAEnvironment environment; private final String puName; private final static DataSource dataSource; protected final static Map EMF_PROPERTIES; private static boolean seesJPA2 = (LockModeType.values().length > 2); static { final DataSource aDataSource; if (!ServerInfoHolder.isOnServer()) { Map<String, String> properties = JUnitTestCaseHelper.getDatabaseProperties(); String driver = properties.get(PersistenceUnitProperties.JDBC_DRIVER); String url = properties.get(PersistenceUnitProperties.JDBC_URL); String user = properties.get(PersistenceUnitProperties.JDBC_USER); String password = properties.get(PersistenceUnitProperties.JDBC_PASSWORD); Properties userPasswd = new Properties(); userPasswd.put("user", user); userPasswd.put("password", password); DataSource ds = new TestDataSource(driver, url, userPasswd); aDataSource = new PooledDataSource(ds); } else { Context context; try { context = new InitialContext(); aDataSource = (DataSource) context.lookup(ServerInfoHolder.getDataSourceName()); } catch (NamingException e) { throw new RuntimeException(e); } } dataSource = aDataSource; EMF_PROPERTIES = new HashMap(); EMF_PROPERTIES.put("delimited-identifiers", "true"); EMF_PROPERTIES.put(PersistenceUnitProperties.NON_JTA_DATASOURCE, dataSource); } public AbstractBaseTest(String name) { environment = new ResourceLocalEnvironment(); puName = name; } protected final JPAEnvironment getEnvironment() { return environment; } @Parameters public static void parameters() { } final class ResourceLocalEnvironment implements JPAEnvironment { @Override public void beginTransaction(EntityManager em) { em.getTransaction().begin(); } @Override public void commitTransaction(EntityManager em) { em.getTransaction().commit(); } @Override public void commitTransactionAndClear(EntityManager em) { try { commitTransaction(em); } finally { em.clear(); } } @Override public EntityManagerFactory createNewEntityManagerFactory() throws NamingException { AbstractBaseTest.closeEntityManagerFactory(puName); return Persistence.createEntityManagerFactory(puName, EMF_PROPERTIES); } @Override public EntityManager getEntityManager() { return getEntityManagerFactory().createEntityManager(); // return AbstractBaseTest.createEntityManager(puName, // EMF_PROPERTIES); } @Override public EntityManagerFactory getEntityManagerFactory() { return AbstractBaseTest.getEntityManagerFactory(puName, EMF_PROPERTIES); } @Override public boolean isTransactionActive(EntityManager em) { return em.getTransaction().isActive(); } @Override public boolean isTransactionMarkedForRollback(EntityManager em) { return em.getTransaction().getRollbackOnly(); } @Override public void markTransactionForRollback(EntityManager em) { em.getTransaction().setRollbackOnly(); } @Override public void rollbackTransaction(EntityManager em) { em.getTransaction().rollback(); } @Override public void rollbackTransactionAndClear(EntityManager em) { try { rollbackTransaction(em); } finally { em.clear(); } } @Override public boolean usesExtendedPC() { return true; } @Override public DataSource getDataSource() { return AbstractBaseTest.this.getDataSource(); } @Override public EntityManagerFactory createNewEntityManagerFactory(Map properties) throws NamingException { Map mergedProperties = new HashMap(); mergedProperties.putAll(EMF_PROPERTIES); mergedProperties.putAll(properties); AbstractBaseTest.closeEntityManagerFactory(puName); return Persistence.createEntityManagerFactory(puName, mergedProperties); } @Override public Object getPropertyValue(EntityManager em, String key) { Object delegate = em.getDelegate(); Method getEntityManagerFactoryMethod; try { getEntityManagerFactoryMethod = delegate.getClass().getMethod("getEntityManagerFactory"); Object emf = getEntityManagerFactoryMethod.invoke(delegate); Method getPropertiesMethod = emf.getClass().getMethod("getProperties"); @SuppressWarnings("rawtypes") Map map = (Map) getPropertiesMethod.invoke(emf); return map.get(key); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } } @Override public void evict(EntityManager em, Class<?> clazz) { Object delegate = em.getDelegate(); Method getEntityManagerFactoryMethod; try { getEntityManagerFactoryMethod = delegate.getClass().getMethod("getEntityManagerFactory"); Object emf = getEntityManagerFactoryMethod.invoke(delegate); Method getCacheMethod = emf.getClass().getMethod("getCache"); Object cache = getCacheMethod.invoke(emf); Method evictClassMethod = cache.getClass().getMethod("evict", Class.class); evictClassMethod.invoke(cache, clazz); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } } @Override public void evictAll(EntityManager em) { Object delegate = em.getDelegate(); Method getEntityManagerFactoryMethod; try { getEntityManagerFactoryMethod = delegate.getClass().getMethod("getEntityManagerFactory"); Object emf = getEntityManagerFactoryMethod.invoke(delegate); Method getCacheMethod = emf.getClass().getMethod("getCache"); Object cache = getCacheMethod.invoke(emf); Method evictClassMethod = cache.getClass().getMethod("evictAll", new Class[]{}); evictClassMethod.invoke(cache, new Object[]{}); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } } } final class JTATxScopedEnvironment implements JPAEnvironment { @Override public void beginTransaction(EntityManager em) { AbstractBaseTest.this.beginTransaction(em); } @Override public void commitTransaction(EntityManager em) { AbstractBaseTest.this.commitTransaction(em); } @Override public void commitTransactionAndClear(EntityManager em) { try { commitTransaction(em); } finally { em.clear(); } } @Override public EntityManagerFactory createNewEntityManagerFactory() throws NamingException { AbstractBaseTest.closeEntityManagerFactory(puName); return Persistence.createEntityManagerFactory(puName, EMF_PROPERTIES); } @Override public EntityManager getEntityManager() { return AbstractBaseTest.createEntityManager(puName, EMF_PROPERTIES); } @Override public EntityManagerFactory getEntityManagerFactory() { return AbstractBaseTest.getEntityManagerFactory(puName, EMF_PROPERTIES); } @Override public boolean isTransactionActive(EntityManager em) { return AbstractBaseTest.this.isTransactionActive(em); } @Override public boolean isTransactionMarkedForRollback(EntityManager em) { return AbstractBaseTest.this.getRollbackOnly(em); } @Override public void markTransactionForRollback(EntityManager em) { throw new UnsupportedOperationException(); } @Override public void rollbackTransaction(EntityManager em) { AbstractBaseTest.this.rollbackTransaction(em); } @Override public void rollbackTransactionAndClear(EntityManager em) { try { rollbackTransaction(em); } finally { em.clear(); } } @Override public boolean usesExtendedPC() { return true; } @Override public DataSource getDataSource() { return AbstractBaseTest.this.getDataSource(); } @Override public EntityManagerFactory createNewEntityManagerFactory(Map<String, Object> properties) throws NamingException { throw new UnsupportedOperationException(); } @Override public Object getPropertyValue(EntityManager em, String key) { throw new UnsupportedOperationException(); } @Override public void evict(EntityManager em, Class<?> clazz) { throw new UnsupportedOperationException(); } @Override public void evictAll(EntityManager em) { throw new UnsupportedOperationException(); } } public DataSource getDataSource() { return dataSource; } final public void closeEntityManager(EntityManager em) { if (!em.isOpen()) { return; } if (environment.isTransactionActive(em)/* * ||environment. * isTransactionMarkedForRollback * (em) */) { // FIXME discuss if tx is // active if marked for // rollback environment.rollbackTransaction(em); } // // close application-managed entity manager // if (!(getEnvironment() instanceof JTASharedPCEnvironment)) { // em.close(); FIXME // } } protected static void verify(boolean condition, String string) { Assert.assertTrue(string, condition); } protected final void flop(final String msg) { Assert.fail(msg); } abstract protected String[] getClearableTableNames(); @Before public void clearAllTablesAndSetup() throws SQLException { clearAllTables(); setup(); } protected void clearAllTables() throws SQLException { Connection conn = getDataSource().getConnection(); try { conn.setAutoCommit(false); Set<String> existingTables = new HashSet<String>(); DatabaseMetaData metaData = conn.getMetaData(); String schemaPattern = null; if (metaData.getDriverName().toLowerCase().contains("oracle")) { schemaPattern = metaData.getUserName().toUpperCase(); } ResultSet rs = metaData.getTables(null, schemaPattern, "TMP_%", null); try { while (rs.next()) { existingTables.add(rs.getString("TABLE_NAME").toUpperCase(Locale.ENGLISH)); } } finally { rs.close(); } Statement statement = conn.createStatement(); try { if (existingTables.contains("TMP_CASC_NODE")) { statement.executeUpdate("update TMP_CASC_NODE set PARENT = null"); } if (existingTables.contains("TMP_NODE")) { statement.executeUpdate("update TMP_NODE set PARENT = null"); } if (existingTables.contains("TMP_COP")) { statement.executeUpdate("update TMP_COP set PARTNER_ID = null"); } if (existingTables.contains("TMP_UCOFFICE_CUBICLE")) { statement.executeUpdate("delete from TMP_UCOFFICE_CUBICLE"); existingTables.remove("TMP_UCOFFICE_CUBICLE"); } for (String name : getClearableTableNames()) { if (existingTables.contains(name.toUpperCase(Locale.ENGLISH))) { statement.executeUpdate("delete from " + name); } } } catch (SQLException ex) { System.err.println(ex.getMessage()); throw ex; } finally { statement.close(); } conn.commit(); } finally { conn.close(); } // TODO evictAll } /** * intended to be overwritten by subclasses */ protected void setup() throws SQLException { } public static final <T extends Serializable> T serializeDeserialize(T serializable) throws IOException, ClassNotFoundException { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(out); try { objectOutputStream.writeObject(serializable); } finally { objectOutputStream.close(); } ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); return (T) new ObjectInputStream(in).readObject(); } public static boolean isInsideEngine() { return false; } /** * Checks whether the given throwable is of type * java.lang.IllegalStateException, or otherwise if the throwable contains a * java.lang.IllegalStateException somewhere in the cause stack. * * @param e * The throwable to check * @return <code>true</code> if the throwable is instance of or caused by * java.lang.IllegalStateException */ protected final boolean checkForIllegalStateException(Throwable e) { boolean contained = false; while (e != null) { if (e instanceof IllegalStateException) { contained = true; break; } e = e.getCause(); } return contained; } /** * Checks whether the given throwable is of type java.sql.SQLException, or * otherwise if the throwable contains a java.sql.SQLException somewhere in * the cause stack. * * @param e * The throwable to check * @return <code>true</code> if the throwable is instance of or caused by * java.sql.SQLException */ protected final boolean checkForSQLException(Throwable e) { boolean contained = false; while (e != null) { if (e instanceof SQLException) { contained = true; break; } e = e.getCause(); } return contained; } /** * Return if the transaction is active. This allows the same code to be used * on the server where JTA is used. */ public boolean isTransactionActive(EntityManager entityManager) { if (ServerInfoHolder.isOnServer()) { return getServerPlatform().isTransactionActive(); } else { return entityManager.getTransaction().isActive(); } } /** * Return if the transaction is roll back only. This allows the same code to * be used on the server where JTA is used. */ public boolean getRollbackOnly(EntityManager entityManager) { if (ServerInfoHolder.isOnServer()) { return getServerPlatform().getRollbackOnly(); } else { return entityManager.getTransaction().getRollbackOnly(); } } /** * Begin a transaction on the entity manager. This allows the same code to * be used on the server where JTA is used. */ public void beginTransaction(EntityManager entityManager) { if (ServerInfoHolder.isOnServer()) { getServerPlatform().beginTransaction(); } else { entityManager.getTransaction().begin(); } } /** * Commit a transaction on the entity manager. This allows the same code to * be used on the server where JTA is used. */ public void commitTransaction(EntityManager entityManager) { if (ServerInfoHolder.isOnServer()) { getServerPlatform().commitTransaction(); } else { entityManager.getTransaction().commit(); } } /** * Rollback a transaction on the entity manager. This allows the same code * to be used on the server where JTA is used. */ public void rollbackTransaction(EntityManager entityManager) { if (ServerInfoHolder.isOnServer()) { getServerPlatform().rollbackTransaction(); } else { entityManager.getTransaction().rollback(); } } /** * Return the server platform if running in JEE. */ public static ServerPlatform getServerPlatform() { if (serverPlatform == null) { serverPlatform = new JEEPlatform(); } return serverPlatform; } /** * Create a new entity manager for the "default" persistence unit. If in JEE * this will create or return the active managed entity manager. */ public static EntityManager createEntityManager() { if (ServerInfoHolder.isOnServer()) { return getServerPlatform().getEntityManager("default"); } else { return getEntityManagerFactory().createEntityManager(); } } /** * Create a new entity manager for the persistence unit using the * properties. The properties will only be used the first time this entity * manager is accessed. If in JEE this will create or return the active * managed entity manager. */ public static EntityManager createEntityManager(String persistenceUnitName, Map<String, String> properties) { if (ServerInfoHolder.isOnServer()) { return getServerPlatform().getEntityManager(persistenceUnitName); } else { return getEntityManagerFactory(persistenceUnitName, properties).createEntityManager(); } } public static EntityManagerFactory getEntityManagerFactory(String persistenceUnitName) { return getEntityManagerFactory(persistenceUnitName, JUnitTestCaseHelper.getDatabaseProperties()); } public static EntityManagerFactory getEntityManagerFactory(String persistenceUnitName, Map<String, String> properties) { if (ServerInfoHolder.isOnServer()) { return getServerPlatform().getEntityManagerFactory(persistenceUnitName); } else { EntityManagerFactory emfNamedPersistenceUnit = (EntityManagerFactory) emfNamedPersistenceUnits.get(persistenceUnitName); if (emfNamedPersistenceUnit == null) { emfNamedPersistenceUnit = Persistence.createEntityManagerFactory(persistenceUnitName, properties); emfNamedPersistenceUnits.put(persistenceUnitName, emfNamedPersistenceUnit); } return emfNamedPersistenceUnit; } } public static EntityManagerFactory getEntityManagerFactory() { return getEntityManagerFactory("default"); } public static void closeEntityManagerFactory() { closeEntityManagerFactory("default"); } public static void closeEntityManagerFactory(String persistenceUnitName) { EntityManagerFactory emfNamedPersistenceUnit = (EntityManagerFactory) emfNamedPersistenceUnits.get(persistenceUnitName); if (emfNamedPersistenceUnit != null) { if (emfNamedPersistenceUnit.isOpen()) { emfNamedPersistenceUnit.close(); } emfNamedPersistenceUnits.remove(persistenceUnitName); } } public static boolean seesJPA2() { return seesJPA2; } public static Map<String, String> getTestProperties() { if (ServerInfoHolder.isOnServer()) { return ServerInfoHolder.getTestProperties(); } else { return JUnitTestCaseHelper.getDatabaseProperties(); } } }