/*
 * Copyright (c) 1998, 2019 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;
import org.eclipse.persistence.internal.sessions.AbstractSession;

/**
 * <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.
     * @param query
     */
    @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.
     * <p>
     * @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.currentThread().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();
    }
}
