You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ui...@apache.org on 2014/05/19 08:47:08 UTC

svn commit: r1595756 [1/2] - in /felix/sandbox/pderop/dependencymanager-prototype: dm.it/src/dm/it/ dm/src/dm/ dm/src/dm/impl/ dm/src/dm/impl/index/ dm/src/dm/impl/index/multiproperty/ dm/src/dm/impl/metatype/ dm/src/tracker/

Author: uiterlix
Date: Mon May 19 06:47:07 2014
New Revision: 1595756

URL: http://svn.apache.org/r1595756
Log:
Work in progress on Aspects. Yet to resolve issues especially in Aspects and concurrency.

Added:
    felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectBaseTest.java   (with props)
    felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectChainTest.java   (with props)
    felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectDynamicsTest.java   (with props)
    felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectRaceTest.java   (with props)
    felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectServiceDependencyWithSwapCallbackTest.java   (with props)
    felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWhiteboardTest.java   (with props)
    felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWithCallbacksServiceDependencyTest.java   (with props)
    felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWithPropagationTest.java   (with props)
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/AspectServiceImpl.java   (with props)
Modified:
    felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectServiceDependencyTest.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/Component.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/DependencyActivatorBase.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/DependencyManager.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/ServiceDependency.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/AbstractDecorator.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ComponentImpl.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/DependencyImpl.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/FactoryConfigurationAdapterImpl.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/FilterComponent.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/Logger.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/SerialExecutor.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/ServiceDependencyImpl.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/TemporalServiceDependencyImpl.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/AspectFilterIndex.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/ServiceRegistryCache.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/index/multiproperty/Property.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/metatype/MetaTypeProviderImpl.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/metatype/PropertyMetaDataImpl.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/tracker/AbstractTracked.java
    felix/sandbox/pderop/dependencymanager-prototype/dm/src/tracker/ServiceTracker.java

Added: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectBaseTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectBaseTest.java?rev=1595756&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectBaseTest.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectBaseTest.java Mon May 19 06:47:07 2014
@@ -0,0 +1,198 @@
+package dm.it;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import junit.framework.Assert;
+
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+import dm.Component;
+import dm.DependencyManager;
+
+public class AspectBaseTest extends TestBase {    
+
+	public void testSingleAspect() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create a service provider and consumer
+        ServiceProvider p = new ServiceProvider(e, "a");
+        ServiceConsumer c = new ServiceConsumer(e);
+        Component sp = m.createComponent()
+            .setInterface(ServiceInterface.class.getName(), new Properties() {{ put("name", "a"); }})
+            .setImplementation(p);
+        Component sc = m.createComponent()
+            .setImplementation(c)
+            .add(m.createServiceDependency()
+                .setService(ServiceInterface.class)
+                .setRequired(true)
+                .setCallbacks("add", "remove")
+                .setAutoConfig(true)
+            );
+        Component sa = m.createAspectService(ServiceInterface.class, null, 20, null)
+            .setImplementation(ServiceAspect.class);
+        m.add(sc);
+        m.add(sp);
+        // after the provider was added, the consumer's add should have been invoked once
+        e.waitForStep(1, 2000);
+        Assert.assertEquals("a", c.invoke());
+        m.add(sa);
+        // after the aspect was added, the consumer should get and add for the aspect and a remove
+        // for the original service
+        e.waitForStep(3, 2000);
+        Assert.assertEquals("aa", c.invoke());
+        m.remove(sa);
+        // removing the aspect again should give a remove and add
+        e.waitForStep(5, 2000);
+        Assert.assertEquals("a", c.invoke());
+        m.remove(sp);
+        // finally removing the original service should give a remove
+        e.waitForStep(6, 2000);
+        m.remove(sc);
+        e.step(7);
+    }
+    
+    public void testSingleAspectThatAlreadyExisted() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create a service provider and consumer
+        ServiceProvider p = new ServiceProvider(e, "a");
+        ServiceConsumer c = new ServiceConsumer(e);
+        Component sp = m.createComponent().setImplementation(p).setInterface(ServiceInterface.class.getName(), new Properties() {{ put("name", "a"); }});
+        Component sc = m.createComponent().setImplementation(c).add(m.createServiceDependency().setService(ServiceInterface.class).setRequired(true).setCallbacks("add", "remove").setAutoConfig(true));
+        Component sa = m.createAspectService(ServiceInterface.class, null, 20, null).setImplementation(ServiceAspect.class);
+        // we first add the aspect
+        m.add(sa);
+        // then the service provider
+        m.add(sp);
+        // finally the consumer
+        m.add(sc);
+
+        Assert.assertEquals("aa", c.invoke());
+        
+        // now the consumer's added should be invoked once, as the aspect is already available and should
+        // directly hide the original service
+        e.waitForStep(1, 2000);
+        e.step(2);
+
+        m.remove(sa);
+        // after removing the aspect, the consumer should get the original service back, so
+        // remove and add will be invoked
+        e.waitForStep(4, 2000);
+        
+        Assert.assertEquals("a", c.invoke());
+        
+        m.remove(sp);
+        // after removing the original service, the consumer's remove should be called once
+        e.waitForStep(5, 2000);
+        
+        m.remove(sc);
+        e.step(6);
+    }
+
+    public void testMultipleAspects() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create service providers and consumers
+        ServiceConsumer c = new ServiceConsumer(e);
+        Component sp = m.createComponent().setImplementation(new ServiceProvider(e, "a")).setInterface(ServiceInterface.class.getName(), new Properties() {{ put("name", "a"); }});
+        Component sp2 = m.createComponent().setImplementation(new ServiceProvider(e, "b")).setInterface(ServiceInterface.class.getName(), new Properties() {{ put("name", "b"); }});
+        Component sc = m.createComponent().setImplementation(c).add(m.createServiceDependency().setService(ServiceInterface.class).setRequired(true).setCallbacks("add", "remove"));
+        Component sa = m.createAspectService(ServiceInterface.class, null, 20, null).setImplementation(ServiceAspect.class);
+        Component sa2 = m.createAspectService(ServiceInterface.class, null, 10, null).setImplementation(ServiceAspect.class);
+        m.add(sp);
+        m.add(sp2);
+        m.add(sa);
+        m.add(sa2);
+        m.add(sc);
+        // the consumer will monitor progress, it should get it's add invoked twice, once for every
+        // (highest) aspect
+        e.waitForStep(2, 2000);
+        e.step(3);
+        
+        // now invoke all services the consumer collected
+        List<String> list = c.invokeAll();
+        // and make sure both of them are correctly invoked
+        Assert.assertTrue(list.size() == 2);
+        Assert.assertTrue(list.contains("aaa"));
+        Assert.assertTrue(list.contains("bbb"));
+        
+        m.remove(sc);
+        // removing the consumer now should get its removed method invoked twice
+        e.waitForStep(5, 2000);
+        e.step(6);
+        m.remove(sa2);
+        m.remove(sa);
+        m.remove(sp2);
+        m.remove(sp);
+        e.step(7);
+    }
+    
+    public static interface ServiceInterface {
+        public String invoke(String input);
+    }
+    
+    public static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        private final String m_name;
+        public ServiceProvider(Ensure e, String name) {
+            m_ensure = e;
+            m_name = name;
+        }
+        public String invoke(String input) {
+            return input + m_name;
+        }
+    }
+    
+    public static class ServiceAspect implements ServiceInterface {
+        private volatile ServiceInterface m_originalService;
+        private volatile ServiceRegistration m_registration;
+        
+        public String invoke(String input) {
+            String result = m_originalService.invoke(input);
+            String property = (String) m_registration.getReference().getProperty("name");
+            return result + property;
+        }
+    }
+
+    public static class ServiceConsumer {
+        private final Ensure m_ensure;
+        private volatile ServiceInterface m_service;
+        private List<ServiceInterface> m_services = new ArrayList<ServiceInterface>();
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void add(ServiceReference ref, ServiceInterface si) {
+            System.out.println("add: " + ServiceUtil.toString(ref));
+            m_services.add(si);
+            m_ensure.step();
+        }
+        
+        public void remove(ServiceReference ref, ServiceInterface si) {
+            System.out.println("rem: " + ServiceUtil.toString(ref));
+            m_services.remove(si);
+            m_ensure.step();
+        }
+        
+        public String invoke() {
+            return m_service.invoke("");
+        }
+        
+        public List<String> invokeAll() {
+            List<String> results = new ArrayList<String>();
+            for (ServiceInterface si : m_services) {
+                results.add(si.invoke(""));
+            }
+            return results;
+        }
+    }
+}

Propchange: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectBaseTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectChainTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectChainTest.java?rev=1595756&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectChainTest.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectChainTest.java Mon May 19 06:47:07 2014
@@ -0,0 +1,86 @@
+package dm.it;
+import dm.Component;
+import dm.DependencyManager;
+
+public class AspectChainTest extends TestBase {
+
+	public void testBuildAspectChain() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = m.createComponent().setImplementation(new ServiceProvider(e)).setInterface(ServiceInterface.class.getName(), null);
+        Component sc = m.createComponent().setImplementation(new ServiceConsumer(e)).add(m.createServiceDependency().setService(ServiceInterface.class).setRequired(true));
+        Component sa2 = m.createAspectService(ServiceInterface.class, null, 20, null).setImplementation(new ServiceAspect(e, 3));
+        Component sa3 = m.createAspectService(ServiceInterface.class, null, 30, null).setImplementation(new ServiceAspect(e, 2));
+        Component sa1 = m.createAspectService(ServiceInterface.class, null, 10, null).setImplementation(new ServiceAspect(e, 4));
+        m.add(sc);
+
+        m.add(sp);
+        m.add(sa2);
+        m.add(sa3);
+        m.add(sa1);
+        e.step();
+        
+        m.remove(sa3);
+        m.remove(sa2);
+        m.remove(sa1);
+        m.remove(sp);
+        
+        m.remove(sc);
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(Runnable run);
+    }
+    
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(Runnable run) {
+            run.run();
+        }
+    }
+    
+    static class ServiceAspect implements ServiceInterface {
+        private final Ensure m_ensure;
+        private volatile ServiceInterface m_parentService;
+        private final int m_step;
+        
+        public ServiceAspect(Ensure e, int step) {
+            m_ensure = e;
+            m_step = step;
+        }
+        public void start() {
+        }
+        
+        public void invoke(Runnable run) {
+            m_ensure.step(m_step);
+            m_parentService.invoke(run);
+        }
+        
+        public void stop() {
+        }
+    }
+
+    static class ServiceConsumer implements Runnable {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            Thread t = new Thread(this);
+            t.start();
+        }
+        
+        public void run() {
+            m_ensure.waitForStep(1, 2000);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 5));
+        }
+    }
+}

Propchange: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectChainTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectDynamicsTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectDynamicsTest.java?rev=1595756&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectDynamicsTest.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectDynamicsTest.java Mon May 19 06:47:07 2014
@@ -0,0 +1,145 @@
+package dm.it;
+import dm.Component;
+import dm.DependencyManager;
+
+public class AspectDynamicsTest extends TestBase {
+
+	public void testDynamicallyAddAndRemoveAspect() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component provider = m.createComponent().setImplementation(new ServiceProvider(e)).setInterface(ServiceInterface.class.getName(), null);
+        Component provider2 = m.createComponent().setImplementation(new ServiceProvider2(e)).setInterface(ServiceInterface2.class.getName(), null);
+        Component consumer = m.createComponent().setImplementation(new ServiceConsumer(e)).add(m.createServiceDependency().setService(ServiceInterface.class).setRequired(true));
+        Component aspect = m.createAspectService(ServiceInterface.class, null, 1, null).setImplementation(new ServiceAspect(e));
+        
+        m.add(consumer);
+        m.add(provider);
+        // the consumer should invoke the provider here, and when done, arrive at step 3
+        // finally wait for step 6 before continuing
+        e.waitForStep(3, 15000);
+        
+        m.add(aspect);
+        // after adding the aspect, we wait for its init to be invoked, arriving at
+        // step 4 after an instance bound dependency was added (on a service provided by
+        // provider 2)
+        e.waitForStep(4, 15000);
+        
+        m.add(provider2);
+        
+        // after adding provider 2, we should now see the aspect being started, so
+        // we wait for step 5 to happen
+        e.waitForStep(5, 15000);
+        
+        // now we continue with step 6, which will trigger the next part of the consumer's
+        // run method to be executed
+        e.step(6);
+        
+        // invoking step 7, 8 and 9 when invoking the aspect which in turn invokes the
+        // dependency and the original service, so we wait for that to finish here, which
+        // is after step 10 has been reached (the client will now wait for step 12)
+        e.waitForStep(10, 15000);
+        
+        m.remove(aspect);
+        // removing the aspect should trigger step 11 (in the stop method of the aspect)
+        e.waitForStep(11, 15000);
+        
+        // step 12 triggers the client to continue
+        e.step(12);
+        
+        // wait for step 13, the final invocation of the provided service (without aspect)
+        e.waitForStep(13, 15000);
+        
+        // clean up
+        m.remove(provider2);
+        m.remove(provider);
+        m.remove(consumer);
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(Runnable run);
+    }
+    
+    static interface ServiceInterface2 {
+        public void invoke();
+    }
+    
+    static class ServiceProvider2 implements ServiceInterface2 {
+        private final Ensure m_ensure;
+
+        public ServiceProvider2(Ensure ensure) {
+            m_ensure = ensure;
+        }
+
+        public void invoke() {
+            m_ensure.step(9);
+        }
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(Runnable run) {
+            run.run();
+        }
+    }
+    
+    static class ServiceAspect implements ServiceInterface {
+        private final Ensure m_ensure;
+        private volatile ServiceInterface m_originalService;
+        private volatile ServiceInterface2 m_injectedService;
+        private volatile Component m_service;
+        private volatile DependencyManager m_manager;
+        
+        public ServiceAspect(Ensure e) {
+            m_ensure = e;
+        }
+        public void init() {
+            m_service.add(m_manager.createServiceDependency()
+                .setService(ServiceInterface2.class)
+                .setRequired(true)
+            );
+            m_ensure.step(4);
+        }
+        public void start() {
+            m_ensure.step(5);
+        }
+        public void invoke(Runnable run) {
+            m_ensure.step(7);
+            m_originalService.invoke(run);
+            m_injectedService.invoke();
+        }
+        
+        public void stop() {
+            m_ensure.step(11);
+        }
+    }
+
+    static class ServiceConsumer implements Runnable {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            Thread t = new Thread(this);
+            t.start();
+        }
+        
+        public void run() {
+            m_ensure.step(1);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 2));
+            m_ensure.step(3);
+            m_ensure.waitForStep(6, 15000);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 8));
+            m_ensure.step(10);
+            m_ensure.waitForStep(12, 15000);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 13));
+        }
+    }
+}

Propchange: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectDynamicsTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectRaceTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectRaceTest.java?rev=1595756&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectRaceTest.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectRaceTest.java Mon May 19 06:47:07 2014
@@ -0,0 +1,343 @@
+package dm.it;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.Assert;
+
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+import dm.Component;
+import dm.DependencyManager;
+import dm.ServiceDependency;
+
+public class AspectRaceTest extends TestBase {
+	volatile ExecutorService m_serviceExec;
+	volatile ExecutorService m_aspectExec;
+	volatile DependencyManager m_dm;
+	final static int SERVICES = 1; // 3;
+	final static int ASPECTS_PER_SERVICE = 2;
+	final static int ITERATIONS = 3000; // 3000;
+
+	public void testConcurrentAspects() {
+		try {
+			warn("starting aspect race test");
+			int cores = Math.max(4, Runtime.getRuntime().availableProcessors());
+			// Used to inject S services
+			m_serviceExec = Executors.newFixedThreadPool(cores);
+			// Used to inject S Aspects
+			m_aspectExec = Executors.newFixedThreadPool(cores);
+
+			// Setup test components using dependency manager.
+			// We create a Controller which is injected with some S services,
+			// and each S services has some aspects (SAspect).
+
+			m_dm = new DependencyManager(context);
+			Controller controller = new Controller();
+			ServiceDependency dependency = m_dm.createServiceDependency().setService(S.class)
+					.setCallbacks("bind", null, "unbind", "swap")
+					.setRequired(true);
+//			dependency.setDebug("controller");
+			Component c = m_dm
+					.createComponent()
+					.setImplementation(controller)
+					.setInterface(Controller.class.getName(), null)
+					.setComposition("getComposition")
+					.add(dependency);
+
+			m_dm.add(c);
+
+			for (int loop = 1; loop <= ITERATIONS; loop++) {
+				System.out.println("\niteration: " + loop);
+				// Perform concurrent injections of "S" service and S aspects
+				// into the Controller component;
+				debug("Iteration: " + loop);
+				Factory f = new Factory();
+				f.register();
+				
+//				System.out.println("Checking...");
+
+				controller.check();
+				
+//				System.out.println("Done checking...");
+
+				// unregister all services and aspects concurrently
+				f.unregister();
+
+				if ((loop) % 100 == 0) {
+					warn("Performed " + loop + " tests.");
+				}				
+
+	            if (super.errorsLogged()) {
+	                throw new IllegalStateException("Race test interrupted (some error occured, see previous logs)");
+	            }
+			}
+		}
+
+		catch (Throwable t) {
+			error("Test failed", t);
+			Assert.fail("Test failed: " + t.getMessage());
+		} finally {
+			shutdown(m_serviceExec);
+			shutdown(m_aspectExec);
+			m_dm.clear();
+		}
+	}
+
+	void shutdown(ExecutorService exec) {
+		exec.shutdown();
+		try {
+			exec.awaitTermination(5, TimeUnit.SECONDS);
+		} catch (InterruptedException e) {
+		}
+	}
+
+	public interface S {
+		void invoke(Ensure e);
+	}
+
+	public static class SImpl implements S {
+		final int m_step;
+
+		SImpl(int step) {
+			m_step = step;
+		}
+
+		public void invoke(Ensure e) {
+			e.step(m_step);
+		}
+
+		public String toString() {
+			return "SImpl[" + m_step + "]";
+		}
+	}
+
+	public static class SAspect implements S {
+		volatile S m_next;
+		final int m_rank;
+		final int m_step;
+		final int m_id;
+		volatile Component m_component;
+
+		SAspect(int id, int rank) {
+			m_rank = rank;
+			m_id = id;
+			m_step = ASPECTS_PER_SERVICE - rank + 1;
+		}
+
+		public synchronized void added(S s) {
+			 System.out.println(Thread.currentThread().getId() + " ARTA aspect added " + m_rank + ": " + s );
+			if (m_next != null) {
+				fail("Adding while expected swap... " + m_rank);
+			}
+			m_next = s;
+		}
+
+		public synchronized void swap(S oldS, S newS) {
+			 System.out.println(Thread.currentThread().getId() + " ARTA aspect swap " + m_rank + ": " + oldS + " with " + newS);
+			m_next = newS;
+		}
+		
+		public synchronized void removed(S s) {
+			System.out.println(Thread.currentThread().getId() + " ARTA aspect removed " + m_rank + ": " + s );
+			m_next = null;
+		}
+
+		public synchronized void invoke(Ensure e) {
+//			System.out.println("config " + m_rank + ": " + toString() + " " + m_component.getExecutor() + " " + m_component);
+			e.step(m_step);
+			m_next.invoke(e);
+		}
+
+		public String toString() {
+			return "SAspect[" + m_id + ", " + m_rank + ", " + m_step + "], " + m_next.toString();
+		}
+	}
+
+	class Factory {
+		final ConcurrentLinkedQueue<Component> m_services = new ConcurrentLinkedQueue<Component>();
+		final ConcurrentLinkedQueue<Component> m_aspects = new ConcurrentLinkedQueue<Component>();
+
+		public void register() throws InterruptedException {
+			final CountDownLatch latch = new CountDownLatch(SERVICES
+					+ (ASPECTS_PER_SERVICE * SERVICES));
+
+			for (int i = 1; i <= SERVICES; i++) {
+				final int serviceId = i;
+				m_serviceExec.execute(new Runnable() {
+					public void run() {
+						try {
+							Component c = m_dm.createComponent();
+							Hashtable<String, String> props = new Hashtable<String, String>();
+							props.put("id", String.valueOf(serviceId));
+							c.setInterface(S.class.getName(), props)
+									.setImplementation(
+											new SImpl(ASPECTS_PER_SERVICE + 1));
+							m_services.add(c);
+							m_dm.add(c);
+							latch.countDown();
+						} catch (Throwable e) {
+							error(e);
+						}
+					}
+				});
+
+				for (int j = 1; j <= ASPECTS_PER_SERVICE; j++) {
+					final int rank = j;
+					m_aspectExec.execute(new Runnable() {
+						public void run() {
+							try {
+								SAspect sa = new SAspect(serviceId, rank);
+								Component aspect = m_dm.createAspectService(
+										S.class, "(id=" + serviceId + ")",
+										rank, "added", "removed", null, "swap")
+										.setImplementation(sa);
+								m_aspects.add(aspect);
+								m_dm.add(aspect);
+								latch.countDown();
+							} catch (Throwable e) {
+								error(e);
+							}
+						}
+					});
+				}
+			}
+
+			if (!latch.await(5000, TimeUnit.MILLISECONDS)) {
+				throw new IllegalStateException(
+						"could not register services and aspects timely");
+			}
+
+			debug("all registered: aspects=" + m_aspects);
+//			System.out.println("all registered: aspects=" + m_aspects);
+			// Thread.sleep(5000);
+		}
+
+		public void unregister() throws InterruptedException,
+				InvalidSyntaxException {
+			final CountDownLatch latch = new CountDownLatch(SERVICES
+					+ (ASPECTS_PER_SERVICE * SERVICES));
+
+			unregisterAspects(latch);
+			unregisterServices(latch);
+
+			if (!latch.await(5000, TimeUnit.MILLISECONDS)) {
+				throw new IllegalStateException(
+						"could not unregister services and aspects timely");
+			}
+
+			if (context.getServiceReference(S.class.getName()) != null) {
+				error("could not unregister some services or aspects !");
+			}
+			debug("unregistered all aspects and services concurrently");
+		}
+
+		public void unregisterAspects(final CountDownLatch latch)
+				throws InterruptedException, InvalidSyntaxException {
+			Component c;
+			debug("unregister: aspects=" + m_aspects);
+
+			while ((c = m_aspects.poll()) != null) {
+				final Component c$ = c;
+				m_serviceExec.execute(new Runnable() {
+					public void run() {
+						try {
+							debug("removing service " + c$);
+							m_dm.remove(c$);
+							latch.countDown();
+						} catch (Throwable e) {
+							error(e);
+						}
+					}
+				});
+			}
+		}
+
+		public void unregisterServices(final CountDownLatch latch)
+				throws InterruptedException {
+			Component c;
+			debug("unregister: services=" + m_services);
+
+			while ((c = m_services.poll()) != null) {
+				final Component c$ = c;
+				m_serviceExec.execute(new Runnable() {
+					public void run() {
+						try {
+							debug("removing service " + c$);
+							m_dm.remove(c$);
+							latch.countDown();
+						} catch (Throwable e) {
+							error(e);
+						}
+					}
+				});
+			}
+
+			debug("unregistered all services");
+		}
+	}
+
+	public class Controller {
+		final Composition m_compo = new Composition();
+		final HashSet<S> m_services = new HashSet<S>();
+
+		Object[] getComposition() {
+			return new Object[] { this, m_compo };
+		}
+
+		void bind(ServiceReference sr, Object service) {
+//			System.out.println("ARTC bind... " + service);
+			S s = (S) sr.getBundle().getBundleContext().getService(sr);
+			if (s == null) {
+				throw new IllegalStateException(
+						"bindA: bundleContext.getService returned null");
+			}
+			debug("bind " + s);
+			synchronized (this) {
+				m_services.add(s);
+//				System.out.println("service count after bind: " + m_services.size());
+			}
+		}
+
+		void swap(S previous, S current) {
+//			System.out.println("swap...");
+//			System.out.println("ARTC swap: " + previous + " with " + current);
+			synchronized (this) {
+				if (!m_services.remove(previous)) {
+					System.out.println("swap: unknow previous service: " + previous);
+				}
+				m_services.add(current);
+//				System.out.println("service count after swap: " + m_services.size());
+			}
+		}
+
+		void unbind(S a) {
+//			System.out.println("ARTC unbind...");
+			debug("unbind " + a);
+			synchronized (this) {
+				m_services.remove(a);
+//				System.out.println("service count after unbind: " + m_services.size());
+			}
+		}
+
+		void check() {
+			synchronized (this) {
+//				System.out.println("service count: " + m_services.size());
+				for (S s : m_services) {
+//					System.out.println("checking service: " + s);
+					debug("checking service: " + s + " ...");
+					Ensure ensure = new Ensure(false);
+					s.invoke(ensure);
+				}
+			}
+		}
+	}
+
+	public static class Composition {
+	}
+}
\ No newline at end of file

Propchange: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectRaceTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectServiceDependencyTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectServiceDependencyTest.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectServiceDependencyTest.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectServiceDependencyTest.java Mon May 19 06:47:07 2014
@@ -29,20 +29,25 @@ public class AspectServiceDependencyTest
         Ensure e = new Ensure();
         // create a service provider and consumer
         Component sp = m.createComponent().setImplementation(new ServiceProvider(e)).setInterface(ServiceInterface.class.getName(), null);
-        Component sc = m.createComponent().setImplementation(new ServiceConsumer(e)).add(m.createServiceDependency().setService(ServiceInterface.class).setRequired(true));
+        Component sc = m.createComponent().setImplementation(new ServiceConsumer(e)).add(m.createServiceDependency()
+        		.setService(ServiceInterface.class)
+        		.setCallbacks("add", "remove")
+        		.setRequired(true));
+        Component asp = m.createAspectService(ServiceInterface.class, null, 100)
+        		.setImplementation(ServiceProviderAspect.class);
         m.add(sp);
         m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
         m.remove(sc);
         m.remove(sp);
         
-        // TODO: Further implementation when aspect services have been implemented.
-        
         // ensure we executed all steps inside the component instance
-        e.step(4);
+        e.step(8);
     }
     
     static interface ServiceInterface {
-        public void invoke();
+        public void invoke(String caller);
     }
 
     static class ServiceProvider implements ServiceInterface {
@@ -50,41 +55,63 @@ public class AspectServiceDependencyTest
         public ServiceProvider(Ensure e) {
             m_ensure = e;
         }
-        public void invoke() {
-            m_ensure.step(2);
+        public void invoke(String caller) {
+        	if (caller.equals("consumer.init")) {
+        		m_ensure.step(3);
+        	} else if (caller.equals("aspect.consumer.add")) {
+        		m_ensure.step(5);
+        	}
         }
     }
+    
+    static class ServiceProviderAspect implements ServiceInterface {
+    	private volatile ServiceInterface m_service;
+    	
+    	public ServiceProviderAspect() {
+		}
+
+		@Override
+		public void invoke(String caller) {
+			m_service.invoke("aspect." + caller);
+		}
+    }
 
     static class ServiceConsumer {
         private volatile ServiceInterface m_service;
         private final Ensure m_ensure;
+        private int addCount = 0;
 
         public ServiceConsumer(Ensure e) {
             m_ensure = e;
         }
         
         public void init() {
-            m_ensure.step(1);
-            m_service.invoke();
+            m_ensure.step(2);
+            m_service.invoke("consumer.init");
         }
         
         public void destroy() {
-            m_ensure.step(3);
-        }
-    }
-
-    static class ServiceConsumerCallbacks {
-        private final Ensure m_ensure;
-
-        public ServiceConsumerCallbacks(Ensure e) {
-            m_ensure = e;
+            m_ensure.step(7);
         }
         
         public void add(ServiceInterface service) {
-            m_ensure.step(4);
+        	m_service = service;
+        	switch (addCount) {
+        		case 0: m_ensure.step(1);
+        				break;
+        		case 1: m_ensure.step(4);
+        				// aspect had been added
+        				m_service.invoke("consumer.add");
+        				break;
+        		case 2: m_ensure.step(6);
+        				break;
+        		default:
+        	}
+        	addCount ++;
         }
         public void remove(ServiceInterface service) {
-            m_ensure.step(5);
-        }
+        	m_service = null;
+        }    
     }
+
 }

Added: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectServiceDependencyWithSwapCallbackTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectServiceDependencyWithSwapCallbackTest.java?rev=1595756&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectServiceDependencyWithSwapCallbackTest.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectServiceDependencyWithSwapCallbackTest.java Mon May 19 06:47:07 2014
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+package dm.it;
+
+import dm.Component;
+import dm.DependencyManager;
+
+
+public class AspectServiceDependencyWithSwapCallbackTest extends TestBase {
+    public void testServiceRegistrationAndConsumption() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = m.createComponent().setImplementation(new ServiceProvider(e)).setInterface(ServiceInterface.class.getName(), null);
+        Component sc = m.createComponent().setImplementation(new ServiceConsumer(e)).add(m.createServiceDependency()
+        		.setService(ServiceInterface.class)
+        		.setCallbacks("add", null, "remove", "swap")
+        		.setRequired(true));
+        Component asp = m.createAspectService(ServiceInterface.class, null, 100)
+        		.setImplementation(ServiceProviderAspect.class);
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(7);
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(String caller);
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(String caller) {
+        	if (caller.equals("consumer.init")) {
+        		m_ensure.step(3);
+        	} else if (caller.equals("aspect.consumer.add")) {
+        		m_ensure.step(5);
+        	}
+        }
+    }
+    
+    static class ServiceProviderAspect implements ServiceInterface {
+    	private volatile ServiceInterface m_service;
+    	
+    	public ServiceProviderAspect() {
+		}
+
+		@Override
+		public void invoke(String caller) {
+			m_service.invoke("aspect." + caller);
+		}
+    }
+
+    static class ServiceConsumer {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+        private int swapCount = 0;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            m_ensure.step(2);
+            m_service.invoke("consumer.init");
+        }
+        
+        public void destroy() {
+            m_ensure.step(6);
+        }
+        
+        public void add(ServiceInterface service) {
+        	m_service = service;
+        	m_ensure.step(1);
+        }
+        
+        public void remove(ServiceInterface service) {
+        	m_service = null;
+        }
+        
+        public void swap(ServiceInterface previous, ServiceInterface current) {
+        	switch (swapCount) {
+        		case 0: m_ensure.step(4);
+        				break;
+        		case 1: m_ensure.step(5);
+        				break;
+        		default:
+        	}
+        	m_service = current;
+        	swapCount ++;
+        }
+    }
+
+}

Propchange: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectServiceDependencyWithSwapCallbackTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWhiteboardTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWhiteboardTest.java?rev=1595756&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWhiteboardTest.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWhiteboardTest.java Mon May 19 06:47:07 2014
@@ -0,0 +1,177 @@
+package dm.it;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+import dm.Component;
+import dm.DependencyManager;
+
+public class AspectWhiteboardTest extends TestBase {
+
+	public void testWhiteboardConsumer() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create service providers and consumer
+        Component sp1 = m.createComponent().setImplementation(new ServiceProvider(e)).setInterface(ServiceInterface.class.getName(), null);
+        Component sp2 = m.createComponent().setImplementation(new ServiceProvider(e)).setInterface(ServiceInterface.class.getName(), null);
+        ServiceConsumer sci = new ServiceConsumer(e);
+        Component sc = m.createComponent().setImplementation(sci).add(m.createServiceDependency().setService(ServiceInterface.class).setRequired(false).setCallbacks("add", "remove"));
+        Component sa2 = m.createAspectService(ServiceInterface.class, null, 20, null).setImplementation(new ServiceAspect(e, 3));
+        Component sa1 = m.createAspectService(ServiceInterface.class, null, 10, null).setImplementation(new ServiceAspect(e, 4));
+        
+        // start with a service consumer
+        System.out.println("Adding consumer");
+        m.add(sc);
+        
+        // then add two providers, so the consumer will see two services
+        System.out.println("Adding 2 providers");
+        m.add(sp1);
+        m.add(sp2);
+        
+        // make sure consumer sees both services
+        Assert.assertEquals(2, sci.services());
+        
+        // add an aspect with ranking 20
+        System.out.println("Adding aspect with rank 20");
+        m.add(sa2);
+        
+        // make sure the consumer sees the two new aspects and no longer sees the two original services
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(20, sci.highestRanking());
+        Assert.assertEquals(20, sci.lowestRanking());
+        
+        // add an aspect with ranking 10
+        System.out.println("Adding aspect with rank 10");
+        m.add(sa1);
+        
+        // make sure the consumer still sees the two aspects with ranking 20
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(20, sci.highestRanking());
+        Assert.assertEquals(20, sci.lowestRanking());
+        
+        // remove the aspect with ranking 20
+        System.out.println("Removing aspect with rank 20");
+        m.remove(sa2);
+        
+        // make sure the consumer now sees the aspects with ranking 10
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(10, sci.highestRanking());
+        Assert.assertEquals(10, sci.lowestRanking());
+        
+        // remove one of the original services
+        System.out.println("Removing 1 service");
+        m.remove(sp1);
+        
+        // make sure the aspect of that service goes away
+        Assert.assertEquals(1, sci.services());
+        Assert.assertEquals(10, sci.highestRanking());
+        Assert.assertEquals(10, sci.lowestRanking());
+        
+        // remove the aspect with ranking 10
+        System.out.println("Removing aspect with rank 10");
+        m.remove(sa1);
+        
+        // make sure only the original service remains
+        Assert.assertEquals(1, sci.services());
+        Assert.assertEquals(0, sci.highestRanking());
+        Assert.assertEquals(0, sci.lowestRanking());
+
+        System.out.println("Done with test");
+
+        // end of test
+        m.remove(sa2);
+        m.remove(sp2);
+        m.remove(sc);
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(Runnable run);
+    }
+    
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(Runnable run) {
+            run.run();
+        }
+    }
+    
+    static class ServiceAspect implements ServiceInterface {
+        private final Ensure m_ensure;
+        private volatile ServiceInterface m_parentService;
+        private final int m_step;
+        
+        public ServiceAspect(Ensure e, int step) {
+            m_ensure = e;
+            m_step = step;
+        }
+        public void start() {
+        }
+        
+        public void invoke(Runnable run) {
+            m_ensure.step(m_step);
+            m_parentService.invoke(run);
+        }
+        
+        public void stop() {
+        }
+    }
+
+    static class ServiceConsumer implements Runnable {
+        private List m_services = new ArrayList();
+        private final Ensure m_ensure;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            Thread t = new Thread(this);
+            t.start();
+        }
+        
+        public void run() {
+        }
+        
+        public int services() {
+            return m_services.size();
+        }
+        
+        public int highestRanking() {
+            int ranking = Integer.MIN_VALUE;
+            for (int i = 0; i < m_services.size(); i++) {
+                ServiceReference ref = (ServiceReference) m_services.get(i);
+                Integer r = (Integer) ref.getProperty(Constants.SERVICE_RANKING);
+                int rank = r == null ? 0 : r.intValue();
+                ranking = Math.max(ranking, rank);
+            }
+            return ranking;
+        }
+        public int lowestRanking() {
+            int ranking = Integer.MAX_VALUE;
+            for (int i = 0; i < m_services.size(); i++) {
+                ServiceReference ref = (ServiceReference) m_services.get(i);
+                Integer r = (Integer) ref.getProperty(Constants.SERVICE_RANKING);
+                int rank = r == null ? 0 : r.intValue();
+                ranking = Math.min(ranking, rank);
+            }
+            return ranking;
+        }
+        
+        public void add(ServiceReference ref, ServiceInterface svc) {
+            System.out.println("Added: " + ServiceUtil.toString(ref));
+            m_services.add(ref);
+        }
+        public void remove(ServiceReference ref, ServiceInterface svc) {
+            System.out.println("Removed: " + ServiceUtil.toString(ref));
+            m_services.remove(ref);
+        }
+    }
+}

Propchange: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWhiteboardTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWithCallbacksServiceDependencyTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWithCallbacksServiceDependencyTest.java?rev=1595756&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWithCallbacksServiceDependencyTest.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWithCallbacksServiceDependencyTest.java Mon May 19 06:47:07 2014
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+package dm.it;
+
+import dm.Component;
+import dm.DependencyManager;
+
+
+public class AspectWithCallbacksServiceDependencyTest extends TestBase {
+    public void testServiceRegistrationAndConsumption() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = m.createComponent().setImplementation(new ServiceProvider(e)).setInterface(ServiceInterface.class.getName(), null);
+        Component sc = m.createComponent().setImplementation(new ServiceConsumer(e)).add(m.createServiceDependency()
+        		.setService(ServiceInterface.class)
+        		.setCallbacks("add", "remove")
+        		.setRequired(true));
+        Component asp = m.createAspectService(ServiceInterface.class, null, 100, "add", null, "remove", "swap")
+        		.setImplementation(ServiceProviderAspect.class);
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(8);
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(String caller);
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(String caller) {
+        	if (caller.equals("consumer.init")) {
+        		m_ensure.step(3);
+        	} else if (caller.equals("aspect.consumer.add")) {
+        		m_ensure.step(5);
+        	}
+        }
+    }
+    
+    static class ServiceProviderAspect implements ServiceInterface {
+    	private volatile ServiceInterface m_service;
+    	
+    	public ServiceProviderAspect() {
+		}
+
+		@Override
+		public void invoke(String caller) {
+			m_service.invoke("aspect." + caller);
+		}
+		
+		public void add(ServiceInterface service) {
+			m_service = service;
+		}
+		
+		public void remove(ServiceInterface service) {
+			m_service = null;
+		}
+		
+		public void swap(ServiceInterface previous, ServiceInterface current) {
+			m_service = current;
+		}
+    }
+
+    static class ServiceConsumer {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+        private int addCount = 0;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            m_ensure.step(2);
+            m_service.invoke("consumer.init");
+        }
+        
+        public void destroy() {
+            m_ensure.step(7);
+        }
+        
+        public void add(ServiceInterface service) {
+        	m_service = service;
+        	switch (addCount) {
+        		case 0: m_ensure.step(1);
+        				break;
+        		case 1: m_ensure.step(4);
+        				// aspect had been added
+        				m_service.invoke("consumer.add");
+        				break;
+        		case 2: m_ensure.step(6);
+        				break;
+        		default:
+        	}
+        	addCount ++;
+        }
+        public void remove(ServiceInterface service) {
+        	m_service = null;
+        }    
+    }
+
+}

Propchange: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWithCallbacksServiceDependencyTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWithPropagationTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWithPropagationTest.java?rev=1595756&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWithPropagationTest.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWithPropagationTest.java Mon May 19 06:47:07 2014
@@ -0,0 +1,652 @@
+package dm.it;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import junit.framework.Assert;
+
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+import dm.Component;
+import dm.DependencyManager;
+
+/**
+ * Test for aspects with service properties propagations.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectWithPropagationTest extends TestBase {
+    private final static int ASPECTS = 3;
+    private final Set<Integer> _randoms = new HashSet<Integer>();
+    private final Random _rnd = new Random();
+    private static Ensure m_invokeStep;
+    private static Ensure m_changeStep;
+    
+    /**
+     * This test does the following:
+     * 
+     * - Create S service
+     * - Create some S Aspects
+     * - Create a Client, depending on S (actually, on the top-level S aspect)
+     * - Client has a "change" callack in order to track S service properties modifications.
+     * - First, invoke Client.invoke(): all S aspects, and finally original S service must be invoked orderly.
+     * - Modify S original service properties, and check if all aspects, and the client has been orderly called in their "change" callback.
+     * - Modify the First lowest ranked aspect (rank=1), and check if all aspects, and client have been orderly called in their "change" callback.
+     */
+    public void testAspectsWithPropagation() {
+        System.out.println("----------- Running testAspectsWithPropagation ...");
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        m_invokeStep = new Ensure(); 
+        
+        // Create our original "S" service.
+        Dictionary props = new Hashtable();
+        props.put("foo", "bar");
+        Component s = m.createComponent()
+                .setImplementation(new SImpl())
+                .setInterface(S.class.getName(), props);
+        
+        // Create an aspect aware client, depending on "S" service.
+        Client clientImpl;
+        Component client = m.createComponent()
+                .setImplementation((clientImpl = new Client()))
+                .add(m.createServiceDependency()
+                     .setService(S.class)
+                     .setRequired(true)
+                     .setCallbacks("add", "change", "remove", "swap"));
+
+        // Create some "S" aspects
+        Component[] aspects = new Component[ASPECTS];
+        for (int rank = 1; rank <= ASPECTS; rank ++) {
+            aspects[rank-1] = m.createAspectService(S.class, null, rank, "add", "change", "remove", "swap")
+                    .setImplementation(new A("A" + rank, rank));
+            props = new Hashtable();
+            props.put("a" + rank, "v" + rank);
+            aspects[rank-1].setServiceProperties(props);
+        }                                    
+              
+        // Register client
+        m.add(client);
+        
+        // Randomly register aspects and original service
+        boolean originalServiceAdded = false;
+        for (int i = 0; i < ASPECTS; i ++) {
+            int index = getRandomAspect();
+            m.add(aspects[index]);
+            if (_rnd.nextBoolean()) {
+                m.add(s);
+                originalServiceAdded = true;
+            }
+        }
+        if (! originalServiceAdded) {
+            m.add(s);
+        }
+              
+        // All set, check if client has inherited from top level aspect properties + original service properties
+        Map check = new HashMap();
+        check.put("foo", "bar");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS);
+        checkServiceProperties(check, clientImpl.getServiceProperties());
+
+        // Now invoke client, which orderly calls all aspects in the chain, and finally the original service "S".
+        System.out.println("-------------------------- Invoking client.");
+        clientImpl.invoke();
+        m_invokeStep.waitForStep(ASPECTS+1, 5000);
+        
+        // Now, change original service "S" properties: this will orderly trigger "change" callbacks on aspects, and on client. 
+        System.out.println("-------------------------- Modifying original service properties.");
+        m_changeStep = new Ensure();
+        props = new Hashtable();
+        props.put("foo", "barModified");
+        s.setServiceProperties(props);
+        
+        // Check if aspects and client have been orderly called in their "changed" callback
+        m_changeStep.waitForStep(ASPECTS+1, 5000);
+        
+        // Check if modified "foo" original service property has been propagated
+        check = new HashMap();
+        check.put("foo", "barModified");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS); // we only see top-level aspect service properties
+        checkServiceProperties(check, clientImpl.getServiceProperties());
+        
+        // Now, change the top-level ranked aspect: it must propagate to all upper aspects, as well as to the client
+        System.out.println("-------------------------- Modifying top-level aspect service properties.");
+
+        m_changeStep = new Ensure();
+        for (int i = 1; i <= ASPECTS; i ++) {
+            m_changeStep.step(i); // only client has to be changed.
+        }
+        props = new Hashtable();
+        props.put("a" + ASPECTS, "v" + ASPECTS + "-Modified");
+        aspects[ASPECTS-1].setServiceProperties(props); // That triggers change callbacks for upper aspects (with rank >= 2)
+        m_changeStep.waitForStep(ASPECTS+1, 5000); // check if client have been changed.
+        
+        // Check if top level aspect service properties have been propagated up to the client.
+        check = new HashMap();
+        check.put("foo", "barModified");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS + "-Modified");
+        checkServiceProperties(check, clientImpl.getServiceProperties());
+
+        // Clear all components.
+        m_changeStep = null;
+        m.clear();
+    }    
+    
+    /**
+     * This test does the following:
+     * 
+     * - Create S service
+     * - Create some S Aspects without any callbacks (add/change/remove/swap)
+     * - Create a Client, depending on S (actually, on the top-level S aspect)
+     * - Client has a "change" callack in order to track S service properties modifications.
+     * - First, invoke Client.invoke(): all S aspects, and finally original S service must be invoked orderly.
+     * - Modify S original service properties, and check if the client has been called in its "change" callback.
+     */
+    public void testAspectsWithPropagationAndNoCallbacks() {
+        System.out.println("----------- Running testAspectsWithPropagation ...");
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        m_invokeStep = new Ensure(); 
+        
+        // Create our original "S" service.
+        Dictionary props = new Hashtable();
+        props.put("foo", "bar");
+        Component s = m.createComponent()
+                .setImplementation(new SImpl())
+                .setInterface(S.class.getName(), props);
+        
+        // Create an aspect aware client, depending on "S" service.
+        Client clientImpl;
+        Component client = m.createComponent()
+                .setImplementation((clientImpl = new Client()))
+                .add(m.createServiceDependency()
+                     .setService(S.class)
+                     .setRequired(true)
+                     .setCallbacks("add", "change", "remove"));
+
+        // Create some "S" aspects
+        Component[] aspects = new Component[ASPECTS];
+        for (int rank = 1; rank <= ASPECTS; rank ++) {
+            aspects[rank-1] = m.createAspectService(S.class, null, rank)
+                    .setImplementation(new A("A" + rank, rank));
+            props = new Hashtable();
+            props.put("a" + rank, "v" + rank);
+            aspects[rank-1].setServiceProperties(props);
+        }                                    
+              
+        // Register client
+        m.add(client);
+        
+        // Randomly register aspects and original service
+        boolean originalServiceAdded = false;
+        for (int i = 0; i < ASPECTS; i ++) {
+            int index = getRandomAspect();
+            m.add(aspects[index]);
+            if (_rnd.nextBoolean()) {
+                m.add(s);
+                originalServiceAdded = true;
+            }
+        }
+        if (! originalServiceAdded) {
+            m.add(s);
+        }
+              
+        // All set, check if client has inherited from top level aspect properties + original service properties
+        Map check = new HashMap();
+        check.put("foo", "bar");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS);
+        checkServiceProperties(check, clientImpl.getServiceProperties());
+
+        // Now invoke client, which orderly calls all aspects in the chain, and finally the original service "S".
+        System.out.println("-------------------------- Invoking client.");
+        clientImpl.invoke();
+        m_invokeStep.waitForStep(ASPECTS+1, 5000);
+        
+        // Now, change original service "S" properties: this will orderly trigger "change" callbacks on aspects, and on client. 
+        System.out.println("-------------------------- Modifying original service properties.");
+        m_changeStep = new Ensure();
+        for (int i = 1; i <= ASPECTS; i ++) {
+            m_changeStep.step(i); // skip aspects, which have no "change" callbacks.
+        }
+        props = new Hashtable();
+        props.put("foo", "barModified");
+        s.setServiceProperties(props);
+        
+        // Check if aspects and client have been orderly called in their "changed" callback
+        m_changeStep.waitForStep(ASPECTS+1, 5000);
+        
+        // Check if modified "foo" original service property has been propagated
+        check = new HashMap();
+        check.put("foo", "barModified");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS); // we only see top-level aspect service properties
+        checkServiceProperties(check, clientImpl.getServiceProperties());
+        
+        // Clear all components.
+        m_changeStep = null;
+        m.clear();
+    }    
+    
+    /**
+     * This test does the following:
+     * 
+     * - Create S service
+     * - Create some S Aspects
+     * - Create S2 Adapter, which adapts S to S2
+     * - Create Client2, which depends on S2. Client2 listens to S2 property change events.
+     * - Now, invoke Client2.invoke(): all S aspects, and finally original S service must be invoked orderly.
+     * - Modify S original service properties, and check if all aspects, S2 Adapter, and Client2 have been orderly called in their "change" callback.
+     */
+    public void testAdapterWithAspectsAndPropagation() {
+        System.out.println("----------- Running testAdapterWithAspectsAndPropagation ...");
+
+        DependencyManager m = new DependencyManager(context);
+        m_invokeStep = new Ensure(); 
+        
+        // Create our original "S" service.
+        Dictionary props = new Hashtable();
+        props.put("foo", "bar");
+        Component s = m.createComponent()
+                .setImplementation(new SImpl())
+                .setInterface(S.class.getName(), props);
+        
+        // Create some "S" aspects
+        Component[] aspects = new Component[ASPECTS];
+        for (int rank = 1; rank <= ASPECTS; rank ++) {
+            aspects[rank-1] = m.createAspectService(S.class, null, rank, "add", "change", "remove", "swap")
+                    .setImplementation(new A("A" + rank, rank));
+            props = new Hashtable();
+            props.put("a" + rank, "v" + rank);
+            aspects[rank-1].setServiceProperties(props);
+        } 
+        
+        // Create S2 adapter (which adapts S1 to S2 interface)
+        Component adapter = m.createAdapterService(S.class, null, "add", "change", "remove", "swap")
+                .setInterface(S2.class.getName(), null)
+                .setImplementation(new S2Impl());
+        
+        // Create Client2, which depends on "S2" service.
+        Client2 client2Impl;
+        Component client2 = m.createComponent()
+                .setImplementation((client2Impl = new Client2()))
+                .add(m.createServiceDependency()
+                     .setService(S2.class)
+                     .setRequired(true)
+                     .setCallbacks("add", "change", null));
+              
+        // Register client2
+        m.add(client2);
+        
+        // Register S2 adapter
+        m.add(adapter);
+        
+        // Randomly register aspects, original service
+        boolean originalServiceAdded = false;
+        for (int i = 0; i < ASPECTS; i ++) {
+            int index = getRandomAspect();
+            m.add(aspects[index]);
+            if (_rnd.nextBoolean()) {
+                m.add(s);
+                originalServiceAdded = true;
+            }
+        }
+        if (! originalServiceAdded) {
+            m.add(s);
+        }
+             
+        // Now invoke client2, which orderly calls all S1 aspects, then S1Impl, and finally S2 service
+        System.out.println("-------------------------- Invoking client2.");
+        client2Impl.invoke2();
+        m_invokeStep.waitForStep(ASPECTS+2, 5000);
+        
+        // Now, change original service "S" properties: this will orderly trigger "change" callbacks on aspects, S2Impl, and Client2.
+        System.out.println("-------------------------- Modifying original service properties.");
+        m_changeStep = new Ensure();
+        props = new Hashtable();
+        props.put("foo", "barModified");
+        s.setServiceProperties(props);
+        
+        // Check if aspects and Client2 have been orderly called in their "changed" callback
+        m_changeStep.waitForStep(ASPECTS+2, 5000);
+        
+        // Check if modified "foo" original service property has been propagated to Client2
+        Map check = new HashMap();
+        check.put("foo", "barModified");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS);
+        checkServiceProperties(check, client2Impl.getServiceProperties());
+        
+        // Clear all components.
+        m_changeStep = null;
+        m.clear();
+    }    
+    
+    /**
+     * This test does the following:
+     * 
+     * - Create S service
+     * - Create some S Aspects without any callbacks (add/change/remove)
+     * - Create S2 Adapter, which adapts S to S2 (but does not have any add/change/remove callbacks)
+     * - Create Client2, which depends on S2. Client2 listens to S2 property change events.
+     * - Now, invoke Client2.invoke(): all S aspects, and finally original S service must be invoked orderly.
+     * - Modify S original service properties, and check if all aspects, S2 Adapter, and Client2 have been orderly called in their "change" callback.
+     */
+    public void testAdapterWithAspectsAndPropagationNoCallbacks() {
+        System.out.println("----------- Running testAdapterWithAspectsAndPropagationNoCallbacks ...");
+
+        DependencyManager m = new DependencyManager(context);
+        m_invokeStep = new Ensure(); 
+        
+        // Create our original "S" service.
+        Dictionary props = new Hashtable();
+        props.put("foo", "bar");
+        Component s = m.createComponent()
+                .setImplementation(new SImpl())
+                .setInterface(S.class.getName(), props);
+        
+        // Create some "S" aspects
+        Component[] aspects = new Component[ASPECTS];
+        for (int rank = 1; rank <= ASPECTS; rank ++) {
+            aspects[rank-1] = m.createAspectService(S.class, null, rank)
+                    .setImplementation(new A("A" + rank, rank));
+            props = new Hashtable();
+            props.put("a" + rank, "v" + rank);
+            aspects[rank-1].setServiceProperties(props);
+        } 
+        
+        // Create S2 adapter (which adapts S1 to S2 interface)
+        Component adapter = m.createAdapterService(S.class, null)
+                .setInterface(S2.class.getName(), null)
+                .setImplementation(new S2Impl());
+        
+        // Create Client2, which depends on "S2" service.
+        Client2 client2Impl;
+        Component client2 = m.createComponent()
+                .setImplementation((client2Impl = new Client2()))
+                .add(m.createServiceDependency()
+                     .setService(S2.class)
+                     .setRequired(true)
+                     .setCallbacks("add", "change", "remove"));
+              
+        // Register client2
+        m.add(client2);
+        
+        // Register S2 adapter
+        m.add(adapter);
+        
+        // Randomly register aspects, original service
+        boolean originalServiceAdded = false;
+        for (int i = 0; i < ASPECTS; i ++) {
+            int index = getRandomAspect();
+            m.add(aspects[index]);
+            if (_rnd.nextBoolean()) {
+                m.add(s);
+                originalServiceAdded = true;
+            }
+        }
+        if (! originalServiceAdded) {
+            m.add(s);
+        }
+             
+        // Now invoke client2, which orderly calls all S1 aspects, then S1Impl, and finally S2 service
+        System.out.println("-------------------------- Invoking client2.");
+        client2Impl.invoke2();
+        m_invokeStep.waitForStep(ASPECTS+2, 5000);
+        
+        // Now, change original service "S" properties: this will orderly trigger "change" callbacks on aspects, S2Impl, and Client2.
+        System.out.println("-------------------------- Modifying original service properties.");
+        m_changeStep = new Ensure();
+        for (int i = 1; i <= ASPECTS+1; i ++) {
+            m_changeStep.step(i); // skip all aspects and the adapter
+        }
+        props = new Hashtable();
+        props.put("foo", "barModified");
+        s.setServiceProperties(props);
+        
+        // Check if Client2 has been called in its "changed" callback
+        m_changeStep.waitForStep(ASPECTS+2, 5000);
+        
+        // Check if modified "foo" original service property has been propagated to Client2
+        Map check = new HashMap();
+        check.put("foo", "barModified");
+        for (int i = 1; i < (ASPECTS - 1); i ++) {
+            check.put("a" + i, null); // we must not inherit from lower ranks, only from the top-level aspect.
+        }
+        check.put("a" + ASPECTS, "v" + ASPECTS);
+        checkServiceProperties(check, client2Impl.getServiceProperties());
+        
+        // Clear all components.
+        m_changeStep = null;
+        m.clear();
+    }    
+    
+   private void checkServiceProperties(Map<?, ?> check, Dictionary properties) {
+        for (Object key : check.keySet()) {
+            Object val = check.get(key);   
+            if (val == null) {
+                Assert.assertNull(properties.get(key));
+            } else {
+                Assert.assertEquals(val, properties.get(key));
+            }
+        }
+    }
+    
+    private int getRandomAspect() {
+        int index = 0;  
+        do {
+            index = _rnd.nextInt(ASPECTS);            
+        } while (_randoms.contains(new Integer(index)));
+        _randoms.add(new Integer(index));
+        return index;
+    }
+
+    // S Service
+    public static interface S {
+        public void invoke();
+    }
+    
+    // S ServiceImpl
+    static class SImpl implements S {
+        public SImpl() {
+        }
+        
+        public String toString() {
+            return "S";
+        }
+        
+        public void invoke() {
+             m_invokeStep.step(ASPECTS+1);
+        }
+    }
+    
+    // S Aspect
+    static class A implements S {
+        private final String m_name;
+        private volatile ServiceRegistration m_registration;
+        private volatile S m_next;
+        private final int m_rank;
+
+        public A(String name, int rank) {
+            m_name = name;
+            m_rank = rank;
+        }
+        
+        public String toString() {
+            return m_name;
+        }
+        
+        public void invoke() {
+            int rank = ServiceUtil.getRanking(m_registration.getReference());
+            m_invokeStep.step(ASPECTS - rank + 1);
+            m_next.invoke();
+        }
+               
+        public void add(ServiceReference ref, S s) {
+            System.out.println("+++ A" + m_rank + ".add:" + s + "/" + ServiceUtil.toString(ref));   
+            m_next = s;
+        }
+
+        public void swap(ServiceReference oldSRef, S oldS, ServiceReference newSRef, S newS) {
+            System.out.println("+++ A" + m_rank + ".swap: new=" + newS + ", props=" + ServiceUtil.toString(newSRef));
+            Assert.assertTrue(m_next == oldS);
+            m_next = newS;
+        }
+
+        public void change(ServiceReference props, S s) {   
+            System.out.println("+++ A" + m_rank + ".change: s=" + s + ", props=" + ServiceUtil.toString(props));
+            if (m_changeStep != null) {
+                int rank = ServiceUtil.getRanking(m_registration.getReference());
+                m_changeStep.step(rank);
+            }
+        }
+        
+        public void remove(ServiceReference props, S s) {
+            System.out.println("+++ A" + m_rank + ".remove: " + s + ", props=" + ServiceUtil.toString(props));
+        }
+    }
+    
+    // Aspect aware client, depending of "S" service aspects.
+    static class Client {
+        private volatile S m_s;
+        private volatile ServiceReference m_sRef;
+
+        public Client() {
+        }
+        
+        public Dictionary getServiceProperties() {
+            Dictionary props = new Hashtable();
+            for (String key : m_sRef.getPropertyKeys()) {
+                props.put(key, m_sRef.getProperty(key));
+            }
+            return props;
+        }
+
+        public void invoke() {
+            m_s.invoke();           
+        }
+
+        public String toString() {
+            return "Client";
+        }
+        
+        public void add(ServiceReference ref, S s) {
+            System.out.println("+++ Client.add: " + s + "/" + ServiceUtil.toString(ref));
+            m_s = s;
+            m_sRef = ref;
+        }
+              
+        public void swap(ServiceReference oldSRef, S oldS, ServiceReference newSRef, S newS) {
+            System.out.println("+++ Client.swap: m_s = " + m_s + ", old=" + oldS + ", oldProps=" + ServiceUtil.toString(oldSRef) + ", new=" + newS + ", props=" + ServiceUtil.toString(newSRef));
+            Assert.assertTrue(m_s == oldS);
+            m_s = newS;
+            m_sRef = newSRef;
+        }
+
+        public void change(ServiceReference properties, S s) {
+            System.out.println("+++ Client.change: s=" + s + ", props=" + ServiceUtil.toString(properties));
+            if (m_changeStep != null) {
+                m_changeStep.step(ASPECTS+1);
+            }
+        }
+        
+        public void remove(ServiceReference props, S s) {
+            System.out.println("+++ Client.remove: " + s + ", props=" + ServiceUtil.toString(props));
+        }
+    }
+    
+    // S2 Service
+    public static interface S2 {
+        public void invoke2();
+    }
+
+    // S2 impl, which adapts S1 interface to S2 interface
+    static class S2Impl implements S2 {
+        private volatile S m_s; // we shall see top-level aspect on S service
+        
+        public void add(ServiceReference ref, S s) {
+            System.out.println("+++ S2Impl.add: " + s + "/" + ServiceUtil.toString(ref));
+            m_s = s;
+        }
+              
+        public void swap(ServiceReference oldSRef, S oldS, ServiceReference newSRef, S newS) {
+            System.out.println("+++ S2Impl.swap: new=" + newS + ", props=" + ServiceUtil.toString(newSRef));
+            m_s = newS;
+        }
+
+        public void change(ServiceReference properties, S s) {
+            System.out.println("+++ S2Impl.change: s=" + s + ", props=" + ServiceUtil.toString(properties));
+            if (m_changeStep != null) {
+                m_changeStep.step(ASPECTS+1);
+            }
+        }
+        
+        public void remove(ServiceReference props, S s) {
+            System.out.println("+++ S2Impl.remove: " + s + ", props=" + ServiceUtil.toString(props));
+        }
+        
+        public void invoke2() {
+            m_s.invoke();
+            m_invokeStep.step(ASPECTS + 2); // All aspects, and S1Impl have been invoked
+        }
+
+        public String toString() {
+            return "S2";
+        }        
+    }
+    
+    // Client2 depending on S2.
+    static class Client2 {
+        private volatile S2 m_s2;
+        private volatile ServiceReference m_s2Ref;
+
+        public Dictionary getServiceProperties() {
+            Dictionary props = new Hashtable();
+            for (String key : m_s2Ref.getPropertyKeys()) {
+                props.put(key, m_s2Ref.getProperty(key));
+            }
+            return props;
+        }
+
+        public void invoke2() {
+            m_s2.invoke2();           
+        }
+
+        public String toString() {
+            return "Client2";
+        }  
+                
+        public void add(ServiceReference ref, S2 s2) {
+            System.out.println("+++ Client2.add: " + s2 + "/" + ServiceUtil.toString(ref));
+            m_s2 = s2;
+            m_s2Ref = ref;
+        }
+
+        public void change(ServiceReference props, S2 s2) {   
+            System.out.println("+++ Client2.change: s2=" + s2 + ", props=" + ServiceUtil.toString(props));
+            if (m_changeStep != null) {
+                m_changeStep.step(ASPECTS + 2); // S1Impl, all aspects, and S2 adapters have been changed before us.
+            }
+        }
+    }
+}

Propchange: felix/sandbox/pderop/dependencymanager-prototype/dm.it/src/dm/it/AspectWithPropagationTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/Component.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/Component.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/Component.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/Component.java Mon May 19 06:47:07 2014
@@ -33,4 +33,8 @@ public interface Component {
 	public DependencyManager getDependencyManager();
 	public ComponentDeclaration getComponentDeclaration();
 	public Component setExecutor(Executor executor);
+	
+	// TODO ASPECTS: Methods added for debugging AspectRaceTest, but we might just leave the 'debug' features in there.
+	public Executor getExecutor();
+	public void setDebug(String string);
 }

Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/DependencyActivatorBase.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/DependencyActivatorBase.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/DependencyActivatorBase.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/DependencyActivatorBase.java Mon May 19 06:47:07 2014
@@ -18,10 +18,11 @@
  */
 package dm;
 
-import dm.impl.Logger;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 
+import dm.impl.Logger;
+
 /**
  * Base bundle activator class. Subclass this activator if you want to use dependency
  * management in your bundle. There are two methods you should implement:

Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/DependencyManager.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/DependencyManager.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/DependencyManager.java Mon May 19 06:47:07 2014
@@ -32,12 +32,13 @@ import org.osgi.framework.BundleExceptio
 import org.osgi.framework.FrameworkUtil;
 
 import dm.context.ComponentContext;
-import dm.impl.FactoryConfigurationAdapterImpl;
 import dm.impl.AdapterServiceImpl;
+import dm.impl.AspectServiceImpl;
 import dm.impl.BundleAdapterImpl;
 import dm.impl.BundleDependencyImpl;
 import dm.impl.ComponentImpl;
 import dm.impl.ConfigurationDependencyImpl;
+import dm.impl.FactoryConfigurationAdapterImpl;
 import dm.impl.Logger;
 import dm.impl.ResourceAdapterImpl;
 import dm.impl.ResourceDependencyImpl;
@@ -222,24 +223,20 @@ public class DependencyManager {
         return m_components;
     }
 
-    public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String attributeName) {
-        // TODO
-        return null;
+    public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String autoConfig) {
+        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, autoConfig, null, null, null, null);
     }
     
     public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking) {
-        // TODO
-        return null;
+        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, null, null, null);
     }
     
     public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String add, String change, String remove) {
-        // TODO
-        return null;
+        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove, null);
     }
     
     public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String add, String change, String remove, String swap) {
-        // TODO
-        return null;	
+    	return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove, swap);    
     }
 
     public void clear() {

Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/ServiceDependency.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/ServiceDependency.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/ServiceDependency.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/ServiceDependency.java Mon May 19 06:47:07 2014
@@ -20,4 +20,7 @@ public interface ServiceDependency exten
     public ServiceDependency setDefaultImplementation(Object implementation);
     public ServiceDependency setPropagate(boolean propagate);
     public ServiceDependency setPropagate(Object instance, String method);
+    
+    // TODO ASPECTS: Added debug option. Decide whether we might just leave it in.
+    public void setDebug(String debugKey);
 }

Modified: felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/AbstractDecorator.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/AbstractDecorator.java?rev=1595756&r1=1595755&r2=1595756&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/AbstractDecorator.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/dm/src/dm/impl/AbstractDecorator.java Mon May 19 06:47:07 2014
@@ -20,7 +20,6 @@ package dm.impl;
 
 import java.net.URL;
 import java.util.Dictionary;
-import java.util.Iterator;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;