blob: ac81b57f24cebdd7981e133b7c22aeda83d6e35f [file] [log] [blame]
/****************************************************************************
* Copyright (c) 2010 Composent, Inc. and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* Contributors: Composent, Inc. - initial API and implementation
*
* SPDX-License-Identifier: EPL-2.0
*****************************************************************************/
package org.eclipse.ecf.provider.remoteservice.generic;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.*;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.ecf.core.ContainerConnectException;
import org.eclipse.ecf.core.events.*;
import org.eclipse.ecf.core.identity.*;
import org.eclipse.ecf.core.jobs.JobsExecutor;
import org.eclipse.ecf.core.security.IConnectContext;
import org.eclipse.ecf.core.sharedobject.*;
import org.eclipse.ecf.core.sharedobject.events.ISharedObjectActivatedEvent;
import org.eclipse.ecf.core.status.SerializableStatus;
import org.eclipse.ecf.core.util.*;
import org.eclipse.ecf.core.util.reflection.ClassUtil;
import org.eclipse.ecf.internal.provider.remoteservice.Activator;
import org.eclipse.ecf.internal.provider.remoteservice.IRemoteServiceProviderDebugOptions;
import org.eclipse.ecf.remoteservice.*;
import org.eclipse.ecf.remoteservice.asyncproxy.AsyncReturnUtil;
import org.eclipse.ecf.remoteservice.events.*;
import org.eclipse.ecf.remoteservice.util.AsyncUtil;
import org.eclipse.equinox.concurrent.future.*;
import org.eclipse.osgi.framework.eventmgr.*;
import org.osgi.framework.InvalidSyntaxException;
public class RegistrySharedObject extends BaseSharedObject implements IRemoteServiceContainerAdapter {
/**
* @since 3.3
*/
protected static final int ADD_REGISTRATION_REQUEST_TIMEOUT = Integer.parseInt(System.getProperty("org.eclipse.ecf.provider.remoteservice.addRegistrationRequestTimeout", "7000")); //$NON-NLS-1$ //$NON-NLS-2$
/**
* @since 4.2
*/
protected static final boolean PROPAGATE_RESPONSE_ERROR = new Boolean(System.getProperty("org.eclipse.ecf.provider.remoteservice.propagateResponseError", "true")).booleanValue(); //$NON-NLS-1$ //$NON-NLS-2$
private static int uniqueRequestId = 0;
private static synchronized Integer createNextRequestId() {
uniqueRequestId = (uniqueRequestId == Integer.MAX_VALUE) ? 0 : uniqueRequestId + 1;
return Integer.valueOf(uniqueRequestId);
}
/**
* registry impl for local remote service registrations
*/
protected RemoteServiceRegistryImpl localRegistry;
/**
* map of registry impls for remote registrys key: ID (identifier of remote container), value: RemoteServiceRegistryImpl (copy of remote service registry for remote container
*/
@SuppressWarnings("unchecked")
protected final Map remoteRegistrys = Collections.synchronizedMap(new HashMap());
/**
* List of remote service listeners (added to/removed from by addRemoteServiceListener/removeRemoteServiceListener
*/
protected final List serviceListeners = new ArrayList();
/**
* Map of add registration requests. key: Integer (unique Request id), value: AddRegistrationRequest
*/
protected Map addRegistrationRequests = new Hashtable();
/**
* Add registration request default timeout
* @since 3.0
*/
protected int addRegistrationRequestTimeout = ADD_REGISTRATION_REQUEST_TIMEOUT;
/**
* List of invocation requests...instances of Request
*/
@SuppressWarnings("unchecked")
protected List requests = Collections.synchronizedList(new ArrayList());
/**
* Connect context to be used for connect.
* @since 3.0
*/
protected IConnectContext connectContext;
/**
* @since 3.3
*/
protected final Object rsConnectLock = new Object();
/**
* Whether or not we are connected
* @since 3.3
*/
protected boolean rsConnected = false;
/**
* Add registration request default timeout.
* @since 3.3
*/
protected int rsConnectTimeout = ADD_REGISTRATION_REQUEST_TIMEOUT;
/**
* ListenerQueue for asynchronously dispatching remote service registration/unregistration
* events
* @since 3.3
*/
private ListenerQueue rsListenerDispatchQueue;
/**
* Queue lock so that rsListenerDispatchQueue above can be lazily instantiated
* @since 3.3
*/
private final Object rsQueueLock = new Object();
/**
* EventManager for the rsListenerDispatchEventManager
* @since 3.3
*/
private EventManager rsListenerDispatchEventManager;
/**
* @since 3.4
*/
protected long registryUpdateRequestTimeout = new Long(System.getProperty("org.eclipse.ecf.provider.remoteservice.registryUpdateRequestTimeout", "5000")).longValue(); //$NON-NLS-1$ //$NON-NLS-2$
private Hashtable pendingUpdateContainers = new Hashtable();
private List registryUpdateRequests = new ArrayList();
// system property allowing the executorType to be configured. Currently types are: jobs, threads, immediate.
private static final String DEFAULT_EXECUTOR_TYPE = System.getProperty("org.eclipse.ecf.provider.remoteservice.executorType", "jobs"); //$NON-NLS-1$ //$NON-NLS-2$
private IExecutor requestExecutor;
private Object remoteServiceCallPolicyLock = new Object();
private IRemoteServiceCallPolicy remoteServiceCallPolicy;
public RegistrySharedObject() {
//
}
// IRemoteServiceContainerAdapter methods
/**
* @since 3.4
*/
public IRemoteServiceReference[] getRemoteServiceReferences(ID target, ID[] idFilter, String clazz, String filter) throws InvalidSyntaxException, ContainerConnectException {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "getRemoteServiceReferences", new Object[] {target, idFilter, clazz, filter}); //$NON-NLS-1$
final IRemoteFilter remoteFilter = (filter == null) ? null : new RemoteFilterImpl(filter);
// First, if we need to connect, then do so
if (target != null)
connectToRemoteServiceTarget(target);
// Wait for any pending remote registry updates...whether we've connected or not
waitForPendingUpdates(idFilter);
// Now we lookup remote service references
final List references = new ArrayList();
// first from remote registrys
addReferencesFromRemoteRegistrys(idFilter, clazz, remoteFilter, references);
// then from the local registry
addReferencesFromLocalRegistry(idFilter, clazz, remoteFilter, references);
// And we return the result
@SuppressWarnings("unchecked")
final IRemoteServiceReference[] result = (IRemoteServiceReference[]) references.toArray(new IRemoteServiceReference[references.size()]);
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), "getRemoteServiceReferences", result); //$NON-NLS-1$
return (result.length == 0) ? null : result;
}
/* (non-Javadoc)
* @see org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter#getRemoteServiceReferences(org.eclipse.ecf.core.identity.ID[], java.lang.String, java.lang.String)
*/
public IRemoteServiceReference[] getRemoteServiceReferences(ID[] idFilter, String clazz, String filter) throws InvalidSyntaxException {
try {
return getRemoteServiceReferences(null, idFilter, clazz, filter);
} catch (ContainerConnectException e) {
// can't occur, because first parameter is null
return null;
}
}
/**
* @since 3.0
*/
public IRemoteServiceReference[] getRemoteServiceReferences(ID targetID, String clazz, String filter) throws InvalidSyntaxException, ContainerConnectException {
return getRemoteServiceReferences(targetID, null, clazz, filter);
}
/**
* @since 3.0
*/
public IRemoteServiceReference[] getAllRemoteServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
final IRemoteServiceReference[] result = getRemoteServiceReferences((ID[]) null, clazz, filter);
if (result == null)
return null;
return (result.length == 0) ? null : result;
}
/* Begin implementation of IRemoteServiceContainerAdapter public interface */
/* (non-Javadoc)
* @see org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter#addRemoteServiceListener(org.eclipse.ecf.remoteservice.IRemoteServiceListener)
*/
@SuppressWarnings("unchecked")
public void addRemoteServiceListener(IRemoteServiceListener listener) {
synchronized (serviceListeners) {
serviceListeners.add(listener);
}
}
/* (non-Javadoc)
* @see org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter#removeRemoteServiceListener(org.eclipse.ecf.remoteservice.IRemoteServiceListener)
*/
public void removeRemoteServiceListener(IRemoteServiceListener listener) {
synchronized (serviceListeners) {
serviceListeners.remove(listener);
}
}
/**
* @param registration registration
* @return RemoteServiceImpl remote service implementation
* @since 4.1
*/
protected RemoteServiceImpl createRemoteService(RemoteServiceRegistrationImpl registration) {
return new RemoteServiceImpl(this, registration);
}
/* (non-Javadoc)
* @see org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter#getRemoteService(org.eclipse.ecf.remoteservice.IRemoteServiceReference)
*/
@SuppressWarnings("unchecked")
public IRemoteService getRemoteService(IRemoteServiceReference reference) {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "getRemoteService", reference); //$NON-NLS-1$
final RemoteServiceRegistrationImpl registration = getRemoteServiceRegistrationImpl(reference);
if (registration == null)
return null;
final RemoteServiceImpl remoteService = createRemoteService(registration);
synchronized (refToImplMap) {
List remoteServiceImplList = (List) refToImplMap.get(reference);
if (remoteServiceImplList == null)
remoteServiceImplList = new ArrayList();
remoteServiceImplList.add(remoteService);
refToImplMap.put(reference, remoteServiceImplList);
}
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), "getRemoteService", remoteService); //$NON-NLS-1$
return remoteService;
}
/* (non-Javadoc)
* @see org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter#registerRemoteService(java.lang.String[], java.lang.Object, java.util.Dictionary)
*/
public IRemoteServiceRegistration registerRemoteService(String[] clazzes, Object service, Dictionary properties) {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "registerRemoteService", new Object[] {clazzes, service, properties}); //$NON-NLS-1$
if (service == null) {
throw new NullPointerException("service cannot be null"); //$NON-NLS-1$
}
final int size = clazzes.length;
if (size == 0) {
throw new IllegalArgumentException("service classes list is empty"); //$NON-NLS-1$
}
final String[] copy = new String[clazzes.length];
for (int i = 0; i < clazzes.length; i++) {
copy[i] = new String(clazzes[i].getBytes());
}
clazzes = copy;
final String invalidService = checkServiceClass(clazzes, service);
if (invalidService != null) {
throw new IllegalArgumentException("Service=" + invalidService + " is invalid"); //$NON-NLS-1$ //$NON-NLS-2$
}
// Add to local registry
final RemoteServiceRegistrationImpl reg = new RemoteServiceRegistrationImpl();
synchronized (localRegistry) {
reg.publish(this, localRegistry, service, clazzes, properties);
// Only send add registrations if we are connected
if (isConnected()) {
final ID[] targets = getTargetsFromProperties(properties);
RemoteServiceRegistrationImpl[] regs = new RemoteServiceRegistrationImpl[] {reg};
if (targets == null)
sendAddRegistrations(null, null, regs);
else
for (int i = 0; i < targets.length; i++)
sendAddRegistrations(targets[i], null, regs);
}
}
fireRemoteServiceListeners(createRegisteredEvent(reg));
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), "registerRemoteService", reg); //$NON-NLS-1$
return reg;
}
// <IRemoteServiceReference,List<RemoteServiceImpl>>
private Map refToImplMap = new HashMap();
/* (non-Javadoc)
* @see org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter#ungetRemoteService(org.eclipse.ecf.remoteservice.IRemoteServiceReference)
*/
public boolean ungetRemoteService(IRemoteServiceReference ref) {
if (ref == null)
return false;
IRemoteServiceID serviceID = ref.getID();
if (serviceID == null)
return false;
synchronized (refToImplMap) {
List remoteServiceImplList = (List) refToImplMap.remove(ref);
if (remoteServiceImplList != null) {
for (Iterator i = remoteServiceImplList.iterator(); i.hasNext();) {
RemoteServiceImpl rsImpl = (RemoteServiceImpl) i.next();
if (rsImpl != null)
rsImpl.dispose();
i.remove();
}
return true;
}
}
return false;
}
/**
* @since 3.0
*/
@SuppressWarnings("unchecked")
public IFuture asyncGetRemoteServiceReferences(final ID[] idFilter, final String clazz, final String filter) {
IExecutor executor = new JobsExecutor("asyncGetRemoteServiceReferences"); //$NON-NLS-1$
return executor.execute(new IProgressRunnable() {
public Object run(IProgressMonitor monitor) throws Exception {
return getRemoteServiceReferences(idFilter, clazz, filter);
}
}, null);
}
/**
* @since 3.4
*/
@SuppressWarnings("unchecked")
public IFuture asyncGetRemoteServiceReferences(final ID target, final ID[] idFilter, final String clazz, final String filter) {
IExecutor executor = new JobsExecutor("asyncGetRemoteServiceReferences"); //$NON-NLS-1$
return executor.execute(new IProgressRunnable() {
public Object run(IProgressMonitor monitor) throws Exception {
return getRemoteServiceReferences(target, idFilter, clazz, filter);
}
}, null);
}
/**
* @since 3.0
*/
@SuppressWarnings("unchecked")
public IFuture asyncGetRemoteServiceReferences(final ID target, final String clazz, final String filter) {
IExecutor executor = new JobsExecutor("asyncGetRemoteServiceReferences"); //$NON-NLS-1$
return executor.execute(new IProgressRunnable() {
public Object run(IProgressMonitor monitor) throws Exception {
return getRemoteServiceReferences(target, clazz, filter);
}
}, null);
}
/**
* @since 3.0
*/
public Namespace getRemoteServiceNamespace() {
return IDFactory.getDefault().getNamespaceByName(RemoteServiceNamespace.NAME);
}
/**
* @since 3.0
*/
public IRemoteFilter createRemoteFilter(String filter) throws InvalidSyntaxException {
return new RemoteFilterImpl(filter);
}
/**
* @since 3.0
*/
@SuppressWarnings("unchecked")
public IRemoteServiceReference getRemoteServiceReference(IRemoteServiceID serviceId) {
ID containerID = serviceId.getContainerID();
if (containerID == null)
return null;
RemoteServiceRegistrationImpl registration = null;
waitForPendingUpdates(new ID[] {containerID});
ID localContainerID = getLocalContainerID();
if (containerID.equals(localContainerID)) {
synchronized (localRegistry) {
registration = localRegistry.findRegistrationForServiceId(serviceId.getContainerRelativeID());
if (registration != null)
return registration.getReference();
}
} else {
synchronized (remoteRegistrys) {
final ArrayList registrys = new ArrayList(remoteRegistrys.values());
for (final Iterator i = registrys.iterator(); i.hasNext();) {
final RemoteServiceRegistryImpl registry = (RemoteServiceRegistryImpl) i.next();
registration = registry.findRegistrationForServiceId(serviceId.getContainerRelativeID());
}
}
}
return (registration == null) ? null : registration.getReference();
}
/**
* @since 3.0
*/
public IRemoteServiceID getRemoteServiceID(ID containerId, long containerRelativeId) {
if (containerId == null)
return null;
ID localContainerID = getLocalContainerID();
if (containerId.equals(localContainerID)) {
synchronized (localRegistry) {
RemoteServiceRegistrationImpl reg = localRegistry.findRegistrationForServiceId(containerRelativeId);
if (reg != null)
return reg.getID();
}
} else {
synchronized (remoteRegistrys) {
@SuppressWarnings("unchecked")
final ArrayList registrys = new ArrayList(remoteRegistrys.values());
for (final Iterator i = registrys.iterator(); i.hasNext();) {
final RemoteServiceRegistryImpl registry = (RemoteServiceRegistryImpl) i.next();
RemoteServiceRegistrationImpl reg = registry.findRegistrationForServiceId(containerRelativeId);
if (reg != null)
return reg.getID();
}
}
}
return null;
}
/**
* @since 3.0
*/
public void setConnectContextForAuthentication(IConnectContext connectContext) {
this.connectContext = connectContext;
}
// End IRemoteServiceContainerAdapter methods
// ISharedObject overrides
/* (non-Javadoc)
* @see org.eclipse.ecf.core.sharedobject.BaseSharedObject#initialize()
*/
public void initialize() throws SharedObjectInitException {
super.initialize();
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "initialize"); //$NON-NLS-1$
ID localContainerID = getLocalContainerID();
localRegistry = (localContainerID == null) ? new RemoteServiceRegistryImpl() : new RemoteServiceRegistryImpl(localContainerID);
super.addEventProcessor(new IEventProcessor() {
public boolean processEvent(Event arg0) {
if (arg0 instanceof IContainerConnectedEvent) {
handleContainerConnectedEvent((IContainerConnectedEvent) arg0);
} else if (arg0 instanceof IContainerDisconnectedEvent) {
handleContainerDisconnectedEvent((IContainerDisconnectedEvent) arg0);
} else if (arg0 instanceof IContainerEjectedEvent) {
handleContainerEjectedEvent((IContainerEjectedEvent) arg0);
} else if (arg0 instanceof ISharedObjectActivatedEvent) {
// If it's us that's being activated, then we do something about it
if (getID().equals(((ISharedObjectActivatedEvent) arg0).getActivatedID()))
handleRegistryActivatedEvent();
}
return false;
}
});
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), "initialize"); //$NON-NLS-1$
}
/* (non-Javadoc)
* @see org.eclipse.ecf.core.sharedobject.BaseSharedObject#dispose(org.eclipse.ecf.core.identity.ID)
*/
public void dispose(ID containerID) {
synchronized (rsQueueLock) {
if (rsListenerDispatchEventManager != null) {
rsListenerDispatchEventManager.close();
rsListenerDispatchEventManager = null;
rsListenerDispatchQueue = null;
}
}
synchronized (refToImplMap) {
refToImplMap.clear();
}
synchronized (remoteRegistrys) {
remoteRegistrys.clear();
}
synchronized (serviceListeners) {
serviceListeners.clear();
}
synchronized (addRegistrationRequests) {
addRegistrationRequests.clear();
}
synchronized (requests) {
requests.clear();
}
synchronized (pendingUpdateContainers) {
pendingUpdateContainers.clear();
}
synchronized (registryUpdateRequests) {
registryUpdateRequests.clear();
}
synchronized (localRegistry) {
localRegistry.unpublishServices();
}
synchronized (localRegistryUnregistrationTargets) {
localRegistryUnregistrationTargets.clear();
}
super.dispose(containerID);
}
// End ISharedObject overrides
/**
* @return int connect timeout
* @since 3.3
*/
protected int getRSConnectTimeout() {
return rsConnectTimeout;
}
/**
* @return long registry update request timeout
* @since 3.4
*/
protected long getRegistryUpdateRequestTimeout() {
return registryUpdateRequestTimeout;
}
@SuppressWarnings("unchecked")
private void sendRegistryUpdateRequestAndWait(ID targetContainerID) {
synchronized (registryUpdateRequests) {
// create request id
Integer requestId = createNextRequestId();
// add it to the registryUpdateRequests list
registryUpdateRequests.add(requestId);
// send registry update request message to targetContainerID
sendRegistryUpdateRequest(targetContainerID, requestId);
// Get timeout
long timeOut = System.currentTimeMillis() + getRegistryUpdateRequestTimeout();
while ((timeOut - System.currentTimeMillis()) >= 0) {
if (!registryUpdateRequests.contains(requestId)) {
Trace.trace(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.DEBUG, this.getClass(), "sendRegistryUpdateRequestAndWait", "localContainerID=" + getLocalContainerID() + " returning because response received"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
return;
}
try {
registryUpdateRequests.wait(100);
} catch (InterruptedException e) {
return;
}
}
Trace.trace(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.DEBUG, this.getClass(), "sendRegistryUpdateRequestAndWait", "localContainerID=" + getLocalContainerID() + " returning because of timeout"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
private void addReferencesFromRemoteRegistrys(ID[] idFilter, String clazz, IRemoteFilter remoteFilter, List referencesFound) {
// If no idFilter, then we add all known references from all remote registrys
if (idFilter == null) {
synchronized (remoteRegistrys) {
@SuppressWarnings("unchecked")
final ArrayList registrys = new ArrayList(remoteRegistrys.values());
for (final Iterator i = registrys.iterator(); i.hasNext();) {
final RemoteServiceRegistryImpl registry = (RemoteServiceRegistryImpl) i.next();
// Add IRemoteServiceReferences from each remote registry
addReferencesFromRegistry(clazz, remoteFilter, registry, referencesFound);
}
}
// Otherwise there is a filter
} else {
for (int i = 0; i < idFilter.length; i++) {
ID targetContainerID = idFilter[i];
// Skip if the targetContainerID is null
if (targetContainerID == null)
continue;
sendRegistryUpdateRequestAndWait(targetContainerID);
synchronized (remoteRegistrys) {
RemoteServiceRegistryImpl remoteRegistryForContainer = (RemoteServiceRegistryImpl) remoteRegistrys.get(targetContainerID);
if (remoteRegistryForContainer != null)
addReferencesFromRegistry(clazz, remoteFilter, remoteRegistryForContainer, referencesFound);
}
}
}
}
private void addReferencesFromLocalRegistry(ID[] idFilter, String clazz, IRemoteFilter remoteFilter, List referencesFound) {
ID localContainerID = getLocalContainerID();
if (idFilter == null || Arrays.asList(idFilter).contains(localContainerID)) {
synchronized (localRegistry) {
// Add any from local registry
addReferencesFromRegistry(clazz, remoteFilter, localRegistry, referencesFound);
}
}
}
/**
* @return int add registration request timeout
* @since 3.0
*/
protected int getAddRegistrationRequestTimeout() {
return addRegistrationRequestTimeout;
}
/**
* @param targetID target ID to connect to
* @throws ContainerConnectException if container cannot connect to target ID
* @since 3.3 for preventing issues like bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=304427
*/
protected void connectToRemoteServiceTarget(ID targetID) throws ContainerConnectException {
ISharedObjectContext context = getContext();
ID connectedID = context.getConnectedID();
// If we're already connected to something then we don't need to connect...and we return
if (connectedID != null)
return;
synchronized (rsConnectLock) {
// we just try to connect to target with our given connectContext
context.connect(targetID, connectContext);
// wait to receive connected event
// Wait until we receive the IContainerConnectedEvent on the shared object thread
int rsTimeout = getRSConnectTimeout();
long endTime = System.currentTimeMillis() + rsTimeout;
while (!rsConnected && (endTime >= System.currentTimeMillis())) {
try {
// wait for asynchronous notification of getting connected
rsConnectLock.wait(rsTimeout / 10);
} catch (InterruptedException e) {
throw new ContainerConnectException("No notification of registry connect complete for connect targetID=" + targetID); //$NON-NLS-1$
}
}
if (!rsConnected)
throw new ContainerConnectException("Could not complete registry connect for targetID=" + targetID); //$NON-NLS-1$
}
}
protected Serializable getAddRegistrationRequestCredentials(AddRegistrationRequest request) {
return null;
}
@SuppressWarnings("unchecked")
protected ID[] getTargetsFromProperties(Dictionary properties) {
if (properties == null)
return null;
List results = new ArrayList();
Object o = properties.get(Constants.SERVICE_REGISTRATION_TARGETS);
if (o != null) {
if (o instanceof ID)
results.add(o);
if (o instanceof ID[]) {
ID[] targets = (ID[]) o;
for (int i = 0; i < targets.length; i++)
results.add(targets[i]);
}
}
if (results.size() == 0)
return null;
return (ID[]) results.toArray(new ID[] {});
}
protected ISharedObjectContext getSOContext() {
return super.getContext();
}
/**
* @since 3.4
*/
protected void handleRegistryActivatedEvent() {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "handleRegistryActivatedEvent"); //$NON-NLS-1$
// Only do something with this if we're already connected
ID[] members = getGroupMemberIDs();
ID localContainerID = getLocalContainerID();
ID connectedID = getConnectedID();
Trace.trace(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.DEBUG, this.getClass(), "handleRegistryActivatedEvent", "localContainerID=" + getLocalContainerID() + ",members=" + Arrays.asList(members)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
// Only do this if we've already been connected
if (isConnected()) {
for (int i = 0; i < members.length; i++) {
// Don't do this for us
if (!members[i].equals(localContainerID)) {
// Add the target to the set of pending update containers. These are the ones we expect
// to hear from about their registry contents
addPendingContainers(new ID[] {members[i]});
// And send a registry update to the given target
sendRegistryUpdate(members[i]);
// If we are now connected, then set our registry connected
if (connectedID.equals(members[i]))
setRegistryConnected(true);
}
}
}
}
/**
* @param event event to handle
* @since 3.3
*/
protected void handleContainerEjectedEvent(IContainerEjectedEvent event) {
handleTargetGoneEvent(event.getTargetID());
}
/**
* @since 3.4
*/
@SuppressWarnings("unchecked")
protected void clearRemoteRegistrys() {
List registrations = new ArrayList();
synchronized (remoteRegistrys) {
for (Iterator i = remoteRegistrys.keySet().iterator(); i.hasNext();) {
ID containerID = (ID) i.next();
RemoteServiceRegistryImpl registry = (RemoteServiceRegistryImpl) remoteRegistrys.get(containerID);
if (registry != null) {
removeRemoteRegistry(containerID);
RemoteServiceRegistrationImpl[] regs = registry.getRegistrations();
if (regs != null) {
for (int j = 0; j < regs.length; j++) {
registry.unpublishService(regs[j]);
registrations.add(regs[j]);
}
}
}
}
}
for (Iterator i = registrations.iterator(); i.hasNext();) {
fireRemoteServiceListeners(createUnregisteredEvent((RemoteServiceRegistrationImpl) i.next()));
}
}
private void removeUnregistrationTarget(ID targetID) {
// reg -> List<ID>
synchronized (localRegistryUnregistrationTargets) {
for (Iterator i = this.localRegistryUnregistrationTargets.keySet().iterator(); i.hasNext();) {
RemoteServiceRegistrationImpl reg = (RemoteServiceRegistrationImpl) i.next();
List targets = (List) this.localRegistryUnregistrationTargets.get(reg);
for (Iterator t = targets.iterator(); t.hasNext();) {
ID unregTarget = (ID) t.next();
if (targetID.equals(unregTarget))
t.remove();
}
if (targets.isEmpty())
i.remove();
}
}
}
private void handleTargetGoneEvent(ID targetID) {
RemoteServiceRegistrationImpl registrations[] = null;
synchronized (remoteRegistrys) {
final RemoteServiceRegistryImpl registry = getRemoteRegistry(targetID);
if (registry != null) {
removeRemoteRegistry(targetID);
registrations = registry.getRegistrations();
if (registrations != null) {
for (int i = 0; i < registrations.length; i++) {
registry.unpublishService(registrations[i]);
}
}
}
}
// remove from localRegistryUnregistrationTargets
removeUnregistrationTarget(targetID);
// Remove from pending updates
removePendingContainers(targetID);
if (!isConnected())
setRegistryConnected(false);
ID localContainerID = getLocalContainerID();
if (localContainerID == null) {
synchronized (localRegistry) {
localRegistry.setContainerID(null);
}
}
// Do notification outside synchronized block
if (registrations != null) {
for (int i = 0; i < registrations.length; i++) {
fireRemoteServiceListeners(createUnregisteredEvent(registrations[i]));
}
}
}
/**
* @param connected true if registry is connected, false otherwise
* @since 3.3
*/
protected void setRegistryConnected(boolean connected) {
synchronized (rsConnectLock) {
rsConnected = connected;
rsConnectLock.notify();
}
}
protected void handleContainerDisconnectedEvent(IContainerDisconnectedEvent event) {
handleTargetGoneEvent(event.getTargetID());
}
protected void sendRegistryUpdate(ID targetContainerID) {
sendRegistryUpdate(targetContainerID, null);
}
/**
* @param targetContainerID target container ID
* @param requestId requestId
* @since 3.4
*/
protected void sendRegistryUpdate(ID targetContainerID, Integer requestId) {
synchronized (localRegistry) {
final RemoteServiceRegistrationImpl registrations[] = localRegistry.getRegistrations();
sendAddRegistrations(targetContainerID, requestId, registrations);
}
}
@SuppressWarnings("unchecked")
private void addPendingContainers(ID[] ids) {
if (ids == null)
return;
ID localContainerID = getLocalContainerID();
synchronized (pendingUpdateContainers) {
for (int i = 0; i < ids.length; i++) {
if (!ids[i].equals(localContainerID)) {
pendingUpdateContainers.put(ids[i], ids[i]);
}
}
}
}
private boolean removePendingContainers(ID id) {
if (id == null)
return false;
ID localContainerID = getLocalContainerID();
synchronized (pendingUpdateContainers) {
Object result = pendingUpdateContainers.remove(id);
Trace.trace(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.DEBUG, this.getClass(), "removePendingContainers", "localContainerID=" + localContainerID + ",REMOVED=" + result + ",pendingUpdateContainers=" + pendingUpdateContainers); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
pendingUpdateContainers.notify();
return result != null;
}
}
private boolean anyPending(ID[] idFilter) {
if (idFilter == null)
return pendingUpdateContainers.size() > 0;
for (int i = 0; i < idFilter.length; i++) {
if (pendingUpdateContainers.containsKey(idFilter[i]))
return true;
}
return false;
}
private void waitForPendingUpdates(ID[] idFilter) {
long timeout = getAddRegistrationRequestTimeout();
long endTime = System.currentTimeMillis() + timeout;
synchronized (pendingUpdateContainers) {
// If there are any requred
while (anyPending(idFilter) && (endTime >= System.currentTimeMillis())) {
try {
pendingUpdateContainers.wait(timeout / 10);
} catch (InterruptedException e) {
// just return
return;
}
}
}
}
protected void handleContainerConnectedEvent(IContainerConnectedEvent event) {
handleTargetConnected(event.getTargetID());
}
/**
* @param targetID targetID
* @since 3.4
*/
protected void handleTargetConnected(ID targetID) {
Trace.trace(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.DEBUG, this.getClass(), "handleTargetConnected", "localContainerID=" + getLocalContainerID() + ",targetID=" + targetID); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
// Add the target to the set of pending update containers. These are the ones we expect
// to hear from about their registry contents
addPendingContainers(new ID[] {targetID});
// And send a registry update to the given target
sendRegistryUpdate(targetID);
// If we are now connected, then set our registry connected
if (getConnectedID().equals(targetID))
setRegistryConnected(true);
}
// generic
private Request createRequest(RemoteServiceRegistrationImpl remoteRegistration, IRemoteCall call, IRemoteCallListener listener) {
return new Request(this.getLocalContainerID(), remoteRegistration.getServiceId(), RemoteCallImpl.createRemoteCall(null, call.getMethod(), call.getParameters(), call.getTimeout()), listener);
}
@SuppressWarnings("unchecked")
void doFireRemoteServiceListeners(IRemoteServiceEvent event) {
List entries;
synchronized (serviceListeners) {
entries = new ArrayList(serviceListeners);
}
for (final Iterator i = entries.iterator(); i.hasNext();) {
final IRemoteServiceListener l = (IRemoteServiceListener) i.next();
l.handleServiceEvent(event);
}
}
@SuppressWarnings("unchecked")
protected void fireRemoteServiceListeners(IRemoteServiceEvent event) {
synchronized (rsQueueLock) {
if (rsListenerDispatchQueue == null) {
ID containerID = getLocalContainerID();
String threadGroupName = "RSRegistry Dispatcher for containerID=" + containerID; //$NON-NLS-1$
ThreadGroup eventGroup = new ThreadGroup(threadGroupName);
eventGroup.setDaemon(true);
rsListenerDispatchEventManager = new EventManager(threadGroupName, eventGroup);
rsListenerDispatchQueue = new ListenerQueue(rsListenerDispatchEventManager);
CopyOnWriteIdentityMap listeners = new CopyOnWriteIdentityMap();
listeners.put(this, this);
rsListenerDispatchQueue.queueListeners(listeners.entrySet(), new EventDispatcher() {
public void dispatchEvent(Object eventListener, Object listenerObject, int eventAction, Object eventObject) {
doFireRemoteServiceListeners((IRemoteServiceEvent) eventObject);
}
});
}
}
rsListenerDispatchQueue.dispatchEventAsynchronous(0, event);
}
private RemoteServiceRegistrationImpl getRemoteServiceRegistrationImpl(IRemoteServiceReference reference) {
if (reference instanceof RemoteServiceReferenceImpl) {
final RemoteServiceReferenceImpl ref = (RemoteServiceReferenceImpl) reference;
if (!ref.isActive()) {
return null;
}
return ref.getRegistration();
}
return null;
}
@SuppressWarnings("unchecked")
private void addReferencesFromRegistry(String clazz, IRemoteFilter remoteFilter, RemoteServiceRegistryImpl registry, List references) {
final IRemoteServiceReference[] rs = registry.lookupServiceReferences(clazz, remoteFilter);
if (rs != null) {
for (int j = 0; j < rs.length; j++) {
references.add(rs[j]);
}
}
}
protected Object callSynch(RemoteServiceRegistrationImpl registration, IRemoteCall call) throws ECFException {
boolean doneWaiting = false;
Response response = null;
try {
// First send request
final Request request = sendCallRequest(registration, call);
long requestId = request.getRequestId();
// Then get the specified timeout and calculate when we should
// timeout in real time
final long timeout = call.getTimeout() + System.currentTimeMillis();
// Now loop until timeout time has elapsed
while ((timeout - System.currentTimeMillis()) > 0 && !doneWaiting) {
synchronized (request) {
if (request.isDone()) {
doneWaiting = true;
response = request.getResponse();
if (response == null)
throw new ECFException("Invalid response for requestId=" + requestId); //$NON-NLS-1$
} else {
request.wait(RESPONSE_WAIT_INTERVAL);
}
}
}
if (!doneWaiting)
throw new ECFException("Request timed out after " + Long.toString(call.getTimeout()) + "ms", new TimeoutException(call.getTimeout())); //$NON-NLS-1$ //$NON-NLS-2$
} catch (final IOException e) {
log(CALL_REQUEST_ERROR_CODE, CALL_REQUEST_ERROR_MESSAGE, e);
throw new ECFException("Error sending request", e); //$NON-NLS-1$
} catch (final InterruptedException e) {
log(CALL_REQUEST_TIMEOUT_ERROR_CODE, CALL_REQUEST_TIMEOUT_ERROR_MESSAGE, e);
throw new ECFException("Wait for response interrupted", e); //$NON-NLS-1$
}
// Success...now get values and return
if (response.hadException())
throw new ECFException("Exception in remote call", response.getException()); //$NON-NLS-1$
return response.getResponse();
}
protected void fireCallStartEvent(IRemoteCallListener listener, final long requestId, final IRemoteServiceReference reference, final IRemoteCall call) {
if (listener != null) {
listener.handleEvent(new IRemoteCallStartEvent() {
public long getRequestId() {
return requestId;
}
public IRemoteCall getCall() {
return call;
}
public IRemoteServiceReference getReference() {
return reference;
}
public String toString() {
final StringBuffer buf = new StringBuffer("IRemoteCallStartEvent["); //$NON-NLS-1$
buf.append(";reference=").append(reference).append(";call=").append(call).append("]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
return buf.toString();
}
});
}
}
protected void fireCallCompleteEvent(IRemoteCallListener listener, final long requestId, final Object response, final boolean hadException, final Throwable exception) {
if (listener != null) {
listener.handleEvent(new IRemoteCallCompleteEvent() {
public long getRequestId() {
return requestId;
}
public Throwable getException() {
return exception;
}
public Object getResponse() {
return response;
}
public boolean hadException() {
return hadException;
}
public String toString() {
final StringBuffer buf = new StringBuffer("IRemoteCallCompleteEvent["); //$NON-NLS-1$
buf.append(";response=").append(response).append(";hadException=").append(hadException).append(";exception=").append(exception).append("]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
return buf.toString();
}
});
}
}
static String checkServiceClass(final String[] clazzes, final Object serviceObject) {
@SuppressWarnings("unchecked")
final ClassLoader cl = (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return serviceObject.getClass().getClassLoader();
}
});
for (int i = 0; i < clazzes.length; i++) {
try {
final Class serviceClazz = cl == null ? Class.forName(clazzes[i]) : cl.loadClass(clazzes[i]);
if (!serviceClazz.isInstance(serviceObject)) {
return clazzes[i];
}
} catch (final ClassNotFoundException e) {
// This check is rarely done
if (extensiveCheckServiceClass(clazzes[i], serviceObject.getClass())) {
return clazzes[i];
}
}
}
return null;
}
private static boolean extensiveCheckServiceClass(String clazz, Class serviceClazz) {
if (clazz.equals(serviceClazz.getName())) {
return false;
}
final Class[] interfaces = serviceClazz.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
if (!extensiveCheckServiceClass(clazz, interfaces[i])) {
return false;
}
}
final Class superClazz = serviceClazz.getSuperclass();
if (superClazz != null) {
if (!extensiveCheckServiceClass(clazz, superClazz)) {
return false;
}
}
return true;
}
/**
* Message send and handlers
*/
private static final String FIRE_REQUEST = "handleFireRequest"; //$NON-NLS-1$
private static final String FIRE_REQUEST_ERROR_MESSAGE = "exception sending fire request message"; //$NON-NLS-1$
private static final int FIRE_REQUEST_ERROR_CODE = 202;
private static final String CALL_REQUEST = "handleCallRequest"; //$NON-NLS-1$
private static final String CALL_REQUEST_ERROR_MESSAGE = "exception sending call request message"; //$NON-NLS-1$
private static final int CALL_REQUEST_ERROR_CODE = 203;
private static final String CALL_REQUEST_TIMEOUT_ERROR_MESSAGE = "timeout for remote call"; //$NON-NLS-1$
private static final int CALL_REQUEST_TIMEOUT_ERROR_CODE = 204;
private static final String UNREGISTER = "handleUnregister"; //$NON-NLS-1$
private static final String UNREGISTER_ERROR_MESSAGE = "exception sending service unregister message"; //$NON-NLS-1$
private static final int UNREGISTER_ERROR_CODE = 206;
private static final int MSG_INVOKE_ERROR_CODE = 207;
private static final String CALL_RESPONSE = "handleCallResponse"; //$NON-NLS-1$
private static final String CALL_RESPONSE_ERROR_MESSAGE = "Exception sending response"; //$NON-NLS-1$
private static final int CALL_RESPONSE_ERROR_CODE = 210;
private static final String REQUEST_NOT_FOUND_ERROR_MESSAGE = "request not found for response"; //$NON-NLS-1$
private static final int REQUEST_NOT_FOUND_ERROR_CODE = 211;
private static final long RESPONSE_WAIT_INTERVAL = 500;
private static final String ADD_REGISTRATION = "handleAddRegistration"; //$NON-NLS-1$
private static final String ADD_REGISTRATIONS = "handleAddRegistrations"; //$NON-NLS-1$
private static final String ADD_REGISTRATION_ERROR_MESSAGE = "exception sending add service registration message"; //$NON-NLS-1$
private static final int ADD_REGISTRATION_ERROR_CODE = 212;
private static final String ADD_REGISTRATION_REFUSED = "handleAddRegistrationRefused"; //$NON-NLS-1$
private static final String ADD_REGISTRATION_REFUSED_ERROR_MESSAGE = "Error sending addRegistration refused"; //$NON-NLS-1$
private static final int ADD_REGISTRATION_REFUSED_ERROR_CODE = 214;
private static final String REQUEST_SERVICE = "handleRequestService"; //$NON-NLS-1$
private static final int REQUEST_SERVICE_ERROR_CODE = 213;
private static final String REQUEST_SERVICE_ERROR_MESSAGE = "Error sending requestServiceReference"; //$NON-NLS-1$
private static final String REGISTRY_UPDATE_REQUEST = "handleRegistryUpdateRequest"; //$NON-NLS-1$
/**
* @param receiver receiver
* @param requestId requestId
* @since 3.4
*/
protected void sendRegistryUpdateRequest(ID receiver, Integer requestId) {
ID localContainerID = getLocalContainerID();
Trace.trace(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.DEBUG, this.getClass(), "sendRegistryUpdateRequest", "localContainerID=" + localContainerID + ",targetContainerID=" + receiver + ",requestId=" + requestId); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
try {
sendSharedObjectMsgTo(receiver, SharedObjectMsg.createMsg(null, REGISTRY_UPDATE_REQUEST, new Object[] {localContainerID, requestId}));
} catch (IOException e) {
log(ADD_REGISTRATION_ERROR_CODE, "Exception sending registry update request/2 message", e); //$NON-NLS-1$
}
}
/**
* @param remoteContainerID remoteContainerID
* @param requestId requestId
* @since 3.4
*/
protected void handleRegistryUpdateRequest(ID remoteContainerID, Integer requestId) {
Trace.trace(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.DEBUG, this.getClass(), "handleRegistryUpdateRequest", "localContainerID=" + getLocalContainerID() + ",remoteContainerID=" + remoteContainerID + ",requestId=" + requestId); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
sendRegistryUpdate(remoteContainerID, requestId);
}
protected void sendRegistryUpdateRequest() {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "sendRegistryUpdateRequest"); //$NON-NLS-1$
try {
sendSharedObjectMsgTo(null, SharedObjectMsg.createMsg(REGISTRY_UPDATE_REQUEST, getLocalContainerID()));
} catch (final IOException e) {
log(CALL_RESPONSE_ERROR_CODE, CALL_RESPONSE_ERROR_MESSAGE, e);
}
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), "sendRegistryUpdateRequest"); //$NON-NLS-1$
}
protected void handleRegistryUpdateRequest(ID remoteContainerID) {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), REGISTRY_UPDATE_REQUEST);
if (remoteContainerID == null)
return;
sendRegistryUpdate(remoteContainerID);
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), REGISTRY_UPDATE_REQUEST);
}
private boolean removeRegistryUpdateRequest(Integer requestId) {
if (requestId == null)
return false;
synchronized (registryUpdateRequests) {
boolean result = registryUpdateRequests.remove(requestId);
Trace.trace(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.DEBUG, this.getClass(), "removeRegistryUpdateRequest", "localContainerID=" + getLocalContainerID() + ", REMOVED requestId=" + requestId); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
registryUpdateRequests.notify();
return result;
}
}
protected AddRegistrationRequest sendAddRegistrationRequest(ID receiver, AddRegistrationRequest request, Serializable credentials) {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "sendAddRegistrationRequest", new Object[] {receiver, request, credentials}); //$NON-NLS-1$
Assert.isNotNull(receiver);
Assert.isNotNull(request);
try {
sendSharedObjectMsgTo(receiver, SharedObjectMsg.createMsg(null, REQUEST_SERVICE, new Object[] {getLocalContainerID(), request, request.getId(), credentials}));
} catch (final IOException e) {
log(REQUEST_SERVICE_ERROR_CODE, REQUEST_SERVICE_ERROR_MESSAGE, e);
}
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), "sendAddRegistrationRequest"); //$NON-NLS-1$
return request;
}
protected void checkRequestServiceAuthorization(ID remoteContainerID, AddRegistrationRequest request, Serializable credentials) throws AccessControlException {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "checkRequestServiceAuthorization", new Object[] {remoteContainerID, request, credentials}); //$NON-NLS-1$
return;
}
@SuppressWarnings("unchecked")
protected void handleRequestService(ID remoteContainerID, AddRegistrationRequest request, Integer requestId, Serializable credentials) {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "handleRequestServiceReference", new Object[] {remoteContainerID, request, requestId, credentials}); //$NON-NLS-1$
if (remoteContainerID == null || requestId == null)
return;
if (request == null)
return;
IRemoteFilter rf = null;
try {
rf = (request.getFilter() == null) ? null : new RemoteFilterImpl(request.getFilter());
} catch (InvalidSyntaxException e) {
// log and set rf to null and ignore
log("handleRequestService invalid syntax exception for filter", e); //$NON-NLS-1$
rf = null;
}
try {
checkRequestServiceAuthorization(remoteContainerID, request, credentials);
} catch (AccessControlException e) {
// Log and return...i.e. do nothing
log("handleRequestService. checkRequestServiceAuthorization exception", e); //$NON-NLS-1$
sendAddRegistrationRequestRefused(remoteContainerID, requestId, e);
return;
}
String service = request.getService();
synchronized (localRegistry) {
RemoteServiceRegistrationImpl[] regs = null;
if (service == null) {
regs = localRegistry.getRegistrations();
} else {
RemoteServiceReferenceImpl[] srs = (RemoteServiceReferenceImpl[]) localRegistry.lookupServiceReferences(request.getService(), rf);
List regsList = new ArrayList();
if (srs != null && srs.length > 0) {
for (int i = 0; i < srs.length; i++) {
RemoteServiceRegistrationImpl impl = getRemoteServiceRegistrationImpl(srs[i]);
if (impl != null)
regsList.add(impl);
}
}
if (regsList.size() > 0) {
regs = (RemoteServiceRegistrationImpl[]) regsList.toArray(new RemoteServiceRegistrationImpl[] {});
}
}
sendAddRegistrations(remoteContainerID, requestId, regs);
}
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), "handleRequestService"); //$NON-NLS-1$
}
protected void sendAddRegistration(ID receiver, RemoteServiceRegistrationImpl reg) {
sendAddRegistration(receiver, null, reg);
}
protected void sendAddRegistration(ID receiver, Integer requestId, RemoteServiceRegistrationImpl reg) {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "sendAddRegistration", new Object[] {receiver, requestId, reg}); //$NON-NLS-1$
try {
sendSharedObjectMsgTo(receiver, SharedObjectMsg.createMsg(null, ADD_REGISTRATION, getLocalContainerID(), requestId, reg));
} catch (final IOException e) {
log(ADD_REGISTRATION_ERROR_CODE, ADD_REGISTRATION_ERROR_MESSAGE, e);
}
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), "sendAddRegistration"); //$NON-NLS-1$
}
/**
* @param receiver receiver
* @param requestId requestId
* @param regs registrations to send
* @since 3.3
*/
protected void sendAddRegistrations(ID receiver, Integer requestId, RemoteServiceRegistrationImpl[] regs) {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "sendAddRegistrations", new Object[] {receiver, requestId, regs}); //$NON-NLS-1$
try {
sendSharedObjectMsgTo(receiver, SharedObjectMsg.createMsg(null, ADD_REGISTRATIONS, getLocalContainerID(), requestId, regs));
// if the receiver is in response to an explicit remote request (receiver != null && requestId != null)
// then for all registrations add a target for unregistration, so that upon unregistration we can
if (receiver != null && requestId != null) {
for (int i = 0; i < regs.length; i++)
addTargetForUnregister(regs[i], receiver);
}
} catch (final IOException e) {
log(ADD_REGISTRATION_ERROR_CODE, ADD_REGISTRATION_ERROR_MESSAGE, e);
}
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), "sendAddRegistrations"); //$NON-NLS-1$
}
protected void sendAddRegistrationRequestRefused(ID receiver, Integer requestId, Exception except) {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "sendAddRegistrationRequestRefused", new Object[] {receiver, except}); //$NON-NLS-1$
try {
sendSharedObjectMsgTo(receiver, SharedObjectMsg.createMsg(null, ADD_REGISTRATION_REFUSED, getLocalContainerID(), requestId, except));
} catch (final IOException e) {
log(ADD_REGISTRATION_REFUSED_ERROR_CODE, ADD_REGISTRATION_REFUSED_ERROR_MESSAGE, e);
}
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), "sendAddRegistrationRequestRefused"); //$NON-NLS-1$
}
protected void handleAddRegistrationRequestRefused(ID remoteContainerID, Integer requestId, AccessControlException e) {
if (remoteContainerID == null || requestId == null)
return;
// else lookup AddRegistrationRequest and notify
notifyAddRegistrationResponse(remoteContainerID, requestId, e);
}
protected void handleAddRegistration(ID remoteContainerID, final RemoteServiceRegistrationImpl registration) {
handleAddRegistration(remoteContainerID, null, registration);
}
/**
* @param remoteContainerID container id
* @param requestId requestId
* @param registrations the registrations to add
* @since 3.3
*/
@SuppressWarnings("unchecked")
protected void handleAddRegistrations(ID remoteContainerID, Integer requestId, final RemoteServiceRegistrationImpl[] registrations) {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), ADD_REGISTRATIONS, new Object[] {remoteContainerID, registrations});
ID localContainerID = getLocalContainerID();
if (remoteContainerID == null || localContainerID == null || localContainerID.equals(remoteContainerID)) {
return;
}
List addedRegistrations = new ArrayList();
if (registrations != null) {
synchronized (remoteRegistrys) {
// Find registry for remoteContainer
RemoteServiceRegistryImpl registry = getRemoteRegistry(remoteContainerID);
// If there's not one already then lazily make one and add it
if (registry == null) {
registry = new RemoteServiceRegistryImpl(remoteContainerID);
addRemoteRegistry(registry);
}
for (int i = 0; i < registrations.length; i++) {
RemoteServiceRegistrationImpl[] regs = registry.getRegistrations();
List regList = Arrays.asList(regs);
if (!regList.contains(registrations[i])) {
addedRegistrations.add(registrations[i]);
registry.publishService(registrations[i]);
}
}
}
}
// remove pending containers
removePendingContainers(remoteContainerID);
// remove from pending update requests
if (requestId != null)
removeRegistryUpdateRequest(requestId);
for (Iterator i = addedRegistrations.iterator(); i.hasNext();) {
fireRemoteServiceListeners(createRegisteredEvent((RemoteServiceRegistrationImpl) i.next()));
}
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), ADD_REGISTRATIONS);
}
protected void handleAddRegistration(ID remoteContainerID, Integer requestId, final RemoteServiceRegistrationImpl registration) {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), ADD_REGISTRATION, new Object[] {remoteContainerID, registration});
ID localContainerID = getLocalContainerID();
if (remoteContainerID == null || localContainerID == null || localContainerID.equals(remoteContainerID)) {
return;
}
boolean added = false;
synchronized (remoteRegistrys) {
// Find registry for remoteContainer
RemoteServiceRegistryImpl registry = getRemoteRegistry(remoteContainerID);
// If there's not one already then lazily make one and add it
if (registry == null) {
registry = new RemoteServiceRegistryImpl(remoteContainerID);
addRemoteRegistry(registry);
}
// publish service in this registry. At this point it's ready to go
RemoteServiceRegistrationImpl[] regs = registry.getRegistrations();
List regList = Arrays.asList(regs);
if (!regList.contains(registration)) {
added = true;
registry.publishService(registration);
}
notifyAddRegistrationResponse(remoteContainerID, requestId, null);
}
// notify IRemoteServiceListeners
if (added)
fireRemoteServiceListeners(createRegisteredEvent(registration));
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), ADD_REGISTRATION);
}
/**
* @param remoteContainerID remoteContainerID
* @param requestId requestId
* @param exception exception
* @since 3.2
*/
protected void notifyAddRegistrationResponse(ID remoteContainerID, Integer requestId, AccessControlException exception) {
if (remoteContainerID == null)
return;
if (requestId == null)
return;
AddRegistrationRequest request = removeAddRegistrationRequest(requestId);
if (request != null)
request.notifyResponse(exception);
}
private AddRegistrationRequest removeAddRegistrationRequest(Integer requestId) {
synchronized (addRegistrationRequests) {
return (AddRegistrationRequest) addRegistrationRequests.remove(requestId);
}
}
protected Request sendCallRequest(RemoteServiceRegistrationImpl remoteRegistration, final IRemoteCall call) throws IOException {
final Request request = createRequest(remoteRegistration, call, null);
addRequest(request);
try {
sendSharedObjectMsgTo(remoteRegistration.getContainerID(), SharedObjectMsg.createMsg(CALL_REQUEST, request));
} catch (final IOException e) {
removeRequest(request);
throw e;
}
return request;
}
private IExecutor getRequestExecutor(Request request) {
if (requestExecutor == null) {
requestExecutor = createRequestExecutor(request);
}
return requestExecutor;
}
/**
* @param request request
* @return IExcecutor excecutor to use for given request
* @since 3.4
*/
protected IExecutor createRequestExecutor(final Request request) {
IExecutor executor = null;
if (DEFAULT_EXECUTOR_TYPE.equals("jobs")) { //$NON-NLS-1$
executor = new JobsExecutor("Remote Request Handler") { //$NON-NLS-1$
protected String createJobName(String executorName, int jobCounter, IProgressRunnable runnable) {
return executorName + " - " + request.getCall().getMethod() + ":" + request.getRequestId(); //$NON-NLS-1$ //$NON-NLS-2$
}
};
} else if (DEFAULT_EXECUTOR_TYPE.equals("immediate")) { //$NON-NLS-1$
executor = new ImmediateExecutor();
} else if (DEFAULT_EXECUTOR_TYPE.equals("threads")) { //$NON-NLS-1$
executor = new ThreadsExecutor() {
protected String createThreadName(IProgressRunnable runnable) {
return "Remote Request Handler - " + request.getCall().getMethod() + ":" + request.getRequestId(); //$NON-NLS-1$ //$NON-NLS-2$
}
};
}
return executor;
}
/**
* @since 4.4
*/
protected Object invokeLocal(RemoteServiceRegistrationImpl reg, RemoteCallImpl call) throws InvocationTargetException, Exception, NoClassDefFoundError {
Object[] callArgs = call.getParameters();
Object[] args = (callArgs == null) ? SharedObjectMsg.nullArgs : callArgs;
Object service = reg.getService();
// Find appropriate method on service
final Method method = ClassUtil.getMethod(service.getClass(), call.getMethod(), SharedObjectMsg.getTypesForParameters(args));
// Actually invoke method on service object
Object result = method.invoke(service, args);
if (result != null) {
Class returnType = method.getReturnType();
// provider must expose osgi.async property and must be async return type
if (AsyncUtil.isOSGIAsync(reg.getReference()) && AsyncReturnUtil.isAsyncType(returnType))
return AsyncReturnUtil.convertAsyncToReturn(result, returnType, call.getTimeout());
}
return result;
}
/**
* @param executor executor to use to execute request
* @param request the request to execute
* @param responseTarget response target
* @param localRegistration the local registration
* @param respond true if response is expected, false otherwise
* @since 3.4
*/
@SuppressWarnings("unchecked")
protected void executeRequest(IExecutor executor, final Request request, final ID responseTarget, final RemoteServiceRegistrationImpl localRegistration, final boolean respond) {
IProgressRunnable runnable = new IProgressRunnable() {
public Object run(IProgressMonitor monitor) throws Exception {
final RemoteCallImpl call = request.getCall();
Response response = null;
Object result = null;
try {
// Get remote service call policy
IRemoteServiceCallPolicy callPolicy = getRemoteServiceCallPolicy();
// If it's set, then check remote call *before* actual invocation
if (callPolicy != null)
callPolicy.checkRemoteCall(responseTarget, localRegistration, call);
result = invokeLocal(localRegistration, call);
response = new Response(request.getRequestId(), result);
// Invocation target exception happens if the local method being invoked throws (cause)
} catch (InvocationTargetException e) {
response = new Response(request.getRequestId(), getSerializableException(e));
logRemoteCallException("Invocation target exception invoking remote service. Remote request=" + request, e); //$NON-NLS-1$
// This is to catch most other problems
} catch (Exception e) {
response = new Response(request.getRequestId(), getSerializableException(e));
logRemoteCallException("Unexpected exception invoking remote service. Remote request=" + request, e); //$NON-NLS-1$
} catch (NoClassDefFoundError e) {
response = new Response(request.getRequestId(), getSerializableException(e));
logRemoteCallException("No class def found error invoking remote service. Remote request=" + request, e); //$NON-NLS-1$
}
// Now send response back to responseTarget (original requestor)
if (respond)
sendCallResponse(responseTarget, response);
return null;
}
};
// Now actually execute the runnable asynchronously using the executor
executor.execute(runnable, new NullProgressMonitor());
}
private void sendErrorResponse(ID responseTarget, long requestId, String message, Throwable e) {
logRemoteCallException(message, e);
Response response = new Response(requestId, e);
sendCallResponse(responseTarget, response);
}
protected void handleCallRequest(Request request) {
// If request is null, it's bogus, give up/do not respond
if (request == null) {
log("handleCallRequest", new NullPointerException("Request cannot be null")); //$NON-NLS-1$//$NON-NLS-2$
return;
}
final ID responseTarget = request.getRequestContainerID();
// If response target is null then the request is bogus and we give up/do not respond
if (responseTarget == null) {
log("handleCallRequest", new NullPointerException("Response target cannot be null")); //$NON-NLS-1$ //$NON-NLS-2$
return;
}
final RemoteServiceRegistrationImpl localRegistration = getLocalRegistrationForRequest(request);
// If localRegistration not found for request, then it's a bogus request and we respond with NPE
if (localRegistration == null) {
sendErrorResponse(responseTarget, request.getRequestId(), "handleCallRequest", new NullPointerException("local service registration not found for remote request=" + request)); //$NON-NLS-1$ //$NON-NLS-2$
return;
}
IExecutor executor = getRequestExecutor(request);
if (executor == null) {
sendErrorResponse(responseTarget, request.getRequestId(), "handleCallRequest", new NullPointerException("request executor is not available and so no requests can be processed")); //$NON-NLS-1$ //$NON-NLS-2$
return;
}
// Else we've got a local service and we execute it using executor
executeRequest(executor, request, responseTarget, localRegistration, true);
}
/**
* @param message message
* @param e the exception
* @since 3.4
*/
protected void logRemoteCallException(String message, Throwable e) {
//Activator.getDefault().log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, SERVICE_INVOKE_ERROR_CODE, message, e));
}
private Throwable getSerializableException(Throwable e) {
// Just use the SerializableStatus
SerializableStatus ss = new SerializableStatus(0, Activator.PLUGIN_ID, null, e);
return ss.getException();
}
protected void sendCallRequestWithListener(RemoteServiceRegistrationImpl remoteRegistration, IRemoteCall call, IRemoteCallListener listener) {
final Request request = createRequest(remoteRegistration, call, listener);
fireCallStartEvent(listener, request.getRequestId(), remoteRegistration.getReference(), call);
try {
addRequest(request);
sendSharedObjectMsgTo(remoteRegistration.getContainerID(), SharedObjectMsg.createMsg(CALL_REQUEST, request));
} catch (final IOException e) {
log(CALL_REQUEST_ERROR_CODE, CALL_REQUEST_ERROR_MESSAGE, e);
removeRequest(request);
fireCallCompleteEvent(listener, request.getRequestId(), null, true, e);
}
}
protected void log(int code, String method, Throwable e) {
Activator.getDefault().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, code, method, e));
}
protected void sendCallResponse(ID responseTarget, Response response) {
try {
sendSharedObjectMsgTo(responseTarget, SharedObjectMsg.createMsg(CALL_RESPONSE, response));
} catch (final IOException e) {
log(CALL_RESPONSE_ERROR_CODE, CALL_RESPONSE_ERROR_MESSAGE, e);
// Also print to standard error, just in case
e.printStackTrace(System.err);
// added to address bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=470245
if (PROPAGATE_RESPONSE_ERROR)
try {
sendSharedObjectMsgTo(responseTarget, SharedObjectMsg.createMsg(CALL_RESPONSE, new Response(response.getRequestId(), getSerializableException(e))));
} catch (final IOException e1) {
log(CALL_RESPONSE_ERROR_CODE, "Exception propagating response error", e1); //$NON-NLS-1$
e1.printStackTrace(System.err);
}
}
}
protected void handleCallResponse(Response response) {
final Request request = getRequest(response.getRequestId());
if (request == null) {
log(REQUEST_NOT_FOUND_ERROR_CODE, REQUEST_NOT_FOUND_ERROR_MESSAGE, new NullPointerException());
return;
}
removeRequest(request);
final IRemoteCallListener listener = request.getListener();
if (listener != null) {
fireCallCompleteEvent(listener, request.getRequestId(), response.getResponse(), response.hadException(), response.getException());
return;
}
synchronized (request) {
request.setResponse(response);
request.setDone(true);
request.notify();
}
}
protected Request sendFireRequest(RemoteServiceRegistrationImpl remoteRegistration, IRemoteCall call) throws ECFException {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "sendFireRequest", new Object[] {remoteRegistration, call}); //$NON-NLS-1$
final Request request = createRequest(remoteRegistration, call, null);
try {
sendSharedObjectMsgTo(remoteRegistration.getContainerID(), SharedObjectMsg.createMsg(FIRE_REQUEST, request));
} catch (final IOException e) {
log(FIRE_REQUEST_ERROR_CODE, FIRE_REQUEST_ERROR_MESSAGE, e);
throw new ECFException("IOException sending fire request", e); //$NON-NLS-1$
}
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), "sendFireRequest", request); //$NON-NLS-1$
return request;
}
protected void handleFireRequest(Request request) {
// If request is null, it's bogus, give up/do not respond
if (request == null) {
log("handleFireRequest", new NullPointerException("Request cannot be null")); //$NON-NLS-1$//$NON-NLS-2$
return;
}
final ID responseTarget = request.getRequestContainerID();
// If response target is null then the request is bogus and we give up/do not respond
if (responseTarget == null) {
log("handleFireRequest", new NullPointerException("Response target cannot be null")); //$NON-NLS-1$ //$NON-NLS-2$
return;
}
final RemoteServiceRegistrationImpl localRegistration = getLocalRegistrationForRequest(request);
// If localRegistration not found for request, then it's a bogus request and we respond with NPE
if (localRegistration == null) {
sendErrorResponse(responseTarget, request.getRequestId(), "handleFireRequest", new NullPointerException("local service registration not found for remote request=" + request)); //$NON-NLS-1$ //$NON-NLS-2$
return;
}
IExecutor executor = getRequestExecutor(request);
if (executor == null) {
sendErrorResponse(responseTarget, request.getRequestId(), "handleFireRequest", new NullPointerException("request executor is not available and so no requests can be processed")); //$NON-NLS-1$ //$NON-NLS-2$
return;
}
// Else we've got a local service and we execute it using executor
executeRequest(executor, request, responseTarget, localRegistration, false);
}
// RemoteServiceRegistrationImpl -> List<ID>
private Map localRegistryUnregistrationTargets = new HashMap();
@SuppressWarnings("unchecked")
private void addTargetForUnregister(RemoteServiceRegistrationImpl serviceRegistration, ID targetContainerID) {
synchronized (localRegistryUnregistrationTargets) {
List existingTargets = (List) localRegistryUnregistrationTargets.get(serviceRegistration);
if (existingTargets == null) {
existingTargets = new ArrayList();
}
existingTargets.add(targetContainerID);
Trace.trace(Activator.PLUGIN_ID, "addTargetForUnregister localContainerID=" + getLocalContainerID() + ",targetContainerID=" + targetContainerID + ",serviceRegistration=" + serviceRegistration); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
localRegistryUnregistrationTargets.put(serviceRegistration, existingTargets);
}
}
@SuppressWarnings("unchecked")
private void sendUnregisterToTargets(RemoteServiceRegistrationImpl serviceRegistration, ID[] otherTargets) {
List allTargets = new ArrayList();
// First add in otherTargets
if (otherTargets != null) {
allTargets.addAll(Arrays.asList(otherTargets));
}
// Then add any explicitly registered targets
List registeredTargets = null;
synchronized (localRegistryUnregistrationTargets) {
registeredTargets = (List) localRegistryUnregistrationTargets.remove(serviceRegistration);
}
if (registeredTargets != null) {
allTargets.addAll(registeredTargets);
}
// Now allTargets should have all the container IDs of unregistration messages so we send to all
for (Iterator i = allTargets.iterator(); i.hasNext();) {
ID unregistrationTarget = (ID) i.next();
ID registrationLocalContainerID = serviceRegistration.getContainerID();
Long serviceId = new Long(serviceRegistration.getServiceId());
Trace.trace(Activator.PLUGIN_ID, "sendUnregisterToTargets " + "localContainerID=" + getLocalContainerID() + ",targetContainerID=" + unregistrationTarget + ",serviceRegistration=" + serviceRegistration); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
try {
this.sendSharedObjectMsgTo(unregistrationTarget, SharedObjectMsg.createMsg(UNREGISTER, new Object[] {registrationLocalContainerID, serviceId}));
} catch (final IOException e) {
log(UNREGISTER_ERROR_CODE, UNREGISTER_ERROR_MESSAGE, e);
}
}
}
protected void sendUnregister(RemoteServiceRegistrationImpl serviceRegistration) {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "sendUnregister", new Object[] {serviceRegistration}); //$NON-NLS-1$
synchronized (localRegistry) {
localRegistry.unpublishService(serviceRegistration);
if (isConnected()) {
final ID containerID = serviceRegistration.getContainerID();
final Long serviceId = new Long(serviceRegistration.getServiceId());
// Get targetIds from serviceRegistration properties
ID[] targetIds = getTargetsFromProperties(serviceRegistration.properties);
// If none/null, then send unregister message to all group members
if (targetIds == null) {
try {
this.sendSharedObjectMsgTo(null, SharedObjectMsg.createMsg(UNREGISTER, new Object[] {containerID, serviceId}));
} catch (final IOException e) {
log(UNREGISTER_ERROR_CODE, UNREGISTER_ERROR_MESSAGE, e);
}
}
// And send unregister explicitly to targets
sendUnregisterToTargets(serviceRegistration, targetIds);
}
}
fireRemoteServiceListeners(createUnregisteredEvent(serviceRegistration));
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), "sendUnregister"); //$NON-NLS-1$
}
protected void handleUnregister(ID containerID, Long serviceId) {
Trace.entering(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_ENTERING, this.getClass(), "handleUnregister", new Object[] {containerID, serviceId}); //$NON-NLS-1$
RemoteServiceRegistrationImpl registration = null;
synchronized (remoteRegistrys) {
// get registry for given containerID
final RemoteServiceRegistryImpl serviceRegistry = (RemoteServiceRegistryImpl) remoteRegistrys.get(containerID);
if (serviceRegistry != null) {
registration = serviceRegistry.findRegistrationForServiceId(serviceId.longValue());
if (registration != null) {
serviceRegistry.unpublishService(registration);
// If there are no remaining registration for this remote service registry,
// then remove the registry from the remoteRegistrys
RemoteServiceRegistrationImpl[] registrations = serviceRegistry.getRegistrations();
Trace.trace(Activator.PLUGIN_ID, "handleUnregister localContainerID=" + getLocalContainerID() + ",registrationRemoved=" + registration + ",containerID=" + containerID); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if (registrations.length == 0) {
remoteRegistrys.remove(containerID);
}
}
}
}
if (registration != null)
fireRemoteServiceListeners(createUnregisteredEvent(registration));
Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceProviderDebugOptions.METHODS_EXITING, this.getClass(), "handleUnregister"); //$NON-NLS-1$
}
protected IRemoteServiceUnregisteredEvent createUnregisteredEvent(final RemoteServiceRegistrationImpl registration) {
return new IRemoteServiceUnregisteredEvent() {
public String[] getClazzes() {
return registration.getClasses();
}
public ID getLocalContainerID() {
return RegistrySharedObject.this.getLocalContainerID();
}
public ID getContainerID() {
return registration.getContainerID();
}
public IRemoteServiceReference getReference() {
return registration.getReference();
}
public String toString() {
final StringBuffer buf = new StringBuffer("RemoteServiceUnregisteredEvent["); //$NON-NLS-1$
buf.append("localContainerID=").append(getLocalContainerID()); //$NON-NLS-1$
buf.append(";containerID=").append(registration.getContainerID()); //$NON-NLS-1$
buf.append(";clazzes=").append(Arrays.asList(registration.getClasses())); //$NON-NLS-1$
buf.append(";reference=").append(registration.getReference()).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
return buf.toString();
}
};
}
protected IRemoteServiceRegisteredEvent createRegisteredEvent(final RemoteServiceRegistrationImpl registration) {
return new IRemoteServiceRegisteredEvent() {
public ID getLocalContainerID() {
return RegistrySharedObject.this.getLocalContainerID();
}
public String[] getClazzes() {
return registration.getClasses();
}
public ID getContainerID() {
return registration.getContainerID();
}
public IRemoteServiceReference getReference() {
return registration.getReference();
}
public String toString() {
final StringBuffer buf = new StringBuffer("RemoteServiceRegisteredEvent["); //$NON-NLS-1$
buf.append("localContainerID=").append(getLocalContainerID()); //$NON-NLS-1$
buf.append(";containerID=").append(registration.getContainerID()); //$NON-NLS-1$
buf.append(";clazzes=").append(Arrays.asList(registration.getClasses())); //$NON-NLS-1$
buf.append(";reference=").append(registration.getReference()).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
return buf.toString();
}
};
}
@SuppressWarnings("unchecked")
protected RemoteServiceRegistryImpl addRemoteRegistry(RemoteServiceRegistryImpl registry) {
return (RemoteServiceRegistryImpl) remoteRegistrys.put(registry.getContainerID(), registry);
}
protected RemoteServiceRegistryImpl getRemoteRegistry(ID containerID) {
return (RemoteServiceRegistryImpl) remoteRegistrys.get(containerID);
}
protected RemoteServiceRegistryImpl removeRemoteRegistry(ID containerID) {
return (RemoteServiceRegistryImpl) remoteRegistrys.remove(containerID);
}
/**
* @param request request
* @return RemoteServiceRegistrationImpl the registration
* @since 3.2
*/
protected RemoteServiceRegistrationImpl getLocalRegistrationForRequest(Request request) {
synchronized (localRegistry) {
return localRegistry.findRegistrationForServiceId(request.getServiceId());
}
}
/**
* @param request the request to add
* @return true if added, false if not added
* @since 3.2
*/
@SuppressWarnings("unchecked")
protected boolean addRequest(Request request) {
synchronized (requests) {
return requests.add(request);
}
}
/**
* @param requestId requestId
* @return Request the request associated with the given requestId or <code>null</code>
* @since 3.2
*/
protected Request getRequest(long requestId) {
synchronized (requests) {
for (final Iterator i = requests.iterator(); i.hasNext();) {
final Request req = (Request) i.next();
final long reqId = req.getRequestId();
if (reqId == requestId) {
return req;
}
}
}
return null;
}
/**
* @param request request
* @return boolean true if removed, false otherwise
* @since 3.2
*/
protected boolean removeRequest(Request request) {
synchronized (requests) {
return requests.remove(request);
}
}
protected void logException(int code, String message, Throwable e) {
Activator.getDefault().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, code, message, e));
}
protected boolean handleSharedObjectMsg(SharedObjectMsg msg) {
try {
msg.invoke(this);
return true;
} catch (final Exception e) {
logException(MSG_INVOKE_ERROR_CODE, "Exception invoking shared object message=" + msg, e); //$NON-NLS-1$
}
return false;
}
/**
* @return IRemoteServiceCallPolicy the policy. May be <code>null</code>
* @since 4.0
*/
protected IRemoteServiceCallPolicy getRemoteServiceCallPolicy() {
synchronized (remoteServiceCallPolicyLock) {
return remoteServiceCallPolicy;
}
}
/**
* @param policy the policy to set. May be <code>null</code>
* @return boolean true if set, false if cannot be set.
* @since 4.0
*/
public boolean setRemoteServiceCallPolicy(IRemoteServiceCallPolicy policy) {
synchronized (remoteServiceCallPolicyLock) {
this.remoteServiceCallPolicy = policy;
return true;
}
}
}