/*
 * 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
//     17/10/2008-1.1  Michael O'Brien
//       - 251005: The default JNDI InitialContextFactory is modified from
//       OC4J: oracle.j2ee.rmi.RMIInitialContextFactory to
//       WebLogic: weblogic.jndi.WLInitialContextFactory
package org.eclipse.persistence.sessions.coordination;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Map;

import javax.naming.Context;
import javax.naming.NamingException;

import org.eclipse.persistence.exceptions.CommunicationException;
import org.eclipse.persistence.exceptions.RemoteCommandManagerException;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.SecurableObjectHolder;
import org.eclipse.persistence.internal.sessions.coordination.ConnectToHostCommand;
import org.eclipse.persistence.internal.sessions.coordination.RemoteConnection;

/**
 * <p>
 * <b>Purpose</b>: Provide an abstract class that offers a common API to handling
 * remote command connections.
 * </p><p>
 * <b>Description</b>: This class manages the remote connections to other RCM service
 * instances and posts the local connection to this service instance in a name
 * service so that other RCM service instances can connect to it.
 * </p>
 * @author Steven Vo
 * @since OracleAS TopLink 10<i>g</i> (9.0.4)
 */
public abstract class TransportManager {

    /** The remote command connection to this transport */
    protected RemoteConnection localConnection;

    /** The RCM that manages this transport */
    protected RemoteCommandManager rcm;

    /** The type of naming service used to look up other connections */
    protected int namingServiceType;

    /** Properties to obtain the context used for local JNDI access */
    protected Hashtable localContextProperties;

    /** Properties to obtain the context used for remote JNDI access */
    protected Hashtable remoteContextProperties;

    /** Determines whether a connection should be discarded if an error occurs on it */
    protected boolean shouldRemoveConnectionOnError;

    /** Connections to other services */
    protected Hashtable<String, RemoteConnection> connectionsToExternalServices;

    /** Security util that is used to decrypt and encrypt password */
    protected SecurableObjectHolder securableObjectHolder;

    public static final boolean DEFAULT_REMOVE_CONNECTION_ON_ERROR_MODE = true;

    /** Valid values for naming service type */
    public static final int JNDI_NAMING_SERVICE = 0;
    public static final int REGISTRY_NAMING_SERVICE = 1;

    /** Defaults for RMI applications */
    public static final String DEFAULT_URL_PROTOCOL = "rmi";
    public static final String DEFAULT_IIOP_URL_PROTOCOL = "corbaname";
    public static final String DEFAULT_URL_PORT = "23791";
    public static final String DEFAULT_IIOP_URL_PORT = "5555#";
    public static final int DEFAULT_NAMING_SERVICE = JNDI_NAMING_SERVICE;

    /** Default JNDI properties for remote access */
    public static final String DEFAULT_CONTEXT_FACTORY = "weblogic.jndi.WLInitialContextFactory";
    public static final String DEFAULT_DEDICATED_CONNECTION_KEY = "dedicated.connection";
    public static final String DEFAULT_DEDICATED_CONNECTION_VALUE = "true";
    public static final String DEFAULT_USER_NAME = "admin";

    /**
     * Default constructor.
     */
    protected TransportManager() {
    }

    /**
     * INTERNAL:
     * Return a remote connection to the specified service
     */
    public abstract RemoteConnection createConnection(ServiceId serviceId);

    /**
     * INTERNAL:
     * Does nothing by default. In case TransportManager doesn't use DiscoveryManager
     * (createDiscoveryManager method retuns null)
     * this method called during RCM initialization to create all the necessary connections.
     * TransportManager ancestors that override createDiscoveryManager method to return null
     * must override this method, too.
     */
    public void createConnections() {
    }

    /**
     * INTERNAL:
     * This method is called by the remote command manager when this service should
     * connect back ('handshake') to the service from which this remote connection came.
     */
    public void connectBackToRemote(RemoteConnection connection) throws Exception {
        ConnectToHostCommand command = new ConnectToHostCommand();
        command.setServiceId(rcm.getServiceId());
        connection.executeCommand(command);
    }

    /**
     * INTERNAL:
     * Return a remote connection to this service
     */
    public RemoteConnection getConnectionToLocalHost() {
        return localConnection;
    }

    /**
     * INTERNAL:
     * Put the remote connection to local host in naming service and return the  of the created remote connection
     */
    public abstract void createLocalConnection();

    /**
     * PUBLIC:
     * Return the type of naming service used to look up remote connections to other
     * service instances.
     *
     * @return The type of naming service used.
     */
    public int getNamingServiceType() {
        return namingServiceType;
    }

    /**
     * ADVANCED:
     * Set the type of naming service used to look up remote connections to other
     * service instances. The service type must be one of JNDI_NAMING_SERVICE or
     * REGISTRY_NAMING_SERVICE.
     */
    public void setNamingServiceType(int serviceType) {
        namingServiceType = serviceType;
    }

    /**
     * PUBLIC:
     * Return the user name used as the value to the SECURITY_PRINCIPAL key in the
     * cached context properties.
     */
    public String getUserName() {
        return (String)getRemoteContextProperties().get(Context.SECURITY_PRINCIPAL);
    }

    /**
     * ADVANCED:
     * Set the user name used as the value to the SECURITY_PRINCIPAL key in the
     * cached context properties.
     */
    public void setUserName(String userName) {
        getRemoteContextProperties().put(Context.SECURITY_PRINCIPAL, userName);
    }

    /**
     * PUBLIC:
     * Return the password used as the value to the SECURITY_CREDENTIALS key in
     * the cached context properties.
     */
    public String getPassword() {
        return decrypt(getEncryptedPassword());
    }

    /**
     * PUBLIC:
     * Return the encrypted (assumed) password used as the value to the
     * SECURITY_CREDENTIALS key in the cached context properties.
     */
    public String getEncryptedPassword() {
        return (String) getRemoteContextProperties().get(Context.SECURITY_CREDENTIALS);
    }

    /**
     * ADVANCED:
     * Set the password used as the value to the SECURITY_CREDENTIALS key in the
     * cached context properties.
     */
    public void setPassword(String password) {
        if (password != null) {
            getRemoteContextProperties().put(Context.SECURITY_CREDENTIALS, encrypt(password));
        }
    }

    /**
     * ADVANCED:
     * Set the encrypted password used as the value to the SECURITY_CREDENTIALS key in the
     * cached context properties.
     */
    public void setEncryptedPassword(String encryptedPassword) {
        getRemoteContextProperties().put(Context.SECURITY_CREDENTIALS, encryptedPassword);
    }

    /**
     * PUBLIC:
     * Return the context factory name used as the value to the INITIAL_CONTEXT_FACTORY
     * key in the cached context properties.
     */
    public String getInitialContextFactoryName() {
        return (String)getRemoteContextProperties().get(Context.INITIAL_CONTEXT_FACTORY);
    }

    /**
     * ADVANCED:
     * Set the context factory name used as the value to the INITIAL_CONTEXT_FACTORY
     * key in the cached context properties.
     */
    public void setInitialContextFactoryName(String contextFactoryName) {
        getRemoteContextProperties().put(Context.INITIAL_CONTEXT_FACTORY, contextFactoryName);
    }

    /**
     * INTERNAL:
     * Helper method to get a naming context.
     */
    public Context getContext(Hashtable contextProperties) {
        try {
            return new javax.naming.InitialContext(contextProperties);
        } catch (NamingException exception) {
            RemoteCommandManagerException rcmException = RemoteCommandManagerException.errorObtainingContext(exception);
            rcm.handleException(RemoteCommandManagerException.errorObtainingContext(exception));
            throw rcmException;
        }
    }

    /**
     * ADVANCED:
     * Return the cached properties that will be used to create the initial context
     * when doing remote JNDI lookups.
     */
    public Hashtable getRemoteContextProperties() {
        return remoteContextProperties;
    }

    /**
     * ADVANCED:
     * Set the cached properties that will be used to create the initial context
     * when doing remote JNDI lookups.
     */
    public void setRemoteContextProperties(Hashtable properties) {
        remoteContextProperties = properties;
    }

    /**
     * ADVANCED:
     * Return the properties that will be used to create the initial context
     * for local JNDI access.
     */
    public Hashtable getLocalContextProperties() {
        if (localContextProperties == null) {
            localContextProperties = new Hashtable();
        }
        return localContextProperties;
    }

    /**
     * ADVANCED:
     * Set the properties that will be used to create the initial context
     * for local JNDI access.
     */
    public void setLocalContextProperties(Hashtable properties) {
        localContextProperties = properties;
    }

    /**
     * INTERNAL:
     */
    public RemoteCommandManager getRemoteCommandManager() {
        return rcm;
    }

    /**
     * INTERNAL:
     */
    public void setRemoteCommandManager(RemoteCommandManager rcm) {
        this.rcm = rcm;
    }

    /**
     * INTERNAL:
     * Add a remote Connection to a remote service.
     */
    public void addConnectionToExternalService(RemoteConnection connection) {
        if (connection == null) {
            return;
        }
        try {
            connectBackToRemote(connection);
            connectionsToExternalServices.put(connection.getServiceId().getId(), connection);
            Object[] args = { connection.getServiceId() };
            rcm.logDebug("received_connection_from", args);
        } catch (Exception exception) {
            try {
                rcm.handleException(CommunicationException.errorSendingConnectionService(connection.toString(), exception));
            } catch (RuntimeException reThrownException) {
                Object[] args = { connection.getServiceId(), reThrownException };
                rcm.logWarning("problem_adding_connection", args);
                if (!shouldRemoveConnectionOnError) {
                    throw reThrownException;
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Remove a remote connection from the list of connections to receive remote commands.
     */
    public void removeConnectionToExternalService(RemoteConnection connection) {
        synchronized (this) {
            connectionsToExternalServices.remove(connection.getServiceId().getId());
            connection.close();
        }
    }

    /**
     * INTERNAL:
     * Remove all remote connections from the list.
     */
    public void removeAllConnectionsToExternalServices() {
        synchronized (this) {
            Enumeration<RemoteConnection> connections = connectionsToExternalServices.elements();
            connectionsToExternalServices = new Hashtable(3);

            while (connections.hasMoreElements()) {
                connections.nextElement().close();
            }
        }
    }

    /**
     * INTERNAL:
     */
    public Map<String, RemoteConnection> getConnectionsToExternalServices() {
        return connectionsToExternalServices;
    }

    /**
     * INTERNAL:
     * Returns clone of the original map.
     */
    public Map<String, RemoteConnection> getConnectionsToExternalServicesForCommandPropagation() {
        return (Map<String, RemoteConnection>) connectionsToExternalServices.clone();
    }

    /**
     * PUBLIC:
     * Set whether connections to remote services should be disconnected when an
     * error occurs.
     */
    public void setShouldRemoveConnectionOnError(boolean shouldRemoveConnectionOnError) {
        this.shouldRemoveConnectionOnError = shouldRemoveConnectionOnError;
    }

    /**
     * PUBLIC:
     * Return whether connections to remote services should be disconnected when an
     * error occurs.
     */
    public boolean shouldRemoveConnectionOnError() {
        return shouldRemoveConnectionOnError;
    }

    /**
     * INTERNAL SECURITY:
     * Set encryption class that will be loaded by the SecurableObjectHolder
     */
    public void setEncryptionClassName(String encryptionClassName) {
        SecurableObjectHolder oldHolder = securableObjectHolder;

        // re-initialize encryption mechanism
        securableObjectHolder = new SecurableObjectHolder();
        securableObjectHolder.setEncryptionClassName(encryptionClassName);

        // re-encrypt password
        if (hasPassword()) {
            setPassword(oldHolder.getSecurableObject().decryptPassword(getEncryptedPassword()));
        }
    }

    /**
     * INTERNAL:
     * @return true if a non null password has been set.
     */
    protected boolean hasPassword() {
        return getRemoteContextProperties().containsKey(Context.SECURITY_CREDENTIALS) && getRemoteContextProperties().get(Context.SECURITY_CREDENTIALS) != null;
    }

    /**
     * INTERNAL:
     * Initialize default properties.
     */
    public void initialize() {
        this.shouldRemoveConnectionOnError = DEFAULT_REMOVE_CONNECTION_ON_ERROR_MODE;
        this.connectionsToExternalServices = new Hashtable(2);

        remoteContextProperties = new Hashtable();
        // Factory is not require inside the server, do not default.
        //remoteContextProperties.put(Context.INITIAL_CONTEXT_FACTORY, DEFAULT_CONTEXT_FACTORY);
        remoteContextProperties.put(DEFAULT_DEDICATED_CONNECTION_KEY, DEFAULT_DEDICATED_CONNECTION_VALUE);
        // User/password are not required inside the server, do not default.
        //remoteContextProperties.put(Context.SECURITY_PRINCIPAL, DEFAULT_USER_NAME);

        this.securableObjectHolder = new SecurableObjectHolder();
    }

    /**
     * INTERNAL:
     * Security method.
     */
    protected String encrypt(String pwd) {
        return securableObjectHolder.getSecurableObject().encryptPassword(pwd);
    }

    /**
     * INTERNAL:
     * Security method called by the children classes
     */
    protected String decrypt(String encryptedPwd) {
        return securableObjectHolder.getSecurableObject().decryptPassword(encryptedPwd);
    }

    /**
     * INTERNAL:
     * Return the context used for looking up in the JNDI space of the specified remote URL.
     */
    public Context getRemoteHostContext(String remoteHostURL) {
        Hashtable remoteProperties = (Hashtable)getRemoteContextProperties().clone();
        // Host is only required if JMS connection factory is not accessible from local JNDI.
        if (remoteHostURL != null) {
            remoteProperties.put(Context.PROVIDER_URL, remoteHostURL);
        }
        Object[] args = { remoteProperties };
        rcm.logDebug("context_props_for_remote_lookup", args);

        if (hasPassword()) {
            // decrypt password just before looking up context. Calling
            // getPassword() will decrypt it.
            remoteProperties.put(Context.SECURITY_CREDENTIALS, getPassword());
        }

        return getContext(remoteProperties);
    }

    /**
     * ADVANCED:
     * Factory of new DiscoveryManager for different transports.  The RemoteCommandManger uses this method to create its DicscoveryManager.
     * Sub-class of TransportManager should return special discovery if required.  The default is discovery type is DiscoveryManager;
     * If this method returns null then during initialization RemoteCommandManager
     * calls createConnections method.
     */
    public DiscoveryManager createDiscoveryManager() {
        return new DiscoveryManager(rcm);
    }

    /**
     * INTERNAL:
     * Remove all remote connections for its list and the local connection from JNDI or JMS Subsriber
     */
    public void discardConnections() {
        removeLocalConnection();
        removeAllConnectionsToExternalServices();
    }

    /**
     * ADVANCED:
     * Remove the local connection from remote accesses.  The implementation should set remove the local connection from JNDI or JMS and set it to null.
     * This method is invoked internally by TopLink when the RCM is shutdown and should not be invoked by user's application.
     */
    public abstract void removeLocalConnection();

    /**
     * Generic API to allow config to be set.
     */
    public void setConfig(String config) {
    }

    /**
     * INTERNAL:
     * Creates a new instance of {@code org.eclipse.persistence.sessions.coordination.rmi.RMITransportManager} class.
     * @param rcm cache coordination manager
     * @return new instance of RMI transport manager implementation
     */
    public static TransportManager newSunCORBATransportManager(final RemoteCommandManager rcm) {
        try {
            return (TransportManager) PrivilegedAccessHelper.invokeConstructor(
                    PrivilegedAccessHelper.getConstructorFor(
                            Class.forName("org.eclipse.persistence.sessions.coordination.corba.sun.SunCORBATransportManager"),
                            new Class<?>[] { RemoteCommandManager.class }, false),
                    new Object[] { rcm });
        } catch (ReflectiveOperationException e) {
            throw RemoteCommandManagerException.errorInitCorba("org.eclipse.persistence.sessions.coordination.corba.sun.SunCORBATransportManager", e);
        }
    }

}
