/* * This file is part of the OpenSCADA project * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) * * OpenSCADA is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenSCADA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenSCADA. If not, see * <http://opensource.org/licenses/lgpl-3.0.html> for a copy of the LGPLv3 License. */ package org.openscada.core.ui.connection.discoverer.osgi; import java.util.HashSet; import java.util.Set; import org.openscada.core.ConnectionInformation; import org.openscada.core.connection.provider.ConnectionService; import org.openscada.core.ui.connection.AbstractConnectionDiscoverer; import org.openscada.core.ui.connection.ConnectionDescriptor; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ServiceDiscoverer extends AbstractConnectionDiscoverer implements ServiceListener { private final static Logger logger = LoggerFactory.getLogger ( ServiceDiscoverer.class ); private final BundleContext context; private final Set<ServiceReference<?>> references = new HashSet<ServiceReference<?>> (); public ServiceDiscoverer () { this.context = Activator.getDefault ().getBundle ().getBundleContext (); setup (); } private synchronized void setup () { try { this.context.addServiceListener ( this, String.format ( "(%s=%s)", Constants.OBJECTCLASS, ConnectionService.class.getName () ) ); final ServiceReference<?>[] refs = this.context.getAllServiceReferences ( ConnectionService.class.getName (), null ); if ( refs != null ) { for ( final ServiceReference<?> ref : refs ) { addReference ( ref ); } } } catch ( final InvalidSyntaxException e ) { logger.warn ( "Invalid syntax when setting up filter", e ); return; } } private ConnectionInformation fromReference ( final ServiceReference<?> ref ) { final Object o = ref.getProperty ( ConnectionService.CONNECTION_URI ); if ( o instanceof String ) { final String uri = (String)o; return ConnectionInformation.fromURI ( uri ); } return null; } private void addReference ( final ServiceReference<?> ref ) { logger.info ( "Adding service: {}", ref ); if ( this.references.add ( ref ) ) { update (); } } private void removeReference ( final ServiceReference<?> ref ) { logger.info ( "Removing service: {}", ref ); if ( this.references.remove ( ref ) ) { update (); } } /** * Gather all ConnectionInformation objects and set them as connections */ private void update () { final Set<ConnectionDescriptor> infos = new HashSet<ConnectionDescriptor> (); for ( final ServiceReference<?> ref : this.references ) { final ConnectionInformation ci = fromReference ( ref ); if ( ci != null ) { final Object o = ref.getProperty ( Constants.SERVICE_PID ); final String id = o != null ? o.toString () : null; final ConnectionDescriptor cd = new ConnectionDescriptor ( ci, id ); infos.add ( cd ); } } setConnections ( infos ); } @Override public void dispose () { super.dispose (); this.context.removeServiceListener ( this ); } @Override public synchronized void serviceChanged ( final ServiceEvent event ) { switch ( event.getType () ) { case ServiceEvent.REGISTERED: addReference ( event.getServiceReference () ); break; case ServiceEvent.MODIFIED: update (); break; case ServiceEvent.UNREGISTERING: removeReference ( event.getServiceReference () ); break; } } }