/*
 * 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:
//     05/28/2008-1.0M8 Andrei Ilitchev.
//       - New file introduced for bug 224964: Provide support for Proxy Authentication through JPA.
package org.eclipse.persistence.testing.tests.jpa.proxyauthentication;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import javax.sql.DataSource;
import jakarta.transaction.TransactionManager;

import org.eclipse.persistence.config.ExclusiveConnectionMode;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.jpa.EntityManagerImpl;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.JpaEntityManager;
import org.eclipse.persistence.jpa.JpaHelper;
import org.eclipse.persistence.platform.server.glassfish.GlassfishPlatform;
import org.eclipse.persistence.platform.server.wls.WebLogicPlatform;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.JNDIConnector;
import org.eclipse.persistence.sessions.server.ServerSession;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCaseHelper;
import org.eclipse.persistence.testing.models.jpa.proxyauthentication.Employee;
import org.eclipse.persistence.testing.models.jpa.proxyauthentication.PhoneNumber;
import org.eclipse.persistence.testing.models.jpa.proxyauthentication.PhoneNumberPK;
import org.eclipse.persistence.testing.tests.proxyauthentication.thin.ProxyAuthenticationUsersAndProperties;
import org.eclipse.persistence.transaction.JTATransactionController;

import junit.framework.Test;
import junit.framework.TestSuite;
import oracle.jdbc.OracleConnection;

/**
 * TestSuite to verifying that connectionUser(PAS_CONN) and proxyUser(PAS_PROXY) are used as expected.
 * See also comment in ProxyAuthenticationUsersAndProperties.
 * To run this test suite several users should be setup in the Oracle database,
 * to setup Proxy Authentication users in Oracle db, need to execute in sqlPlus or EnterpriseManager
     * (sql in the following example uses default names):
    1 - connect sys/password as sysdba
        drop user PAS_CONN cascade;
        drop user PAS_PROXY cascade;

    2 - Create connectionUser:
        create user PAS_CONN identified by pas_conn;
        grant connect to PAS_CONN;
        grant resource to PAS_CONN;

    3 - Create proxyUsers:
        create user PAS_PROXY identified by pas_proxy;
        grant connect to PAS_PROXY;
        grant resource to PAS_PROXY;

    4.- Grant proxyUsers connection through connUser
        alter user PAS_PROXY grant connect through PAS_CONN;
        commit;

    5.- Create JPA_PROXY_EMPLOYEE and PROXY_EMPLOYEE_SEQ tables against PAS_CONN user
        CONNECT PAS_CONN/pas_conn;
        DROP TABLE JPA_PROXY_EMPLOYEE;
        CREATE TABLE JPA_PROXY_EMPLOYEE (EMP_ID NUMBER(15) NOT NULL, F_NAME VARCHAR2(40) NULL, L_NAME VARCHAR2(40) NULL, PRIMARY KEY (EMP_ID));
        DROP TABLE PROXY_EMPLOYEE_SEQ;
        CREATE TABLE PROXY_EMPLOYEE_SEQ (SEQ_NAME VARCHAR2(50) NOT NULL, SEQ_COUNT NUMBER(38) NULL, PRIMARY KEY (SEQ_NAME));
        INSERT INTO PROXY_EMPLOYEE_SEQ(SEQ_NAME, SEQ_COUNT) values ('PROXY_EMPLOYEE_SEQ', 1);
        COMMIT;

    6.- Create PROXY_PHONENUMBER table against PAS_PROXY user (you can also create these tables by login as PAS_CONN, and execute new PhoneNumberTableCreator().replaceTables(JUnitTestCase.getServerSession()); in testSetup())
        CONNECT PAS_PROXY/pas_proxy;
        ALTER TABLE PROXY_PHONENUMBER DROP CONSTRAINT FK_PROXY_PHONENUMBER_OWNER_ID;
        DROP TABLE PROXY_PHONENUMBER;
        CREATE TABLE PROXY_PHONENUMBER (OWNER_ID NUMBER(15) NOT NULL, TYPE VARCHAR2(15) NOT NULL, AREA_CODE VARCHAR2(3) NULL, NUMB VARCHAR2(8) NULL, PRIMARY KEY (OWNER_ID, TYPE));
        COMMIT;

    6.- Add object priviledges(ALTER, DELETE, INSERT, REFERENCE, SELECT, UPDATE, INDEX) to JPA_PROXY_EMPLOYEE and PROXY_EMPLOYEE_SEQ for PAS_PROXY user
        CONNECT SYS/PASSWORD as SYSDBA;
        GRANT ALTER ON PAS_CONN.JPA_PROXY_EMPLOYEE TO PAS_PROXY;
        GRANT DELETE ON PAS_CONN.JPA_PROXY_EMPLOYEE TO PAS_PROXY;
        GRANT INSERT ON PAS_CONN.JPA_PROXY_EMPLOYEE TO PAS_PROXY;
        GRANT SELECT ON PAS_CONN.JPA_PROXY_EMPLOYEE TO PAS_PROXY;
        GRANT UPDATE ON PAS_CONN.JPA_PROXY_EMPLOYEE TO PAS_PROXY;
        GRANT INDEX ON PAS_CONN.JPA_PROXY_EMPLOYEE TO PAS_PROXY;

        GRANT ALTER ON PAS_CONN.PROXY_EMPLOYEE_SEQ TO PAS_PROXY;
        GRANT DELETE ON PAS_CONN.PROXY_EMPLOYEE_SEQ TO PAS_PROXY;
        GRANT INSERT ON PAS_CONN.PROXY_EMPLOYEE_SEQ TO PAS_PROXY;
        GRANT SELECT ON PAS_CONN.PROXY_EMPLOYEE_SEQ TO PAS_PROXY;
        GRANT UPDATE ON PAS_CONN.PROXY_EMPLOYEE_SEQ TO PAS_PROXY;
        GRANT INDEX ON PAS_CONN.PROXY_EMPLOYEE_SEQ TO PAS_PROXY;
        COMMIT;
 */
public class ProxyAuthenticationServerTestSuite extends JUnitTestCase {
    private static Integer empId = null;
    private Employee proxyEmp = null;
    private PhoneNumber proxyPhone = null;
    private static final String PROXY_PU = "proxyauthentication";
    private static boolean shouldOverrideGetEntityManager = false;
    private static boolean shouldRunPureJdbcTests = false;
    private static boolean shouldCloseProxySessionOnRollback = false;
    private static ServerSession serverSession;

    public ProxyAuthenticationServerTestSuite(){
    }

    public ProxyAuthenticationServerTestSuite(String name){
        super(name);
    }

    public static Test suite() {
        TestSuite suite = new TestSuite();
        suite.setName("Proxy Authentication Test Suite");

        suite.addTest(new ProxyAuthenticationServerTestSuite("testSetup"));
        suite.addTest(new ProxyAuthenticationServerTestSuite("testCreateWithProxy"));
        suite.addTest(new ProxyAuthenticationServerTestSuite("testUpdateWithProxy"));
        suite.addTest(new ProxyAuthenticationServerTestSuite("testReadDeleteWithProxy"));
        suite.addTest(new ProxyAuthenticationServerTestSuite("testCreateWithOutProxy"));
        suite.addTest(new ProxyAuthenticationServerTestSuite("testFlushRollback"));
        suite.addTest(new ProxyAuthenticationServerTestSuite("testProxyIsInJTATransaction"));
        // Bug 323880 - "This is already a proxy session" exception on WLS 10.3.3 after explicitly rolling back the user transaction
        suite.addTest(new ProxyAuthenticationServerTestSuite("testJtaDataSource"));
        suite.addTest(new ProxyAuthenticationServerTestSuite("testNonJtaDataSource"));
        return suite;
    }

    public void testSetup() {
        // sets up all user names and properties used by the tests.
        ProxyAuthenticationUsersAndProperties.initialize();
        // verifies that all the users correctly setup in the db.
        serverSession = getServerSession(PROXY_PU, createConnProperties());
        String errorMsg = ProxyAuthenticationUsersAndProperties.verify(serverSession);
        if(errorMsg.length() > 0) {
            fail(errorMsg);
        }
        
        shouldOverrideGetEntityManager = shouldOverrideGetEntityManager();
        shouldCloseProxySessionOnRollback = shouldCloseProxySessionOnRollback();
        System.out.println("====the shouldOverrideGetEntityManager====" + shouldOverrideGetEntityManager);
        // currently only WLS 10.3.4 and later is known to fully support Oracle Proxy Authentication in both JTA and Non Jta cases.
        shouldRunPureJdbcTests = shouldRunPureJdbcTests();
        System.out.println("====the shouldRunPureJdbcTests====" + shouldRunPureJdbcTests);
        //new PhoneNumberTableCreator().replaceTables(JUnitTestCase.getServerSession(PROXY_PU));
        //new EmployeeTableCreator().replaceTables(JUnitTestCase.getServerSession(PROXY_PU));
        //getServerSession(PROXY_PU).executeNonSelectingSQL("update PROXY_EMPLOYEE_SEQ set SEQ_COUNT = 1 where SEQ_NAME='PROXY_EMPLOYEE_SEQ'");
    }

    /**
     * Tests creating Entity with proxy setting
     */
    public void testCreateWithProxy() throws Exception{
        proxyEmp  = new Employee();
        EntityManager em = createEntityManager_proxy(PROXY_PU);
        try {
            beginTransaction_proxy(em);
            proxyEmp.setFirstName("Guy");
            proxyEmp.setLastName("Pelletier");
            em.persist(proxyEmp);
            empId = proxyEmp.getId();

            proxyPhone = new PhoneNumber();
            proxyPhone.setAreaCode("61x");
            proxyPhone.setNumber("823-6262");
            proxyPhone.setOwner(proxyEmp);
            proxyPhone.setId(empId);
            proxyPhone.setType("Home");

            em.persist(proxyPhone);
            commitTransaction(em);
        } catch (Exception ex) {
            ex.printStackTrace();
            if (isTransactionActive(em)){
                rollbackTransaction_proxy(em);
            }
            throw ex;
        } finally {
            closeEntityManager(em);
        }

        EntityManager newEm = createEntityManager_proxy(PROXY_PU);
        try {
            beginTransaction_proxy(newEm);
            PhoneNumberPK pk = new PhoneNumberPK();
            pk.setId(empId);
            pk.setType("Home");
            PhoneNumber phone = newEm.find(PhoneNumber.class, pk);
            Employee emp = newEm.find(Employee.class, empId);
            compareObjects(emp, proxyEmp, phone, proxyPhone);
            //clearCache
            newEm.unwrap(JpaEntityManager.class).getDatabaseSession().getIdentityMapAccessor().initializeAllIdentityMaps();
            compareObjects(emp, proxyEmp, phone, proxyPhone);
            commitTransaction(newEm);
        } catch (Exception ex) {
            ex.printStackTrace();
            if (isTransactionActive(newEm)){
                rollbackTransaction_proxy(newEm);
            }
            throw ex;
        } finally {
            closeEntityManager(newEm);
        }

    }

    /**
     * Tests Read and Delete with proxy setting
     */
    public void testReadDeleteWithProxy() throws Exception{
        EntityManager em = createEntityManager_proxy(PROXY_PU);
        Employee readEmp = null;
        PhoneNumber readPhone = null;
        try {
            beginTransaction_proxy(em);
            PhoneNumberPK pk = new PhoneNumberPK();
            pk.setId(empId);
            pk.setType("Home");
            readPhone = em.find(PhoneNumber.class, pk);
            readEmp = readPhone.getOwner();
            em.remove(readEmp);
            em.remove(readPhone);
            commitTransaction(em);
        } catch (Exception ex) {
            ex.printStackTrace();
            if (isTransactionActive(em)){
                rollbackTransaction_proxy(em);
            }
            throw ex;
        } finally {
            closeEntityManager(em);
        }
    }

    /**
     * Tests Update with proxy setting
     */
    public void testUpdateWithProxy() throws Exception{
        EntityManager em = createEntityManager_proxy(PROXY_PU);
        try {
            beginTransaction_proxy(em);
            Query query = em.createQuery("SELECT e FROM PhoneNumber e");
            List<PhoneNumber> phoneNumbers = query.getResultList();
            for (PhoneNumber phoneNumber : phoneNumbers) {
                phoneNumber.setAreaCode("613");
                phoneNumber.getOwner();
            }
            commitTransaction(em);
        } catch (Exception ex) {
            ex.printStackTrace();
            if (isTransactionActive(em)){
                rollbackTransaction_proxy(em);
            }
            throw ex;
        } finally {
            closeEntityManager(em);
        }
    }

    /**
     * Tests create with out proxy setting, it should fail
     */
    public void testCreateWithOutProxy() throws Exception{
        Employee employee  = new Employee();
        EntityManager em = createEntityManager(PROXY_PU, createConnProperties());
        try {
            beginTransaction(em);
            employee.setFirstName("Guy");
            employee.setLastName("Pelletier");
            em.persist(employee);

            PhoneNumber homeNumber = new PhoneNumber();
            homeNumber.setAreaCode("61x");
            homeNumber.setNumber("823-6262");
            homeNumber.setOwner(employee);
            homeNumber.setType("Home");

            em.persist(homeNumber);
            empId = employee.getId();
            commitTransaction(em);
        } catch (Exception ex) {
            if (ex.getMessage().indexOf("ORA-00942: table or view does not exist") == -1){
                ex.printStackTrace();
                fail("it's not the right exception");
            }
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

    /**
     * Test verifies that after rollback is called connection returned to the pool is still usable.
     */
    public void testFlushRollback() throws Exception{
        System.out.println("====testFlushRollback begin");
        // create new object, persist it, flush, then rollback transaction
        EntityManager em = createEntityManager_proxy(PROXY_PU);
        try {
            beginTransaction_proxy(em);
            Employee employee  = new Employee();
            employee.setFirstName("FlushRollback");
            employee.setLastName("1");
            em.persist(employee);
            em.flush();
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction_proxy(em);
            }
            closeEntityManager(em);
        }

        // now do something with a new em
        //clearCache
        serverSession.getIdentityMapAccessor().initializeAllIdentityMaps();

        em = createEntityManager_proxy(PROXY_PU);
        // read
        em.createQuery("SELECT e FROM Employee e").getResultList();
        // write through proxy connection
        try {
            beginTransaction_proxy(em);
            Employee employee  = new Employee();
            employee.setFirstName("FlushRollback");
            employee.setFirstName("2");
            em.persist(employee);
            em.flush();
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction_proxy(em);
            }
        }
        // write through main connection - that's expected to fail with "table or view does not exist" exception
        try {
            beginTransaction(em);
            Employee employee  = new Employee();
            employee.setFirstName("FlushRollback");
            employee.setFirstName("3");
            em.persist(employee);
            em.flush();
        } catch (Exception ex) {
            if (ex.getMessage().indexOf("ORA-00942: table or view does not exist") == -1){
                ex.printStackTrace();
                fail("it's not the right exception");
            }
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            System.out.println("====testFlushRollback end");
        }
    }

    /**
     * Test verifies that proxy connection is managed by the active JTA transaction
     */
    public void testProxyIsInJTATransaction() throws Exception{
        System.out.println("====testProxyIsInJTATransactionn");
        EntityManager em = createEntityManager_proxy(PROXY_PU);
        // Glassfish runs into issues with the rollback with proxies.  Temporarily disable see bug 390021
        JpaEntityManager jpaem = JpaHelper.getEntityManager(em);
        if (GlassfishPlatform.class.isAssignableFrom(jpaem.getServerSession().getServerPlatform().getClass())){
            return;
        }
        // create new object, persist it, flush, then rollback transaction

        Employee employee = null;
        try {
            beginTransaction_proxy(em);
            employee  = new Employee();
            employee.setFirstName("ProxyIsInJTATransaction");
            employee.setLastName("1");
            em.persist(employee);
            em.flush();
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction_proxy(em);
            }
            closeEntityManager(em);
        }

        //clearCache
        serverSession.getIdentityMapAccessor().initializeAllIdentityMaps();

        Employee employeeRead = null;
        em = createEntityManager_proxy(PROXY_PU);
        try {
            beginTransaction_proxy(em);
            // read
            employeeRead = em.find(Employee.class, employee.getId());
            if (employeeRead != null) {
                // clean-up
                em.remove(employeeRead);
                commitTransaction(em);
                fail(employeeRead + " found in the db even though JTA transaction had rolled back");
            }
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction_proxy(em);
            }
            closeEntityManager(em);
            System.out.println("====testProxyIsInJTATransaction end");
        }
    }

    public void testJtaDataSource() throws Exception {
        if(!shouldRunPureJdbcTests) {
            System.out.println("Currently only WLS 10.3.4 and later is known to fully support Oracle Proxy Authentication in both JTA and Non Jta cases.");
            return;
        }
        if(!serverSession.getLogin().shouldUseExternalTransactionController()) {
            throw new RuntimeException("Test problem: jta data source is required");
        }
        System.out.println("====testJtaDataSource begin");
//        Context context = new InitialContext();
//        TransactionManager mngr = (TransactionManager)context.lookup("weblogic.transaction.TransactionManager");
        // Eclipselink session is used only to obtain TransactionManager from the application server.
        TransactionManager mngr = ((JTATransactionController)serverSession.getExternalTransactionController()).getTransactionManager();
//        DataSource jtaDs = (DataSource)context.lookup("jdbc/EclipseLinkDS");
        // Eclipselink session is used only to obtain jta data source from the application server.
        DataSource jtaDs = ((JNDIConnector)serverSession.getLogin().getConnector()).getDataSource();
        Properties props = new Properties();
        props.setProperty(OracleConnection.PROXY_USER_NAME, ProxyAuthenticationUsersAndProperties.proxyUser);
        props.setProperty(OracleConnection.PROXY_USER_PASSWORD, ProxyAuthenticationUsersAndProperties.proxyUserPassword);

        mngr.begin();
        Connection conn = jtaDs.getConnection();
        OracleConnection oracleConn;
        if(conn instanceof OracleConnection) {
            oracleConn = (OracleConnection)conn;
        } else {
            oracleConn = (OracleConnection)serverSession.getServerPlatform().unwrapConnection(conn);
        }
        oracleConn.openProxySession(OracleConnection.PROXYTYPE_USER_NAME, props);
        // 12c driver will default to an autoCommit setting of true on calling openProxySession
        oracleConn.setAutoCommit(false);
        System.out.println("====testJtaDataSource openProxySession ok");
        mngr.rollback();

        mngr.begin();
        conn = jtaDs.getConnection();
        if(conn instanceof OracleConnection) {
            oracleConn = (OracleConnection)conn;
        } else {
            oracleConn = (OracleConnection)serverSession.getServerPlatform().unwrapConnection(conn);
        }
        try {
            if(oracleConn.isProxySession()) {
                // close proxy session
                oracleConn.close(OracleConnection.PROXY_SESSION);
                fail("Connection has been released into connection pool with the proxy session still open");
            }
            System.out.println("====testJtaDataSource not a proxy session");
        } finally {
            try {
                conn.close();
            } catch (SQLException ex) {
                // Ignore
            }
            mngr.rollback();
            System.out.println("====testJtaDataSource end");
        }
    }

    public void testNonJtaDataSource() throws Exception {
        if(!shouldRunPureJdbcTests) {
            System.out.println("Currently only WLS 10.3.4 and later is known to fully support Oracle Proxy Authentication in both JTA and Non Jta cases.");
            return;
        }
        if(serverSession.getReadConnectionPool().getLogin().shouldUseExternalTransactionController()) {
            throw new RuntimeException("Test problem: non jta data source is required");
        }
        System.out.println("====testNonJtaDataSource begin");
//        Context context = new InitialContext();
//        DataSource nonJtaDs = (DataSource)context.lookup("jdbc/ELNonJTADS");
        // Eclipselink session is used only to obtain non jta data source from the application server.
        DataSource nonJtaDs = ((JNDIConnector)((DatabaseLogin)serverSession.getReadConnectionPool().getLogin()).getConnector()).getDataSource();
        Properties props = new Properties();
        props.setProperty(OracleConnection.PROXY_USER_NAME, ProxyAuthenticationUsersAndProperties.proxyUser);
        props.setProperty(OracleConnection.PROXY_USER_PASSWORD, ProxyAuthenticationUsersAndProperties.proxyUserPassword);

        Connection conn = nonJtaDs.getConnection();
        OracleConnection oracleConn;
        if(conn instanceof OracleConnection) {
            oracleConn = (OracleConnection)conn;
        } else {
            oracleConn = (OracleConnection)serverSession.getServerPlatform().unwrapConnection(conn);
        }
        oracleConn.openProxySession(OracleConnection.PROXYTYPE_USER_NAME, props);
        System.out.println("====testJtaDataSource openProxySession ok");
        conn.close();

        conn = nonJtaDs.getConnection();
        if(conn instanceof OracleConnection) {
            oracleConn = (OracleConnection)conn;
        } else {
            oracleConn = (OracleConnection)serverSession.getServerPlatform().unwrapConnection(conn);
        }
        try {
            if(oracleConn.isProxySession()) {
                fail("Connection has been released into connection pool with the proxy session still open");
            }
            System.out.println("====testJtaDataSource not a proxy session");
        } finally {
            conn.close();
            System.out.println("====testJtaDataSource end");
        }
    }

    /**
     * Setup Proxy properties settings to EntityManager through EntityManagerImpl
     */
    private void setupProperties(EntityManager em){
        EntityManagerImpl empl = (EntityManagerImpl)em.getDelegate();
        empl.setProperties(createProperties());
    }

    private Map createConnProperties() {
        Map newProps = JUnitTestCaseHelper.getDatabaseProperties(PROXY_PU);
        newProps.put(PersistenceUnitProperties.JDBC_USER, ProxyAuthenticationUsersAndProperties.connectionUser);
        newProps.put(PersistenceUnitProperties.JDBC_PASSWORD, ProxyAuthenticationUsersAndProperties.connectionPassword);
        return newProps;
    }

    private Map createProperties(){
        Map newProps = new HashMap(4);
        newProps.put(PersistenceUnitProperties.ORACLE_PROXY_TYPE, OracleConnection.PROXYTYPE_USER_NAME);
        newProps.put(OracleConnection.PROXY_USER_NAME, ProxyAuthenticationUsersAndProperties.proxyUser);
        newProps.put(OracleConnection.PROXY_USER_PASSWORD, ProxyAuthenticationUsersAndProperties.proxyUserPassword);
        newProps.put(PersistenceUnitProperties.EXCLUSIVE_CONNECTION_MODE, ExclusiveConnectionMode.Always);
        return newProps;
    }

    /*
     * Use it instead of beginTransaction to pass proxy properties.
     */
    private void beginTransaction_proxy(EntityManager em){
        if(shouldOverrideGetEntityManager) {
            beginTransaction(em);
            em.joinTransaction();
        } else {
            if (!isOnServer()){
                setupProperties(em);
            }
            beginTransaction(em);
            if (isOnServer){
                setupProperties(em);
            }
        }
    }

    /*
     * Use it instead of rollbackTransaction when beginTransaction_proxy was used
     */
    private void rollbackTransaction_proxy(EntityManager em) {
        if (shouldCloseProxySessionOnRollback) {
            AbstractSession session = JpaHelper.getEntityManager(em).getUnitOfWork().getParent();
            session.getAccessor().releaseCustomizer(session);
        }
        rollbackTransaction(em);
    }

    private void compareObjects(Employee readEmp, Employee writtenEmp, PhoneNumber readPhone, PhoneNumber writtenPhone){
        if (!serverSession.compareObjects(readEmp, proxyEmp)) {
            fail("Object: " + readEmp + " does not match object that was written: " + proxyEmp + ". See log (on finest) for what did not match.");
        }
        if (!serverSession.compareObjects(readPhone, writtenPhone)) {
            fail("Object: " + readPhone + " does not match object that was written: " + writtenPhone + ". See log (on finest) for what did not match.");
        }
    }

    /*
     * Use it instead of createEntityManager to pass proxy properties.
     */
    EntityManager createEntityManager_proxy(String puName) {
        if(shouldOverrideGetEntityManager) {
            EntityManager em = getEntityManagerFactory(puName).createEntityManager(createProperties());
            return em;
        } else {
            return createEntityManager(puName, createProperties());
        }
    }

    private boolean shouldOverrideGetEntityManager(){
        if(serverSession.getServerPlatform().getClass().getName().equals("org.eclipse.persistence.platform.server.oc4j.Oc4jPlatform") ||
           serverSession.getServerPlatform().getClass().getName().equals("org.eclipse.persistence.platform.server.jboss.JBossPlatform") ){
            return true;
        } else {
            return false;
        }
    }

    private boolean shouldCloseProxySessionOnRollback(){
        // https://glassfish.dev.java.net/issues/show_bug.cgi?id=14753   Oracle proxy session problems
        if(serverSession.getServerPlatform().getClass().getName().equals("org.eclipse.persistence.platform.server.glassfish.GlassfishPlatform") ||
           serverSession.getServerPlatform().getClass().getName().equals("org.eclipse.persistence.platform.server.sunas.SunAS9ServerPlatform") ) {
            return true;
        } else {
            return false;
        }
    }

    private boolean shouldRunPureJdbcTests(){
        // currently only WLS 10.3.4 and later is known to fully support Oracle Proxy Authentication in both JTA and Non Jta cases.
        return WebLogicPlatform.class.isAssignableFrom(serverSession.getServerPlatform().getClass()) && Helper.compareVersions(getServerSession(PROXY_PU).getServerPlatform().getServerNameAndVersion(), "10.3.4") >= 0;
    }

    @Override
    protected Properties getServerProperties(){
        String proxy_user=System.getProperty("proxy.user.name");
        Properties p = new Properties();
        p.setProperty(ProxyAuthenticationUsersAndProperties.PA_PROXYUSER, ProxyAuthenticationUsersAndProperties.proxyUser);
        p.setProperty(ProxyAuthenticationUsersAndProperties.PA_PROXYUSERPWD, ProxyAuthenticationUsersAndProperties.proxyUserPassword);
        return p;
    }

}
