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();
 


Reply via email to