You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2015/11/12 23:26:32 UTC

svn commit: r1714132 [5/5] - in /felix/sandbox/pderop/dependencymanager.builder.java: ./ cnf/ cnf/bin/ cnf/buildrepo/ cnf/buildrepo/biz.aQute.junit/ cnf/buildrepo/biz.aQute.launcher/ cnf/buildrepo/ee.foundation/ cnf/buildrepo/ee.minimum/ cnf/buildrepo/...

Added: felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/src/org/apache/felix/dm/builder/java/impl/ServiceCallbacksBuilderImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/src/org/apache/felix/dm/builder/java/impl/ServiceCallbacksBuilderImpl.java?rev=1714132&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/src/org/apache/felix/dm/builder/java/impl/ServiceCallbacksBuilderImpl.java (added)
+++ felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/src/org/apache/felix/dm/builder/java/impl/ServiceCallbacksBuilderImpl.java Thu Nov 12 22:26:29 2015
@@ -0,0 +1,383 @@
+package org.apache.felix.dm.builder.java.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.builder.java.Callbacks.DictServiceDictService;
+import org.apache.felix.dm.builder.java.Callbacks.InstanceDictServiceDictService;
+import org.apache.felix.dm.builder.java.Callbacks.InstanceMapServiceMapService;
+import org.apache.felix.dm.builder.java.Callbacks.InstanceRef;
+import org.apache.felix.dm.builder.java.Callbacks.InstanceRefServiceRefService;
+import org.apache.felix.dm.builder.java.Callbacks.InstanceService;
+import org.apache.felix.dm.builder.java.Callbacks.InstanceServiceDict;
+import org.apache.felix.dm.builder.java.Callbacks.InstanceServiceMap;
+import org.apache.felix.dm.builder.java.Callbacks.InstanceServiceRef;
+import org.apache.felix.dm.builder.java.Callbacks.MapServiceMapService;
+import org.apache.felix.dm.builder.java.Callbacks.Ref;
+import org.apache.felix.dm.builder.java.Callbacks.RefServiceRefService;
+import org.apache.felix.dm.builder.java.Callbacks.Service;
+import org.apache.felix.dm.builder.java.Callbacks.ServiceDict;
+import org.apache.felix.dm.builder.java.Callbacks.ServiceMap;
+import org.apache.felix.dm.builder.java.Callbacks.ServiceRef;
+import org.osgi.framework.ServiceReference;
+
+import net.jodah.typetools.TypeResolver;
+
+/**
+ * Dependency Callbacks management.
+ *
+ * @param <T> the type of the service dependency
+ * @param <B> the type of the sub-classes which may extend this class
+ */
+@SuppressWarnings({"unchecked", "unused"})
+public abstract class ServiceCallbacksBuilderImpl<T, B extends ServiceCallbacksBuilderImpl<T, B>> {
+	/**
+	 * This interface (lambda) is called when we want to invoke a method reference. the lambda is called with all necessary service dependency 
+	 * informations.
+	 * 
+	 * When the lambda is called, it will invoke the proper callback on the given component instance.
+	 *
+	 * @param <I> type of a component instance
+	 * @param <T> service dependency type
+	 */
+	@FunctionalInterface
+    interface MethodRef<I, T> {
+    	public void call(I instance, Component c, ServiceReference<T> ref, T service);
+    }
+    
+	/**
+	 * This interface (lambda) is called when we want to invoke a swap method reference. the lambda is called with all necessary swap info.
+	 * When the lambda is called, it will invoke the proper swap callback on the given component instance.
+	 *
+	 * @param <I> type of a component instance
+	 * @param <T> service dependency type
+	 */
+	@FunctionalInterface
+	interface SwapMethodRef<I, T> {
+    	public void inject(I instance, Component c, ServiceReference<T> oldRef, T oldService, ServiceReference<T> newRef, T newService);
+    }
+
+    /**
+	 * Mapping between a DM service dependency callback ("add"/"change"/"removed/") and a list of component instances that have some method references on 
+	 * the given service.
+	 * 
+	 * Key: lifecycle service dependency callback ("add", "change", "remove")
+	 * Value: Map<component instance class, MethodRef>
+	 */
+	private final ConcurrentHashMap<String, ConcurrentHashMap<Class<?>, MethodRef<?, T>>> m_CbInstanceRefs = new ConcurrentHashMap<>();
+	
+    /**
+	 * Mapping between a DM service dependency callback ("add"/"change"/"removed") and a list of instance callbacks (method references).
+	 * 
+	 * Key: lifecycle service dependency callback ("add", "change", "remove")
+	 * Value: List of method references
+	 */
+	private final ConcurrentHashMap<String, List<MethodRef<?, T>>> m_CbRefs = new ConcurrentHashMap<>();	
+	
+	/**
+	 * Mapping between DM swap callback ("swap"), and list of instance callbacks (method refs).
+	 */
+	private final ConcurrentHashMap<Class<?>, SwapMethodRef<?, T>> m_swapCbInstanceRefs = new ConcurrentHashMap<>();
+	
+	/**
+	 * Mapping between DM swap callback ("swap") and list of callbacks (method refs).
+	 */
+	private final List<SwapMethodRef<?, T>> m_swapCbRefs = new ArrayList<>();
+    
+    public <I> B onAdd(InstanceService<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceService.class, callback.getClass())[0];
+        return setCallbackInstanceRef("add", instanceType, 
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, service));             
+    }      
+
+    public B onAdd(Service<T> callback) {
+    	return setCallbackRef("add", 
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(service));             
+    }      
+
+    public <I> B onAdd(InstanceServiceMap<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceServiceMap.class, callback.getClass())[0];
+        return setCallbackInstanceRef("add", instanceType, 
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, service, new SRefAsMap(ref)));             
+    }
+    
+    public B onAdd(ServiceMap<T> callback) {
+    	return setCallbackRef("add", 
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(service, new SRefAsMap(ref)));             
+    }
+    
+    public <I> B onAdd(InstanceServiceDict<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceServiceDict.class, callback.getClass())[0];
+        return setCallbackInstanceRef("add", instanceType, 
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, service, new SRefAsDictionary(ref)));             
+    }     
+    
+    public B onAdd(ServiceDict<T> callback) {
+    	return setCallbackRef("add", 
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(service, new SRefAsDictionary(ref)));             
+    }      
+
+    public <I> B onAdd(InstanceRef<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceRef.class, callback.getClass())[0];
+        return setCallbackInstanceRef("add", instanceType, 
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, ref));             
+    }      
+
+    public B onAdd(Ref<T> callback) {
+    	return setCallbackRef("add", 
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(ref));             
+    }      
+
+    public <I> B onAdd(InstanceServiceRef<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceServiceRef.class, callback.getClass())[0];
+        return setCallbackInstanceRef("add", instanceType, 
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, service, ref));             
+    }      
+
+    public B onAdd(ServiceRef<T> callback) {
+    	return setCallbackRef("add", 
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(service, ref));             
+    }      
+
+    public <I> B onChange(InstanceService<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceService.class, callback.getClass())[0];
+        return setCallbackInstanceRef("change", instanceType,
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, service));
+    }
+
+    public B onChange(Service<T> callback) {
+    	return setCallbackRef("change",
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(service));
+    }
+
+    public <I> B onChange(InstanceServiceMap<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceServiceMap.class, callback.getClass())[0];
+        return setCallbackInstanceRef("change", instanceType,
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, service, new SRefAsMap(ref)));
+    }
+
+    public B onChange(ServiceMap<T> callback) {
+    	return setCallbackRef("change",
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(service, new SRefAsMap(ref)));
+    }
+
+    public <I> B onChange(InstanceServiceDict<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceServiceDict.class, callback.getClass())[0];
+        return setCallbackInstanceRef("change", instanceType,
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, service, new SRefAsDictionary(ref)));
+    }
+    
+    public B onChange(ServiceDict<T> callback) {
+    	return setCallbackRef("change",
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(service, new SRefAsDictionary(ref)));
+    }
+    
+    public <I> B onChange(InstanceRef<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceRef.class, callback.getClass())[0];
+        return setCallbackInstanceRef("change", instanceType,
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, ref));
+    }
+
+    public B onChange(Ref<T> callback) {
+    	return setCallbackRef("change",
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(ref));
+    }
+
+    public <I> B onChange(InstanceServiceRef<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceServiceRef.class, callback.getClass())[0];
+        return setCallbackInstanceRef("change", instanceType, 
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, service, ref));             
+    }      
+
+    public B onChange(ServiceRef<T> callback) {
+    	return setCallbackRef("change", 
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(service, ref));             
+    }      
+
+    public <I> B onRemove(InstanceService<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceService.class, callback.getClass())[0];
+        return setCallbackInstanceRef("remove", instanceType,
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, service));
+    }
+
+    public B onRemove(Service<T> callback) {
+    	return setCallbackRef("remove",
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(service));
+    }
+
+    public <I> B onRemove(InstanceServiceMap<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceServiceMap.class, callback.getClass())[0];
+        return setCallbackInstanceRef("remove", instanceType,
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, service, new SRefAsMap(ref)));
+    }
+
+    public B onRemove(ServiceMap<T> callback) {
+    	return setCallbackRef("remove",
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(service, new SRefAsMap(ref)));
+    }
+
+    public <I> B onRemove(InstanceServiceDict<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceServiceDict.class, callback.getClass())[0];
+        return setCallbackInstanceRef("remove", instanceType,
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, service, new SRefAsDictionary(ref)));
+    }
+
+    public B onRemove(ServiceDict<T> callback) {
+    	return setCallbackRef("remove",
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(service, new SRefAsDictionary(ref)));
+    }
+
+    public <I> B onRemove(InstanceRef<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceRef.class, callback.getClass())[0];
+        return setCallbackInstanceRef("remove", instanceType,
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, ref));
+    }
+
+    public B onRemove(Ref<T> callback) {
+    	return setCallbackRef("remove",
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(ref));
+    }
+
+    public <I> B onRemove(InstanceServiceRef<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceServiceRef.class, callback.getClass())[0];
+        return setCallbackInstanceRef("remove", instanceType, 
+            (I inst, Component c, ServiceReference<T> ref, T service) -> callback.call(inst, service, ref));             
+    }      
+
+    public B onRemove(ServiceRef<T> callback) {
+    	return setCallbackRef("remove", 
+            (Object inst, Component c, ServiceReference<T> ref, T service) -> callback.call(service, ref));             
+    }      
+    
+    public <I> B onSwap(InstanceRefServiceRefService<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceRefServiceRefService.class, callback.getClass())[0];
+        return setSwapInstanceRef(instanceType,
+            (I inst, Component c, ServiceReference<T> oldR, T old, ServiceReference<T> replR, T repl) ->             
+                callback.call(inst, oldR, old, replR, repl));		        
+    }
+
+    public B onSwap(RefServiceRefService<T> callback) {
+    	return setSwapRef((Object inst, Component c, ServiceReference<T> oldR, T old, ServiceReference<T> replR, T repl) ->   
+    		callback.call(oldR, old, replR, repl));		        
+    }
+
+    public <I> B onSwap(InstanceMapServiceMapService<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceMapServiceMapService.class, callback.getClass())[0];
+        return setSwapInstanceRef(instanceType,
+            (I inst, Component c, ServiceReference<T> oldR, T old, ServiceReference<T> replR, T repl) ->             
+                callback.call(inst, new SRefAsMap(oldR), old, new SRefAsMap(replR), repl));		        
+    }
+
+   public B onSwap(MapServiceMapService<T> callback) {
+	   return setSwapRef((Object inst, Component c, ServiceReference<T> oldR, T old, ServiceReference<T> replR, T repl) ->             
+	   		callback.call(new SRefAsMap(oldR), old, new SRefAsMap(replR), repl));		        
+   }
+
+   public <I> B onSwap(InstanceDictServiceDictService<I, T> callback) {
+        Class<?> instanceType = TypeResolver.resolveRawArguments(InstanceDictServiceDictService.class, callback.getClass())[0];
+        return setSwapInstanceRef(instanceType,
+            (I inst, Component c, ServiceReference<T> oldR, T old, ServiceReference<T> replR, T repl) ->             
+                callback.call(inst, new SRefAsDictionary(oldR), old, new SRefAsDictionary(replR), repl));		        
+   }
+
+   public B onSwap(DictServiceDictService<T> callback) {
+	   return setSwapRef((Object inst, Component c, ServiceReference<T> oldR, T old, ServiceReference<T> replR, T repl) ->             
+	   		callback.call(new SRefAsDictionary(oldR), old, new SRefAsDictionary(replR), repl));
+   }
+
+   public <I> B setCallbackInstanceRef(String cb,  Class<?> instanceType, MethodRef<I, T> inject) {
+	   ConcurrentHashMap<Class<?>, MethodRef<?, T>> refs = m_CbInstanceRefs.computeIfAbsent(cb, map -> new ConcurrentHashMap<>());
+	   MethodRef<?, T> ref = refs.get(instanceType);
+	   if (ref != null) {
+		   throw new IllegalStateException("component instance type " + instanceType + " already has a \"" + cb + "\" method reference."); 
+	   }
+	   refs.put(instanceType, inject);
+	   return (B) this;
+   }
+
+   public <I> B setCallbackRef(String cb,  MethodRef<I, T> ref) {
+	   m_CbRefs.computeIfAbsent(cb, list -> new ArrayList<>()).add(ref);
+	   return (B) this;
+   }
+
+   public <I> B setSwapInstanceRef(Class<?> instanceType, SwapMethodRef<I, T> inject) {
+	   m_swapCbInstanceRefs.put(instanceType, inject);
+	   return (B) this;
+   }
+   
+   public <I> B setSwapRef(SwapMethodRef<I, T> ref) {
+	   m_swapCbRefs.add(ref);
+	   return (B) this;
+   }
+
+   protected Object createCallbackInstance() {
+       Object cb = null;
+
+       cb = new Object() {
+           void add(Component c, ServiceReference<T> ref, Object service) {
+               invokeInstanceMethodRefs("add", c, ref, (T) service);                
+               invokeMethodRefs("add", c, ref, (T) service);
+           }
+
+           void change(Component c, ServiceReference<T> ref, Object service) {
+               invokeInstanceMethodRefs("change", c, ref, (T) service);
+               invokeMethodRefs("change", c, ref, (T) service);
+           }
+
+           void remove(Component c, ServiceReference<T> ref, Object service) {
+               invokeInstanceMethodRefs("remove", c, ref, (T) service);
+               invokeMethodRefs("remove", c, ref, (T) service);
+           }
+
+           void swap(Component c, ServiceReference<T> oldRef, Object oldSrv, ServiceReference<T> newRef, Object newSrv) {
+               invokeSwapInstanceMethodRefs(c, oldRef, (T) oldSrv, newRef, (T) newSrv);
+               invokeSwapMethodRefs(c, oldRef, (T) oldSrv, newRef, (T) newSrv);
+           }
+       };
+
+       return cb;
+   }
+
+   protected boolean hasCallbacks() {
+	   return m_CbInstanceRefs.size() > 0 || m_CbRefs.size() > 0 || m_swapCbInstanceRefs.size() > 0 || m_swapCbRefs.size() > 0;
+   }
+	
+   protected boolean hasInstanceCallbacks() {
+	   return m_CbInstanceRefs.size() > 0 || m_swapCbInstanceRefs.size() > 0;
+   }
+   
+   private void invokeInstanceMethodRefs(String method, Component comp, ServiceReference<T> ref, T service) {
+		m_CbInstanceRefs.computeIfPresent(method, (k, mrefs) -> {
+			Stream.of(comp.getInstances()).forEach(instance -> {
+				MethodRef<Object, T> mref = (MethodRef<Object, T>) mrefs.get(instance.getClass());
+				if (mref != null) {
+					mref.call(instance,  comp,  ref, service);
+				}
+			});            
+			return mrefs;
+		});
+   }
+
+   private void invokeMethodRefs(String method, Component comp, ServiceReference<T> ref, T service) {
+		m_CbRefs.computeIfPresent(method, (k, mrefs) -> {
+			mrefs.stream().forEach(mref -> mref.call(null, comp, ref, service));
+			return mrefs;
+		});		
+   }
+
+   private void invokeSwapMethodRefs(Component comp, ServiceReference<T> oRef, T oSrv, ServiceReference<T> nRef, T nSrv) {
+		m_swapCbRefs.stream().forEach(mref -> mref.inject(null, comp, oRef, oSrv, nRef, nSrv));
+   }  
+   
+   private void invokeSwapInstanceMethodRefs(Component comp, ServiceReference<T> oRef, T oSrv, ServiceReference<T> nRef, T nSrv) {
+		Stream.of(comp.getInstances()).forEach(instance -> {
+			SwapMethodRef<Object, T> swapRef = (SwapMethodRef<Object, T>) m_swapCbInstanceRefs.get(instance.getClass());
+			if (swapRef != null) {
+				swapRef.inject(instance, comp, oRef, oSrv, nRef, nSrv);
+			}
+		});
+   }   
+}

Added: felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/src/org/apache/felix/dm/builder/java/impl/ServiceDependencyBuilderImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/src/org/apache/felix/dm/builder/java/impl/ServiceDependencyBuilderImpl.java?rev=1714132&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/src/org/apache/felix/dm/builder/java/impl/ServiceDependencyBuilderImpl.java (added)
+++ felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/src/org/apache/felix/dm/builder/java/impl/ServiceDependencyBuilderImpl.java Thu Nov 12 22:26:29 2015
@@ -0,0 +1,167 @@
+package org.apache.felix.dm.builder.java.impl;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.ServiceDependency;
+import org.apache.felix.dm.builder.java.ServiceDependencyBuilder;
+import org.osgi.framework.ServiceReference;
+
+public class ServiceDependencyBuilderImpl<T> extends ServiceCallbacksBuilderImpl<T, ServiceDependencyBuilderImpl<T>> implements ServiceDependencyBuilder<T> {
+    private Class<T> m_serviceIface;
+    private String m_filter;
+    private ServiceReference<T> m_ref;
+    private Object m_callbackInstance;
+    private String m_added;
+    private String m_changed;
+    private String m_removed;
+    private String m_swapped;
+    private boolean m_callbacksSet;
+    private Boolean m_autoConfig; // null means setAutoConfig has not been called.
+    private String m_autoConfigField;
+    private boolean m_required = true;
+    private String m_debug;
+    private boolean m_propagate;
+    private Object m_propagateInstance;
+    private String m_propagateMethod;
+    private Object m_defaultImpl;
+    private final Component m_component;
+
+    public ServiceDependencyBuilderImpl(Component component, Class<T> service) {
+        m_serviceIface = service;
+        m_component = component;
+    }
+
+    public ServiceDependencyBuilder<T> autoConfig() {
+        m_autoConfig = true;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> autoConfig(boolean autoConfig) {
+        m_autoConfig = autoConfig;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> autoConfig(String field) {
+        m_autoConfigField = field;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> filter(String filter) {
+        this.m_filter = filter;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> ref(ServiceReference<T> ref) {
+        this.m_ref = ref;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> required() {
+        return required(true);
+    }
+
+    public ServiceDependencyBuilder<T> required(boolean required) {
+        m_required = required;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> callbackInstance(Object instance) {
+        m_callbackInstance = instance;
+        m_callbacksSet = true;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> onAdd(String added) {
+        this.m_added = added;
+        m_callbacksSet = true;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> onChange(String changed) {
+        this.m_changed = changed;
+        m_callbacksSet = true;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> onRemove(String removed) {
+        this.m_removed = removed;
+        m_callbacksSet = true;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> onSwap(String swapped) {
+        this.m_swapped = swapped;
+        m_callbacksSet = true;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> debug(String label) {
+        m_debug = label;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> propagate() {
+        return propagate(true);
+    }
+
+    public ServiceDependencyBuilder<T> propagate(boolean propagate) {
+        m_propagate = propagate;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> propagateTo(Object instance, String method) {
+        m_propagateInstance = instance;
+        m_propagateMethod = method;
+        return this;
+    }
+
+    public ServiceDependencyBuilder<T> defImpl(Object defaultImpl) {
+        m_defaultImpl = defaultImpl;
+        return this;
+    }
+
+   	// Build final ServiceDependency object.
+    @Override
+    public ServiceDependency build() {
+        DependencyManager dm = m_component.getDependencyManager();
+        if (m_ref != null && m_filter != null) {
+            throw new IllegalArgumentException("Can not set ref and filter at the same time");
+        }
+        ServiceDependency sd = dm.createServiceDependency();
+        if (m_ref != null) {
+            sd.setService(m_serviceIface, m_ref);
+        } else {
+            sd.setService(m_serviceIface, m_filter);
+        }
+        sd.setRequired(m_required);
+        sd.setDefaultImplementation(m_defaultImpl);
+        if (m_debug != null) {
+            sd.setDebug(m_debug);
+        }
+        if (m_propagate) {
+            sd.setPropagate(true);
+        } else if (m_propagateInstance != null) {
+            if (m_propagateMethod == null) {
+                throw new IllegalArgumentException("propagate instance can't be null");
+            }
+            sd.setPropagate(m_propagateInstance, m_propagateMethod);
+        }
+        if (m_callbacksSet) {
+            sd.setCallbacks(m_callbackInstance, m_added, m_changed, m_removed, m_swapped);
+        } else if (hasInstanceCallbacks() || hasCallbacks()) {
+            Object cb = createCallbackInstance();
+            sd.setCallbacks(cb, "add", "change", "remove", "swap");
+
+            if (! hasInstanceCallbacks()) {
+            	sd.setAutoConfig(true);
+            }
+        }
+        
+        if (m_autoConfigField != null) {
+            sd.setAutoConfig(m_autoConfigField);
+        } else if (m_autoConfig != null) {
+            sd.setAutoConfig(m_autoConfig);
+        }
+        return sd;
+    }
+}

Added: felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/src/org/apache/felix/dm/builder/java/packageinfo
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/src/org/apache/felix/dm/builder/java/packageinfo?rev=1714132&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/src/org/apache/felix/dm/builder/java/packageinfo (added)
+++ felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/src/org/apache/felix/dm/builder/java/packageinfo Thu Nov 12 22:26:29 2015
@@ -0,0 +1 @@
+version 1.0.0
\ No newline at end of file

Added: felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/test/.gitignore
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.builder.java/org.apache.felix.dependencymanager.builder.java/test/.gitignore?rev=1714132&view=auto
==============================================================================
    (empty)

Added: felix/sandbox/pderop/dependencymanager.builder.java/settings.gradle
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager.builder.java/settings.gradle?rev=1714132&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager.builder.java/settings.gradle (added)
+++ felix/sandbox/pderop/dependencymanager.builder.java/settings.gradle Thu Nov 12 22:26:29 2015
@@ -0,0 +1,127 @@
+/*
+ * Master Gradle initialization script
+ *
+ * Depends on bnd_* values from gradle.properties.
+ */
+
+import aQute.bnd.build.Workspace
+
+/* Add bnd as a script dependency */
+buildscript {
+  dependencies {
+    def bndURI = rootDir.toURI().resolve(bnd_jar)
+    if (bndURI.scheme != 'file') {
+      /* If not a local file, copy to a local file in cnf/cache */
+      def cnfCache = mkdir("${rootDir}/${bnd_cnf}/cache")
+      def bndJarFile = new File(cnfCache, 'biz.aQute.bnd.gradle.jar')
+      if (!bndJarFile.exists()) {
+        println "Downloading ${bndURI} to ${bndJarFile} ..."
+        bndURI.toURL().withInputStream { is ->
+          bndJarFile.withOutputStream { os ->
+            def bos = new BufferedOutputStream( os )
+            bos << is
+          }
+        }
+      }
+      bndURI = bndJarFile.toURI()
+    }
+    classpath files(bndURI)
+
+    /* After the rootProject is created, pass URI to projects */
+    gradle.rootProject { rootProject ->
+      rootProject.ext.bndURI = bndURI
+    }
+  }
+}
+
+/* Initialize the bnd workspace */
+def workspace = Workspace.getWorkspace(rootDir, bnd_cnf)
+if (workspace == null) {
+  throw new GradleException("Unable to load workspace ${rootDir}/${bnd_cnf}")
+}
+
+/* Add cnf project to the graph */
+include bnd_cnf
+
+/* Start with the declared build project name */
+def defaultProjectName = bnd_build
+
+/* If in a subproject, use the subproject name */
+for (def currentDir = startParameter.currentDir; currentDir != rootDir; currentDir = currentDir.parentFile) {
+  defaultProjectName = currentDir.name
+}
+
+/* Build a set of project names we need to include from the specified tasks */
+def projectNames = startParameter.taskNames.collect { taskName ->
+  def elements = taskName.split(':')
+  switch (elements.length) {
+    case 1:
+      return defaultProjectName
+    case 2:
+      return elements[0].empty ? bnd_build : elements[0]
+    default:
+      return elements[0].empty ? elements[1] : elements[0]
+  }
+}.toSet()
+
+/* Include the default project name if in a subproject or no tasks specified */
+if ((startParameter.currentDir != rootDir) || projectNames.empty) {
+  projectNames += defaultProjectName
+}
+
+/* If bnd_build used but declared empty, add all non-private folders of rootDir */
+if (projectNames.remove('')) {
+  rootDir.eachDir {
+    def projectName = it.name
+    if (!projectName.startsWith('.')) {
+      projectNames += projectName
+    }
+  }
+}
+
+/* Add each project and its dependencies to the graph */
+projectNames.each { projectName ->
+  include projectName
+  def project = getBndProject(workspace, projectName)
+  project?.dependson.each {
+    include it.name
+  }
+}
+
+/* Get the bnd project for the specified project name */
+def getBndProject(Workspace workspace, String projectName) {
+  def project = workspace.getProject(projectName)
+  if (project == null) {
+    return null
+  }
+  project.prepare()
+  if (project.isValid()) {
+    return project
+  }
+
+  project.getInfo(workspace, "${rootDir} :")
+  def errorCount = 0
+  project.warnings.each {
+    println "Warning: ${it}"
+  }
+  project.errors.each {
+    println "Error  : ${it}"
+    errorCount++
+  }
+  if (!project.isOk()) {
+    def str = 'even though no errors were reported'
+    if (errorCount == 1) {
+      str = 'one error was reported'
+    } else if (errorCount > 1) {
+      str = "${errorCount} errors were reported"
+    }
+    throw new GradleException("Project ${rootDir}/${projectName} is invalid, ${str}")
+  }
+  throw new GradleException("Project ${rootDir}/${projectName} is not a valid bnd project")
+}
+
+/* After the rootProject is created, set up some properties. */
+gradle.rootProject { rootProject ->
+  rootProject.ext.bndWorkspace = workspace
+  rootProject.ext.cnf = rootProject.project(bnd_cnf)
+}