/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2015, 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
//     14/05/2012-2.4 Guy Pelletier
//       - 376603: Provide for table per tenant support for multitenant applications
//     22/05/2012-2.4 Guy Pelletier
//       - 380008: Multitenant persistence units with a dedicated emf should force tenant property specification up front.
//     31/05/2012-2.4 Guy Pelletier
//       - 381196: Multitenant persistence units with a dedicated emf should allow for DDL generation.
//     12/24/2012-2.5 Guy Pelletier
//       - 389090: JPA 2.1 DDL Generation Support
//     01/11/2013-2.5 Guy Pelletier
//       - 389090: JPA 2.1 DDL Generation Support
//     03/19/2015 - Rick Curtis
//       - 462586 : Add national character support for z/OS.
//     04/14/2015 - Will Dazey
//       - 464641 : Fixed platform matching returning CNF.
//     09/03/2015 - Will Dazey
//       - 456067 : Added support for defining query timeout units
//     06/26/2018 - Will Dazey
//       - 532160 : Add support for non-extension OracleXPlatform classes
package org.eclipse.persistence.internal.sessions;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.partitioning.PartitioningPolicy;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.EclipseLinkException;
import org.eclipse.persistence.exceptions.IntegrityException;
import org.eclipse.persistence.exceptions.OptimisticLockException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.databaseaccess.Platform;
import org.eclipse.persistence.internal.helper.DBPlatformHelper;
import org.eclipse.persistence.internal.sequencing.Sequencing;
import org.eclipse.persistence.internal.sequencing.SequencingFactory;
import org.eclipse.persistence.internal.sequencing.SequencingHome;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.platform.database.DatabasePlatform;
import org.eclipse.persistence.platform.database.OraclePlatform;
import org.eclipse.persistence.platform.database.events.DatabaseEventListener;
import org.eclipse.persistence.platform.server.NoServerPlatform;
import org.eclipse.persistence.platform.server.ServerPlatform;
import org.eclipse.persistence.platform.server.ServerPlatformBase;
import org.eclipse.persistence.queries.AttributeGroup;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.QueryResultsCachePolicy;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.sequencing.Sequence;
import org.eclipse.persistence.sequencing.SequencingControl;
import org.eclipse.persistence.sessions.DatasourceLogin;
import org.eclipse.persistence.sessions.Login;
import org.eclipse.persistence.sessions.SessionProfiler;
import org.eclipse.persistence.tools.tuning.SessionTuner;

/**
 * Implementation of org.eclipse.persistence.sessions.DatabaseSession
 * The public interface should be used.
 * @see org.eclipse.persistence.sessions.DatabaseSession
 *
 * <p>
 * <b>Purpose</b>: Define the implementation for a single user/single connection EclipseLink 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.  The database session is intended
 * for usage in two-tier client-server applications.  Although it could be used in a server
 * situation, it is limited to only having a single database connection and only allows
 * a single open database transaction.
 * <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>
 */
public class DatabaseSessionImpl extends AbstractSession implements org.eclipse.persistence.sessions.DatabaseSession {

    /**
     * Database event listener, this allows database events to invalidate the cache.
     */
    protected DatabaseEventListener databaseEventListener;

    /**
     * INTERNAL:
     * sequencingHome for this session.
     */
    protected SequencingHome sequencingHome;

    /**
     * Used to store the server platform that handles server-specific functionality for Oc4j, WLS,  etc.
     */
    protected ServerPlatform serverPlatform;

    /**
     * Stores the tuner used to tune the configuration of this session.
     */
    protected SessionTuner tuner;

    /**
     * INTERNAL:
     * connectedTime indicates the exact time this session was logged in.
     */
    protected long connectedTime;

    /**
     * INTERNAL
     * Indicate if this session is logged in.
     */

    //Bug#3440544 Used to stop the attempt to login more than once.
    protected volatile boolean isLoggedIn;

    /**
     * INTERNAL:
     * Set the SequencingHome object used by the session.
     */
    protected void setSequencingHome(SequencingHome sequencingHome) {
        this.sequencingHome = sequencingHome;
    }

    /**
     * INTERNAL:
     * Return  SequencingHome which used to obtain all sequence-related
     * interfaces for DatabaseSession
     */
    protected SequencingHome getSequencingHome() {
        if (sequencingHome == null) {
            setSequencingHome(SequencingFactory.createSequencingHome(this));
        }
        return sequencingHome;
    }

    /**
     * INTERNAL:
     * Return if the session was logged in.
     * This may slight differ to isConnected which asks the JDBC Connection if it is connected.
     */
    public boolean isLoggedIn() {
        return isLoggedIn;
    }

    /**
     * Return the database event listener, this allows database events to invalidate the cache.
     */
    @Override
    public DatabaseEventListener getDatabaseEventListener() {
        return databaseEventListener;
    }

    /**
     * PUBLIC:
     * Set the database event listener, this allows database events to invalidate the cache.
     */
    @Override
    public void setDatabaseEventListener(DatabaseEventListener databaseEventListener) {
        this.databaseEventListener = databaseEventListener;
    }

    /**
     * INTERNAL:
     * Issue any pre connect and post connect without an actual connection to
     * the database. Descriptors are initialized in postConnectDatasource and
     * are used in DDL generation. This will look to set the schema platform
     * via the JPA 2.1 properties or through a detection on the connection
     * before DDL generation.
     */
    public void setDatasourceAndInitialize() throws DatabaseException {
        preConnectDatasource();
        setOrDetectDatasource(false);
        postConnectDatasource();
    }

    /**
     * INTERNAL:
     * Will set the platform from specified schema generation properties or
     * by detecting it through the connection (if one is available).
     * Any connection that is open for detection is closed before this method
     * returns.
     *
     * @param throwException - set to true if the caller cares to throw exceptions, false to swallow them.
     */
    protected void setOrDetectDatasource(boolean throwException) {
        String vendorName = null;
        String minorVersion = null;
        String majorVersion = null;
        String driverName = null;

        // Try to set the platform from JPA 2.1 schema properties first before
        // attempting a detection.
        if (getProperties().containsKey(PersistenceUnitProperties.SCHEMA_DATABASE_PRODUCT_NAME)) {
            vendorName = (String) getProperties().get(PersistenceUnitProperties.SCHEMA_DATABASE_PRODUCT_NAME);
            minorVersion = (String) getProperties().get(PersistenceUnitProperties.SCHEMA_DATABASE_MINOR_VERSION);
            majorVersion = (String) getProperties().get(PersistenceUnitProperties.SCHEMA_DATABASE_MAJOR_VERSION);
        } else {
            Connection conn = null;
            try {
                conn = (Connection) getReadLogin().connectToDatasource(null, this);
                DatabaseMetaData dmd = conn.getMetaData();
                vendorName = dmd.getDatabaseProductName();
                minorVersion = dmd.getDatabaseProductVersion();
                majorVersion = Integer.toString(dmd.getDatabaseMajorVersion());
                driverName = conn.getMetaData().getDriverName();
            } catch (SQLException ex) {
                if (throwException) {
                    DatabaseException dbEx = DatabaseException.errorRetrieveDbMetadataThroughJDBCConnection();
                    // Typically exception would occur if user did not provide
                    // correct connection
                    // parameters. The root cause of exception should be
                    // propagated up
                    dbEx.initCause(ex);
                    throw dbEx;
                }
            } finally {
                if (conn != null) {
                    try {
                        conn.close();
                    } catch (SQLException ex) {
                        if (throwException) {
                            DatabaseException dbEx = DatabaseException.errorRetrieveDbMetadataThroughJDBCConnection();
                            // Typically exception would occur if user did not
                            // provide correct connection
                            // parameters. The root cause of exception should be
                            // propagated up
                            dbEx.initCause(ex);
                            throw dbEx;
                        }
                    }
                }
            }
        }

        String platformName = null;
        try {
            // null out the cached platform because the platform on the login
            // will be changed by the following line of code
            this.platform = null;
            platformName = DBPlatformHelper.getDBPlatform(vendorName, minorVersion, majorVersion, getSessionLog());
            getLogin().setPlatformClassName(platformName);
        } catch (EclipseLinkException classNotFound) {
            if (platformName != null && platformName.indexOf("Oracle") != -1) {
                try {
                    // If we are running against Oracle, it is possible that we are
                    // running in an environment where the extension OracleXPlatform classes can 
                    // not be loaded. Try using the core OracleXPlatform classes
                    platformName = DBPlatformHelper.getDBPlatform("core."+ vendorName, minorVersion, majorVersion, getSessionLog());
                    getLogin().setPlatformClassName(platformName);
                } catch (EclipseLinkException oracleClassNotFound) {
                    // If we still cannot classload a matching OracleXPlatform class, 
                    // fallback on the base OraclePlatform class
                    getLogin().setPlatformClassName(OraclePlatform.class.getName());
                }
            } else {
                throw classNotFound;
            }
        }
        if (driverName != null) {
            getLogin().getPlatform().setDriverName(driverName);
        }
    }

    /**
     * PUBLIC:
     * Return  SequencingControl which used for sequencing setup and
     * customization including management of sequencing preallocation.
     */
    @Override
    public SequencingControl getSequencingControl() {
        return getSequencingHome().getSequencingControl();
    }

    /**
     * PUBLIC:
     * Return the Sequencing object used by the session.
     */
    @Override
    public Sequencing getSequencing() {
        return getSequencingHome().getSequencing();
    }

    /**
     * INTERNAL:
     * Indicates whether SequencingCallback is required.
     * Always returns false if sequencing is not connected.
     */
    public boolean isSequencingCallbackRequired() {
        return getSequencingHome().isSequencingCallbackRequired();
    }

    /**
     * INTERNAL:
     * Creates sequencing object
     */
    public void initializeSequencing() {
        getSequencingHome().onDisconnect();
        getSequencingHome().onConnect();
    }

    /**
     * INTERNAL:
     * If sequencing is connected then initializes sequences referenced by the passed descriptors,
     * otherwise connects sequencing.
     */
    public void addDescriptorsToSequencing(Collection descriptors) {
        getSequencingHome().onAddDescriptors(descriptors);
    }

    /**
     * INTERNAL:
     * Called in the end of beforeCompletion of external transaction synchronization listener.
     * Close the managed sql connection corresponding to the external transaction.
     */
    @Override
    public void releaseJTSConnection() {
        getAccessor().closeJTSConnection();
    }

    /**
     * INTERNAL:
     * Create and return a new default database session.
     * Used for EJB SessionManager to instantiate a database session
     */
    public DatabaseSessionImpl() {
        super();
        this.setServerPlatform(new NoServerPlatform(this));
        this.shouldOptimizeResultSetAccess = ObjectLevelReadQuery.isResultSetAccessOptimizedQueryDefault;
    }

    /**
     * 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 DatabaseSessionImpl(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 DatabaseSessionImpl(org.eclipse.persistence.sessions.Project project) {
        super(project);
        this.setServerPlatform(new NoServerPlatform(this));
        this.shouldOptimizeResultSetAccess = ObjectLevelReadQuery.isResultSetAccessOptimizedQueryDefault;
    }

    /**
     * PUBLIC:
     * Add the descriptor to the session.
     * All persistent classes must have a descriptor registered for them with the session.
     * It is best to add the descriptors before login, if added after login the order in which
     * descriptors are added is dependent on inheritance and references unless the addDescriptors
     * method is used.
     *
     * @see #addDescriptors(Collection)
     * @see #addDescriptors(org.eclipse.persistence.sessions.Project)
     */
    @Override
    public void addDescriptor(ClassDescriptor descriptor) {
        // Reset cached data, as may be invalid later on.
        this.lastDescriptorAccessed = null;
        // Bug# 429760: Add descriptor to the session when session Map exists and is not the same as in the project.
        if (this.descriptors != null && this.descriptors != getProject().getDescriptors()) {
            this.descriptors.put(descriptor.getJavaClass(), descriptor);
        }
        getProject().addDescriptor(descriptor, this);
    }

    /**
     * PUBLIC:
     * Add the descriptors to the session.
     * All persistent classes must have a descriptor registered for them with the session.
     * This method allows for a batch of descriptors to be added at once so that EclipseLink
     * can resolve the dependencies between the descriptors and perform initialization optimally.
     * @param descriptors The descriptors to be added to the session and project.
     */
    @Override
    public void addDescriptors(final Collection descriptors) {
        // Reset cached data, as may be invalid later on.
        this.lastDescriptorAccessed = null;
        // Bug# 429760: Add descriptors to the session when session Map exists and is not the same as in the project.
        if (this.descriptors != null && this.descriptors != getProject().getDescriptors()) {
            for (ClassDescriptor descriptor : (Collection<ClassDescriptor>) descriptors) {
                this.descriptors.put(descriptor.getJavaClass(), descriptor);
            }
        }
        getProject().addDescriptors(descriptors, this);
    }

    /**
     * PUBLIC:
     * Add the descriptors to the session from the Project.
     * This can be used to combine the descriptors from multiple projects into a single session.
     * This can be called after the session has been connected as long as there are no external dependencies.
     */
    @Override
    public void addDescriptors(org.eclipse.persistence.sessions.Project project) {
        // Reset cached data, as may be invalid later on.
        this.lastDescriptorAccessed = null;

        getProject().addDescriptors(project, this);
    }

    /**
     * PUBLIC:
     * Add the sequence to the session.
     * Allows to add a new sequence to the session even if the session is connected.
     * If the session is connected then the sequence is added only
     * if there is no sequence with the same name already in use.
     * Call this method before addDescriptor(s) if need to add new descriptor
     * with a new non-default sequence to connected session.
     */
    @Override
    public void addSequence(Sequence sequence) {
        getProject().getLogin().getDatasourcePlatform().addSequence(sequence, this.getSequencingHome().isConnected());
    }

    /**
     * INTERNAL:
     * Connect the session only.
     */
    public void connect() throws DatabaseException {
        getAccessor().connect(getDatasourceLogin(), this);
    }

    /**
     * INTERNAL:
     * Disconnect the accessor only.
     */
    public void disconnect() throws DatabaseException {
        getSequencingHome().onDisconnect();
        getAccessor().disconnect(this);
    }

    /**
     * PUBLIC:
     * Answer the server platform to handle server specific behavior for WLS, Oc4j, etc.
     *
     * If the user wants a different external transaction controller class or
     * to provide some different behavior than the provided ServerPlatform(s), we recommend
     * subclassing org.eclipse.persistence.platform.server.ServerPlatformBase (or a subclass),
     * and overriding:
     *
     * ServerPlatformBase.getExternalTransactionControllerClass()
     * ServerPlatformBase.registerMBean()
     * ServerPlatformBase.unregisterMBean()
     *
     * for the desired behavior.
     *
     * @see org.eclipse.persistence.platform.server.ServerPlatformBase
     */
    @Override
    public ServerPlatform getServerPlatform() {
        return serverPlatform;
    }

    /**
     * PUBLIC:
     * Set the server platform to handle server specific behavior for WLS, Oc4j, etc
     *
     * This is not permitted after the session is logged in.
     *
     * If the user wants a different external transaction controller class or
     * to provide some different behavior than the provided ServerPlatform(s), we recommend
     * subclassing org.eclipse.persistence.platform.server.ServerPlatformBase (or a subclass),
     * and overriding:
     *
     * ServerPlatformBase.getExternalTransactionControllerClass()
     * ServerPlatformBase.registerMBean()
     * ServerPlatformBase.unregisterMBean()
     *
     * for the desired behavior.
     *
     * @see org.eclipse.persistence.platform.server.ServerPlatformBase
     */
    @Override
    public void setServerPlatform(ServerPlatform newServerPlatform) {
        if (this.isLoggedIn) {
            throw ValidationException.serverPlatformIsReadOnlyAfterLogin(newServerPlatform.getClass().getName());
        }
        this.serverPlatform = newServerPlatform;
    }

    /**
     * INTERNAL:
     * Logout in case still connected.
     */
    @Override
    protected void finalize() throws DatabaseException {
        if (isConnected()) {
            logout();
        }
    }

    /**
     * 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) {
            if(isLoggedIn) {
                platform = getDatasourceLogin().getPlatform();
            } else {
                return getDatasourceLogin().getPlatform();
            }
        }
        return (DatabasePlatform)platform;
    }

    /**
     * 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) {
            if(isLoggedIn) {
                platform = getDatasourceLogin().getDatasourcePlatform();
            } else {
                return getDatasourceLogin().getDatasourcePlatform();
            }
        }
        return platform;
    }

    /**
     * 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) {
            if(isLoggedIn) {
                platform = getDatasourceLogin().getDatasourcePlatform();
            } else {
                return getDatasourceLogin().getDatasourcePlatform();
            }
        }
        return platform;
    }

    /**
     * INTERNAL:
     * A descriptor may have been added after the session is logged in.
     * In this case the descriptor must be allowed to initialize any dependencies on this session.
     * Normally the descriptors are added before login, then initialized on login.
     */
    public void initializeDescriptorIfSessionAlive(ClassDescriptor descriptor) {
        if (isConnected() && (descriptor.requiresInitialization(this))) {
            try {
                try {
                    Collection descriptorsToAdd = new ArrayList(1);
                    descriptorsToAdd.add(descriptor);
                    addDescriptorsToSequencing(descriptorsToAdd);
                    descriptor.preInitialize(this);
                    descriptor.initialize(this);
                    descriptor.postInitialize(this);
                    getCommitManager().initializeCommitOrder();
                } catch (RuntimeException exception) {
                    getIntegrityChecker().handleError(exception);
                }

                if (getIntegrityChecker().hasErrors()) {
                    //CR#4011
                    handleException(new IntegrityException(getIntegrityChecker()));
                }
            } finally {
                clearIntegrityChecker();
            }
        }
    }

    /**
     * INTERNAL:
     * Allow each descriptor to initialize any dependencies on this session.
     * This is done in two passes to allow the inheritance to be resolved first.
     * Normally the descriptors are added before login, then initialized on login.
     */
    public void initializeDescriptors() {
        // Must clone to avoid modification of the map while enumerating.
        initializeDescriptors((Map)((HashMap)getDescriptors()).clone(), true);
        // Initialize serializer
        if (this.serializer != null) {
            this.serializer.initialize(null, null, this);
        }
        // Initialize partitioning policies.
        for (PartitioningPolicy policy : getProject().getPartitioningPolicies().values()) {
            policy.initialize(this);
        }

        if (getProject().getMultitenantPolicy() != null) {
            getProject().getMultitenantPolicy().initialize(this);
        }

        // Process JPA named queries and add as session queries,
        // this must be done after descriptor init as requires to parse the JPQL.
        processJPAQueries();

        // Configure default query cache for all named queries.
        QueryResultsCachePolicy defaultQueryCachePolicy = getProject().getDefaultQueryResultsCachePolicy();
        if (defaultQueryCachePolicy != null) {
            for (List<DatabaseQuery> queries : getQueries().values()) {
                for (DatabaseQuery query : queries) {
                    if (query.isReadQuery() && (query.getDescriptor() != null) && !query.getDescriptor().getCachePolicy().isIsolated()) {
                        ReadQuery readQuery = (ReadQuery)query;
                        if (!readQuery.shouldCacheQueryResults()) {
                            readQuery.setQueryResultsCachePolicy(defaultQueryCachePolicy.clone());
                        }
                    }
                }
            }
        }
        for (AttributeGroup group : getProject().getAttributeGroups().values()){
            getAttributeGroups().put(group.getName(), group);
            this.getDescriptor(group.getType()).addAttributeGroup(group);
        }
    }

    /**
     * INTERNAL:
     * Allow each descriptor to initialize any dependencies on this session.
     * This is done in two passes to allow the inheritance to be resolved first.
     * Normally the descriptors are added before login, then initialized on login.
     * The descriptors session must be used, not the broker.
     * Sequencing is (re)initialized: disconnected (if has been already connected), then connected.
     */
    public void initializeDescriptors(Map descriptors) {
        initializeDescriptors(descriptors.values(), false);
    }
    public void initializeDescriptors(Collection descriptors) {
        initializeDescriptors(descriptors, false);
    }

    /**
     * INTERNAL:
     * Allow each descriptor to initialize any dependencies on this session.
     * This is done in two passes to allow the inheritance to be resolved first.
     * Normally the descriptors are added before login, then initialized on login.
     * The descriptors session must be used, not the broker.
     * If shouldInitializeSequencing parameter is true then sequencing is (re)initialized:
     * disconnected (if has been connected), then connected.
     * If shouldInitializeSequencing parameter is false then
     *   if sequencing has been already connected, then it stays connected:
     *     only the new sequences used by the passed descriptors are initialized;
     *   otherwise, if sequencing has NOT been connected then it is connected
     *     (just like in shouldInitializeSequencing==true case);
     *   disconnected (if has been connected), then connected.
     */
    public void initializeDescriptors(Map descriptors, boolean shouldInitializeSequencing) {
        initializeDescriptors(descriptors.values(), shouldInitializeSequencing);
    }
    public void initializeDescriptors(Collection descriptors, boolean shouldInitializeSequencing) {
        if (shouldInitializeSequencing) {
            initializeSequencing();
        } else {
            addDescriptorsToSequencing(descriptors);
        }

        try {
            // First initialize basic properties (things that do not depend on anything else)
            Iterator iterator = descriptors.iterator();
            while (iterator.hasNext()) {
                ClassDescriptor descriptor = (ClassDescriptor)iterator.next();
                try {
                    AbstractSession session = getSessionForClass(descriptor.getJavaClass());
                    if (descriptor.requiresInitialization(session)) {
                        descriptor.preInitialize(session);
                    } else if (descriptor.hasTablePerMultitenantPolicy()) {
                        // If the descriptor doesn't require initialization and
                        // has a table per tenant policy then add to the list
                        // to be cloned and initialized per client session.
                        addTablePerTenantDescriptor(descriptor);
                    }

                    //check if inheritance is involved in aggregate relationship, and let the parent know the child descriptor
                    if (descriptor.isDescriptorTypeAggregate() && descriptor.isChildDescriptor()) {
                        descriptor.initializeAggregateInheritancePolicy(session);
                    }
                } catch (RuntimeException exception) {
                    getIntegrityChecker().handleError(exception);
                }
            }

            // Second initialize basic mappings
            iterator = descriptors.iterator();
            while (iterator.hasNext()) {
                ClassDescriptor descriptor = (ClassDescriptor)iterator.next();
                try {
                    AbstractSession session = getSessionForClass(descriptor.getJavaClass());
                    if (descriptor.requiresInitialization(session)) {
                        descriptor.initialize(session);
                    }
                } catch (RuntimeException exception) {
                    getIntegrityChecker().handleError(exception);
                }
            }

            // Third initialize child dependencies
            iterator = descriptors.iterator();
            while (iterator.hasNext()) {
                ClassDescriptor descriptor = (ClassDescriptor)iterator.next();
                try {
                    AbstractSession session = getSessionForClass(descriptor.getJavaClass());
                    if (descriptor.requiresInitialization(session)) {
                        descriptor.postInitialize(session);
                    }
                } catch (RuntimeException exception) {
                    getIntegrityChecker().handleError(exception);
                }
            }

            if (getIntegrityChecker().hasErrors()) {
                //CR#4011
                handleSevere(new IntegrityException(getIntegrityChecker()));
            }
        } finally {
            clearIntegrityChecker();
        }

        getCommitManager().initializeCommitOrder();
    }

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

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

    /**
     * INTERNAL:
     * Return the login for the read connection.  Used by the platform autodetect feature
     */
    protected Login getReadLogin(){
        return getDatasourceLogin();
    }

    /**
     * PUBLIC:
     * Connect to the database using the predefined login.
     * During connection, attempt to auto detect the required database platform.
     * This method can be used in systems where for ease of use developers have
     * EclipseLink autodetect the platform.
     * To be safe, however, the platform should be configured directly.
     * The login must have been assigned when or after creating the session.
     *
     */
    public void loginAndDetectDatasource() throws DatabaseException {
        preConnectDatasource();
        setOrDetectDatasource(true);
        connect();
        postConnectDatasource();
    }

    /**
     * PUBLIC:
     * Connect to the database using the predefined login.
     * The login must have been assigned when or after creating the session.
     *
     * @see #login(Login)
     */
    @Override
    public void login() throws DatabaseException {
        preConnectDatasource();
        connect();
        postConnectDatasource();
    }

    /**
     * INTERNAL:
     * This method includes all of the code that is issued before the datasource
     * is connected to.
     */
    protected void preConnectDatasource(){
        //Bug#3440544 Check if logged in already to stop the attempt to login more than once
        if (isLoggedIn) {
            throw ValidationException.alreadyLoggedIn(this.getName());
        }
        this.platform = null;
        if (isInProfile()) {
            getProfiler().initialize();
        }
        updateProfile(SessionProfiler.LoginTime, new Date(System.currentTimeMillis()));
        updateProfile(SessionProfiler.SessionName, getName());

        // Login and initialize
        if (this.eventManager != null) {
            this.eventManager.preLogin(this);
        }
        if (!hasBroker()) {
            //setup the external transaction controller
            getServerPlatform().initializeExternalTransactionController();
            log(SessionLog.INFO, null, "topLink_version", DatasourceLogin.getVersion());
            if (getServerPlatform().getServerNameAndVersion() != null &&
                    !getServerPlatform().getServerNameAndVersion().equals(ServerPlatformBase.DEFAULT_SERVER_NAME_AND_VERSION)) {
                log(SessionLog.INFO, null, "application_server_name_and_version", getServerPlatform().getServerNameAndVersion());
            }
        }
        this.isLoggingOff = (getLogLevel() == SessionLog.OFF);
    }

    /**
     * INTERNAL:
     * This method includes all of the code that is issued after the datasource
     * is connected to.
     */
    protected void postConnectDatasource(){
        if (!hasBroker()) {
            initializeDescriptors();

            //added to process ejbQL query strings
            if (getCommandManager() != null) {
                getCommandManager().initialize();
            }
        }

        // Once the descriptors are initialized we can check if there are
        // multitenant entities and if this session (emf) is shared or not. If
        // not shared, all multitenant properties must be available and set by
        // the user at this point for us to validate (meaning they must be set
        // in a persitence.xml or passed into the create EMF call).
        if (getProperties().containsKey(PersistenceUnitProperties.MULTITENANT_SHARED_EMF)) {
            String value = (String) getProperties().get(PersistenceUnitProperties.MULTITENANT_SHARED_EMF);
            if (!Boolean.parseBoolean(value)) {
                for (String property : getMultitenantContextProperties()) {
                    if (! getProperties().containsKey(property)) {
                        throw ValidationException.multitenantContextPropertyForNonSharedEMFNotSpecified(property);
                    }
                }

                // Once the properties are validated we can allow ddl generation to happen (if needed).
                project.setAllowTablePerMultitenantDDLGeneration(true);
            }
        }

        log(SessionLog.FINE, SessionLog.CONNECTION, "login_successful", this.getName());
        // postLogin event should not be risen before descriptors have been initialized
        if (!hasBroker()) {
            postLogin();
        }

        initializeConnectedTime();
        this.isLoggedIn = true;
        this.platform = null;

        if (!hasBroker()) {
            //register the MBean
            getServerPlatform().registerMBean();
        }
        this.descriptors = getDescriptors();
        if (!isBroker()) {
            // EclipseLink 23869 - Initialize plaformOperators eagerly to avoid concurrency issues.
            getDatasourcePlatform().initialize();
            getIdentityMapAccessorInstance().getIdentityMapManager().checkIsCacheAccessPreCheckRequired();
        }
        if (this.databaseEventListener != null) {
            this.databaseEventListener.register(this);
        }
        if ((getDatasourcePlatform() instanceof DatabasePlatform) && getPlatform().getBatchWritingMechanism() != null) {
            getPlatform().getBatchWritingMechanism().initialize(this);
        }

    }

    /**
     * INTERNAL:
     * Rise postLogin event.
     */
    public void postLogin() {
        if (this.eventManager != null) {
            this.eventManager.postLogin(this);
        }
    }

    /**
     * PUBLIC:
     * Connect to the database using the given user name and password.
     * The additional login information must have been preset in the session's login attribute.
     * This is the login that should be used if each user has their own id,
     * but all users share the same database configuration.
     */
    @Override
    public void login(String userName, String password) throws DatabaseException {
        getDatasourceLogin().setUserName(userName);
        getDatasourceLogin().setPassword(password);
        login();
    }

    /**
     * PUBLIC:
     * Connect to the database using the given login.
     * The login may also the preset and the login() protocol called.
     * This is the login should only be used if each user has their own database configuration.
     */
    @Override
    public void login(Login login) throws DatabaseException {
        setLogin(login);
        login();
    }

    /**
     * PUBLIC:
     * Disconnect from the database.
     *
     * @exception EclipseLinkException if a transaction is active, you must rollback any active transaction before logout.
     * @exception DatabaseException the database will also raise an error if their is an active transaction,
     * or a general error occurs.
     */
    @Override
    public void logout() throws DatabaseException {
        if (this.eventManager != null) {
            this.eventManager.preLogout(this);
        }

        cleanUpInjectionManager();

        // Reset cached data, as may be invalid later on.
        this.lastDescriptorAccessed = null;

        if (isInTransaction()) {
            throw DatabaseException.logoutWhileTransactionInProgress();
        }

        if (getAccessor() == null) {
            return;
        }

        if (this.databaseEventListener != null) {
            this.databaseEventListener.remove(this);
        }

        // We're logging out so turn off change propagation.
        setShouldPropagateChanges(false);

        if (!hasBroker()) {
            if (getCommandManager() != null) {
                getCommandManager().shutdown();
            }

            // Unregister the JMX MBean before logout to avoid a javax.naming.NameNotFoundException
            getServerPlatform().shutdown();
        }

        disconnect();
        getIdentityMapAccessor().initializeIdentityMaps();
        this.isLoggedIn = false;
        if (this.eventManager != null) {
            this.eventManager.postLogout(this);
        }
        log(SessionLog.FINE, SessionLog.CONNECTION, "logout_successful", this.getName());

    }

    /**
     * PUBLIC:
     * Initialize the time that this session got connected. This can help determine how long a session has been
     * connected.
     */
    public void initializeConnectedTime() {
        connectedTime = System.currentTimeMillis();
    }

    /**
     * PUBLIC:
     * Answer the time that this session got connected. This can help determine how long a session has been
     * connected.
     */
    public long getConnectedTime() {
        return connectedTime;
    }

    /**
     * PUBLIC:
     * Write all of the objects and all of their privately owned parts in the database.
     * The objects will be committed through a single transaction.
     *
     * @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.
     */
    @Override
    public void writeAllObjects(Collection domainObjects) throws DatabaseException, OptimisticLockException {
        for (Iterator objectsEnum = domainObjects.iterator(); objectsEnum.hasNext();) {
            writeObject(objectsEnum.next());
        }
    }

    /**
     * PUBLIC:
     * Write all of the objects and all of their privately owned parts in the database.
     * The objects will be committed through a single transaction.
     *
     * @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 writeAllObjects(Vector domainObjects) throws DatabaseException, OptimisticLockException {
        for (Enumeration objectsEnum = domainObjects.elements(); objectsEnum.hasMoreElements();) {
            writeObject(objectsEnum.nextElement());
        }
    }

    /**
     * INTERNAL:
     * A query execution failed due to an invalid query.
     * Re-connect and retry the query.
     */
    @Override
    public Object retryQuery(DatabaseQuery query, AbstractRecord row, DatabaseException databaseException, int retryCount, AbstractSession executionSession) {
        if (getClass() != DatabaseSessionImpl.class) {
            return super.retryQuery(query, row, databaseException, retryCount, executionSession);
        }
        //attempt to reconnect connection:
        final 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
                ++retryCount;
                databaseException.getAccessor().reestablishConnection(this);
                break;
            } catch (DatabaseException ex) {
                // failed to get connection because of
                // database error.
                try {
                    // Give the failover time to recover.
                    Thread.sleep(getLogin().getDelayBetweenConnectionAttempts());
                    Object[] args = new Object[1];
                    args[0] = ex;
                    log(SessionLog.INFO, SessionLog.QUERY, "communication_failure_attempting_query_retry", args, null);
                } catch (InterruptedException intEx) {
                    break;
                }
            }
        }
        return executionSession.executeQuery(query, row, retryCount);
    }

    /**
     * Return the tuner used to tune the configuration of this session.
     */
    public SessionTuner getTuner() {
        return tuner;
    }

    /**
     * Set the tuner used to tune the configuration of this session.
     */
    public void setTuner(SessionTuner tuner) {
        this.tuner = tuner;
    }
}
