package com.codeaffine.example.rwt.osgi.ui.platform.internal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import com.codeaffine.example.rwt.osgi.ui.platform.UIContributor;
import com.codeaffine.example.rwt.osgi.ui.platform.UIContributorFactory;
public class UIContributorTrackerService {
final ServiceTracker<UIContributorFactory, UIContributorFactory> serviceTracker;
final Map<ServiceReference<UIContributorFactory>,UIContributorFactory> contributors;
final Map<Tracker,TrackerAdapter> trackers;
final Object lock;
private TrackerAdapter trackerAdapter;
public interface Tracker {
void removedService( ServiceReference<UIContributorFactory> reference, UIContributor service );
void addingService( ServiceReference<UIContributorFactory> reference, UIContributor service );
}
private static class TrackerAdapter implements Tracker {
private final ConcurrentHashMap<ServiceReference<UIContributorFactory>,UIContributor> contribs;
private final Tracker tracker;
TrackerAdapter( Tracker tracker ) {
this.tracker = tracker;
contribs = new ConcurrentHashMap<ServiceReference<UIContributorFactory>, UIContributor>();
}
@Override
public void removedService( ServiceReference<UIContributorFactory> reference,
UIContributor service )
{
contribs.remove( reference );
tracker.removedService( reference, service );
}
@Override
public void addingService( final ServiceReference<UIContributorFactory> reference,
final UIContributor service )
{
tracker.addingService( reference, service );
contribs.put( reference, service );
}
UIContributor getContributor( ServiceReference<UIContributorFactory> reference ) {
return contribs.get( reference );
}
}
public UIContributorTrackerService( BundleContext context ) {
Class<UIContributorFactory> type = UIContributorFactory.class;
this.lock = new Object();
this.trackers = new HashMap<Tracker,TrackerAdapter>();
this.contributors = new HashMap<ServiceReference<UIContributorFactory>,UIContributorFactory>();
this.serviceTracker
= new ServiceTracker<UIContributorFactory,UIContributorFactory>( context, type, null ) {
@Override
public UIContributorFactory addingService( ServiceReference<UIContributorFactory> reference ) {
UIContributorFactory result = super.addingService( reference );
Object[] trackerList;
synchronized( lock ) {
contributors.put( reference, result );
trackerList = trackers.values().toArray();
}
for( int i = 0; i < trackerList.length; i++ ) {
( ( Tracker )trackerList[ i ] ).addingService( reference, result.create() );
}
return result;
}
@Override
public void removedService( ServiceReference<UIContributorFactory> reference,
UIContributorFactory service )
{
Object[] trackerList;
synchronized( lock ) {
contributors.remove( reference );
trackerList = trackers.values().toArray();
}
for( int i = 0; i < trackerList.length; i++ ) {
TrackerAdapter tracker = ( TrackerAdapter )trackerList[ i ];
tracker.removedService( reference, tracker.getContributor( reference ) );
}
super.removedService( reference, service );
}
};
serviceTracker.open();
}
@SuppressWarnings( "unchecked" )
public void addTracker( Tracker tracker ) {
Object[] references;
Object[] services;
trackerAdapter = new TrackerAdapter( tracker );
synchronized( lock ) {
trackers.put( tracker, trackerAdapter );
references = contributors.keySet().toArray();
services = contributors.values().toArray();
}
for( int i = 0; i < services.length; i++ ) {
trackerAdapter.addingService( ( ServiceReference<UIContributorFactory> )references[ i ],
( ( UIContributorFactory )services[ i ] ).create() );
}
}
@SuppressWarnings( "unchecked" )
public void removeTracker( Tracker tracker ) {
Object[] references;
Object[] services;
TrackerAdapter trackerAdapter;
synchronized( lock ) {
trackerAdapter = trackers.remove( tracker );
references = contributors.keySet().toArray();
services = contributors.values().toArray();
}
for( int i = 0; i < services.length; i++ ) {
ServiceReference<UIContributorFactory> reference
= ( ServiceReference<UIContributorFactory> )references[ i ];
UIContributor contributor = trackerAdapter.getContributor( reference );
trackerAdapter.removedService( reference, contributor );
}
}
}