/*
 * 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.isolatedsession;

import java.util.*;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.sessions.*;
import org.eclipse.persistence.sessions.server.*;
import org.eclipse.persistence.exceptions.*;

// 05/28/2008-1.0M8 Andrei Ilitchev
//   - 224964: Provide support for Proxy Authentication through JPA.
//      Changed behaviour of ExclusiveIsolatedClientSession - it no longer throws exception
//      on attempt to instantiate value holder for isolated object when the session is closed,
//      it rather obtains the connection again and releases connection immediately after the query is done.
public class ExclusiveConnectionClosedExceptionTest extends AutoVerifyTestCase {
    protected DatabaseLogin login;
    protected ServerSession server;
    protected int numAcquireExclusive;
    protected int numReleaseExclusive;
    protected String errorMsg = "";
    class Listener extends SessionEventAdapter {
        @Override
        public void postAcquireExclusiveConnection(SessionEvent event) {
            numAcquireExclusive++;
            // Bug 299048 - Triggering indirection on closed ExclusiveIsolatedSession may cause exception
            event.getSession().executeNonSelectingSQL("UPDATE ISOLATED_EMPLOYEE SET F_NAME = 'A' WHERE EMP_ID = 0");
        }

        @Override
        public void preReleaseExclusiveConnection(SessionEvent event) {
            numReleaseExclusive++;
            // Bug 299048 - Triggering indirection on closed ExclusiveIsolatedSession may cause exception
            event.getSession().executeNonSelectingSQL("UPDATE EMPLOYEE SET F_NAME = 'A' WHERE EMP_ID = 0");
        }
    }
    Listener listener = new Listener();
    protected Vector emps;

    public ExclusiveConnectionClosedExceptionTest() {
        setDescription("This test will verify that when indirection is triggered after the session is released callbacks are called and connection released. Exception is no longer thrown.");
    }

    public void copyDescriptors(Session session) {
        Vector descriptors = new Vector();

        for (Iterator<ClassDescriptor> iterator = session.getDescriptors().values().iterator(); iterator.hasNext(); ) {
            descriptors.addElement(iterator.next());
        }
        this.server.addDescriptors(descriptors);
        // Since the descriptors are already initialized, must also set the session to isolated.
        this.server.getProject().setHasIsolatedClasses(true);
    }

    @Override
    public void reset() {
        try {
            errorMsg = "";
            numAcquireExclusive = 0;
            numReleaseExclusive = 0;
            this.server.getEventManager().removeListener(listener);
            this.server.logout();
            getDatabaseSession().logout();
            getDatabaseSession().login();
            String schemaName = getSession().getLogin().getUserName();
        } catch (DatabaseException ex) {
        }
    }

    @Override
    public void setup() {
        try {
            this.emps = getSession().readAllObjects(IsolatedEmployee.class);
            String schemaName = getSession().getLogin().getUserName();
            this.login = (DatabaseLogin)getSession().getLogin().clone();
            this.server = new ServerSession(this.login, 2, 5);
            this.server.getDefaultConnectionPolicy().setExclusiveMode(ConnectionPolicy.ExclusiveMode.Isolated);
            this.server.setSessionLog(getSession().getSessionLog());
            copyDescriptors(getSession());
            this.server.getEventManager().addListener(listener);
            this.server.login();
        } catch (RuntimeException ex) {
            getSession().logMessage("This test requires that the connected user has privleges to \"Creat any context\", \"Drop any context\" and \"execute Sys.DBMS_RLS package\" and \"execute Sys.DBMS_SESSION package\".");
            throw ex;
        }
    }

    @Override
    public void test() {
        ReadObjectQuery query = new ReadObjectQuery(IsolatedEmployee.class);
        ClientSession client1 = this.server.acquireClientSession();
        IsolatedEmployee employee = (IsolatedEmployee)client1.executeQuery(query);
        // executing the query causes exclusive connection to be acquired.
        if(numAcquireExclusive != 1 || numReleaseExclusive != 0) {
            errorMsg += "After executing query numAcquireExclusive == " +numAcquireExclusive+" and numReleaseExclusive = "+numReleaseExclusive+"; 1 and 0 were expected.\n";
        }
        client1.release();
        // releasing the session causes exclusive connection to be acquired.
        if(numAcquireExclusive != 1 || numReleaseExclusive != 1) {
            errorMsg += "After releasing ExclusiveIsolatedClientSession numAcquireExclusive == " +numAcquireExclusive+" and numReleaseExclusive = "+numReleaseExclusive+"; 1 and 1 were expected.\n";
        }
        if(client1.getWriteConnection() != null) {
            errorMsg += "After releasing ExclusiveIsolatedClientSession its writeConnection is not null.\n";
        }
        employee.getPhoneNumbers();
        // instantiating of a ValueHolder on released session causes exclusive connection to be acquired for the query, released as soon as the query is completed.
        if(numAcquireExclusive != 2 || numReleaseExclusive != 2) {
            errorMsg += "After instantiating ValueHolder on released ExclusiveIsolatedClientSession numAcquireExclusive == " +numAcquireExclusive+" and numReleaseExclusive = "+numReleaseExclusive+"; 2 and 2 were expected.\n";
        }
        if(client1.getWriteConnection() != null) {
            errorMsg += "After instantiating ValueHolder on released ExclusiveIsolatedClientSession its writeConnection is not null.\n";
        }
    }

    @Override
    public void verify() {
        if(errorMsg.length() > 0) {
            throw new TestErrorException(errorMsg);
        }
    }
}
