All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.sisu.osgi.BindingTracker Maven / Gradle / Ivy

There is a newer version: 3.0.0-alpha-3
Show newest version
/*
 * Copyright (c) 2010-2024 Sonatype, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *   Stuart McCulloch (Sonatype, Inc.) - initial API and implementation
 */
package org.eclipse.sisu.osgi;

import java.util.Collection;

import org.eclipse.sisu.inject.BindingSubscriber;
import org.eclipse.sisu.inject.Logs;
import org.eclipse.sisu.inject.Weak;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;

/**
 * Tracker of {@link ServiceBinding}s from the OSGi service registry.
 */
final class BindingTracker
    extends ServiceTracker>
{
    // ----------------------------------------------------------------------
    // Implementation fields
    // ----------------------------------------------------------------------

    private final Collection> subscribers = Weak.elements();

    private final String clazzName;

    private final int maxRank;

    private boolean isOpen;

    // ----------------------------------------------------------------------
    // Constructors
    // ----------------------------------------------------------------------

    BindingTracker( final BundleContext context, final int maxRank, final String clazzName )
    {
        super( context, clazzName, null );
        this.clazzName = clazzName;
        this.maxRank = maxRank;
    }

    // ----------------------------------------------------------------------
    // Public methods
    // ----------------------------------------------------------------------

    public void subscribe( final BindingSubscriber subscriber )
    {
        synchronized ( subscribers )
        {
            openIfNecessary();
            for ( final ServiceBinding binding : getTracked().values() )
            {
                if ( binding.isCompatibleWith( subscriber ) )
                {
                    subscriber.add( binding, binding.rank() );
                }
            }
            subscribers.add( subscriber );
        }
    }

    public void unsubscribe( final BindingSubscriber subscriber )
    {
        synchronized ( subscribers )
        {
            if ( subscribers.remove( subscriber ) )
            {
                for ( final ServiceBinding binding : getTracked().values() )
                {
                    subscriber.remove( binding );
                }
            }
            closeIfNecessary();
        }
    }

    @Override
    public ServiceBinding addingService( final ServiceReference reference )
    {
        final ServiceBinding binding;
        try
        {
            binding = new ServiceBinding( context, clazzName, maxRank, reference );
        }
        catch ( final Exception e )
        {
            Logs.warn( "Problem subscribing to service: {}", reference, e );
            return null;
        }
        synchronized ( subscribers )
        {
            for ( final BindingSubscriber subscriber : subscribers )
            {
                if ( binding.isCompatibleWith( subscriber ) )
                {
                    subscriber.add( binding, binding.rank() );
                }
            }
            closeIfNecessary();
        }
        return binding;
    }

    @Override
    public void removedService( final ServiceReference reference, final ServiceBinding binding )
    {
        synchronized ( subscribers )
        {
            for ( final BindingSubscriber subscriber : subscribers )
            {
                subscriber.remove( binding );
            }
            closeIfNecessary();
        }
        super.removedService( reference, binding );
    }

    // ----------------------------------------------------------------------
    // Implementation methods
    // ----------------------------------------------------------------------

    private void openIfNecessary()
    {
        if ( !isOpen )
        {
            open( true ); // calls addingService to pre-fill the tracker
            Logs.trace( "Started tracking services: {}", filter, null );
            isOpen = true; // set last to avoid premature close
        }
    }

    private void closeIfNecessary()
    {
        if ( isOpen && subscribers.isEmpty() )
        {
            isOpen = false; // set first to avoid repeated close
            Logs.trace( "Stopped tracking services: {}", filter, null );
            close(); // calls removedService to clear out the tracker
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy