/*
 * Copyright (c) 1997, 2018 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.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.enterprise.resource.deployer;


import com.sun.appserv.connectors.internal.api.ConnectorRuntimeException;
import com.sun.appserv.connectors.internal.api.ConnectorsUtil;
import com.sun.enterprise.connectors.ConnectorConnectionPool;
import com.sun.enterprise.connectors.ConnectorDescriptorInfo;
import com.sun.enterprise.connectors.ConnectorRuntime;
import com.sun.enterprise.connectors.util.ConnectionPoolObjectsUtils;
import com.sun.enterprise.connectors.util.ConnectorDDTransformUtils;
import com.sun.enterprise.connectors.util.SecurityMapUtils;
import com.sun.enterprise.deployment.ConnectionDefDescriptor;
import com.sun.enterprise.deployment.ConnectorConfigProperty;
import com.sun.enterprise.deployment.ConnectorDescriptor;
import com.sun.enterprise.util.i18n.StringManager;
import com.sun.logging.LogDomains;
import org.glassfish.connectors.config.SecurityMap;
import org.glassfish.resourcebase.resources.api.PoolInfo;
import org.glassfish.resourcebase.resources.api.ResourceDeployer;
import org.glassfish.resourcebase.resources.api.ResourceDeployerInfo;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.config.types.Property;

import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * @author Srikanth P, Sivakumar Thyagarajan
 */

@Service
@ResourceDeployerInfo(org.glassfish.connectors.config.ConnectorConnectionPool.class)
@Singleton
public class ConnectorConnectionPoolDeployer extends AbstractConnectorResourceDeployer{

    @Inject
    private ConnectorRuntime runtime;

    private static Logger _logger = LogDomains.getLogger(ConnectorConnectionPoolDeployer.class, LogDomains.RSR_LOGGER);

    private static StringManager localStrings =
            StringManager.getManager(ConnectorConnectionPoolDeployer.class);

    private static final Locale locale = Locale.getDefault();

    /**
     * {@inheritDoc}
     */
    public void deployResource(Object resource, String applicationName, String moduleName) throws Exception {
        //deployResource is not synchronized as there is only one caller
        //ResourceProxy which is synchronized

        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ConnectorConnectionPoolDeployer : deployResource ");
        }

        final org.glassfish.connectors.config.ConnectorConnectionPool
                domainCcp =
                (org.glassfish.connectors.config.ConnectorConnectionPool) resource;

        // If the user is trying to modify the default pool,
        // redirect call to redeployResource
        if (ConnectionPoolObjectsUtils.isPoolSystemPool(domainCcp)) {
            this.redeployResource(resource);
            return;
        }

        PoolInfo poolInfo = new PoolInfo(domainCcp.getName(), applicationName, moduleName);
        final ConnectorConnectionPool ccp = getConnectorConnectionPool(domainCcp, poolInfo);
        String rarName = domainCcp.getResourceAdapterName();
        String connDefName = domainCcp.getConnectionDefinitionName();
        List<Property> props = domainCcp.getProperty();
        List<SecurityMap> securityMaps = domainCcp.getSecurityMap();

        populateConnectorConnectionPool(ccp, connDefName, rarName, props, securityMaps);
        final String defName = domainCcp.getConnectionDefinitionName();

        /*if (domainCcp.isEnabled()) {
            if (UNIVERSAL_CF.equals(defName) || QUEUE_CF.equals(defName) || TOPIC_CF.equals(defName)) {
            //registers the jsr77 object for the mail resource deployed
            final ManagementObjectManager mgr =
                getAppServerSwitchObject().getManagementObjectManager();
            mgr.registerJMSResource(domainCcp.getName(), defName, null, null,
                    getPropNamesAsStrArr(domainCcp.getElementProperty()),
                    getPropValuesAsStrArr(domainCcp.getElementProperty()));
            }

        } else {
                _logger.log(Level.INFO, "core.resource_disabled",
                        new Object[] {domainCcp.getName(),
                        IASJ2EEResourceFactoryImpl.CONNECTOR_CONN_POOL_TYPE});
        }*/


        if(_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "Calling backend to add connectorConnectionPool", domainCcp.getResourceAdapterName());
        }
        runtime.createConnectorConnectionPool(ccp, defName, domainCcp.getResourceAdapterName(),
                domainCcp.getProperty(), domainCcp.getSecurityMap());
        if(_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "Added connectorConnectionPool in backend",
                domainCcp.getResourceAdapterName());
        }

    }

    /**
     * {@inheritDoc}
     */
    public void deployResource(Object resource) throws Exception {
        org.glassfish.connectors.config.ConnectorConnectionPool ccp =
                (org.glassfish.connectors.config.ConnectorConnectionPool)resource;
        PoolInfo poolInfo = ConnectorsUtil.getPoolInfo(ccp);
        deployResource(resource, poolInfo.getApplicationName(), poolInfo.getModuleName());
    }

    /**
     * {@inheritDoc}
     */
    public void undeployResource(Object resource, String applicationName, String moduleName) throws Exception{
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ConnectorConnectionPoolDeployer : undeployResource : ");
        }
        final org.glassfish.connectors.config.ConnectorConnectionPool
                domainCcp =
                (org.glassfish.connectors.config.ConnectorConnectionPool) resource;
        PoolInfo poolInfo = new PoolInfo(domainCcp.getName(), applicationName, moduleName);
        actualUndeployResource(domainCcp, poolInfo);
    }

    /**
     * {@inheritDoc}
     */
    public synchronized void undeployResource(Object resource)
            throws Exception {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ConnectorConnectionPoolDeployer : undeployResource : ");
        }
        final org.glassfish.connectors.config.ConnectorConnectionPool
                domainCcp =
                (org.glassfish.connectors.config.ConnectorConnectionPool) resource;
        PoolInfo poolInfo = ConnectorsUtil.getPoolInfo(domainCcp);

        actualUndeployResource(domainCcp, poolInfo);
    }

    private void actualUndeployResource(org.glassfish.connectors.config.ConnectorConnectionPool domainCcp,
                                        PoolInfo poolInfo) throws ConnectorRuntimeException {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "Calling backend to delete ConnectorConnectionPool", domainCcp);
        }
        runtime.deleteConnectorConnectionPool(poolInfo);
        if(_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "Deleted ConnectorConnectionPool in backend", domainCcp);
        }

        /*//unregister the managed object
        if (QUEUE_CF.equals(defName) || TOPIC_CF.equals(defName)) {
            //registers the jsr77 object for the mail resource deployed
            final ManagementObjectManager mgr =
                getAppServerSwitchObject().getManagementObjectManager();
            mgr.unregisterJMSResource(domainCcp.getName());
        }*/
    }

    /**
     * {@inheritDoc}
     */
    public synchronized void redeployResource(Object resource)
            throws Exception {
        //Connector connection pool reconfiguration or
        //change in security maps
        org.glassfish.connectors.config.ConnectorConnectionPool
                domainCcp =
                (org.glassfish.connectors.config.ConnectorConnectionPool) resource;
        List<SecurityMap> securityMaps = domainCcp.getSecurityMap();

        //Since 8.1 PE/SE/EE, only if pool has already been deployed in this
        //server-instance earlier, reconfig this pool
        PoolInfo poolInfo = ConnectorsUtil.getPoolInfo(domainCcp);
        if (!runtime.isConnectorConnectionPoolDeployed(poolInfo)) {
            if(_logger.isLoggable(Level.FINE)) {
                _logger.fine("The connector connection pool " + poolInfo
                    + " is either not referred or not yet created in "
                    + "this server instance and pool and hence "
                    + "redeployment is ignored");
            }
            return;
        }


        String rarName = domainCcp.getResourceAdapterName();
        String connDefName = domainCcp.getConnectionDefinitionName();
        List<Property> props = domainCcp.getProperty();
        ConnectorConnectionPool ccp = getConnectorConnectionPool(domainCcp, poolInfo);
        populateConnectorConnectionPool(ccp, connDefName, rarName, props, securityMaps);

        boolean poolRecreateRequired = false;
        try {
            if(_logger.isLoggable(Level.FINE)) {
                _logger.fine("Calling reconfigure pool");
            }
            poolRecreateRequired = runtime.reconfigureConnectorConnectionPool(ccp,
                    new HashSet());
        } catch (ConnectorRuntimeException cre) {
            Object params[] = new Object[]{poolInfo, cre};
            _logger.log(Level.WARNING,"error.reconfiguring.pool", params);
        }

        if (poolRecreateRequired) {
            if(_logger.isLoggable(Level.FINE)) {
                _logger.fine("Pool recreation required");
            }
            runtime.recreateConnectorConnectionPool(ccp);
            if(_logger.isLoggable(Level.FINE)) {
                _logger.fine("Pool recreation done");
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public boolean handles(Object resource){
        return resource instanceof org.glassfish.connectors.config.ConnectorConnectionPool;
    }

    /**
     * @inheritDoc
     */
    public boolean supportsDynamicReconfiguration() {
        return false;
    }

    /**
     * @inheritDoc
     */
    public Class[] getProxyClassesForDynamicReconfiguration() {
        return new Class[0];
    }

    /**
     * {@inheritDoc}
     */
    public synchronized void disableResource(Object resource)
            throws Exception {
    }

    /**
     * {@inheritDoc}
     */
    public synchronized void enableResource(Object resource)
            throws Exception {
    }

    private ConnectorConnectionPool getConnectorConnectionPool(
            org.glassfish.connectors.config.ConnectorConnectionPool domainCcp, PoolInfo poolInfo)
            throws Exception {
        ConnectorConnectionPool ccp ;
        ccp = new ConnectorConnectionPool(poolInfo);
        ccp.setSteadyPoolSize(domainCcp.getSteadyPoolSize());
        ccp.setMaxPoolSize(domainCcp.getMaxPoolSize());
        ccp.setMaxWaitTimeInMillis(domainCcp.getMaxWaitTimeInMillis());
        ccp.setPoolResizeQuantity(domainCcp.getPoolResizeQuantity());
        ccp.setIdleTimeoutInSeconds(domainCcp.getIdleTimeoutInSeconds());
        ccp.setFailAllConnections(Boolean.valueOf(domainCcp.getFailAllConnections()));
        ccp.setAuthCredentialsDefinedInPool(
                isAuthCredentialsDefinedInPool(domainCcp));
        //The line below will change for 9.0. We will get this from
        //the domain.xml
        ccp.setConnectionValidationRequired(Boolean.valueOf(domainCcp.getIsConnectionValidationRequired()));

        String txSupport = domainCcp.getTransactionSupport();
        int txSupportIntVal = parseTransactionSupportString(txSupport);

        if (txSupportIntVal == -1) {
            //if transaction-support attribute is null load the value
            //from the ra.xml
            if (_logger.isLoggable(Level.FINE)) {
                _logger.fine("Got transaction-support attr null from domain.xml");
            }
            txSupportIntVal = ConnectionPoolObjectsUtils.getTransactionSupportFromRaXml(
                    domainCcp.getResourceAdapterName());

        } else {
            //We got some valid transaction-support attribute value
            //so go figure if it is valid.
            //The tx support is valid if it is less-than/equal-to
            //the value specified in the ra.xml
            if (!ConnectionPoolObjectsUtils.isTxSupportConfigurationSane(txSupportIntVal,
                    domainCcp.getResourceAdapterName())) {

                String i18nMsg = localStrings.getString("ccp_deployer.incorrect_tx_support");
                ConnectorRuntimeException cre = new
                        ConnectorRuntimeException(i18nMsg);

                _logger.log(Level.SEVERE, "rardeployment.incorrect_tx_support",
                        ccp.getName());
                throw cre;
            }
        }
        if (_logger.isLoggable(Level.FINE)) {
            _logger.fine("setting txSupportVal to " + txSupportIntVal +
                    " in pool " + domainCcp.getName());
        }
        ccp.setTransactionSupport(txSupportIntVal);

        //Always for ccp
        ccp.setNonComponent(false);
        ccp.setNonTransactional(false);
        ccp.setConnectionLeakTracingTimeout(domainCcp.getConnectionLeakTimeoutInSeconds());
        ccp.setConnectionReclaim(Boolean.valueOf(domainCcp.getConnectionLeakReclaim()));

        ccp.setMatchConnections(Boolean.valueOf(domainCcp.getMatchConnections()));
        ccp.setAssociateWithThread(Boolean.valueOf(domainCcp.getAssociateWithThread()));
        ccp.setPooling(Boolean.valueOf(domainCcp.getPooling()));
        ccp.setPingDuringPoolCreation(Boolean.valueOf(domainCcp.getPing()));

        boolean lazyConnectionEnlistment = Boolean.valueOf(domainCcp.getLazyConnectionEnlistment());
        boolean lazyConnectionAssociation = Boolean.valueOf(domainCcp.getLazyConnectionAssociation());

        if (lazyConnectionAssociation) {
            if (lazyConnectionEnlistment) {
                ccp.setLazyConnectionAssoc(true);
                ccp.setLazyConnectionEnlist(true);
            } else {
                _logger.log(Level.SEVERE,
                        "conn_pool_obj_utils.lazy_enlist-lazy_assoc-invalid-combination",
                        domainCcp.getName());
                String i18nMsg = localStrings.getString(
                        "cpou.lazy_enlist-lazy_assoc-invalid-combination",  domainCcp.getName());
                throw new RuntimeException(i18nMsg);
            }
        } else {
            ccp.setLazyConnectionAssoc(lazyConnectionAssociation);
            ccp.setLazyConnectionEnlist(lazyConnectionEnlistment);
        }
        boolean pooling = Boolean.valueOf(domainCcp.getPooling());

        //TODO: should this be added to the beginning of this method?
        if(!pooling) {
            //Throw exception if assoc with thread is set to true.
            if(Boolean.valueOf(domainCcp.getAssociateWithThread())) {
                _logger.log(Level.SEVERE, "conn_pool_obj_utils.pooling_disabled_assocwiththread_invalid_combination",
                        domainCcp.getName());
                String i18nMsg = localStrings.getString(
                        "cpou.pooling_disabled_assocwiththread_invalid_combination", domainCcp.getName());
                throw new RuntimeException(i18nMsg);
            }

            //Below are useful in pooled environment only.
            //Throw warning for connection validation/validate-atmost-once/
            //match-connections/max-connection-usage-count/idele-timeout
            if(Boolean.valueOf(domainCcp.getIsConnectionValidationRequired())) {
                _logger.log(Level.WARNING, "conn_pool_obj_utils.pooling_disabled_conn_validation_invalid_combination",
                        domainCcp.getName());
            }
            if(Integer.parseInt(domainCcp.getValidateAtmostOncePeriodInSeconds()) > 0) {
                _logger.log(Level.WARNING, "conn_pool_obj_utils.pooling_disabled_validate_atmost_once_invalid_combination",
                        domainCcp.getName());
            }
            if(Boolean.valueOf(domainCcp.getMatchConnections())) {
                _logger.log(Level.WARNING, "conn_pool_obj_utils.pooling_disabled_match_connections_invalid_combination",
                        domainCcp.getName());
            }
            if(Integer.parseInt(domainCcp.getMaxConnectionUsageCount()) > 0) {
                _logger.log(Level.WARNING, "conn_pool_obj_utils.pooling_disabled_max_conn_usage_invalid_combination",
                        domainCcp.getName());
            }
            if(Integer.parseInt(domainCcp.getIdleTimeoutInSeconds()) > 0) {
                _logger.log(Level.WARNING, "conn_pool_obj_utils.pooling_disabled_idle_timeout_invalid_combination",
                        domainCcp.getName());
            }
        }
        ccp.setPooling(pooling);

        ccp.setMaxConnectionUsage(domainCcp.getMaxConnectionUsageCount());
        ccp.setValidateAtmostOncePeriod(
                domainCcp.getValidateAtmostOncePeriodInSeconds());

        ccp.setConCreationRetryAttempts(
                domainCcp.getConnectionCreationRetryAttempts());
        ccp.setConCreationRetryInterval(
                domainCcp.getConnectionCreationRetryIntervalInSeconds());

        //IMPORTANT
        //Here all properties that will be checked by the
        //convertElementPropertyToPoolProperty method need to be set to
        //their default values
        convertElementPropertyToPoolProperty(ccp, domainCcp);
        return ccp;
    }

    private void populateConnectorConnectionPool(ConnectorConnectionPool ccp,
                                                 String connectionDefinitionName, String rarName,
                                                 List<Property> props, List<SecurityMap> securityMaps)
            throws ConnectorRuntimeException {

        ConnectorDescriptor connectorDescriptor = runtime.getConnectorDescriptor(rarName);
        if (connectorDescriptor == null) {
            ConnectorRuntimeException cre = new ConnectorRuntimeException("Failed to get connection pool object");
            _logger.log(Level.SEVERE, "rardeployment.connector_descriptor_notfound_registry", rarName);
            _logger.log(Level.SEVERE, "", cre);
            throw cre;
        }
        Set connectionDefs =
                connectorDescriptor.getOutboundResourceAdapter().getConnectionDefs();
        ConnectionDefDescriptor cdd = null;
        Iterator it = connectionDefs.iterator();
        while (it.hasNext()) {
            cdd = (ConnectionDefDescriptor) it.next();
            if (connectionDefinitionName.equals(cdd.getConnectionFactoryIntf()))
                break;

        }
        ConnectorDescriptorInfo cdi = new ConnectorDescriptorInfo();

        cdi.setRarName(rarName);
        cdi.setResourceAdapterClassName(connectorDescriptor.getResourceAdapterClass());
        cdi.setConnectionDefinitionName(cdd.getConnectionFactoryIntf());
        cdi.setManagedConnectionFactoryClass(cdd.getManagedConnectionFactoryImpl());
        cdi.setConnectionFactoryClass(cdd.getConnectionFactoryImpl());
        cdi.setConnectionFactoryInterface(cdd.getConnectionFactoryIntf());
        cdi.setConnectionClass(cdd.getConnectionImpl());
        cdi.setConnectionInterface(cdd.getConnectionIntf());
        Properties properties = new Properties();
        //skip the AddressList in case of JMS RA.
        //Refer Sun Bug :6579154 - Equivalent Oracle Bug :12206278
        if(rarName.trim().equals(ConnectorRuntime.DEFAULT_JMS_ADAPTER)){
            properties.put("AddressList","localhost");
        }
        Set mergedProps = ConnectorDDTransformUtils.mergeProps(props, cdd.getConfigProperties(),properties);
        cdi.setMCFConfigProperties(mergedProps);
        cdi.setResourceAdapterConfigProperties(connectorDescriptor.getConfigProperties());
        ccp.setConnectorDescriptorInfo(cdi);
        ccp.setSecurityMaps(SecurityMapUtils.getConnectorSecurityMaps(securityMaps));

    }

    private int parseTransactionSupportString(String txSupport) {
        return ConnectionPoolObjectsUtils.parseTransactionSupportString(txSupport);
    }

    /**
     * The idea is to convert the ElementProperty values coming from the admin
     * connection pool to standard pool attributes thereby making it
     * easy in case of a reconfig
     */
    public void convertElementPropertyToPoolProperty(ConnectorConnectionPool ccp,
                                                     org.glassfish.connectors.config.ConnectorConnectionPool domainCcp) {
        List<Property> elemProps = domainCcp.getProperty();
        if (elemProps == null) {
            return;
        }
        for (Property ep : elemProps) {
            if (ep != null) {
                if ("MATCHCONNECTIONS".equals(ep.getName().toUpperCase(locale))) {
                    if (_logger.isLoggable(Level.FINE)) {
                        _logger.fine(" ConnectorConnectionPoolDeployer::  Setting matchConnections");
                    }
                    ccp.setMatchConnections(toBoolean(ep.getValue(), true));
                } else if ("LAZYCONNECTIONASSOCIATION".equals(ep.getName().toUpperCase(locale))) {
                    ConnectionPoolObjectsUtils.setLazyEnlistAndLazyAssocProperties(ep.getValue(),
                            domainCcp.getProperty(), ccp);
                    if(_logger.isLoggable(Level.FINE)) {
                        _logger.fine("LAZYCONNECTIONASSOCIATION");
                    }

                } else if ("LAZYCONNECTIONENLISTMENT".equals(ep.getName().toUpperCase(locale))) {
                    ccp.setLazyConnectionEnlist(toBoolean(ep.getValue(), false));
                    if(_logger.isLoggable(Level.FINE)) {
                        _logger.fine("LAZYCONNECTIONENLISTMENT");
                    }

                } else if ("ASSOCIATEWITHTHREAD".equals(ep.getName().toUpperCase(locale))) {
                    ccp.setAssociateWithThread(toBoolean(ep.getValue(), false));
                    if(_logger.isLoggable(Level.FINE)) {
                        _logger.fine("ASSOCIATEWITHTHREAD");
                    }
                } else if ("POOLDATASTRUCTURE".equals(ep.getName().toUpperCase(locale))) {
                    ccp.setPoolDataStructureType(ep.getValue());
                    if(_logger.isLoggable(Level.FINE)) {
                        _logger.fine("POOLDATASTRUCTURE");
                    }

                } else if ("POOLWAITQUEUE".equals(ep.getName().toUpperCase(locale))) {
                    ccp.setPoolWaitQueue(ep.getValue());
                    if(_logger.isLoggable(Level.FINE)) {
                        _logger.fine("POOLWAITQUEUE");
                    }

                } else if ("DATASTRUCTUREPARAMETERS".equals(ep.getName().toUpperCase(locale))) {
                    ccp.setDataStructureParameters(ep.getValue());
                    if(_logger.isLoggable(Level.FINE)) {
                        _logger.fine("DATASTRUCTUREPARAMETERS");
                    }
                } else if ("PREFER-VALIDATE-OVER-RECREATE".equals(ep.getName().toUpperCase(locale))) {
                    String value = ep.getValue();
                    if (_logger.isLoggable(Level.FINE)) {
                        _logger.fine(" ConnectorConnectionPoolDeployer::  " +
                                "Setting PREFER-VALIDATE-OVER-RECREATE to " +
                                value);
                    }
                    ccp.setPreferValidateOverRecreate(toBoolean(value, false));
                }
            }
        }
    }

    private boolean toBoolean(Object prop, boolean defaultVal) {
        if (prop == null) {
            return defaultVal;
        }

        return Boolean.valueOf((String) prop);
    }

    private boolean isAuthCredentialsDefinedInPool(
            org.glassfish.connectors.config.ConnectorConnectionPool domainCcp) {
        List<Property> elemProps = domainCcp.getProperty();
        if (elemProps == null) {
            return false;
        }

        for (Property ep : elemProps) {

            if (ep.getName().equalsIgnoreCase("UserName") ||
                    ep.getName().equalsIgnoreCase("User") ||
                    ep.getName().equalsIgnoreCase("Password")) {
                return true;
            }
        }
        return false;
    }
}
