| /******************************************************************************* |
| * Copyright (c) 2010 Markus Alexander Kuppe. |
| * 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 Alexander Kuppe (ecf-dev_eclipse.org <at> lemmster <dot> de) - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.ecf.internal.discovery; |
| |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.ecf.core.identity.*; |
| import org.eclipse.ecf.core.util.StringUtils; |
| import org.eclipse.ecf.discovery.*; |
| import org.eclipse.ecf.discovery.identity.*; |
| import org.osgi.framework.*; |
| |
| public class DiscoveryServiceListener implements ServiceListener { |
| |
| private final AbstractDiscoveryContainerAdapter discoveryContainer; |
| private final Class listenerClass; |
| private final BundleContext context; |
| private final IServiceIDFactory idFactory; |
| private final Namespace discoveryNamespace; |
| |
| public DiscoveryServiceListener( |
| AbstractDiscoveryContainerAdapter anAbstractDiscoveryContainerAdapter, |
| Class clazz) { |
| discoveryContainer = anAbstractDiscoveryContainerAdapter; |
| listenerClass = clazz; |
| discoveryNamespace = IDFactory.getDefault().getNamespaceByName( |
| DiscoveryNamespace.NAME); |
| idFactory = ServiceIDFactory.getDefault(); |
| context = DiscoveryPlugin.getDefault().getBundleContext(); |
| try { |
| // get existing listener |
| final ServiceReference[] references = context.getServiceReferences( |
| listenerClass.getName(), null); |
| addServiceListener(references); |
| |
| // listen for more listeners |
| context.addServiceListener(this, getFilter()); |
| } catch (InvalidSyntaxException e) { |
| DiscoveryPlugin.getDefault().log( |
| new Status(IStatus.ERROR, DiscoveryPlugin.PLUGIN_ID, |
| IStatus.ERROR, "Cannot create filter", e)); //$NON-NLS-1$ |
| } |
| } |
| |
| public void dispose() { |
| if (!DiscoveryPlugin.isStopped()) { |
| context.removeServiceListener(this); |
| } |
| } |
| |
| private void addServiceListener(ServiceReference[] references) { |
| if (references == null) { |
| return; |
| } |
| for (int i = 0; i < references.length; i++) { |
| final ServiceReference serviceReference = references[i]; |
| if (listenerClass.getName() |
| .equals(IServiceListener.class.getName())) { |
| if (isAllWildcards(serviceReference)) { |
| final IServiceListener aListener = (IServiceListener) context |
| .getService(serviceReference); |
| discoveryContainer.addServiceListener(aListener); |
| } else { |
| final IServiceTypeID aType = getIServiceTypeID(serviceReference); |
| if (aType == null) { |
| continue; |
| } |
| final IServiceListener aListener = (IServiceListener) context |
| .getService(serviceReference); |
| discoveryContainer.addServiceListener(aType, aListener); |
| } |
| } else { |
| final IServiceTypeListener aListener = (IServiceTypeListener) context |
| .getService(serviceReference); |
| discoveryContainer.addServiceTypeListener(aListener); |
| } |
| } |
| } |
| |
| private void addServiceListener(ServiceReference reference) { |
| addServiceListener(new ServiceReference[] { reference }); |
| } |
| |
| private void removeServiceListener(ServiceReference[] references) { |
| if (references == null) { |
| return; |
| } |
| for (int i = 0; i < references.length; i++) { |
| final ServiceReference serviceReference = references[i]; |
| if (listenerClass.getName() |
| .equals(IServiceListener.class.getName())) { |
| if (isAllWildcards(serviceReference)) { |
| final IServiceListener aListener = (IServiceListener) context |
| .getService(serviceReference); |
| discoveryContainer.removeServiceListener(aListener); |
| } else { |
| final IServiceTypeID aType = getIServiceTypeID(serviceReference); |
| if (aType == null) { |
| continue; |
| } |
| final IServiceListener aListener = (IServiceListener) context |
| .getService(serviceReference); |
| discoveryContainer.removeServiceListener(aType, aListener); |
| } |
| } else { |
| final IServiceTypeListener aListener = (IServiceTypeListener) context |
| .getService(serviceReference); |
| discoveryContainer.removeServiceTypeListener(aListener); |
| } |
| } |
| } |
| |
| private void removeServiceListener(ServiceReference reference) { |
| removeServiceListener(new ServiceReference[] { reference }); |
| } |
| |
| private boolean isAllWildcards(ServiceReference serviceReference) { |
| return serviceReference |
| .getProperty("org.eclipse.ecf.discovery.namingauthority") == null |
| && serviceReference |
| .getProperty("org.eclipse.ecf.discovery.services") == null |
| && serviceReference |
| .getProperty("org.eclipse.ecf.discovery.scopes") == null |
| && serviceReference |
| .getProperty("org.eclipse.ecf.discovery.protocols") == null; |
| } |
| |
| private IServiceTypeID getIServiceTypeID(ServiceReference serviceReference) { |
| String namingAuthority = (String) serviceReference |
| .getProperty("org.eclipse.ecf.discovery.namingauthority"); //$NON-NLS-1$ |
| if (namingAuthority == null) { |
| namingAuthority = "*"; //$NON-NLS-1$ |
| } |
| try { |
| final IServiceTypeID createServiceTypeID = idFactory |
| .createServiceTypeID( |
| discoveryNamespace, |
| convert(serviceReference, |
| "org.eclipse.ecf.discovery.services"), //$NON-NLS-1$ |
| convert(serviceReference, |
| "org.eclipse.ecf.discovery.scopes"), //$NON-NLS-1$ |
| convert(serviceReference, |
| "org.eclipse.ecf.discovery.protocols"), //$NON-NLS-1$ |
| namingAuthority); |
| return createServiceTypeID; |
| } catch (final IDCreateException e) { |
| return null; |
| } |
| } |
| |
| private String[] convert(ServiceReference serviceReference, String key) { |
| final Object value = serviceReference.getProperty(key); |
| // default to wildcard for non-set values |
| if (value == null) { |
| return new String[] { "*" }; //$NON-NLS-1$ |
| } else if (value instanceof String[]) { |
| return (String[]) value; |
| } |
| return StringUtils.split((String) value, "._"); //$NON-NLS-1$ |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework. |
| * ServiceEvent) |
| */ |
| public void serviceChanged(ServiceEvent event) { |
| // ignore events that are targeted at different discovery containers |
| final Object containerName = event.getServiceReference().getProperty( |
| IDiscoveryLocator.CONTAINER_NAME); |
| if (!discoveryContainer.getContainerName().equals(containerName)) { |
| return; |
| } |
| switch (event.getType()) { |
| case ServiceEvent.REGISTERED: |
| addServiceListener(event.getServiceReference()); |
| break; |
| case ServiceEvent.UNREGISTERING: |
| removeServiceListener(event.getServiceReference()); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| private String getFilter() { |
| return "(" + Constants.OBJECTCLASS + "=" + listenerClass.getName() //$NON-NLS-1$ //$NON-NLS-2$ |
| + ")"; //$NON-NLS-1$ |
| } |
| } |