FELIX-987 implemented the request as documented, FELIX-992 merged the patch, resolved some issues findbugs found in the code.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@759760 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/pom.xml b/dependencymanager/pom.xml
index 17fdefb..4e6ea3d 100644
--- a/dependencymanager/pom.xml
+++ b/dependencymanager/pom.xml
@@ -58,7 +58,6 @@
<Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
<Export-Package>org.apache.felix.dependencymanager</Export-Package>
<Import-Package>!org.apache.felix.dependencymanager,*</Import-Package>
- <Include-Resource>META-INF/LICENSE=LICENSE,META-INF/NOTICE=NOTICE,org/osgi/util/tracker/=target/classes/org/osgi/util/tracker</Include-Resource>
</instructions>
</configuration>
</plugin>
diff --git a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/Logger.java b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/Logger.java
index f7409d3..ab85366 100644
--- a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/Logger.java
+++ b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/Logger.java
@@ -143,7 +143,7 @@
* there will never be a log service present since the system bundle is
* started before every other bundle.
*/
- private void startListeningForLogService() {
+ private synchronized void startListeningForLogService() {
// Add a service listener for log services.
try {
m_context.addServiceListener(this, "(objectClass=org.osgi.service.log.LogService)");
diff --git a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
index 43946ff..b7d40d3 100644
--- a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
+++ b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
@@ -22,15 +22,17 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
+import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
/**
* Service dependency that can track an OSGi service.
@@ -40,14 +42,14 @@
public class ServiceDependency implements Dependency, ServiceTrackerCustomizer, ServiceComponentDependency {
private boolean m_isRequired;
private Service m_service;
- private ServiceTracker m_tracker;
+ private volatile ServiceTracker m_tracker;
private BundleContext m_context;
private boolean m_isAvailable;
- private Class m_trackedServiceName;
+ private volatile Class m_trackedServiceName;
private Object m_nullObject;
- private String m_trackedServiceFilter;
- private ServiceReference m_trackedServiceReference;
- private boolean m_isStarted;
+ private volatile String m_trackedServiceFilter;
+ private volatile ServiceReference m_trackedServiceReference;
+ private volatile boolean m_isStarted;
private Object m_callbackInstance;
private String m_callbackAdded;
private String m_callbackChanged;
@@ -83,6 +85,78 @@
}
};
+ // Class used to wrap service properties behing a Map
+ private final static class ServicePropertiesMapEntry implements Map.Entry {
+ private final String m_key;
+ private Object m_value;
+
+ public ServicePropertiesMapEntry(String key, Object value) {
+ m_key = key;
+ m_value = value;
+ }
+
+ public Object getKey() {
+ return m_key;
+ }
+
+ public Object getValue() {
+ return m_value;
+ }
+
+ public String toString() {
+ return m_key + "=" + m_value;
+ }
+
+ public Object setValue(Object value) {
+ Object oldValue = m_value;
+ m_value = value;
+ return oldValue;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof Map.Entry)) {
+ return false;
+ }
+ Map.Entry e = (Map.Entry) o;
+ return eq(m_key, e.getKey()) && eq(m_value, e.getValue());
+ }
+
+ public int hashCode() {
+ return ((m_key == null) ? 0 : m_key.hashCode()) ^ ((m_value == null) ? 0 : m_value.hashCode());
+ }
+
+ private static final boolean eq(Object o1, Object o2) {
+ return (o1 == null ? o2 == null : o1.equals(o2));
+ }
+ }
+
+ // Class used to wrap service properties behing a Map
+ private final static class ServicePropertiesMap extends AbstractMap {
+ private final ServiceReference m_ref;
+
+ public ServicePropertiesMap(ServiceReference ref) {
+ m_ref = ref;
+ }
+
+ public Object get(Object key) {
+ return m_ref.getProperty(key.toString());
+ }
+
+ public int size() {
+ return m_ref.getPropertyKeys().length;
+ }
+
+ public Set entrySet() {
+ Set set = new HashSet();
+ String[] keys = m_ref.getPropertyKeys();
+ for (int i = 0; i < keys.length; i++) {
+ set.add(new ServicePropertiesMapEntry(keys[i], m_ref.getProperty(keys[i])));
+ }
+ return set;
+ }
+ }
+
+
/**
* Creates a new service dependency.
*
@@ -377,8 +451,8 @@
trackedServiceName = m_trackedServiceName;
}
done = invokeMethod(instance, currentClazz, methodName,
- new Class[][] {{ServiceReference.class, trackedServiceName}, {ServiceReference.class, Object.class}, {ServiceReference.class}, {trackedServiceName}, {Object.class}, {}},
- new Object[][] {{reference, service}, {reference, service}, {reference}, {service}, {service}, {}},
+ new Class[][] {{ServiceReference.class, trackedServiceName}, {ServiceReference.class, Object.class}, {ServiceReference.class}, {trackedServiceName}, {Object.class}, {}, {Map.class}},
+ new Object[][] {{reference, service}, {reference, service}, {reference}, {service}, {service}, {}, {new ServicePropertiesMap(reference)}},
false);
if (!done) {
currentClazz = currentClazz.getSuperclass();
diff --git a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
index a50dfac..3b8204d 100644
--- a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
+++ b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
@@ -26,9 +26,11 @@
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Properties;
import org.osgi.framework.BundleContext;
@@ -86,6 +88,8 @@
// internal logging
private final Logger m_logger;
private ServiceRegistration m_serviceRegistration;
+ private Map m_autoConfig = new HashMap();
+ private Map m_autoConfigInstance = new HashMap();
public ServiceImpl(BundleContext context, DependencyManager manager, Logger logger) {
m_logger = logger;
@@ -97,6 +101,9 @@
m_callbackStop = "stop";
m_callbackDestroy = "destroy";
m_implementation = null;
+ m_autoConfig.put(BundleContext.class, Boolean.TRUE);
+ m_autoConfig.put(ServiceRegistration.class, Boolean.TRUE);
+ m_autoConfig.put(DependencyManager.class, Boolean.TRUE);
}
private void calculateStateChanges(final State oldState, final State newState) {
@@ -575,13 +582,15 @@
if (factory == null) {
m_logger.log(Logger.LOG_ERROR, "Factory cannot be null.");
}
- try {
- Method m = factory.getClass().getDeclaredMethod(m_instanceFactoryCreateMethod, null);
- m_serviceInstance = m.invoke(factory, null);
- }
- catch (Exception e) {
- m_logger.log(Logger.LOG_ERROR, "Could not create service instance using factory " + factory + " method " + m_instanceFactoryCreateMethod + ".", e);
- }
+ else {
+ try {
+ Method m = factory.getClass().getDeclaredMethod(m_instanceFactoryCreateMethod, null);
+ m_serviceInstance = m.invoke(factory, null);
+ }
+ catch (Exception e) {
+ m_logger.log(Logger.LOG_ERROR, "Could not create service instance using factory " + factory + " method " + m_instanceFactoryCreateMethod + ".", e);
+ }
+ }
}
if (m_implementation == null) {
m_logger.log(Logger.LOG_ERROR, "Implementation cannot be null.");
@@ -591,12 +600,27 @@
}
}
// configure the bundle context
- configureImplementation(BundleContext.class, m_context);
- configureImplementation(ServiceRegistration.class, NULL_REGISTRATION);
- configureImplementation(DependencyManager.class, m_manager);
+ if (((Boolean) m_autoConfig.get(BundleContext.class)).booleanValue()) {
+ configureImplementation(BundleContext.class, m_context, (String) m_autoConfigInstance.get(BundleContext.class));
+ }
+ if (((Boolean) m_autoConfig.get(ServiceRegistration.class)).booleanValue()) {
+ configureImplementation(ServiceRegistration.class, NULL_REGISTRATION, (String) m_autoConfigInstance.get(ServiceRegistration.class));
+ }
+ if (((Boolean) m_autoConfig.get(DependencyManager.class)).booleanValue()) {
+ configureImplementation(DependencyManager.class, m_manager, (String) m_autoConfigInstance.get(DependencyManager.class));
+ }
}
}
+ public void setAutoConfig(Class clazz, boolean autoConfig) {
+ m_autoConfig.put(clazz, Boolean.valueOf(autoConfig));
+ }
+
+ public void setAutoConfig(Class clazz, String instanceName) {
+ m_autoConfig.put(clazz, Boolean.valueOf(instanceName != null));
+ m_autoConfigInstance.put(clazz, instanceName);
+ }
+
private void configureService(State state) {
// configure all services (the optional dependencies might be configured
// as null objects but that's what we want at this point)
@@ -612,7 +636,10 @@
if (m_serviceName != null) {
ServiceRegistrationImpl wrapper = new ServiceRegistrationImpl();
m_registration = wrapper;
- configureImplementation(ServiceRegistration.class, wrapper);
+ if (((Boolean) m_autoConfig.get(ServiceRegistration.class)).booleanValue()) {
+ configureImplementation(ServiceRegistration.class, m_registration, (String) m_autoConfigInstance.get(ServiceRegistration.class));
+ }
+
// service name can either be a string or an array of strings
ServiceRegistration registration;
diff --git a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceTracker.java b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceTracker.java
index c79257d..83c4b4b 100644
--- a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceTracker.java
+++ b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceTracker.java
@@ -162,7 +162,7 @@
this.trackReference = null;
this.trackClass = clazz;
this.customizer = (customizer == null) ? this : customizer;
- this.listenerFilter = "(" + Constants.OBJECTCLASS + "=" + clazz.toString() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ this.listenerFilter = "(" + Constants.OBJECTCLASS + "=" + clazz + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
try {
this.filter = context.createFilter(listenerFilter);
}