/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2014, 2021 IBM Corporation. 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
//     10/15/2010-2.2 Guy Pelletier
//       - 322008: Improve usability of additional criteria applied to queries at the session/EM
//     06/30/2011-2.3.1 Guy Pelletier
//       - 341940: Add disable/enable allowing native queries
//     09/09/2011-2.3.1 Guy Pelletier
//       - 356197: Add new VPD type to MultitenantType
//     09/14/2011-2.3.1 Guy Pelletier
//       - 357533: Allow DDL queries to execute even when Multitenant entities are part of the PU
//     05/14/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.
//     11/29/2012-2.5 Guy Pelletier
//       - 395406: Fix nightly static weave test errors
//     08/11/2014-2.5 Rick Curtis
//       - 440594: Tolerate invalid NamedQuery at EntityManager creation.
//     09/03/2015 - Will Dazey
//       - 456067: Added support for defining query timeout units
//     05/26/2016-2.7 Tomas Kraus
//       - 494610: Session Properties map should be Map<String, Object>
package org.eclipse.persistence.internal.sessions;

import java.io.Serializable;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.TimeUnit;

import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.config.ReferenceMode;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.DescriptorQueryManager;
import org.eclipse.persistence.descriptors.TablePerMultitenantPolicy;
import org.eclipse.persistence.descriptors.invalidation.CacheInvalidationPolicy;
import org.eclipse.persistence.descriptors.partitioning.PartitioningPolicy;
import org.eclipse.persistence.exceptions.ConcurrencyException;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.EclipseLinkException;
import org.eclipse.persistence.exceptions.ExceptionHandler;
import org.eclipse.persistence.exceptions.IntegrityChecker;
import org.eclipse.persistence.exceptions.IntegrityException;
import org.eclipse.persistence.exceptions.OptimisticLockException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.history.AsOfClause;
import org.eclipse.persistence.indirection.ValueHolderInterface;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.databaseaccess.Accessor;
import org.eclipse.persistence.internal.databaseaccess.Platform;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.helper.ConcurrencyManager;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.QueryCounter;
import org.eclipse.persistence.internal.helper.linkedlist.ExposedNodeLinkedList;
import org.eclipse.persistence.internal.history.HistoricalSession;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.identitymaps.IdentityMapManager;
import org.eclipse.persistence.internal.indirection.DatabaseValueHolder;
import org.eclipse.persistence.internal.indirection.ProtectedValueHolder;
import org.eclipse.persistence.internal.indirection.ProxyIndirectionPolicy;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedGetConstructorFor;
import org.eclipse.persistence.internal.security.PrivilegedInvokeConstructor;
import org.eclipse.persistence.internal.security.PrivilegedNewInstanceFromClass;
import org.eclipse.persistence.internal.sequencing.Sequencing;
import org.eclipse.persistence.internal.sessions.cdi.DisabledInjectionManager;
import org.eclipse.persistence.internal.sessions.cdi.InjectionManager;
import org.eclipse.persistence.logging.DefaultSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.logging.SessionLogEntry;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.foundation.AbstractTransformationMapping;
import org.eclipse.persistence.platform.database.DatabasePlatform;
import org.eclipse.persistence.platform.server.ServerPlatform;
import org.eclipse.persistence.queries.AttributeGroup;
import org.eclipse.persistence.queries.Call;
import org.eclipse.persistence.queries.DataModifyQuery;
import org.eclipse.persistence.queries.DataReadQuery;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.DeleteObjectQuery;
import org.eclipse.persistence.queries.DoesExistQuery;
import org.eclipse.persistence.queries.InsertObjectQuery;
import org.eclipse.persistence.queries.JPAQueryBuilder;
import org.eclipse.persistence.queries.JPQLCall;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.SQLCall;
import org.eclipse.persistence.queries.UpdateObjectQuery;
import org.eclipse.persistence.queries.WriteObjectQuery;
import org.eclipse.persistence.sessions.CopyGroup;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.ExternalTransactionController;
import org.eclipse.persistence.sessions.Login;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.SessionEventManager;
import org.eclipse.persistence.sessions.SessionProfiler;
import org.eclipse.persistence.sessions.coordination.Command;
import org.eclipse.persistence.sessions.coordination.CommandManager;
import org.eclipse.persistence.sessions.coordination.CommandProcessor;
import org.eclipse.persistence.sessions.coordination.MetadataRefreshListener;
import org.eclipse.persistence.sessions.serializers.Serializer;

/**
 * Implementation of org.eclipse.persistence.sessions.Session
 * The public interface should be used.
 * @see org.eclipse.persistence.sessions.Session
 *
 * <p>
 * <b>Purpose</b>: Define the interface and common protocol of an EclipseLink compliant session.
 * <p>
 * <b>Description</b>: The session is the primary interface into EclipseLink,
 * the application should do all of its reading and writing of objects through the session.
 * The session also manages transactions and units of work.  Normally the session
 * is passed and used by the application controller objects.  Controller objects normally
 * sit behind the GUI and perform the business processes required for the application,
 * they should perform all explicit database access and database access should be avoided from
 * the domain object model.  Do not use a globally accessible session instance, doing so does
 * not allow for multiple sessions.  Multiple sessions may required when performing things like
 * data migration or multiple database access, as well the unit of work feature requires the usage
 * of multiple session instances.  Although session is abstract, any users of its subclasses
 * should only cast the variables to Session to allow usage of any of its subclasses.
 * <p>
 * <b>Responsibilities</b>:
 *    <ul>
 *    <li> Connecting/disconnecting.
 *    <li> Reading and writing objects.
 *    <li> Transaction and unit of work support.
 *    <li> Identity maps and caching.
 *    </ul>
 * @see DatabaseSessionImpl
 */
public abstract class AbstractSession extends CoreAbstractSession<ClassDescriptor, Login, Platform, Project, SessionEventManager> implements org.eclipse.persistence.sessions.Session, CommandProcessor, Serializable, Cloneable {
    /** ExceptionHandler handles database exceptions. */
    transient protected ExceptionHandler exceptionHandler;

    /** IntegrityChecker catch all the descriptor Exceptions.  */
    transient protected IntegrityChecker integrityChecker;

    /** The project stores configuration information, such as the descriptors and login. */
    transient protected Project project;

    /** Ensure mutual exclusion of the session's transaction state across multiple threads.*/
    transient protected ConcurrencyManager transactionMutex;

    /** Manages the live object cache.*/
    protected IdentityMapAccessor identityMapAccessor;

    /** If Transactions were externally started */
    protected boolean wasJTSTransactionInternallyStarted;

    /** The connection to the data store. */
    transient protected Collection<Accessor> accessors;

    /** Allow the datasource platform to be cached. */
    transient protected Platform platform;

    /** Stores predefine reusable queries.*/
    transient protected Map<String, List<DatabaseQuery>> queries;

    /**
     * Stores predefined reusable AttributeGroups.
     */
    protected Map<String, AttributeGroup> attributeGroups;

    /** Stores predefined not yet parsed JPQL queries.*/
    protected boolean jpaQueriesProcessed = false;

    /** Resolves referential integrity on commits. */
    transient protected CommitManager commitManager;

    /** Tool that log performance information. */
    transient protected SessionProfiler profiler;

    /** Support being owned by a session broker. */
    transient protected AbstractSession broker;

    /** Used to identify a session when using the session broker. */
    protected String name;

    /** Keep track of active units of work. */
    transient protected int numberOfActiveUnitsOfWork;

    /**
     * This collection will be used to store those objects that are currently locked
     * for the clone process. It should be populated with an EclipseLinkIdentityHashMap
     */
    protected Map objectsLockedForClone;

    /** Destination for logged messages and SQL. */
    transient protected SessionLog sessionLog;

    /** When logging the name of the session is typed: class name + system hashcode. */
    transient protected String logSessionString;

    /** Stores the event listeners for this session. */
    transient protected SessionEventManager eventManager;

    /** Allow for user defined properties. */
    protected Map<String, Object> properties;

    /** Delegate that handles synchronizing a UnitOfWork with an external transaction. */
    transient protected ExternalTransactionController externalTransactionController;

    /** Last descriptor accessed, use to optimize descriptor lookup. */
    transient protected ClassDescriptor lastDescriptorAccessed;

    /** PERF: cache descriptors from project. */
    transient protected Map<Class, ClassDescriptor> descriptors;

    /** PERF: cache table per tenant descriptors needing to be initialized per EM */
    transient protected List<ClassDescriptor> tablePerTenantDescriptors;

    /** PERF: cache table per tenant queries needing to be initialized per EM */
    transient protected List<DatabaseQuery> tablePerTenantQueries;

    // bug 3078039: move EJBQL alias > descriptor map from Session to Project (MWN)

    /** Used to determine If a session is in a Broker or not */
    protected boolean isInBroker;

    /**
     * Used to connect this session to EclipseLink cluster for distributed command
     */
    transient protected CommandManager commandManager;

    /**
     * PERF: Cache the write-lock check to avoid cost of checking in every register/clone.
     */
    protected boolean shouldCheckWriteLock;

    /**
     * Determined whether changes should be propagated to an EclipseLink cluster
     */
    protected boolean shouldPropagateChanges;

    /** Used to determine If a session is in a profile or not */
    protected boolean isInProfile;

    /** PERF: Quick check if logging is OFF entirely. */
    protected boolean isLoggingOff;

    /** PERF: Allow for finalizers to be enabled, currently enables client-session finalize. */
    protected boolean isFinalizersEnabled;

    /** List of active command threads. */
    transient protected ExposedNodeLinkedList activeCommandThreads;

    /**
     * Indicates whether the session is synchronized.
     * In case external transaction controller is used isSynchronized==true means
     * the session's jta connection will be freed during external transaction callback.
     */
    protected boolean isSynchronized;

    /**
     *  Stores the default reference mode that a UnitOfWork will use when referencing
     *  managed objects.
     *  @see org.eclipse.persistence.config.ReferenceMode
     */
    protected ReferenceMode defaultReferenceMode;

    /**
     * Default pessimistic lock timeout value.
     */
    protected Integer pessimisticLockTimeoutDefault;
    
    protected TimeUnit pessimisticLockTimeoutUnitDefault;

    protected int queryTimeoutDefault;

    protected TimeUnit queryTimeoutUnitDefault;

    /** Allow a session to enable concurrent processing. */
    protected boolean isConcurrent;

    /**
     * This map will hold onto class to static metamodel class references from JPA.
     */
    protected Map<String, String> staticMetamodelClasses;

    /** temporarily holds a list of events that must be fired after the current operation completes.
     *  Initialy created for postClone events.
     */
    protected List<DescriptorEvent> deferredEvents;

    /** records that the UOW is executing deferred events.  Events could cause operations to occur that may attempt to restart the event execution.  This must be avoided*/
    protected boolean isExecutingEvents;

    /** Allow queries to be targeted at specific connection pools. */
    protected PartitioningPolicy partitioningPolicy;

    /** the MetadataRefreshListener is used with RCM to force a refresh of the metadata used within EntityManagerFactoryWrappers */
    protected MetadataRefreshListener metadatalistener;

    /** Stores the set of multitenant context properties this session requires **/
    protected Set<String> multitenantContextProperties;

    /** Store the query builder used to parse JPQL. */
    transient protected JPAQueryBuilder queryBuilder;

    /** Set the Serializer to use by default for serialization. */
    transient protected Serializer serializer;

    /** Allow CDI injection of entity listeners **/
    transient protected InjectionManager injectionManager;

    /**
     * Indicates whether ObjectLevelReadQuery should by default use ResultSet Access optimization.
    * Optimization specified by the session is ignored if incompatible with other query settings.
     */
    protected boolean shouldOptimizeResultSetAccess;

    /**
     * Indicates whether Session creation should tolerate an invalid NamedQuery. If true, an exception
     * will be thrown on .createNamedQuery(..) rather than at init time.
     */
    protected boolean tolerateInvalidJPQL = false;

    /**
     * INTERNAL:
     * Create and return a new session.
     * This should only be called if the database login information is not know at the time of creation.
     * Normally it is better to call the constructor that takes the login information as an argument
     * so that the session can initialize itself to the platform information given in the login.
     */
    protected AbstractSession() {
        this.name = "";
        this.queryTimeoutUnitDefault = DescriptorQueryManager.DefaultTimeoutUnit;
        this.pessimisticLockTimeoutUnitDefault = DescriptorQueryManager.DefaultTimeoutUnit;
        initializeIdentityMapAccessor();
        // PERF - move to lazy init (3286091)
    }

    /**
     * INTERNAL:
     * Create a blank session, used for proxy session.
     */
    protected AbstractSession(int nothing) {
    }

    /**
     * PUBLIC:
     * Create and return a new session.
     * By giving the login information on creation this allows the session to initialize itself
     * to the platform given in the login. This constructor does not return a connected session.
     * To connect the session to the database login() must be sent to it. The login(userName, password)
     * method may also be used to connect the session, this allows for the user name and password
     * to be given at login but for the other database information to be provided when the session is created.
     */
    public AbstractSession(Login login) {
        this(new org.eclipse.persistence.sessions.Project(login));
    }

    /**
     * PUBLIC:
     * Create and return a new session.
     * This constructor does not return a connected session.
     * To connect the session to the database login() must be sent to it. The login(userName, password)
     * method may also be used to connect the session, this allows for the user name and password
     * to be given at login but for the other database information to be provided when the session is created.
     */
    public AbstractSession(org.eclipse.persistence.sessions.Project project) {
        this();
        this.project = project;
        if (project.getDatasourceLogin() == null) {
            throw ValidationException.projectLoginIsNull(this);
        }
        // add the Project's queries as session queries
        for (DatabaseQuery query : project.getQueries()) {
            addQuery(query.getName(), query);
        }
    }

    /**
     * Return the Serializer to use by default for serialization.
     */
    @Override
    public Serializer getSerializer() {
        return serializer;
    }

    /**
     * Set the Serializer to use by default for serialization.
     */
    @Override
    public void setSerializer(Serializer serializer) {
        this.serializer = serializer;
    }

    /**
     * INTERNAL
     * Return the query builder used to parser JPQL.
     */
    public JPAQueryBuilder getQueryBuilder() {
        if (this.queryBuilder == null) {
            AbstractSession parent = getParent();
            if (parent != null) {
                this.queryBuilder = parent.getQueryBuilder();
            } else {
                this.queryBuilder = buildDefaultQueryBuilder();
            }
        }
        return this.queryBuilder;
    }

    /**
     * INTERNAL
     * Set the query builder used to parser JPQL.
     */
    public void setQueryBuilder(JPAQueryBuilder queryBuilder) {
        this.queryBuilder = queryBuilder;
    }

    /**
     * INTERNAL
     * Build the JPQL builder based on session properties.
     */
    protected JPAQueryBuilder buildDefaultQueryBuilder() {
        String queryBuilderClassName = (String)getProperty(PersistenceUnitProperties.JPQL_PARSER);
        if (queryBuilderClassName == null) {
            queryBuilderClassName = "org.eclipse.persistence.internal.jpa.jpql.HermesParser";
            //queryBuilderClassName = "org.eclipse.persistence.queries.ANTLRQueryBuilder";
        }
        String validation = (String)getProperty(PersistenceUnitProperties.JPQL_VALIDATION);
        JPAQueryBuilder builder = null;
        try {
            Class parserClass = null;
            // use class.forName() to avoid loading parser classes for JAXB
            // Use Class.forName not thread class loader to avoid class loader issues.
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                parserClass = AccessController.doPrivileged(new PrivilegedClassForName(queryBuilderClassName));
                builder = (JPAQueryBuilder)AccessController.doPrivileged(new PrivilegedNewInstanceFromClass(parserClass));
            } else {
                parserClass = PrivilegedAccessHelper.getClassForName(queryBuilderClassName);
                builder = (JPAQueryBuilder)PrivilegedAccessHelper.newInstanceFromClass(parserClass);
            }
        } catch (Exception e) {
            throw new IllegalStateException("Could not load the JPQL parser class." /* TODO: Localize string */, e);
        }
        if (validation != null) {
            builder.setValidationLevel(validation);
        }
        return builder;
    }

    /**
     * INTERNAL:
     * PERF: Used for quick turning logging ON/OFF entirely.
     * @param loggingOff Logging is turned off when <code>true</code>
     *                   and turned on when <code>false</code>.
     */
    public void setLoggingOff(final boolean loggingOff) {
        isLoggingOff = loggingOff;
    }

    /**
     * INTERNAL:
     * PERF: Used for quick check if logging is OFF entirely.
     */
    public boolean isLoggingOff() {
        return isLoggingOff;
    }

    /**
     * INTERNAL:
     * Called by a sessions queries to obtain individual query ids.
     * CR #2698903
     */
    public long getNextQueryId() {
        return QueryCounter.getCount();
    }

    /**
     * INTERNAL:
     * Return a unit of work for this session not registered with the JTS transaction.
     */
    public UnitOfWorkImpl acquireNonSynchronizedUnitOfWork() {
        return acquireNonSynchronizedUnitOfWork(null);
    }

    /**
     * INTERNAL:
     * Return a unit of work for this session not registered with the JTS transaction.
     */
    public UnitOfWorkImpl acquireNonSynchronizedUnitOfWork(ReferenceMode referenceMode) {
        setNumberOfActiveUnitsOfWork(getNumberOfActiveUnitsOfWork() + 1);
        UnitOfWorkImpl unitOfWork = new UnitOfWorkImpl(this, referenceMode);
        if (shouldLog(SessionLog.FINER, SessionLog.TRANSACTION)) {
            log(SessionLog.FINER, SessionLog.TRANSACTION, "acquire_unit_of_work_with_argument", String.valueOf(System.identityHashCode(unitOfWork)));
        }
        return unitOfWork;
    }

    /**
     * INTERNAL:
     * Constructs a HistoricalSession given a valid AsOfClause.
     */
    @Override
    public org.eclipse.persistence.sessions.Session acquireHistoricalSession(AsOfClause clause) throws ValidationException {
        if ((clause == null) || (clause.getValue() == null)) {
            throw ValidationException.cannotAcquireHistoricalSession();
        }
        if (!getProject().hasGenericHistorySupport() && !hasBroker() && ((getPlatform() == null) || !getPlatform().isOracle())) {
            throw ValidationException.historicalSessionOnlySupportedOnOracle();
        }
        return new HistoricalSession(this, clause);
    }

    /**
     * PUBLIC:
     * Return a unit of work for this session.
     * The unit of work is an object level transaction that allows
     * a group of changes to be applied as a unit.
     *
     * @see UnitOfWorkImpl
     */
    @Override
    public UnitOfWorkImpl acquireUnitOfWork() {
        UnitOfWorkImpl unitOfWork = acquireNonSynchronizedUnitOfWork(getDefaultReferenceMode());
        unitOfWork.registerWithTransactionIfRequired();

        return unitOfWork;
    }

    /**
     * PUBLIC:
     * Return a repeatable write unit of work for this session.
     * A repeatable write unit of work allows multiple writeChanges (flushes).
     *
     * @see RepeatableWriteUnitOfWork
     */
    public RepeatableWriteUnitOfWork acquireRepeatableWriteUnitOfWork(ReferenceMode referenceMode) {
        return new RepeatableWriteUnitOfWork(this, referenceMode);
    }

    /**
     * PUBLIC:
     * Return a unit of work for this session.
     * The unit of work is an object level transaction that allows
     * a group of changes to be applied as a unit.
     *
     * @see UnitOfWorkImpl
     * @param referenceMode The reference type the UOW should use internally when
     * referencing Working clones.  Setting this to WEAK means the UOW will use
     * weak references to reference clones that support active object change
     * tracking and hard references for deferred change tracked objects.
     * Setting to FORCE_WEAK means that all objects will be referenced by weak
     * references and if the application no longer references the clone the
     * clone may be garbage collected.  If the clone
     * has uncommitted changes then those changes will be lost.
     */
    @Override
    public UnitOfWorkImpl acquireUnitOfWork(ReferenceMode referenceMode) {
        UnitOfWorkImpl unitOfWork = acquireNonSynchronizedUnitOfWork(referenceMode);
        unitOfWork.registerWithTransactionIfRequired();

        return unitOfWork;
    }
   /**
     * PUBLIC:
     * Add an alias for the descriptor
     */
    public void addAlias(String alias, ClassDescriptor descriptor) {
        project.addAlias(alias, descriptor);
    }

    /**
     * INTERNAL:
     * Return all pre-defined not yet parsed EJBQL queries.
     */
    @Override
    public void addJPAQuery(DatabaseQuery query) {
        getProject().addJPAQuery(query);
    }

    /**
     * INTERNAL:
     * Return all pre-defined not yet parsed EJBQL multitenant queries.
     */
    public void addJPATablePerTenantQuery(DatabaseQuery query) {
        getProject().addJPATablePerTenantQuery(query);
    }

    /**
     * PUBLIC:
     * Return a set of multitenant context properties this session
     */
    public void addMultitenantContextProperty(String contextProperty) {
        getMultitenantContextProperties().add(contextProperty);
    }

    /**
     * INTERNAL:
     * Add the query to the session queries.
     */
    protected synchronized void addQuery(DatabaseQuery query, boolean nameMustBeUnique) {
        Vector queriesByName = (Vector)getQueries().get(query.getName());
        if (queriesByName == null) {
            // lazily create Vector in Hashtable.
            queriesByName = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
            getQueries().put(query.getName(), queriesByName);
        }

        if (nameMustBeUnique){ // JPA addNamedQuery
            if (queriesByName.size() <= 1){
                queriesByName.clear();
            }else{
                throw new IllegalStateException(ExceptionLocalization.buildMessage("argument_keyed_named_query_with_JPA", new Object[]{query.getName()}));
            }
        }else{
            // Check that we do not already have a query that matched it
            for (Iterator enumtr = queriesByName.iterator(); enumtr.hasNext();) {
                DatabaseQuery existingQuery = (DatabaseQuery)enumtr.next();
                if (Helper.areTypesAssignable(query.getArgumentTypes(), existingQuery.getArgumentTypes())) {
                    throw ValidationException.existingQueryTypeConflict(query, existingQuery);
                }
            }
        }
        queriesByName.add(query);
    }

    /**
     * PUBLIC:
     * Add the query to the session queries with the given name.
     * This allows for common queries to be pre-defined, reused and executed by name.
     */
    @Override
    public void addQuery(String name, DatabaseQuery query) {
        query.setName(name);
        addQuery(query, false);
    }

    /**
     * PUBLIC:
     * Add the query to the session queries with the given name.
     * This allows for common queries to be pre-defined, reused and executed by name.
     */
    public void addQuery(String name, DatabaseQuery query, boolean replace) {
        query.setName(name);
        addQuery(query, replace);
    }

    /**
     * INTERNAL:
     * Add a metamodel class to model class reference.
     */
    public void addStaticMetamodelClass(String modelClassName, String metamodelClassName) {
        if (staticMetamodelClasses == null) {
            staticMetamodelClasses = new HashMap<>();
        }

        staticMetamodelClasses.put(modelClassName, metamodelClassName);
    }

    /**
     * INTERNAL:
     * Add a descriptor that is uses a table per tenant multitenant policy.
     */
    protected void addTablePerTenantDescriptor(ClassDescriptor descriptor) {
        getTablePerTenantDescriptors().add(descriptor);
    }

    /**
     * INTERNAL:
     * Add a query that queries a table per tenant entity
     */
    protected void addTablePerTenantQuery(DatabaseQuery query) {
        getTablePerTenantQueries().add(query);
    }

    /**
     * INTERNAL:
     * Called by beginTransaction() to start a transaction.
     * This starts a real database transaction.
     * Allows retry if the connection is dead.
     */
    protected void basicBeginTransaction() throws DatabaseException {
        Collection<Accessor> accessors = getAccessors();
        if (accessors == null) {
            return;
    }
        Accessor failedAccessor = null;
        try {
            for (Accessor accessor : accessors) {
                failedAccessor = accessor;
                basicBeginTransaction(accessor);
            }
        } catch (RuntimeException exception) {
            // If begin failed, rollback ones already started.
            for (Accessor accessor : accessors) {
                if (accessor == failedAccessor) {
                    break;
                }
                try {
                    accessor.rollbackTransaction(this);
                } catch (RuntimeException ignore) { }
            }
            throw exception;
        }
    }

    /**
     * INTERNAL:
     * Called by beginTransaction() to start a transaction.
     * This starts a real database transaction.
     * Allows retry if the connection is dead.
     */
    protected void basicBeginTransaction(Accessor accessor) throws DatabaseException {
        try {
            accessor.beginTransaction(this);
        } catch (DatabaseException databaseException) {
            // Retry if the failure was communication based?  (i.e. timeout, database down, can no longer ping)
            if ((!getDatasourceLogin().shouldUseExternalTransactionController()) && databaseException.isCommunicationFailure()) {
                DatabaseException exceptionToThrow = databaseException;
                Object[] args = new Object[1];
                args[0] = databaseException;
                log(SessionLog.INFO, SessionLog.TRANSACTION, "communication_failure_attempting_begintransaction_retry", args, null);
                // Attempt to reconnect connection.
                exceptionToThrow = retryTransaction(accessor, databaseException, 0, this);
                if (exceptionToThrow == null) {
                    // Retry was a success.
                    return;
                }
                handleException(exceptionToThrow);
            } else {
                handleException(databaseException);
            }
        } catch (RuntimeException exception) {
            handleException(exception);
        }
    }

    /**
     * INTERNAL:
     * A begin transaction failed.
     * Re-connect and retry the begin transaction.
     */
    public DatabaseException retryTransaction(Accessor accessor, DatabaseException databaseException, int retryCount, AbstractSession executionSession) {
        DatabaseException exceptionToThrow = databaseException;
        // Attempt to reconnect connection.
        int count = getLogin().getQueryRetryAttemptCount();
        while (retryCount < count) {
            try {
                // if database session then re-establish
                // connection
                // else the session will just get a new
                // connection from the pool
                accessor.reestablishConnection(this);
                accessor.beginTransaction(this);
                return null;
            } catch (DatabaseException newException) {
                // Need to use last exception, as may not be a communication exception.
                exceptionToThrow = newException;
                // failed to get connection because of
                // database error.
                ++retryCount;
                try {
                    // Give the failover time to recover.
                    Thread.currentThread().sleep(getLogin().getDelayBetweenConnectionAttempts());
                    Object[] args = new Object[1];
                    args[0] = exceptionToThrow;
                    log(SessionLog.INFO, SessionLog.TRANSACTION, "communication_failure_attempting_begintransaction_retry", args, null);
                } catch (InterruptedException intEx) {
                    break;
                }
            }
        }
        return exceptionToThrow;
    }

    /**
     * INTERNAL:
     * Called in the end of beforeCompletion of external transaction synchronization listener.
     * Close the managed sql connection corresponding to the external transaction,
     * if applicable releases accessor.
     */
    public void releaseJTSConnection() {
    }

    /**
     * INTERNAL:
     * Called by commitTransaction() to commit a transaction.
     * This commits the active transaction.
     */
    protected void basicCommitTransaction() throws DatabaseException {
        Collection<Accessor> accessors = getAccessors();
        if (accessors == null) {
            return;
        }
        try {
            for (Accessor accessor : accessors) {
                accessor.commitTransaction(this);
            }
        } catch (RuntimeException exception) {
            // Leave transaction uncommitted as rollback should be called.
            handleException(exception);
        }
    }

    /**
     * INTERNAL:
     * Called by rollbackTransaction() to rollback a transaction.
     * This rolls back the active transaction.
     */
    protected void basicRollbackTransaction() throws DatabaseException {
        Collection<Accessor> accessors = getAccessors();
        if (accessors == null) {
            return;
        }
        RuntimeException exception = null;
        for (Accessor accessor : accessors) {
        try {
                accessor.rollbackTransaction(this);
            } catch (RuntimeException failure) {
                exception = failure;
            }
        }
        if (exception != null) {
            handleException(exception);
        }
    }

    /**
     * INTERNAL:
     * Attempts to begin an external transaction.
     * Returns true only in one case -
     * external transaction has been internally started during this method call:
     * wasJTSTransactionInternallyStarted()==false in the beginning of this method and
     * wasJTSTransactionInternallyStarted()==true in the end of this method.
     */
    public boolean beginExternalTransaction() {
        boolean externalTransactionHasBegun = false;
        if (hasExternalTransactionController() && !wasJTSTransactionInternallyStarted()) {
            try {
                getExternalTransactionController().beginTransaction(this);
            } catch (RuntimeException exception) {
                handleException(exception);
            }
            if (wasJTSTransactionInternallyStarted()) {
                externalTransactionHasBegun = true;
                log(SessionLog.FINER, SessionLog.TRANSACTION, "external_transaction_has_begun_internally");
            }
        }
        return externalTransactionHasBegun;
    }

    /**
     * PUBLIC:
     * Begin a transaction on the database.
     * This allows a group of database modification to be committed or rolled back as a unit.
     * All writes/deletes will be sent to the database be will not be visible to other users until commit.
     * Although databases do not allow nested transaction,
     * EclipseLink supports nesting through only committing to the database on the outer commit.
     *
     * @exception DatabaseException if the database connection is lost or the begin is rejected.
     * @exception ConcurrencyException if this session's transaction is acquired by another thread and a timeout occurs.
     *
     * @see #isInTransaction()
     */
    public void beginTransaction() throws DatabaseException, ConcurrencyException {
        ConcurrencyManager mutex = getTransactionMutex();
        // If there is no db transaction in progress
        // beginExternalTransaction() starts an external transaction -
        // provided externalTransactionController is used, and there is
        // no active external transaction - so we have to start one internally.
        if (!mutex.isAcquired()) {
            beginExternalTransaction();
        }
        // For unit of work and client session multi threading is allowed as they are a context,
        // this is required for JTS/RMI/CORBA/EJB stuff where the server thread can be different across calls.
        if (isClientSession()) {
            mutex.setActiveThread(Thread.currentThread());
        }

        // Ensure mutual exclusion and call subclass specific begin.
        mutex.acquire();
        if (!mutex.isNested()) {
            if (this.eventManager != null) {
                this.eventManager.preBeginTransaction();
            }
            basicBeginTransaction();
            if (this.eventManager != null) {
                this.eventManager.postBeginTransaction();
            }
        }
    }


    /**
     * Check to see if the descriptor of a superclass can be used to describe this class
     *
     * @param theClass
     * @return ClassDescriptor
     */
    protected ClassDescriptor checkHierarchyForDescriptor(Class theClass){
        return getDescriptor(theClass.getSuperclass());
    }

    /**
     * allow the entity listener injection manager to clean itself up.
     */
    public void cleanUpInjectionManager(){
        if (injectionManager != null){
            injectionManager.cleanUp(this);
        }
    }

    /**
     * PUBLIC:
     * clear the integrityChecker. IntegrityChecker holds all the ClassDescriptor Exceptions.
     */
    @Override
    public void clearIntegrityChecker() {
        setIntegrityChecker(null);
    }

    /**
     * INTERNAL:
     * Clear the the lastDescriptorAccessed cache.
     */
    public void clearLastDescriptorAccessed() {
        this.lastDescriptorAccessed = null;
    }

    /**
     * INTERNAL:
     * Clear the the descriptors cache.
     */
    public void clearDescriptors() {
        this.descriptors = null;
    }

    /**
     * PUBLIC:
     * Clear the profiler, this will end the current profile operation.
     */
    @Override
    public void clearProfile() {
        setProfiler(null);
    }

    /**
     * INTERNAL:
     * Clones the descriptor
     */
    @Override
    public Object clone() {
        // An alternative to this process should be found
        try {
            return super.clone();
        } catch (Exception exception) {
            throw new AssertionError(exception);
        }
    }

    /**
     * INTERNAL:
     * Attempts to commit the running internally started external transaction.
     * Returns true only in one case -
     * external transaction has been internally committed during this method call:
     * wasJTSTransactionInternallyStarted()==true in the beginning of this method and
     * wasJTSTransactionInternallyStarted()==false in the end of this method.
     */
    public boolean commitExternalTransaction() {
        boolean externalTransactionHasCommitted = false;
        if (hasExternalTransactionController() && wasJTSTransactionInternallyStarted()) {
            try {
                getExternalTransactionController().commitTransaction(this);
            } catch (RuntimeException exception) {
                handleException(exception);
            }
            if (!wasJTSTransactionInternallyStarted()) {
                externalTransactionHasCommitted = true;
                log(SessionLog.FINER, SessionLog.TRANSACTION, "external_transaction_has_committed_internally");
            }
        }
        return externalTransactionHasCommitted;
    }

    /**
     * PUBLIC:
     * Commit the active database transaction.
     * This allows a group of database modification to be committed or rolled back as a unit.
     * All writes/deletes will be sent to the database be will not be visible to other users until commit.
     * Although databases do not allow nested transaction,
     * EclipseLink supports nesting through only committing to the database on the outer commit.
     *
     * @exception DatabaseException most databases validate changes as they are done,
     * normally errors do not occur on commit unless the disk fails or the connection is lost.
     * @exception ConcurrencyException if this session is not within a transaction.
     */
    public void commitTransaction() throws DatabaseException, ConcurrencyException {
        ConcurrencyManager mutex = getTransactionMutex();
        // Release mutex and call subclass specific commit.
        if (!mutex.isNested()) {
            if (this.eventManager != null) {
                this.eventManager.preCommitTransaction();
            }
            basicCommitTransaction();
            if (this.eventManager != null) {
                this.eventManager.postCommitTransaction();
            }
        }

        // This MUST not be in a try catch or finally as if the commit failed the transaction is still open.
        mutex.release();

        // If there is no db transaction in progress
        // if there is an active external transaction
        // which was started internally - it should be committed internally, too.
        if (!mutex.isAcquired()) {
            commitExternalTransaction();
        }
    }

    /**
     * INTERNAL:
     * Return if the two object match completely.
     * This checks the objects attributes and their private parts.
     */
    public boolean compareObjects(Object firstObject, Object secondObject) {
        if ((firstObject == null) && (secondObject == null)) {
            return true;
        }

        if ((firstObject == null) || (secondObject == null)) {
            return false;
        }

        if (!(firstObject.getClass().equals(secondObject.getClass()))) {
            return false;
        }

        ObjectBuilder builder = getDescriptor(firstObject.getClass()).getObjectBuilder();

        return builder.compareObjects(builder.unwrapObject(firstObject, this), builder.unwrapObject(secondObject, this), this);
    }

    /**
     * TESTING:
     * Return true if the object do not match.
     * This checks the objects attributes and their private parts.
     */
    public boolean compareObjectsDontMatch(Object firstObject, Object secondObject) {
        return !this.compareObjects(firstObject, secondObject);
    }

    /**
     * PUBLIC:
     * Return true if the pre-defined query is defined on the session.
     */
    @Override
    public boolean containsQuery(String queryName) {
        return getQueries().containsKey(queryName);
    }

    /**
     * PUBLIC:
     * Return a complete copy of the object or of collection of objects.
     * In case of collection all members should be either entities of the same type
     * or have a common inheritance hierarchy mapped root class.
     * This can be used to obtain a scratch copy of an object,
     * or for templatizing an existing object into another new object.
     * The object and all of its privately owned parts will be copied.
     *
     * @see #copy(Object, AttributeGroup)
     */
    @Override
    public Object copy(Object originalObjectOrObjects) {
        return copy(originalObjectOrObjects, new CopyGroup());
    }

    /**
     * PUBLIC:
     * Return a complete copy of the object or of collection of objects.
     * In case of collection all members should be either entities of the same type
     * or have a common inheritance hierarchy mapped root class.
     * This can be used to obtain a scratch copy of an object,
     * or for templatizing an existing object into another new object.
     * If there are no attributes in the group
     * then the object and all of its privately owned parts will be copied.
     * Otherwise only the attributes included into the group will be copied.
     */
    @Override
    public Object copy(Object originalObjectOrObjects, AttributeGroup group) {
        if (originalObjectOrObjects == null) {
            return null;
        }

        CopyGroup copyGroup = group.toCopyGroup();
        copyGroup.setSession(this);
        if(originalObjectOrObjects instanceof Collection) {
            // it's a collection - make sure all elements use the same instance of CopyGroup.
            Collection originalCollection = (Collection)originalObjectOrObjects;
            Collection copies;
            if(originalCollection instanceof List) {
                copies = new ArrayList();
            } else {
                copies = new HashSet();
            }
            Iterator it = originalCollection.iterator();
            while(it.hasNext()) {
                copies.add(copyInternal(it.next(), copyGroup));
            }
            return copies;
        }

        // it's not a collection
        return copyInternal(originalObjectOrObjects, copyGroup);
    }

    /**
     * INTERNAL:
     */
    public Object copyInternal(Object originalObject, CopyGroup copyGroup) {
        if (originalObject == null) {
            return null;
        }

        ClassDescriptor descriptor = getDescriptor(originalObject);
        if (descriptor == null) {
            return originalObject;
        }

        return descriptor.getObjectBuilder().copyObject(originalObject, copyGroup);
    }

    /**
     * INTERNAL:
     * Copy the read only classes from the unit of work
     *
     * Added Nov 8, 2000 JED for Patch 2.5.1.8
     * Ref: Prs 24502
     */
    public Vector copyReadOnlyClasses() {
        return getDefaultReadOnlyClasses();
    }

    public DatabaseValueHolder createCloneQueryValueHolder(ValueHolderInterface attributeValue, Object clone, AbstractRecord row, ForeignReferenceMapping mapping) {
        return new ProtectedValueHolder(attributeValue, mapping, this);
    }

    public DatabaseValueHolder createCloneTransformationValueHolder(ValueHolderInterface attributeValue, Object original, Object clone, AbstractTransformationMapping mapping) {
        return new ProtectedValueHolder(attributeValue, mapping, this);
    }

    public <T> InjectionManager<T> createInjectionManager(Object beanManager){
        try{
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    Class elim = AccessController.doPrivileged(new PrivilegedClassForName(InjectionManager.DEFAULT_CDI_INJECTION_MANAGER, true, getLoader()));
                    Constructor constructor = AccessController.doPrivileged(new PrivilegedGetConstructorFor(elim, new Class[] {String.class}, false));
                    return (InjectionManager<T>) AccessController.doPrivileged(new PrivilegedInvokeConstructor(constructor, new Object[] {beanManager}));
            } else {
                Class elim = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(InjectionManager.DEFAULT_CDI_INJECTION_MANAGER, true, getLoader());
                Constructor constructor = PrivilegedAccessHelper.getConstructorFor(elim, new Class[] {Object.class}, false);
                return (InjectionManager<T>) PrivilegedAccessHelper.invokeConstructor(constructor, new Object[] {beanManager});
            }
        } catch (Exception e){
            logThrowable(SessionLog.FINEST, SessionLog.JPA, e);
        }
        return new DisabledInjectionManager<>();
    }

    /**
     * INTERNAL:
     * This method is similar to getAndCloneCacheKeyFromParent.  It purpose is to get protected cache data from the shared cache and
     * build/return a protected instance.
     */
    public Object createProtectedInstanceFromCachedData(Object cached, Integer refreshCascade, ClassDescriptor descriptor){
        CacheKey localCacheKey = getIdentityMapAccessorInstance().getCacheKeyForObject(cached);
        if (localCacheKey != null && localCacheKey.getObject() != null){
            return localCacheKey.getObject();
        }
        boolean identityMapLocked = this.shouldCheckWriteLock && getParent().getIdentityMapAccessorInstance().acquireWriteLock();
        boolean rootOfCloneRecursion = false;
        CacheKey cacheKey = getParent().getIdentityMapAccessorInstance().getCacheKeyForObject(cached);
        try{
            Object key = null;
            Object lockValue = null;
            long readTime = 0;
            if (cacheKey != null){
                if (identityMapLocked) {
                    checkAndRefreshInvalidObject(cached, cacheKey, descriptor);
                } else {
                    // Check if we have locked all required objects already.
                    if (this.objectsLockedForClone == null) {
                        // PERF: If a simple object just acquire a simple read-lock.
                        if (descriptor.shouldAcquireCascadedLocks()) {
                            this.objectsLockedForClone = getParent().getIdentityMapAccessorInstance().getWriteLockManager().acquireLocksForClone(cached, descriptor, cacheKey, this);
                        } else {
                            checkAndRefreshInvalidObject(cached, cacheKey, descriptor);
                            cacheKey.acquireReadLock();
                        }
                        rootOfCloneRecursion = true;
                    }
                }
                key = cacheKey.getKey();
                lockValue = cacheKey.getWriteLockValue();
                readTime = cacheKey.getReadTime();
            }
            if (descriptor.hasInheritance()){
                descriptor = this.getClassDescriptor(cached.getClass());
            }
            ObjectBuilder builder = descriptor.getObjectBuilder();
            Object workingClone = builder.instantiateWorkingCopyClone(cached, this);
            // PERF: Cache the primary key if implements PersistenceEntity.
            builder.populateAttributesForClone(cached, cacheKey,  workingClone, refreshCascade, this);
            getIdentityMapAccessorInstance().putInIdentityMap(workingClone, key, lockValue, readTime, descriptor);
            return workingClone;
        }finally{
            if (rootOfCloneRecursion){
                if (this.objectsLockedForClone == null && cacheKey != null) {
                    cacheKey.releaseReadLock();
                } else {
                    for (Iterator iterator = this.objectsLockedForClone.values().iterator(); iterator.hasNext();) {
                        ((CacheKey)iterator.next()).releaseReadLock();
                    }
                    this.objectsLockedForClone = null;
                }
                executeDeferredEvents();
            }
        }
    }

        /**
         * INTERNAL:
         * Check if the object is invalid and refresh it.
         * This is used to ensure that no invalid objects are registered.
         */
        public void checkAndRefreshInvalidObject(Object object, CacheKey cacheKey, ClassDescriptor descriptor) {
            if (isConsideredInvalid(object, cacheKey, descriptor)) {
                ReadObjectQuery query = new ReadObjectQuery();
                query.setReferenceClass(object.getClass());
                query.setSelectionId(cacheKey.getKey());
                query.refreshIdentityMapResult();
                query.setIsExecutionClone(true);
                this.executeQuery(query);
            }
        }

        /**
         * INTERNAL:
         * Check if the object is invalid and *should* be refreshed.
         * This is used to ensure that no invalid objects are cloned.
         */
        public boolean isConsideredInvalid(Object object, CacheKey cacheKey, ClassDescriptor descriptor) {
            if (cacheKey.getObject() != null) {
                CacheInvalidationPolicy cachePolicy = descriptor.getCacheInvalidationPolicy();
                // BUG#6671556 refresh invalid objects when accessed in the unit of work.
                return (cachePolicy.shouldRefreshInvalidObjectsOnClone() && cachePolicy.isInvalidated(cacheKey));
            }
            return false;
        }

    /**
     * INTERNAL:
     * Add an event to the deferred list.  Events will be fired after the operation completes
     */
    public void deferEvent(DescriptorEvent event){
        if (this.deferredEvents == null){
            this.deferredEvents = new ArrayList<>();
        }
        this.deferredEvents.add(event);
    }

    /**
     * PUBLIC:
     * delete all of the objects and all of their privately owned parts in the database.
     * The allows for a group of objects to be deleted as a unit.
     * The objects will be deleted through a single transactions.
     *
     * @exception DatabaseException if an error occurs on the database,
     * these include constraint violations, security violations and general database errors.
     * @exception OptimisticLockException if the object's descriptor is using optimistic locking and
     * the object has been updated or deleted by another user since it was last read.
     */
    public void deleteAllObjects(Collection domainObjects) throws DatabaseException, OptimisticLockException {
        for (Iterator objectsEnum = domainObjects.iterator(); objectsEnum.hasNext();) {
            deleteObject(objectsEnum.next());
        }
    }

    /**
     * PUBLIC:
     * Delete the object and all of its privately owned parts from the database.
     * The delete operation can be customized through using a delete query.
     *
     * @exception DatabaseException if an error occurs on the database,
     * these include constraint violations, security violations and general database errors.
     * An database error is not raised if the object is already deleted or no rows are effected.
     * @exception OptimisticLockException if the object's descriptor is using optimistic locking and
     * the object has been updated or deleted by another user since it was last read.
     *
     * @see DeleteObjectQuery
     */
    public Object deleteObject(Object domainObject) throws DatabaseException, OptimisticLockException {
        DeleteObjectQuery query = new DeleteObjectQuery();
        query.setObject(domainObject);
        query.setIsExecutionClone(true);
        return executeQuery(query);
    }

    /**
     * PUBLIC:
     * Return if the object exists on the database or not.
     * This always checks existence on the database.
     */
    @Override
    public boolean doesObjectExist(Object object) throws DatabaseException {
        DoesExistQuery query = new DoesExistQuery();
        query.setObject(object);
        query.checkDatabaseForDoesExist();
        query.setIsExecutionClone(true);
        return ((Boolean)executeQuery(query)).booleanValue();
    }

    /**
     * PUBLIC:
     * Turn off logging
     */
    @Override
    public void dontLogMessages() {
        setLogLevel(SessionLog.OFF);
    }

    /**
     * INTERNAL:
     * End the operation timing.
     */
    @Override
    public void endOperationProfile(String operationName) {
        if (this.isInProfile) {
            getProfiler().endOperationProfile(operationName);
        }
    }

    /**
     * INTERNAL:
     * End the operation timing.
     */
    public void endOperationProfile(String operationName, DatabaseQuery query, int weight) {
        if (this.isInProfile) {
            getProfiler().endOperationProfile(operationName, query, weight);
        }
    }

    /**
     * INTERNAL:
     * Updates the value of SessionProfiler state
     */
    @Override
    public void updateProfile(String operationName, Object value) {
        if (this.isInProfile) {
            getProfiler().update(operationName, value);
        }
    }

    /**
     * INTERNAL:
     * Set the table per tenant. This should be called per client session after
     * the start of a transaction. From JPA this method is called on the entity
     * manager by setting the multitenant table per tenant property.
     */
    public void updateTablePerTenantDescriptors(String property, Object value) {
        // When all the table per tenant descriptors are set, we should initialize them.
        boolean shouldInitializeDescriptors = hasTablePerTenantDescriptors();

        for (ClassDescriptor descriptor : getTablePerTenantDescriptors()) {
            TablePerMultitenantPolicy policy = (TablePerMultitenantPolicy) descriptor.getMultitenantPolicy();

            if ((! policy.hasContextTenant()) && policy.usesContextProperty(property)) {
                policy.setContextTenant((String) value);
            }

            shouldInitializeDescriptors = shouldInitializeDescriptors && policy.hasContextTenant();
        }

        if (shouldInitializeDescriptors) {
            // Now that the correct tables are set on all table per tenant
            // descriptors, we can go through the initialization phases safely.
            try {
                // First initialize basic properties (things that do not depend on anything else)
                for (ClassDescriptor descriptor : tablePerTenantDescriptors) {
                    descriptor.preInitialize(this);
                }

                // Second initialize basic mappings
                for (ClassDescriptor descriptor : tablePerTenantDescriptors) {
                    descriptor.initialize(this);
                }

                // Third initialize child dependencies
                for (ClassDescriptor descriptor : tablePerTenantDescriptors) {
                    descriptor.postInitialize(this);
                }

                if (getIntegrityChecker().hasErrors()) {
                    handleSevere(new IntegrityException(getIntegrityChecker()));
                }
            } finally {
                clearIntegrityChecker();
            }

            getCommitManager().initializeCommitOrder();

            // If we have table per tenant queries, initialize and add them now
            // once all the descriptors have been initialized.
            if (hasTablePerTenantQueries()) {
                for (DatabaseQuery query : getTablePerTenantQueries()) {
                    processJPAQuery(query);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Updates the count of SessionProfiler event
     */
    @Override
    public void incrementProfile(String operationName) {
        if (this.isInProfile) {
            getProfiler().occurred(operationName, this);
        }
    }

    /**
     * INTERNAL:
     * Updates the count of SessionProfiler event
     */
    public void incrementProfile(String operationName, DatabaseQuery query) {
        if (this.isInProfile) {
            getProfiler().occurred(operationName, query, this);
        }
    }

    /**
     * INTERNAL:
     * Causes any deferred events to be fired.  Called after operation completes
     */
    public void executeDeferredEvents(){
        if (!this.isExecutingEvents && this.deferredEvents != null) {
            this.isExecutingEvents = true;
            try {
                for (int i = 0; i < this.deferredEvents.size(); ++i) {
                    // the size is checked every time here because the list may grow
                    DescriptorEvent event = this.deferredEvents.get(i);
                    event.getDescriptor().getEventManager().executeEvent(event);
                }
                this.deferredEvents.clear();
            } finally {
                this.isExecutingEvents = false;
            }
        }
    }


    /**
     * INTERNAL:
     * Overridden by subclasses that do more than just execute the call.
     * Executes the call directly on this session and does not check which
     * session it should have executed on.
     */
    public Object executeCall(Call call, AbstractRecord translationRow, DatabaseQuery query) throws DatabaseException {
        if (query.getAccessors() == null) {
            query.setAccessors(getAccessors());
        }
        try {
            return basicExecuteCall(call, translationRow, query);
        } finally {
            if (call.isFinished()) {
                query.setAccessors(null);
            }
        }
    }

    /**
     * INTERNAL:
     * Release (if required) connection after call.
     * @param query
     */
    public void releaseConnectionAfterCall(DatabaseQuery query) {
    }

    /**
     * PUBLIC:
     * Execute the call on the database.
     * The row count is returned.
     * The call can be a stored procedure call, SQL call or other type of call.
     * <p>Example:
     * <p>session.executeNonSelectingCall(new SQLCall("Delete from Employee");
     *
     * @see #executeSelectingCall(Call)
     */
    @Override
    public int executeNonSelectingCall(Call call) throws DatabaseException {
        DataModifyQuery query = new DataModifyQuery();
        query.setIsExecutionClone(true);
        query.setCall(call);
        Integer value = (Integer)executeQuery(query);
        if (value == null) {
            return 0;
        } else {
            return value.intValue();
        }
    }

    /**
     * PUBLIC:
     * Execute the sql on the database.
     * <p>Example:
     * <p>session.executeNonSelectingSQL("Delete from Employee");
     * @see #executeNonSelectingCall(Call)
     * Warning: Allowing an unverified SQL string to be passed into this
     * method makes your application vulnerable to SQL injection attacks.
     */
    @Override
    public void executeNonSelectingSQL(String sqlString) throws DatabaseException {
        executeNonSelectingCall(new SQLCall(sqlString));
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     *
     * @see #addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName) throws DatabaseException {
        DatabaseQuery query = getQuery(queryName);

        if (query == null) {
            throw QueryException.queryNotDefined(queryName);
        }

        return executeQuery(query);
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     * The class is the descriptor in which the query was pre-defined.
     *
     * @see DescriptorQueryManager#addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName, Class domainClass) throws DatabaseException {
        ClassDescriptor descriptor = getDescriptor(domainClass);

        if (descriptor == null) {
            throw QueryException.descriptorIsMissingForNamedQuery(domainClass, queryName);
        }

        DatabaseQuery query = descriptor.getQueryManager().getQuery(queryName);

        if (query == null) {
            throw QueryException.queryNotDefined(queryName, domainClass);
        }

        return executeQuery(query);
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     * The class is the descriptor in which the query was pre-defined.
     *
     * @see DescriptorQueryManager#addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName, Class domainClass, Object arg1) throws DatabaseException {
        Vector argumentValues = new Vector();
        argumentValues.addElement(arg1);
        return executeQuery(queryName, domainClass, argumentValues);
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     * The class is the descriptor in which the query was pre-defined.
     *
     * @see DescriptorQueryManager#addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName, Class domainClass, Object arg1, Object arg2) throws DatabaseException {
        Vector argumentValues = new Vector();
        argumentValues.addElement(arg1);
        argumentValues.addElement(arg2);
        return executeQuery(queryName, domainClass, argumentValues);
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     * The class is the descriptor in which the query was pre-defined.
     *
     * @see DescriptorQueryManager#addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName, Class domainClass, Object arg1, Object arg2, Object arg3) throws DatabaseException {
        Vector argumentValues = new Vector();
        argumentValues.addElement(arg1);
        argumentValues.addElement(arg2);
        argumentValues.addElement(arg3);
        return executeQuery(queryName, domainClass, argumentValues);
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     * The class is the descriptor in which the query was pre-defined.
     *
     * @see DescriptorQueryManager#addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName, Class domainClass, List argumentValues) throws DatabaseException {
        if (argumentValues instanceof Vector) {
            return executeQuery(queryName, domainClass, (Vector)argumentValues);
        } else {
            return executeQuery(queryName, domainClass, new Vector(argumentValues));
        }
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     * The class is the descriptor in which the query was pre-defined.
     *
     * @see DescriptorQueryManager#addQuery(String, DatabaseQuery)
     */
    public Object executeQuery(String queryName, Class domainClass, Vector argumentValues) throws DatabaseException {
        ClassDescriptor descriptor = getDescriptor(domainClass);

        if (descriptor == null) {
            throw QueryException.descriptorIsMissingForNamedQuery(domainClass, queryName);
        }

        DatabaseQuery query = descriptor.getQueryManager().getQuery(queryName, argumentValues);

        if (query == null) {
            throw QueryException.queryNotDefined(queryName, domainClass);
        }

        return executeQuery(query, argumentValues);
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     *
     * @see #addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName, Object arg1) throws DatabaseException {
        Vector argumentValues = new Vector();
        argumentValues.addElement(arg1);
        return executeQuery(queryName, argumentValues);
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     *
     * @see #addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName, Object arg1, Object arg2) throws DatabaseException {
        Vector argumentValues = new Vector();
        argumentValues.addElement(arg1);
        argumentValues.addElement(arg2);
        return executeQuery(queryName, argumentValues);
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     *
     * @see #addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName, Object arg1, Object arg2, Object arg3) throws DatabaseException {
        Vector argumentValues = new Vector();
        argumentValues.addElement(arg1);
        argumentValues.addElement(arg2);
        argumentValues.addElement(arg3);
        return executeQuery(queryName, argumentValues);
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     *
     * @see #addQuery(String, DatabaseQuery)
     */
    @Override
    public Object executeQuery(String queryName, List argumentValues) throws DatabaseException {
        if (argumentValues instanceof Vector) {
            return executeQuery(queryName, (Vector)argumentValues);
        } else {
            return executeQuery(queryName, new Vector(argumentValues));
        }
    }

    /**
     * PUBLIC:
     * Execute the pre-defined query by name and return the result.
     * Queries can be pre-defined and named to allow for their reuse.
     *
     * @see #addQuery(String, DatabaseQuery)
     */
    public Object executeQuery(String queryName, Vector argumentValues) throws DatabaseException {
        DatabaseQuery query = getQuery(queryName, argumentValues);

        if (query == null) {
            throw QueryException.queryNotDefined(queryName);
        }

        return executeQuery(query, argumentValues);
    }

    /**
     * PUBLIC:
     * Execute the database query.
     * A query is a database operation such as reading or writing.
     * The query allows for the operation to be customized for such things as,
     * performance, depth, caching, etc.
     *
     * @see DatabaseQuery
     */
    @Override
    public Object executeQuery(DatabaseQuery query) throws DatabaseException {
        return executeQuery(query, EmptyRecord.getEmptyRecord());
    }

    /**
     * PUBLIC:
     * Return the results from executing the database query.
     * The query arguments are passed in as a List of argument values in the same order as the query arguments.
     */
    @Override
    public Object executeQuery(DatabaseQuery query, List argumentValues) throws DatabaseException {
        if (query == null) {
            throw QueryException.queryNotDefined();
        }
        AbstractRecord row = query.rowFromArguments(argumentValues, this);

        return executeQuery(query, row);
    }

    /**
     * INTERNAL:
     * Return the results from executing the database query.
     * the arguments should be a database row with raw data values.
     */
    public Object executeQuery(DatabaseQuery query, AbstractRecord row) throws DatabaseException {
        if (hasBroker()) {
            if (!((query.isDataModifyQuery() || query.isDataReadQuery()) && (query.getSessionName() == null))) {
                return getBroker().executeQuery(query, row);
            }
        }

        if (query == null) {
            throw QueryException.queryNotDefined();
        }

        // Check for disabled native queries.
        if (query.isUserDefinedSQLCall() && query.isSQLCallQuery() && ! query.isJPQLCallQuery()) {
            if (! query.shouldAllowNativeSQLQuery(getProject().allowNativeSQLQueries())) {
                // If the session/project says no to SQL queries and the database
                // query doesn't ask to bypass this decision then throw an exception.
                throw QueryException.nativeSQLQueriesAreDisabled(query);
            }
        }

        //CR#2272
        log(SessionLog.FINEST, SessionLog.QUERY, "execute_query", query);

        //Make a call to the internal method with a retry count of 0.  This will
        //initiate a retry call stack if required and supported.  The separation between the
        //calling stack and the target method is made because the target method may call itself
        //recursively.
        return this.executeQuery(query, row, 0);
    }

    /**
     * INTERNAL:
     * Return the results from executing the database query.
     * the arguments should be a database row with raw data values.
     */
    public Object executeQuery(DatabaseQuery query, AbstractRecord row, int retryCount) throws DatabaseException {

        try {
            if (this.eventManager != null) {
                this.eventManager.preExecuteQuery(query);
            }
            Object result;
            if (isInProfile()) {
                result = getProfiler().profileExecutionOfQuery(query, row, this);
            } else {
                result = internalExecuteQuery(query, row);
            }
            if (this.eventManager != null) {
                this.eventManager.postExecuteQuery(query, result);
            }
            return result;
        } catch (RuntimeException exception) {
            if (exception instanceof QueryException) {
                QueryException queryException = (QueryException)exception;
                if (queryException.getQuery() == null) {
                    queryException.setQuery(query);
                }
                if (queryException.getQueryArgumentsRecord() == null) {
                    queryException.setQueryArguments(row);
                }
                if (queryException.getSession() == null) {
                    queryException.setSession(this);
                }
            } else if (exception instanceof DatabaseException) {
                DatabaseException databaseException = (DatabaseException)exception;
                if (databaseException.getQuery() == null) {
                    databaseException.setQuery(query);
                }
                if (databaseException.getQueryArgumentsRecord() == null) {
                    databaseException.setQueryArguments(row);
                }
                if (databaseException.getSession() == null) {
                    databaseException.setSession(this);
                }
                //if this query is a read query outside of a transaction then we may be able to retry the query
                if (!isInTransaction() && query.isReadQuery() && getDatasourceLogin() instanceof DatabaseLogin) {
                    final int count = getLogin().getQueryRetryAttemptCount();
                    //was the failure communication based?  (ie timeout)
                    if (databaseException.isCommunicationFailure() && retryCount < count) {
                        Object[] args = new Object[1];
                        args[0] = databaseException;
                        log(SessionLog.INFO, SessionLog.QUERY, "communication_failure_attempting_query_retry", args, null);
                        Object result = retryQuery(query, row, databaseException, retryCount, this);
                        if (result instanceof DatabaseException) {
                            exception = (DatabaseException)result;
                        } else {
                            return result;
                        }
                    }
                }
            }
            return handleException(exception);
        }
    }

    /**
     * INTERNAL:
     * A query execution failed due to an invalid query.
     * Re-connect and retry the query.
     */
    public Object retryQuery(DatabaseQuery query, AbstractRecord row, DatabaseException databaseException, int retryCount, AbstractSession executionSession) {
        DatabaseException exception = databaseException;
        //retry
        if (retryCount <= getLogin().getQueryRetryAttemptCount()) {
            try {
                // attempt to reconnect for a certain number of times.
                // servers may take some time to recover.
                ++retryCount;
                try {
                    //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(getLogin().getDelayBetweenConnectionAttempts());
                    }
                    return executionSession.executeQuery(query, row, retryCount);
                } catch (DatabaseException newException){
                    //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.
                    exception = newException;
                }
            } catch (InterruptedException ex) {
                //Ignore interrupted exception.
            }
        }
        return exception;
    }

    /**
     * PUBLIC:
     * Execute the call on the database and return the result.
     * The call must return a value, if no value is return executeNonSelectCall must be used.
     * The call can be a stored procedure call, SQL call or other type of call.
     * A vector of database rows is returned, database row implements Java 2 Map which should be used to access the data.
     * <p>Example:
     * <p>session.executeSelectingCall(new SQLCall("Select * from Employee");
     *
     * @see #executeNonSelectingCall(Call)
     */
    @Override
    public Vector executeSelectingCall(Call call) throws DatabaseException {
        DataReadQuery query = new DataReadQuery();
        query.setCall(call);
        query.setIsExecutionClone(true);
        return (Vector)executeQuery(query);
    }

    /**
     * PUBLIC:
     * Execute the sql on the database and return the result.
     * It must return a value, if no value is return executeNonSelectingSQL must be used.
     * A vector of database rows is returned, database row implements Java 2 Map which should be used to access the data.
      * Warning: Allowing an unverified SQL string to be passed into this
     * method makes your application vulnerable to SQL injection attacks.
     * <p>Example:
     * <p>session.executeSelectingCall("Select * from Employee");
     *
     * @see #executeSelectingCall(Call)
     */
    @Override
    public Vector executeSQL(String sqlString) throws DatabaseException {
        return executeSelectingCall(new SQLCall(sqlString));
    }

    /**
     * INTERNAL:
     * This should normally not be used, most sessions do not have a single accessor.
     * ServerSession has a set of connection pools.
     * ClientSession only has an accessor during a transaction.
     * SessionBroker has multiple accessors.
     * getAccessors() should be used to support partitioning.
     * To maintain backward compatibility, and to support certain cases that required a default accessor,
     * this returns the first accessor.
     */
    public Accessor getAccessor() {
        Collection<Accessor> accessors = getAccessors();
        if ((accessors == null) || accessors.isEmpty()) {
            return null;
        }
        if (accessors instanceof List) {
            return ((List<Accessor>)accessors).get(0);
        }
        return accessors.iterator().next();
    }

    /**
     * INTERNAL:
     * This should normally not be used, most sessions do not have specific accessors.
     * ServerSession has a set of connection pools.
     * ClientSession only has an accessor during a transaction.
     * SessionBroker has multiple accessors.
     * getAccessors() is used to support partitioning.
     * If the accessor is null, this lazy initializes one for backwardcompatibility with DatabaseSession.
     */
    public Collection<Accessor> getAccessors() {
        if ((this.accessors == null) && (this.project != null) && (this.project.getDatasourceLogin() != null)) {
            synchronized (this) {
                if ((this.accessors == null) && (this.project != null) && (this.project.getDatasourceLogin() != null)) {
                    // PERF: lazy init, not always required.
                    List<Accessor> newAccessors = new ArrayList(1);
                    newAccessors.add(this.project.getDatasourceLogin().buildAccessor());
                    this.accessors = newAccessors;
                }
            }
        }
        return this.accessors;
    }

    /**
     * INTERNAL:
     * Return the connections to use for the query execution.
     */
    public Collection<Accessor> getAccessors(Call call, AbstractRecord translationRow, DatabaseQuery query) {
        // Check for partitioning.
        Collection<Accessor> accessors = null;
        if (query.getPartitioningPolicy() != null) {
            accessors = query.getPartitioningPolicy().getConnectionsForQuery(this, query, translationRow);
            if (accessors != null) {
                return accessors;
            }
        }
        ClassDescriptor descriptor = query.getDescriptor();
        if ((descriptor != null) && (descriptor.getPartitioningPolicy() != null)) {
            accessors = descriptor.getPartitioningPolicy().getConnectionsForQuery(this, query, translationRow);
            if (accessors != null) {
                return accessors;
            }
        }
        if (this.partitioningPolicy != null) {
            accessors = this.partitioningPolicy.getConnectionsForQuery(this, query, translationRow);
            if (accessors != null) {
                return accessors;
            }
        }
        return accessors;
    }

    /**
     * INTERNAL:
     * Execute the call on each accessors and merge the results.
     */
    public Object basicExecuteCall(Call call, AbstractRecord translationRow, DatabaseQuery query) throws DatabaseException {
        Object result = null;

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

        try {
            if (query.getAccessors().size() == 1) {
                result = query.getAccessor().executeCall(call, translationRow, this);
            } else {
                RuntimeException exception = null;
                // Replication or partitioning may require execution on multiple connections.
                for (Accessor accessor : query.getAccessors()) {
                    Object object = null;
                    try {
                        object = accessor.executeCall(call, translationRow, this);
                    } catch (RuntimeException failed) {
                        // Catch any exceptions to allow execution on each connections.
                        // This is used to have DDL run on every database even if one db fails because table already exists.
                        if (exception == null) {
                            exception = failed;
                        }
                    }
                    if (call.isOneRowReturned()) {
                        // If one row is desired, then break on first hit.
                        if (object != null) {
                            result = object;
                            break;
                        }
                    } else if (call.isNothingReturned()) {
                        // If no return ensure row count is consistent, 0 if any 0, otherwise first number.
                        if (result == null) {
                            result = object;
                        } else {
                            if (object instanceof Integer) {
                                if (((Integer)result).intValue() != 0) {
                                    if (((Integer)object).intValue() != 0) {
                                        result = object;
                                    }
                                }
                            }
                        }
                    } else {
                        // Either a set of rows (union), or cursor (return).
                        if (result == null) {
                            result = object;
                        } else {
                            if (object instanceof List) {
                                ((List)result).addAll((List)object);
                            } else {
                                break; // Not sure what to do, so break (if a cursor, don't only want to open one cursor.
                            }
                        }
                    }
                }
                if (exception != null) {
                    throw exception;
                }
            }
        } finally {
            if (this.eventManager != null) {
                this.eventManager.postExecuteCall(call, result);
            }
        }
        return result;
    }

    /**
     * INTERNAL:
     */
    public ExposedNodeLinkedList getActiveCommandThreads() {
        if (activeCommandThreads == null) {
            activeCommandThreads = new ExposedNodeLinkedList();
        }

        return activeCommandThreads;
    }

    /**
     * PUBLIC:
     * Return the active session for the current active external (JTS) transaction.
     * This should only be used with JTS and will return the session if no external transaction exists.
     */
    @Override
    public org.eclipse.persistence.sessions.Session getActiveSession() {
        org.eclipse.persistence.sessions.Session activeSession = getActiveUnitOfWork();
        if (activeSession == null) {
            activeSession = this;
        }

        return activeSession;
    }

    /**
     * PUBLIC:
     * Return the active unit of work for the current active external (JTS) transaction.
     * This should only be used with JTS and will return null if no external transaction exists.
     */
    @Override
    public org.eclipse.persistence.sessions.UnitOfWork getActiveUnitOfWork() {
        if (hasExternalTransactionController()) {
            return getExternalTransactionController().getActiveUnitOfWork();
        }

        /* Steven Vo:  CR# 2517
           Get from the server session since the external transaction controller could be
           null out from the client session by TL WebLogic 5.1 to provide non-jts transaction
           operations
          */
        if (isClientSession()) {
            return ((org.eclipse.persistence.sessions.server.ClientSession)this).getParent().getActiveUnitOfWork();
        }

        return null;
    }

    /**
     * INTERNAL:
     * Returns the alias descriptors Map.
     */
    public Map getAliasDescriptors() {
        return project.getAliasDescriptors();
    }

    /**
     * ADVANCED:
     * Answers the past time this session is as of.  Indicates whether or not this
     * is a special historical session where all objects are read relative to a
     * particular point in time.
     * @return An immutable object representation of the past time.
     * <code>null</code> if no clause set, or this a regular session.
     * @see #acquireHistoricalSession(org.eclipse.persistence.history.AsOfClause)
     */
    @Override
    public AsOfClause getAsOfClause() {
        return null;
    }

    /**
     * INTERNAL:
     * Allow the session to be used from a session broker.
     */
    public AbstractSession getBroker() {
        return broker;
    }

    /**
     * INTERNAL:
     * The session that this query is executed against when not in transaction.
     * The session containing the shared identity map.
     * <p>
     * In most cases this is the root ServerSession or DatabaseSession.
     * <p>
     * In cases where objects are not to be cached in the global identity map
     * an alternate session may be returned:
     * <ul>
     * <li>A ClientSession if in transaction
     * <li>An isolated ClientSession or HistoricalSession
     * <li>A registered session of a root SessionBroker
     * </ul>
     */
    public AbstractSession getRootSession(DatabaseQuery query) {
        ClassDescriptor descriptor = null;
        if (query != null){
            descriptor = query.getDescriptor();
        }
        return getParentIdentityMapSession(descriptor, true, true);
    }

    /**
     * INTERNAL:
     * Gets the parent session.
     */
    public AbstractSession getParent() {
        return null;
    }

    /**
     * INTERNAL:
     * Gets the next link in the chain of sessions followed by a query's check
     * early return, the chain of sessions with identity maps all the way up to
     * the root session.
     */
    public AbstractSession getParentIdentityMapSession(DatabaseQuery query) {
        ClassDescriptor descriptor = null;
        if (query != null){
            descriptor = query.getDescriptor();
        }
        return getParentIdentityMapSession(descriptor, false, false);
    }

    /**
     * INTERNAL:
     * Gets the next link in the chain of sessions followed by a query's check
     * early return, the chain of sessions with identity maps all the way up to
     * the root session.
     * <p>
     * Used for session broker which delegates to registered sessions, or UnitOfWork
     * which checks parent identity map also.
     * @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 session we will execute the call on, not
     * the next step towards it.
     * @return this if there is no next link in the chain
     */
    public AbstractSession getParentIdentityMapSession(DatabaseQuery query, boolean canReturnSelf, boolean terminalOnly) {
        ClassDescriptor descriptor = null;
        if (query != null){
            descriptor = query.getDescriptor();
        }
        return getParentIdentityMapSession(descriptor, canReturnSelf, terminalOnly);
    }

    /**
     * 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
     */
    public AbstractSession getParentIdentityMapSession(ClassDescriptor descriptor, boolean canReturnSelf, boolean terminalOnly) {
        return this;
    }

    /**
     * INTERNAL:
     * Returns the default pessimistic lock timeout value.
     */
    public Integer getPessimisticLockTimeoutDefault() {
        return pessimisticLockTimeoutDefault;
    }

    public TimeUnit getPessimisticLockTimeoutUnitDefault() {
        return pessimisticLockTimeoutUnitDefault;
    }
    /**
     * PUBLIC:
     * Return the default query timeout for this session.
     * This timeout will apply to any queries that do not have a timeout set,
     * and that do not have a default timeout defined in their descriptor.
     */
    public int getQueryTimeoutDefault() {
        return queryTimeoutDefault;
    }

    public TimeUnit getQueryTimeoutUnitDefault() {
        return queryTimeoutUnitDefault;
    }

    @SuppressWarnings("unchecked")
    public <T> InjectionManager<T> getInjectionManager() {
        if (injectionManager == null){
            injectionManager = createInjectionManager(this.getProperty(PersistenceUnitProperties.CDI_BEANMANAGER));
        }
        return injectionManager;
    }

    /**
     * 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
     */
    public AbstractSession getExecutionSession(DatabaseQuery query) {
        return this;
    }

    /**
     * INTERNAL:
     * Return if the commit manager has been set.
     */
    public boolean hasCommitManager() {
        return commitManager != null;
    }

    /**
     * INTERNAL:
     * The commit manager is used to resolve referential integrity on commits of multiple objects.
     * All brokered sessions share the same commit manager.
     */
    public CommitManager getCommitManager() {
        if (hasBroker()) {
            return getBroker().getCommitManager();
        }

        // PERF: lazy init, not always required, not required for client sessions
        if (commitManager == null) {
            commitManager = new CommitManager(this);
        }
        return commitManager;
    }

    /**
     * INTERNAL:
     * Returns the set of read-only classes that gets assigned to each newly created UnitOfWork.
     *
     * @see org.eclipse.persistence.sessions.Project#setDefaultReadOnlyClasses(Collection)
     */
    public Vector getDefaultReadOnlyClasses() {
        //Bug#3911318  All brokered sessions share the same DefaultReadOnlyClasses.
        if (hasBroker()) {
            return getBroker().getDefaultReadOnlyClasses();
        }
        return getProject().getDefaultReadOnlyClasses();
    }

    /**
     * ADVANCED:
     * Return the descriptor specified for the class.
     * If the class does not have a descriptor but implements an interface that is also implemented
     * by one of the classes stored in the map, that descriptor will be stored under the
     * new class. If a descriptor does not exist for the Class parameter, null is returned.
     * If the passed Class parameter is null, then null will be returned.
     */
    @Override
    public ClassDescriptor getClassDescriptor(Class theClass) {
        if (theClass == null) {
            return null;
        }
        return getDescriptor(theClass);
    }

    /**
     * ADVANCED:
     * Return the descriptor specified for the object's class.
     * If a descriptor does not exist for the Object parameter, null is returned.
     * If the passed Object parameter is null, then null will be returned.
     */
    @Override
    public ClassDescriptor getClassDescriptor(Object domainObject) {
        if (domainObject == null) {
            return null;
        }
        return getDescriptor(domainObject);
    }

    /**
     * PUBLIC:
     * Return the descriptor for  the alias.
     * UnitOfWork delegates this to the parent
     */
    @Override
    public ClassDescriptor getClassDescriptorForAlias(String alias) {
        return project.getDescriptorForAlias(alias);
    }

    /**
     * ADVANCED:
     * Return the descriptor specified for the class.
     * If the class does not have a descriptor but implements an interface that is also implemented
     * by one of the classes stored in the map, that descriptor will be stored under the
     * new class. If the passed Class is null, null will be returned.
     */
    @Override
    public ClassDescriptor getDescriptor(Class theClass) {
        if (theClass == null) {
            return null;
        }

        // Optimize descriptor lookup through caching the last one accessed.
        ClassDescriptor descriptor = this.lastDescriptorAccessed;
        if ((descriptor != null) && (descriptor.getJavaClass() == theClass)) {
            return descriptor;
        }

        if (this.descriptors != null) {
            descriptor = this.descriptors.get(theClass);
        } else {
            descriptor = this.project.getDescriptors().get(theClass);
        }

        if (descriptor == null) {
            if (hasBroker()) {
                // Also check the broker
                descriptor = getBroker().getDescriptor(theClass);
            }
            if (descriptor == null) {
                // Allow for an event listener to lazy register the descriptor for a class.
                if (this.eventManager != null) {
                    this.eventManager.missingDescriptor(theClass);
                }
                descriptor = getDescriptors().get(theClass);

                if (descriptor == null) {
                    // This allows for the correct descriptor to be found if the class implements an interface,
                    // or extends a class that a descriptor is registered for.
                    // This is used by EJB to find the descriptor for a stub and remote to unwrap it,
                    // and by inheritance to allow for subclasses that have no additional state to not require a descriptor.
                    if (!theClass.isInterface()) {
                        Class[] interfaces = theClass.getInterfaces();
                        for (int index = 0; index < interfaces.length; ++index) {
                            Class interfaceClass = interfaces[index];
                            descriptor = getDescriptor(interfaceClass);
                            if (descriptor != null) {
                                getDescriptors().put(interfaceClass, descriptor);
                                break;
                            }
                        }
                        if (descriptor == null ) {
                            descriptor = checkHierarchyForDescriptor(theClass);
                        }
                    }
                }
            }
        }

        // Cache for optimization.
        this.lastDescriptorAccessed = descriptor;

        return descriptor;
    }

    /**
     * ADVANCED:
     * Return the descriptor specified for the object's class.
     * If the passed Object is null, null will be returned.
     */
    @Override
    public ClassDescriptor getDescriptor(Object domainObject) {
        if (domainObject == null) {
            return null;
        }
        //Bug#3947714  Check and trigger the proxy here
        if (this.project.hasProxyIndirection()) {
            return getDescriptor(ProxyIndirectionPolicy.getValueFromProxy(domainObject).getClass());
        }
        return getDescriptor(domainObject.getClass());
    }

    /**
     * PUBLIC:
     * Return the descriptor for the alias.
     * @param alias The descriptor alias.
     * @return The descriptor for the alias or {@code null} if no descriptor was found.
     */
    @Override
    public ClassDescriptor getDescriptorForAlias(final String alias) {
        // If we have a descriptors list return our sessions descriptor and
        // not that of the project since we may be dealing with a multitenant
        // descriptor which will have been initialized locally on the session.
        // The project descriptor will be not initialized.
        final ClassDescriptor desc = project.getDescriptorForAlias(alias);
        if (desc != null && desc.hasMultitenantPolicy() && this.descriptors != null) {
            return this.descriptors.get(desc.getJavaClass());
        } else {
            return desc;
        }
    }

    /**
     * ADVANCED:
     * Return all registered descriptors.
     */
    @Override
    public Map<Class, ClassDescriptor> getDescriptors() {
        return this.project.getDescriptors();
    }

    /**
     * INTERNAL:
     * Return if an event manager has been set.
     */
    public boolean hasEventManager() {
        return eventManager != null;
    }

    /**
     * PUBLIC:
     * Return the event manager.
     * The event manager can be used to register for various session events.
     */
    @Override
    public SessionEventManager getEventManager() {
        if (eventManager == null) {
            synchronized (this) {
                if (eventManager == null) {
                    // PERF: lazy init.
                    eventManager = new SessionEventManager(this);
                }
            }
        }
        return eventManager;
    }

    /**
     * INTERNAL:
     * Return a string which represents my ExceptionHandler's class
     * Added for F2104: Properties.xml
     * - gn
     */
    public String getExceptionHandlerClass() {
        String className = null;
        try {
            className = getExceptionHandler().getClass().getName();
        } catch (Exception exception) {
            return null;
        }
        return className;
    }

    /**
     * PUBLIC:
     * Return the ExceptionHandler.Exception handler can catch errors that occur on queries or during database access.
     */
    @Override
    public ExceptionHandler getExceptionHandler() {
        return exceptionHandler;
    }

    /**
     * PUBLIC:
     * Used for JTS integration.  If your application requires to have JTS control transactions instead of EclipseLink an
     * external transaction controller must be specified.
     * EclipseLink provides JTS controllers for several JTS implementations including JTS 1.0, Weblogic 5.1 and WebSphere 3.0.
     *
     * @see org.eclipse.persistence.transaction.JTATransactionController
     */
    @Override
    public ExternalTransactionController getExternalTransactionController() {
        return externalTransactionController;
    }

    /**
     * PUBLIC:
     * The IdentityMapAccessor is the preferred way of accessing IdentityMap funcitons
     * This will return an object which implements an interface which exposes all public
     * IdentityMap functions.
     */
    @Override
    public org.eclipse.persistence.sessions.IdentityMapAccessor getIdentityMapAccessor() {
        return identityMapAccessor;
    }

    /**
     * INTERNAL:
     * Return the internally available IdentityMapAccessor instance.
     */
    public org.eclipse.persistence.internal.sessions.IdentityMapAccessor getIdentityMapAccessorInstance() {
        return identityMapAccessor;
    }

    /**
     * PUBLIC:
     * Returns the integrityChecker.IntegrityChecker holds all the ClassDescriptor Exceptions.
     */
    @Override
    public IntegrityChecker getIntegrityChecker() {
        // BUG# 2700595 - Lazily create an IntegrityChecker if one has not already been created.
        if (integrityChecker == null) {
            integrityChecker = new IntegrityChecker();
        }

        return integrityChecker;
    }

    /**
     * ADVANCED:
     * Return all pre-defined not yet parsed JPQL queries.
     */
    @Override
    public List<DatabaseQuery> getJPAQueries() {
        return getProject().getJPAQueries();
    }

    /**
     * ADVANCED:
     * Return all pre-defined not yet parsed JPQL queries.
     */
    public List<DatabaseQuery> getJPATablePerTenantQueries() {
        return getProject().getJPATablePerTenantQueries();
    }

    /**
     * PUBLIC:
     * Return the writer to which an accessor writes logged messages and SQL.
     * If not set, this reference defaults to a writer on System.out.
     * To enable logging, logMessages must be turned on.
     *
     * @see #setLoggingOff(boolean) 
     */
    @Override
    public Writer getLog() {
        return getSessionLog().getWriter();
    }

    /**
     * INTERNAL:
     * Return the name of the session: class name + system hashcode.
     * <p>
     * This should be the implementation of toString(), and also the
     * value should be calculated in the constructor for it is used all the
     * time.  However everything is lazily initialized now and the value is
     * transient for the system hashcode could vary?
     */
    public String getLogSessionString() {
        if (logSessionString == null) {
            StringWriter writer = new StringWriter();
            writer.write(getSessionTypeString());
            writer.write("(");
            writer.write(String.valueOf(System.identityHashCode(this)));
            writer.write(")");
            logSessionString = writer.toString();
        }
        return logSessionString;
    }

    /**
     * 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.
     */
    public String getSessionTypeString() {
        return Helper.getShortClassName(getClass());
    }

    /**
     * INTERNAL:
     * Return the static metamodel class associated with the given model class
     * if available. Callers must handle null.
     */
    public String getStaticMetamodelClass(String modelClassName) {
        if (staticMetamodelClasses != null) {
            return staticMetamodelClasses.get(modelClassName);
        }

        return null;
    }

    /**
     * OBSOLETE:
     * Return the login, the login holds any database connection information given.
     * This has been replaced by getDatasourceLogin to make use of the Login interface
     * to support non-relational datasources,
     * if DatabaseLogin API is required it will need to be cast.
     */
    @Override
    public DatabaseLogin getLogin() {
        try {
            return (DatabaseLogin)getDatasourceLogin();
        } catch (ClassCastException wrongType) {
            throw ValidationException.notSupportedForDatasource();
        }
    }

    /**
     * PUBLIC:
     * Return the login, the login holds any database connection information given.
     * This return the Login interface and may need to be cast to the datasource specific implementation.
     */
    @Override
    public Login getDatasourceLogin() {
        if (this.project == null) {
            return null;
        }
        return this.project.getDatasourceLogin();
    }

    /**
     * INTERNAL:
     * Return the mapped superclass descriptor if one exists for the given
     * class name. Must check any broker as well.
     */
    public ClassDescriptor getMappedSuperclass(String className) {
        ClassDescriptor desc = getProject().getMappedSuperclass(className);

        if (desc == null && hasBroker()) {
            getBroker().getMappedSuperclass(className);
        }

        return desc;
    }

    /**
     * PUBLIC:
     * Return a set of multitenant context properties this session
     */
    public Set<String> getMultitenantContextProperties() {
        if (this.multitenantContextProperties == null) {
            this.multitenantContextProperties = new HashSet<>();
        }

        return this.multitenantContextProperties;
    }

    /**
     * PUBLIC:
     * Return the name of the session.
     * This is used with the session broker, or to give the session a more meaningful name.
     */
    @Override
    public String getName() {
        return name;
    }

    /**
     * ADVANCED:
     * Return the sequnce number from the database
     */
    @Override
    public Number getNextSequenceNumberValue(Class domainClass) {
        return (Number)getSequencing().getNextValue(domainClass);
    }

    /**
     * INTERNAL:
     * Return the number of units of work connected.
     */
    public int getNumberOfActiveUnitsOfWork() {
        return numberOfActiveUnitsOfWork;
    }

    /**
     * INTERNAL:
     * For use within the merge process this method will get an object from the shared
     * cache using a readlock.  If a readlock is unavailable then the merge manager will be
     * transitioned to deferred locks and a deferred lock will be used.
     */
    protected CacheKey getCacheKeyFromTargetSessionForMerge(Object implementation, ObjectBuilder builder, ClassDescriptor descriptor, MergeManager mergeManager){
      Object original = null;
       Object primaryKey = builder.extractPrimaryKeyFromObject(implementation, this, true);
       if (primaryKey == null) {
           return null;
       }
       CacheKey cacheKey = null;
       if (mergeManager == null){
           cacheKey = getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, implementation.getClass(), descriptor, true);
           if (cacheKey != null){
               cacheKey.checkReadLock();
           }
           return cacheKey;
       }

       cacheKey = getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, implementation.getClass(), descriptor, true);
       if (cacheKey != null) {
           if (cacheKey.acquireReadLockNoWait()) {
               original = cacheKey.getObject();
               cacheKey.releaseReadLock();
           } else {
               if (!mergeManager.isTransitionedToDeferredLocks()) {
                   getIdentityMapAccessorInstance().getWriteLockManager().transitionToDeferredLocks(mergeManager);
               }
               cacheKey.acquireDeferredLock();
               original = cacheKey.getObject();
               if (original == null) {
                   synchronized (cacheKey) {
                       if (cacheKey.isAcquired()) {
                           try {
                               cacheKey.wait();
                           } catch (InterruptedException e) {
                               //ignore and return
                           }
                       }
                       original = cacheKey.getObject();
                   }
               }
               cacheKey.releaseDeferredLock();
           }
       }
       return cacheKey;
    }

    /**
     * INTERNAL:
     * Return the database platform currently connected to.
     * The platform is used for database specific behavior.
     * NOTE: this must only be used for relational specific usage,
     * it will fail for non-relational datasources.
     */
    @Override
    public DatabasePlatform getPlatform() {
        // PERF: Cache the platform.
        if (platform == null) {
            platform = getDatasourceLogin().getPlatform();
        }
        return (DatabasePlatform)platform;
    }


    /**
     * INTERNAL:
     * Return the class loader for the session's application.
     * This loader should be able to load any application or EclipseLink class.
     */
    public ClassLoader getLoader() {
        return getDatasourcePlatform().getConversionManager().getLoader();
    }

    /**
     * INTERNAL:
     * Return the database platform currently connected to.
     * The platform is used for database specific behavior.
     */
    @Override
    public Platform getDatasourcePlatform() {
        // PERF: Cache the platform.
        if (platform == null) {
            platform = getDatasourceLogin().getDatasourcePlatform();
        }
        return platform;
    }

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

    /**
     * INTERNAL:
     * Return the database platform currently connected to
     * for specified class.
     * The platform is used for database specific behavior.
     */
    @Override
    public Platform getPlatform(Class domainClass) {
        // PERF: Cache the platform.
        if (platform == null) {
            platform = getDatasourcePlatform();
        }
        return platform;
    }

    /**
     * PUBLIC:
     * Return the profiler.
     * The profiler is a tool that can be used to determine performance bottlenecks.
     * The profiler can be queries to print summaries and configure for logging purposes.
     */
    @Override
    public SessionProfiler getProfiler() {
        return profiler;
    }

    /**
     * PUBLIC:
     * Return the project, the project holds configuartion information including the descriptors.
     */
    @Override
    public org.eclipse.persistence.sessions.Project getProject() {
        return project;
    }

    /**
     * ADVANCED:
     * Allow for user defined properties.
     */
    @Override
    public Map<String, Object> getProperties() {
        if (properties == null) {
            properties = new HashMap(5);
        }
        return properties;
    }

    /**
     * INTERNAL:
     * Allow to check for user defined properties.
     */
    public boolean hasProperties() {
        return ((properties != null) && !properties.isEmpty());
    }

    /**
     * INTERNAL:
     * Return list of table per tenant multitenant descriptors.
     */
    public boolean hasTablePerTenantDescriptors() {
        return (tablePerTenantDescriptors != null && ! tablePerTenantDescriptors.isEmpty());
    }

    /**
     * INTERNAL:
     * Return a list of table per tenant multitenant queries.
     */
    public boolean hasTablePerTenantQueries() {
        return (tablePerTenantQueries != null && ! tablePerTenantQueries.isEmpty());
    }

    /**
     * ADVANCED:
     * Returns the user defined property.
     */
    @Override
    public Object getProperty(String name) {
        if(this.properties==null){
            return null;
        }
        return getProperties().get(name);
    }

    /**
     * ADVANCED:
     * Return all pre-defined queries.
     */
    @Override
    public Map<String, List<DatabaseQuery>> getQueries() {
        // PERF: lazy init, not normally required.
        if (queries == null) {
            queries = new HashMap(5);
        }
        return queries;
    }

    /**
     * ADVANCED:
     * Return an attribute group of a particular name.
     */

    /**
     * ADVANCED
     * Return all predefined attribute groups
     */
    public Map<String, AttributeGroup> getAttributeGroups(){
        if (this.attributeGroups == null){
            this.attributeGroups = new HashMap<>(5);
        }
        return this.attributeGroups;
    }

    /**
     * INTERNAL:
     * Return the pre-defined queries in this session.
     * A single vector containing all the queries is returned.
     *
     * @see #getQueries()
     */
    public List<DatabaseQuery> getAllQueries() {
        Vector allQueries = new Vector();
        for (Iterator vectors = getQueries().values().iterator(); vectors.hasNext();) {
            allQueries.addAll((Vector)vectors.next());
        }
        return allQueries;
    }

    /**
     * PUBLIC:
     * 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) {
        return getQuery(name, null);
    }

    /**
     * PUBLIC:
     * Return the query from the session pre-defined queries with the given name and argument types.
     * This allows for common queries to be pre-defined, reused and executed by name.
     * This method should be used if the Session has multiple queries with the same name but
     * different arguments.
     *
     * @see #getQuery(String)
     */
    @Override
    public DatabaseQuery getQuery(String name, List arguments) {
        if (arguments instanceof Vector) {
            return getQuery(name, (Vector)arguments);
        } else {
            return getQuery(name, new Vector(arguments));
        }
    }

    /**
     * PUBLIC:
     * Return the query from the session pre-defined queries with the given name and argument types.
     * This allows for common queries to be pre-defined, reused and executed by name.
     * This method should be used if the Session has multiple queries with the same name but
     * different arguments.
     *
     * @see #getQuery(String)
     */
    public DatabaseQuery getQuery(String name, Vector arguments) {
        return getQuery(name, arguments, true);
    }

    /**
     * INTERNAL:
     * Return the query from the session pre-defined queries with the given name and argument types.
     * This allows for common queries to be pre-defined, reused and executed by name.
     * This method should be used if the Session has multiple queries with the same name but
     * different arguments.
     *
     * @param shouldSearchParent indicates whether parent should be searched if query not found.
     * @see #getQuery(String, List)
     */
    public DatabaseQuery getQuery(String name, Vector arguments, boolean shouldSearchParent) {
        Vector queries = (Vector)getQueries().get(name);
        if ((queries != null) && !queries.isEmpty()) {
            // Short circuit the simple, most common case of only one query.
            if (queries.size() == 1) {
                return (DatabaseQuery)queries.firstElement();
            }

            // CR#3754; Predrag; mar 19/2002;
            // We allow multiple named queries with the same name but
            // different argument set; we can have only one query with
            // no arguments; Vector queries is not sorted;
            // When asked for the query with no parameters the
            // old version did return the first query - wrong:
            // return (DatabaseQuery) queries.firstElement();
            int argumentTypesSize = 0;
            if (arguments != null) {
                argumentTypesSize = arguments.size();
            }
            Vector argumentTypes = new Vector(argumentTypesSize);
            for (int i = 0; i < argumentTypesSize; i++) {
                argumentTypes.addElement(arguments.elementAt(i).getClass());
            }
            for (Enumeration queriesEnum = queries.elements(); queriesEnum.hasMoreElements();) {
                DatabaseQuery query = (DatabaseQuery)queriesEnum.nextElement();
                if (Helper.areTypesAssignable(argumentTypes, query.getArgumentTypes())) {
                    return query;
                }
            }
        }
        if(shouldSearchParent) {
            AbstractSession parent = getParent();
            if(parent != null) {
                return parent.getQuery(name, arguments, true);
            }
        }
        return null;
    }

    /**
     * Returns an AttributeGroup by name
     */

    /**
     * INTERNAL:
     * Return the Sequencing object used by the session.
     */
    public Sequencing getSequencing() {
        return null;
    }

    /**
     * INTERNAL:
     * Return the session to be used for the class.
     * Used for compatibility with the session broker.
     */
    public AbstractSession getSessionForClass(Class domainClass) {
        if (hasBroker()) {
            return getBroker().getSessionForClass(domainClass);
        }
        return this;
    }

    /**
     * INTERNAL:
     * Return the session by name.
     * Used for compatibility with the session broker.
     */
    public AbstractSession getSessionForName(String name) throws ValidationException {
        if (hasBroker()) {
            return getBroker().getSessionForName(name);
        }
        return this;
    }

    /**
     * PUBLIC:
     * Return the session log to which an accessor logs messages and SQL.
     * If not set, this will default to a session log on a writer on System.out.
     * To enable logging, logMessages must be turned on.
     *
     * @see #setLoggingOff(boolean) 
     */
    @Override
    public SessionLog getSessionLog() {
        if (sessionLog == null) {
            setSessionLog(new DefaultSessionLog());
        }
        return sessionLog;
    }

    /**
     * INTERNAL:
     * Return list of table per tenant multitenant descriptors.
     */
    public List<ClassDescriptor> getTablePerTenantDescriptors() {
        if (tablePerTenantDescriptors == null) {
            tablePerTenantDescriptors = new ArrayList<>();
        }

        return tablePerTenantDescriptors;
    }

    /**
     * INTERNAL:
     * Return list of table per tenant multitenant descriptors.
     */
    public List<DatabaseQuery> getTablePerTenantQueries() {
        if (tablePerTenantQueries == null) {
            tablePerTenantQueries = new ArrayList<>();
        }

        return tablePerTenantQueries;
    }

    /**
     * INTERNAL:
     * The transaction mutex ensure mutual exclusion on transaction across multiple threads.
     */
    public ConcurrencyManager getTransactionMutex() {
        // PERF: not always required, defer.
        if (transactionMutex == null) {
            synchronized (this) {
                if (transactionMutex == null) {
                    transactionMutex = new ConcurrencyManager();
                }
            }
        }
        return transactionMutex;
    }

    /**
     * PUBLIC:
     * Allow any WARNING level exceptions that occur within EclipseLink to be logged and handled by the exception handler.
     */
    @Override
    public Object handleException(RuntimeException exception) throws RuntimeException {
        if ((exception instanceof EclipseLinkException)) {
            EclipseLinkException eclipseLinkException = (EclipseLinkException)exception;
            if (eclipseLinkException.getSession() == null) {
                eclipseLinkException.setSession(this);
            }

            //Bug#3559280  Avoid logging an exception twice
            if (!eclipseLinkException.hasBeenLogged()) {
                logThrowable(SessionLog.WARNING, null, exception);
                eclipseLinkException.setHasBeenLogged(true);
            }
        } else {
            logThrowable(SessionLog.WARNING, null, exception);
        }
        if (hasExceptionHandler()) {
            if (this.broker != null && this.broker.hasExceptionHandler()) {
                try {
                    return getExceptionHandler().handleException(exception);
                } catch (RuntimeException ex) {
                    // handle the original exception
                    return this.broker.getExceptionHandler().handleException(exception);
                }
            } else {
                return getExceptionHandler().handleException(exception);
            }
        } else {
            if (this.broker != null && this.broker.hasExceptionHandler()) {
                return this.broker.getExceptionHandler().handleException(exception);
            } else {
                throw exception;
            }
        }
    }

    /**
     * INTERNAL:
     * Allow the session to be used from a session broker.
     */
    public boolean hasBroker() {
        return broker != null;
    }


    /**
     * ADVANCED:
     * Return true if a descriptor exists for the given class.
     */
    @Override
    public boolean hasDescriptor(Class theClass) {
        if (theClass == null) {
            return false;
        }

        return getDescriptors().get(theClass) != null;
    }

    /**
     * PUBLIC:
     * Return if an exception handler is present.
     */
    @Override
    public boolean hasExceptionHandler() {
        if (exceptionHandler == null) {
            return false;
        }
        return true;
    }

    /**
     * PUBLIC:
     * Used for JTA integration.  If your application requires to have JTA control transactions instead of EclipseLink an
     * external transaction controler must be specified.  EclipseLink provides JTA controlers for JTA 1.0 and application
     * servers.
     * @see org.eclipse.persistence.transaction.JTATransactionController
     */
    @Override
    public boolean hasExternalTransactionController() {
        return externalTransactionController != null;
    }


    /**
     * INTERNAL:
     * Set up the IdentityMapManager.  This method allows subclasses of Session to override
     * the default IdentityMapManager functionality.
     */
    public void initializeIdentityMapAccessor() {
        this.identityMapAccessor = new org.eclipse.persistence.internal.sessions.IdentityMapAccessor(this, new IdentityMapManager(this));
    }

    /**
     * PUBLIC:
     * Insert the object and all of its privately owned parts into the database.
     * Insert should only be used if the application knows that the object is new,
     * otherwise writeObject should be used.
     * The insert operation can be customized through using an insert query.
     *
     * @exception DatabaseException if an error occurs on the database,
     * these include constraint violations, security violations and general database errors.
     *
     * @see InsertObjectQuery
     * @see #writeObject(Object)
     */
    public Object insertObject(Object domainObject) throws DatabaseException {
        InsertObjectQuery query = new InsertObjectQuery();
        query.setObject(domainObject);
        query.setIsExecutionClone(true);
        return executeQuery(query);
    }

    /**
     * INTERNAL:
     * Return the results from exeucting the database query.
     * The arguments should be a database row with raw data values.
     * This method is provided to allow subclasses to change the default querying behavior.
     * All querying goes through this method.
     */
    public Object internalExecuteQuery(DatabaseQuery query, AbstractRecord databaseRow) throws DatabaseException {
        return query.execute(this, databaseRow);
    }

    /**
     * INTERNAL:
     * Returns true if the session is a session Broker.
     */
    public boolean isBroker() {
        return false;
    }

    /**
     * INTERNAL:
     * Returns true if the session is in a session Broker.
     */
    public boolean isInBroker() {
        return isInBroker;
    }

    /**
     * PUBLIC:
     * Return if the class is defined as read-only.
     */
    public boolean isClassReadOnly(Class theClass) {
        ClassDescriptor descriptor = getDescriptor(theClass);
        return isClassReadOnly(theClass, descriptor);
    }

    /**
     * INTERNAL:
     * Return if the class is defined as read-only.
     * PERF: Pass descriptor to avoid re-lookup.
     */
    public boolean isClassReadOnly(Class theClass, ClassDescriptor descriptor) {
        if ((descriptor != null) && descriptor.shouldBeReadOnly()) {
            return true;
        }
        if (theClass != null) {
            return getDefaultReadOnlyClasses().contains(theClass);
        }
        return false;
    }

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

    /**
     * PUBLIC:
     * Return if this session is an isolated client session.
     */
    public boolean isIsolatedClientSession() {
        return false;
    }

    /**
     * PUBLIC:
     * Return if this session is an exclusive isolated client session.
     */
    public boolean isExclusiveIsolatedClientSession() {
        return false;
    }

    /**
     * PUBLIC:
     * Return if this session is connected to the database.
     */
    @Override
    public boolean isConnected() {
        if (getAccessor() == null) {
            return false;
        }

        return getAccessor().isConnected();
    }

    /**
     * PUBLIC:
     * Return if this session is a database session.
     */
    @Override
    public boolean isDatabaseSession() {
        return false;
    }

    /**
     * PUBLIC:
     * Return if this session is a distributed session.
     */
    @Override
    public boolean isDistributedSession() {
        return false;
    }

    /**
     * PUBLIC:
     * Return if a profiler is being used.
     */
    @Override
    public boolean isInProfile() {
        return isInProfile;
    }

    /**
     * PUBLIC:
     * Allow for user deactive a profiler
     */
    public void setIsInProfile(boolean inProfile) {
        this.isInProfile = inProfile;
    }

    /**
     * INTERNAL:
     * Set if this session is contained in a SessionBroker.
     */
    public void setIsInBroker(boolean isInBroker) {
        this.isInBroker = isInBroker;
    }

    /**
     * PUBLIC:
     * Return if this session's decendants should use finalizers.
     * The allows certain finalizers such as in ClientSession to be enabled.
     * These are disable by default for performance reasons.
     */
    @Override
    public boolean isFinalizersEnabled() {
        return isFinalizersEnabled;
    }

    /**
     * INTERNAL:
     * Register a finalizer to release this session.
     */
    public void registerFinalizer() {
        // Ensure the finalizer is referenced until the session is gc'd.
        setProperty("finalizer", new SessionFinalizer(this));
    }

    /**
     * INTERNAL:
     * Return if this session is a historical session.
     */
    public boolean isHistoricalSession() {
        return false;
    }

    /**
     * PUBLIC:
     * Set if this session's decendants should use finalizers.
     * The allows certain finalizers such as in ClientSession to be enabled.
     * These are disable by default for performance reasons.
     */
    @Override
    public void setIsFinalizersEnabled(boolean isFinalizersEnabled) {
        this.isFinalizersEnabled = isFinalizersEnabled;
    }

    /**
     * PUBLIC:
     * Return if the session is currently in the progress of a database transaction.
     * Because nested transactions are allowed check if the transaction mutex has been aquired.
     */
    public boolean isInTransaction() {
        return this.transactionMutex != null && this.transactionMutex.isAcquired();
    }

    /**
     * INTERNAL:
     * used to see if JPA Queries have been processed during initialization
     */
    public boolean isJPAQueriesProcessed(){
        return this.jpaQueriesProcessed;
    }

    /**
     * PUBLIC:
     * Returns true if Protected Entities should be built within this session
     */
    public boolean isProtectedSession(){
        return true;
    }

    /**
     * PUBLIC:
     * Return if this session is remote.
     */
    @Override
    public boolean isRemoteSession() {
        return false;
    }

    /**
     * PUBLIC:
     * Return if this session is a unit of work.
     */
    @Override
    public boolean isRemoteUnitOfWork() {
        return false;
    }

    /**
     * PUBLIC:
     * Return if this session is a server session.
     */
    @Override
    public boolean isServerSession() {
        return false;
    }

    /**
     * PUBLIC:
     * Return if this session is a session broker.
     */
    @Override
    public boolean isSessionBroker() {
        return false;
    }

    /**
     * INTERNAL:
     * Return if this session is synchronized.
     */
    public boolean isSynchronized() {
        return isSynchronized;
    }

    /**
     * PUBLIC:
     * Return if this session is a unit of work.
     */
    @Override
    public boolean isUnitOfWork() {
        return false;
    }

    /**
     * ADVANCED:
     * Extract and return the primary key from the object.
     */
    @Override
    public Object getId(Object domainObject) throws ValidationException {
        ClassDescriptor descriptor = getDescriptor(domainObject);
        return keyFromObject(domainObject, descriptor);
    }

    /**
     * ADVANCED:
     * Extract and return the primary key from the object.
     */
    public Object keyFromObject(Object domainObject, ClassDescriptor descriptor) throws ValidationException {
        if (descriptor == null) {
            throw ValidationException.missingDescriptor(domainObject.getClass().getName());
        }
        Object implemention = descriptor.getObjectBuilder().unwrapObject(domainObject, this);
        if (implemention == null) {
            return null;
        }
        return descriptor.getObjectBuilder().extractPrimaryKeyFromObject(implemention, this);
    }

    /**
     * PUBLIC:
     * Log the log entry.
     */
    @Override
    public void log(SessionLogEntry entry) {
        if (this.isLoggingOff) {
            return;
        }
        if (shouldLog(entry.getLevel(), entry.getNameSpace())) {
            if (entry.getSession() == null) {// Used for proxy session.
                entry.setSession(this);
            }
            getSessionLog().log(entry);
        }
    }

    /**
     * Log a untranslated message to the EclipseLink log at FINER level.
     */
    @Override
    public void logMessage(String message) {
        if (this.isLoggingOff) {
            return;
        }
        log(SessionLog.FINER, SessionLog.MISC, message, null, null, false);
    }

    /**
     * INTERNAL:
     * A call back to do session specific preparation of a query.
     * <p>
     * The call back occurs soon before we clone the query for execution,
     * meaning that if this method needs to clone the query then the caller will
     * determine that it doesn't need to clone the query itself.
     */
    public DatabaseQuery prepareDatabaseQuery(DatabaseQuery query) {
        if (!isUnitOfWork() && query.isObjectLevelReadQuery()) {
            return ((ObjectLevelReadQuery)query).prepareOutsideUnitOfWork(this);
        } else {
            return query;
        }
    }


    /**
     * PUBLIC:
     * Read all of the instances of the class from the database.
     * This operation can be customized through using a ReadAllQuery,
     * or through also passing in a selection criteria.
     *
     * @see ReadAllQuery
     * @see #readAllObjects(Class, Expression)
     */
    @Override
    public Vector readAllObjects(Class domainClass) throws DatabaseException {
        ReadAllQuery query = new ReadAllQuery();
        query.setIsExecutionClone(true);
        query.setReferenceClass(domainClass);
        return (Vector)executeQuery(query);
    }

    /**
     * PUBLIC:
     * Read all of the instances of the class from the database return through execution the SQL string.
     * The SQL string must be a valid SQL select statement or selecting stored procedure call.
     * This operation can be customized through using a ReadAllQuery.
      * Warning: Allowing an unverified SQL string to be passed into this
     * method makes your application vulnerable to SQL injection attacks.
     *
     * @see ReadAllQuery
     */
    public Vector readAllObjects(Class domainClass, String sqlString) throws DatabaseException {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(domainClass);
        query.setSQLString(sqlString);
        query.setIsExecutionClone(true);
        return (Vector)executeQuery(query);
    }

    /**
     * PUBLIC:
     * Read all the instances of the class from the database returned through execution the Call string.
     * The Call can be an SQLCall or JPQLCall.
     *
     * example: session.readAllObjects(Employee.class, new SQLCall("SELECT * FROM EMPLOYEE"));
     * @see Call
     */
    @Override
    public Vector readAllObjects(Class referenceClass, Call aCall) throws DatabaseException {
        ReadAllQuery raq = new ReadAllQuery();
        raq.setReferenceClass(referenceClass);
        raq.setCall(aCall);
        raq.setIsExecutionClone(true);
        return (Vector)executeQuery(raq);
    }

    /**
     * PUBLIC:
     * Read all of the instances of the class from the database matching the given expression.
     * This operation can be customized through using a ReadAllQuery.
     *
     * @see ReadAllQuery
     */
    @Override
    public Vector readAllObjects(Class domainClass, Expression expression) throws DatabaseException {
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(domainClass);
        query.setSelectionCriteria(expression);
        query.setIsExecutionClone(true);
        return (Vector)executeQuery(query);
    }

    /**
     * PUBLIC:
     * Read the first instance of the class from the database.
     * This operation can be customized through using a ReadObjectQuery,
     * or through also passing in a selection criteria.
     *
     * @see ReadObjectQuery
     * @see #readAllObjects(Class, Expression)
     */
    @Override
    public Object readObject(Class domainClass) throws DatabaseException {
        ReadObjectQuery query = new ReadObjectQuery();
        query.setReferenceClass(domainClass);
        query.setIsExecutionClone(true);
        return executeQuery(query);
    }

    /**
     * PUBLIC:
     * Read the first instance of the class from the database return through execution the SQL string.
     * The SQL string must be a valid SQL select statement or selecting stored procedure call.
     * This operation can be customized through using a ReadObjectQuery.
      * Warning: Allowing an unverified SQL string to be passed into this
     * method makes your application vulnerable to SQL injection attacks.
     *
     * @see ReadObjectQuery
     */
    public Object readObject(Class domainClass, String sqlString) throws DatabaseException {
        ReadObjectQuery query = new ReadObjectQuery();
        query.setReferenceClass(domainClass);
        query.setSQLString(sqlString);
        query.setIsExecutionClone(true);
        return executeQuery(query);
    }

    /**
     * PUBLIC:
     * Read the first instance of the class from the database returned through execution the Call string.
     * The Call can be an SQLCall or JPQLCall.
     *
     * example: session.readObject(Employee.class, new SQLCall("SELECT * FROM EMPLOYEE"));
     * @see SQLCall
     * @see JPQLCall
     */
    @Override
    public Object readObject(Class domainClass, Call aCall) throws DatabaseException {
        ReadObjectQuery query = new ReadObjectQuery();
        query.setReferenceClass(domainClass);
        query.setCall(aCall);
        query.setIsExecutionClone(true);
        return executeQuery(query);
    }

    /**
     * PUBLIC:
     * Read the first instance of the class from the database matching the given expression.
     * This operation can be customized through using a ReadObjectQuery.
     *
     * @see ReadObjectQuery
     */
    @Override
    public Object readObject(Class domainClass, Expression expression) throws DatabaseException {
        ReadObjectQuery query = new ReadObjectQuery();
        query.setReferenceClass(domainClass);
        query.setSelectionCriteria(expression);
        query.setIsExecutionClone(true);
        return executeQuery(query);
    }

    /**
     * PUBLIC:
     * Use the example object to consruct a read object query by the objects primary key.
     * This will read the object from the database with the same primary key as the object
     * or null if no object is found.
     */
    @Override
    public Object readObject(Object object) throws DatabaseException {
        ReadObjectQuery query = new ReadObjectQuery();
        query.setSelectionObject(object);
        query.setIsExecutionClone(true);
        return executeQuery(query);
    }

    /**
     * PUBLIC:
     * Refresh the attributes of the object and of all of its private parts from the database.
     * The object will be pessimisticly locked on the database for the duration of the transaction.
     * If the object is already locked this method will wait until the lock is released.
     * A no wait option is available through setting the lock mode.
     * @see #refreshAndLockObject(Object, short)
     */
    public Object refreshAndLockObject(Object object) throws DatabaseException {
        return refreshAndLockObject(object, ObjectBuildingQuery.LOCK);
    }

    /**
     * PUBLIC:
     * Refresh the attributes of the object and of all of its private parts from the database.
     * The object will be pessimisticly locked on the database for the duration of the transaction.
     * <p>Lock Modes: ObjectBuildingQuery.NO_LOCK, LOCK, LOCK_NOWAIT
     */
    public Object refreshAndLockObject(Object object, short lockMode) throws DatabaseException {
        ReadObjectQuery query = new ReadObjectQuery();
        query.setSelectionObject(object);
        query.refreshIdentityMapResult();
        query.cascadePrivateParts();
        query.setLockMode(lockMode);
        query.setIsExecutionClone(true);
        return executeQuery(query);
    }

    /**
     * PUBLIC:
     * Refresh the attributes of the object and of all of its private parts from the database.
     * This can be used to ensure the object is up to date with the database.
     * Caution should be used when using this to make sure the application has no un commited
     * changes to the object.
     */
    @Override
    public Object refreshObject(Object object) throws DatabaseException {
        return refreshAndLockObject(object, ObjectBuildingQuery.NO_LOCK);
    }

    /**
     * PUBLIC:
     * Release the session.
     * This does nothing by default, but allows for other sessions such as the ClientSession to do something.
     */
    @Override
    public void release() {
    }

    /**
     * INTERNAL:
     * Release the unit of work, if lazy release the connection.
     */
    public void releaseUnitOfWork(UnitOfWorkImpl unitOfWork) {
        // Nothing is required by default, allow subclasses to do cleanup.
        setNumberOfActiveUnitsOfWork(getNumberOfActiveUnitsOfWork() - 1);
    }


    /**
     * PUBLIC:
     * Remove the user defined property.
     */
    @Override
    public void removeProperty(String property) {
        getProperties().remove(property);
    }

    /**
     * PUBLIC:
     * Remove all queries with the given queryName regardless of the argument types.
     *
     * @see #removeQuery(String, Vector)
     */
    @Override
    public void removeQuery(String queryName) {
        getQueries().remove(queryName);
    }

    /**
     * PUBLIC:
     * Remove the specific query with the given queryName and argumentTypes.
     */
    public void removeQuery(String queryName, Vector argumentTypes) {
        Vector queries = (Vector)getQueries().get(queryName);
        if (queries == null) {
            return;
        } else {
            DatabaseQuery query = null;
            for (Enumeration enumtr = queries.elements(); enumtr.hasMoreElements();) {
                query = (DatabaseQuery)enumtr.nextElement();
                if (Helper.areTypesAssignable(argumentTypes, query.getArgumentTypes())) {
                    break;
                }
            }
            if (query != null) {
                queries.remove(query);
            }
        }
    }

    /**
     * PROTECTED:
     * Attempts to rollback the running internally started external transaction.
     * Returns true only in one case -
     * extenal transaction has been internally rolled back during this method call:
     * wasJTSTransactionInternallyStarted()==true in the beginning of this method and
     * wasJTSTransactionInternallyStarted()==false in the end of this method.
     */
    protected boolean rollbackExternalTransaction() {
        boolean externalTransactionHasRolledBack = false;
        if (hasExternalTransactionController() && wasJTSTransactionInternallyStarted()) {
            try {
                getExternalTransactionController().rollbackTransaction(this);
            } catch (RuntimeException exception) {
                handleException(exception);
            }
            if (!wasJTSTransactionInternallyStarted()) {
                externalTransactionHasRolledBack = true;
                log(SessionLog.FINER, SessionLog.TRANSACTION, "external_transaction_has_rolled_back_internally");
            }
        }
        return externalTransactionHasRolledBack;
    }

    /**
     * PUBLIC:
     * Rollback the active database transaction.
     * This allows a group of database modification to be commited or rolledback as a unit.
     * All writes/deletes will be sent to the database be will not be visible to other users until commit.
     * Although databases do not allow nested transaction,
     * EclipseLink supports nesting through only committing to the database on the outer commit.
     *
     * @exception DatabaseException if the database connection is lost or the rollback fails.
     * @exception ConcurrencyException if this session is not within a transaction.
     */
    public void rollbackTransaction() throws DatabaseException, ConcurrencyException {
        ConcurrencyManager mutex = getTransactionMutex();
        // Ensure release of mutex and call subclass specific release.
        try {
            if (!mutex.isNested()) {
                if (this.eventManager != null) {
                    this.eventManager.preRollbackTransaction();
                }
                basicRollbackTransaction();
                if (this.eventManager != null) {
                    this.eventManager.postRollbackTransaction();
                }
            }
        } finally {
            mutex.release();

            // If there is no db transaction in progress
            // if there is an active external transaction
            // which was started internally - it should be rolled back internally, too.
            if (!mutex.isAcquired()) {
                rollbackExternalTransaction();
            }
        }
    }

    /**
     * INTERNAL:
     * Set the accessor.
     */
    public void setAccessor(Accessor accessor) {
        this.accessors = new ArrayList(1);
        this.accessors.add(accessor);
    }

    /**
     * INTERNAL:
     * Allow the session to be used from a session broker.
     */
    public void setBroker(AbstractSession broker) {
        this.broker = broker;
    }


    /**
     * INTERNAL:
     * The commit manager is used to resolve referncial integrity on commits of multiple objects.
     */
    public void setCommitManager(CommitManager commitManager) {
        this.commitManager = commitManager;
    }

    public void setInjectionManager(
            InjectionManager injectionManager) {
        this.injectionManager = injectionManager;
    }

    /**
     * INTERNAL:
     * Set the event manager.
     * The event manager can be used to register for various session events.
     */
    public void setEventManager(SessionEventManager eventManager) {
        this.eventManager = eventManager;
        if (eventManager != null) {
            this.eventManager.setSession(this);
        }
    }

    /**
     * PUBLIC:
     * Set the exceptionHandler.
     * Exception handler can catch errors that occur on queries or during database access.
     */
    @Override
    public void setExceptionHandler(ExceptionHandler exceptionHandler) {
        this.exceptionHandler = exceptionHandler;
    }

    /**
     * Used for JTS integration internally by ServerPlatform.
     */
    @Override
    public void setExternalTransactionController(ExternalTransactionController externalTransactionController) {
        this.externalTransactionController = externalTransactionController;
        if (externalTransactionController == null) {
            return;
        }
        if (!hasBroker()) {
            externalTransactionController.setSession(this);
        }
    }

    /**
     * PUBLIC:
     * set the integrityChecker. IntegrityChecker holds all the ClassDescriptor Exceptions.
     */
    @Override
    public void setIntegrityChecker(IntegrityChecker integrityChecker) {
        this.integrityChecker = integrityChecker;
    }

    /**
     * INTERNAL:
     * used to set if JPA Queries have been processed during initialization
     */
    public void setJPAQueriesProcessed(boolean jpaQueriesProcessed){
        this.jpaQueriesProcessed = jpaQueriesProcessed;
    }

    /**
     * PUBLIC:
     * Set the writer to which an accessor writes logged messages and SQL.
     * If not set, this reference defaults to a writer on System.out.
     * To enable logging logMessages() is used.
     *
     * @see #setLoggingOff(boolean) 
     */
    @Override
    public void setLog(Writer log) {
        getSessionLog().setWriter(log);
    }

    /**
     * PUBLIC:
     * Set the login.
     */
    public void setLogin(DatabaseLogin login) {
        setDatasourceLogin(login);
    }

    /**
     * PUBLIC:
     * Set the login.
     */
    public void setLogin(Login login) {
        setDatasourceLogin(login);
    }

    /**
     * PUBLIC:
     * Set the login.
     */
    public void setDatasourceLogin(Login login) {
        getProject().setDatasourceLogin(login);
        this.platform = null;
    }

    /**
     * PUBLIC:
     * Set the name of the session.
     * This is used with the session broker.
     */
    @Override
    public void setName(String name) {
        this.name = name;
    }

    protected void setNumberOfActiveUnitsOfWork(int numberOfActiveUnitsOfWork) {
        this.numberOfActiveUnitsOfWork = numberOfActiveUnitsOfWork;
    }

    /**
     * PUBLIC:
     * Set the default pessimistic lock timeout value. This value will be used
     * to set the WAIT clause of a SQL SELECT FOR UPDATE statement. It defines
     * how long EcliseLink should wait for a lock on the database row before
     * aborting.
     */
    public void setPessimisticLockTimeoutDefault(Integer pessimisticLockTimeoutDefault) {
        this.pessimisticLockTimeoutDefault = pessimisticLockTimeoutDefault;
    }
    
    public void setPessimisticLockTimeoutUnitDefault(TimeUnit pessimisticLockTimeoutUnitDefault) {
        this.pessimisticLockTimeoutUnitDefault = pessimisticLockTimeoutUnitDefault;
    }
    /**
     * PUBLIC:
     * Set the default query timeout for this session.
     * This timeout will apply to any queries that do not have a timeout set,
     * and that do not have a default timeout defined in their descriptor.
     */
    @Override
    public void setQueryTimeoutDefault(int queryTimeoutDefault) {
        this.queryTimeoutDefault = queryTimeoutDefault;
    }

    @Override
    public void setQueryTimeoutUnitDefault(TimeUnit queryTimeoutUnitDefault) {
        this.queryTimeoutUnitDefault = queryTimeoutUnitDefault;
    }

    /**
     * PUBLIC:
     * Set the profiler for the session.
     * This allows for performance operations to be profiled.
     */
    @Override
    public void setProfiler(SessionProfiler profiler) {
        this.profiler = profiler;
        if (profiler != null) {
            profiler.setSession(this);
            setIsInProfile(getProfiler().getProfileWeight() != SessionProfiler.NONE);
            // Clear cached flag that bypasses the profiler check.
            getIdentityMapAccessorInstance().getIdentityMapManager().checkIsCacheAccessPreCheckRequired();
        } else {
            setIsInProfile(false);
        }
    }

    /**
     * INTERNAL:
     * Set the project, the project holds configuration information including the descriptors.
     */
    public void setProject(org.eclipse.persistence.sessions.Project project) {
        this.project = project;
    }

    /**
     * INTERNAL:
     * Set the user defined properties by shallow copying the propertiesMap.
     * @param propertiesMap
     */
    public void setProperties(Map<String, Object> propertiesMap) {
        if (null == propertiesMap) {
            // Keep current behavior and set properties map to null
            properties = null;
        } else {
            /*
             * Bug# 219097 Clone as (HashMap) possible immutable maps to avoid
             * an UnsupportedOperationException on a later put() We do not know
             * the key:value type values at design time. putAll() is not
             * synchronized. We clone all maps whether immutable or not.
             */
            properties = new HashMap();
            // Shallow copy all internal key:value pairs - a null propertiesMap will throw a NPE
            properties.putAll(propertiesMap);
        }
    }

    /**
     * PUBLIC: Allow for user defined properties.
     */
    @Override
    public void setProperty(String propertyName, Object propertyValue) {
        getProperties().put(propertyName, propertyValue);
    }

    /**
     * INTERNAL:
     * Set the named queries.
     */
    public void setQueries(Map<String, List<DatabaseQuery>> queries) {
        this.queries = queries;
    }

    /**
     * PUBLIC:
     * Set the session log to which an accessor logs messages and SQL.
     * If not set, this will default to a session log on a writer on System.out.
     * To enable logging, log level can not be OFF.
     * Also set a backpointer to this session in SessionLog.
     *
     * @see #logMessage(String)
     */
    @Override
    public void setSessionLog(SessionLog sessionLog) {
        this.isLoggingOff = false;
        this.sessionLog = sessionLog;
        if ((sessionLog != null) && (sessionLog.getSession() == null)) {
            sessionLog.setSession(this);
        }
    }

    /**
     * INTERNAL:
     * Set isSynchronized flag to indicate that this session is synchronized.
     * This method should only be called by setSynchronized methods of derived classes.
     */
    public void setSynchronized(boolean synched) {
        isSynchronized = synched;
    }

    protected void setTransactionMutex(ConcurrencyManager transactionMutex) {
        this.transactionMutex = transactionMutex;
    }

    /**
     * INTERNAL:
     * Return if a JTS transaction was started by the session.
     * The session will start a JTS transaction if a unit of work or transaction is begun without a JTS transaction present.
     */
    public void setWasJTSTransactionInternallyStarted(boolean wasJTSTransactionInternallyStarted) {
        this.wasJTSTransactionInternallyStarted = wasJTSTransactionInternallyStarted;
    }

    /**
     * PUBLIC:
     * Return if logging is enabled (false if log level is OFF)
     */
    @Override
    public boolean shouldLogMessages() {
        if (this.isLoggingOff) {
            return false;
        }
        if (getLogLevel(null) == SessionLog.OFF) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * INTERNAL:
     * Start the operation timing.
     */
    @Override
    public void startOperationProfile(String operationName) {
        if (this.isInProfile) {
            getProfiler().startOperationProfile(operationName);
        }
    }

    /**
     * INTERNAL:
     * Start the operation timing.
     */
    public void startOperationProfile(String operationName, DatabaseQuery query, int weight) {
        if (this.isInProfile) {
            getProfiler().startOperationProfile(operationName, query, weight);
        }
    }

    /**
     * Print the connection status with the session.
     */
    @Override
    public String toString() {
        StringWriter writer = new StringWriter();
        writer.write(getSessionTypeString() + "(" + Helper.cr() + "\t" + getAccessor() + Helper.cr() + "\t" + getDatasourcePlatform() + ")");
        return writer.toString();
    }

    /**
     * INTERNAL:
     * Unwrap the object if required.
     * This is used for the wrapper policy support and EJB.
     */
    public Object unwrapObject(Object proxy) {
        return getDescriptor(proxy).getObjectBuilder().unwrapObject(proxy, this);
    }

    /**
     * PUBLIC:
     * Update the object and all of its privately owned parts in the database.
     * Update should only be used if the application knows that the object is new,
     * otherwise writeObject should be used.
     * The update operation can be customized through using an update query.
     *
     * @exception DatabaseException if an error occurs on the database,
     * these include constraint violations, security violations and general database errors.
     * @exception OptimisticLockException if the object's descriptor is using optimistic locking and
     * the object has been updated or deleted by another user since it was last read.
     *
     * @see UpdateObjectQuery
     * @see #writeObject(Object)
     */
    public Object updateObject(Object domainObject) throws DatabaseException, OptimisticLockException {
        UpdateObjectQuery query = new UpdateObjectQuery();
        query.setObject(domainObject);
        query.setIsExecutionClone(true);
        return executeQuery(query);
    }

    /**
     * ADVANCED:
     * This can be used to help debugging an object identity problem.
     * An object identity problem is when an object in the cache references an object not in the cache.
     * This method will validate that all cached objects are in a correct state.
     */
    @Override
    public void validateCache() {
        getIdentityMapAccessorInstance().validateCache();
    }

    /**
     * INTERNAL:
     * This method will be used to update the query with any settings required
     * For this session.  It can also be used to validate execution.
     */
    public void validateQuery(DatabaseQuery query) {
        // a no-op for this class
    }

    /**
     * TESTING:
     * This is used by testing code to ensure that a deletion was successful.
     */
    public boolean verifyDelete(Object domainObject) {
        ObjectBuilder builder = getDescriptor(domainObject).getObjectBuilder();
        Object implementation = builder.unwrapObject(domainObject, this);

        return builder.verifyDelete(implementation, this);
    }

    /**
     * INTERNAL:
     * Return if a JTS transaction was started by the session.
     * The session will start a JTS transaction if a unit of work or transaction is begun without a JTS transaction present.
     */
    public boolean wasJTSTransactionInternallyStarted() {
        return wasJTSTransactionInternallyStarted;
    }

    /**
     * INTERNAL:
     * Wrap the object if required.
     * This is used for the wrapper policy support and EJB.
     */
    public Object wrapObject(Object implementation) {
        return getDescriptor(implementation).getObjectBuilder().wrapObject(implementation, this);
    }

    /**
     * INTERNAL:
     * Write all of the objects and all of their privately owned parts in the database.
     * The allows for a group of new objects to be commited as a unit.
     * The objects will be commited through a single transactions and any
     * foreign keys/circular references between the objects will be resolved.
     */
    protected void writeAllObjectsWithChangeSet(UnitOfWorkChangeSet uowChangeSet) throws DatabaseException, OptimisticLockException {
        getCommitManager().commitAllObjectsWithChangeSet(uowChangeSet);
    }

    /**
     * PUBLIC:
     * Write the object and all of its privately owned parts in the database.
     * Write will determine if an insert or an update should be done,
     * it may go to the database to determine this (by default will check the identity map).
     * The write operation can be customized through using an write query.
     *
     * @exception DatabaseException if an error occurs on the database,
     * these include constraint violations, security violations and general database errors.
     * @exception OptimisticLockException if the object's descriptor is using optimistic locking and
     * the object has been updated or deleted by another user since it was last read.
     *
     * @see WriteObjectQuery
     * @see #insertObject(Object)
     * @see #updateObject(Object)
     */
    public Object writeObject(Object domainObject) throws DatabaseException, OptimisticLockException {
        WriteObjectQuery query = new WriteObjectQuery();
        query.setObject(domainObject);
        query.setIsExecutionClone(true);
        return executeQuery(query);
    }

    /**
     * INTERNAL:
     * This method notifies the accessor that a particular sets of writes has
     * completed.  This notification can be used for such thing as flushing the
     * batch mechanism
     */
    public void writesCompleted() {
        if (getAccessors() == null) {
            return;
        }
        for (Accessor accessor : getAccessors()) {
            accessor.writesCompleted(this);
    }
    }

    /**
      * INTERNAL:
      * RemoteCommandManager method. This is a required method in order
      * to implement the CommandProcessor interface.
      * Process the remote command from the RCM. The command may have come from
      * any remote session or application. Since this is a EclipseLink session we can
      * always assume that the object that we receive here will be a Command object.
      */
    @Override
    public void processCommand(Object command) {
        ((Command)command).executeWithSession(this);
    }

    /**
     * INTERNAL:
     * Process the JPA named queries into EclipseLink Session queries. This
     * method is called after descriptor initialization.
     * Temporarily made public for ODI. Should not be used elsewhere.
     */
    public void processJPAQueries() {
        if (! jpaQueriesProcessed) {
            // Process the JPA queries that do not query table per tenant entities.
            for (DatabaseQuery jpaQuery : getJPAQueries()) {
                processJPAQuery(jpaQuery);
            }

            // Process the JPA queries that query table per tenant entities. At
            // the EMF level, these queries will be initialized and added right
            // away. At the EM level we must defer their initialization to each
            // individual client session.
            for (DatabaseQuery jpaQuery : getJPATablePerTenantQueries()) {
                boolean processQuery = true;

                for (ClassDescriptor descriptor : jpaQuery.getDescriptors()) {
                    // If the descriptor is not fully initialized then we can
                    // not initialize the query and must isolate it to be
                    // initialized and stored per client session (EM).
                    if (! descriptor.isFullyInitialized()) {
                        processQuery = false;
                        break;
                    }
                }

                if (processQuery) {
                    processJPAQuery(jpaQuery);
                } else {
                    addTablePerTenantQuery(jpaQuery);
                }
            }

            jpaQueriesProcessed = true;
        }
    }

    /**
     * INTERNAL:
     * Process the JPA named query into an EclipseLink Session query. This
     * method is called after descriptor initialization.
     */
    protected void processJPAQuery(DatabaseQuery jpaQuery) {
        // This is a hack, to allow the core Session to initialize JPA queries, without have a dependency on JPA.
        // They need to be initialized after login, as the database platform must be known.
        try {
            jpaQuery.prepareInternal(this);
        } catch (RuntimeException re) {
            // If jpql-tolerate-error==true, any problems will be ignored at query prep time and the runtime will
            // continue chugging along. The invalid query will be left in place so that an exception
            // will be thrown at runtime if a user attempts to use it.
            if (!tolerateInvalidJPQL) {
                throw re;
            }
        }
        DatabaseQuery databaseQuery = (DatabaseQuery) jpaQuery.getProperty("databasequery");
        databaseQuery = (databaseQuery == null) ? jpaQuery : databaseQuery;
        addQuery(databaseQuery, false); // this should be true but for backward compatibility it
                                        // is set to false.
    }

    /**
     * PUBLIC:
     * Return the CommandManager that allows this session to act as a
     * CommandProcessor and receive or propagate commands from/to the
     * EclipseLink cluster.
     *
     * @see CommandManager
     * @return The CommandManager instance that controls the remote command
     * service for this session
     */
    @Override
    public CommandManager getCommandManager() {
        return commandManager;
    }

    /**
     * ADVANCED:
     * Set the CommandManager that allows this session to act as a
     * CommandProcessor and receive or propagate commands from/to the
     * EclipseLink cluster.
     *
     * @see CommandManager
     * @param mgr The CommandManager instance to control the remote command
     * service for this session
     */
    @Override
    public void setCommandManager(CommandManager mgr) {
        commandManager = mgr;
    }

    /**
     * PUBLIC:
     * Return whether changes should be propagated to other sessions or applications
     * in a EclipseLink cluster through the Remote Command Manager mechanism. In order for
     * this to occur the CommandManager must be set.
     *
     * @see #setCommandManager(CommandManager)
     * @return True if propagation is set to occur, false if not
     */
    public boolean shouldPropagateChanges() {
        return shouldPropagateChanges;
    }

    /**
     * ADVANCED:
     * Set whether changes should be propagated to other sessions or applications
     * in a EclipseLink cluster through the Remote Command Manager mechanism. In order for
     * this to occur the CommandManager must be set.
     *
     * @see #setCommandManager(CommandManager)
     * @param choice If true (and the CommandManager is set) then propagation will occur
     */
    public void setShouldPropagateChanges(boolean choice) {
        shouldPropagateChanges = choice;
    }

    /**
     * INTERNAL:
     * RemoteCommandManager method. This is a required method in order
     * to implement the CommandProcessor interface.
     * Return true if a message at the specified log level would be logged given the
     * log level setting of this session. This can be used by the CommandManager to
     * know whether it should even bother to create the localized strings and call
     * the logMessage method, or if it would only find that the message would not be
     * logged because the session level does not permit logging. The log level passed
     * in will be one of the constants LOG_ERROR, LOG_WARNING, LOG_INFO, and LOG_DEBUG
     * defined in the CommandProcessor interface.
     */
    @Override
    public boolean shouldLogMessages(int logLevel) {
        if (this.isLoggingOff) {
            return false;
        }
        if (LOG_ERROR == logLevel) {
            return getLogLevel(SessionLog.PROPAGATION) <= SessionLog.SEVERE;
        }
        if (LOG_WARNING == logLevel) {
            return getLogLevel(SessionLog.PROPAGATION) <= SessionLog.WARNING;
        }
        if (LOG_INFO == logLevel) {
            return getLogLevel(SessionLog.PROPAGATION) <= SessionLog.FINER;
        }
        if (LOG_DEBUG == logLevel) {
            return getLogLevel(SessionLog.PROPAGATION) <= SessionLog.FINEST;
        }
        return false;
    }

    /**
     * INTERNAL:
     * RemoteCommandManager method. This is a required method in order
     * to implement the CommandProcessor interface.
     * Log the specified message string at the specified level if it should be logged
     * given the log level setting in this session. The log level passed in will be one
     * of the constants LOG_ERROR, LOG_WARNING, LOG_INFO, and LOG_DEBUG defined in the
     * CommandProcessor interface.
     */
    @Override
    public void logMessage(int logLevel, String message) {
        if (this.isLoggingOff) {
            return;
        }
        if (shouldLogMessages(logLevel)) {
            int level;
            switch (logLevel) {
            case CommandProcessor.LOG_ERROR:
                level = SessionLog.SEVERE;
                break;
            case CommandProcessor.LOG_WARNING:
                level = SessionLog.WARNING;
                break;
            case CommandProcessor.LOG_INFO:
                level = SessionLog.FINER;
                break;
            case CommandProcessor.LOG_DEBUG:
                level = SessionLog.FINEST;
                break;
            default:
                level = SessionLog.ALL;
            }
            log(level, SessionLog.PROPAGATION, message, null, null, false);
        }
    }

    /**
     * PUBLIC:
     * <p>
     * Return the log level
     * </p>
     *
     * @return the log level
     * @param category  the string representation of a EclipseLink category, e.g. "sql", "transaction" ...
     */
    @Override
    public int getLogLevel(String category) {
        return getSessionLog().getLevel(category);
    }

    /**
     * PUBLIC:
     * <p>
     * Return the log level
     * </p>
     * @return the log level
     */
    @Override
    public int getLogLevel() {
        return getSessionLog().getLevel();
    }

    /**
     * PUBLIC:
     * <p>
     * Set the log level
     * </p>
     *
     * @param level     the new log level
     */
    @Override
    public void setLogLevel(int level) {
        this.isLoggingOff = false;
        getSessionLog().setLevel(level);
    }

    /**
     * PUBLIC:
     * Return true if SQL logging should log visible bind parameters. If the
     * shouldDisplayData is not set, check the session log level and return
     * true for a level greater than CONFIG.
     */
    public boolean shouldDisplayData() {
        return getSessionLog().shouldDisplayData();
    }

    /**
     * PUBLIC:
     * <p>
     * Check if a message of the given level would actually be logged.</p>
     *
     * @return true if the given message level will be logged
     * @param level  the log request level
     * @param category  the string representation of a EclipseLink category
     */
    @Override
    public boolean shouldLog(int level, String category) {
        if (this.isLoggingOff) {
            return false;
        }
        return getSessionLog().shouldLog(level, category);
    }

    /**
     * PUBLIC:
     * <p>
     * Log a message with level and category that needs to be translated.
     * </p>
     *
     * @param level  the log request level value
     * @param message  the string message
     * @param category  the string representation of a EclipseLink category.
     */
    public void log(int level, String category, String message) {
        if (this.isLoggingOff) {
            return;
        }
        if (!shouldLog(level, category)) {
            return;
        }
        log(level, category, message, null);
    }

    /**
     * PUBLIC:
     * <p>
     * Log a message with level, category and a parameter that needs to be translated.
     * </p>
     *
     * @param level  the log request level value
     * @param message  the string message
     * @param category  the string representation of a EclipseLink category.
     * @param param  a parameter of the message
     */
    public void log(int level, String category, String message, Object param) {
        if (this.isLoggingOff) {
            return;
        }
        if (!shouldLog(level, category)) {
            return;
        }
        log(level, category, message, new Object[] { param });
    }

    /**
     * PUBLIC:
     * <p>
     * Log a message with level, category and two parameters that needs to be translated.
     * </p>
     *
     * @param level  the log request level value
     * @param message  the string message
     * @param category  the string representation of a EclipseLink category.
     * @param param1  a parameter of the message
     * @param param2  second parameter of the message
     */
    public void log(int level, String category, String message, Object param1, Object param2) {
        if (this.isLoggingOff) {
            return;
        }
        if (!shouldLog(level, category)) {
            return;
        }
        log(level, category, message, new Object[] { param1, param2 });
    }

    /**
     * PUBLIC:
     * <p>
     * Log a message with level, category and three parameters that needs to be translated.
     * </p>
     *
     * @param level  the log request level value
     * @param message  the string message
     * @param category  the string representation of a EclipseLink category.
     * @param param1  a parameter of the message
     * @param param2  second parameter of the message
     * @param param3  third parameter of the message
     */
    public void log(int level, String category, String message, Object param1, Object param2, Object param3) {
        if (this.isLoggingOff) {
            return;
        }
        if (!shouldLog(level, category)) {
            return;
        }
        log(level, category, message, new Object[] { param1, param2, param3 });
    }

    /**
     * PUBLIC:
     * <p>
     * Log a message with level, category and an array of parameters that needs to be translated.
     * </p>
     *
     * @param level  the log request level value
     * @param message  the string message
     * @param category  the string representation of a EclipseLink category.
     * @param params  array of parameters to the message
     */
    public void log(int level, String category, String message, Object[] params) {
        if (this.isLoggingOff) {
            return;
        }
        log(level, category, message, params, null);
    }

    /**
     * PUBLIC:
     * <p>
     * Log a message with level, category, parameters and accessor that needs to be translated.
     * </p>
     *
     * @param level  the log request level value
     * @param message  the string message
     * @param params  array of parameters to the message
     * @param accessor  the connection that generated the log entry
     * @param category  the string representation of a EclipseLink category.
     */
    public void log(int level, String category, String message, Object[] params, Accessor accessor) {
        if (this.isLoggingOff) {
            return;
        }
        log(level, category, message, params, accessor, true);
    }

    /**
     * PUBLIC:
     * <p>
     * Log a message with level, category, parameters and accessor.  shouldTranslate determines if the message needs to be translated.
     * </p>
     *
     * @param level  the log request level value
     * @param message  the string message
     * @param params  array of parameters to the message
     * @param accessor  the connection that generated the log entry
     * @param category  the string representation of a EclipseLink category.
     * @param shouldTranslate  true if the message needs to be translated.
     */
    public void log(int level, String category, String message, Object[] params, Accessor accessor, boolean shouldTranslate) {
        if (this.isLoggingOff) {
            return;
        }
        if (shouldLog(level, category)) {
            startOperationProfile(SessionProfiler.Logging);
            log(new SessionLogEntry(level, category, this, message, params, accessor, shouldTranslate));
            endOperationProfile(SessionProfiler.Logging);
        }
    }

    /**
     * PUBLIC:
     * <p>
     * Log a throwable with level and category.
     * </p>
     *
     * @param level  the log request level value
     * @param category  the string representation of a EclipseLink category.
     * @param throwable  a Throwable
     */
    public void logThrowable(int level, String category, Throwable throwable) {
        if (this.isLoggingOff) {
            return;
        }
        // Must not create the log if not logging as is a performance issue.
        if (shouldLog(level, category)) {
            startOperationProfile(SessionProfiler.Logging);
            log(new SessionLogEntry(this, level, category, throwable));
            endOperationProfile(SessionProfiler.Logging);
        }
    }

    /**
     * PUBLIC:
     * <p>
     * This method is called when a severe level message needs to be logged.
     * The message will be translated
     * </p>
     *
     * @param message  the message key
     */
    public void severe(String message, String category) {
        if (this.isLoggingOff) {
            return;
        }
        log(SessionLog.SEVERE, category, message);
    }

    /**
     * PUBLIC:
     * <p>
     * This method is called when a warning level message needs to be logged.
     * The message will be translated
     * </p>
     *
     * @param message  the message key
     */
    public void warning(String message, String category) {
        if (this.isLoggingOff) {
            return;
        }
        log(SessionLog.WARNING, category, message);
    }

    /**
     * PUBLIC:
     * <p>
     * This method is called when a info level message needs to be logged.
     * The message will be translated
     * </p>
     *
     * @param message  the message key
     */
    public void info(String message, String category) {
        if (this.isLoggingOff) {
            return;
        }
        log(SessionLog.INFO, category, message);
    }

    /**
     * PUBLIC:
     * <p>
     * This method is called when a config level message needs to be logged.
     * The message will be translated
     * </p>
     *
     * @param message  the message key
     */
    public void config(String message, String category) {
        if (this.isLoggingOff) {
            return;
        }
        log(SessionLog.CONFIG, category, message);
    }

    /**
     * PUBLIC:
     * <p>
     * This method is called when a fine level message needs to be logged.
     * The message will be translated
     * </p>
     *
     * @param message  the message key
     */
    public void fine(String message, String category) {
        if (this.isLoggingOff) {
            return;
        }
        log(SessionLog.FINE, category, message);
    }

    /**
     * PUBLIC:
     * <p>
     * This method is called when a finer level message needs to be logged.
     * The message will be translated
     * </p>
     *
     * @param message  the message key
     */
    public void finer(String message, String category) {
        if (this.isLoggingOff) {
            return;
        }
        log(SessionLog.FINER, category, message);
    }

    /**
     * PUBLIC:
     * <p>
     * This method is called when a finest level message needs to be logged.
     * The message will be translated
     * </p>
     *
     * @param message  the message key
     */
    public void finest(String message, String category) {
        if (this.isLoggingOff) {
            return;
        }
        log(SessionLog.FINEST, category, message);
    }

    /**
     * PUBLIC:
     * Allow any SEVERE level exceptions that occur within EclipseLink to be logged and handled by the exception handler.
     */
    @Override
    public Object handleSevere(RuntimeException exception) throws RuntimeException {
        logThrowable(SessionLog.SEVERE, null, exception);
        if (hasExceptionHandler()) {
            return getExceptionHandler().handleException(exception);
        } else {
            throw exception;
        }
    }

    /**
      * INTERNAL:
      */
    public void releaseReadConnection(Accessor connection) {
        //bug 4668234 -- used to only release connections on server sessions but should always release
        //do nothing -- overidden in UnitOfWork,ClientSession and ServerSession
    }

    /**
     * INTERNAL:
     * Copies descriptors cached on the Project.
     * Used after Project.descriptors has been reset by addDescriptor(s) when the session is connected.
     */
   public void copyDescriptorsFromProject() {
       this.descriptors = getDescriptors();
   }

    /**
     * INTERNAL:
     * This method will be used to copy all EclipseLink named queries defined in descriptors into the session.
     * @param allowSameQueryNameDiffArgsCopyToSession  if the value is true, it allow
     * multiple queries of the same name but different arguments to be copied to the session.
     */
    public void copyDescriptorNamedQueries(boolean allowSameQueryNameDiffArgsCopyToSession) {
        for (ClassDescriptor descriptor : getProject().getOrderedDescriptors()) {
            Map queries  = descriptor.getQueryManager().getQueries();
            if ((queries != null) && (queries.size() > 0)) {
                for (Iterator keyValueItr = queries.entrySet().iterator(); keyValueItr.hasNext();){
                    Map.Entry entry = (Map.Entry) keyValueItr.next();
                    Vector thisQueries = (Vector)entry.getValue();
                    if ((thisQueries != null) && (thisQueries.size() > 0)){
                        for( Iterator thisQueriesItr=thisQueries.iterator();thisQueriesItr.hasNext();){
                            DatabaseQuery queryToBeAdded = (DatabaseQuery)thisQueriesItr.next();
                            if (allowSameQueryNameDiffArgsCopyToSession){
                                addQuery(queryToBeAdded, false);
                            } else {
                                if (getQuery(queryToBeAdded.getName()) == null){
                                    addQuery(queryToBeAdded, false);
                                } else {
                                    log(SessionLog.WARNING, SessionLog.PROPERTIES, "descriptor_named_query_cannot_be_added", new Object[]{queryToBeAdded,queryToBeAdded.getName(),queryToBeAdded.getArgumentTypes()});
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * INTERNAL:
     * This method rises appropriate for the session event(s)
     * right after connection is acquired.
     */
    public void postAcquireConnection(Accessor accessor) {
        if (getProject().hasVPDIdentifier(this)) {
            if (getPlatform().supportsVPD()) {
                DatabaseQuery query = getPlatform().getVPDSetIdentifierQuery(getProject().getVPDIdentifier());
                List argValues = new ArrayList();
                query.addArgument(getProject().getVPDIdentifier());
                argValues.add(getProperty(getProject().getVPDIdentifier()));
                executeQuery(query, argValues);
            } else {
                throw ValidationException.vpdNotSupported(getPlatform().getClass().getName());
            }
        }

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

    /**
     * INTERNAL:
     * This method rises appropriate for the session event(s)
     * right before the connection is released.
     */
    public void preReleaseConnection(Accessor accessor) {
        if (getProject().hasVPDIdentifier(this)) {
            if (getPlatform().supportsVPD()) {
                DatabaseQuery query = getPlatform().getVPDClearIdentifierQuery(getProject().getVPDIdentifier());
                List argValues = new ArrayList();
                query.addArgument(getProject().getVPDIdentifier());
                argValues.add(getProperty(getProject().getVPDIdentifier()));
                executeQuery(query, argValues);
            } else {
                throw ValidationException.vpdNotSupported(getPlatform().getClass().getName());
            }
        }

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

    /**
     * INTERNAL:
     * Execute the call on the database. Calling this method will bypass a
     * global setting to disallow native SQL queries. (set by default when
     * one Entity is marked as multitenant)
     *
     * The row count is returned.
     *
     * The call can be a stored procedure call, SQL call or other type of call.
     *
     * <p>Example:
     * <p>session.executeNonSelectingCall(new SQLCall("Delete from Employee"), true);
     *
     * @see #priviledgedExecuteSelectingCall(Call)
     */
    public int priviledgedExecuteNonSelectingCall(Call call) throws DatabaseException {
        DataModifyQuery query = new DataModifyQuery();
        query.setAllowNativeSQLQuery(true);
        query.setIsExecutionClone(true);
        query.setCall(call);
        Integer value = (Integer)executeQuery(query);
        if (value == null) {
            return 0;
        } else {
            return value.intValue();
        }
    }

    /**
     * INTERNAL:
     * Execute the call on the database and return the result. Calling this
     * method will bypass a global setting to disallow native SQL queries. (set
     * by default when one Entity is marked as multitenant)
     *
     * The call must return a value, if no value is return executeNonSelectCall
     * must be used.
     *
     * The call can be a stored procedure call, SQL call or other type of call.
     *
     * A vector of database rows is returned, database row implements Java 2 Map
     * which should be used to access the data.
     *
     * <p>Example:
     * <p>session.executeSelectingCall(new SQLCall("Select * from Employee");
     *
     * @see #priviledgedExecuteNonSelectingCall(Call)
     */
    public Vector priviledgedExecuteSelectingCall(Call call) throws DatabaseException {
        DataReadQuery query = new DataReadQuery();
        query.setAllowNativeSQLQuery(true);
        query.setCall(call);
        query.setIsExecutionClone(true);
        return (Vector)executeQuery(query);
    }

    /**
     * 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.
     */
    public boolean isExclusiveConnectionRequired() {
        return false;
    }

    /**
     *  Stores the default Session wide reference mode that a UnitOfWork will use when referencing
     *  managed objects.
     *  @see org.eclipse.persistence.config.ReferenceMode
     */
    @Override
    public ReferenceMode getDefaultReferenceMode() {
        return defaultReferenceMode;
    }

    /**
     *  Stores the default Session wide reference mode that a UnitOfWork will use when referencing
     *  managed objects.
     *  @see org.eclipse.persistence.config.ReferenceMode
     */
   @Override
   public void setDefaultReferenceMode(ReferenceMode defaultReferenceMode) {
        this.defaultReferenceMode = defaultReferenceMode;
    }

   /**
    * This method will load the passed object or collection of objects using the passed AttributeGroup.
    * In case of collection all members should be either objects of the same mapped type
    * or have a common inheritance hierarchy mapped root class.
    * The AttributeGroup should correspond to the object type.
    *
    * @param objectOrCollection
    */
   public void load(Object objectOrCollection, AttributeGroup group) {
       if (objectOrCollection == null || group == null) {
           return;
       }
       if (objectOrCollection instanceof Collection) {
           Iterator iterator = ((Collection)objectOrCollection).iterator();
           while (iterator.hasNext()) {
               Object object = iterator.next();
               load(object, group, getClassDescriptor(object.getClass()), false);
           }
       } else {
           ClassDescriptor concreteDescriptor =  getClassDescriptor(objectOrCollection.getClass());
           load(objectOrCollection, group, concreteDescriptor, false);
       }
   }

   /**
    * This method will load the passed object or collection of objects using the passed AttributeGroup.
    * In case of collection all members should be either objects of the same mapped type
    * or have a common inheritance hierarchy mapped root class.
    * The AttributeGroup should correspond to the object type.
    *
    * @param objectOrCollection
    */
   public void load(Object objectOrCollection, AttributeGroup group, ClassDescriptor referenceDescriptor, boolean fromFetchGroup) {
       if (objectOrCollection == null || group == null) {
           return;
       }
       if (objectOrCollection instanceof Collection) {
           Iterator iterator = ((Collection)objectOrCollection).iterator();
           while (iterator.hasNext()) {
               load(iterator.next(), group, referenceDescriptor, fromFetchGroup);
           }
       } else {
           ClassDescriptor concreteDescriptor = referenceDescriptor;
           if (concreteDescriptor.hasInheritance() && !objectOrCollection.getClass().equals(concreteDescriptor.getJavaClass())){
               concreteDescriptor = concreteDescriptor.getInheritancePolicy().getDescriptor(objectOrCollection.getClass());
           }
           AttributeGroup concreteGroup = group.findGroup(concreteDescriptor);
           concreteDescriptor.getObjectBuilder().load(objectOrCollection, concreteGroup, this, fromFetchGroup);
       }
   }

   public CacheKey retrieveCacheKey(Object primaryKey, ClassDescriptor concreteDescriptor, JoinedAttributeManager joinManager, ObjectBuildingQuery query){

       CacheKey cacheKey;
       //lock the object in the IM
       // PERF: Only use deferred locking if required.
       // CR#3876308 If joining is used, deferred locks are still required.
       if (query.requiresDeferredLocks()) {
           cacheKey = this.getIdentityMapAccessorInstance().acquireDeferredLock(primaryKey, concreteDescriptor.getJavaClass(), concreteDescriptor, query.isCacheCheckComplete() || query.shouldRetrieveBypassCache());

           if (cacheKey.getActiveThread() != Thread.currentThread()) {
               int counter = 0;
               while ((cacheKey.getObject() == null) && (counter < 1000)) {
                   //must release lock here to prevent acquiring multiple deferred locks but only
                   //releasing one at the end of the build object call.
                   //bug 5156075
                   cacheKey.releaseDeferredLock();
                   //sleep and try again if we are not the owner of the lock for CR 2317
                   // prevents us from modifying a cache key that another thread has locked.
                   try {
                       Thread.sleep(10);
                   } catch (InterruptedException exception) {
                   }
                   cacheKey = this.getIdentityMapAccessorInstance().acquireDeferredLock(primaryKey, concreteDescriptor.getJavaClass(), concreteDescriptor, query.isCacheCheckComplete() || query.shouldRetrieveBypassCache());
                   if (cacheKey.getActiveThread() == Thread.currentThread()) {
                       break;
                   }
                   counter++;
               }
               if (counter == 1000) {
                   throw ConcurrencyException.maxTriesLockOnBuildObjectExceded(cacheKey.getActiveThread(), Thread.currentThread());
               }
           }
       } else {
           cacheKey = this.getIdentityMapAccessorInstance().acquireLock(primaryKey, concreteDescriptor.getJavaClass(), concreteDescriptor, query.isCacheCheckComplete() || query.shouldRetrieveBypassCache());
       }
       return  cacheKey;
   }


   /**
    * PUBLIC:
    * Return the session's partitioning policy.
    */
   @Override
   public PartitioningPolicy getPartitioningPolicy() {
       return partitioningPolicy;
   }

   /**
    * PUBLIC:
    * Set the session's partitioning policy.
    * A PartitioningPolicy is used to partition, load-balance or replicate data across multiple difference databases
    * or across a database cluster such as Oracle RAC.
    * Partitioning can provide improved scalability by allowing multiple database machines to service requests.
    */
   @Override
   public void setPartitioningPolicy(PartitioningPolicy partitioningPolicy) {
       this.partitioningPolicy = partitioningPolicy;
   }

   /**
    * INTERNAL:
    * This currently only used by JPA with RCM to force a refresh of the metadata used within EntityManagerFactoryWrappers
    */
   public MetadataRefreshListener getRefreshMetadataListener() {
       return metadatalistener;
   }

   public void setRefreshMetadataListener(MetadataRefreshListener metadatalistener) {
       this.metadatalistener = metadatalistener;
   }

   /**
    * ADVANCED:
    * Return if the session enables concurrent processing.
    * Concurrent processing allow certain processing to be done on seperate threads.
    * This can result in improved performance.
    * This will use the session's server platform's thread pool.
    */
   public boolean isConcurrent() {
       return this.isConcurrent;
   }

   /**
    * ADVANCED:
    * Set if the session enables concurrent processing.
    * Concurrent processing allow certain processing to be done on seperate threads.
    * This can result in improved performance.
    * This will use the session's server platform's thread pool.
    */
   public void setIsConcurrent(boolean isConcurrent) {
       this.isConcurrent = isConcurrent;
   }

   /**
    * ADVANCED:
    * Set to indicate whether ObjectLevelReadQuery should by default use ResultSet Access optimization.
    * If not set then parent's flag is used, is none set then ObjectLevelReadQuery.isResultSetAccessOptimizedQueryDefault is used.
    * If the optimization specified by the session is ignored if incompatible with other query settings.
    */
   public void setShouldOptimizeResultSetAccess(boolean shouldOptimizeResultSetAccess) {
       this.shouldOptimizeResultSetAccess = shouldOptimizeResultSetAccess;
   }

   /**
    * ADVANCED:
    * Indicates whether ObjectLevelReadQuery should by default use ResultSet Access optimization.
    * Optimization specified by the session is ignored if incompatible with other query settings.
    */
   public boolean shouldOptimizeResultSetAccess() {
       return this.shouldOptimizeResultSetAccess;
   }

   /**
    * ADVANCED: Indicates whether an invalid NamedQuery will be tolerated at init time.
    *
    * Default is false.
    */
   public void setTolerateInvalidJPQL(boolean b) {
       this.tolerateInvalidJPQL = b;
   }

   /**
    * ADVANCED: Indicates whether an invalid NamedQuery will be tolerated at init time.
    *
    * Default is false.
    */
   public boolean shouldTolerateInvalidJPQL() {
       return this.tolerateInvalidJPQL;
   }
}
