Package org.eclipse.ecf.provider.discovery

Source Code of org.eclipse.ecf.provider.discovery.CompositeDiscoveryContainer$CompositeServiceInfoWrapper

/*******************************************************************************
* Copyright (c) 2007 Versant Corp.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Markus Kuppe (mkuppe <at> versant <dot> com) - initial API and implementation
******************************************************************************/
package org.eclipse.ecf.provider.discovery;

import java.net.URI;
import java.util.*;
import org.eclipse.core.runtime.Assert;
import org.eclipse.ecf.core.ContainerConnectException;
import org.eclipse.ecf.core.IContainer;
import org.eclipse.ecf.core.events.*;
import org.eclipse.ecf.core.identity.*;
import org.eclipse.ecf.core.security.IConnectContext;
import org.eclipse.ecf.core.util.ECFRuntimeException;
import org.eclipse.ecf.core.util.Trace;
import org.eclipse.ecf.discovery.*;
import org.eclipse.ecf.discovery.identity.*;
import org.eclipse.ecf.discovery.service.IDiscoveryService;
import org.eclipse.ecf.internal.provider.discovery.Activator;
import org.eclipse.ecf.internal.provider.discovery.CompositeNamespace;

public class CompositeDiscoveryContainer extends AbstractDiscoveryContainerAdapter implements IDiscoveryService {

  public static final String NAME = "ecf.discovery.composite"; //$NON-NLS-1$

  protected class CompositeContainerServiceListener implements IServiceListener {

    /* (non-Javadoc)
     * @see org.eclipse.ecf.discovery.IServiceListener#serviceDiscovered(org.eclipse.ecf.discovery.IServiceEvent)
     */
    public void serviceDiscovered(final IServiceEvent event) {
      final Collection col = getListeners(event.getServiceInfo().getServiceID().getServiceTypeID());
      if (!col.isEmpty()) {
        for (final Iterator itr = col.iterator(); itr.hasNext();) {
          final IServiceListener isl = (IServiceListener) itr.next();
          // we want to pretend the discovery event comes from us, thus we change the connectedId
          isl.serviceDiscovered(new CompositeServiceContainerEvent(event, getConnectedID()));
          Trace.trace(Activator.PLUGIN_ID, METHODS_TRACING, this.getClass(), "serviceDiscovered", //$NON-NLS-1$
              "serviceResolved fired for listener " //$NON-NLS-1$
                  + isl.toString() + " with event: " + event.toString()); //$NON-NLS-1$
        }
      } else {
        Trace.trace(Activator.PLUGIN_ID, METHODS_TRACING, this.getClass(), "serviceDiscovered", //$NON-NLS-1$
            "serviceResolved fired without any listeners present"); //$NON-NLS-1$
      }
    }

    /* (non-Javadoc)
     * @see org.eclipse.ecf.discovery.IServiceListener#serviceUndiscovered(org.eclipse.ecf.discovery.IServiceEvent)
     */
    public void serviceUndiscovered(final IServiceEvent event) {
      final Collection col = getListeners(event.getServiceInfo().getServiceID().getServiceTypeID());
      if (!col.isEmpty()) {
        for (final Iterator itr = col.iterator(); itr.hasNext();) {
          final IServiceListener isl = (IServiceListener) itr.next();
          // we want to pretend the discovery event comes from us, thus we change the connectedId
          isl.serviceUndiscovered(new CompositeServiceContainerEvent(event, getConnectedID()));
          Trace.trace(Activator.PLUGIN_ID, METHODS_TRACING, this.getClass(), "serviceUndiscovered", //$NON-NLS-1$
              "serviceRemoved fired for listener " //$NON-NLS-1$
                  + isl.toString() + " with event: " + event.toString()); //$NON-NLS-1$
        }
      } else {
        Trace.trace(Activator.PLUGIN_ID, METHODS_TRACING, this.getClass(), "serviceUndiscovered", //$NON-NLS-1$
            "serviceRemoved fired without any listeners present"); //$NON-NLS-1$
      }
    }

    /* (non-Javadoc)
     * @see org.eclipse.ecf.discovery.IServiceListener#triggerDiscovery()
     */
    public boolean triggerDiscovery() {
      return false;
    }
  }

  protected class CompositeContainerServiceTypeListener implements IServiceTypeListener {

    /* (non-Javadoc)
     * @see org.eclipse.ecf.discovery.IServiceTypeListener#serviceTypeDiscovered(org.eclipse.ecf.discovery.IServiceEvent)
     */
    public synchronized void serviceTypeDiscovered(final IServiceTypeEvent event) {
      // notify our listeners first so they get a chance to register for
      // the type before the underlying provider fires service added
      synchronized (serviceTypeListeners) {
        for (final Iterator itr = serviceTypeListeners.iterator(); itr.hasNext();) {
          final IServiceTypeListener listener = (IServiceTypeListener) itr.next();
          // we want to pretend the discovery event comes from us, thus we change the connectedId
          listener.serviceTypeDiscovered(new CompositeServiceTypeContainerEvent(event, getConnectedID()));
          Trace.trace(Activator.PLUGIN_ID, METHODS_TRACING, this.getClass(), "serviceTypeDiscovered", //$NON-NLS-1$
              "serviceTypeDiscovered fired for listener " //$NON-NLS-1$
                  + listener.toString() + " with event: " + event.toString()); //$NON-NLS-1$
        }
      }
      // add ourself as a listener to the underlying providers. This might
      // trigger a serviceAdded alread
      final IServiceTypeID istid = event.getServiceTypeID();
      synchronized (containers) {
        for (final Iterator itr = containers.iterator(); itr.hasNext();) {
          // TODO ccstl doesn't have to be a listener for a non
          // matching (namespace) container, but it doesn't hurt
          // either
          final IDiscoveryLocator idca = (IDiscoveryLocator) itr.next();
          idca.addServiceListener(istid, ccsl);
        }
      }
    }
  }

  protected static final String METHODS_CATCHING = Activator.PLUGIN_ID + "/debug/methods/catching"; //$NON-NLS-1$

  protected static final String METHODS_TRACING = Activator.PLUGIN_ID + "/debug/methods/tracing"; //$NON-NLS-1$

  protected final CompositeContainerServiceListener ccsl = new CompositeContainerServiceListener();
  protected final CompositeContainerServiceTypeListener ccstl = new CompositeContainerServiceTypeListener();

  /**
   * History of services registered with this IDCA
   *
   * Used on newly added IDCAs
   */
  protected Set registeredServices;

  protected final Collection containers;

  private ID targetID;

  /**
   * @param containers
   */
  public CompositeDiscoveryContainer(final Collection containers) {
    super(CompositeNamespace.NAME, new DiscoveryContainerConfig(IDFactory.getDefault().createStringID(CompositeDiscoveryContainer.class.getName())));
    this.containers = containers;
    this.registeredServices = new HashSet();
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.core.IContainer#connect(org.eclipse.ecf.core.identity.ID, org.eclipse.ecf.core.security.IConnectContext)
   */
  public void connect(final ID aTargetID, final IConnectContext connectContext) throws ContainerConnectException {
    if (targetID != null || getConfig() == null) {
      throw new ContainerConnectException("Already connected"); //$NON-NLS-1$
    }
    targetID = (aTargetID == null) ? getConfig().getID() : aTargetID;
    fireContainerEvent(new ContainerConnectingEvent(this.getID(), targetID, connectContext));
    synchronized (containers) {
      final Collection containersFailedToConnect = new HashSet();
      for (final Iterator itr = containers.iterator(); itr.hasNext();) {
        final IContainer container = (IContainer) itr.next();
        if (container.getConnectedID() == null) {
          try {
            container.connect(targetID, connectContext);
          } catch (ContainerConnectException cce) {
            Trace.catching(Activator.PLUGIN_ID, METHODS_TRACING, this.getClass(), "connect", //$NON-NLS-1$
                cce);
            containersFailedToConnect.add(container);
            continue;
          }
        }
        final IDiscoveryLocator idca = (IDiscoveryLocator) container;
        idca.addServiceListener(ccsl);
        idca.addServiceTypeListener(ccstl);
      }
      // remove all containers that failed to connect and thus are unusable subsequently
      containers.removeAll(containersFailedToConnect);
    }
    fireContainerEvent(new ContainerConnectedEvent(this.getID(), targetID));
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.core.IContainer#disconnect()
   */
  public void disconnect() {
    fireContainerEvent(new ContainerDisconnectingEvent(this.getID(), getConnectedID()));
    targetID = null;
    synchronized (containers) {
      for (final Iterator itr = containers.iterator(); itr.hasNext();) {
        final IContainer container = (IContainer) itr.next();
        container.disconnect();
      }
      containers.clear();
    }
    synchronized (registeredServices) {
      registeredServices.clear();
    }
    synchronized (allServiceListeners) {
      allServiceListeners.clear();
    }
    synchronized (serviceListeners) {
      serviceListeners.clear();
    }
    synchronized (serviceTypeListeners) {
      serviceTypeListeners.clear();
    }
    fireContainerEvent(new ContainerDisconnectedEvent(this.getID(), getConnectedID()));
  }

  public static class CompositeServiceInfoWrapper implements IServiceInfo {
    private final IServiceInfo anInfo;
    private final ID anId;

    public CompositeServiceInfoWrapper(IServiceInfo anInfo, ID anId) {
      this.anInfo = anInfo;
      this.anId = anId;
    }

    public ID getId() {
      return anId;
    }

    public URI getLocation() {
      return anInfo.getLocation();
    }

    public IServiceID getServiceID() {
      return anInfo.getServiceID();
    }

    public int getPriority() {
      return anInfo.getPriority();
    }

    public Object getAdapter(Class adapter) {
      return anInfo.getAdapter(adapter);
    }

    public int getWeight() {
      return anInfo.getWeight();
    }

    public long getTTL() {
      return anInfo.getTTL();
    }

    public IServiceProperties getServiceProperties() {
      return anInfo.getServiceProperties();
    }

    public String getServiceName() {
      return anInfo.getServiceName();
    }
  }

  protected IServiceEvent getServiceEvent(IServiceInfo iServiceInfo, ID id) {
    final CompositeServiceInfoWrapper csi = (CompositeServiceInfoWrapper) iServiceInfo;
    return new CompositeServiceContainerEvent(iServiceInfo, id, csi.getId());
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.discovery.AbstractDiscoveryContainerAdapter#dispose()
   */
  public void dispose() {
    disconnect();
    synchronized (containers) {
      for (final Iterator itr = containers.iterator(); itr.hasNext();) {
        final IContainer container = (IContainer) itr.next();
        container.dispose();
      }
      containers.clear();
    }
    targetID = null;
    super.dispose();
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.core.IContainer#getConnectedID()
   */
  public ID getConnectedID() {
    return targetID;
  }

  private IServiceID getServiceIDForDiscoveryContainer(final IServiceID service, final IDiscoveryLocator dca) {
    final Namespace connectNamespace = dca.getServicesNamespace();
    if (!connectNamespace.equals(service.getNamespace())) {
      return (IServiceID) connectNamespace.createInstance(new Object[] {service.getServiceTypeID().getName(), service.getLocation()});
    }
    return service;
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.discovery.IDiscoveryContainerAdapter#getServiceInfo(org.eclipse.ecf.discovery.identity.IServiceID)
   */
  public IServiceInfo getServiceInfo(final IServiceID aService) {
    Assert.isNotNull(aService);
    synchronized (containers) {
      for (final Iterator itr = containers.iterator(); itr.hasNext();) {
        final IDiscoveryLocator idca = (IDiscoveryLocator) itr.next();
        final IServiceID isi = getServiceIDForDiscoveryContainer(aService, idca);
        final IServiceInfo service = idca.getServiceInfo(isi);
        if (service != null) {
          return service;
        }
      }
    }
    return null;
  }

  private IServiceInfo getServiceInfoForDiscoveryContainer(final IServiceInfo aSi, final IDiscoveryLocator idca) {
    final IServiceID serviceId = aSi.getServiceID();
    final IServiceID sid = getServiceIDForDiscoveryContainer(serviceId, idca);
    final IServiceTypeID serviceTypeID = sid.getServiceTypeID();
    return new ServiceInfo(serviceId.getLocation(), aSi.getServiceName(), serviceTypeID, aSi.getPriority(), aSi.getWeight(), aSi.getServiceProperties());
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.discovery.IDiscoveryContainerAdapter#getServices()
   */
  public IServiceInfo[] getServices() {
    final Set set = new HashSet();
    synchronized (containers) {
      for (final Iterator itr = containers.iterator(); itr.hasNext();) {
        final IDiscoveryLocator idca = (IDiscoveryLocator) itr.next();
        final ID containerId = ((IContainer) idca).getID();
        final IServiceInfo[] services = idca.getServices();
        for (int i = 0; i < services.length; i++) {
          IServiceInfo iServiceInfo = services[i];
          services[i] = new CompositeServiceInfoWrapper(iServiceInfo, containerId);
        }
        set.addAll(Arrays.asList(services));
      }
    }
    return (IServiceInfo[]) set.toArray(new IServiceInfo[set.size()]);
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.discovery.IDiscoveryContainerAdapter#getServices(org.eclipse.ecf.discovery.identity.IServiceTypeID)
   */
  public IServiceInfo[] getServices(final IServiceTypeID type) {
    Assert.isNotNull(type);
    final Set set = new HashSet();
    synchronized (containers) {
      for (final Iterator itr = containers.iterator(); itr.hasNext();) {
        final IDiscoveryLocator idca = (IDiscoveryLocator) itr.next();
        final IServiceTypeID isti = getServiceTypeIDForDiscoveryContainer(type, idca);
        final IServiceInfo[] services = idca.getServices(isti);
        set.addAll(Arrays.asList(services));
      }
    }
    return (IServiceInfo[]) set.toArray(new IServiceInfo[set.size()]);
  }

  private IServiceTypeID getServiceTypeIDForDiscoveryContainer(final IServiceTypeID type, final IDiscoveryLocator dca) {
    final Namespace connectNamespace = dca.getServicesNamespace();
    if (!connectNamespace.equals(type.getNamespace())) {
      return ServiceIDFactory.getDefault().createServiceTypeID(connectNamespace, type);
    }
    return type;
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.discovery.IDiscoveryContainerAdapter#getServiceTypes()
   */
  public IServiceTypeID[] getServiceTypes() {
    final Set set = new HashSet();
    synchronized (containers) {
      for (final Iterator itr = containers.iterator(); itr.hasNext();) {
        final IDiscoveryLocator idca = (IDiscoveryLocator) itr.next();
        final IServiceTypeID[] services = idca.getServiceTypes();
        set.addAll(Arrays.asList(services));
      }
    }
    return (IServiceTypeID[]) set.toArray(new IServiceTypeID[set.size()]);
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.discovery.IDiscoveryContainerAdapter#registerService(org.eclipse.ecf.discovery.IServiceInfo)
   */
  public void registerService(final IServiceInfo serviceInfo) {
    Assert.isNotNull(serviceInfo);
    synchronized (registeredServices) {
      Assert.isTrue(registeredServices.add(serviceInfo));
    }
    synchronized (containers) {
      for (final Iterator itr = containers.iterator(); itr.hasNext();) {
        final IDiscoveryAdvertiser dca = (IDiscoveryAdvertiser) itr.next();
        final IServiceInfo isi = getServiceInfoForDiscoveryContainer(serviceInfo, (IDiscoveryLocator) dca);
        dca.registerService(isi);
        Trace.trace(Activator.PLUGIN_ID, METHODS_TRACING, this.getClass(), "registerService", "registeredService " //$NON-NLS-1$ //$NON-NLS-2$
            + serviceInfo.toString());
      }
    }
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.discovery.IDiscoveryContainerAdapter#unregisterService(org.eclipse.ecf.discovery.IServiceInfo)
   */
  public void unregisterService(final IServiceInfo serviceInfo) {
    Assert.isNotNull(serviceInfo);
    synchronized (registeredServices) {
      // no assert as unregisterService might be called with an non-existing ISI
      registeredServices.remove(serviceInfo);
    }
    synchronized (containers) {
      for (final Iterator itr = containers.iterator(); itr.hasNext();) {
        final IDiscoveryAdvertiser idca = (IDiscoveryAdvertiser) itr.next();
        final IServiceInfo isi = getServiceInfoForDiscoveryContainer(serviceInfo, (IDiscoveryLocator) idca);
        idca.unregisterService(isi);
      }
    }
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.discovery.AbstractDiscoveryContainerAdapter#unregisterAllServices()
   */
  public void unregisterAllServices() {
    synchronized (registeredServices) {
      synchronized (containers) {
        for (final Iterator itr = containers.iterator(); itr.hasNext();) {
          final IDiscoveryAdvertiser idca = (IDiscoveryAdvertiser) itr.next();
          for (Iterator itr2 = registeredServices.iterator(); itr2.hasNext();) {
            final IServiceInfo serviceInfo = (IServiceInfo) itr2.next();
            final IServiceInfo isi = getServiceInfoForDiscoveryContainer(serviceInfo, (IDiscoveryLocator) idca);
            idca.unregisterService(isi);
          }
        }
      }
    }
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.discovery.AbstractDiscoveryContainerAdapter#purgeCache()
   */
  public IServiceInfo[] purgeCache() {
    final Set set = new HashSet();
    synchronized (containers) {
      for (final Iterator itr = containers.iterator(); itr.hasNext();) {
        final IDiscoveryLocator idca = (IDiscoveryLocator) itr.next();
        final IServiceInfo[] services = idca.purgeCache();
        set.addAll(Arrays.asList(services));
      }
    }
    return (IServiceInfo[]) set.toArray(new IServiceInfo[set.size()]);
  }

  /**
   * @param object
   * @return true on success
   * @see java.util.List#add(java.lang.Object)
   */
  public boolean addContainer(final Object object) {
    // connect the new container if necessary and register ourself as listeners
    IContainer iContainer = (IContainer) object;
    if (iContainer.getConnectedID() == null) {
      try {
        iContainer.connect(targetID, null);
      } catch (ContainerConnectException e) {
        // we eat the exception here
        Trace.catching(Activator.PLUGIN_ID, METHODS_CATCHING, this.getClass(), "addContainer(Object)", e); //$NON-NLS-1$
        return false;
      }
    }
    final IDiscoveryLocator idca = (IDiscoveryLocator) object;
    idca.addServiceListener(ccsl);
    idca.addServiceTypeListener(ccstl);
    // register previously registered with the new IDS
    synchronized (registeredServices) {
      final IDiscoveryAdvertiser ida = (IDiscoveryAdvertiser) object;
      for (final Iterator itr = registeredServices.iterator(); itr.hasNext();) {
        final IServiceInfo serviceInfo = (IServiceInfo) itr.next();
        try {
          ida.registerService(serviceInfo);
        } catch (final ECFRuntimeException e) {
          // we eat the exception here since the original registerService call is long done
          Trace.catching(Activator.PLUGIN_ID, METHODS_CATCHING, this.getClass(), "addContainer(Object)", e); //$NON-NLS-1$
        }
      }
    }
    synchronized (containers) {
      Trace.trace(Activator.PLUGIN_ID, METHODS_TRACING, this.getClass(), "addContainer(Object)", "addContainer " //$NON-NLS-1$ //$NON-NLS-2$
          + object.toString());
      return containers.add(object);
    }
  }

  /**
   * @param object
   * @return true on success
   * @see java.util.List#remove(java.lang.Object)
   */
  public boolean removeContainer(final Object object) {
    final IDiscoveryLocator idca = (IDiscoveryLocator) object;
    idca.removeServiceListener(ccsl);
    idca.removeServiceTypeListener(ccstl);
    synchronized (containers) {
      Trace.trace(Activator.PLUGIN_ID, METHODS_TRACING, this.getClass(), "removeContainer(Object)", "removeContainer " //$NON-NLS-1$ //$NON-NLS-2$
          + object.toString());
      return containers.remove(object);
    }
  }

  /**
   * @return The List of currently registered containers.
   * @since 2.1
   */
  public Collection getDiscoveryContainers() {
    return Collections.unmodifiableCollection(containers);
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.discovery.AbstractDiscoveryContainerAdapter#getContainerName()
   */
  public String getContainerName() {
    return NAME;
  }
}
TOP

Related Classes of org.eclipse.ecf.provider.discovery.CompositeDiscoveryContainer$CompositeServiceInfoWrapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.