/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.sessions.factories;

import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.eclipse.persistence.exceptions.ServerPlatformException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedGetClassLoaderForClass;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.factories.model.SessionConfigs;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.platform.server.ServerPlatform;
import org.eclipse.persistence.platform.server.ServerPlatformUtils;
import org.eclipse.persistence.sessions.DatabaseSession;
import org.eclipse.persistence.sessions.Session;

/**
 * <p>
 * <b>Purpose</b>: Global session location.</p>
 *
 * <p><b>Description</b>: This allows for a global session local which can
 * be accessed globally from other classes.  This is needed for EJB data stores
 * as they must have a globally accessible place to access the session.
 * This can be by EJB session beans, BMP beans and CMP beans as well as Servlets and
 * other three-tier services.</p>
 *
 * <p><b>Responsibilities</b>:</p>
 * <ul>
 * <li> Store a global session.
 * <li> Allow the storage of alternative sessions as well.
 * </ul>
 *
 * @author James Sutherland
 * @since TOPLink/Java 3.0
 */
public class SessionManager {
    /** Allow for usage of schema validation to be configurable. */
    protected static boolean shouldUseSchemaValidation = true;

    protected static volatile SessionManager manager;
    protected AbstractSession defaultSession;
    protected ConcurrentMap<String, Session> sessions;
    protected static boolean shouldPerformDTDValidation;
    private static volatile ConcurrentMap<String, SessionManager> managers;
    private static volatile ServerPlatform detectedPlatform;
    private static volatile boolean supportPartitions;
    private String context;
    private static final Object[] lock = new Object[0];
    // not final for tests
    private static SessionLog LOG = AbstractSessionLog.getLog();

    static {
        init();
    }

    private static void init() {
        String platformClass = ServerPlatformUtils.detectServerPlatform(null);
        try {
            detectedPlatform = platformClass != null
                    ? ServerPlatformUtils.createServerPlatform(null, platformClass, SessionManager.class.getClassLoader())
                    : null;
        } catch (ServerPlatformException e) {
            // some platforms may not be handling 'null' session well or
            // detected class as such may not be valid for some reason (ie
            // not found), so be defensive here and only log throwable here
            detectedPlatform = null;
            LOG.logThrowable(SessionLog.WARNING, AbstractSessionLog.CONNECTION, e);
        }
        supportPartitions = detectedPlatform != null && detectedPlatform.usesPartitions();
        if (supportPartitions) {
            managers = new ConcurrentHashMap<>(4, 0.9f, 1);
            SessionManager sm = initializeManager();
            manager = sm;
            managers.put(sm.context, sm);
        } else {
            manager = initializeManager();
        }
    }

    /**
     * PUBLIC:
     * Return if schema validation will be used when parsing the 10g (10.1.3) sessions XML.
     *
     * @return {@code true} if schema validation will be used when parsing
     * the 10g (10.1.3) sessions XML, {@code false} otherwise
     */
    public static boolean shouldUseSchemaValidation() {
        return shouldUseSchemaValidation;
    }

    /**
     * PUBLIC:
     * Set if schema validation will be used when parsing the 10g (10.1.3) sessions XML.
     * By default schema validation is on, but can be turned off if validation problems occur,
     * or to improve parsing performance.
     *
     * @param useSchemaValidation {@code true} if schema validation should be used when parsing
     * the 10g (10.1.3) sessions XML, {@code false} otherwise
     */
    public static void setShouldUseSchemaValidation(boolean useSchemaValidation) {
        shouldUseSchemaValidation = useSchemaValidation;
    }

    /**
     * PUBLIC:
     * The default constructor to create a new session manager.
     */
    public SessionManager() {
        sessions = new ConcurrentHashMap<>(5);
        if (supportPartitions) {
            context = getPartitionID();
        }
    }

    /**
     * INTERNAL:
     * Add an named session to the hashtable.
     * Session must have a name prior to setting into session manager.
     *
     * @param session session to be added to the session manager
     */
    public void addSession(Session session) {
        getSessions().put(session.getName(), session);
    }

    /**
     * ADVANCED:
     * add an named session to the hashtable.
     *
     * @param sessionName session name
     * @param session session to be added to the session manager
     */
    public void addSession(String sessionName, Session session) {
        session.setName(sessionName);
        getSessions().put(sessionName, session);
    }

    /**
     * PUBLIC:
     * Return the default session.
     * The session configuration is stored in a sessions.xml file in a
     * directory on your classpath. Other sessions are supported through the
     * getSession by name API.
     *
     * @return default session
     */
    public Session getDefaultSession() {
        if (defaultSession == null) {
            defaultSession = getSession("default");
        }
        return defaultSession;
    }

    /**
     * PUBLIC:
     * Destroy current session manager instance.
     */
    public void destroy() {
        if (supportPartitions) {
            if (managers.remove(getPartitionID()) == null) {
                //should not happen
                LOG.log(SessionLog.WARNING, "session_manager_no_partition", new Object[0]);
           }
        }
    }

    /**
     * INTERNAL:
     * Destroy the session defined by sessionName on this manager.
     *
     * @param sessionName name of the session to be destroyed
     */
    public void destroySession(String sessionName) {
        Session session = getSessions().get(sessionName);

        if (session != null) {
            destroy(session);
        } else {
            logAndThrowException(SessionLog.WARNING, ValidationException.noSessionRegisteredForName(sessionName));
        }
    }

    private void destroy(Session session) {
        try {
            if (session.isConnected()) {
                ((DatabaseSession) session).logout();
            }
        } catch (Throwable ig) {
            // EL Bug 321843 - Must handle errors from logout.
            LOG.logThrowable(SessionLog.WARNING, AbstractSessionLog.CONNECTION, ig);
        }

        sessions.remove(session.getName());
        session = null;
    }

    /**
     * INTERNAL:
     * Destroy all sessions held onto by this manager.
     */
    public void destroyAllSessions() {
        Iterator<Session> toRemoveSessions = new ArrayList<>(getSessions().values()).iterator();

        while (toRemoveSessions.hasNext()) {
            destroy(toRemoveSessions.next());
        }
    }

    /**
     * INTERNAL:
     * This method is to be used to load config objects for the Mapping Workbench
     * only. Do not call this method.
     *
     * @param resourceName resource to load
     * @param objectClassLoader ClassLoader used to load the resource
     * @return parsed session configuration
     */
    public synchronized SessionConfigs getInternalMWConfigObjects(String resourceName, ClassLoader objectClassLoader) {
        return getInternalMWConfigObjects(resourceName, objectClassLoader, true);
    }

    /**
     * INTERNAL:
     * This method is to be used to load config objects for the Mapping Workbench
     * only. Do not call this method.
     *
     * @param resourceName resource to load
     * @param objectClassLoader ClassLoader used to load the resource
     * @param validate whether to validate the resource passed in
     * @return parsed session configuration
     */
    public synchronized SessionConfigs getInternalMWConfigObjects(String resourceName, ClassLoader objectClassLoader, boolean validate) {
        return new XMLSessionConfigLoader(resourceName).loadConfigsForMappingWorkbench(objectClassLoader, validate);
    }

    /**
     * PUBLIC:
     * Return the session manager for current context.
     * This allow global access to a set of named sessions.
     *
     * @return the session manager for current context
     */
    public static SessionManager getManager() {
        if (!supportPartitions) {
            if (manager == null) {
                synchronized (lock) {
                    if (manager == null) {
                        manager = initializeManager();
                    }
                }
            }
            return manager;
        }
        SessionManager current = manager;
        String currentCtx = getPartitionID();
        if (current != null && currentCtx.equals(current.context)) {
            if (LOG.shouldLog(SessionLog.FINER)) {
                LOG.log(SessionLog.FINER, "returning cached session manager for " + current.context);
            }
            return current;
        }
        current = managers.get(currentCtx);
        if (current == null) {
            synchronized (lock) {
                if (current == null) {
                    current = initializeManager();
                    current.context = currentCtx;
                    managers.put(current.context, current);
                    manager = current;
                    if (LOG.shouldLog(SessionLog.FINER)) {
                        LOG.log(SessionLog.FINER, "created session manager for " + current.context);
                    }
                }
            }
        }
        if (LOG.shouldLog(SessionLog.FINER)) {
            LOG.log(SessionLog.FINER, "returning session manager for " + current.context);
        }
        return current;
    }

    /**
     * ADVANCED:
     * Return all session managers.
     * This allows global access to all instances of SessionManager.
     *
     * @return all SessionManager instances
     */
    public static Collection<SessionManager> getAllManagers() {
        return supportPartitions ? managers.values() : Collections.singleton(getManager());
    }

    /**
     * INTERNAL:
     * Initialize the singleton session manager.
     *
     * @return initialized session manager
     */
    protected static SessionManager initializeManager() {
        if (LOG.shouldLog(SessionLog.FINER)) {
            LOG.log(SessionLog.FINER, "initializing session manager");
        }
        return new SessionManager();
    }

    /**
     * PUBLIC:
     * Return the session by name.
     *
     * @param sessionName session name
     * @return session with given session name
     */
    public org.eclipse.persistence.internal.sessions.AbstractSession getSession(String sessionName) {
        XMLSessionConfigLoader loader = new XMLSessionConfigLoader();
        loader.setSessionName(sessionName);
        return getSession(loader);
    }

    /**
     * PUBLIC:
     * Return the session by name.
     * Log the session in only if specified.
     *
     * @param sessionName session name
     * @param shouldLoginSession whether the session should be logged in
     * @return session with given session name
     */
    public org.eclipse.persistence.internal.sessions.AbstractSession getSession(String sessionName, boolean shouldLoginSession) {
        XMLSessionConfigLoader loader = new XMLSessionConfigLoader();
        loader.setSessionName(sessionName);
        loader.setShouldLogin(shouldLoginSession);
        return getSession(loader);
    }

    /**
     * PUBLIC:
     * Return the session by name.
     * Log the session in only if specified.
     * Refresh the session only if specified.
     *
     * @param sessionName session name
     * @param shouldLoginSession whether the session should be logged in
     * @param shouldRefreshSession whether the session should be refreshed
     * @return session with given session name
     */
    public org.eclipse.persistence.internal.sessions.AbstractSession getSession(String sessionName, boolean shouldLoginSession, boolean shouldRefreshSession) {
        XMLSessionConfigLoader loader = new XMLSessionConfigLoader();
        loader.setSessionName(sessionName);
        loader.setShouldLogin(shouldLoginSession);
        loader.setShouldRefresh(shouldRefreshSession);
        return getSession(loader);
    }

    /**
     * PUBLIC:
     * Return the session by name, using the classloader of the Object specified.
     * This method is used in older versions of BMP support
     * This method will cause the class loader of the provided object to be
     * compared with the classloader used to load the original session of this
     * name, with this classloader.  If they are not the same then the session
     * will be refreshed.
     *
     * @param sessionName session name
     * @param objectBean object to get the ClassLoader from
     * @return session with given session name
     */
    public org.eclipse.persistence.internal.sessions.AbstractSession getSession(String sessionName, Object objectBean) {
        XMLSessionConfigLoader loader = new XMLSessionConfigLoader();
        loader.setSessionName(sessionName);
        ClassLoader classLoader;
        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
            try{
                classLoader = AccessController.doPrivileged(new PrivilegedGetClassLoaderForClass(objectBean.getClass()));
            }catch (PrivilegedActionException ex){
                throw (RuntimeException) ex.getCause();
            }
        }else{
            classLoader = PrivilegedAccessHelper.getClassLoaderForClass(objectBean.getClass());
        }
        loader.setClassLoader(classLoader);
        return getSession(loader);
    }

    /**
     * PUBLIC:
     * Return the session by name, in the file specified.
     * Login the session.
     *
     * @param sessionName session name
     * @param filename file name containing session definition
     * @return session with given session name
     */
    public org.eclipse.persistence.internal.sessions.AbstractSession getSession(String sessionName, String filename) {
        XMLSessionConfigLoader loader = new XMLSessionConfigLoader();
        loader.setSessionName(sessionName);
        loader.setResourceName(filename);
        return getSession(loader);
    }

    /**
     * PUBLIC:
     * Return the session by name, in the file specified, using the class loader to find the resource.
     * This method will cause the class loader to be compared with the classloader
     * used to load the original session of this name.
     * If they are not the same then the session will be refreshed.
     *
     * @param sessionName session name
     * @param filename file name containing session definition
     * @param classLoader ClassLoader used to load the original session
     * @return session with given session name
     */
    public AbstractSession getSession(String sessionName, String filename, ClassLoader classLoader) {
        XMLSessionConfigLoader loader = new XMLSessionConfigLoader();
        loader.setSessionName(sessionName);
        loader.setResourceName(filename);
        loader.setClassLoader(classLoader);
        loader.setShouldCheckClassLoader(true);
        return getSession(loader);
    }

    /**
     * PUBLIC:
     * Return the session by name.
     * Provide the class loader for loading the project, the configuration file
     * and the deployed classes.
     * E.g. SessionManager.getManager().getSession("mySession", MySessionBean.getClassLoader());
     * This method will cause the class loader to be compared with the classloader
     * used to load the original session of this name.
     * If they are not the same then the session will be refreshed.
     *
     * @param sessionName session name
     * @param objectClassLoader ClassLoader used to load the original session
     * @return session with given session name
     */
    public AbstractSession getSession(String sessionName, ClassLoader objectClassLoader) {
        XMLSessionConfigLoader loader = new XMLSessionConfigLoader();
        loader.setSessionName(sessionName);
        loader.setClassLoader(objectClassLoader);
        loader.setShouldCheckClassLoader(true);
        return getSession(loader);
    }

    /**
     * PUBLIC:
     * Return the session by name, loading the configuration from the file
     * specified in the XMLSessionConfigLoader. Provide the class loader for
     * loading the project, the configuration file and the deployed classes.
     * This method will cause the class loader to be compared with the classloader
     * used to load the original session of this name.
     * If they are not the same then the session will be refreshed.
     *
     * @param loader {@link XMLSessionConfigLoader} containing session configuration
     * @param sessionName session name
     * @param objectClassLoader ClassLoader used to load the original session
     * @return session with given session name
     */
    public AbstractSession getSession(XMLSessionConfigLoader loader, String sessionName, ClassLoader objectClassLoader) {
        if (loader == null){
            loader = new XMLSessionConfigLoader();
        }
        loader.setSessionName(sessionName);
        loader.setClassLoader(objectClassLoader);
        loader.setShouldCheckClassLoader(true);
        return getSession(loader);
    }


    /**
     * PUBLIC:
     * Return the session by name, loading the configuration from the file
     * specified in the loader. Provide the class loader for loading the
     * project, the configuration file and the deployed classes. Pass in true for
     * shouldLoginSession if the session returned should be logged in before
     * returned otherwise false. Pass in true for shouldRefreshSession if the
     * XMLSessionConfigLoader should reparse the configuration file for new
     * sessions. False, will cause the XMLSessionConfigLoader not to parse the
     * file again.
     *
     * @param loader {@link XMLSessionConfigLoader} containing session configuration
     * @param sessionName session name
     * @param objectClassLoader ClassLoader used to load the original session
     * @param shouldLoginSession whether the session should be logged in
     * @param shouldRefreshSession whether the session should be refreshed
     * @return session with given session name
     */
    public AbstractSession getSession(XMLSessionConfigLoader loader, String sessionName, ClassLoader objectClassLoader, boolean shouldLoginSession, boolean shouldRefreshSession) {
        if (loader == null){
            loader = new XMLSessionConfigLoader();
        }
        loader.setSessionName(sessionName);
        loader.setClassLoader(objectClassLoader);
        loader.setShouldLogin(shouldLoginSession);
        loader.setShouldRefresh(shouldRefreshSession);
        return getSession(loader);
    }

    /**
     * PUBLIC:
     * Return the session by name, loading the configuration from the file
     * specified in the loader. Provide the class loader for loading the
     * project, the configuration file and the deployed classes. Pass in true for
     * shouldLoginSession if the session returned should be logged in before
     * returned otherwise false. Pass in true for shouldRefreshSession if the
     * XMLSessionConfigLoader should reparse the configuration file for new
     * sessions. False, will cause the XMLSessionConfigLoader not to parse the
     * file again.
     * Pass true for shouldCheckClassLoader will cause the class loader to be compared with the classloader
     * used to load the original session of this name.
     * If they are not the same then the session will be refreshed, this can be used for re-deployment.
     *
     * @param loader {@link XMLSessionConfigLoader} containing session configuration
     * @param sessionName session name
     * @param objectClassLoader ClassLoader used to load the original session
     * @param shouldLoginSession whether the session should be logged in
     * @param shouldRefreshSession whether the session should be refreshed
     * @param shouldCheckClassLoader whether to compare class loaders used to load given session
     * @return session with given session name
     */
    public AbstractSession getSession(XMLSessionConfigLoader loader, String sessionName, ClassLoader objectClassLoader, boolean shouldLoginSession, boolean shouldRefreshSession, boolean shouldCheckClassLoader) {
        if (loader == null){
            loader = new XMLSessionConfigLoader();
        }
        loader.setSessionName(sessionName);
        loader.setClassLoader(objectClassLoader);
        loader.setShouldLogin(shouldLoginSession);
        loader.setShouldRefresh(shouldRefreshSession);
        loader.setShouldCheckClassLoader(shouldCheckClassLoader);
        return getSession(loader);
    }

    /**
     * PUBLIC:
     * Return the session by name, loading the configuration from the file
     * specified in the loader, using the loading options provided on the loader.
     *
     * @param loader {@link XMLSessionConfigLoader} containing session configuration
     * @return session with given session name
     */
    public AbstractSession getSession(XMLSessionConfigLoader loader) {
        AbstractSession session = (AbstractSession)getSessions().get(loader.getSessionName());
        boolean shouldRefreshSession = loader.shouldRefresh();
        if (loader.shouldCheckClassLoader() && (session != null) && !session.getDatasourcePlatform().getConversionManager().getLoader().equals(loader.getClassLoader())) {
            //bug 3766808  if a different classloader is being used then a reload of the session should
            //be completed otherwise failures may occur
            shouldRefreshSession = true;
        }
        if ((session == null) || shouldRefreshSession) {
            // PERF: Avoid synchronization for normal get.
            synchronized (this) {
                // Must re-assert checks inside synchronization.
                session = (AbstractSession)getSessions().get(loader.getSessionName());
                if (loader.shouldCheckClassLoader() && (session != null) && !session.getDatasourcePlatform().getConversionManager().getLoader().equals(loader.getClassLoader())) {
                    //bug 3766808  if a different classloader is being used then a reload of the session should
                    //be completed otherwise failures may occur
                    shouldRefreshSession = true;
                }
                if ((session == null) || shouldRefreshSession) {
                    if (session != null) {
                        if (session.isDatabaseSession() && session.isConnected()) {
                            // Must handles errors from logout as session maybe hosed.
                            try {
                                ((DatabaseSession)session).logout();
                            } catch (Throwable ig) {
                                LOG.logThrowable(SessionLog.WARNING, AbstractSessionLog.CONNECTION, ig);
                            }
                        }
                        getSessions().remove(loader.getSessionName());
                    }

                    if (loader.load(this, loader.getClassLoader())) {
                        session = (AbstractSession)getSessions().get(loader.getSessionName());
                    }
                }
            }
        }

        // Connect the session if specified.
        if (session == null) {
            logAndThrowException(SessionLog.WARNING, ValidationException.noSessionFound(loader.getSessionName(), loader.getResourcePath()));
        } else if (loader.shouldLogin() && !session.isConnected()) {
            // PERF: Avoid synchronization for normal get.
            synchronized (this) {
                // Must re-assert checks inside synchronization.
                if (loader.shouldLogin() && !session.isConnected()) {
                    ((DatabaseSession)session).login();
                }
            }
        }

        return session;
    }

    /**
     * INTERNAL:
     * Log exceptions to the default log then throw them.
     */
    private void logAndThrowException(int level, RuntimeException exception) throws RuntimeException {
        LOG.logThrowable(level, AbstractSessionLog.CONNECTION, exception);
        throw exception;
    }


    /**
     * INTERNAL:
     * Set a hashtable of all sessions
     *
     * @param sessions sessions for this session manager
     */
    public void setSessions(ConcurrentMap<String, Session> sessions) {
        this.sessions = sessions;
    }

    /**
     * INTERNAL:
     * Return a hashtable on all sessions.
     *
     * @return all sessions known by this session manager
     */
    public ConcurrentMap<String, Session> getSessions() {
        return sessions;
    }

    /**
     * PUBLIC:
     * Set the default session.
     * If not set the session configuration is stored in a sessions.xml
     * file in a TopLink directory on your classpath.
     * Other sessions are supported through the getSession by name API.
     *
     * @param defaultSession default session
     */
    public void setDefaultSession(Session defaultSession) {
        this.defaultSession = (org.eclipse.persistence.internal.sessions.AbstractSession)defaultSession;
        addSession("default", defaultSession);
    }

    /**
     * INTERNAL:
     * Set the singleton session manager.
     * This allows global access to a set of named sessions.
     *
     * @param theManager session manager for current context
     */
    public static void setManager(SessionManager theManager) {
        if (!supportPartitions) {
             manager = theManager;
        } else {
            if (theManager.context == null) {
                synchronized (lock) {
                    if (theManager.context == null) {
                        theManager.context = getPartitionID();
                    }
                    managers.put(theManager.context, theManager);
                    if (LOG.shouldLog(SessionLog.FINER)) {
                        LOG.log(SessionLog.FINER, "registered session manager w/o partitionId for " + theManager.context);
                    }
                }
            } else {
                managers.put(theManager.context, theManager);
                if (LOG.shouldLog(SessionLog.FINER)) {
                    LOG.log(SessionLog.FINER, "registered session manager w/ partitionId for " + theManager.context);
                }
            }
        }
    }

    private static String getPartitionID() {
        return detectedPlatform.getPartitionID();
    }
}
