/*
 * 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.coordination.rmi;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.rmi.Naming;
import java.rmi.NoSuchObjectException;
import java.rmi.server.UnicastRemoteObject;

import javax.naming.Context;

import org.eclipse.persistence.exceptions.RemoteCommandManagerException;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.sessions.coordination.RemoteConnection;
import org.eclipse.persistence.internal.sessions.coordination.rmi.RMIRemoteCommandConnection;
import org.eclipse.persistence.internal.sessions.coordination.rmi.RMIRemoteCommandConnectionImpl;
import org.eclipse.persistence.internal.sessions.coordination.rmi.RMIRemoteConnection;
import org.eclipse.persistence.sessions.coordination.RemoteCommandManager;
import org.eclipse.persistence.sessions.coordination.ServiceId;
import org.eclipse.persistence.sessions.coordination.TransportManager;

/**
 * <p>
 * <b>Purpose</b>: Provide an RMI transport implementation for RCM.
 * </p><p>
 * <b>Description</b>: This class manages the RMI remote connections to other
 * RCM service instances and posts the local RMI 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 class RMITransportManager extends TransportManager {

    private Method narrow;
    private Constructor constructor;

    public RMITransportManager(RemoteCommandManager rcm) {
        this.rcm = rcm;
        this.initialize();
    }

    /**
     * INTERNAL:
     * Create and return an RMI remote connection to the specified service
     */
    @Override
    public RemoteConnection createConnection(ServiceId connectionServiceId) {
        RemoteConnection connection = null;

        if (namingServiceType == REGISTRY_NAMING_SERVICE) {
            connection = createConnectionFromRegistry(connectionServiceId.getId(), connectionServiceId.getURL());

        } else if (namingServiceType == JNDI_NAMING_SERVICE) {
            connection = createConnectionFromJNDI(connectionServiceId.getId(), connectionServiceId.getURL());
        }
        if (connection != null) {
            connection.setServiceId(connectionServiceId);
        }
        return connection;
    }

    /**
     * INTERNAL:
     * Look the specified remote object up in JNDI and return a Connection to it.
     */
    protected RemoteConnection createConnectionFromJNDI(String remoteObjectIdentifier, String hostURL) {
        Object[] args = { remoteObjectIdentifier, hostURL };
        rcm.logDebug("looking_up_remote_conn_in_jndi", args);
        try {
            Context context = getRemoteHostContext(hostURL);

            //Use JNDI lookup(), rather than the RMI version,
            //AND replace the Java remote interface cast with a call to javax.rmi.PortableRemoteObject.narrow():
            if (narrow != null) {
                return new RMIRemoteConnection((RMIRemoteCommandConnection) narrow.invoke(
                        null, context.lookup(remoteObjectIdentifier), RMIRemoteCommandConnection.class));
            } else {
                return new RMIRemoteConnection((RMIRemoteCommandConnection)context.lookup(remoteObjectIdentifier));
            }
        } catch (Exception e) {
            try {
                rcm.handleException(RemoteCommandManagerException.errorLookingUpRemoteConnection(remoteObjectIdentifier, hostURL, e));
            } catch (Exception ex2) {
                 // Must catch this exception and log a debug message
                rcm.logDebug("unable_to_look_up_remote_conn_in_jndi", args);
            }
        }
        return null;
    }

    /**
     * INTERNAL:
     * Look the specified remote object up in the RMIRegistry and return a Connection to it.
     */
    protected RemoteConnection createConnectionFromRegistry(String remoteObjectIdentifier, String hostURL) {
        String formattedUrl = formatURLforRegistry(hostURL, remoteObjectIdentifier);
        Object[] args = { formattedUrl };
        rcm.logDebug("looking_up_remote_conn_in_registry", args);
        try {
            return new RMIRemoteConnection((RMIRemoteCommandConnection)Naming.lookup(formattedUrl));
        } catch (Exception e) {
            try {
                rcm.handleException(RemoteCommandManagerException.errorLookingUpRemoteConnection(remoteObjectIdentifier, hostURL, e));
            } catch (Exception ex2) {
                // Must catch this exception and log a debug message
                rcm.logDebug("unable_to_look_up_remote_conn_in_registry", args);
            }
        }
        return null;
    }

    /**
     * INTERNAL:
     * Create the local command connection for this transport in a naming service and
     * return it.
     */
    @Override
    public void createLocalConnection() {
        if (namingServiceType == REGISTRY_NAMING_SERVICE) {
            createLocalConnectionInRegistry();

        } else if (namingServiceType == JNDI_NAMING_SERVICE) {
            createLocalConnectionInJNDI();
        }
        if (localConnection != null) {
            localConnection.setServiceId(rcm.getServiceId());
        }
    }

    /**
     * INTERNAL:
     * Put the local command connection of this transport in JNDI and return it
     */
    protected void createLocalConnectionInJNDI() {
        try {
            // Register the remote connection in JNDI naming service
            RMIRemoteCommandConnection remoteConnectionObject;
            if (narrow != null) {
                if (constructor == null) {
                    try {
                        constructor = PrivilegedAccessHelper.getConstructorFor(
                            Class.forName("org.eclipse.persistence.internal.sessions.coordination.rmi.iiop.RMIRemoteCommandConnectionImpl"),
                            new Class[] {RemoteCommandManager.class}, false);
                    } catch (ReflectiveOperationException e) {
                        throw RemoteCommandManagerException.errorInitCorba("javax.rmi.PortableRemoteObject", e);
                    }
                }
                try {
                    remoteConnectionObject = (RMIRemoteCommandConnection) PrivilegedAccessHelper.invokeConstructor(constructor, new Object[] {rcm});
                } catch (ReflectiveOperationException e) {
                    // TODO Auto-generated catch block
                    throw RemoteCommandManagerException.errorInitCorba("javax.rmi.PortableRemoteObject", e);
                }
            } else {
                remoteConnectionObject = new RMIRemoteCommandConnectionImpl(rcm);
            }
            Object[] args = { rcm.getServiceId().getId() };
            rcm.logDebug("register_local_connection_in_jndi", args);
            getLocalHostContext().rebind(rcm.getServiceId().getId(), remoteConnectionObject);
            localConnection = new RMIRemoteConnection(remoteConnectionObject);
        } catch (Exception exception) {
            rcm.handleException(RemoteCommandManagerException.errorBindingConnection(rcm.getServiceId().toString(), exception));
        }
    }

    /**
     * INTERNAL:
     * Put the local command connection of this transport in the Registry and return it
     */
    protected RemoteConnection createLocalConnectionInRegistry() {
        String fullURL = formatURLforRegistry(rcm.getServiceId().getURL(), rcm.getServiceId().getId());

        try {
            // Register the remote connection in RMI Registry naming service
            RMIRemoteCommandConnectionImpl remoteConnectionObject = new RMIRemoteCommandConnectionImpl(rcm);
            Object[] args = { fullURL };
            rcm.logDebug("register_local_connection_in_registry", args);
            Naming.rebind(fullURL, remoteConnectionObject);
            localConnection = new RMIRemoteConnection(remoteConnectionObject);
        } catch (Exception exception) {
            rcm.handleException(RemoteCommandManagerException.errorBindingConnection(fullURL, exception));
        }
        return localConnection;
    }

    /**
     * INTERNAL:
     * Return the context used for looking up in local JNDI.
     */
    public Context getLocalHostContext() {
        return getContext(getLocalContextProperties());
    }

    /**
     * INTERNAL:
     * Format the URL so that it can be used to look up the RMI Registry.
     */
    private String formatURLforRegistry(String url, String serviceName) {
        if (url == null) {
            return null;
        }
        String fullURL = url;

        if ((fullURL.endsWith("/") || fullURL.endsWith("\\"))) {
            fullURL = fullURL.substring(0, fullURL.length() - 1);
        }
        return fullURL + "/" + serviceName;
    }

    /**
     * INTERNAL:
     * Return the default local URL for JNDI lookups
     */
    public String getDefaultLocalUrl() {
        try {
            // Look up the local host name and paste it in a default URL
            String localHost = InetAddress.getLocalHost().getHostName();
            if (narrow != null) {
                return DEFAULT_IIOP_URL_PROTOCOL + "::" + localHost + ":" + DEFAULT_IIOP_URL_PORT;
            } else {
                return DEFAULT_URL_PROTOCOL + "://" + localHost + ":" + DEFAULT_URL_PORT;
            }
        } catch (IOException exception) {
            throw RemoteCommandManagerException.errorGettingHostName(exception);
        }
    }

    /**
     * INTERNAL:
     * Initialize default properties for RMI.
     */
    @Override
    public void initialize() {
        super.initialize();
        // URL is not required when in a cluster, do not default.
        //if (rcm.getServiceId().getURL() == null) {
        //    rcm.getServiceId().setURL(getDefaultLocalUrl());
        //}
        namingServiceType = DEFAULT_NAMING_SERVICE;
    }

    /**
     * ADVANCED:
     * Remove the local connection from remote accesses. The implementation removes the local connection from JNDI or the
     * RMI registry, un-exports it from the RMI runtime, and sets it to null.
     * This method is invoked internally by EclipseLink when the RCM is shutdown and should not be invoked by user's application.
     */
    @Override
    public void removeLocalConnection() {
        String unbindName = null;
        try {
            if (namingServiceType == REGISTRY_NAMING_SERVICE) {
                unbindName = formatURLforRegistry(rcm.getServiceId().getURL(), rcm.getServiceId().getId());
                Naming.unbind(unbindName);
            } else if (namingServiceType == JNDI_NAMING_SERVICE) {
                unbindName = rcm.getServiceId().getId();
                getLocalHostContext().unbind(unbindName);
            } else {
                return;
            }
        } catch (Exception exception) {
            rcm.handleException(RemoteCommandManagerException.errorUnbindingLocalConnection(unbindName, exception));
        } finally {
            // unexport the local connection from the RMI runtime
            RMIRemoteConnection localConnection = (RMIRemoteConnection)getConnectionToLocalHost();
            if (localConnection != null) {
                RMIRemoteCommandConnection commandConnection = localConnection.getConnection();
                if (commandConnection != null) {
                    try {
                        UnicastRemoteObject.unexportObject(commandConnection, true);
                    } catch (NoSuchObjectException nso) {
                        // if the object isn't exported, ignore this exception since cleanup is being performed
                    }
                }
                this.localConnection = null;
            }
        }
    }

    public void setIsRMIOverIIOP(boolean b) {
        if (b) {
            try {
                narrow = PrivilegedAccessHelper.getDeclaredMethod(Class.forName("javax.rmi.PortableRemoteObject"), "narrow", new Class[] {Object.class, Class.class});
            } catch (ReflectiveOperationException e) {
                // TODO Auto-generated catch block
                throw RemoteCommandManagerException.errorInitCorba("javax.rmi.PortableRemoteObject", e);
            }
        } else {
            narrow = null;
        }

    }
}
