/******************************************************************************* * Copyright (c) 2009 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.provider.dnssd; import java.util.Dictionary; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Properties; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.ecf.core.ContainerConnectException; import org.eclipse.ecf.core.ContainerTypeDescription; import org.eclipse.ecf.core.IContainer; import org.eclipse.ecf.core.identity.Namespace; import org.eclipse.ecf.core.util.ExtensionRegistryRunnable; import org.eclipse.ecf.discovery.IDiscoveryAdvertiser; import org.eclipse.ecf.discovery.IDiscoveryLocator; import org.osgi.framework.Bundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceFactory; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.cm.ManagedServiceFactory; public class Activator implements BundleActivator { public static final String PLUGIN_ID = "org.eclipse.ecf.provider.dnssd"; //$NON-NLS-1$ public static final String DISCOVERY_CONTAINER_NAME_VALUE = "ecf.discovery.dnssd"; //$NON-NLS-1$ public static final String LOCATOR = ".locator"; //$NON-NLS-1$ public static final String ADVERTISER = ".advertiser"; //$NON-NLS-1$ private static final String DISCOVERY_CONTAINER_NAME_KEY = "org.eclipse.ecf.discovery.containerName"; //$NON-NLS-1$ private final Map serviceRegistrations = new HashMap(); private volatile BundleContext context; /* * (non-Javadoc) * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) */ public void start(final BundleContext context) throws Exception { this.context = context; SafeRunner.run(new ExtensionRegistryRunnable(context) { protected void runWithoutRegistry() throws Exception { context.registerService(Namespace.class, new DnsSdNamespace(), null); context.registerService(ContainerTypeDescription.class, new ContainerTypeDescription(DISCOVERY_CONTAINER_NAME_VALUE + LOCATOR,new ContainerInstantiator(),"Discovery Locator Container"), null); context.registerService(ContainerTypeDescription.class, new ContainerTypeDescription(DISCOVERY_CONTAINER_NAME_VALUE + ADVERTISER,new ContainerInstantiator(),"Discovery Advertiser Container"), null); } }); // register a managed factory for the locator service final Properties locCmProps = new Properties(); locCmProps.put(Constants.SERVICE_PID, DISCOVERY_CONTAINER_NAME_VALUE + LOCATOR); context.registerService(ManagedServiceFactory.class.getName(), new DnsSdManagedServiceFactory(DnsSdDiscoveryLocator.class), locCmProps); // register the locator service final Properties locProps = new Properties(); locProps.put(DISCOVERY_CONTAINER_NAME_KEY, DISCOVERY_CONTAINER_NAME_VALUE + LOCATOR); locProps.put(Constants.SERVICE_RANKING, new Integer(750)); serviceRegistrations.put(null, context.registerService(IDiscoveryLocator.class.getName(), new DnsSdServiceFactory(DnsSdDiscoveryLocator.class), locProps)); // register a managed factory for the advertiser service final Properties advCmProps = new Properties(); advCmProps.put(Constants.SERVICE_PID, DISCOVERY_CONTAINER_NAME_VALUE + ADVERTISER); context.registerService(ManagedServiceFactory.class.getName(), new DnsSdManagedServiceFactory(DnsSdDiscoveryAdvertiser.class), advCmProps); // register the advertiser service final Properties advProps = new Properties(); advProps.put(DISCOVERY_CONTAINER_NAME_KEY, DISCOVERY_CONTAINER_NAME_VALUE + ADVERTISER); advProps.put(Constants.SERVICE_RANKING, new Integer(750)); serviceRegistrations.put(null, context.registerService(IDiscoveryAdvertiser.class.getName(), new DnsSdServiceFactory(DnsSdDiscoveryAdvertiser.class), advProps)); } /* * (non-Javadoc) * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) */ public void stop(BundleContext context) throws Exception { if (serviceRegistrations != null) { for (final Iterator itr = serviceRegistrations.values().iterator(); itr.hasNext();) { final ServiceRegistration serviceRegistration = (ServiceRegistration) itr.next(); disposeServiceRegistration(serviceRegistration); } } this.context = null; } /** * @param serviceRegistration disconnects the underlying IContainer and unregisters the service */ private void disposeServiceRegistration(ServiceRegistration serviceRegistration) { final ServiceReference reference = serviceRegistration.getReference(); final IContainer aContainer = (DnsSdDiscoveryContainerAdapter) context.getService(reference); serviceRegistration.unregister(); final IContainer container = (IContainer) aContainer.getAdapter(IContainer.class); container.dispose(); container.disconnect(); } /** * A ManagedServiceFactory capable to handle DnsSdDiscoveryContainerAdapters */ private class DnsSdManagedServiceFactory implements ManagedServiceFactory { private final Class containerClass; public DnsSdManagedServiceFactory(Class aContainerClass) { containerClass = aContainerClass; } /* (non-Javadoc) * @see org.osgi.service.cm.ManagedServiceFactory#getName() */ public String getName() { return this.getClass().getName(); } /* (non-Javadoc) * @see org.osgi.service.cm.ManagedServiceFactory#updated(java.lang.String, java.util.Dictionary) */ public void updated(String pid, Dictionary properties) throws ConfigurationException { if(properties != null) { DnsSdDiscoveryContainerAdapter adapter = null; DnsSdServiceTypeID targetID = null; try { // get existing or create new discoverycontainer final ServiceRegistration serviceRegistration = (ServiceRegistration) serviceRegistrations.get(pid); if(serviceRegistration != null) { adapter = (DnsSdDiscoveryContainerAdapter) context.getService(serviceRegistration.getReference()); targetID = (DnsSdServiceTypeID) adapter.getConnectedID(); } else { adapter = (DnsSdDiscoveryContainerAdapter) containerClass.newInstance(); targetID = new DnsSdServiceTypeID(); } // apply configuration final String[] searchPaths = (String[]) properties.get(IDnsSdDiscoveryConstants.CA_SEARCH_PATH); if(searchPaths != null) { targetID.setSearchPath(searchPaths); } final String resolver = (String) properties.get(IDnsSdDiscoveryConstants.CA_RESOLVER); if(resolver != null) { adapter.setResolver(resolver); } final String tsigKey = (String) properties.get(IDnsSdDiscoveryConstants.CA_TSIG_KEY); if(tsigKey != null) { final String tsigKeyName = (String) properties.get(IDnsSdDiscoveryConstants.CA_TSIG_KEY_NAME); adapter.setTsigKey(tsigKeyName, tsigKey); } // finally connect container and keep ser reg for later updates/deletes if(serviceRegistration == null) { final Properties props = new Properties(); props.put(Constants.SERVICE_PID, pid); adapter.connect(targetID, null); serviceRegistrations.put(pid, context.registerService(IDiscoveryLocator.class.getName(), adapter, props)); } } catch (ContainerConnectException e) { throw new ConfigurationException("IDnsSdDiscoveryConstants properties", e.getLocalizedMessage(), e); //$NON-NLS-1$ } catch (ClassCastException cce) { throw new ConfigurationException("IDnsSdDiscoveryConstants properties", cce.getLocalizedMessage(), cce); //$NON-NLS-1$ } catch (InstantiationException e) { // may never happen throw new ConfigurationException("InstantiationException", e.getLocalizedMessage(), e); //$NON-NLS-1$ } catch (IllegalAccessException e) { // may never happen throw new ConfigurationException("IllegalAccessException", e.getLocalizedMessage(), e); //$NON-NLS-1$ } } } /* (non-Javadoc) * @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String) */ public void deleted(String pid) { final ServiceRegistration serviceRegistration = (ServiceRegistration) serviceRegistrations.get(pid); disposeServiceRegistration(serviceRegistration); } } /** * A ServiceFactory capable to handle DnsSdDiscoveryContainerAdapters */ public class DnsSdServiceFactory implements ServiceFactory { private volatile DnsSdDiscoveryContainerAdapter container; private final Class containerClass; public DnsSdServiceFactory(Class aDiscoveryContainerClass) { containerClass = aDiscoveryContainerClass; } /* (non-Javadoc) * @see org.osgi.framework.ServiceFactory#getService(org.osgi.framework.Bundle, org.osgi.framework.ServiceRegistration) */ public Object getService(Bundle bundle, ServiceRegistration registration) { if (container == null) { try { container = (DnsSdDiscoveryContainerAdapter) containerClass.newInstance(); container.connect(null, null); } catch (final ContainerConnectException e) { // may never happen e.printStackTrace(); container = null; } catch (InstantiationException e) { // may never happen e.printStackTrace(); container = null; } catch (IllegalAccessException e) { // may never happen e.printStackTrace(); container = null; } } return container; } /* (non-Javadoc) * @see org.osgi.framework.ServiceFactory#ungetService(org.osgi.framework.Bundle, org.osgi.framework.ServiceRegistration, java.lang.Object) */ public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) { // nop } } }