Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2008-12-19 21:10:00 +0000
committerThomas Watson2008-12-19 21:10:00 +0000
commitc0bf408b216d2511900a0e48b4185d50fb6017e2 (patch)
treecc91e6e2a43514f5088471048125db7503fed0b8 /bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeServiceTracker.java
parentf1a814066412e3ae14174179eea848452496bb34 (diff)
downloadrt.equinox.framework-c0bf408b216d2511900a0e48b4185d50fb6017e2.tar.gz
rt.equinox.framework-c0bf408b216d2511900a0e48b4185d50fb6017e2.tar.xz
rt.equinox.framework-c0bf408b216d2511900a0e48b4185d50fb6017e2.zip
Bug 254021 Implement new LinkBundleFactory service (rfc 138)
Diffstat (limited to 'bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeServiceTracker.java')
-rw-r--r--bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeServiceTracker.java178
1 files changed, 178 insertions, 0 deletions
diff --git a/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeServiceTracker.java b/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeServiceTracker.java
new file mode 100644
index 000000000..a9a449b40
--- /dev/null
+++ b/bundles/org.eclipse.osgi/core/composite/org/eclipse/osgi/internal/composite/CompositeServiceTracker.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.composite;
+
+import java.util.*;
+import org.eclipse.osgi.util.ManifestElement;
+import org.osgi.framework.*;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+class CompositeServiceTracker implements ServiceTrackerCustomizer {
+ final BundleContext sourceContext;
+ final BundleContext targetContext;
+ final ServiceTracker[] trackers;
+ final String[] filters;
+ /* @GuardedBy("serviceComposites") */
+ final HashMap serviceComposites = new HashMap();
+
+ public CompositeServiceTracker(BundleContext sourceContext, BundleContext targetContext, String serviceFilters) {
+ this.sourceContext = sourceContext;
+ this.targetContext = targetContext;
+ filters = ManifestElement.getArrayFromList(serviceFilters, ","); //$NON-NLS-1$
+ trackers = new ServiceTracker[filters.length];
+ }
+
+ synchronized void open() {
+ for (int i = 0; i < trackers.length; i++) {
+ try {
+ trackers[i] = new ServiceTracker(sourceContext, sourceContext.createFilter(filters[i]), this);
+ trackers[i].open();
+ } catch (InvalidSyntaxException e) {
+ // TODO log
+ // we will skip this filter; note that trackers may have null entries
+ }
+ }
+ }
+
+ synchronized void close() {
+ for (int i = 0; i < trackers.length; i++) {
+ if (trackers[i] != null)
+ trackers[i].close();
+ }
+ }
+
+ public Object addingService(ServiceReference reference) {
+ ServiceLink serviceLink;
+ int useCount;
+ synchronized (serviceComposites) {
+ serviceLink = (ServiceLink) serviceComposites.get(reference);
+ if (serviceLink == null) {
+ serviceLink = new ServiceLink(reference);
+ serviceComposites.put(reference, serviceLink);
+ }
+ useCount = serviceLink.incrementUse();
+ }
+ // register service outside of the sync block
+ if (useCount == 1)
+ serviceLink.register();
+ return serviceLink;
+ }
+
+ public void modifiedService(ServiceReference reference, Object service) {
+ ServiceLink serviceLink = (ServiceLink) service;
+ Dictionary serviceProps = null;
+ synchronized (serviceComposites) {
+ serviceProps = serviceLink.getRefreshProperties();
+ }
+ // set service properties out side the sync block
+ if (serviceProps != null)
+ ((ServiceLink) service).setServiceProperties(serviceProps);
+ }
+
+ public void removedService(ServiceReference reference, Object service) {
+ int useCount;
+ synchronized (serviceComposites) {
+ useCount = ((ServiceLink) service).decrementUse();
+ if (useCount == 0)
+ serviceComposites.remove(reference);
+ }
+ // unregister outside the sync block
+ if (useCount == 0)
+ ((ServiceLink) service).unregister();
+ }
+
+ class ServiceLink implements ServiceFactory {
+ private final ServiceReference reference;
+ private volatile ServiceRegistration registration;
+ /* @GuardedBy("this") */
+ private Object service;
+ /* @GuardedBy("serviceLinks") */
+ private int useCount;
+
+ ServiceLink(ServiceReference reference) {
+ this.reference = reference;
+ }
+
+ /* @GuardedBy("serviceLinks") */
+ Dictionary getRefreshProperties() {
+ Dictionary result = getServiceProperties();
+ if (useCount <= 1)
+ return result;
+ // need to do an expensive properties check to avoid multiple registration property changes
+ String[] originalKeys = registration.getReference().getPropertyKeys();
+ for (int i = 0; i < originalKeys.length; i++) {
+ if (!Constants.OBJECTCLASS.equals(originalKeys[i]) && !Constants.SERVICE_ID.equals(originalKeys[i]))
+ // identity compare is done on purpose here to catch any kind of change
+ if (registration.getReference().getProperty(originalKeys[i]) != result.get(originalKeys[i]))
+ return result;
+ }
+ for (Enumeration eKeys = result.keys(); eKeys.hasMoreElements();) {
+ String key = (String) eKeys.nextElement();
+ if (!Constants.OBJECTCLASS.equals(key) && !Constants.SERVICE_ID.equals(key))
+ // identity compare is done on purpose here to catch any kind of change
+ if (result.get(key) != registration.getReference().getProperty(key))
+ return result;
+ }
+ return null;
+ }
+
+ /* @GuardedBy("serviceLinks") */
+ int decrementUse() {
+ return --useCount;
+ }
+
+ /* @GuardedBy("serviceLinks") */
+ int incrementUse() {
+ return ++useCount;
+ }
+
+ /* @GuardedBy("serviceLinks") */
+ int getUse() {
+ return useCount;
+ }
+
+ void setServiceProperties(Dictionary props) {
+ ServiceRegistration current = registration;
+ if (current != null)
+ current.setProperties(props);
+ }
+
+ void register() {
+ Dictionary props = getServiceProperties();
+ registration = targetContext.registerService((String[]) props.get(Constants.OBJECTCLASS), this, props);
+ }
+
+ void unregister() {
+ ServiceRegistration current = registration;
+ if (current != null)
+ current.unregister();
+ }
+
+ private Dictionary getServiceProperties() {
+ String[] keys = reference.getPropertyKeys();
+ Hashtable serviceProps = new Hashtable(keys.length);
+ for (int i = 0; i < keys.length; i++)
+ serviceProps.put(keys[i], reference.getProperty(keys[i]));
+ return serviceProps;
+ }
+
+ public synchronized Object getService(Bundle bundle, ServiceRegistration reg) {
+ if (service == null)
+ service = sourceContext.getService(reference);
+ return service;
+ }
+
+ public void ungetService(Bundle bundle, ServiceRegistration reg, Object serv) {
+ // nothing
+ }
+ }
+}

Back to the top