/*
 * 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.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 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 poolsEnum = ((ServerSession)getServerSession()).getConnectionPools().values().iterator(); poolsEnum.hasNext();) {
                    ((ConnectionPool)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 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();
        UnitOfWork 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()) {
                ((org.eclipse.persistence.internal.sessions.UnitOfWorkImpl)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.");
        }
    }
}
