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

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     @author  mobrien
//     @since   EclipseLink 1.0 enh# 235168
package org.eclipse.persistence.services;

import java.security.AccessController;
import java.security.PrivilegedActionException;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.factories.XMLProjectReader;

/**
 * <p>
 * <b>Purpose</b>: Provide a dynamic interface into the EclipseLink Identity Map Manager.
 * <p>
 * <b>Description</b>: This class is meant to provide a framework for gaining access to configuration and
 * statistics of the EclipseLink Cache during runtime.  It will provide the basis for development
 * of a JMX service and possibly other frameworks.
 *
 */
public class DevelopmentServices {

    /** stores access to the session object that we are controlling */
    protected Session session;

    /**
         * Default constructor
     */
    public DevelopmentServices() {
    }

    /**
     * Constructor
     * @param session the session for these services
     */
    public DevelopmentServices(Session session) {
        this.session = session;
    }

    /**
     *        This method is used to clear the contents of a particular identity map.  Users should be
     * aware that if any of these objects are in use when this action is completed they will lose object identity.
     * @param className the fully qualified name of the class for which the identity map should be cleared.
     * @exception ClassNotFoundException thrown then the IdenityMap for that class name could not be found
     */
    public void initializeIdentityMap(String className) throws ClassNotFoundException {
        Class classToChange = (Class)getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
        getSession().getIdentityMapAccessorInstance().initializeIdentityMap(classToChange);
    }

    /**
     *        This method is used to clear the contents of all identity maps.  Users should be
     * aware that if any of these objects are in use when this action is completed they will lose object identity.
     */
    public void initializeAllIdentityMaps() {
        getSession().getIdentityMapAccessorInstance().initializeIdentityMaps();
    }

    /**
     *        This method will be used to set a new type of identity map for a particular class type.  If objects
     * of that class type are in use loss of object identity will result.  For prevention client may wish to
     * initialize all identity maps first.
     * @param className the fully qualified className to set the identity map for.
     * @param identityMapClassType the fully qualified class name of the new identity map type.
     * @param maxSize the maximum size to be specified for the new identity map.
     * @exception ClassNotFoundException thrown then the IdenityMap for that class name could not be found
     */
    public void setIdentityMapForClass(String className, String identityMapClassType, int maxSize) throws ClassNotFoundException {
        Class classToChange = (Class)getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
        Class identityMapClass = null;
        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
            try{
                identityMapClass = AccessController.doPrivileged(new PrivilegedClassForName(identityMapClassType));
            }catch (PrivilegedActionException ex){
                throw (RuntimeException)ex.getCause();
            }
        }else{
            identityMapClass = PrivilegedAccessHelper.getClassForName(identityMapClassType);
        }
        ClassDescriptor descriptor = getSession().getDescriptor(classToChange);
        descriptor.setIdentityMapClass(identityMapClass);
        descriptor.setIdentityMapSize(maxSize);
        getSession().getIdentityMapAccessorInstance().initializeIdentityMap(classToChange);
    }

    /**
     *        This method used to reset a project in a session. All connected clients will get errors.
     * project must be of the xml type.  This attribute will not be stored on a save.
     * @param projectFilePath the filename of the project xml file to build the new project from.
     */
    public void refreshProject(String projectFilePath) {
        ((DatabaseSessionImpl)getSession()).logout();
        getSession().setProject(XMLProjectReader.read(projectFilePath));
        ((DatabaseSessionImpl)getSession()).login();
    }

    /**
     *        This method is used to update the cache size of a particular Identity Map
     * @param className the name of the class for which to update the identity map size.
     * @exception ClassNotFoundException thrown then the IdenityMap for that class name could not be found
     */
    public void updateCacheSize(String className, int newSize) throws ClassNotFoundException {
        Class classToChange = (Class)getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
        getSession().getIdentityMapAccessorInstance().getIdentityMap(classToChange).updateMaxSize(newSize);
    }

    /**
     *     This method is used to control if All parameters should be bound
     */
    public void setShouldBindAllParameters(boolean shouldBindAllParameters) {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return;
        }
        ((DatabaseLogin)getSession().getDatasourceLogin()).setShouldBindAllParameters(shouldBindAllParameters);
    }

    /**
     *     Method returns if all Parameters should be bound or not
     */
    public boolean getShouldBindAllParameters() {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return false;
        }
        return ((DatabaseLogin)getSession().getDatasourceLogin()).shouldBindAllParameters();
    }

    /**
     *        Sets the size of strings after which they will be bound into the statement
     */
    public void setStringBindingSize(int size) {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return;
        }
        ((DatabaseLogin)getSession().getDatasourceLogin()).setStringBindingSize(size);
    }

    /**
     *     Return the size of strings after which will be bound into the statement
     */
    public int getStringBindingSize() {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return 0;
        }
        return ((DatabaseLogin)getSession().getDatasourceLogin()).getStringBindingSize();
    }

    /**
     *        This method is used to turn on EclipseLink Batch Writing.  Please note that toggling this
     * setting while a transaction is open may result in unordered sql statements or loss of statements.
     * Also please note that EclipseLink Batch Writing may not work with all JDBC Drivers
     */
    public void setUsesBatchWriting(boolean usesBatchWriting) {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return;
        }
        ((DatabaseLogin)getSession().getDatasourceLogin()).setUsesBatchWriting(usesBatchWriting);
    }

    /**
     *        This method will return if batchWriting is in use or not.
     */
    public boolean getUsesBatchWriting() {
        return getSession().getDatasourceLogin().getPlatform().usesBatchWriting();
    }

    /**
     *        This method is used to turn on JDBC Batch Writing.  Please note that toggling this
     * setting while a transaction is open may result in mis-ordered sql statements or loss of statements.
     *
     */
    public void setUsesJDBCBatchWriting(boolean usesJDBCBatchWriting) {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return;
        }
        ((DatabaseLogin)getSession().getDatasourceLogin()).setUsesJDBCBatchWriting(usesJDBCBatchWriting);
    }

    /**
     *        This method will return if batchWriting is in use or not.
      */
    public boolean getUsesJDBCBatchWriting() {
        return getSession().getDatasourceLogin().getPlatform().usesJDBCBatchWriting();
    }

    /**
     *        This method allows control of whether byte arrays should be bound into the statement or not.
     * Toggling this attribute while an SQL statement is being built, or if you are caching statements, will
     * result in errors.
     */
    public void setUsesByteArrayBinding(boolean usesByteArrayBinding) {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return;
        }
        ((DatabaseLogin)getSession().getDatasourceLogin()).setUsesByteArrayBinding(usesByteArrayBinding);
    }

    /**
     *     Shows if Byte Array Binding is turned on or not
     */
    public boolean getUsesByteArrayBinding() {
        return getSession().getDatasourceLogin().getPlatform().usesByteArrayBinding();
    }

    /**
     *     This method allows the client to set if Native SQL should be used.
     */
    public void setUsesNativeSQL(boolean usesNativeSQL) {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return;
        }
        ((DatabaseLogin)getSession().getDatasourceLogin()).setUsesNativeSQL(usesNativeSQL);
    }

    /**
     *     Shows if native SQL is being used
     */
    public boolean getUsesNativeSQL() {
        return getSession().getDatasourceLogin().getPlatform().usesNativeSQL();
    }

    /**
     *     This method is used to set if streams should be used for binding.  Please note that toggling this
     * attribute while a statement is being built will result in errors.
     */
    public void setUsesStreamsForBinding(boolean usesStreamsForBinding) {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return;
        }
        ((DatabaseLogin)getSession().getDatasourceLogin()).setUsesStreamsForBinding(usesStreamsForBinding);
    }

    /**
     *     This method indicates if streams are being used for binding
     */
    public boolean getUsesStreamsForBinding() {
        return getSession().getDatasourceLogin().getPlatform().usesStreamsForBinding();
    }

    /**
     *     Allows the client to set if String should be bound into the statement or not.  Please note that
     * toggling this attribute while a statement is being built, or if statement caching is being used, will result
     * in errors.
     */
    public void setUsesStringBinding(boolean usesStringBinding) {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return;
        }
        ((DatabaseLogin)getSession().getDatasourceLogin()).setUsesStringBinding(usesStringBinding);
    }

    /**
     *     This method indicates if Strings are being bound
     */
    public boolean getUsesStringBinding() {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return false;
        }
        return getSession().getDatasourceLogin().getPlatform().usesStringBinding();
    }

    /**
     * INTERNAL:
     */
    protected AbstractSession getSession() {
        return (AbstractSession)this.session;
    }
}
