FELIX-3186 Applied the patch, with some improvements.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1226520 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
index 8d3a04d..e0b5d3e 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
@@ -243,6 +243,15 @@
}
/**
+ * Creates a new adapter service.
+ * @return the adapter service
+ * @see DependencyManager#createAdapterService(Class, String, String, String, String, String)
+ */
+ public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove, String swap) {
+ return m_manager.createAdapterService(serviceInterface, serviceFilter, add, change, remove, swap);
+ }
+
+ /**
* Creates a new resource adapter service.
*
* @return the resource adapter service
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
index 3da661d..befe82a 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
@@ -391,8 +391,13 @@
* @param add name of the callback method to invoke on add
* @param change name of the callback method to invoke on change
* @param remove name of the callback method to invoke on remove
+ * @param swap name of the callback method to invoke on swap
* @return a service that acts as a factory for generating adapters
*/
+ public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove, String swap) {
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove, swap);
+ }
+
public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove) {
return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove);
}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java
index c77a628..991fe90 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java
@@ -21,7 +21,6 @@
import java.net.URL;
import java.util.Dictionary;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -64,13 +63,12 @@
* Set some service properties to all already instantiated services.
*/
public void setServiceProperties(Dictionary serviceProperties) {
- Map services = new HashMap();
- synchronized (this) {
- services.putAll(m_services);
+ Object[] components;
+ synchronized (m_services) {
+ components = m_services.values().toArray();
}
- Iterator i = services.values().iterator();
- while (i.hasNext()) {
- ((Component) i.next()).setServiceProperties(serviceProperties);
+ for (int i = 0; i < components.length; i++) {
+ ((Component) components[i]).setServiceProperties(serviceProperties);
}
}
@@ -78,96 +76,93 @@
* Remove a StateListener from all already instantiated services.
*/
public void addStateListener(ComponentStateListener listener) {
- Map services = new HashMap();
- synchronized (this) {
- services.putAll(m_services);
+ Object[] components;
+ synchronized (m_services) {
+ components = m_services.values().toArray();
}
- Iterator i = services.values().iterator();
- while (i.hasNext()) {
- ((Component) i.next()).addStateListener(listener);
- }
+ for (int i = 0; i < components.length; i++) {
+ ((Component) components[i]).addStateListener(listener);
+ }
}
/**
* Remove a StateListener from all already instantiated services.
*/
public void removeStateListener(ComponentStateListener listener) {
- Map services = new HashMap();
- synchronized (this) {
- services.putAll(m_services);
+ Object[] components;
+ synchronized (m_services) {
+ components = m_services.values().toArray();
}
- Iterator i = services.values().iterator();
- while (i.hasNext()) {
- ((Component) i.next()).removeStateListener(listener);
- }
+ for (int i = 0; i < components.length; i++) {
+ ((Component) components[i]).removeStateListener(listener);
+ }
}
/**
* Add a Dependency to all already instantiated services.
*/
public void addDependency(Dependency d) {
- Map services = new HashMap();
- synchronized (this) {
- services.putAll(m_services);
+ Object[] components;
+ synchronized (m_services) {
+ components = m_services.values().toArray();
}
- Iterator i = services.values().iterator();
- while (i.hasNext()) {
- ((Component) i.next()).add(d);
- }
+ for (int i = 0; i < components.length; i++) {
+ ((Component) components[i]).add(d);
+ }
}
/**
* Add a Dependency to all already instantiated services.
*/
public void addDependencies(List dependencies) {
- Map services = new HashMap();
- synchronized (this) {
- services.putAll(m_services);
+ Object[] components;
+ synchronized (m_services) {
+ components = m_services.values().toArray();
}
- Iterator i = services.values().iterator();
- while (i.hasNext()) {
- ((Component) i.next()).add(dependencies);
- }
+ for (int i = 0; i < components.length; i++) {
+ ((Component) components[i]).add(dependencies);
+ }
}
/**
* Remove a Dependency from all instantiated services.
*/
public void removeDependency(Dependency d) {
- Map services = new HashMap();
- synchronized (this) {
- services.putAll(m_services);
+ Object[] components;
+ synchronized (m_services) {
+ components = m_services.values().toArray();
}
- Iterator i = services.values().iterator();
- while (i.hasNext()) {
- ((Component) i.next()).remove(d);
- }
+ for (int i = 0; i < components.length; i++) {
+ ((Component) components[i]).remove(d);
+ }
}
// callbacks for FactoryConfigurationAdapterImpl
public void updated(String pid, Dictionary properties) throws ConfigurationException {
try {
Component service;
- synchronized (this) {
+ synchronized (m_services) {
service = (Component) m_services.get(pid);
}
if (service == null) {
service = createService(new Object[] { properties });
- synchronized (this) {
+ synchronized (m_services) {
m_services.put(pid, service);
}
m_manager.add(service);
- } else {
+ }
+ else {
updateService(new Object[] { properties, service });
}
}
-
catch (Throwable t) {
if (t instanceof ConfigurationException) {
throw (ConfigurationException) t;
- } else if (t.getCause() instanceof ConfigurationException) {
+ }
+ else if (t.getCause() instanceof ConfigurationException) {
throw (ConfigurationException) t.getCause();
- } else {
+ }
+ else {
throw new ConfigurationException(null, "Could not create service for ManagedServiceFactory Pid " + pid, t);
}
}
@@ -175,11 +170,10 @@
public void deleted(String pid) {
Component service = null;
- synchronized (this) {
+ synchronized (m_services) {
service = (Component) m_services.remove(pid);
}
- if (service != null)
- {
+ if (service != null) {
m_manager.remove(service);
}
}
@@ -187,60 +181,79 @@
// callbacks for resources
public void added(URL resource) {
Component newService = createService(new Object[] { resource });
- m_services.put(resource, newService);
+ synchronized (m_services) {
+ m_services.put(resource, newService);
+ }
m_manager.add(newService);
}
public void removed(URL resource) {
- Component newService = (Component) m_services.remove(resource);
+ Component newService;
+ synchronized (m_services) {
+ newService = (Component) m_services.remove(resource);
+ }
if (newService == null) {
throw new IllegalStateException("Service should not be null here.");
}
- else {
- m_manager.remove(newService);
- }
+ m_manager.remove(newService);
}
// callbacks for services
public void added(ServiceReference ref, Object service) {
Component newService = createService(new Object[] { ref, service });
- m_services.put(ref, newService);
+ synchronized (m_services) {
+ m_services.put(ref, newService);
+ }
m_manager.add(newService);
}
public void removed(ServiceReference ref, Object service) {
- Component newService = (Component) m_services.remove(ref);
+ Component newService;
+ synchronized (m_services) {
+ newService = (Component) m_services.remove(ref);
+ }
if (newService == null) {
throw new IllegalStateException("Service should not be null here.");
}
- else {
- m_manager.remove(newService);
+ m_manager.remove(newService);
+ }
+
+ public void swapped(ServiceReference oldRef, Object oldService, ServiceReference newRef, Object newService) {
+ synchronized (m_services) {
+ Component service = (Component) m_services.remove(oldRef);
+ m_services.put(newRef, service);
}
}
// callbacks for bundles
public void added(Bundle bundle) {
Component newService = createService(new Object[] { bundle });
- m_services.put(bundle, newService);
+ synchronized (m_services) {
+ m_services.put(bundle, newService);
+ }
m_manager.add(newService);
}
public void removed(Bundle bundle) {
- Component newService = (Component) m_services.remove(bundle);
+ Component newService;
+ synchronized (m_services) {
+ newService = (Component) m_services.remove(bundle);
+ }
if (newService == null) {
throw new IllegalStateException("Service should not be null here.");
}
- else {
- m_manager.remove(newService);
- }
+ m_manager.remove(newService);
}
-
+
public void stop() {
- Iterator i = m_services.values().iterator();
- while (i.hasNext()) {
- m_manager.remove((Component) i.next());
+ Object[] components;
+ synchronized (m_services) {
+ components = m_services.values().toArray();
+ m_services.clear();
}
- m_services.clear();
+ for (int i = 0; i < components.length; i++) {
+ m_manager.remove((Component) components[i]);
+ }
}
public void configureAutoConfigState(Component target, Component source) {
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AdapterServiceImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AdapterServiceImpl.java
index 7bb6f75..b9b39b2 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AdapterServiceImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AdapterServiceImpl.java
@@ -46,13 +46,22 @@
* @param change
* @param remove
*/
- public AdapterServiceImpl(DependencyManager dm, Class adapteeInterface, String adapteeFilter, String autoConfig, String add, String change, String remove) {
+ public AdapterServiceImpl(DependencyManager dm, Class adapteeInterface, String adapteeFilter, String autoConfig, String add, String change, String remove, String swap) {
super(dm.createComponent()); // This service will be filtered by our super class, allowing us to take control.
- m_component.setImplementation(new AdapterImpl(adapteeInterface, adapteeFilter, autoConfig, add, change, remove))
+ m_component.setImplementation(new AdapterImpl(adapteeInterface, adapteeFilter, autoConfig, add, change, remove, swap))
.add(dm.createServiceDependency()
.setService(adapteeInterface, adapteeFilter)
.setAutoConfig(false)
- .setCallbacks("added", "removed"));
+ .setCallbacks("added", null, "removed", "swapped"));
+ }
+
+ public AdapterServiceImpl(DependencyManager dm, Class adapteeInterface, String adapteeFilter, String autoConfig, String add, String change, String remove) {
+ super(dm.createComponent()); // This service will be filtered by our super class, allowing us to take control.
+ m_component.setImplementation(new AdapterImpl(adapteeInterface, adapteeFilter, autoConfig, add, change, remove, null))
+ .add(dm.createServiceDependency()
+ .setService(adapteeInterface, adapteeFilter)
+ .setAutoConfig(false)
+ .setCallbacks("added", null, "removed", "swapped"));
}
public class AdapterImpl extends AbstractDecorator {
@@ -61,14 +70,16 @@
private final String m_add;
private final String m_change;
private final String m_remove;
+ private final String m_swap;
private final String m_autoConfig;
- public AdapterImpl(Class adapteeInterface, String adapteeFilter, String autoConfig, String add, String change, String remove) {
+ public AdapterImpl(Class adapteeInterface, String adapteeFilter, String autoConfig, String add, String change, String remove, String swap) {
m_adapteeInterface = adapteeInterface;
m_adapteeFilter = adapteeFilter;
m_autoConfig = autoConfig;
m_add = add;
m_change = change;
+ m_swap = swap;
m_remove = remove;
}
@@ -95,13 +106,15 @@
List dependencies = m_component.getDependencies();
dependencies.remove(0);
ServiceDependency dependency = m_manager.createServiceDependency()
- .setService(m_adapteeInterface, ref)
+ // create a dependency on both the service id we're adapting and possible aspects for this given service id
+ .setService(m_adapteeInterface, "(|(" + Constants.SERVICE_ID + "=" + ref.getProperty(Constants.SERVICE_ID)
+ + ")(" + DependencyManager.ASPECT + "=" + ref.getProperty(Constants.SERVICE_ID) + "))")
.setRequired(true);
if (m_autoConfig != null) {
dependency.setAutoConfig(m_autoConfig);
}
- if (m_add != null || m_change != null || m_remove != null) {
- dependency.setCallbacks(m_add, m_change, m_remove);
+ if (m_add != null || m_change != null || m_remove != null || m_swap != null) {
+ dependency.setCallbacks(m_add, m_change, m_remove, m_swap);
}
Component service = m_manager.createComponent()
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
index fc3184a..09b20c0 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
@@ -538,7 +538,8 @@
// when a changed callback is specified we might not call the added callback just yet
if (m_callbackSwapped != null) {
handleAspectAwareAdded(dependencyService, reference, service);
- } else {
+ }
+ else {
invoke(dependencyService, reference, service, m_callbackAdded);
}
}
@@ -553,7 +554,6 @@
Integer ranking = ServiceUtil.getRankingAsInteger(reference);
Tuple highestRankedService = null;
synchronized (m_componentByRank) {
- // TODO would be nicer if there was a ServiceUtil method for this...
Long originalServiceId = ServiceUtil.getServiceIdAsLong(reference);
Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
if (componentMap == null) {
@@ -581,11 +581,16 @@
}
}
- private boolean componentIsDependencyManagerFactory(DependencyService dependencyService) {
- // TODO review if we can be a bit smarter with these package name checks
- return dependencyService.getService() != null && dependencyService.getService().getClass().getName().startsWith("org.apache.felix.dm")
- && !dependencyService.getService().getClass().getName().startsWith("org.apache.felix.dm.test");
- }
+ private boolean componentIsDependencyManagerFactory(DependencyService dependencyService) {
+ Object component = dependencyService.getService();
+ if (component != null) {
+ String className = component.getClass().getName();
+ return className.startsWith("org.apache.felix.dm")
+ && !className.startsWith("org.apache.felix.dm.impl.AdapterServiceImpl$AdapterImpl")
+ && !className.startsWith("org.apache.felix.dm.test");
+ }
+ return false;
+ }
private Tuple swapHighestRankedService(DependencyService dependencyService, Long serviceId, ServiceReference newReference, Object newService, Integer newRanking) {
// does a component with a higher ranking exists
@@ -655,7 +660,8 @@
if (removed) {
if (m_callbackSwapped != null) {
handleAspectAwareRemoved(dependencyService, reference, service);
- } else {
+ }
+ else {
invoke(dependencyService, reference, service, m_callbackRemoved);
}
}