/******************************************************************************* * Copyright (c) 2013 Markus Alexander Kuppe and others. 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 - 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.Namespace; import org.eclipse.ecf.discovery.*; import org.eclipse.ecf.discovery.identity.*; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.util.tracker.ServiceTracker; import org.osgi.util.tracker.ServiceTrackerCustomizer; /** * An IServiceInfoServiceListener is a whiteboard pattern listener responsible * to handle IServiceInfos registered in the OSGi service registry. */ public class IServiceInfoServiceListener { private final ServiceTracker serviceTracker; void logException(String message, Throwable t) { DiscoveryPlugin.getDefault().log(new Status(IStatus.ERROR, DiscoveryPlugin.PLUGIN_ID, message, t)); } public IServiceInfoServiceListener(final IDiscoveryAdvertiser advertiser) { final BundleContext bundleContext = DiscoveryPlugin.getDefault().getBundleContext(); serviceTracker = new ServiceTracker(bundleContext, IServiceInfo.class, new ServiceTrackerCustomizer() { public Object addingService(ServiceReference reference) { final IServiceInfo serviceInfo = (IServiceInfo) bundleContext.getService(reference); try { advertiser.registerService(convertToProviderSpecific(advertiser, serviceInfo)); } catch (Exception e) { logException("Advertiser.registerService failed", e); } return serviceInfo; } public void modifiedService(ServiceReference reference, Object service) { // TODO discovery containers might require to // unregisterService first try { advertiser.registerService(convertToProviderSpecific(advertiser, (IServiceInfo) service)); } catch (Exception e) { logException("Advertiser.modifiedService failed", e); } } public void removedService(ServiceReference reference, Object service) { try { advertiser.unregisterService(convertToProviderSpecific(advertiser, (IServiceInfo) service)); } catch (Exception e) { logException("Advertiser.removedService failed", e); } } }); serviceTracker.open(); } /** * Converts the generic (not discovery provider specific WRT * IServiceID/IServiceTypeID) IServiceInfo into a discovery provider * specific one. This is required so that discovery providers can correctly * advertise services. */ private IServiceInfo convertToProviderSpecific(final IDiscoveryAdvertiser advertiser, final IServiceInfo genericInfo) { // Convert similar to // org.eclipse.ecf.provider.discovery.CompositeDiscoveryContainer.getServiceIDForDiscoveryContainer(IServiceID, // IDiscoveryLocator) final Namespace servicesNamespace = advertiser.getServicesNamespace(); final IServiceID genericServiceID = genericInfo.getServiceID(); final ServiceID specificServiceID = (ServiceID) servicesNamespace.createInstance( new Object[] { genericServiceID.getServiceTypeID().getName(), genericServiceID.getLocation() }); final IServiceTypeID serviceTypeID = specificServiceID.getServiceTypeID(); return new ServiceInfo(genericServiceID.getLocation(), genericInfo.getServiceName(), serviceTypeID, genericInfo.getPriority(), genericInfo.getWeight(), genericInfo.getServiceProperties(), genericInfo.getTTL()); } public void dispose() { serviceTracker.close(); } }