blob: 530e6317aa41b2ead93b8fcbf91ab9c88e87bc6b [file] [log] [blame]
/*
* Copyright (c) 2005, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2015 SAP. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// 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 jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.LockModeType;
import jakarta.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");
evictClassMethod.invoke(cache);
} 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 static void verifyEquals(Object expected, Object actual, String msg) {
Assert.assertEquals(msg, expected, actual);
}
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 = 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 = 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();
}
}
}