/*
 * 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
//     05/28/2008-1.0M8 Andrei Ilitchev
//        - 224964: Provide support for Proxy Authentication through JPA.
//        Added a new constructor that takes Properties.
//     14/05/2012-2.4 Guy Pelletier
//       - 376603: Provide for table per tenant support for multitenant applications
//     08/11/2012-2.5 Guy Pelletier
//       - 393867: Named queries do not work when using EM level Table Per Tenant Multitenancy.
//     09/03/2015 - Will Dazey
//       - 456067 : Added support for defining query timeout units
package org.eclipse.persistence.sessions.server;

import java.util.*;
import java.io.*;
import org.eclipse.persistence.platform.server.ServerPlatform;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.SchemaPerMultitenantPolicy;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.internal.databaseaccess.*;
import org.eclipse.persistence.internal.sequencing.Sequencing;
import org.eclipse.persistence.internal.sequencing.SequencingFactory;
import org.eclipse.persistence.sessions.coordination.CommandManager;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.internal.sessions.*;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.SessionProfiler;

/**
 * <b>Purpose</b>: Acts as a client to the server session.
 * <p>
 * <b>Description</b>: This session is brokered by the server session for use in three-tiered applications.
 * It is used to store the context of the connection, i.e. the login to be used for this client.
 * This allows each client connected to the server to contain its own user login.
 * <p>
 * <b>Responsibilities</b>:
 *    <ul>
 *    <li> Allow units of work to be acquired and pass them the client login's exclusive connection.
 *    <li> Forward all requests and queries to its parent server session.
 *    </ul>
 *  <p>
 * This class is an implementation of {@link org.eclipse.persistence.sessions.Session}.
 * Please refer to that class for a full API.  The public interface should be used.
 * @see Server
 * @see org.eclipse.persistence.sessions.Session
 * @see org.eclipse.persistence.sessions.UnitOfWork
 */
public class ClientSession extends AbstractSession {
    protected ServerSession parent;
    protected ConnectionPolicy connectionPolicy;
    protected Map<String, Accessor> writeConnections;
    protected boolean isActive;
    protected Sequencing sequencing;

    /**
     * INTERNAL:
     * Create and return a new client session.
     */
    public ClientSession(ServerSession parent, ConnectionPolicy connectionPolicy) {
        this(parent, connectionPolicy, null);
    }

    public ClientSession(ServerSession parent, ConnectionPolicy connectionPolicy, Map properties) {
        super();
        // If we have table per tenant descriptors let's clone the project so
        // that we can have a separate jpql parse cache for each tenant.
        if (parent.hasTablePerTenantDescriptors() || parent.getProject().getMultitenantPolicy() != null) {
            this.project = parent.getProject().clone();
            this.project.setJPQLParseCacheMaxSize(parent.getProject().getJPQLParseCache().getMaxSize());
        } else {
            this.project = parent.getProject();
        }

        if (connectionPolicy.isUserDefinedConnection()) {
            // PERF: project only requires clone if login is different
            this.setProject(getProject().clone());
            this.setLogin(connectionPolicy.getLogin());
        }
        if (this.project.getMultitenantPolicy() != null && this.project.getMultitenantPolicy().isSchemaPerMultitenantPolicy()) {
            SchemaPerMultitenantPolicy mp = (SchemaPerMultitenantPolicy) this.project.getMultitenantPolicy();
            if (mp.shouldUseSharedEMF()) {
                //force different login instance
                this.setLogin(getLogin().clone());
            }
        }
        this.isLoggingOff = parent.isLoggingOff();
        this.isActive = true;
        this.externalTransactionController = parent.getExternalTransactionController();
        this.parent = parent;
        this.connectionPolicy = connectionPolicy;
        this.name = parent.getName();
        this.profiler = parent.getProfiler();
        this.serializer = parent.getSerializer();
        this.isInProfile = parent.isInProfile();
        this.commitManager = parent.getCommitManager();
        this.partitioningPolicy = parent.getPartitioningPolicy();
        this.sessionLog = parent.getSessionLog();
        if (parent.hasEventManager()) {
            this.eventManager = parent.getEventManager().clone(this);
        }
        this.exceptionHandler = parent.getExceptionHandler();
        this.pessimisticLockTimeoutDefault = parent.getPessimisticLockTimeoutDefault();
        this.pessimisticLockTimeoutUnitDefault = parent.getPessimisticLockTimeoutUnitDefault();
        this.queryTimeoutDefault = parent.getQueryTimeoutDefault();
        this.queryTimeoutUnitDefault = parent.getQueryTimeoutUnitDefault();
        this.isConcurrent = parent.isConcurrent();
        this.shouldOptimizeResultSetAccess = parent.shouldOptimizeResultSetAccess();
        this.properties = properties;
        this.multitenantContextProperties = parent.getMultitenantContextProperties();

        if (this.eventManager != null) {
            this.eventManager.postAcquireClientSession();
        }

        // Copy down the table per tenant queries from the parent. These queries
        // must be cloned per client session.
        if (parent.hasTablePerTenantQueries()) {
            for (DatabaseQuery query : parent.getTablePerTenantQueries()) {
                addTablePerTenantQuery((DatabaseQuery) query.clone());
            }
        }
        // If we have table per tenant descriptors, they will need to be
        // cloned as we will be changing the descriptors per tenant.
        if (parent.hasTablePerTenantDescriptors()) {
            this.descriptors = new HashMap<>();
            this.descriptors.putAll(parent.getDescriptors());

            for (ClassDescriptor descriptor : parent.getTablePerTenantDescriptors()) {
                ClassDescriptor clonedDescriptor = (ClassDescriptor) descriptor.clone();
                addTablePerTenantDescriptor(clonedDescriptor);
                this.descriptors.put(clonedDescriptor.getJavaClass(), clonedDescriptor);
            }

            if (hasProperties()) {
                for (Object propertyName : properties.keySet()) {
                    updateTablePerTenantDescriptors((String) propertyName, properties.get(propertyName));
                }
            }
        } else {
            this.descriptors = parent.getDescriptors();
        }

        incrementProfile(SessionProfiler.ClientSessionCreated);
    }

    protected ClientSession(org.eclipse.persistence.sessions.Project project) {
        super(project);
    }

    /**
     * INTERNAL:
     * Called in the end of beforeCompletion of external transaction synchronization listener.
     * Close the managed sql connection corresponding to the external transaction
     * and releases accessor.
     */
    @Override
    public void releaseJTSConnection() {
        if (hasWriteConnection()) {
            for (Accessor accessor : getWriteConnections().values()) {
                accessor.closeJTSConnection();
            }
            releaseWriteConnection();
        }
    }

    /**
     * INTERNAL:
     * This is internal to the unit of work and should not be called otherwise.
     */
    @Override
    public void basicCommitTransaction() {
        //Only release connection when transaction succeeds.
        //If not, connection will be released in rollback.
        super.basicCommitTransaction();

        // if synchronized then the connection will be released in external transaction callback.
        if (hasExternalTransactionController()) {
            if(!isSynchronized()) {
                releaseJTSConnection();
            }
        } else {
            releaseWriteConnection();
        }
    }

    /**
     * INTERNAL:
     * This is internal to the unit of work and should not be called otherwise.
     */
    @Override
    public void basicRollbackTransaction() {
        try {
            //BUG 2660471: Make sure there is an accessor (moved here from Session)
            //BUG 2846785: EXCEPTION THROWN IN PREBEGINTRANSACTION EVENT CAUSES NPE
            if (hasWriteConnection()) {
                super.basicRollbackTransaction();
            }
        } finally {
            // if synchronized then the connection will be released in external transaction callback.
            if (hasExternalTransactionController()) {
                if(!isSynchronized()) {
                    releaseJTSConnection();
                }
            } else {
                releaseWriteConnection();
            }
        }
    }

    /**
     * INTERNAL:
     * Connect the session only (this must be the write connection as the read is shared).
     */
    public void connect(Accessor accessor) throws DatabaseException {
        accessor.connect(getDatasourceLogin(), this);
    }

    /**
     * INTERNAL:
     * Was PUBLIC: customer will be redirected to {@link org.eclipse.persistence.sessions.Session}.
     * Return true if the pre-defined query is defined on the session.
     */
    @Override
    public boolean containsQuery(String queryName) {
        boolean containsQuery = getQueries().containsKey(queryName);
        if (containsQuery == false) {
            containsQuery = this.parent.containsQuery(queryName);
        }
        return containsQuery;
    }

    /**
     * INTERNAL:
     * Disconnect the accessor only (this must be the write connection as the read is shared).
     */
    public void disconnect(Accessor accessor) throws DatabaseException {
        accessor.disconnect(this);
    }

    /**
     * INTERNAL:
     * Execute the call on the correct connection accessor.
     * Outside of a transaction the server session's read connection pool is used.
     * In side a transaction, or for exclusive sessions the write connection is used.
     * For partitioning there may be multiple write connections.
     */
    @Override
    public Object executeCall(Call call, AbstractRecord translationRow, DatabaseQuery query) throws DatabaseException {
        if ((!isInTransaction() || (query.isObjectLevelReadQuery() && ((ObjectLevelReadQuery)query).isReadOnly())) && !isExclusiveIsolatedClientSession() ) {
            return this.parent.executeCall(call, translationRow, query);
        }
        boolean shouldReleaseConnection = false;
        if (query.getAccessors() == null) {
            // First check for a partitioning policy.
            // An exclusive session will always use a single connection once allocated.
            if (!hasWriteConnection()  || !isExclusiveIsolatedClientSession()) {
                Collection<Accessor> accessors = getAccessors(call, translationRow, query);
                if (accessors != null && !accessors.isEmpty()) {
                    query.setAccessors(accessors);
                    // the session has been already released and this query is likely instantiates a ValueHolder -
                    // release exclusive connection immediately after the query is executed, otherwise it may never be released.
                    shouldReleaseConnection = !this.isActive;
                }
            }
        }
        if (query.getAccessors() == null) {
            // If the connection has not yet been acquired then do it here.
            if (!hasWriteConnection()) {
                this.parent.acquireClientConnection(this);
                // The session has been already released and this query is likely instantiates a ValueHolder -
                // release exclusive connection immediately after the query is executed, otherwise it may never be released.
                shouldReleaseConnection = !this.isActive;
                query.setAccessors(getAccessors());
            } else {
                // Must use the default write connection if there are multiple connections.
                if (!isExclusiveIsolatedClientSession() && this.connectionPolicy.isPooled()) {
                    Accessor defaultWriteConnection = this.writeConnections.get(this.connectionPolicy.getPoolName());
                    if (defaultWriteConnection == null) {
                        // No default connection yet, must acquire it.
                        this.parent.acquireClientConnection(this);
                    }
                    if (this.writeConnections.size() == 1) {
                        // Connection is the default, just use it.
                        query.setAccessors(getAccessors());
                    } else {
                        List<Accessor> accessors = new ArrayList(1);
                        accessors.add(defaultWriteConnection);
                        query.setAccessors(accessors);
                    }
                } else {
                    query.setAccessors(getAccessors());
                }
            }
        }
        Object result = null;
        RuntimeException exception = null;
        try {
            result = basicExecuteCall(call, translationRow, query);
        } catch (RuntimeException caughtException) {
            exception = caughtException;
        } finally {
            if (call.isFinished() || exception != null) {
                query.setAccessors(null);
                // Note that connection could be release only if it has been acquired by the same query,
                // that allows to execute other queries from postAcquireConnection / preReleaseConnection events
                // without wiping out connection set by the original query or causing stack overflow, see
                // bug 299048 - Triggering indirection on closed ExclusiveIsolatedSession may cause exception
                if (shouldReleaseConnection && hasWriteConnection()) {
                    try {
                        this.parent.releaseClientSession(this);
                    } catch (RuntimeException releaseException) {
                        if (exception == null) {
                            throw releaseException;
                        }
                        //else ignore
                    }
                }
            } else {
                if (query.isObjectLevelReadQuery()) {
                    ((DatabaseCall)call).setHasAllocatedConnection(shouldReleaseConnection);
                }
            }
            if (exception != null) {
                throw exception;
            }
        }
        return result;
    }

    /**
     * INTERNAL:
     * Release (if required) connection after call.
     */
    @Override
    public void releaseConnectionAfterCall(DatabaseQuery query) {
        if ((!isInTransaction() || (query.isObjectLevelReadQuery() && ((ObjectLevelReadQuery)query).isReadOnly())) && !isExclusiveIsolatedClientSession() ) {
            this.parent.releaseConnectionAfterCall(query);
        } else {
            if (hasWriteConnection()) {
                query.setAccessors(null);
                this.parent.releaseClientSession(this);
            }
        }
    }

    /**
     * INTERNAL:
     * Return the write connections if in a transaction.
     * These may be empty/null until the first query has been executed inside the transaction.
     * This should only be called within a transaction.
     * If outside of a transaction it will return null (unless using an exclusive connection).
     */
    @Override
    public Collection<Accessor> getAccessors() {
        if (isInTransaction()) {
            if (this.writeConnections == null) {
                return null;
            }
            return this.writeConnections.values();
        } else {
            return this.accessors;
        }
    }

    /**
     * INTERNAL:
     * This should normally not be used, getAccessors() should be used to support partitioning.
     * To maintain backward compatibility, and to support certain cases that required a default accessor,
     * if inside a transaction, then a default connection will be allocated.
     * This is required for sequencing, and JPA connection unwrapping, and ordt mappings.
     * Outside of a transaction, to maintain backward compatibility the server session's accessor will be returned.
     */
    @Override
    public Accessor getAccessor() {
        Collection<Accessor> accessors = getAccessors();
        if ((accessors == null) || accessors.isEmpty()) {
            if (isInTransaction()) {
                this.parent.acquireClientConnection(this);
                accessors = getAccessors();
            } else {
                return this.parent.getAccessor();
            }
        }
        if (accessors instanceof List) {
            return ((List<Accessor>)accessors).get(0);
        }
        return accessors.iterator().next();
    }

    /**
     * ADVANCED:
     * This method will return the connection policy that was used during the
     * acquisition of this client session.  The properties within the ConnectionPolicy
     * may be used when acquiring an exclusive connection for an IsolatedSession.
     */
    public ConnectionPolicy getConnectionPolicy() {
        return connectionPolicy;
    }

    /**
     * ADVANCED:
     * Return all registered descriptors.
     */
    @Override
    public Map<Class<?>, ClassDescriptor> getDescriptors() {
        // descriptors from the project may have been modified (for table per
        // tenants so make sure to return the updated ones)
        if (hasTablePerTenantDescriptors()) {
            return this.descriptors;
        } else {
            return super.getDescriptors();
        }
    }

    /**
     * INTERNAL:
     * Returns the appropriate IdentityMap session for this descriptor.  Sessions can be
     * chained and each session can have its own Cache/IdentityMap.  Entities can be stored
     * at different levels based on Cache Isolation.  This method will return the correct Session
     * for a particular Entity class based on the Isolation Level and the attributes provided.
     * @param canReturnSelf true when method calls itself.  If the path
     * starting at <code>this</code> is acceptable.  Sometimes true if want to
     * move to the first valid session, i.e. executing on ClientSession when really
     * should be on ServerSession.
     * @param terminalOnly return the last session in the chain where the Enitity is stored.
     * @return Session with the required IdentityMap
     */
    @Override
    public AbstractSession getParentIdentityMapSession(ClassDescriptor descriptor, boolean canReturnSelf, boolean terminalOnly) {
        // Note could return self as ClientSession shares the same identity map
        // as parent.  This reveals a deep problem, as queries will be cached in
        // the Server identity map but executed here using the write connection.
        return this.parent.getParentIdentityMapSession(descriptor, canReturnSelf, terminalOnly);
    }

    /**
     * Search for and return the user defined property from this client session, if it not found then search for the property
     * from parent.
     */
    @Override
    public Object getProperty(String name){
        Object propertyValue = super.getProperty(name);
        if (propertyValue == null) {
           propertyValue = this.parent.getProperty(name);
        }
        return propertyValue;
    }

    /**
     * INTERNAL:
     * Gets the session which this query will be executed on.
     * Generally will be called immediately before the call is translated,
     * which is immediately before session.executeCall.
     * <p>
     * Since the execution session also knows the correct datasource platform
     * to execute on, it is often used in the mappings where the platform is
     * needed for type conversion, or where calls are translated.
     * <p>
     * Is also the session with the accessor.  Will return a ClientSession if
     * it is in transaction and has a write connection.
     * @return a session with a live accessor
     * @param query may store session name or reference class for brokers case
     */
    @Override
    public AbstractSession getExecutionSession(DatabaseQuery query) {
        // For CR#4334 if in transaction stay on client session.
        // That way client's write accessor will be used for all queries.
        // This is to preserve transaction isolation levels.
        // For bug 3602222 if a query is executed directly on a client session when
        // in transaction, then dirty data could be put in the shared cache for the
        // client session uses the identity map of its parent.
        // However beginTransaction() is not public API on ClientSession.
        // if fix this could add: && (query.getSession() != this).
        if (isInTransaction()) {
            return this;
        }
        return this.parent.getExecutionSession(query);
    }

    /**
     * INTERNAL:
     * Return the parent.
     * This is a server session.
     */
    @Override
    public ServerSession getParent() {
        return parent;
    }

    /**
     * INTERNAL:
     * Was PUBLIC: customer will be redirected to {@link org.eclipse.persistence.sessions.Session}.
     * Return the query from the session pre-defined queries with the given name.
     * This allows for common queries to be pre-defined, reused and executed by name.
     */
    @Override
    public DatabaseQuery getQuery(String name) {
        DatabaseQuery query = super.getQuery(name);
        if (query == null) {
            query = this.parent.getQuery(name);
        }

        return query;
    }

    /**
     * INTERNAL:
     */
    @Override
    public DatabaseQuery getQuery(String name, Vector args) {// CR3716; Predrag;
        DatabaseQuery query = super.getQuery(name, args);
        if (query == null) {
            query = this.parent.getQuery(name, args);
        }
        return query;
    }

    /**
     * INTERNAL:
     * was ADVANCED:
     * Creates sequencing object for the session.
     * Typically there is no need for the user to call this method -
     * it is called from the constructor.
     */
    public void initializeSequencing() {
        this.sequencing = SequencingFactory.createSequencing(this);
    }

    /**
     * INTERNAL:
     * Return the Sequencing object used by the session.
     * Lazy init sequencing to defer from client session creation to improve creation performance.
     */
    @Override
    public Sequencing getSequencing() {
        // PERF: lazy init defer from constructor, only created when needed.
        if (this.sequencing == null) {
            initializeSequencing();
        }
        return this.sequencing;
    }

    /**
     * INTERNAL:
     * Marked internal as this is not customer API but helper methods for
     * accessing the server platform from within other sessions types
     * (i.e. not DatabaseSession)
     */
    @Override
    public ServerPlatform getServerPlatform() {
        return this.parent.getServerPlatform();
    }

    /**
     * INTERNAL:
     * Returns the type of session, its class.
     * <p>
     * Override to hide from the user when they are using an internal subclass
     * of a known class.
     * <p>
     * A user does not need to know that their UnitOfWork is a
     * non-deferred UnitOfWork, or that their ClientSession is an
     * IsolatedClientSession.
     */
    @Override
    public String getSessionTypeString() {
        return "ClientSession";
    }

    /**
     * INTERNAL:
     * Return the map of write connections.
     * Multiple connections can be used for data partitioning and replication.
     * The connections are keyed by connection pool name.
     */
    public Map<String, Accessor> getWriteConnections() {
        if (this.writeConnections == null) {
            this.writeConnections = new HashMap(4);
        }
        return this.writeConnections;
    }

    /**
     * INTERNAL:
     * Return the connection to be used for database modification.
     */
    public Accessor getWriteConnection() {
        if ((this.writeConnections == null) || this.writeConnections.isEmpty()) {
            return null;
        }
        return this.writeConnections.values().iterator().next();
    }

    /**
     * INTERNAL:
     * Return if this session has been connected.
     */
    public boolean hasWriteConnection() {
        if (this.writeConnections == null) {
            return false;
        }

        return !this.writeConnections.isEmpty();
    }

    /**
     * INTERNAL:
     * Set up the IdentityMapManager.  This method allows subclasses of Session to override
     * the default IdentityMapManager functionality.
     */
    @Override
    public void initializeIdentityMapAccessor() {
        this.identityMapAccessor = new ClientSessionIdentityMapAccessor(this);
    }

    /**
     * INTERNAL:
     * Was PUBLIC: customer will be redirected to {@link org.eclipse.persistence.sessions.Session}.
     * Return if the client session is active (has not been released).
     */
    public boolean isActive() {
        return isActive;
    }

    /**
     * INTERNAL:
     * Return if this session is a client session.
     */
    @Override
    public boolean isClientSession() {
        return true;
    }

    /**
     * INTERNAL:
     * Was PUBLIC: customer will be redirected to {@link org.eclipse.persistence.sessions.Session}.
     * Return if this session has been connected to the database.
     */
    @Override
    public boolean isConnected() {
        return this.parent.isConnected();
    }

    /**
     * INTERNAL:
     * Was PUBLIC: customer will be redirected to {@link org.eclipse.persistence.sessions.Session}.
     * Release the client session.
     * This releases the client session back to it server.
     * Normally this will logout of the client session's connection,
     * and allow the client session to garbage collect.
     */
    @Override
    public void release() throws DatabaseException {
        // Clear referencing classes. If this is not done the object is not garbage collected.
        for (Map.Entry<Class<?>, ClassDescriptor> entry : getDescriptors().entrySet()) {
            entry.getValue().clearReferencingClasses();
        }

        if (!this.isActive) {
            return;
        }
        if (this.eventManager != null) {
            this.eventManager.preReleaseClientSession();
        }

        //removed is Lazy check as we should always release the connection once
        //the client session has been released.  It is also required for the
        //behavior of a subclass ExclusiveIsolatedClientSession
        if (hasWriteConnection()) {
            this.parent.releaseClientSession(this);
        }

        // we are not inactive until the connection is  released
        this.isActive = false;
        log(SessionLog.FINER, SessionLog.CONNECTION, "client_released");
        if (this.eventManager != null) {
            this.eventManager.postReleaseClientSession();
        }
        incrementProfile(SessionProfiler.ClientSessionReleased);
    }

    /**
     * INTERNAL:
     * A query execution failed due to an invalid query.
     * Re-connect and retry the query.
     */
    @Override
    public Object retryQuery(DatabaseQuery query, AbstractRecord row, DatabaseException databaseException, int retryCount, AbstractSession executionSession) {
        // If not in a transaction and has a write connection, must release it if invalid.
        getParent().releaseInvalidClientSession(this);
        return super.retryQuery(query, row, databaseException, retryCount, executionSession);
    }

    /**
     * INTERNAL:
     * This is internal to the unit of work and should not be called otherwise.
     */
    protected void releaseWriteConnection() {
        if (this.connectionPolicy.isLazy() && hasWriteConnection()) {
            this.parent.releaseClientSession(this);
        }
    }

    /**
     * INTERNAL:
     * Set the connection policy.
     */
    public void setConnectionPolicy(ConnectionPolicy connectionPolicy) {
        this.connectionPolicy = connectionPolicy;
    }

    /**
     * INTERNAL:
     * Set if the client session is active (has not been released).
     */
    protected void setIsActive(boolean isActive) {
        this.isActive = isActive;
    }

    /**
     * INTERNAL:
     * Set the parent.
     * This is a server session.
     */
    protected void setParent(ServerSession parent) {
        this.parent = parent;
    }

    /**
     * INTERNAL:
     * Add the connection to the client session.
     * Multiple connections are supported to allow data partitioning and replication.
     * The accessor is returned, as if detected to be dead it may be replaced.
     */
    public Accessor addWriteConnection(String poolName, Accessor writeConnection) {
        getWriteConnections().put(poolName, writeConnection);
        writeConnection.createCustomizer(this);
        //if connection is using external connection pooling then the event will be risen right after it connects.
        if (!writeConnection.usesExternalConnectionPooling()) {
            postAcquireConnection(writeConnection);
        }
        // Transactions are lazily started on connections.
        if (isInTransaction()) {
            basicBeginTransaction(writeConnection);
        }
        return getWriteConnections().get(poolName);
    }

    /**
     * INTERNAL:
     * A begin transaction failed.
     * Re-connect and retry the begin transaction.
     */
    @Override
    public DatabaseException retryTransaction(Accessor writeConnection, DatabaseException databaseException, int retryCount, AbstractSession executionSession) {
        if (writeConnection.getPool() == null) {
            return super.retryTransaction(writeConnection, databaseException, retryCount, executionSession);
        }
        String poolName = writeConnection.getPool().getName();
        DatabaseLogin login = getLogin();
        int count = login.getQueryRetryAttemptCount();
        DatabaseException exceptionToThrow = databaseException;
        while (retryCount < count) {
            getWriteConnections().remove(poolName);
            //if connection is using external connection pooling then the event will be risen right after it connects.
            if (!writeConnection.usesExternalConnectionPooling()) {
                preReleaseConnection(writeConnection);
            }
            writeConnection.getPool().releaseConnection(writeConnection);
            try {
                // attempt to reconnect for a certain number of times.
                // servers may take some time to recover.
                ++retryCount;
                writeConnection = writeConnection.getPool().acquireConnection();
                writeConnection.beginTransaction(this);
                //passing the retry count will prevent a runaway retry where
                // we can acquire connections but are unable to execute any queries
                if (retryCount > 1) {
                    // We are retrying more than once lets wait to give connection time to restart.
                    //Give the failover time to recover.
                    Thread.sleep(login.getDelayBetweenConnectionAttempts());
                }
                getWriteConnections().put(poolName, writeConnection);
                writeConnection.createCustomizer(this);
                //if connection is using external connection pooling then the event will be risen right after it connects.
                if (!writeConnection.usesExternalConnectionPooling()) {
                    postAcquireConnection(writeConnection);
                }
                return null;
            } catch (DatabaseException ex){
                //replace original exception with last exception thrown
                //this exception could be a data based exception as opposed
                //to a connection exception that needs to go back to the customer.
                exceptionToThrow = ex;
            } catch (InterruptedException ex) {
                //Ignore interrupted exception.
            }
        }
        return exceptionToThrow;
    }

    /**
     * INTERNAL:
     * Set the connection to be used for database modification.
     */
    public void setWriteConnections(Map<String, Accessor> writeConnections) {
        // Clear customizers.
        if ((this.writeConnections != null) && (writeConnections == null)) {
            for (Accessor accessor : this.writeConnections.values()) {
                accessor.releaseCustomizer(this);
            }
        }
        this.writeConnections = writeConnections;
    }

    /**
     * INTERNAL:
     * Set the connection to be used for database modification.
     */
    public void setWriteConnection(Accessor writeConnection) {
        if (writeConnection == null) {
            setWriteConnections(null);
            return;
        }
        String poolName = null;
        if (writeConnection.getPool() != null) {
            poolName = writeConnection.getPool().getName();
        } else {
            poolName = ServerSession.NOT_POOLED;
        }
        addWriteConnection(poolName, writeConnection);
    }

    /**
     * INTERNAL:
     * Print the connection status with the session.
     */
    @Override
    public String toString() {
        StringWriter writer = new StringWriter();
        writer.write(getSessionTypeString());
        writer.write("(");
        writer.write(String.valueOf(getWriteConnections()));
        writer.write(")");
        return writer.toString();
    }

    /**
     * INTERNAL:
     * Return the manager that allows this processor to receive or propagate commands from/to TopLink cluster
     * @see CommandManager
     * @return a remote command manager
     */
    @Override
    public CommandManager getCommandManager() {
        return this.parent.getCommandManager();
    }

    /**
     * INTERNAL:
     * Return whether changes should be propagated to TopLink cluster.  This is one of the required
     * cache synchronization setting
     */
    @Override
    public boolean shouldPropagateChanges() {
        return this.parent.shouldPropagateChanges();
    }

    /**
     * INTERNAL:
     * Release the cursor query's connection.
     */
    @Override
    public void releaseReadConnection(Accessor connection) {
        // If the cursor's connection is the write connection, then do not release it.
        if ((this.writeConnections != null) && this.writeConnections.containsValue(connection)) {
            return;
        }
        //bug 4668234 -- used to only release connections on server sessions but should always release
        this.parent.releaseReadConnection(connection);
    }

    /**
     * INTERNAL:
     * This method is called in case externalConnectionPooling is used.
     * If returns true, accessor used by the session keeps its
     * connection open until released by the session.
     */
    @Override
    public boolean isExclusiveConnectionRequired() {
        return !this.connectionPolicy.isLazy && isActive();
    }
}
