/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. 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:
//     Oracle - initial API and implementation from Oracle TopLink
//     11/17/2010-2.2 Guy Pelletier
//       - 329008: Support dynamic context creation without persistence.xml
//     01/23/2013-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     09/11/2017-2.1 Will Dazey
//       - 520387: multiple owning descriptors for an embeddable are not set
package org.eclipse.persistence.testing.framework.junit;

import java.io.StringWriter;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

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.rmi.PortableRemoteObject;

import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.databaseaccess.Platform;
import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.DefaultSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.sessions.Connector;
import org.eclipse.persistence.sessions.DefaultConnector;
import org.eclipse.persistence.sessions.JNDIConnector;
import org.eclipse.persistence.sessions.broker.SessionBroker;
import org.eclipse.persistence.sessions.server.ServerSession;
import org.eclipse.persistence.testing.framework.server.JEEPlatform;
import org.eclipse.persistence.testing.framework.server.ServerPlatform;
import org.eclipse.persistence.testing.framework.server.TestRunner;
import org.eclipse.persistence.testing.framework.server.TestRunner1;
import org.eclipse.persistence.testing.framework.server.TestRunner2;
import org.eclipse.persistence.testing.framework.server.TestRunner3;
import org.eclipse.persistence.testing.framework.server.TestRunner4;
import org.eclipse.persistence.testing.framework.server.TestRunner5;
import org.eclipse.persistence.testing.framework.server.TestRunner6;
import org.eclipse.persistence.transaction.JTA11TransactionController;

import junit.framework.TestCase;

/**
 * This is the superclass for all EclipseLink JUnit tests
 * Provides convenience methods for transactional access as well as to access
 * login information and to create any sessions required for setup.
 *
 * Assumes the existence of a test.properties file on the classpath that defines the
 * following properties:
 *
 * db.platform
 * db.user
 * db.pwd
 * db.url
 * db.driver
 *
 * If you are using the TestingBrowser, these properties come from the login panel instead.
 * If you are running the test in JEE the properties come from the server config.
 * This class should be used for all EntityManager operations to allow tests to be run in the server.
 */
public abstract class JUnitTestCase extends TestCase {

    private static Map<String, EntityManagerFactory> emfNamedPersistenceUnits = null;

    /** Default persistence unit name. */
    private static String DEFAULT_PU_NAME = "default";

    /** Determine if the test is running on a JEE server, or in JSE. */
    protected static Boolean isOnServer;

    /** Determine if the data-source is JTA, or non-JTA. */
    public static Boolean isJTA =true;

    /** Holds an information whether JTA 1.1 API is present. */
    protected final boolean isJTA11;

    /** Allow a JEE server platform to be set. */
    protected static ServerPlatform serverPlatform;

    /** Sets if the test should be run on the client or server. */
    public Boolean shouldRunTestOnServer;

    /** System variable to set the tests to run on the server. */
    public static final String RUN_ON_SERVER = "server.run";

    /** Persistence unit name associated with the test runner, null means single persistence unit */
    public String puName = null;

    static {
        emfNamedPersistenceUnits = new Hashtable();
    }

    protected static boolean isInitialzied;

    /** Allow OSGi specific behavior. */
    public static boolean isOSGi = false;

    /** Indicates whether SOP should be used */
    public static Boolean usesSOP;

    /** Indicates whether SOP should be recoverable. Ignored unless useSOP is true */
    public static Boolean isSOPRecoverable;

    /**
     * This is a hack to enable weaving in Spring tests.
     * The Spring agent does not load persistence units in premain
     * So it must be forced to do so before any domain classes are loaded,
     * otherwise weaving will not work.
     */
    public static void initializePlatform() {
        if (isInitialzied) {
            return;
        }
        ServerPlatform platform = getServerPlatform();
        if (platform != null) {
            platform.initialize();
        }
        isInitialzied = true;
    }

    /**
     * Check that JTA 1.1 API is present.
     *
     * @return value of {@code true} if {@code java:comp/TransactionSynchronizationRegistry}
     *         JNDI name is present or {@code false}  otherwise.
     */
    public static final boolean isJTA11() {
        Context context = null;
        try {
            context = new InitialContext();
            return (context.lookup(JTA11TransactionController.JNDI_TRANSACTION_SYNCHRONIZATION_REGISTRY) != null);
        } catch (NamingException ex) {
            AbstractSessionLog.getLog().log(SessionLog.FINER, "JTA 1.1 API was not found", null, false);
            return false;
        } finally {
            if (context != null) {
                try {
                    context.close();
                } catch (NamingException ex) {
                    AbstractSessionLog.getLog().log(SessionLog.WARNING, "NamingException when closing initial context: {0}", new String[] { ex.getMessage() }, false);
                }
            }
        }
    }

    /**
     * Lookup EJB by JNDI name.
     *
     * @param c EJB class.
     * @param jndi EJB JNDI name
     * @return EJB instance
     */
    public static <C> C lookupEJB(final Class<C> c, final String jndi) {
        Context context = null;
        try {
            context = new InitialContext();
            return c.cast(context.lookup(jndi));
        } catch (NamingException ex) {
            AbstractSessionLog.getLog().log(SessionLog.WARNING, "NamingException when looking up {0} {1}", new String[] { jndi, ex.getMessage() }, false);
            return null;
        } finally {
            if (context != null) {
                try {
                    context.close();
                } catch (NamingException ex) {
                    AbstractSessionLog.getLog().log(SessionLog.WARNING, "NamingException when closing initial context: {0}", new String[] { ex.getMessage() }, false);
                }
            }
        }
    }

    public JUnitTestCase() {
        super();
        isJTA11 = isJTA11();
        initializePlatform();
    }

    public JUnitTestCase(String name) {
        super(name);
        isJTA11 = isJTA11();
        initializePlatform();
    }

    /**
     * Return the name of the persistence context this test uses.
     * This allow a subclass test to set this only in one place.
     */
    public String getPersistenceUnitName() {
        return DEFAULT_PU_NAME;
    }

    /**
     * Return if the test should run on the server.
     */
    public boolean shouldRunTestOnServer() {
        if (shouldRunTestOnServer == null) {
            String property = System.getProperty(RUN_ON_SERVER);
            if (property != null) {
                shouldRunTestOnServer = property.toUpperCase().equals("TRUE");
            } else {
                shouldRunTestOnServer = false;
            }
        }
        return shouldRunTestOnServer;
    }

    /**
     * Return if the data-source is JTA or not.
     */
    public static boolean isJTA() {
        String property =System.getProperty("is.JTA");
        if (property != null && property.toUpperCase().equals("FALSE")) {
            isJTA = false;
        } else {
            isJTA = true;
        }
        return isJTA;
    }

    public boolean isWeavingForChangeTrackingEnabled() {
        return isWeavingForChangeTrackingEnabled(getPersistenceUnitName());
    }

    public boolean isWeavingForChangeTrackingEnabled(String persistenceUnitName) {
        Object changeTrackingWeaving = JUnitTestCase.getDatabaseSession(persistenceUnitName).getProperty("eclipselink.weaving.changetracking");

        if (changeTrackingWeaving == null) {
            changeTrackingWeaving = System.getProperty("eclipselink.weaving.changetracking");
        }

        if ("false".equals(changeTrackingWeaving)) {
            return false;
        }

        return true;
    }

    public boolean isWeavingForFetchGroupsEnabled() {
        return isWeavingForFetchGroupsEnabled(getPersistenceUnitName());
    }

    public boolean isWeavingForFetchGroupsEnabled(String persistenceUnitName) {
        Object fetchGroupsWeaving = JUnitTestCase.getDatabaseSession(persistenceUnitName).getProperty("eclipselink.weaving.fetchgroups");

        if (fetchGroupsWeaving == null) {
            fetchGroupsWeaving = System.getProperty("eclipselink.weaving.fetchgroups");
        }

        if ("false".equals(fetchGroupsWeaving)) {
            return false;
        }

        return true;
    }

    /**
     * Return if the tests were run using weaving, agent or static.
     */
    public boolean isWeavingEnabled() {
        return isWeavingEnabled(getPersistenceUnitName());
    }

    /**
     * Return if the tests were run using weaving, agent or static.
     */
    public static boolean isWeavingEnabled(String persistenceUnitName) {
        return System.getProperty("TEST_NO_WEAVING") == null;
    }

    /**
     * Return if the test is running against JPA 1.0. Any test that uses 2.0
     * functionality should call this method to avoid been run against a 1.0
     * container.
     */
    public static boolean isJPA10() {
        try {
            LockModeType.valueOf("NONE");
        } catch (Exception e) {
           return true;
        }
        return false;
    }

    /**
     * Return if the test is running on a JEE server, or in JSE.
     */
    public static boolean isOnServer() {
        if (isOnServer == null) {
            if (System.getProperty("TEST_SERVER_PLATFORM") != null) {
                isOnServer = true;
            } else {
                isOnServer = false;
            }
        }
        return isOnServer;
    }

    /**
     * Set if the test is running on a JEE server, or in JSE.
     */
    public static void setIsOnServer(boolean value) {
        isOnServer = value;
    }

    /**
     * Return if the Hermes parser is being used for JPQL.
     */
    public boolean isHermesParser() {
        return getDatabaseSession().getQueryBuilder().getClass().getName().indexOf("Hermes") != -1;
    }

    /**
     * Indicates whether SOP should be used.
     */
    public static boolean usesSOP() {
        if (usesSOP == null) {
            usesSOP = Boolean.valueOf(System.getProperty("sop"));
        }
        return usesSOP;
    }

    /**
     * Indicates whether SOP should be recoverable. Ignored unless useSOP is true.
     */
    public static boolean isSOPRecoverable() {
        if (isSOPRecoverable == null) {
            isSOPRecoverable = Boolean.valueOf(System.getProperty("sop.recoverable"));
        }
        return isSOPRecoverable;
    }

    /**
     * Return the server platform if running in JEE.
     */
    public static ServerPlatform getServerPlatform() {
        if (serverPlatform == null) {
            String platformClass = System.getProperty("TEST_SERVER_PLATFORM");
            if (platformClass == null) {
                serverPlatform = new JEEPlatform();
            } else {
                try {
                    serverPlatform = (ServerPlatform)Class.forName(platformClass).newInstance();
                } catch (Exception notFound) {
                    throw new RuntimeException(notFound);
                }
            }
        }
        return serverPlatform;
    }

    /**
     * Set the server platform, this should be done by the test executor
     * when running a test in the server.
     */
    public static void setServerPlatform(ServerPlatform value) {
        serverPlatform = value;
    }

    public void clearCache() {
        try {
            getDatabaseSession().getIdentityMapAccessor().initializeAllIdentityMaps();
        } catch (Exception ex) {
            throw new RuntimeException("An exception occurred trying clear the database session cache.", ex);
        }
    }

    public void clearServerSessionCache() {
        try {
            getServerSession().getIdentityMapAccessor().initializeAllIdentityMaps();
        } catch (Exception ex) {
            throw new RuntimeException("An exception occurred trying clear the server session cache.", ex);
        }
    }

    public static void clearCache(String persistenceUnitName) {
        try {
            getDatabaseSession(persistenceUnitName).getIdentityMapAccessor().initializeAllIdentityMaps();
        } catch (Exception ex) {
            throw new RuntimeException("An exception occurred trying clear the database session cache.", ex);
        }
    }

    public static void clearServerSessionCache(String persistenceUnitName) {
        try {
            getServerSession(persistenceUnitName).getIdentityMapAccessor().initializeAllIdentityMaps();
        } catch (Exception ex) {
            throw new RuntimeException("An exception occurred trying clear the server session cache.", ex);
        }
    }

    /**
     * Close the entity manager.
     * This allows the same code to be used on the server where managed entity managers are not closed.
     */
    public void closeEntityManager(EntityManager entityManager) {
        if (!isOnServer()) {
            entityManager.close();
        }
    }

    /**
     * Close the entity manager.
     * If a transaction is active, then roll it back.
     */
    public void closeEntityManagerAndTransaction(EntityManager entityManager) {
        if (isTransactionActive(entityManager)) {
            rollbackTransaction(entityManager);
        }
        closeEntityManager(entityManager);
    }

    /**
     * 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 (isOnServer() && isJTA()) {
            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 (isOnServer() && isJTA()) {
            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,
     * and will join the EntityManager to the transaction.
     */
    public void beginTransaction(EntityManager entityManager) {
        if (isOnServer() && isJTA()) {
            getServerPlatform().beginTransaction();
            //bug 404294 - the EM is required to join the transaction to be able to
            //    use transactions started after it was created.
            getServerPlatform().joinTransaction(entityManager);
        } 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 (isOnServer() && isJTA()) {
            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 (isOnServer() && isJTA()) {
            getServerPlatform().rollbackTransaction();
        } else {
            entityManager.getTransaction().rollback();
        }
    }

    /**
     * Create a new entity manager for the test suites default persistence unit.
     * If in JEE this will create or return the active managed entity manager.
     */
    public EntityManager createEntityManager() {
        if (isOnServer() && isJTA()) {
            return getServerPlatform().getEntityManager(getPersistenceUnitName());
        } else {
            return getEntityManagerFactory(getPersistenceUnitName(), getPersistenceProperties()).createEntityManager();
        }
    }

    /**
     * Create a new entity manager for the persistence unit.
     * If in JEE this will create or return the active managed entity manager.
     */
    public static EntityManager createEntityManager(String persistenceUnitName) {
        if (isOnServer() && isJTA()) {
            return getServerPlatform().getEntityManager(persistenceUnitName);
        } else {
            return getEntityManagerFactory(persistenceUnitName).createEntityManager();
        }
    }

    /**
     * Create a new entity manager for the persistence unit using the properties
     * and a default persistence unit name..
     * 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 EntityManager createEntityManager(Map properties) {
        if (isOnServer() && isJTA()) {
            return getServerPlatform().getEntityManager(getPersistenceUnitName());
        } else {
            return getEntityManagerFactory(getPersistenceUnitName(), properties).createEntityManager(properties);
        }
    }

    /**
     * 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 properties) {
        return createEntityManager(persistenceUnitName, properties, null);
    }

    /**
     * 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 properties, List<ClassDescriptor> descriptors) {
        if (isOnServer() && isJTA()) {
            return getServerPlatform().getEntityManager(persistenceUnitName);
        } else {
            return getEntityManagerFactory(persistenceUnitName, properties, descriptors).createEntityManager();
        }
    }

    public DatabaseSessionImpl getDatabaseSession() {
        return ((org.eclipse.persistence.jpa.JpaEntityManager)getEntityManagerFactory().createEntityManager()).getDatabaseSession();
    }

    public static DatabaseSessionImpl getDatabaseSession(String persistenceUnitName) {
        return ((org.eclipse.persistence.jpa.JpaEntityManager)getEntityManagerFactory(persistenceUnitName).createEntityManager()).getDatabaseSession();
    }

    public SessionBroker getSessionBroker() {
        return ((org.eclipse.persistence.jpa.JpaEntityManager)getEntityManagerFactory().createEntityManager()).getSessionBroker();
    }

    public static SessionBroker getSessionBroker(String persistenceUnitName) {
        return ((org.eclipse.persistence.jpa.JpaEntityManager)getEntityManagerFactory(persistenceUnitName).createEntityManager()).getSessionBroker();
    }

    public static ServerSession getServerSession() {
        return ((org.eclipse.persistence.jpa.JpaEntityManager)getEntityManagerFactory("default").createEntityManager()).getServerSession();
    }

    public static ServerSession getServerSession(String persistenceUnitName) {
        return ((org.eclipse.persistence.jpa.JpaEntityManager)getEntityManagerFactory(persistenceUnitName).createEntityManager()).getServerSession();
    }

    public static ServerSession getServerSession(String persistenceUnitName, Map properties) {
        return ((org.eclipse.persistence.jpa.JpaEntityManager)getEntityManagerFactory(persistenceUnitName, properties).createEntityManager()).getServerSession();
    }

    public ServerSession getPersistenceUnitServerSession() {
        return getServerSession(getPersistenceUnitName());
    }

    public Map getPersistenceProperties() {
        return JUnitTestCaseHelper.getDatabaseProperties(getPersistenceUnitName());
    }

    public static EntityManagerFactory getEntityManagerFactory(String persistenceUnitName) {
        return getEntityManagerFactory(persistenceUnitName,  JUnitTestCaseHelper.getDatabaseProperties(persistenceUnitName), null);
    }

    public static EntityManagerFactory getEntityManagerFactory(String persistenceUnitName, Map properties) {
        return getEntityManagerFactory(persistenceUnitName, properties, null);
    }

    public static EntityManagerFactory getEntityManagerFactory(String persistenceUnitName, Map properties, List<ClassDescriptor> descriptors) {
        //properties.put("eclipselink.tuning", "ExaLogic");
        if (isOnServer()) {
            return getServerPlatform().getEntityManagerFactory(persistenceUnitName);
        } else {
            // Set class loader for OSGi testing.
            if (isOSGi && (properties.get(PersistenceUnitProperties.CLASSLOADER) == null)) {
                try {
                    properties.put(PersistenceUnitProperties.CLASSLOADER, JUnitTestCase.class.getClassLoader());
                } catch (Exception ignore) {
                    System.out.println(ignore);
                }
            }

            EntityManagerFactory emfNamedPersistenceUnit = emfNamedPersistenceUnits.get(persistenceUnitName);

            if (emfNamedPersistenceUnit == null) {

                // force closing of other persistence units to avoid Sybase running out of connections.
                if (!persistenceUnitName.equals("default")) {
                    if (emfNamedPersistenceUnits.containsKey("default") && (getServerSession().getPlatform().isSybase() || getServerSession().getPlatform().isMySQL())) {
                        Iterator<Map.Entry<String, EntityManagerFactory>> factories = emfNamedPersistenceUnits.entrySet().iterator();
                        while (factories.hasNext()) {
                            Map.Entry<String, EntityManagerFactory> entry = factories.next();
                            if (!entry.getKey().equals("default") && !entry.getKey().equals(persistenceUnitName)) {
                                System.out.println("Closing factory: " + entry.getKey());
                                entry.getValue().close();
                                factories.remove();
                            }
                        }
                    }
                }

                if (descriptors == null) {
                    emfNamedPersistenceUnit = Persistence.createEntityManagerFactory(persistenceUnitName, properties);
                } else {
                    emfNamedPersistenceUnit = new EntityManagerFactoryImpl(persistenceUnitName, properties, descriptors);
                }

                emfNamedPersistenceUnits.put(persistenceUnitName, emfNamedPersistenceUnit);

                // Force uppercase for Postgres. - no longer needed with fix for 299926: Case insensitive table / column matching
            }

            return emfNamedPersistenceUnit;
        }
    }

    public EntityManagerFactory getEntityManagerFactory() {
        return getEntityManagerFactory(getPersistenceUnitName());
    }

    public EntityManagerFactory getEntityManagerFactory(Map properties) {
        return getEntityManagerFactory(getPersistenceUnitName(), properties);
    }

    public boolean doesEntityManagerFactoryExist() {
        return doesEntityManagerFactoryExist(getPersistenceUnitName());
    }

    public static boolean doesEntityManagerFactoryExist(String persistenceUnitName) {
        EntityManagerFactory emf = emfNamedPersistenceUnits.get(persistenceUnitName);
        return emf != null && emf.isOpen();
    }

    public void closeEntityManagerFactory() {
        closeEntityManagerFactory(getPersistenceUnitName());
    }

    public static void closeEntityManagerFactory(String persistenceUnitName) {
        EntityManagerFactory emfNamedPersistenceUnit = emfNamedPersistenceUnits.get(persistenceUnitName);
        if(emfNamedPersistenceUnit != null) {
            if(emfNamedPersistenceUnit.isOpen()) {
                emfNamedPersistenceUnit.close();
            }
            emfNamedPersistenceUnits.remove(persistenceUnitName);
        }
    }

    public Platform getPlatform() {
        return getPlatform(getPersistenceUnitName());
    }

    public Platform getPlatform(Class cls) {
        return getPlatform(getPersistenceUnitName(), cls);
    }

    public static Platform getPlatform(String puName) {
        return getDatabaseSession(puName).getPlatform();
    }

    public static Platform getPlatform(String puName, Class cls) {
        return getDatabaseSession(puName).getPlatform(cls);
    }

    @Override
    public void setUp() {
    }

    @Override
    public void tearDown() {
    }

    /**
     * Used to output a warning.  This does not fail the test, but provides output for someone to review.
     */
    public static void warning(String warning) {
        System.out.println("WARNING: " + warning);
    }

    /**
     * Intercept test case invocation and delegate it to a remote server.
     */
    @Override
    public void runBare() throws Throwable {
        if (shouldRunTestOnServer()) {
            runBareClient();
        } else {
            super.runBare();
        }
    }

    /**
     * Runs a test by delegating method invocation to the application server.
     */
    public void runBareClient() throws Throwable {
        Properties properties = new Properties();
        String url = System.getProperty("server.url");
        if (url == null) {
            fail("System property 'server.url' must be set.");
        }
        properties.put("java.naming.provider.url", url);
        Context context = new InitialContext(properties);
        Throwable exception = null;
        if (puName == null) {
            String testrunner = System.getProperty("server.testrunner");
            if (testrunner == null) {
                fail("System property 'server.testrunner' must be set.");
            }
            TestRunner runner = (TestRunner) PortableRemoteObject.narrow(context.lookup(testrunner), TestRunner.class);
            exception = runner.runTest(getClass().getName(), getName(), getServerProperties());
        }else{
            int i = puName.charAt(8) - 48;
            String testRunner[] = new String[7];
            for (int j=1; j<=6; j++) {
                String serverRunner = "server.testrunner" + j;
                testRunner[j] = System.getProperty(serverRunner);
                if (testRunner[j] == null && j < 6) {
                    fail("System property 'server.testrunner'" + j + " must be set.");
                }
            }
            switch (i)
            {
            case 1:
                TestRunner1 runner1 = (TestRunner1) PortableRemoteObject.narrow(context.lookup(testRunner[1]), TestRunner1.class);
                exception = runner1.runTest(getClass().getName(), getName(), getServerProperties());
                break;
            case 2:
                TestRunner2 runner2 = (TestRunner2) PortableRemoteObject.narrow(context.lookup(testRunner[2]), TestRunner2.class);
                exception = runner2.runTest(getClass().getName(), getName(), getServerProperties());
                break;
            case 3:
                TestRunner3 runner3 = (TestRunner3) PortableRemoteObject.narrow(context.lookup(testRunner[3]), TestRunner3.class);
                exception = runner3.runTest(getClass().getName(), getName(), getServerProperties());
                break;
            case 4:
                TestRunner4 runner4 = (TestRunner4) PortableRemoteObject.narrow(context.lookup(testRunner[4]), TestRunner4.class);
                exception = runner4.runTest(getClass().getName(), getName(), getServerProperties());
                break;
            case 5:
                TestRunner5 runner5 = (TestRunner5) PortableRemoteObject.narrow(context.lookup(testRunner[5]), TestRunner5.class);
                exception = runner5.runTest(getClass().getName(), getName(), getServerProperties());
                break;
            case 6:
                TestRunner6 runner6 = (TestRunner6) PortableRemoteObject.narrow(context.lookup(testRunner[6]), TestRunner6.class);
                exception = runner6.runTest(getClass().getName(), getName(), getServerProperties());
                break;
            default:
                break;
            }
        }
        if (exception != null) {
            throw exception;
        }
    }

    public void runBareServer() throws Throwable {
        setIsOnServer(true);
        super.runBare();
    }

    /**
     * Used by subclasses to pass any properties into the
     * server's vm.  Should be used with caution.
     */
    protected Properties getServerProperties() {
        return null;
    }

    /**
     * Verifies that the object was merged to the cache, and written to the database correctly.
     */
    public void verifyObject(Object writtenObject) {
        verifyObject(writtenObject, getPersistenceUnitName());
    }

    /**
     * Verifies that the object was merged to the cache, and written to the database correctly.
     */
    public static void verifyObject(Object writtenObject, String persistenceUnit) {
        Object readObject = getDatabaseSession(persistenceUnit).readObject(writtenObject);
        if (!getDatabaseSession(persistenceUnit).compareObjects(readObject, writtenObject)) {
            fail("Object: " + readObject + " does not match object that was written: " + writtenObject + ". See log (on finest) for what did not match.");
        }
    }

    /**
     * Verifies the object in a new EntityManager.
     */
    public void verifyObjectInEntityManager(Object writtenObject) {
        verifyObjectInEntityManager(writtenObject, getPersistenceUnitName());
    }

    /**
     * Verifies the object in a new EntityManager.
     */
    public void verifyObjectInEntityManager(Object writtenObject, String persistenceUnit) {
        EntityManager em = createEntityManager(persistenceUnit);
        try {
            Object readObject = em.find(writtenObject.getClass(), getServerSession(persistenceUnit).getId(writtenObject));
            if (!getServerSession(persistenceUnit).compareObjects(readObject, writtenObject)) {
                fail("Object: " + readObject + " does not match object that was written: " + writtenObject + ". See log (on finest) for what did not match.");
            }
        } finally {
            closeEntityManager(em);
        }
    }

    /**
     * Verifies that the object was merged to the cache, and written to the database correctly.
     */
    public void verifyObjectInCacheAndDatabase(Object writtenObject) {
        verifyObjectInCacheAndDatabase(writtenObject, getPersistenceUnitName());
    }

    /**
     * Verifies that the object was merged to the cache, and written to the database correctly.
     */
    public static void verifyObjectInCacheAndDatabase(Object writtenObject, String persistenceUnit) {
        AbstractSession dbs = getDatabaseSession(persistenceUnit);
        Object readObject = dbs.readObject(writtenObject);
        if (!dbs.compareObjects(readObject, writtenObject)) {
            SessionLog oldLog = dbs.getSessionLog();
            dbs.setSessionLog(new DefaultSessionLog());
            dbs.setLogLevel(SessionLog.FINEST);
            StringWriter newLog = new StringWriter();
            dbs.setLog(newLog);
            dbs.compareObjects(readObject, writtenObject);
            dbs.setSessionLog(oldLog);
            fail("Object from cache: " + readObject + " does not match object that was written: " + writtenObject + ". " + newLog);
        }
        dbs.getIdentityMapAccessor().initializeAllIdentityMaps();
        readObject = dbs.readObject(writtenObject);
        if (!dbs.compareObjects(readObject, writtenObject)) {
            SessionLog oldLog = dbs.getSessionLog();
            dbs.setSessionLog(new DefaultSessionLog());
            dbs.setLogLevel(SessionLog.FINEST);
            StringWriter newLog = new StringWriter();
            dbs.setLog(newLog);
            dbs.compareObjects(readObject, writtenObject);
            dbs.setSessionLog(oldLog);
            fail("Object from database: " + readObject + " does not match object that was written: " + writtenObject + ". " + newLog);
        }
    }

    /**
     * Compare objects.
     */
    public void compareObjects(Object obj1, Object obj2) {
        compareObjects(obj1, obj2, getPersistenceUnitName());
    }

    /**
     * Compare objects.
     */
    public static void compareObjects(Object obj1, Object obj2, String persistenceUnit) {
        AbstractSession dbs = getDatabaseSession(persistenceUnit);
        if (!dbs.compareObjects(obj1, obj2)) {
            fail("Objects " + obj1 + " and " + obj2 + " are not equal. See log (on finest) for what did not match.");
        }
    }

    /**
     * Generic persist test.
     */
    public void verifyPersist(Object object) {
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);
            em.persist(object);
            commitTransaction(em);
            beginTransaction(em);
            verifyObjectInCacheAndDatabase(object);
            rollbackTransaction(em);
            closeEntityManager(em);
        } catch (RuntimeException exception) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            throw exception;
        }
    }

    /**
     * Generic remove test.
     */
    public void verifyPersistAndRemove(Object object) {
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);
            em.persist(object);
            commitTransaction(em);
            closeEntityManager(em);

            em = createEntityManager();
            beginTransaction(em);
            object = em.find(object.getClass(), getServerSession(getPersistenceUnitName()).getId(object));
            em.remove(object);
            commitTransaction(em);
            verifyDelete(object);
            closeEntityManager(em);
        }  catch (RuntimeException exception) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            throw exception;
        }
    }

    /**
     * Verifies that the object was deleted from the database correctly.
     */
    public void verifyDelete(Object writtenObject) {
        verifyDelete(writtenObject, getPersistenceUnitName());
    }

    /**
     * Verifies that the object was deleted from the database correctly.
     */
    public void verifyDelete(Object writtenObject, String persistenceUnit) {
        AbstractSession dbs = getDatabaseSession(persistenceUnit);
        boolean ok;
        if (dbs.isServerSession()) {
            ok = ((ServerSession)dbs).acquireClientSession().verifyDelete(writtenObject);
        } else if (dbs.isSessionBroker()) {
            ok = ((SessionBroker)dbs).acquireClientSessionBroker().verifyDelete(writtenObject);
        } else {
            ok = dbs.verifyDelete(writtenObject);
        }
        if (!ok) {
            fail("Object not deleted from the database correctly: " + writtenObject);
        }
    }

    /**
     * Allow printing off stack traces for exceptions that cause test failures when the session log level is set appropriately.
     * Logs at at the warning level
     */
    public void logThrowable(Throwable exception){
        getDatabaseSession().getSessionLog().logThrowable(SessionLog.WARNING, exception);
    }

    /**
     * Return if pessimistic locking/select for update is supported for this test platform.
     * Currently testing supports select for update on Oracle, MySQL, SQLServer, TimesTen.
     * Some of the other platforms may have some support for select for update, but the databases we test with
     * for these do not have sufficient support to pass the tests.
     * TODO: Need to recheck tests on DB2 as it has some support for this.
     * Derby has some support, but does not work with joins (2008-12-01).
     */
    public boolean isSelectForUpateSupported(){
        return isSelectForUpateSupported(getPersistenceUnitName());
    }

    public static boolean isSelectForUpateSupported(String puName) {
        AbstractSession dbSession = getDatabaseSession(puName);
        if (dbSession.isBroker()) {
            for (AbstractSession memberSession : ((SessionBroker)dbSession).getSessionsByName().values()) {
                if (!isSelectForUpateSupported(memberSession.getPlatform())) {
                    return false;
                }
            }
            return true;
        } else {
            return isSelectForUpateSupported(dbSession.getPlatform());
        }
    }

    public static boolean isSelectForUpateSupported(DatabasePlatform platform) {
        // DB2, Derby, Symfoware (bug 304903) and Firebird support pessimistic locking only for a single-table queries.
        // PostgreSQL supports for update, but not on outerjoins, which the test uses.
        // H2 supports pessimistic locking, but has table lock issues with multiple connections used in the tests.
        if (platform.isFirebird() || platform.isH2() || platform.isHSQL() || platform.isAccess() || platform.isSQLAnywhere() || platform.isDerby() || platform.isPostgreSQL() || platform.isSymfoware()) {
            warning("This database does not support FOR UPDATE.");
            return false;
        }
        return true;
    }

    /**
     * @return true if database supports pessimistic write lock false other wise
     */
    public boolean isPessimisticWriteLockSupported() {
        return isPessimisticWriteLockSupported(getPersistenceUnitName());
    }

    public static boolean isPessimisticWriteLockSupported(String puName) {
        AbstractSession dbSession = getDatabaseSession(puName);
        if (dbSession.isBroker()) {
            for(AbstractSession memberSession : ((SessionBroker)dbSession).getSessionsByName().values()) {
                if (!isPessimisticWriteLockSupported(memberSession.getPlatform())) {
                    return false;
                }
            }
            return true;
        } else {
            return isPessimisticWriteLockSupported(dbSession.getPlatform());
        }
    }

    public static boolean isPessimisticWriteLockSupported(DatabasePlatform platform) {
        if (platform.isSybase()) { //Sybase supports getting Pessimistic Read locks but does not support getting Perssimistic Write locks
            warning("This database does not support Pessimistic Write Lock.");
            return false;
        }
        return true;
    }


    /**
     * Return if pessimistic locking/select for update nowait is supported for this test platform.
     * Currently testing supports nowait on Oracle, SQLServer.
     * PostgreSQL also supports NOWAIT, but doesn't support the outer joins used in the tests.
     */
    public static boolean isSelectForUpateNoWaitSupported(String puName) {
        AbstractSession dbSession = getDatabaseSession(puName);
        if (dbSession.isBroker()) {
            for (AbstractSession memberSession : ((SessionBroker)dbSession).getSessionsByName().values()) {
                if (!isSelectForUpateNoWaitSupported(memberSession.getPlatform())) {
                    return false;
                }
            }
            return true;
        } else {
            return isSelectForUpateNoWaitSupported(dbSession.getPlatform());
        }
    }
    public boolean isSelectForUpateNoWaitSupported(){
        return isSelectForUpateNoWaitSupported(getPersistenceUnitName());
    }

    public static boolean isSelectForUpateNoWaitSupported(Platform platform) {
        if (platform.isOracle() || platform.isSQLServer()) {
            return true;
        }
        warning("This database does not support NOWAIT.");
        return false;
    }

    public static boolean supportsSequenceObjects(String puName) {
        DatabasePlatform platform = getDatabaseSession(puName).getPlatform();
        return platform.supportsSequenceObjects();
    }

    public boolean supportsSequenceObjects() {
        DatabasePlatform platform = getDatabaseSession(getPersistenceUnitName()).getPlatform();
        return platform.supportsSequenceObjects();
    }

    /**
     * Return if stored procedures are supported for the database platform for the test database.
     */
    public boolean supportsStoredProcedures(){
        return supportsStoredProcedures(getPersistenceUnitName());
    }

    public static boolean supportsStoredProcedures(String puName) {
        DatabasePlatform platform = getDatabaseSession(puName).getPlatform();
        // PostgreSQL has some level of support for "stored functions", but output parameters do not work as of 8.2.
        // Sybase supports stored procedures, but has issues with output parameters and transaction mode (INOUT and chaining).
        // TODO: DB2 should be in this list.
        if (platform.isOracle() || platform.isMySQL() || platform.isSQLServer()) {
            return true;
        }

        warning("This database does not support stored procedure creation.");
        return false;
    }

    /**
     * Return if stored functions are supported for the database platform for the test database.
     */
    public boolean supportsStoredFunctions(){
        return supportsStoredFunctions(getPersistenceUnitName());
    }

    public static boolean supportsStoredFunctions(String puName) {
        DatabasePlatform platform = getDatabaseSession(puName).getPlatform();
        // PostgreSQL has some level of support for "stored functions", but output parameters do not work as of 8.2.
        // TODO: DB2 should be in this list.
        if (platform.isOracle() || platform.isMySQL()) {
            return true;
        }
        warning("This database does not support stored function creation.");
        return false;
    }

    public void setPuName(String name){
        puName = name;
    }

    /**
     * Indicates whether two sessions are connected to the same db
     */
    public static boolean usingTheSameDatabase(AbstractSession session1, AbstractSession session2) {
        Connector conn1 = session1.getLogin().getConnector();
        Connector conn2 = session2.getLogin().getConnector();
        if (conn1 instanceof DefaultConnector && conn2 instanceof DefaultConnector) {
            return ((DefaultConnector)conn1).getDatabaseURL().equals(((DefaultConnector)conn2).getDatabaseURL());
        } else if (conn1 instanceof JNDIConnector && conn2 instanceof JNDIConnector) {
            String name1 = ((JNDIConnector)conn1).getName();
            String name2 = ((JNDIConnector)conn2).getName();
            if (name1 != null && name1.equals(name2)) {
                return true;
            }
            return ((JNDIConnector)conn1).getDataSource().equals(((JNDIConnector)conn2).getDataSource());
        }
        return false;
    }
}
