You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by cs...@apache.org on 2018/05/28 14:29:01 UTC

svn commit: r1832399 - in /aries/trunk/component-dsl: component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ itests/src/main/java/org/apache/aries/component/dsl/test/

Author: csierra
Date: Mon May 28 14:29:00 2018
New Revision: 1832399

URL: http://svn.apache.org/viewvc?rev=1832399&view=rev
Log:
[Component-DSL] Get initial configuration state

so configuration is not always set to empty and then initialized
asynchronously to the existing value

Modified:
    aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
    aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
    aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java

Modified: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java?rev=1832399&r1=1832398&r2=1832399&view=diff
==============================================================================
--- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java (original)
+++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java Mon May 28 14:29:00 2018
@@ -17,11 +17,18 @@
 
 package org.apache.aries.component.dsl.internal;
 
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.cm.ManagedService;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationEvent;
+import org.osgi.service.cm.ConfigurationListener;
 
 import java.util.Dictionary;
 import java.util.Hashtable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -32,7 +39,7 @@ public class ConfigurationOSGiImpl exten
 
 	public ConfigurationOSGiImpl(String pid) {
 		super((bundleContext, op) -> {
-			AtomicReference<Dictionary<String, ?>> atomicReference =
+			AtomicReference<Configuration> atomicReference =
 				new AtomicReference<>(null);
 
 			AtomicReference<Runnable>
@@ -40,17 +47,55 @@ public class ConfigurationOSGiImpl exten
 
 			AtomicBoolean closed = new AtomicBoolean();
 
-			ServiceRegistration<ManagedService> serviceRegistration =
+			CountDownLatch countDownLatch = new CountDownLatch(1);
+
+			ServiceRegistration<?> serviceRegistration =
 				bundleContext.registerService(
-					ManagedService.class,
-					properties -> {
-						atomicReference.set(properties);
+					ConfigurationListener.class,
+					(ConfigurationEvent configurationEvent) -> {
+						if (configurationEvent.getFactoryPid() != null ||
+							!configurationEvent.getPid().equals(pid)) {
+
+							return;
+						}
+
+						try {
+							countDownLatch.await(1, TimeUnit.MINUTES);
+						}
+						catch (InterruptedException e) {
+							return;
+						}
+
+						Configuration configuration;
+
+						if (configurationEvent.getType() ==
+							ConfigurationEvent.CM_DELETED) {
 
-						signalLeave(terminatorAtomicReference);
+							atomicReference.set(null);
 
-						if (properties != null) {
+							signalLeave(terminatorAtomicReference);
+						}
+						else {
+							 configuration = getConfiguration(
+							 	bundleContext, configurationEvent);
+
+							if (configuration == null) {
+								return;
+							}
+
+							Configuration old = atomicReference.get();
+
+							if (old == null ||
+								configuration.getChangeCount() !=
+									old.getChangeCount()) {
+
+								atomicReference.set(configuration);
+							}
+
+							signalLeave(terminatorAtomicReference);
+							
 							terminatorAtomicReference.set(
-								op.apply(properties));
+								op.apply(configuration.getProperties()));
 
 							if (closed.get()) {
 								/*
@@ -59,14 +104,27 @@ public class ConfigurationOSGiImpl exten
 								directly instead of storing it
 								*/
 								signalLeave(terminatorAtomicReference);
-
-								return;
 							}
 						}
 					},
-					new Hashtable<String, Object>() {{
-						put("service.pid", pid);
-					}});
+					new Hashtable<>());
+
+			ServiceReference<ConfigurationAdmin> serviceReference =
+				bundleContext.getServiceReference(ConfigurationAdmin.class);
+
+			if (serviceReference != null) {
+				Configuration configuration = getConfiguration(
+                    bundleContext, pid, serviceReference);
+
+				if (configuration != null) {
+                    atomicReference.set(configuration);
+
+                    terminatorAtomicReference.set(
+                        op.apply(configuration.getProperties()));
+                }
+			}
+
+			countDownLatch.countDown();
 
 			return new OSGiResultImpl(
 				() -> {
@@ -79,6 +137,43 @@ public class ConfigurationOSGiImpl exten
 		});
 	}
 
+	private static Configuration getConfiguration(
+		BundleContext bundleContext, ConfigurationEvent configurationEvent) {
+
+		String pid = configurationEvent.getPid();
+
+		ServiceReference<ConfigurationAdmin> reference =
+			configurationEvent.getReference();
+
+		return getConfiguration(bundleContext, pid, reference);
+	}
+
+	private static Configuration getConfiguration(
+		BundleContext bundleContext, String pid,
+		ServiceReference<ConfigurationAdmin> reference) {
+
+		ConfigurationAdmin configurationAdmin = bundleContext.getService(
+			reference);
+
+		try {
+			Configuration[] configurations =
+                configurationAdmin.listConfigurations(
+                    "(&(service.pid=" + pid + ")(!(service.factoryPid=*)))");
+
+			if (configurations.length == 0) {
+                return null;
+            }
+
+			return configurations[0];
+		}
+		catch (Exception e) {
+			return null;
+		}
+		finally {
+			bundleContext.ungetService(reference);
+		}
+	}
+
 	private static void signalLeave(
 		AtomicReference<Runnable> terminatorAtomicReference) {
 

Modified: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java?rev=1832399&r1=1832398&r2=1832399&view=diff
==============================================================================
--- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java (original)
+++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java Mon May 28 14:29:00 2018
@@ -17,37 +17,123 @@
 
 package org.apache.aries.component.dsl.internal;
 
-import org.apache.aries.component.dsl.Publisher;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedServiceFactory;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationEvent;
+import org.osgi.service.cm.ConfigurationListener;
 
 import java.util.Dictionary;
 import java.util.Hashtable;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * @author Carlos Sierra Andrés
  */
-public class ConfigurationsOSGiImpl
-	extends OSGiImpl<Dictionary<String, ?>> {
+public class ConfigurationsOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 
 	public ConfigurationsOSGiImpl(String factoryPid) {
 		super((bundleContext, op) -> {
-			Map<String, Runnable> results = new ConcurrentHashMap<>();
+			ConcurrentHashMap<String, Configuration> configurations =
+				new ConcurrentHashMap<>();
+
+			ConcurrentHashMap<String, Runnable> terminators =
+				new ConcurrentHashMap<>();
 
 			AtomicBoolean closed = new AtomicBoolean();
 
-			ServiceRegistration<ManagedServiceFactory> serviceRegistration =
+			CountDownLatch countDownLatch = new CountDownLatch(1);
+
+			ServiceRegistration<?> serviceRegistration =
 				bundleContext.registerService(
-					ManagedServiceFactory.class,
-					new ConfigurationsManagedServiceFactory(
-						results, op, closed),
-					new Hashtable<String, Object>() {{
-						put("service.pid", factoryPid);
-					}});
+					ConfigurationListener.class,
+					(ConfigurationEvent configurationEvent) -> {
+						String incomingFactoryPid =
+							configurationEvent.getFactoryPid();
+
+						if (incomingFactoryPid == null ||
+							!factoryPid.equals(incomingFactoryPid)) {
+
+							return;
+						}
+
+						try {
+							countDownLatch.await(1, TimeUnit.MINUTES);
+						}
+						catch (InterruptedException e) {
+							return;
+						}
+
+						String pid = configurationEvent.getPid();
+
+						Configuration configuration;
+
+						if (configurationEvent.getType() ==
+							ConfigurationEvent.CM_DELETED) {
+
+							configurations.remove(pid);
+
+							signalLeave(pid, terminators);
+						}
+						else {
+							configuration = getConfiguration(
+								bundleContext, configurationEvent);
+
+							Dictionary<String, Object> properties =
+								configuration.getProperties();
+
+							configurations.compute(
+								pid,
+								(__, old) -> {
+									if (old == null ||
+										configuration.getChangeCount() !=
+											old.getChangeCount()) {
+
+										return configuration;
+									}
+
+									return old;
+								}
+							);
+
+							signalLeave(pid, terminators);
+
+							terminators.put(pid, op.apply(properties));
+
+							if (closed.get()) {
+							/*
+							if we have closed while executing the
+							effects we have to execute the terminator
+							directly instead of storing it
+							*/
+								signalLeave(pid, terminators);
+							}
+						}
+					},
+					new Hashtable<>());
+
+			ServiceReference<ConfigurationAdmin> serviceReference =
+				bundleContext.getServiceReference(ConfigurationAdmin.class);
+
+			if (serviceReference != null) {
+				Configuration[] configuration = getConfigurations(
+                    bundleContext, factoryPid, serviceReference);
+
+				for (Configuration c : configuration) {
+					configurations.put(c.getPid(), c);
+
+					terminators.put(c.getPid(), op.apply(c.getProperties()));
+				}
+			}
+
+			countDownLatch.countDown();
 
 			return new OSGiResultImpl(
 				() -> {
@@ -55,68 +141,88 @@ public class ConfigurationsOSGiImpl
 
 					serviceRegistration.unregister();
 
-					results.values().forEach(Runnable::run);
-
-					results.clear();
+					for (Runnable runnable : terminators.values()) {
+						if (runnable != null) {
+							runnable.run();
+						}
+					}
 				});
 		});
 	}
 
-	private static class ConfigurationsManagedServiceFactory
-		implements ManagedServiceFactory {
+	private static Configuration getConfiguration(
+		BundleContext bundleContext, ConfigurationEvent configurationEvent) {
 
-		private final Map<String, Runnable> _results;
+		String pid = configurationEvent.getPid();
+		String factoryPid = configurationEvent.getFactoryPid();
 
-		private final Publisher<? super Dictionary<String, ?>> _op;
-		private AtomicBoolean _closed;
+		ServiceReference<ConfigurationAdmin> reference =
+			configurationEvent.getReference();
 
-		public ConfigurationsManagedServiceFactory(
-			Map<String, Runnable> results,
-			Publisher<? super Dictionary<String, ?>> op,
-			AtomicBoolean closed) {
+		return getConfiguration(bundleContext, pid, factoryPid, reference);
+	}
 
-			_results = results;
-			_op = op;
-			_closed = closed;
-		}
+	private static Configuration getConfiguration(
+		BundleContext bundleContext, String pid, String factoryPid,
+		ServiceReference<ConfigurationAdmin> reference) {
+
+		ConfigurationAdmin configurationAdmin = bundleContext.getService(
+			reference);
+
+		try {
+			Configuration[] configurations =
+				configurationAdmin.listConfigurations(
+					"(&(service.pid=" + pid + ")" +
+						"(service.factoryPid="+ factoryPid + "))");
 
-		@Override
-		public void deleted(String s) {
-			Runnable runnable = _results.remove(s);
+			if (configurations == null || configurations.length == 0) {
+				return null;
+			}
 
-			runnable.run();
+			return configurations[0];
 		}
-
-		@Override
-		public String getName() {
-			return "Functional OSGi Managed Service Factory";
+		catch (Exception e) {
+			return null;
+		}
+		finally {
+			bundleContext.ungetService(reference);
 		}
+	}
 
-		@Override
-		public void updated(String s, Dictionary<String, ?> dictionary)
-			throws ConfigurationException {
+	private static Configuration[] getConfigurations(
+		BundleContext bundleContext, String factoryPid,
+		ServiceReference<ConfigurationAdmin> serviceReference) {
+
+		ConfigurationAdmin configurationAdmin = bundleContext.getService(
+			serviceReference);
+
+		try {
+			Configuration[] configurations =
+				configurationAdmin.listConfigurations(
+					"(&(service.pid=*)(service.factoryPid="+ factoryPid +"))");
 
-			Runnable terminator = _op.apply(dictionary);
+			if (configurations == null) {
+				return new Configuration[0];
+			}
 
-			Runnable old = _results.put(s, terminator);
+			return configurations;
+		}
+		catch (Exception e) {
+			return new Configuration[0];
+		}
+		finally {
+			bundleContext.ungetService(serviceReference);
+		}
+	}
 
-			if (old != null) {
-				old.run();
-			}
+	private static void signalLeave(
+		String factoryPid, ConcurrentHashMap<String, Runnable> terminators) {
 
-			if (_closed.get()) {
-				/* if we have been closed while executing the effects we have
-				   to check if this terminator has been left unexecuted.
-				*/
-				_results.computeIfPresent(
-					s,
-					(key, runnable) -> {
-						runnable.run();
+		Runnable runnable = terminators.remove(factoryPid);
 
-					return null;
-				});
-			}
+		if (runnable != null) {
+			runnable.run();
 		}
-
 	}
+
 }

Modified: aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java?rev=1832399&r1=1832398&r2=1832399&view=diff
==============================================================================
--- aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java (original)
+++ aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java Mon May 28 14:29:00 2018
@@ -32,7 +32,9 @@ import org.osgi.framework.ServiceRegistr
 import org.osgi.service.cm.Configuration;
 import org.osgi.service.cm.ConfigurationAdmin;
 import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
 import org.osgi.service.cm.ManagedServiceFactory;
+import org.osgi.util.tracker.ServiceTracker;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -390,6 +392,65 @@ public class DSLTest {
     }
 
     @Test
+    public void testConfigurationWithExistingValues()
+        throws IOException, InterruptedException {
+
+        ServiceReference<ConfigurationAdmin> serviceReference =
+            bundleContext.getServiceReference(ConfigurationAdmin.class);
+
+        ConfigurationAdmin configurationAdmin = bundleContext.getService(
+            serviceReference);
+
+        Configuration configuration = configurationAdmin.getConfiguration(
+            "test.configuration");
+
+        configuration.update(new Hashtable<>());
+
+        AtomicReference<Dictionary<?,?>> atomicReference =
+            new AtomicReference<>(null);
+
+        AtomicInteger counter = new AtomicInteger();
+
+        CountDownLatch countDownLatch = new CountDownLatch(2);
+
+        ServiceRegistration<ManagedService> serviceRegistration =
+            bundleContext.registerService(
+                ManagedService.class, __ -> countDownLatch.countDown(),
+                new Hashtable<String, Object>() {{
+                    put("service.pid", "test.configuration");
+                }});
+
+        try(OSGiResult result =
+                configuration("test.configuration").run(
+                    bundleContext,
+                    x -> {
+                        atomicReference.set(x);
+
+                        counter.incrementAndGet();
+
+                        countDownLatch.countDown();
+
+                        return NOOP;
+                    }))
+        {
+            assertNotNull(atomicReference.get());
+
+            countDownLatch.await(10, TimeUnit.SECONDS);
+
+            assertEquals(1, counter.get());
+        }
+        finally {
+            bundleContext.ungetService(serviceReference);
+
+            configuration.delete();
+
+            if (serviceRegistration != null) {
+                serviceRegistration.unregister();
+            }
+        }
+    }
+
+    @Test
     public void testConfigurations() throws IOException, InterruptedException {
         ServiceReference<ConfigurationAdmin> serviceReference =
             bundleContext.getServiceReference(ConfigurationAdmin.class);
@@ -470,58 +531,34 @@ public class DSLTest {
 
         CountDownLatch addedLatch = new CountDownLatch(3);
 
-        ServiceRegistration<?> addedServiceRegistration =
-            bundleContext.registerService(
-                ManagedServiceFactory.class,
-                new ManagedServiceFactory() {
-                    @Override
-                    public String getName() {
-                        return "";
-                    }
-
-                    @Override
-                    public void updated(
-                        String s, Dictionary<String, ?> dictionary)
-                        throws ConfigurationException {
+        ServiceTracker serviceTracker = new ServiceTracker<Service, Service>(
+            bundleContext, Service.class, null) {
 
-                        addedLatch.countDown();
-                    }
+            @Override
+            public Service addingService(ServiceReference<Service> reference) {
+                addedLatch.countDown();
 
-                    @Override
-                    public void deleted(String s) {
+                return null;
+            }
+        };
 
-                    }
-                },
-                new Hashtable<String, Object>() {{
-                    put("service.pid", "test.configuration");
-                }});
+        serviceTracker.open();
 
         CountDownLatch deletedLatch = new CountDownLatch(3);
 
-        ServiceRegistration<?> deletedServiceRegistration =
-            bundleContext.registerService(
-                ManagedServiceFactory.class,
-                new ManagedServiceFactory() {
-                    @Override
-                    public String getName() {
-                        return "";
-                    }
-
-                    @Override
-                    public void updated(
-                        String s, Dictionary<String, ?> dictionary)
-                        throws ConfigurationException {
-
-                    }
-
-                    @Override
-                    public void deleted(String s) {
-                        deletedLatch.countDown();
-                    }
-                },
-                new Hashtable<String, Object>() {{
-                    put("service.pid", "test.configuration");
-                }});
+        ServiceTracker serviceTracker2 = new ServiceTracker<Service, Service>(
+            bundleContext, Service.class, null) {
+
+            @Override
+            public void removedService(
+                ServiceReference<Service> reference,
+                Service service) {
+
+                deletedLatch.countDown();
+            }
+        };
+
+        serviceTracker2.open();
 
         Configuration configuration =
             configurationAdmin.createFactoryConfiguration("test.configuration");
@@ -572,9 +609,9 @@ public class DSLTest {
             bundleContext.getServiceReferences(
                 Service.class, "(test.configuration=*)").size());
 
-        addedServiceRegistration.unregister();
+        serviceTracker.close();
 
-        deletedServiceRegistration.unregister();
+        serviceTracker2.close();
 
         result.close();