| package org.eclipse.ecf.remoteservice; |
| |
| import java.security.AccessController; |
| import java.security.PrivilegedAction; |
| import java.util.*; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.ecf.core.ContainerConnectException; |
| import org.eclipse.ecf.core.IContainer; |
| import org.eclipse.ecf.core.identity.*; |
| import org.eclipse.ecf.core.security.IConnectContext; |
| import org.eclipse.ecf.core.util.Trace; |
| import org.eclipse.ecf.internal.remoteservice.Activator; |
| import org.eclipse.ecf.remoteservice.events.*; |
| import org.eclipse.ecf.remoteservice.util.RemoteFilterImpl; |
| import org.eclipse.equinox.concurrent.future.*; |
| import org.osgi.framework.InvalidSyntaxException; |
| |
| /** |
| * @since 8.3 |
| */ |
| public class RemoteServiceContainerAdapterImpl implements IRemoteServiceContainerAdapter { |
| |
| private IExecutor executor; |
| private IContainer container; |
| private IRemoteServiceCallPolicy remoteServiceCallPolicy; |
| private IConnectContext connectContext; |
| |
| protected RemoteServiceRegistryImpl registry; |
| |
| protected final List<IRemoteServiceListener> listeners; |
| |
| protected final Map<IRemoteServiceReference, List<AbstractRemoteService>> refToImplMap; |
| |
| public RemoteServiceContainerAdapterImpl(IContainer container, IExecutor executor) { |
| Assert.isNotNull(container); |
| this.container = container; |
| listeners = new ArrayList<IRemoteServiceListener>(); |
| refToImplMap = new HashMap<IRemoteServiceReference, List<AbstractRemoteService>>(); |
| setRegistry(new RemoteServiceRegistryImpl(container.getID())); |
| setExecutor(executor); |
| } |
| |
| public RemoteServiceContainerAdapterImpl(IContainer container) { |
| this(container, null); |
| } |
| |
| public void dispose() { |
| synchronized (refToImplMap) { |
| refToImplMap.clear(); |
| } |
| synchronized (listeners) { |
| listeners.clear(); |
| } |
| if (registry != null) { |
| registry.unpublishServices(); |
| registry = null; |
| } |
| this.connectContext = null; |
| this.remoteServiceCallPolicy = null; |
| this.container = null; |
| this.executor = null; |
| } |
| |
| public void addRemoteServiceListener(IRemoteServiceListener listener) { |
| synchronized (listeners) { |
| listeners.add(listener); |
| } |
| } |
| |
| public void removeRemoteServiceListener(IRemoteServiceListener listener) { |
| synchronized (listeners) { |
| listeners.remove(listener); |
| } |
| } |
| |
| public void setConnectContextForAuthentication(IConnectContext connectContext) { |
| this.connectContext = connectContext; |
| } |
| |
| public boolean setRemoteServiceCallPolicy(IRemoteServiceCallPolicy policy) { |
| this.remoteServiceCallPolicy = policy; |
| return true; |
| } |
| |
| public Object getAdapter(Class adapter) { |
| return null; |
| } |
| |
| public IRemoteServiceRegistration registerRemoteService(String[] clazzes, Object service, Dictionary properties) { |
| Trace.entering(Activator.PLUGIN_ID, IRemoteServiceImplDebugOptions.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$ |
| if (clazzes.length == 0) |
| throw new IllegalArgumentException("service classes cannot be 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$ |
| |
| RemoteServiceRegistryImpl reg = getRegistry(); |
| if (reg == null) |
| throw new NullPointerException("registry cannot be null"); //$NON-NLS-1$ |
| |
| RemoteServiceRegistrationImpl registration = createRegistration(); |
| synchronized (registry) { |
| registration.publish(reg, service, clazzes, properties); |
| } |
| fireRemoteServiceListeners(createRegisteredEvent(registration)); |
| Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceImplDebugOptions.METHODS_EXITING, this.getClass(), "registerRemoteService", registration); //$NON-NLS-1$ |
| return registration; |
| } |
| |
| public IRemoteServiceReference[] getRemoteServiceReferences(ID target, ID[] idFilter, String clazz, String filter) throws InvalidSyntaxException, ContainerConnectException { |
| Trace.entering(Activator.PLUGIN_ID, IRemoteServiceImplDebugOptions.METHODS_ENTERING, this.getClass(), "getRemoteServiceReferences", new Object[] {target, idFilter, clazz, filter}); //$NON-NLS-1$ |
| RemoteServiceRegistryImpl reg = getRegistry(); |
| if (reg == null) |
| return null; |
| if (target != null) |
| connectToRemoteServiceTarget(target); |
| |
| final IRemoteFilter remoteFilter = (filter == null) ? null : new RemoteFilterImpl(filter); |
| // then from the local registry |
| ID localContainerID = getLocalContainerID(); |
| // Now we lookup remote service references |
| final List<IRemoteServiceReference> references = new ArrayList(); |
| if (idFilter == null || Arrays.asList(idFilter).contains(localContainerID)) { |
| synchronized (reg) { |
| final IRemoteServiceReference[] rs = registry.lookupServiceReferences(clazz, remoteFilter); |
| if (rs != null) |
| for (int j = 0; j < rs.length; j++) |
| references.add(rs[j]); |
| } |
| } |
| // And we return the result |
| final IRemoteServiceReference[] result = references.toArray(new IRemoteServiceReference[references.size()]); |
| Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceImplDebugOptions.METHODS_EXITING, this.getClass(), "getRemoteServiceReferences", result); //$NON-NLS-1$ |
| return (result.length == 0) ? null : result; |
| } |
| |
| public IFuture asyncGetRemoteServiceReferences(final ID target, final ID[] idFilter, final String clazz, final String filter) { |
| IExecutor exec = getExecutor(); |
| if (exec == null) |
| throw new NullPointerException("Executor is null. Cannot asynchronously get remote service references"); //$NON-NLS-1$ |
| return exec.execute(new IProgressRunnable() { |
| public Object run(IProgressMonitor monitor) throws Exception { |
| return getRemoteServiceReferences(target, idFilter, clazz, filter); |
| } |
| }, null); |
| } |
| |
| 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; |
| } |
| } |
| |
| public IRemoteServiceReference[] getRemoteServiceReferences(ID target, String clazz, String filter) throws InvalidSyntaxException, ContainerConnectException { |
| return getRemoteServiceReferences(target, null, clazz, filter); |
| } |
| |
| public IFuture asyncGetRemoteServiceReferences(final ID[] idFilter, final String clazz, final String filter) { |
| IExecutor exec = getExecutor(); |
| if (exec == null) |
| throw new NullPointerException("Executor is null. Cannot asynchronously get remote service references"); //$NON-NLS-1$ |
| return executor.execute(new IProgressRunnable() { |
| public Object run(IProgressMonitor monitor) throws Exception { |
| return getRemoteServiceReferences(idFilter, clazz, filter); |
| } |
| }, null); |
| } |
| |
| public IFuture asyncGetRemoteServiceReferences(final ID target, final String clazz, final String filter) { |
| IExecutor exec = getExecutor(); |
| if (exec == null) |
| throw new NullPointerException("Executor is null. Cannot asynchronously get remote service references"); //$NON-NLS-1$ |
| return executor.execute(new IProgressRunnable() { |
| public Object run(IProgressMonitor monitor) throws Exception { |
| return getRemoteServiceReferences(target, clazz, filter); |
| } |
| }, null); |
| } |
| |
| 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; |
| } |
| |
| public Namespace getRemoteServiceNamespace() { |
| return IDFactory.getDefault().getNamespaceByName(RemoteServiceNamespace.NAME); |
| } |
| |
| public IRemoteServiceID getRemoteServiceID(ID containerID, long containerRelativeID) { |
| if (containerID == null) |
| return null; |
| RemoteServiceRegistryImpl reg = getRegistry(); |
| if (reg == null) |
| return null; |
| ID localContainerID = getLocalContainerID(); |
| if (containerID.equals(localContainerID)) { |
| synchronized (reg) { |
| RemoteServiceRegistrationImpl registration = reg.findRegistrationForServiceId(containerRelativeID); |
| if (registration != null) |
| return registration.getID(); |
| } |
| } |
| return null; |
| } |
| |
| public IRemoteServiceReference getRemoteServiceReference(IRemoteServiceID serviceID) { |
| ID containerID = serviceID.getContainerID(); |
| if (containerID == null) |
| return null; |
| RemoteServiceRegistryImpl reg = getRegistry(); |
| if (reg == null) |
| return null; |
| RemoteServiceRegistrationImpl registration = null; |
| ID localContainerID = getLocalContainerID(); |
| if (containerID.equals(localContainerID)) { |
| synchronized (reg) { |
| registration = reg.findRegistrationForServiceId(serviceID.getContainerRelativeID()); |
| if (registration != null) |
| return registration.getReference(); |
| } |
| } |
| return (registration == null) ? null : registration.getReference(); |
| } |
| |
| public IRemoteService getRemoteService(IRemoteServiceReference reference) { |
| Trace.entering(Activator.PLUGIN_ID, IRemoteServiceImplDebugOptions.METHODS_ENTERING, this.getClass(), "getRemoteService", reference); //$NON-NLS-1$ |
| final RemoteServiceRegistrationImpl registration = getRemoteServiceRegistrationImpl(reference); |
| if (registration == null) |
| return null; |
| final AbstractRemoteService remoteService = createRemoteService(registration); |
| if (remoteService == null) |
| return null; |
| synchronized (refToImplMap) { |
| List<AbstractRemoteService> remoteServiceImplList = refToImplMap.get(reference); |
| if (remoteServiceImplList == null) |
| remoteServiceImplList = new ArrayList(); |
| remoteServiceImplList.add(remoteService); |
| refToImplMap.put(reference, remoteServiceImplList); |
| } |
| Trace.exiting(Activator.PLUGIN_ID, IRemoteServiceImplDebugOptions.METHODS_EXITING, this.getClass(), "getRemoteService", remoteService); //$NON-NLS-1$ |
| return remoteService; |
| } |
| |
| public boolean ungetRemoteService(IRemoteServiceReference ref) { |
| if (ref == null) |
| return false; |
| IRemoteServiceID serviceID = ref.getID(); |
| if (serviceID == null) |
| return false; |
| synchronized (refToImplMap) { |
| List<AbstractRemoteService> remoteServiceImplList = refToImplMap.remove(ref); |
| if (remoteServiceImplList != null) { |
| for (Iterator<AbstractRemoteService> i = remoteServiceImplList.iterator(); i.hasNext();) { |
| AbstractRemoteService rsImpl = i.next(); |
| if (rsImpl != null) |
| rsImpl.dispose(); |
| i.remove(); |
| } |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public IRemoteFilter createRemoteFilter(String filter) throws InvalidSyntaxException { |
| return new RemoteServiceFilterImpl(filter); |
| } |
| |
| protected IRemoteServiceCallPolicy getRemoteServiceCallPolicy() { |
| return remoteServiceCallPolicy; |
| } |
| |
| protected IConnectContext getConnectContext() { |
| return this.connectContext; |
| } |
| |
| protected void setExecutor(IExecutor executor) { |
| this.executor = executor; |
| } |
| |
| protected IExecutor getExecutor() { |
| return this.executor; |
| } |
| |
| protected IContainer getContainer() { |
| return this.container; |
| } |
| |
| protected ID getLocalContainerID() { |
| return getContainer().getID(); |
| } |
| |
| protected RemoteServiceRegistryImpl getRegistry() { |
| return this.registry; |
| } |
| |
| protected void setRegistry(RemoteServiceRegistryImpl registry) { |
| this.registry = registry; |
| } |
| |
| protected AbstractRemoteService createRemoteService(RemoteServiceRegistrationImpl registration) { |
| return null; |
| } |
| |
| protected IRemoteServiceRegisteredEvent createRegisteredEvent(final RemoteServiceRegistrationImpl registration) { |
| return new IRemoteServiceRegisteredEvent() { |
| |
| public ID getLocalContainerID() { |
| return RemoteServiceContainerAdapterImpl.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(); |
| } |
| }; |
| } |
| |
| protected void fireRemoteServiceListeners(IRemoteServiceEvent event) { |
| List<IRemoteServiceListener> entries; |
| synchronized (listeners) { |
| entries = new ArrayList(listeners); |
| } |
| for (final Iterator i = entries.iterator(); i.hasNext();) { |
| final IRemoteServiceListener l = (IRemoteServiceListener) i.next(); |
| l.handleServiceEvent(event); |
| } |
| } |
| |
| protected RemoteServiceRegistrationImpl createRegistration() { |
| return new RemoteServiceRegistrationImpl(new IRegistrationListener() { |
| public void unregister(RemoteServiceRegistrationImpl registration) { |
| handleServiceUnregister(registration); |
| } |
| }); |
| } |
| |
| protected IRemoteServiceUnregisteredEvent createUnregisteredEvent(final RemoteServiceRegistrationImpl registration) { |
| return new IRemoteServiceUnregisteredEvent() { |
| |
| public String[] getClazzes() { |
| return registration.getClasses(); |
| } |
| |
| public ID getLocalContainerID() { |
| return RemoteServiceContainerAdapterImpl.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 void handleServiceUnregister(RemoteServiceRegistrationImpl registration) { |
| fireRemoteServiceListeners(createUnregisteredEvent(registration)); |
| } |
| |
| protected RemoteServiceRegistrationImpl getRemoteServiceRegistrationImpl(IRemoteServiceReference reference) { |
| if (reference instanceof RemoteServiceReferenceImpl) { |
| final RemoteServiceReferenceImpl ref = (RemoteServiceReferenceImpl) reference; |
| if (!ref.isActive()) { |
| return null; |
| } |
| return ref.getRegistration(); |
| } |
| return null; |
| } |
| |
| /** |
| * @param target the ID target |
| * @throws ContainerConnectException container connect exception if cannot connect |
| */ |
| protected void connectToRemoteServiceTarget(ID target) throws ContainerConnectException { |
| // Do nothing by default |
| } |
| |
| protected static String checkServiceClass(final String[] clazzes, final Object serviceObject) { |
| 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; |
| } |
| |
| } |