summaryrefslogtreecommitdiffstats
path: root/sca-java-2.x/trunk/modules/node-impl-osgi/src/main
diff options
context:
space:
mode:
authorrfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68>2010-01-27 04:33:47 +0000
committerrfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68>2010-01-27 04:33:47 +0000
commit0c1527f0415fb7d6c06b0ad2a1d4ce73cd728852 (patch)
tree7d0658a2e64c4fdec2957090fc70dfd0efed09d7 /sca-java-2.x/trunk/modules/node-impl-osgi/src/main
parentc2dfd0917dbb0793b7934ccc298e03187e6e3418 (diff)
Fix multiple concurrency related issues
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@903542 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-java-2.x/trunk/modules/node-impl-osgi/src/main')
-rw-r--r--sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointIntrospector.java13
-rw-r--r--sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiHelper.java9
-rw-r--r--sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/TopologyManagerImpl.java122
-rw-r--r--sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java208
-rw-r--r--sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java21
-rw-r--r--sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java1
-rw-r--r--sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchema18
-rw-r--r--sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/org/osgi/service/remoteserviceadmin/osgi-remoteserviceadmin.xsd92
8 files changed, 311 insertions, 173 deletions
diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointIntrospector.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointIntrospector.java
index d27a8708ee..412e119c76 100644
--- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointIntrospector.java
+++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointIntrospector.java
@@ -26,7 +26,6 @@ import static org.osgi.framework.Constants.OBJECTCLASS;
import static org.osgi.framework.Constants.SERVICE_ID;
import java.io.IOException;
-import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -267,6 +266,7 @@ public class EndpointIntrospector {
return contribution;
}
+ /*
public Contribution loadContribution(Bundle bundle, Composite composite) {
try {
URL root = bundle.getEntry("/");
@@ -277,6 +277,7 @@ public class EndpointIntrospector {
throw new ServiceRuntimeException(e);
}
}
+ */
/**
* Generate a contribution that contains the composite for the exported service
@@ -340,16 +341,16 @@ public class EndpointIntrospector {
}
// FIXME: Should we scan the owning bundle to create the SCA contribution?
- Contribution contribution = loadContribution(bundle, composite);
+ Contribution contribution = loadContribution(bundle, id, composite);
return contribution;
}
- private Contribution createContribution(Bundle bundle, String id, Composite composite) {
+ private Contribution loadContribution(Bundle bundle, String id, Composite composite) {
Contribution contribution = contributionFactory.createContribution();
contribution.setClassLoader(OSGiHelper.createBundleClassLoader(bundle));
- contribution.setURI("urn:" + id);
+ contribution.setURI(id);
contribution.setLocation(bundle.getEntry("/").toString());
- contribution.getDeployables().add(composite);
+ deployer.attachDeploymentComposite(contribution, composite, false);
ModelResolver modelResolver = new ExtensibleModelResolver(contribution, modelResolvers, factories);
contribution.setModelResolver(modelResolver);
// compositeProcessor.resolve(composite, modelResolver, new ProcessorContext(registry));
@@ -433,7 +434,7 @@ public class EndpointIntrospector {
componentReference.getBindings().addAll(bindings);
}
- Contribution contribution = loadContribution(bundle, composite);
+ Contribution contribution = loadContribution(bundle, id, composite);
return contribution;
}
diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiHelper.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiHelper.java
index a4b51d9d0c..b0c55fea71 100644
--- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiHelper.java
+++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiHelper.java
@@ -109,8 +109,9 @@ public class OSGiHelper {
if (value == null) {
return Collections.emptyList();
}
- String paths[] = value.trim().split("( |\t|\n|\r|\f|,)+");
- if (paths.length == 0) {
+ value = value.trim();
+ String paths[] = value.split("( |\t|\n|\r|\f|,)+");
+ if ("".equals(value) || paths.length == 0) {
if (defaultValue != null) {
paths = new String[] {defaultValue};
} else {
@@ -119,6 +120,10 @@ public class OSGiHelper {
}
Collection<URL> files = new HashSet<URL>();
for (String path : paths) {
+ if ("".equals(path)) {
+ // Skip empty ones
+ continue;
+ }
if (path.endsWith("/")) {
path = path + "*.xml";
}
diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/TopologyManagerImpl.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/TopologyManagerImpl.java
index 33faa77c84..97c8b345fa 100644
--- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/TopologyManagerImpl.java
+++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/TopologyManagerImpl.java
@@ -23,6 +23,7 @@ import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SERVICE_EX
import static org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_EXPORTED_CONFIGS;
import static org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_IMPORTED;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
@@ -190,10 +191,11 @@ public class TopologyManagerImpl implements ListenerHook, RemoteServiceAdminList
* @see org.osgi.framework.hooks.service.ListenerHook#added(java.util.Collection)
*/
public void added(Collection listeners) {
- synchronized (serviceListeners) {
- try {
+ boolean changed = false;
+ String[] filters = null;
+ try {
+ synchronized (serviceListeners) {
Collection<ListenerInfo> listenerInfos = (Collection<ListenerInfo>)listeners;
- boolean changed = false;
for (ListenerInfo l : listenerInfos) {
if (l.getBundleContext().getBundle().getBundleId() == 0L || l.getBundleContext() == context) {
// Ignore system and tuscany bundle
@@ -217,75 +219,86 @@ public class TopologyManagerImpl implements ListenerHook, RemoteServiceAdminList
}
}
if (changed) {
- updateEndpointListenerScope();
- }
- } catch (Throwable e) {
- logger.log(Level.SEVERE, e.getMessage(), e);
- if (e instanceof Error) {
- throw (Error)e;
- } else if (e instanceof RuntimeException) {
- throw (RuntimeException)e;
- } else {
- // Should not happen
- throw new RuntimeException(e);
+ filters = getFilters();
}
}
+ if (changed) {
+ updateEndpointListenerScope(filters);
+ }
+ } catch (Throwable e) {
+ logger.log(Level.SEVERE, e.getMessage(), e);
+ if (e instanceof Error) {
+ throw (Error)e;
+ } else if (e instanceof RuntimeException) {
+ throw (RuntimeException)e;
+ } else {
+ // Should not happen
+ throw new RuntimeException(e);
+ }
}
}
- private void updateEndpointListenerScope() {
- Set<String> filterSet = serviceListeners.keySet();
-
+ private void updateEndpointListenerScope(String[] filters) {
Dictionary<String, Object> props = new Hashtable<String, Object>();
- props.put(ENDPOINT_LISTENER_SCOPE, filterSet.toArray(new String[filterSet.size()]));
+ props.put(ENDPOINT_LISTENER_SCOPE, filters);
endpointListener.setProperties(props);
}
+ private String[] getFilters() {
+ Set<String> filterSet = serviceListeners.keySet();
+ String[] filters = filterSet.toArray(new String[filterSet.size()]);
+ return filters;
+ }
+
private CollectionMap<Class<?>, ListenerInfo> findServiceListeners(EndpointDescription endpointDescription,
String matchedFilter) {
+ Collection<ListenerInfo> listeners = null;
synchronized (serviceListeners) {
// First find all the listeners that have the matching filter
- Collection<ListenerInfo> listeners = serviceListeners.get(matchedFilter);
+ listeners = serviceListeners.get(matchedFilter);
if (listeners == null) {
return null;
}
+ listeners = new ArrayList<ListenerInfo>(listeners);
+ }
- // Try to partition the listeners by the interface classes
- List<String> interfaceNames = endpointDescription.getInterfaces();
- CollectionMap<Class<?>, ListenerInfo> interfaceToListeners = new CollectionMap<Class<?>, ListenerInfo>();
- for (String i : interfaceNames) {
- for (Iterator<ListenerInfo> it = listeners.iterator(); it.hasNext();) {
+ // Try to partition the listeners by the interface classes
+ List<String> interfaceNames = endpointDescription.getInterfaces();
+ CollectionMap<Class<?>, ListenerInfo> interfaceToListeners = new CollectionMap<Class<?>, ListenerInfo>();
+ for (String i : interfaceNames) {
+ for (Iterator<ListenerInfo> it = listeners.iterator(); it.hasNext();) {
+ try {
+ ListenerInfo listener = it.next();
+ if (listener.isRemoved()) {
+ it.remove();
+ continue;
+ }
try {
- ListenerInfo listener = it.next();
- if (listener.isRemoved()) {
- it.remove();
- continue;
- }
- try {
- Class<?> interfaceClass = listener.getBundleContext().getBundle().loadClass(i);
- interfaceToListeners.putValue(interfaceClass, listener);
- } catch (IllegalStateException e) {
- logger.log(Level.WARNING, e.getMessage(), e);
- // Ignore the exception
- }
- } catch (ClassNotFoundException e) {
- // Ignore the listener as it cannot load the interface class
+ // The classloading can be synchronzed against the serviceListeners
+ Class<?> interfaceClass = listener.getBundleContext().getBundle().loadClass(i);
+ interfaceToListeners.putValue(interfaceClass, listener);
+ } catch (IllegalStateException e) {
+ logger.log(Level.WARNING, e.getMessage(), e);
+ // Ignore the exception
}
+ } catch (ClassNotFoundException e) {
+ // Ignore the listener as it cannot load the interface class
}
}
- return interfaceToListeners;
}
+ return interfaceToListeners;
}
/**
* @see org.osgi.framework.hooks.service.ListenerHook#removed(java.util.Collection)
*/
public void removed(Collection listeners) {
- synchronized (serviceListeners) {
- try {
+ boolean changed = false;
+ String[] filters = null;
+ try {
+ synchronized (serviceListeners) {
Collection<ListenerInfo> listenerInfos = (Collection<ListenerInfo>)listeners;
- boolean changed = false;
for (ListenerInfo l : listenerInfos) {
if (registration != null && l.getBundleContext() != context) {
String key = l.getFilter();
@@ -298,19 +311,22 @@ public class TopologyManagerImpl implements ListenerHook, RemoteServiceAdminList
}
}
if (changed) {
- updateEndpointListenerScope();
- }
- } catch (Throwable e) {
- logger.log(Level.SEVERE, e.getMessage(), e);
- if (e instanceof Error) {
- throw (Error)e;
- } else if (e instanceof RuntimeException) {
- throw (RuntimeException)e;
- } else {
- // Should not happen
- throw new RuntimeException(e);
+ filters = getFilters();
}
}
+ if (changed) {
+ updateEndpointListenerScope(filters);
+ }
+ } catch (Throwable e) {
+ logger.log(Level.SEVERE, e.getMessage(), e);
+ if (e instanceof Error) {
+ throw (Error)e;
+ } else if (e instanceof RuntimeException) {
+ throw (RuntimeException)e;
+ } else {
+ // Should not happen
+ throw new RuntimeException(e);
+ }
}
}
diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java
index 886e79197d..dbdbbaead8 100644
--- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java
+++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java
@@ -19,15 +19,12 @@
package org.apache.tuscany.sca.osgi.service.discovery.impl;
-import static org.osgi.service.remoteserviceadmin.EndpointListener.ENDPOINT_LISTENER_SCOPE;
-
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Dictionary;
-import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
-import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
@@ -35,9 +32,11 @@ import java.util.logging.Logger;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.LifeCycleListener;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
import org.apache.tuscany.sca.node.NodeFactory;
import org.apache.tuscany.sca.node.impl.NodeFactoryImpl;
import org.apache.tuscany.sca.osgi.remoteserviceadmin.impl.OSGiHelper;
+import org.apache.tuscany.sca.work.WorkScheduler;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
@@ -60,13 +59,13 @@ public abstract class AbstractDiscoveryService implements Discovery, LifeCycleLi
protected BundleContext context;
protected ExtensionPointRegistry registry;
+ private WorkScheduler workScheduler;
- private Map<String, List<EndpointListener>> filtersToListeners = new HashMap<String, List<EndpointListener>>();
- // this is effectively a set which allows for multiple service descriptions with the
- // same interface name but different properties and takes care of itself with respect to concurrency
- protected Map<EndpointDescription, Bundle> endpointDescriptions = new ConcurrentHashMap<EndpointDescription, Bundle>();
private Map<EndpointListener, Collection<String>> listenersToFilters =
- new HashMap<EndpointListener, Collection<String>>();
+ new ConcurrentHashMap<EndpointListener, Collection<String>>();
+
+ protected Map<EndpointDescription, Bundle> endpointDescriptions =
+ new ConcurrentHashMap<EndpointDescription, Bundle>();
private ServiceTracker trackerTracker;
public AbstractDiscoveryService(BundleContext context) {
@@ -75,6 +74,10 @@ public abstract class AbstractDiscoveryService implements Discovery, LifeCycleLi
}
public void start() {
+ getExtensionPointRegistry();
+ UtilityExtensionPoint utilityExtensionPoint = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ this.workScheduler = utilityExtensionPoint.getUtility(WorkScheduler.class);
+
// track the registration of EndpointListener
trackerTracker = new ServiceTracker(this.context, EndpointListener.class.getName(), null) {
public Object addingService(ServiceReference reference) {
@@ -122,66 +125,52 @@ public abstract class AbstractDiscoveryService implements Discovery, LifeCycleLi
return props;
}
- private synchronized void cacheTracker(ServiceReference reference, Object service) {
+ private void cacheTracker(ServiceReference reference, Object service) {
if (service instanceof EndpointListener) {
EndpointListener listener = (EndpointListener)service;
- Collection<String> filters =
- addTracker(reference, listener, ENDPOINT_LISTENER_SCOPE, filtersToListeners, listenersToFilters);
-
- triggerCallbacks(null, filters, listener, true);
+ Collection<String> filters = null;
+ Collection<EndpointDescription> endpoints = null;
+ synchronized (this) {
+ filters = addTracker(reference, listener, EndpointListener.ENDPOINT_LISTENER_SCOPE);
+ // Take a snapshot of the endpoints
+ triggerCallbacks(null, filters, listener);
+ }
}
}
- private synchronized void clearTracker(Object service) {
+ private void clearTracker(Object service) {
if (service instanceof EndpointListener) {
- removeTracker((EndpointListener)service, filtersToListeners, listenersToFilters);
+ synchronized (this) {
+ removeTracker((EndpointListener)service);
+ }
}
}
- private synchronized void updateTracker(ServiceReference reference, Object service) {
+ private void updateTracker(ServiceReference reference, Object service) {
if (service instanceof EndpointListener) {
EndpointListener listener = (EndpointListener)service;
- if (logger.isLoggable(Level.FINE)) {
- logger.fine("updating listener: " + listener);
+ Collection<String> oldFilters = null;
+ Collection<String> newFilters = null;
+ Collection<EndpointDescription> endpoints = null;
+ synchronized (this) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("updating listener: " + listener);
+ }
+ oldFilters = removeTracker(listener);
+ newFilters = addTracker(reference, listener, EndpointListener.ENDPOINT_LISTENER_SCOPE);
+ triggerCallbacks(oldFilters, newFilters, listener);
}
- Collection<String> oldFilters = removeTracker(listener, filtersToListeners, listenersToFilters);
-
- Collection<String> newFilters =
- addTracker(reference, listener, ENDPOINT_LISTENER_SCOPE, filtersToListeners, listenersToFilters);
-
- triggerCallbacks(oldFilters, newFilters, listener, true);
}
}
private void triggerCallbacks(Collection<String> oldInterest,
Collection<String> newInterest,
- EndpointListener listener,
- boolean isFilter) {
+ EndpointListener listener) {
// compute delta between old & new interfaces/filters and
// trigger callbacks for any entries in servicesInfo that
// match any *additional* interface/filters
- Collection<String> deltaInterest = new ArrayList<String>();
- if (newInterest != null && !newInterest.isEmpty()) {
- if (oldInterest == null || oldInterest.isEmpty()) {
- deltaInterest.addAll(newInterest);
- } else {
- Iterator<String> i = newInterest.iterator();
- while (i.hasNext()) {
- String next = (String)i.next();
- if (!oldInterest.contains(next)) {
- deltaInterest.add(next);
- }
- }
- }
- }
+ Collection<String> deltaInterest = getDelta(oldInterest, newInterest);
- if (logger.isLoggable(Level.FINE)) {
- if (endpointDescriptions.size() > 0) {
- logger.fine("search for matches to trigger callbacks with delta: " + deltaInterest);
- } else {
- logger.fine("nothing to search for matches to trigger callbacks with delta: " + deltaInterest);
- }
- }
Iterator<String> i = deltaInterest.iterator();
while (i.hasNext()) {
String next = i.next();
@@ -191,21 +180,74 @@ public abstract class AbstractDiscoveryService implements Discovery, LifeCycleLi
}
}
- private void triggerCallbacks(EndpointListener listener, String matchedFilter, EndpointDescription sd, int type) {
+ private Collection<String> getDelta(Collection<String> oldInterest, Collection<String> newInterest) {
+ if (newInterest == null) {
+ newInterest = Collections.emptySet();
+ }
+
+ Collection<String> deltaInterest = new ArrayList<String>(newInterest);
+ if (oldInterest == null) {
+ oldInterest = Collections.emptySet();
+ }
+ deltaInterest.removeAll(oldInterest);
+ return deltaInterest;
+ }
+
+ /**
+ * Notify the endpoint listener
+ * @param listener
+ * @param matchedFilter
+ * @param endpoint
+ * @param type
+ */
+ private static void notify(EndpointListener listener, String matchedFilter, EndpointDescription endpoint, int type) {
switch (type) {
case ADDED:
- listener.endpointAdded(sd, matchedFilter);
+ listener.endpointAdded(endpoint, matchedFilter);
break;
case REMOVED:
- listener.endpointRemoved(sd, matchedFilter);
+ listener.endpointRemoved(endpoint, matchedFilter);
break;
case MODIFIED:
- listener.endpointRemoved(sd, matchedFilter);
- listener.endpointAdded(sd, matchedFilter);
+ listener.endpointRemoved(endpoint, matchedFilter);
+ listener.endpointAdded(endpoint, matchedFilter);
break;
}
}
+ private static class Notifier implements Runnable {
+ private EndpointListener listener;
+ private String matchedFilter;
+ private EndpointDescription endpoint;
+ private int type;
+
+ /**
+ * @param listener
+ * @param matchedFilter
+ * @param endpoint
+ * @param type
+ */
+ public Notifier(EndpointListener listener, String matchedFilter, EndpointDescription endpoint, int type) {
+ super();
+ this.listener = listener;
+ this.matchedFilter = matchedFilter;
+ this.endpoint = endpoint;
+ this.type = type;
+ }
+
+ public void run() {
+ AbstractDiscoveryService.notify(listener, matchedFilter, endpoint, type);
+ }
+ }
+
+ private void triggerCallbacks(EndpointListener listener,
+ String matchedFilter,
+ EndpointDescription endpoint,
+ int type) {
+ workScheduler.scheduleWork(new Notifier(listener, matchedFilter, endpoint, type));
+
+ }
+
private boolean filterMatches(String filterValue, EndpointDescription sd) {
Filter filter = OSGiHelper.createFilter(context, filterValue);
Hashtable<String, Object> props = new Hashtable<String, Object>(sd.getProperties());
@@ -215,63 +257,25 @@ public abstract class AbstractDiscoveryService implements Discovery, LifeCycleLi
return filter != null ? filter.match(props) : false;
}
- static Collection<String> removeTracker(EndpointListener listener,
- Map<String, List<EndpointListener>> forwardMap,
- Map<EndpointListener, Collection<String>> reverseMap) {
- Collection<String> collection = reverseMap.get(listener);
- if (collection != null && !collection.isEmpty()) {
- reverseMap.remove(listener);
- Iterator<String> i = collection.iterator();
- while (i.hasNext()) {
- String element = i.next();
- if (forwardMap.containsKey(element)) {
- forwardMap.get(element).remove(listener);
- } else {
- // if the element wasn't on the forwardmap, its a new element and
- // shouldn't be returned as part of the collection of old ones
- i.remove();
- }
- }
- }
- return collection;
+ private Collection<String> removeTracker(EndpointListener listener) {
+ return listenersToFilters.remove(listener);
}
- @SuppressWarnings("unchecked")
- static Collection<String> addTracker(ServiceReference reference,
- EndpointListener listener,
- String property,
- Map<String, List<EndpointListener>> forwardMap,
- Map<EndpointListener, Collection<String>> reverseMap) {
+ private Collection<String> addTracker(ServiceReference reference, EndpointListener listener, String property) {
Collection<String> collection = OSGiHelper.getStringCollection(reference, property);
- if (logger.isLoggable(Level.FINE)) {
- logger.fine("adding listener: " + listener
- + " collection: "
- + collection
- + " registered against prop: "
- + property);
- }
if (collection != null && !collection.isEmpty()) {
- reverseMap.put(listener, new ArrayList<String>(collection));
- Iterator<String> i = collection.iterator();
- while (i.hasNext()) {
- String element = i.next();
- if (forwardMap.containsKey(element)) {
- forwardMap.get(element).add(listener);
- } else {
- List<EndpointListener> trackerList = new ArrayList<EndpointListener>();
- trackerList.add(listener);
- forwardMap.put(element, trackerList);
- }
- }
+ listenersToFilters.put(listener, new ArrayList<String>(collection));
}
return collection;
}
- protected synchronized void endpointChanged(EndpointDescription sd, int type) {
- for (Map.Entry<EndpointListener, Collection<String>> entry : listenersToFilters.entrySet()) {
- for (String filter : entry.getValue()) {
- if (filterMatches(filter, sd)) {
- triggerCallbacks(entry.getKey(), filter, sd, type);
+ protected void endpointChanged(EndpointDescription sd, int type) {
+ synchronized (this) {
+ for (Map.Entry<EndpointListener, Collection<String>> entry : listenersToFilters.entrySet()) {
+ for (String filter : entry.getValue()) {
+ if (filterMatches(filter, sd)) {
+ triggerCallbacks(entry.getKey(), filter, sd, type);
+ }
}
}
}
diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java
index a02be672a2..c9c4cb6a69 100644
--- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java
+++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java
@@ -49,7 +49,6 @@ public class DomainDiscoveryService extends AbstractDiscoveryService implements
public void start() {
super.start();
- getExtensionPointRegistry();
this.domainRegistryFactory =
registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(DomainRegistryFactory.class);
domainRegistryFactory.addListener(this);
@@ -80,7 +79,7 @@ public class DomainDiscoveryService extends AbstractDiscoveryService implements
}
}
- public synchronized void endpointAdded(Endpoint endpoint) {
+ public void endpointAdded(Endpoint endpoint) {
Implementation impl = endpoint.getComponent().getImplementation();
if (!(impl instanceof OSGiImplementation)) {
return;
@@ -94,20 +93,24 @@ public class DomainDiscoveryService extends AbstractDiscoveryService implements
bundleContext = bundle != null ? bundle.getBundleContext() : null;
}
- // Notify the endpoint listeners
- EndpointDescription description = createEndpointDescription(bundleContext, endpoint);
- // Set the owning bundle to runtime bundle to avoid NPE
+ // Notify the endpoint listeners
+ EndpointDescription description = createEndpointDescription(bundleContext, endpoint);
+ // Set the owning bundle to runtime bundle to avoid NPE
+ synchronized (this) {
endpointDescriptions.put(description, context.getBundle());
endpointChanged(description, ADDED);
+ }
}
- public synchronized void endpointRemoved(Endpoint endpoint) {
- EndpointDescription description = createEndpointDescription(context, endpoint);
+ public void endpointRemoved(Endpoint endpoint) {
+ EndpointDescription description = createEndpointDescription(context, endpoint);
+ synchronized (this) {
endpointDescriptions.remove(description);
endpointChanged(description, REMOVED);
+ }
}
- public synchronized void endpointUpdated(Endpoint oldEndpoint, Endpoint newEndpoint) {
+ public void endpointUpdated(Endpoint oldEndpoint, Endpoint newEndpoint) {
// FIXME: This is a quick and dirty way for the update
endpointRemoved(oldEndpoint);
endpointAdded(newEndpoint);
@@ -124,7 +127,7 @@ public class DomainDiscoveryService extends AbstractDiscoveryService implements
super.stop();
}
}
-
+
@Override
protected Dictionary<String, Object> getProperties() {
Dictionary<String, Object> props = super.getProperties();
diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java
index 56a830a1e6..a31d05acf0 100644
--- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java
+++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java
@@ -63,7 +63,6 @@ public class LocalDiscoveryService extends AbstractDiscoveryService implements B
public void start() {
super.start();
- getExtensionPointRegistry();
UtilityExtensionPoint utilities = this.registry.getExtensionPoint(UtilityExtensionPoint.class);
this.deployer = utilities.getUtility(Deployer.class);
diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchema b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchema
new file mode 100644
index 0000000000..1991eba409
--- /dev/null
+++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchema
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+org/osgi/service/remoteserviceadmin/osgi-remoteserviceadmin.xsd
diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/org/osgi/service/remoteserviceadmin/osgi-remoteserviceadmin.xsd b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/org/osgi/service/remoteserviceadmin/osgi-remoteserviceadmin.xsd
new file mode 100644
index 0000000000..dc88df965c
--- /dev/null
+++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/org/osgi/service/remoteserviceadmin/osgi-remoteserviceadmin.xsd
@@ -0,0 +1,92 @@
+<!--
+ *
+ * Copyright (c) OSGi Alliance (2008, 2010). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+-->
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:rsa="http://www.osgi.org/xmlns/rsa/v1.0.0"
+ targetNamespace="http://www.osgi.org/xmlns/rsa/v1.0.0" elementFormDefault="qualified" version="1.0.0">
+ <element name="endpoint-descriptions" type="rsa:Tendpoint-descriptions" />
+ <complexType name="Tendpoint-descriptions">
+ <sequence>
+ <element name="endpoint-description" type="rsa:Tendpoint-description" minOccurs="1" maxOccurs="unbounded" />
+ <any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
+ </sequence>
+ <anyAttribute />
+ </complexType>
+ <complexType name="Tendpoint-description">
+ <sequence>
+ <element name="property" type="rsa:Tproperty" minOccurs="1" maxOccurs="unbounded" />
+ <any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
+ </sequence>
+ <anyAttribute />
+ </complexType>
+ <complexType name="Tproperty" mixed="true">
+ <sequence>
+ <choice minOccurs="0" maxOccurs="1">
+ <element name="array" type="rsa:Tmulti-value" />
+ <element name="list" type="rsa:Tmulti-value" />
+ <element name="set" type="rsa:Tmulti-value" />
+ <element name="xml" type="rsa:Txml" />
+ </choice>
+ <any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
+ </sequence>
+ <attribute name="name" type="string" use="required" />
+ <attribute name="value" type="string" use="optional" />
+ <attribute name="value-type" type="rsa:Tvalue-types" default="String" use="optional" />
+ <anyAttribute />
+ </complexType>
+ <complexType name="Tmulti-value">
+ <sequence>
+ <element name="value" minOccurs="0" maxOccurs="unbounded" type="rsa:Tvalue" />
+ <any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
+ </sequence>
+ <anyAttribute />
+ </complexType>
+ <complexType name="Tvalue" mixed="true">
+ <sequence>
+ <element name="xml" minOccurs="0" maxOccurs="1" type="rsa:Txml" />
+ <any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
+ </sequence>
+ <anyAttribute />
+ </complexType>
+ <simpleType name="Tvalue-types">
+ <restriction base="string">
+ <enumeration value="String" />
+ <enumeration value="long" />
+ <enumeration value="Long" />
+ <enumeration value="double" />
+ <enumeration value="Double" />
+ <enumeration value="float" />
+ <enumeration value="Float" />
+ <enumeration value="int" />
+ <enumeration value="Integer" />
+ <enumeration value="byte" />
+ <enumeration value="Byte" />
+ <enumeration value="char" />
+ <enumeration value="Character" />
+ <enumeration value="boolean" />
+ <enumeration value="Boolean" />
+ <enumeration value="short" />
+ <enumeration value="Short" />
+ </restriction>
+ </simpleType>
+ <complexType name="Txml">
+ <sequence>
+ <any namespace="##other" minOccurs="1" maxOccurs="1" processContents="lax" />
+ </sequence>
+ <anyAttribute />
+ </complexType>
+ <attribute name="must-understand" type="boolean" default="false" />
+</schema> \ No newline at end of file