/*
 * 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
package org.eclipse.persistence.testing.tests.transactions;

import java.util.*;

import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.sessions.*;
import org.eclipse.persistence.sessions.server.*;
import org.eclipse.persistence.internal.databaseaccess.*;
import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.models.mapping.*;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.testing.tests.clientserver.ClientServerTest;

/**
 * Tests using the client's write connection when in transaction to
 * maintain the proper isolation levels, even for reads.
 * (see CR#4334, SAM)
 */
public class ReadingThroughWriteConnectionInTransactionTest extends org.eclipse.persistence.testing.framework.AutoVerifyTestCase {
    protected boolean multipleClients = false;
    protected boolean useUnitOfWork = false;
    protected boolean readIntoCache = false;
    protected boolean instantiateValueHolders = false;
    protected boolean readAfterTransaction = false;
    protected String notSupportedExplanation = null;
    protected Expression searchExpression = null;
    protected Server serverSession;
    protected Vector backupReadConnections;
    protected DatabaseLogin login;
    protected Exception exception;
    protected Accessor clientWriteConnection;

    public ReadingThroughWriteConnectionInTransactionTest(String testId) {
        super();
        setName("ReadingThroughWriteConnectionInTransactionTest" + testId);
    }

    public boolean shouldUseMultipleClients() {
        return multipleClients;
    }

    public void useMultipleClients() {
        multipleClients = true;
    }

    public boolean shouldUseUnitOfWork() {
        return useUnitOfWork;
    }

    public void useUnitOfWork() {
        useUnitOfWork = true;
    }

    public boolean shouldReadIntoCache() {
        return readIntoCache;
    }

    public void readIntoCache() {
        readIntoCache = true;
    }

    public boolean shouldInstantiateValueHolders() {
        return instantiateValueHolders;
    }

    public void instantiateValueHolders() {
        instantiateValueHolders = true;
    }

    public boolean shouldReadAfterTransaction() {
        return readAfterTransaction;
    }

    public void readAfterTransaction() {
        readAfterTransaction = true;
    }

    protected String getNotSupportedExplanation() {
        return notSupportedExplanation;
    }

    protected void setNotSupportedExplanation(String notSupportedExplanation) {
        this.notSupportedExplanation = notSupportedExplanation;
    }

    protected Expression getSearchExpression() {
        return searchExpression;
    }

    protected void setSearchExpression(Expression searchExpression) {
        this.searchExpression = searchExpression;
    }

    protected Vector getBackupReadConnections() {
        return backupReadConnections;
    }

    protected void setBackupReadConnections(Vector backupReadConnections) {
        this.backupReadConnections = backupReadConnections;
    }

    protected DatabaseLogin getLogin() {
        return login;
    }

    protected void setLogin(DatabaseLogin login) {
        this.login = login;
    }

    protected Exception getException() {
        return exception;
    }

    protected void setException(Exception exception) {
        this.exception = exception;
    }

    protected Accessor getClientWriteConnection() {
        return clientWriteConnection;
    }

    protected void setClientWriteConnection(Accessor clientWriteConnection) {
        this.clientWriteConnection = clientWriteConnection;
    }

    public static Vector buildTests() {
        Vector tests = new Vector(14);
        ReadingThroughWriteConnectionInTransactionTest test = null;

        /* Test 1.
         * Tests: Uses correct accessor at root level + relationship traversal.
         * Result: No exception thrown.
         */
        test = new ReadingThroughWriteConnectionInTransactionTest("1");
        test.setDescription("base test for reading using write/transaction connection when in transaction (CR#4334).  Correct accessor used at root level and for triggered (attribute) queries.");
        tests.add(test);

        test = new ReadingThroughWriteConnectionInTransactionTest("1:UOW");
        test.setDescription("base test for reading using write/transaction connection when in transaction (CR#4334).  Correct accessor used at root level and for triggered (attribute) queries.  Uses Unit of Work.");
        test.useUnitOfWork();
        tests.add(test);

        /* Test 2.
         * Tests: Uses correct accessor for triggering value holder.
         * Result: No exception thrown.
         */
        test = new ReadingThroughWriteConnectionInTransactionTest("2");
        test.setDescription("test for reading using write/transaction connection when in transaction (CR#4334).  Tests correct (write) accessor used when value holder triggered by in transaction session.");
        test.setNotSupportedExplanation(new String("Unless the value holder is wrapped, as by a UOW, it will instaniate with the same connection as its parent in cache, the server read connection."));
        test.instantiateValueHolders();
        tests.add(test);

        test = new ReadingThroughWriteConnectionInTransactionTest("2:UOW");
        test.setDescription("test for reading using write/transaction connection when in transaction (CR#4334).  Tests correct (write) accessor used when value holder triggered by in transaction session.  Uses Unit of Work.");
        test.instantiateValueHolders();
        test.useUnitOfWork();
        tests.add(test);

        /* Test 3.
         * Tests: Uses correct accessor after transaction over.
         * Result: No exception thrown.
         */
        test = new ReadingThroughWriteConnectionInTransactionTest("3");
        test.setDescription("test for reading using write/transaction connection when in transaction (CR#4334).  Tests server read accessor used when value holder triggered by no longer in transaction session.");
        test.readAfterTransaction();
        tests.add(test);

        test = new ReadingThroughWriteConnectionInTransactionTest("3:UOW");
        test.setDescription("test for reading using write/transaction connection when in transaction (CR#4334).  Tests server read accessor used when value holder triggered by no longer in transaction session.  Uses unit of work.");
        test.readAfterTransaction();
        test.useUnitOfWork();
        tests.add(test);

        /* Test 4.
         * Tests: Trigger value holder on object from cache.
         * Result: No exception thrown.
         */
        test = new ReadingThroughWriteConnectionInTransactionTest("4");
        test.setDescription("test for reading using write/transaction connection when in transaction (CR#4334).  Tests correct accessor used when value holder triggered by in transaction session, on object from global cache.");
        test.setNotSupportedExplanation(new String("A client session is not allowed to own the value holders of objects it has read, as they are put in the cache and another could potentially trigger them with your connection."));
        test.readIntoCache();
        test.instantiateValueHolders();
        tests.add(test);

        /*
         * This test has finally been removed.  Even at the time it was the nasty
         * one for clearly what it is doing is wrong: it is checking to see that
         * we are triggering valueholders in the shared cache with a write/dirty
         * connection.  Now we are triggering unit of work valueholders with this
         * connection.  See the new suite of tests for this:
         * UnitOfWorkTests/UnitOfWorkTransactionIsolationTests
         * Actually this only failed due to optimization.  If original already in the
         * shared cache we assume valueholders already triggered whether they are not,
         * so when we trigger them need a server connection, even though we are in
         * transaction.
        test = new ReadingThroughWriteConnectionInTransactionTest("4:UOW");
        test.setDescription("test for reading using write/transaction connection when in transaction (CR#4334).  Tests correct accessor used when value holder triggered by in transaction session, on object from global cache.  Uses unit of work.");
        test.readIntoCache();
        test.instantiateValueHolders();
        test.useUnitOfWork();
        tests.add(test);
        */
        /* Test 5.
         * Tests: Triggered queries on triggered value holder of object from cache.
         * Result: No exception thrown.
         */
        //Can not implement in this current setup.  Should be covered automatically
        //though as the complex mapping model is now being used.
        /* Test 6.
         * Tests: Second client triggers value holder of object in a transaction cache.
         * Result: Write connection of first (in transaction) client used.
         *
         * This test no longer passes in the new architecture.
        test = new ReadingThroughWriteConnectionInTransactionTest("6");
        test.setDescription("test for reading using write/transaction connection when in transaction (CR#4334).  Tests server read accessor used when value holder triggered by non in transaction session, on object originally read by in transaction session.");
        test.useMultipleClients();
        test.instantiateValueHolders();
        tests.add(test);
        */
        test = new ReadingThroughWriteConnectionInTransactionTest("6:UOW");
        test.setDescription("test for reading using write/transaction connection when in transaction (CR#4334).  Tests server read accessor used when value holder triggered by non in transaction session, on object originally read by in transaction session.  Uses unit of work.");
        test.useMultipleClients();
        test.instantiateValueHolders();
        test.useUnitOfWork();
        tests.add(test);

        /* Test 7.
         * Tests: Second client triggers value holder of object once in a transaction cache.
         * Result: Read connection from server read connection pool used.
         */
        test = new ReadingThroughWriteConnectionInTransactionTest("7");
        test.setDescription("test for reading using write/transaction connection when in transaction (CR#4334).  Tests server read accessor used when value holder triggered by non in transaction session, on object originally read by in transaction session that is no longer in transaction.");
        test.useMultipleClients();
        test.readAfterTransaction();
        tests.add(test);

        test = new ReadingThroughWriteConnectionInTransactionTest("7:UOW");
        test.setDescription("test for reading using write/transaction connection when in transaction (CR#4334).  Tests server read accessor used when value holder triggered by non in transaction session, on object originally read by in transaction session that is no longer in transaction.  Uses unit of work.");
        test.useMultipleClients();
        test.readAfterTransaction();
        test.useUnitOfWork();
        tests.add(test);

        return tests;
    }

    /*
     * Makes a client's write connection unusable, such that a null pointer
     * exception will be thrown if used.
     * Call when server read connection pool should be used.
     */
    private void corruptClientWriteConnection(ClientSession client) {
        if (getClientWriteConnection() != null) {
            return;
        }
        setClientWriteConnection(client.getWriteConnection());
        if (client.isInTransaction()) {
            getClientWriteConnection().rollbackTransaction(client);
        }
        client.setWriteConnection(null);
    }

    /*
     * Makes the server read connection pool unusable, such that a null pointer
     * exception will be thrown if used.
     * Call when a client's write/transaction connection should be used.
     */
    private void corruptServerReadConnections() {
        if (getBackupReadConnections() != null) {
            return;
        }
        List<Accessor> readConnections = getServerSession().getReadConnectionPool().getConnectionsAvailable();
        setBackupReadConnections(new Vector(readConnections));
        readConnections.clear();
        readConnections.add(null);
    }

    @Override
    public Server getServerSession() {
        return serverSession;
    }

    @Override
    public void reset() {
        try {
            getServerSession().logout();

            // This logging out and back in again is not understood clearly.
            // @see ClientServerTest.
            //((DatabaseSession) getSession()).logout();
            //((DatabaseSession) getSession()).login();
        } catch (Exception e) {
            // The likely reason logout failed is because
            // corruptServerReadConnection was used by the test:
            // restoreServerReadConnections restores available connections only,
            // but doesn't restore corrupt used connection (getUsedConnections is a protected method on ConnectionPool).
            // Corrupt used connection is there in Test2 and Test4.
            // Therefore when readConnectionPool.shutdown is called it fails with NPE,
            // as the result the write connection pool is not shutdown and the connections are leaked.
            // Let's close these connections here.
            try {
                for (Iterator<ConnectionPool> poolsEnum = ((ServerSession)getServerSession()).getConnectionPools().values().iterator(); poolsEnum.hasNext();) {
                    poolsEnum.next().shutDown();
                }
            } catch (Exception ex) {
                // ignore
            }

            throw new TestErrorException("Failed in reset.", e);
        } finally {
            setServerSession(null);
        }
    }

    /**
     * Reverses a previous call to corruptClientWriteConnection
     */
    private void restoreClientWriteConnection(ClientSession client) {
        if (getClientWriteConnection() != null) {
            client.setWriteConnection(getClientWriteConnection());
            setClientWriteConnection(null);
        }
    }

    /**
     * Reverses a previous call to corruptServerReadConnections
     */
    private void restoreServerReadConnections() {
        if (getBackupReadConnections() != null) {
            List<Accessor> readConnections = getServerSession().getReadConnectionPool().getConnectionsAvailable();
            readConnections.clear();
            readConnections.addAll(getBackupReadConnections());
            setBackupReadConnections(null);
        }
    }

    public void setServerSession(ServerSession serverSession) {
        this.serverSession = serverSession;
    }

    /**
     * Creates a new server session with same login and descriptors as test session.
     * @see ClientServerTest#setup()
     */
    @Override
    public void setup() {
        exception = null;
        try {
            setLogin((DatabaseLogin)getSession().getLogin().clone());
            setServerSession(new ServerSession(login));
            getServerSession().useExclusiveReadConnectionPool(2, 2);
            Vector descriptors = new Vector(getAbstractSession().getDescriptors().values());
            getServerSession().addDescriptors(descriptors);
            getServerSession().setSessionLog(getSession().getSessionLog());
            getServerSession().login();
        } catch (Exception e) {
            throw new TestErrorException("Failed in setup.", e);
        }
        ExpressionBuilder builder = new ExpressionBuilder(Employee.class);
        setSearchExpression(builder.get("lastName").equal("Vadis"));
    }

    /**
     * Executes one of fourteen different tests, depending on how the receiver was
     * initialized.
     */
    @Override
    public void test() {
        ClientSession client = getServerSession().acquireClientSession();
        UnitOfWorkImpl uow = null;
        UnitOfWork uow2 = null;
        Session session = null;

        // The employee read by the primary in transaction session.
        Employee emp = null;

        // The employee read by the secondary session.  emp and emp2 are
        // the same object.
        Employee emp2 = null;
        if (shouldUseUnitOfWork()) {
            uow = client.acquireUnitOfWork();
            session = uow;
        } else {
            session = client;
        }

        // Tests reading with write connection when object already in cache.
        if (shouldReadIntoCache()) {
            getServerSession().executeQuery(new ReadObjectQuery(Employee.class, getSearchExpression()));
        }

        // Start transaction in primary session.  Write connection should now be used.
        if (shouldUseUnitOfWork()) {
            uow.beginEarlyTransaction();
        } else {
            client.beginTransaction();
        }

        // The secondary session is for now always a unit of work not in transaction.
        if (shouldUseMultipleClients()) {
            uow2 = getServerSession().acquireUnitOfWork();
        }
        try {
            corruptServerReadConnections();
            emp = (Employee)session.executeQuery(new ReadObjectQuery(Employee.class, getSearchExpression()));
            if (shouldUseMultipleClients()) {
                // Read the same object into the secondary session also.  Since this session
                // is not in transaction the read connection pool is needed.
                restoreServerReadConnections();
                emp2 = (Employee)uow2.executeQuery(new ReadObjectQuery(Employee.class, getSearchExpression()));
            }
            if (shouldInstantiateValueHolders()) {
                if (shouldUseMultipleClients()) {
                    // Value holder should execute on server, even though created by
                    // an in transaction session.
                    corruptClientWriteConnection(client);
                    emp2.getPhoneNumbers();
                    emp2.getPolicies();
                    restoreClientWriteConnection(client);
                } else {
                    // Value holder should execute on client, as emp belongs to an
                    // in transaction session.
                    Vector phoneNumbers = emp.getPhoneNumbers();
                    phoneNumbers.size();
                    emp.getPolicies();
                }
            }

            // Now do some post transaction testing.
            if (shouldUseUnitOfWork()) {
                uow.rollbackTransaction();
            } else {
                client.rollbackTransaction();
            }

            // Server read pool should again be used as no transactions active.
            restoreServerReadConnections();
            corruptClientWriteConnection(client);
            if (shouldReadAfterTransaction()) {
                if (shouldUseMultipleClients()) {
                    emp2.getPhoneNumbers();
                } else {
                    emp.getPhoneNumbers();
                }
            }
        } catch (Exception e) {
            setException(e);
        } finally {
            restoreClientWriteConnection(client);
            restoreServerReadConnections();
            client.release();
            if (uow2 != null) {
                uow2.release();
            }
        }
    }

    @Override
    public void verify() {
        if (getException() != null) {
            if (getNotSupportedExplanation() != null) {
                throw new TestWarningException("Not supported: " + getNotSupportedExplanation());
            }
            throw new TestErrorException("Test failed.  Either an in transaction session attempted to use a server read connection, or a session tried to use the connection of another session.");
        }
    }
}
