1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

[256798] - [services] Services can be called after they are shutdown

This commit is contained in:
Pawel Piech 2009-03-13 22:22:48 +00:00
parent 3770b8065d
commit fd7027d65f

View file

@ -13,9 +13,14 @@ package org.eclipse.cdt.dsf.service;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
/**
@ -42,6 +47,7 @@ import org.osgi.framework.ServiceReference;
*
* @since 1.0
*/
@ConfinedToDsfExecutor("DsfSession.getSession(sessionId).getExecutor()")
public class DsfServicesTracker {
private static String getServiceFilter(String sessionId) {
@ -73,19 +79,69 @@ public class DsfServicesTracker {
}
}
private final String fSessionId;
private boolean fDisposed = false;
private BundleContext fBundleContext;
private Map<ServiceKey,ServiceReference> fServiceReferences = new HashMap<ServiceKey,ServiceReference>();
private Map<ServiceReference,Object> fServices = new HashMap<ServiceReference,Object>();
private String fServiceFilter;
private ServiceListener fListner = new ServiceListener() {
public void serviceChanged(final ServiceEvent event) {
// Only listen to unregister events.
if (event.getType() != ServiceEvent.UNREGISTERING) {
return;
}
// If session is not active anymore, just exit. The tracker should
// soon be disposed.
DsfSession session = DsfSession.getSession(fSessionId);
if (session == null) {
return;
}
if (session.getExecutor().isInExecutorThread()) {
handleUnregisterEvent(event);
} else {
try {
session.getExecutor().execute(new DsfRunnable() {
public void run() {
handleUnregisterEvent(event);
};
});
} catch (RejectedExecutionException e) {
// Same situation as when the session is not active
}
}
}
};
private void handleUnregisterEvent(ServiceEvent event) {
for (Iterator<Map.Entry<ServiceKey, ServiceReference>> itr = fServiceReferences.entrySet().iterator(); itr.hasNext();) {
Map.Entry<ServiceKey, ServiceReference> entry = itr.next();
if ( entry.getValue().equals(event.getServiceReference()) ) {
itr.remove();
}
}
if (fServices.remove(event.getServiceReference()) != null) {
fBundleContext.ungetService(event.getServiceReference());
}
}
/**
* Only constructor.
* @param bundleContext Context of the plugin that the client lives in.
* @param sessionId The DSF session that this tracker will be used for.
*/
public DsfServicesTracker(BundleContext bundleContext, String sessionId) {
fSessionId = sessionId;
fBundleContext = bundleContext;
fServiceFilter = getServiceFilter(sessionId);
try {
fBundleContext.addServiceListener(fListner, fServiceFilter);
} catch (InvalidSyntaxException e) {
assert false : "Invalid session ID syntax"; //$NON-NLS-1$
}
}
/**
@ -100,6 +156,17 @@ public class DsfServicesTracker {
*/
@SuppressWarnings("unchecked")
public ServiceReference getServiceReference(Class serviceClass, String filter) {
if (fDisposed) {
return null;
}
// If the session is not active, all of its services are gone.
DsfSession session = DsfSession.getSession(fSessionId);
if (session == null) {
return null;
}
assert session.getExecutor().isInExecutorThread();
ServiceKey key = new ServiceKey(serviceClass, filter != null ? filter : fServiceFilter);
if (fServiceReferences.containsKey(key)) {
return fServiceReferences.get(key);
@ -162,10 +229,19 @@ public class DsfServicesTracker {
* to avoid leaking OSGI service references.
*/
public void dispose() {
assert !fDisposed;
fDisposed = true;
fBundleContext.removeServiceListener(fListner);
for (Iterator<ServiceReference> itr = fServices.keySet().iterator(); itr.hasNext();) {
fBundleContext.ungetService(itr.next());
itr.remove();
}
fServices.clear();
fServiceReferences.clear();
}
@Override
protected void finalize() throws Throwable {
assert fDisposed;
super.finalize();
}
}