org.eclipse.persistence.sessions.coordination.rmi.RMITransportManager Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 1998, 2023 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 org.eclipse.persistence.exceptions.RemoteCommandManagerException;
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;
import javax.naming.Context;
import java.io.IOException;
import java.net.InetAddress;
import java.rmi.Naming;
import java.rmi.NoSuchObjectException;
import java.rmi.server.UnicastRemoteObject;
/**
*
* Purpose: Provide an RMI transport implementation for RCM.
*
* Description: 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.
*
* @author Steven Vo
* @since OracleAS TopLink 10g (9.0.4)
*/
public class RMITransportManager extends TransportManager {
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);
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 = 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();
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;
}
}
}
}