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 2021/03/03 16:44:00 UTC

[aries-component-dsl] branch master updated (851b33c -> f98abdc)

This is an automated email from the ASF dual-hosted git repository.

csierra pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/aries-component-dsl.git.


    from 851b33c  Add flatCombine convenience method
     new 50de3d5  Add update support to OSGi result
     new c802902  Make ServiceReferenceOSGi send updates
     new e4b756c  Add refresh support for update signals
     new f082f84  Add methods with update selectors
     new f5f3aa4  Add update support for configurations
     new f6dc866  Add configuration holder
     new 3d50433  Reorganize methods supporting updates
     new 89291d1  Update ConfigurationHolder and add static initializers
     new f98abdc  Update tests

The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../java/org/apache/aries/component/dsl/OSGi.java  |  81 +++++--
 .../org/apache/aries/component/dsl/OSGiResult.java |   6 +
 .../dsl/configuration/ConfigurationHolder.java     |  60 +++++
 .../Configurations.java}                           |  17 +-
 .../{function => configuration}/package-info.java  |   4 +-
 .../{AllOSGi.java => AggregateOSGiResult.java}     |  59 ++---
 .../aries/component/dsl/internal/AllOSGi.java      |   3 +-
 .../aries/component/dsl/internal/BaseOSGiImpl.java | 135 +++++++----
 .../aries/component/dsl/internal/BundleOSGi.java   |  26 ++-
 .../component/dsl/internal/CoalesceOSGiImpl.java   |  17 +-
 .../dsl/internal/ConfigurationHolderImpl.java      |  61 +++++
 .../dsl/internal/ConfigurationOSGiImpl.java        |  53 +++--
 .../dsl/internal/ConfigurationsOSGiImpl.java       |  75 ++++---
 .../component/dsl/internal/DistributeOSGiImpl.java |  27 +--
 .../aries/component/dsl/internal/EffectsOSGi.java  |  59 +++--
 .../component/dsl/internal/HighestRankingOSGi.java |  60 ++---
 .../aries/component/dsl/internal/JustOSGiImpl.java |  12 +-
 .../component/dsl/internal/NothingOSGiImpl.java    |   2 +-
 .../component/dsl/internal/OSGiResultImpl.java     |  15 +-
 .../component/dsl/internal/OnlyLastPublisher.java  |  24 +-
 .../apache/aries/component/dsl/internal/Pad.java   |   9 +-
 .../aries/component/dsl/internal/ProbeImpl.java    |   6 +-
 .../{RecoverOSGi.java => RefreshWhenOSGi.java}     |  60 +++--
 .../dsl/internal/ServiceReferenceOSGi.java         |  51 +++--
 .../dsl/internal/ServiceRegistrationOSGiImpl.java  |   7 +-
 .../ServiceReferences.java}                        |  27 ++-
 .../dsl/{function => services}/package-info.java   |   4 +-
 .../dsl/{Effect.java => update/UpdateQuery.java}   |  32 ++-
 .../UpdateSelector.java}                           |  10 +-
 .../IgnoreImpl.java => update/UpdateTuple.java}    |  30 ++-
 .../component/dsl/{ => update}/package-info.java   |   4 +-
 itests-run/itest.bndrun                            |   3 +-
 .../apache/aries/component/dsl/test/DSLTest.java   | 249 +++++++++++++++++++++
 33 files changed, 951 insertions(+), 337 deletions(-)
 create mode 100644 component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/ConfigurationHolder.java
 copy component-dsl/src/main/java/org/apache/aries/component/dsl/{internal/IgnoreImpl.java => configuration/Configurations.java} (61%)
 copy component-dsl/src/main/java/org/apache/aries/component/dsl/{function => configuration}/package-info.java (89%)
 copy component-dsl/src/main/java/org/apache/aries/component/dsl/internal/{AllOSGi.java => AggregateOSGiResult.java} (50%)
 create mode 100644 component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationHolderImpl.java
 copy component-dsl/src/main/java/org/apache/aries/component/dsl/internal/{RecoverOSGi.java => RefreshWhenOSGi.java} (51%)
 copy component-dsl/src/main/java/org/apache/aries/component/dsl/{internal/IgnoreImpl.java => services/ServiceReferences.java} (51%)
 copy component-dsl/src/main/java/org/apache/aries/component/dsl/{function => services}/package-info.java (89%)
 copy component-dsl/src/main/java/org/apache/aries/component/dsl/{Effect.java => update/UpdateQuery.java} (54%)
 copy component-dsl/src/main/java/org/apache/aries/component/dsl/{OSGiFactory.java => update/UpdateSelector.java} (78%)
 copy component-dsl/src/main/java/org/apache/aries/component/dsl/{internal/IgnoreImpl.java => update/UpdateTuple.java} (54%)
 copy component-dsl/src/main/java/org/apache/aries/component/dsl/{ => update}/package-info.java (89%)


[aries-component-dsl] 03/09: Add refresh support for update signals

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csierra pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-component-dsl.git

commit e4b756c50c224f2542b19eb5d636267c981511c6
Author: Carlos Sierra Andrés <ca...@liferay.com>
AuthorDate: Fri Feb 26 08:26:08 2021 +0100

    Add refresh support for update signals
---
 .../java/org/apache/aries/component/dsl/OSGi.java  | 31 ++++++++----
 .../org/apache/aries/component/dsl/OSGiResult.java |  4 +-
 .../dsl/internal/AggregateOSGiResult.java          |  8 ++-
 .../aries/component/dsl/internal/AllOSGi.java      |  2 +-
 .../aries/component/dsl/internal/BaseOSGiImpl.java | 29 ++++++-----
 .../aries/component/dsl/internal/BundleOSGi.java   |  6 ++-
 .../component/dsl/internal/CoalesceOSGiImpl.java   | 11 ++--
 .../dsl/internal/ConfigurationOSGiImpl.java        |  2 +-
 .../dsl/internal/ConfigurationsOSGiImpl.java       | 12 ++---
 .../component/dsl/internal/DistributeOSGiImpl.java |  6 ++-
 .../aries/component/dsl/internal/EffectsOSGi.java  |  2 +-
 .../component/dsl/internal/HighestRankingOSGi.java |  2 +-
 .../aries/component/dsl/internal/JustOSGiImpl.java | 10 ++--
 .../component/dsl/internal/NothingOSGiImpl.java    |  2 +-
 .../component/dsl/internal/OSGiResultImpl.java     | 13 +++--
 .../apache/aries/component/dsl/internal/Pad.java   |  4 +-
 .../component/dsl/internal/RefreshWhenOSGi.java    | 58 ++++++++++++++++++++++
 .../dsl/internal/ServiceReferenceOSGi.java         | 33 ++++--------
 18 files changed, 157 insertions(+), 78 deletions(-)

diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
index 1adfba9..fc6597c 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
@@ -45,6 +45,7 @@ import org.apache.aries.component.dsl.function.Function3;
 import org.apache.aries.component.dsl.function.Function5;
 import org.apache.aries.component.dsl.function.Function7;
 import org.apache.aries.component.dsl.update.UpdateQuery;
+import org.apache.aries.component.dsl.update.UpdateSelector;
 import org.apache.aries.component.dsl.update.UpdateTuple;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -56,11 +57,7 @@ import org.osgi.framework.ServiceRegistration;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.BiFunction;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
+import java.util.function.*;
 
 /**
  * @author Carlos Sierra Andrés
@@ -331,7 +328,12 @@ public interface OSGi<T> extends OSGiRunnable<T> {
 	}
 
 	static <T> OSGi<T> fromOsgiRunnable(OSGiRunnable<T> runnable) {
-		return getOsgiFactory().create(runnable);
+		return getOsgiFactory().create(
+			(ec, op) -> new OSGiResultImpl(runnable.run(ec, op), __ -> true));
+	}
+
+	static <T> OSGi<T> fromOsgiRunnableWithUpdateSupport(OSGiRunnable<T> runnable) {
+		return getOsgiFactory().create(runnable::run);
 	}
 
 	static OSGiFactory getOsgiFactory() {
@@ -449,6 +451,10 @@ public interface OSGi<T> extends OSGiRunnable<T> {
 		return new RecoverWithOSGi<>(program, function);
 	}
 
+	static <T> OSGi<T> refreshWhen(OSGi<T> program, BiPredicate<UpdateSelector, T> refresher) {
+		return new RefreshWhenOSGi<>(program, refresher);
+	}
+
 	static <T> OSGi<ServiceRegistration<T>> register(
 		Class<T> clazz, T service, Map<String, Object> properties) {
 
@@ -544,21 +550,28 @@ public interface OSGi<T> extends OSGiRunnable<T> {
 		Class<T> clazz, String filterString,
 		Refresher<? super CachingServiceReference<T>> onModified) {
 
-		return new ServiceReferenceOSGi<>(filterString, clazz, onModified).map(UpdateTuple::getT);
+		return refreshWhen(
+			serviceReferences(clazz, filterString),
+			(__, csr) -> onModified.test(csr));
+
 	}
 
 	static <T> OSGi<CachingServiceReference<T>> serviceReferences(
 		Class<T> clazz,
 		Refresher<? super CachingServiceReference<T>> onModified) {
 
-		return new ServiceReferenceOSGi<>(null, clazz, onModified).map(UpdateTuple::getT);
+		return refreshWhen(
+			serviceReferences(clazz, (String)null),
+			(__, csr) -> onModified.test(csr));
 	}
 
 	static OSGi<CachingServiceReference<Object>> serviceReferences(
 		String filterString,
 		Refresher<? super CachingServiceReference<Object>> onModified) {
 
-		return new ServiceReferenceOSGi<>(filterString, null, onModified).map(UpdateTuple::getT);
+		return refreshWhen(
+			serviceReferences(null, filterString),
+			(__, csr) -> onModified.test(csr));
 	}
 
 	static <T> OSGi<T> services(Class<T> clazz) {
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java
index ad56515..8085975 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java
@@ -31,6 +31,8 @@ public interface OSGiResult extends AutoCloseable, Runnable {
 		close();
 	}
 
-	public default void update(UpdateSelector updateSelector) {};
+	public default boolean update(UpdateSelector updateSelector) {
+		return false;
+	};
 
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AggregateOSGiResult.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AggregateOSGiResult.java
index 24e5124..a6f98e7 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AggregateOSGiResult.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AggregateOSGiResult.java
@@ -46,15 +46,19 @@ public class AggregateOSGiResult implements OSGiResult {
     }
 
     @Override
-    public void update(UpdateSelector updateSelector) {
+    public boolean update(UpdateSelector updateSelector) {
+        boolean bool = false;
+
         if (!_closed.get()) {
             for (OSGiResult result : results) {
                 try {
-                    result.update(updateSelector);
+                    bool |= result.update(updateSelector);
                 } catch (Exception e) {
                 }
             }
         }
+
+        return bool;
     }
 
     private final AtomicBoolean _closed = new AtomicBoolean();
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AllOSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AllOSGi.java
index aa652c6..341792e 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AllOSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AllOSGi.java
@@ -46,7 +46,7 @@ public class AllOSGi<T> extends OSGiImpl<T> {
 
             return new OSGiResultImpl(
                 () -> cleanUp(results),
-                us -> results.forEach(result -> result.update(us))
+                us -> results.stream().map(result -> result.update(us)).reduce(Boolean.FALSE, Boolean::logicalOr)
             );
         });
     }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BaseOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BaseOSGiImpl.java
index cb554a2..4f54586 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BaseOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BaseOSGiImpl.java
@@ -136,12 +136,13 @@ public class BaseOSGiImpl<T> implements OSGi<T> {
 							},
 							us -> {
 								synchronized (identities) {
-
-									identities.forEach(t -> {
+									return identities.stream().map(t -> {
 										OSGiResult terminator = terminators.get(t).get(f);
 
-										terminator.update(us);
-									});
+										return terminator.update(us);
+									}).reduce(
+										Boolean.FALSE, Boolean::logicalOr
+									);
 								}
 							}
 						);
@@ -176,11 +177,13 @@ public class BaseOSGiImpl<T> implements OSGi<T> {
 							},
 							us -> {
 								synchronized (identities) {
-									functions.forEach(f -> {
+									return functions.stream().map(f -> {
 										OSGiResult terminator = terminators.get(t).get(f);
 
-										terminator.update(us);
-									});
+										return terminator.update(us);
+									}).reduce(
+										Boolean.FALSE, Boolean::logicalOr
+									);
 								}
 							}
 						);
@@ -281,7 +284,7 @@ public class BaseOSGiImpl<T> implements OSGi<T> {
 									}
 								}
 
-								terminator.update(us);
+								return terminator.update(us);
 							}
 						);
 
@@ -397,11 +400,11 @@ public class BaseOSGiImpl<T> implements OSGi<T> {
 
 					result.close();
 				},
-				us -> {
-					pads.values().forEach(pad -> pad.update(us));
-
-					result.close();
-				}
+				us -> pads.values().stream().map(
+					pad -> pad.update(us)
+				).reduce(
+					Boolean.FALSE, Boolean::logicalOr
+				) | result.update(us)
 			);
 		});
 	}
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BundleOSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BundleOSGi.java
index 2b5ca5c..9eae7fd 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BundleOSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BundleOSGi.java
@@ -66,7 +66,11 @@ public class BundleOSGi extends OSGiImpl<Bundle> {
 
 			return new OSGiResultImpl(
 				bundleTracker::close,
-				us -> bundleTracker.getTracked().values().forEach(result -> result.update(us))
+				us -> bundleTracker.getTracked().values().stream().map(
+					result -> result.update(us)
+				).reduce(
+					Boolean.FALSE, Boolean::logicalOr
+				)
 			);
 		});
 
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/CoalesceOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/CoalesceOSGiImpl.java
index 3aff2be..6ce33a6 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/CoalesceOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/CoalesceOSGiImpl.java
@@ -21,6 +21,7 @@ import org.apache.aries.component.dsl.OSGi;
 import org.apache.aries.component.dsl.OSGiResult;
 import org.apache.aries.component.dsl.Publisher;
 
+import java.util.Arrays;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
@@ -96,7 +97,7 @@ public class CoalesceOSGiImpl<T> extends OSGiImpl<T> {
                     }),
                     us -> {
                         synchronized (initialized) {
-                            result.get().update(us);
+                            return result.get().update(us);
                         }
                     });
                 };
@@ -131,9 +132,11 @@ public class CoalesceOSGiImpl<T> extends OSGiImpl<T> {
                 },
                 us -> {
                     synchronized (initialized) {
-                        for (int i = 0; i <= index.get(); i++) {
-                            results[i].update(us);
-                        }
+                        return Arrays.stream(results).map(
+                            res -> res.update(us)
+                        ).reduce(
+                            Boolean.FALSE, Boolean::logicalOr
+                        );
                     }
                 }
             );
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
index 26cefbe..36c8514 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
@@ -45,7 +45,7 @@ public class ConfigurationOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 
 			AtomicReference<OSGiResult>
 				terminatorAtomicReference = new AtomicReference<>(
-					new OSGiResultImpl(NOOP, __ -> {}));
+					new OSGiResultImpl(NOOP, __ -> false));
 
 			AtomicBoolean closed = new AtomicBoolean();
 
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
index fe16e10..850533d 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
@@ -150,13 +150,11 @@ public class ConfigurationsOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 						}
 					}
 				},
-				us -> {
-					for (OSGiResult osgiResult : terminators.values()) {
-						if (osgiResult != null) {
-							osgiResult.run();
-						}
-					}
-				});
+				us -> terminators.values().stream().map(
+					osgiResult -> osgiResult.update(us)
+				).reduce(
+					Boolean.FALSE, Boolean::logicalOr
+				));
 		});
 	}
 
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/DistributeOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/DistributeOSGiImpl.java
index 5f21e76..35e9e55 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/DistributeOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/DistributeOSGiImpl.java
@@ -61,7 +61,11 @@ public class DistributeOSGiImpl<T, S> extends BaseOSGiImpl<S> {
 
                     return new OSGiResultImpl(
                         () -> cleanUp(terminators),
-                        us -> terminators.forEach(os -> os.update(us))
+                        us -> terminators.stream().map(
+                            os -> os.update(us)
+                        ).reduce(
+                            Boolean.FALSE, Boolean::logicalOr
+                        )
                     );
                 }));
 
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/EffectsOSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/EffectsOSGi.java
index 932f29c..747a883 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/EffectsOSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/EffectsOSGi.java
@@ -68,7 +68,7 @@ public class EffectsOSGi extends OSGiImpl<Void> {
                             }
                         }
 
-                        terminator.update(us);
+                        return terminator.update(us);
                     }
                 );
 
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/HighestRankingOSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/HighestRankingOSGi.java
index e9dc9fb..31d01e3 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/HighestRankingOSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/HighestRankingOSGi.java
@@ -97,7 +97,7 @@ public class HighestRankingOSGi<T> extends OSGiImpl<T> {
                             synchronized (set) {
                                 Tuple<T> current = set.peek();
 
-                                current.osgiResult.update(us);
+                                return current.osgiResult.update(us);
                             }
                         }
                     );
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/JustOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/JustOSGiImpl.java
index 8b4dae7..cd516d6 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/JustOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/JustOSGiImpl.java
@@ -19,6 +19,8 @@
 package org.apache.aries.component.dsl.internal;
 
 
+import org.apache.aries.component.dsl.OSGiResult;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -38,7 +40,7 @@ public class JustOSGiImpl<T> extends OSGiImpl<T> {
 		super((executionContext, op) -> {
 
 			Collection<T> collection = supplier.get();
-			ArrayList<Runnable> references = new ArrayList<>(collection.size());
+			ArrayList<OSGiResult> references = new ArrayList<>(collection.size());
 
 			try {
 				for (T t : collection) {
@@ -53,13 +55,13 @@ public class JustOSGiImpl<T> extends OSGiImpl<T> {
 
 			return new OSGiResultImpl(
 				() -> cleanUp(references),
-				us -> {}
+				us -> references.stream().map(res -> res.update(us)).reduce(Boolean.FALSE, Boolean::logicalOr)
 			);
 		});
 	}
 
-	private static void cleanUp(ArrayList<Runnable> references) {
-		ListIterator<Runnable> iterator =
+	private static void cleanUp(ArrayList<OSGiResult> references) {
+		ListIterator<OSGiResult> iterator =
 			references.listIterator(references.size());
 
 		while (iterator.hasPrevious()) {
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/NothingOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/NothingOSGiImpl.java
index 5c2dfd3..ff8b0e6 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/NothingOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/NothingOSGiImpl.java
@@ -25,6 +25,6 @@ import org.apache.aries.component.dsl.OSGi;
 public class NothingOSGiImpl<S> extends OSGiImpl<S> {
 
 	public NothingOSGiImpl() {
-		super((executionContext, __) -> new OSGiResultImpl(OSGi.NOOP,  ___ -> {}));
+		super((executionContext, __) -> new OSGiResultImpl(OSGi.NOOP,  ___ -> false));
 	}
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java
index bce94c3..36a0745 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java
@@ -21,14 +21,14 @@ import org.apache.aries.component.dsl.OSGiResult;
 import org.apache.aries.component.dsl.update.UpdateSelector;
 
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Consumer;
+import java.util.function.Predicate;
 
 /**
  * @author Carlos Sierra Andrés
  */
 public class OSGiResultImpl implements OSGiResult {
 
-	public OSGiResultImpl(Runnable close, Consumer<UpdateSelector> onUpdate) {
+	public OSGiResultImpl(Runnable close, Predicate<UpdateSelector> onUpdate) {
 		this.close = close;
 		this.onUpdate = onUpdate;
 	}
@@ -41,17 +41,16 @@ public class OSGiResultImpl implements OSGiResult {
 	}
 
 	@Override
-	public void update(UpdateSelector updateSelector) {
+	public boolean update(UpdateSelector updateSelector) {
 		if (_closed.get()) {
-			return;
+			return false;
 		}
 
-		onUpdate.accept(updateSelector);
+		return onUpdate.test(updateSelector);
 	}
 
 	private final Runnable close;
-	private Consumer<UpdateSelector> onUpdate;
-	private Runnable update;
+	private Predicate<UpdateSelector> onUpdate;
 	private AtomicBoolean _closed = new AtomicBoolean();
 
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/Pad.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/Pad.java
index fd6f305..2da4baa 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/Pad.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/Pad.java
@@ -56,8 +56,8 @@ public class Pad<T, S> implements Publisher<T>, OSGiResult {
     }
 
     @Override
-    public void update(UpdateSelector updateSelector) {
-        _result.update(updateSelector);
+    public boolean update(UpdateSelector updateSelector) {
+        return _result.update(updateSelector);
     }
 
     @Override
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/RefreshWhenOSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/RefreshWhenOSGi.java
new file mode 100644
index 0000000..cab0a0b
--- /dev/null
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/RefreshWhenOSGi.java
@@ -0,0 +1,58 @@
+/*
+ * 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 org.apache.aries.component.dsl.internal;
+
+import org.apache.aries.component.dsl.OSGi;
+import org.apache.aries.component.dsl.OSGiResult;
+import org.apache.aries.component.dsl.Publisher;
+import org.apache.aries.component.dsl.Refresher;
+import org.apache.aries.component.dsl.update.UpdateSelector;
+import org.apache.aries.component.dsl.update.UpdateTuple;
+
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiFunction;
+import java.util.function.BiPredicate;
+import java.util.function.Predicate;
+
+/**
+ * @author Carlos Sierra Andrés
+ */
+public class RefreshWhenOSGi<T> extends OSGiImpl<T> {
+
+    public RefreshWhenOSGi(OSGi<T> program, BiPredicate<UpdateSelector, T> refresher) {
+        super((executionContext, op) -> program.run(
+            executionContext,
+            op.pipe(
+                t -> {
+                    OSGiResult osgiResult = op.publish(t);
+
+                    return new OSGiResultImpl(
+                        osgiResult::close,
+                        us -> {
+                            if (refresher.test(us, t)) {
+                                return true;
+                            }
+
+                            return osgiResult.update(us);
+                        }
+                    );
+                }
+            )));
+    }
+
+}
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java
index 03698aa..cac5c73 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java
@@ -18,7 +18,6 @@
 package org.apache.aries.component.dsl.internal;
 
 import org.apache.aries.component.dsl.OSGiResult;
-import org.apache.aries.component.dsl.Refresher;
 import org.apache.aries.component.dsl.CachingServiceReference;
 import org.apache.aries.component.dsl.Publisher;
 import org.apache.aries.component.dsl.update.UpdateSelector;
@@ -33,29 +32,24 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
 public class ServiceReferenceOSGi<T>
 	extends OSGiImpl<UpdateTuple<CachingServiceReference<T>>> implements UpdateSelector {
 
-	public ServiceReferenceOSGi(
-		String filterString, Class<T> clazz) {
-
-		this(filterString, clazz, CachingServiceReference::isDirty);
-	}
-
-	public ServiceReferenceOSGi(
-		String filterString, Class<T> clazz,
-		Refresher<? super CachingServiceReference<T>> refresher) {
+	public ServiceReferenceOSGi(String filterString, Class<T> clazz) {
 
 		super((executionContext, op) -> {
 			ServiceTracker<T, Tracked<T>>
 				serviceTracker = new ServiceTracker<>(
 					executionContext.getBundleContext(),
 					buildFilter(executionContext, filterString, clazz),
-					new DefaultServiceTrackerCustomizer<>(op, refresher));
+					new DefaultServiceTrackerCustomizer<>(op));
 
 			serviceTracker.open();
 
 			return new OSGiResultImpl(
 				serviceTracker::close,
-				us -> serviceTracker.getTracked().forEach(
-					(__, tracked) -> tracked.runnable.update(us))
+				us -> serviceTracker.getTracked().values().stream().map(
+					tracked -> tracked.runnable.update(us)
+				).reduce(
+					Boolean.FALSE, Boolean::logicalOr
+				)
 			);
 		});
 	}
@@ -64,11 +58,9 @@ public class ServiceReferenceOSGi<T>
 		implements ServiceTrackerCustomizer<T, Tracked<T>>, UpdateSelector{
 
 		public DefaultServiceTrackerCustomizer(
-			Publisher<? super UpdateTuple<CachingServiceReference<T>>> addedSource,
-			Refresher<? super CachingServiceReference<T>> refresher) {
+			Publisher<? super UpdateTuple<CachingServiceReference<T>>> addedSource) {
 
 			_addedSource = addedSource;
-			_refresher = refresher;
 		}
 
 		@Override
@@ -85,18 +77,16 @@ public class ServiceReferenceOSGi<T>
 		public void modifiedService(
 			ServiceReference<T> reference, Tracked<T> tracked) {
 
-			if (_refresher.test(tracked.cachingServiceReference)) {
+			if (tracked.runnable.update(this)) {
 				UpdateSupport.runUpdate(() -> {
 					tracked.runnable.run();
 					tracked.cachingServiceReference = new CachingServiceReference<>(
 						reference);
 					tracked.runnable =
-						_addedSource.apply(new UpdateTuple<>(this, tracked.cachingServiceReference));
+						_addedSource.apply(
+							new UpdateTuple<>(this, tracked.cachingServiceReference));
 				});
 			}
-			else {
-				tracked.runnable.update(this);
-			}
 		}
 
 		@Override
@@ -107,7 +97,6 @@ public class ServiceReferenceOSGi<T>
 		}
 
 		private final Publisher<? super UpdateTuple<CachingServiceReference<T>>> _addedSource;
-		private Refresher<? super CachingServiceReference<T>> _refresher;
 
 	}
 


[aries-component-dsl] 07/09: Reorganize methods supporting updates

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csierra pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-component-dsl.git

commit 3d50433b0ea68de4f2d325eb1b925aad121e081b
Author: Carlos Sierra Andrés <ca...@liferay.com>
AuthorDate: Tue Mar 2 18:43:22 2021 +0100

    Reorganize methods supporting updates
---
 .../java/org/apache/aries/component/dsl/OSGi.java  | 24 +++---------
 .../dsl/configuration/Configurations.java          | 35 +++++++++++++++++
 .../aries/component/dsl/internal/BaseOSGiImpl.java |  5 +--
 .../component/dsl/services/ServiceReferences.java  | 45 ++++++++++++++++++++++
 .../aries/component/dsl/services/package-info.java | 20 ++++++++++
 5 files changed, 107 insertions(+), 22 deletions(-)

diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
index 4476539..b6b9487 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
@@ -590,24 +590,6 @@ public interface OSGi<T> extends OSGiRunnable<T> {
 			(__, csr) -> onModified.test(csr));
 	}
 
-	static <T> OSGi<UpdateTuple<CachingServiceReference<T>>> serviceReferencesUpdatable(
-		Class<T> clazz) {
-
-		return new ServiceReferenceOSGi<>(null, clazz);
-	}
-
-	static OSGi<UpdateTuple<CachingServiceReference<Object>>> serviceReferencesUpdatable(
-		String filterString) {
-
-		return new ServiceReferenceOSGi<>(filterString, null);
-	}
-
-	static <T> OSGi<UpdateTuple<CachingServiceReference<T>>> serviceReferencesUpdatable(
-		Class<T> clazz, String filterString) {
-
-		return new ServiceReferenceOSGi<>(filterString, clazz);
-	}
-
 	static <T> OSGi<T> services(Class<T> clazz) {
 		return services(clazz, null);
 	}
@@ -658,6 +640,12 @@ public interface OSGi<T> extends OSGiRunnable<T> {
 		return effects(effect.getOnIncoming(), effect.getOnLeaving());
 	}
 
+	OSGi<T> effects(
+		Consumer<? super T> onAddedBefore, Consumer<? super T> onAddedAfter,
+		Consumer<? super T> onRemovedBefore,
+		Consumer<? super T> onRemovedAfter,
+		UpdateQuery<T> updateQuery);
+
 	OSGi<T> filter(Predicate<T> predicate);
 
 	<S> OSGi<S> flatMap(Function<? super T, OSGi<? extends S>> fun);
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/Configurations.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/Configurations.java
new file mode 100644
index 0000000..f1472b4
--- /dev/null
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/Configurations.java
@@ -0,0 +1,35 @@
+/*
+ * 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 org.apache.aries.component.dsl.configuration;
+
+import org.apache.aries.component.dsl.OSGi;
+import org.apache.aries.component.dsl.internal.ConfigurationOSGiImpl;
+import org.apache.aries.component.dsl.internal.ConfigurationsOSGiImpl;
+import org.apache.aries.component.dsl.update.UpdateTuple;
+
+public interface Configurations {
+
+    public static OSGi<UpdateTuple<ConfigurationHolder>> singleton(String pid) {
+        return new ConfigurationOSGiImpl(pid);
+    }
+
+    public static OSGi<UpdateTuple<ConfigurationHolder>> factories(String pid) {
+        return new ConfigurationsOSGiImpl(pid);
+    }
+
+}
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BaseOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BaseOSGiImpl.java
index 4f54586..686ee2e 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BaseOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BaseOSGiImpl.java
@@ -234,16 +234,13 @@ public class BaseOSGiImpl<T> implements OSGi<T> {
 		return effects(onAddedBefore, onAddedAfter, onRemovedBefore, onRemovedAfter, UpdateQuery.onUpdate());
 	}
 
+	@Override
 	public OSGi<T> effects(
 		Consumer<? super T> onAddedBefore, Consumer<? super T> onAddedAfter,
 		Consumer<? super T> onRemovedBefore,
 		Consumer<? super T> onRemovedAfter,
 		UpdateQuery<T> updateQuery) {
 
-		//TODO: logging
-		//TODO: logging
-		//TODO: logging
-		//TODO: logging
 		return new BaseOSGiImpl<>((executionContext, op) ->
 			run(
 				executionContext,
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/services/ServiceReferences.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/services/ServiceReferences.java
new file mode 100644
index 0000000..7601989
--- /dev/null
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/services/ServiceReferences.java
@@ -0,0 +1,45 @@
+/*
+ * 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 org.apache.aries.component.dsl.services;
+
+import org.apache.aries.component.dsl.CachingServiceReference;
+import org.apache.aries.component.dsl.OSGi;
+import org.apache.aries.component.dsl.internal.ServiceReferenceOSGi;
+import org.apache.aries.component.dsl.update.UpdateTuple;
+
+public interface ServiceReferences {
+
+    static <T> OSGi<UpdateTuple<CachingServiceReference<T>>> withUpdate(
+        Class<T> clazz) {
+
+        return new ServiceReferenceOSGi<>(null, clazz);
+    }
+
+    static OSGi<UpdateTuple<CachingServiceReference<Object>>> withUpdate(
+        String filterString) {
+
+        return new ServiceReferenceOSGi<>(filterString, null);
+    }
+
+    static <T> OSGi<UpdateTuple<CachingServiceReference<T>>> withUpdate(
+        Class<T> clazz, String filterString) {
+
+        return new ServiceReferenceOSGi<>(filterString, clazz);
+    }
+
+}
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/services/package-info.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/services/package-info.java
new file mode 100644
index 0000000..90da14b
--- /dev/null
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/services/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+@org.osgi.annotation.bundle.Export
+@org.osgi.annotation.versioning.Version("1.0.0")
+package org.apache.aries.component.dsl.services;


[aries-component-dsl] 02/09: Make ServiceReferenceOSGi send updates

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csierra pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-component-dsl.git

commit c8029026fe23ae2270310604475041d5f4112ba4
Author: Carlos Sierra Andrés <ca...@liferay.com>
AuthorDate: Thu Feb 25 15:57:01 2021 +0100

    Make ServiceReferenceOSGi send updates
---
 .../java/org/apache/aries/component/dsl/OSGi.java  | 13 +++++----
 .../dsl/internal/ServiceReferenceOSGi.java         | 17 +++++++----
 .../aries/component/dsl/update/UpdateTuple.java    | 33 ++++++++++++++++++++++
 3 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
index 50502ba..1adfba9 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
@@ -45,6 +45,7 @@ import org.apache.aries.component.dsl.function.Function3;
 import org.apache.aries.component.dsl.function.Function5;
 import org.apache.aries.component.dsl.function.Function7;
 import org.apache.aries.component.dsl.update.UpdateQuery;
+import org.apache.aries.component.dsl.update.UpdateTuple;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceFactory;
@@ -524,40 +525,40 @@ public interface OSGi<T> extends OSGiRunnable<T> {
 	static <T> OSGi<CachingServiceReference<T>> serviceReferences(
 		Class<T> clazz) {
 
-		return new ServiceReferenceOSGi<>(null, clazz);
+		return new ServiceReferenceOSGi<>(null, clazz).map(UpdateTuple::getT);
 	}
 
 	static OSGi<CachingServiceReference<Object>> serviceReferences(
 		String filterString) {
 
-		return new ServiceReferenceOSGi<>(filterString, null);
+		return new ServiceReferenceOSGi<>(filterString, null).map(UpdateTuple::getT);
 	}
 
 	static <T> OSGi<CachingServiceReference<T>> serviceReferences(
 		Class<T> clazz, String filterString) {
 
-		return new ServiceReferenceOSGi<>(filterString, clazz);
+		return new ServiceReferenceOSGi<>(filterString, clazz).map(UpdateTuple::getT);
 	}
 
 	static <T> OSGi<CachingServiceReference<T>> serviceReferences(
 		Class<T> clazz, String filterString,
 		Refresher<? super CachingServiceReference<T>> onModified) {
 
-		return new ServiceReferenceOSGi<>(filterString, clazz, onModified);
+		return new ServiceReferenceOSGi<>(filterString, clazz, onModified).map(UpdateTuple::getT);
 	}
 
 	static <T> OSGi<CachingServiceReference<T>> serviceReferences(
 		Class<T> clazz,
 		Refresher<? super CachingServiceReference<T>> onModified) {
 
-		return new ServiceReferenceOSGi<>(null, clazz, onModified);
+		return new ServiceReferenceOSGi<>(null, clazz, onModified).map(UpdateTuple::getT);
 	}
 
 	static OSGi<CachingServiceReference<Object>> serviceReferences(
 		String filterString,
 		Refresher<? super CachingServiceReference<Object>> onModified) {
 
-		return new ServiceReferenceOSGi<>(filterString, null, onModified);
+		return new ServiceReferenceOSGi<>(filterString, null, onModified).map(UpdateTuple::getT);
 	}
 
 	static <T> OSGi<T> services(Class<T> clazz) {
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java
index a5ac0d2..03698aa 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java
@@ -21,6 +21,8 @@ import org.apache.aries.component.dsl.OSGiResult;
 import org.apache.aries.component.dsl.Refresher;
 import org.apache.aries.component.dsl.CachingServiceReference;
 import org.apache.aries.component.dsl.Publisher;
+import org.apache.aries.component.dsl.update.UpdateSelector;
+import org.apache.aries.component.dsl.update.UpdateTuple;
 import org.osgi.framework.ServiceReference;
 import org.osgi.util.tracker.ServiceTracker;
 import org.osgi.util.tracker.ServiceTrackerCustomizer;
@@ -29,7 +31,7 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
  * @author Carlos Sierra Andrés
  */
 public class ServiceReferenceOSGi<T>
-	extends OSGiImpl<CachingServiceReference<T>> {
+	extends OSGiImpl<UpdateTuple<CachingServiceReference<T>>> implements UpdateSelector {
 
 	public ServiceReferenceOSGi(
 		String filterString, Class<T> clazz) {
@@ -59,10 +61,10 @@ public class ServiceReferenceOSGi<T>
 	}
 
 	private static class DefaultServiceTrackerCustomizer<T>
-		implements ServiceTrackerCustomizer<T, Tracked<T>> {
+		implements ServiceTrackerCustomizer<T, Tracked<T>>, UpdateSelector{
 
 		public DefaultServiceTrackerCustomizer(
-			Publisher<? super CachingServiceReference<T>> addedSource,
+			Publisher<? super UpdateTuple<CachingServiceReference<T>>> addedSource,
 			Refresher<? super CachingServiceReference<T>> refresher) {
 
 			_addedSource = addedSource;
@@ -76,7 +78,7 @@ public class ServiceReferenceOSGi<T>
 
 			return new Tracked<>(
 				cachingServiceReference,
-				_addedSource.apply(cachingServiceReference));
+				_addedSource.apply(new UpdateTuple<>(this, cachingServiceReference)));
 		}
 
 		@Override
@@ -89,9 +91,12 @@ public class ServiceReferenceOSGi<T>
 					tracked.cachingServiceReference = new CachingServiceReference<>(
 						reference);
 					tracked.runnable =
-						_addedSource.apply(tracked.cachingServiceReference);
+						_addedSource.apply(new UpdateTuple<>(this, tracked.cachingServiceReference));
 				});
 			}
+			else {
+				tracked.runnable.update(this);
+			}
 		}
 
 		@Override
@@ -101,7 +106,7 @@ public class ServiceReferenceOSGi<T>
 			tracked.runnable.run();
 		}
 
-		private final Publisher<? super CachingServiceReference<T>> _addedSource;
+		private final Publisher<? super UpdateTuple<CachingServiceReference<T>>> _addedSource;
 		private Refresher<? super CachingServiceReference<T>> _refresher;
 
 	}
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateTuple.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateTuple.java
new file mode 100644
index 0000000..0b7b2e3
--- /dev/null
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateTuple.java
@@ -0,0 +1,33 @@
+/*
+ * 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 org.apache.aries.component.dsl.update;
+
+public final class UpdateTuple<T> {
+
+    public final UpdateSelector updateSelector;
+    public final T t;
+
+    public UpdateTuple(UpdateSelector updateSelector, T t) {
+        this.updateSelector = updateSelector;
+        this.t = t;
+    }
+
+    public T getT() {
+        return t;
+    }
+}


[aries-component-dsl] 09/09: Update tests

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csierra pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-component-dsl.git

commit f98abdc459c6e2ffc109d34e16fa02a1c46976ee
Author: Carlos Sierra Andrés <ca...@liferay.com>
AuthorDate: Wed Mar 3 17:31:41 2021 +0100

    Update tests
---
 .../apache/aries/component/dsl/test/DSLTest.java   | 249 +++++++++++++++++++++
 1 file changed, 249 insertions(+)

diff --git a/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java b/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java
index 1d6e00a..f69ea34 100644
--- a/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java
+++ b/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java
@@ -22,7 +22,13 @@ import org.apache.aries.component.dsl.OSGi;
 import org.apache.aries.component.dsl.OSGiResult;
 import org.apache.aries.component.dsl.Publisher;
 import org.apache.aries.component.dsl.Utils;
+import org.apache.aries.component.dsl.configuration.ConfigurationHolder;
+import org.apache.aries.component.dsl.configuration.Configurations;
 import org.apache.aries.component.dsl.internal.ProbeImpl;
+import org.apache.aries.component.dsl.services.ServiceReferences;
+import org.apache.aries.component.dsl.update.UpdateQuery;
+import org.apache.aries.component.dsl.update.UpdateSelector;
+import org.apache.aries.component.dsl.update.UpdateTuple;
 import org.junit.Test;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
@@ -54,6 +60,11 @@ import java.util.concurrent.atomic.AtomicReference;
 import static org.apache.aries.component.dsl.OSGi.*;
 import static org.apache.aries.component.dsl.Utils.accumulate;
 import static org.apache.aries.component.dsl.Utils.highest;
+import static org.apache.aries.component.dsl.configuration.ConfigurationHolder.fromMap;
+import static org.apache.aries.component.dsl.update.UpdateQuery.From.from;
+import static org.apache.aries.component.dsl.update.UpdateQuery.onUpdate;
+import static org.apache.aries.component.dsl.update.UpdateTuple.flatMap;
+import static org.apache.aries.component.dsl.update.UpdateTuple.fromStatic;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -487,6 +498,114 @@ public class DSLTest {
             new AtomicReference<>(null);
 
         AtomicInteger counter = new AtomicInteger();
+        AtomicInteger updateCounter = new AtomicInteger();
+
+        CountDownLatch countDownLatch = new CountDownLatch(4);
+
+        ServiceRegistration<ManagedService> serviceRegistration =
+            bundleContext.registerService(
+                ManagedService.class, __ -> countDownLatch.countDown(),
+                new Hashtable<String, Object>() {{
+                    put("service.pid", "test.configuration");
+                }});
+
+        AtomicReference<Runnable> effect = new AtomicReference<>();
+
+        effect.set(countDownLatch::countDown);
+
+        try(OSGiResult result =
+                flatMap(coalesce(
+                    Configurations.singleton("test.configuration"),
+                    just(() -> fromStatic(fromMap(new HashMap<>())))),
+                (configurationUpdate, cholder) ->
+                    just(() -> cholder).
+                        effects(
+                        holder -> {
+                            atomicReference.set(holder.getUpdatedProperties());
+
+                            counter.incrementAndGet();
+
+                            effect.get().run();
+                        },
+                        __ -> {},
+                        __ -> {},
+                        __ -> {},
+                        onUpdate(
+                            from(configurationUpdate, holder -> {
+                                atomicReference.set(holder.getUpdatedProperties());
+
+                                updateCounter.incrementAndGet();
+
+                                effect.get().run();
+                            }))
+                    )).run(bundleContext))
+        {
+            configuration.update(
+                new Hashtable<String, Object>() {{
+                    put("property", "value");
+                }}
+            );
+
+            countDownLatch.await(10, TimeUnit.SECONDS);
+
+            assertEquals(1, counter.get());
+            assertEquals(1, updateCounter.get());
+
+            assertEquals("value", atomicReference.get().get("property"));
+
+            if (serviceRegistration != null) {
+                serviceRegistration.unregister();
+            }
+
+            CountDownLatch deleteLatch = new CountDownLatch(2);
+
+            effect.set(deleteLatch::countDown);
+
+            serviceRegistration =
+                bundleContext.registerService(
+                    ManagedService.class, __ -> deleteLatch.countDown(),
+                    new Hashtable<String, Object>() {{
+                        put("service.pid", "test.configuration");
+                    }});
+
+            configuration.delete();
+
+            deleteLatch.await(10, TimeUnit.SECONDS);
+
+            assertEquals(2, counter.get());
+            assertEquals(1, updateCounter.get());
+
+            assertTrue(atomicReference.get().isEmpty());
+        }
+        finally {
+            bundleContext.ungetService(serviceReference);
+
+            if (serviceRegistration != null) {
+                serviceRegistration.unregister();
+            }
+        }
+    }
+
+
+    @Test
+    public void testCoalesceWithConfigurationUpdateRefresh()
+        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(4);
 
@@ -1752,6 +1871,136 @@ public class DSLTest {
     }
 
     @Test
+    public void testServiceReferenceUpdates() {
+        AtomicReference<String> atomicReference = new AtomicReference<>();
+
+        ServiceRegistration<Service> serviceRegistration =
+            bundleContext.registerService(
+                Service.class, new Service(),
+                new Hashtable<String, Object>() {{
+                    put("property", "original");
+                }});
+
+        AtomicInteger atomicInteger = new AtomicInteger();
+
+        try {
+            OSGi<?> program =
+                serviceReferences(
+                    Service.class,
+                    csr -> csr.getServiceReference().getProperty("property").equals("refresh")
+                ).effects(
+                    csr -> {
+                        atomicReference.set(
+                            String.valueOf(
+                                csr.getServiceReference().getProperty("property")));
+
+                        atomicInteger.incrementAndGet();
+                    },
+                    __ -> {},
+                    __ -> {},
+                    __ -> {},
+                    onUpdate(
+                        from(
+                            UpdateSelector.ALL,
+                            csr ->
+                                atomicReference.set(
+                                    String.valueOf(
+                                        csr.getServiceReference().getProperty("property"))))
+                    )
+                );
+
+            program.run(bundleContext);
+
+            assertEquals(1, atomicInteger.get());
+            assertEquals("original", atomicReference.get());
+
+            serviceRegistration.setProperties(
+                new Hashtable<String, Object>() {{
+                    put("property", "updated");
+                }});
+
+            assertEquals(1, atomicInteger.get());
+            assertEquals("updated", atomicReference.get());
+
+            serviceRegistration.setProperties(
+                new Hashtable<String, Object>() {{
+                    put("property", "refresh");
+                }});
+
+            assertEquals(2, atomicInteger.get());
+            assertEquals("refresh", atomicReference.get());
+        }
+        finally {
+            serviceRegistration.unregister();
+        }
+    }
+
+
+    @Test
+    public void testServiceReferenceUpdatesWithSelector() {
+        AtomicReference<String> atomicReference = new AtomicReference<>();
+
+        ServiceRegistration<Service> serviceRegistration =
+            bundleContext.registerService(
+                Service.class, new Service(),
+                new Hashtable<String, Object>() {{
+                    put("property", "original");
+                }});
+
+        AtomicInteger atomicInteger = new AtomicInteger();
+
+        try {
+            OSGi<?> program = UpdateTuple.flatMap(
+                refreshWhen(
+                    ServiceReferences.withUpdate(Service.class),
+                    (us, ut) -> ut.t.getServiceReference().getProperty("property").equals("refresh")
+                ),
+                (serviceUpdate, csr) ->
+                    effects(
+                    () -> {
+                        atomicReference.set(String.valueOf(csr.getServiceReference().getProperty("property")));
+
+                        atomicInteger.incrementAndGet();
+                    },
+                    () -> {},
+                    () -> {},
+                    () -> {},
+                    onUpdate(
+                        from(
+                            serviceUpdate,
+                            __ ->
+                                atomicReference.set(
+                                    String.valueOf(csr.getServiceReference().getProperty("property"))))
+                ))
+            );
+
+            program.run(bundleContext);
+
+            assertEquals(1, atomicInteger.get());
+            assertEquals("original", atomicReference.get());
+
+            serviceRegistration.setProperties(
+                new Hashtable<String, Object>() {{
+                    put("property", "updated");
+                }});
+
+            assertEquals(1, atomicInteger.get());
+            assertEquals("updated", atomicReference.get());
+
+            serviceRegistration.setProperties(
+                new Hashtable<String, Object>() {{
+                    put("property", "refresh");
+                }});
+
+            assertEquals(2, atomicInteger.get());
+            assertEquals("refresh", atomicReference.get());
+        }
+        finally {
+            serviceRegistration.unregister();
+        }
+    }
+
+    @Test
     public void testServiceReferences() {
         AtomicReference<CachingServiceReference<Service>> atomicReference =
             new AtomicReference<>();


[aries-component-dsl] 04/09: Add methods with update selectors

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csierra pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-component-dsl.git

commit f082f840d8ddbedb37ef38d95321b601466ed30e
Author: Carlos Sierra Andrés <ca...@liferay.com>
AuthorDate: Mon Mar 1 09:42:44 2021 +0100

    Add methods with update selectors
---
 .../main/java/org/apache/aries/component/dsl/OSGi.java | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
index fc6597c..4ba192b 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
@@ -574,6 +574,24 @@ public interface OSGi<T> extends OSGiRunnable<T> {
 			(__, csr) -> onModified.test(csr));
 	}
 
+	static <T> OSGi<UpdateTuple<CachingServiceReference<T>>> serviceReferencesUpdatable(
+		Class<T> clazz) {
+
+		return new ServiceReferenceOSGi<>(null, clazz);
+	}
+
+	static OSGi<UpdateTuple<CachingServiceReference<Object>>> serviceReferencesUpdatable(
+		String filterString) {
+
+		return new ServiceReferenceOSGi<>(filterString, null);
+	}
+
+	static <T> OSGi<UpdateTuple<CachingServiceReference<T>>> serviceReferencesUpdatable(
+		Class<T> clazz, String filterString) {
+
+		return new ServiceReferenceOSGi<>(filterString, clazz);
+	}
+
 	static <T> OSGi<T> services(Class<T> clazz) {
 		return services(clazz, null);
 	}


[aries-component-dsl] 08/09: Update ConfigurationHolder and add static initializers

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csierra pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-component-dsl.git

commit 89291d1f56cfc928edac70a07d016d53177b8aa3
Author: Carlos Sierra Andrés <ca...@liferay.com>
AuthorDate: Wed Mar 3 17:30:54 2021 +0100

    Update ConfigurationHolder and add static initializers
---
 .../dsl/configuration/ConfigurationHolder.java     | 35 ++++++++++++++++++----
 .../dsl/internal/ConfigurationHolderImpl.java      | 19 +-----------
 .../aries/component/dsl/update/UpdateSelector.java |  2 ++
 .../aries/component/dsl/update/UpdateTuple.java    | 15 ++++++++++
 4 files changed, 47 insertions(+), 24 deletions(-)

diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/ConfigurationHolder.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/ConfigurationHolder.java
index f114fb1..6c7c721 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/ConfigurationHolder.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/ConfigurationHolder.java
@@ -18,20 +18,43 @@
 package org.apache.aries.component.dsl.configuration;
 
 import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
 
 public interface ConfigurationHolder {
 
-    String getPid();
-
     Dictionary<String, ?> getProperties();
 
-    String getFactoryPid();
-
     long getChangeCount();
 
-    void refresh();
-
     long getUpdatedChangeCount();
 
     Dictionary<String, ?> getUpdatedProperties();
+
+    public static ConfigurationHolder fromMap(Map<String, ?> map) {
+        return new ConfigurationHolder() {
+
+            final Hashtable<String, ?> properties = new Hashtable<>(map);
+
+            @Override
+            public Dictionary<String, ?> getProperties() {
+                return new Hashtable<>(properties);
+            }
+
+            @Override
+            public long getChangeCount() {
+                return 0;
+            }
+
+            @Override
+            public long getUpdatedChangeCount() {
+                return getChangeCount();
+            }
+
+            @Override
+            public Dictionary<String, ?> getUpdatedProperties() {
+                return getProperties();
+            }
+        };
+    }
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationHolderImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationHolderImpl.java
index 891c27d..c9bf04a 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationHolderImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationHolderImpl.java
@@ -27,7 +27,7 @@ import java.util.concurrent.atomic.AtomicReference;
 public class ConfigurationHolderImpl implements ConfigurationHolder {
 
     private Configuration configuration;
-    private AtomicReference<Dictionary<String, ?>> properties;
+    private AtomicReference<Dictionary<String, ?>> properties = new AtomicReference<>();
     private AtomicLong changeCount = new AtomicLong(-1);
 
     public ConfigurationHolderImpl(Configuration configuration) {
@@ -35,11 +35,6 @@ public class ConfigurationHolderImpl implements ConfigurationHolder {
     }
 
     @Override
-    public String getPid() {
-        return configuration.getPid();
-    }
-
-    @Override
     public Dictionary<String, ?> getProperties() {
         properties.compareAndSet(null, configuration.getProperties());
 
@@ -47,11 +42,6 @@ public class ConfigurationHolderImpl implements ConfigurationHolder {
     }
 
     @Override
-    public String getFactoryPid() {
-        return configuration.getFactoryPid();
-    }
-
-    @Override
     public long getChangeCount() {
         changeCount.compareAndSet(-1, configuration.getChangeCount());
 
@@ -59,13 +49,6 @@ public class ConfigurationHolderImpl implements ConfigurationHolder {
     }
 
     @Override
-    public void refresh() {
-        changeCount.set(-1);
-
-        properties.set(null);
-    }
-
-    @Override
     public long getUpdatedChangeCount() {
         return configuration.getChangeCount();
     }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateSelector.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateSelector.java
index 2478759..397e349 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateSelector.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateSelector.java
@@ -20,4 +20,6 @@ package org.apache.aries.component.dsl.update;
 public interface UpdateSelector {
 
     public static final UpdateSelector ALL = new UpdateSelector() {};
+
+    public static final UpdateSelector STATIC = new UpdateSelector() {};
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateTuple.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateTuple.java
index 0b7b2e3..5622638 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateTuple.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateTuple.java
@@ -17,6 +17,10 @@
 
 package org.apache.aries.component.dsl.update;
 
+import org.apache.aries.component.dsl.OSGi;
+
+import java.util.function.BiFunction;
+
 public final class UpdateTuple<T> {
 
     public final UpdateSelector updateSelector;
@@ -30,4 +34,15 @@ public final class UpdateTuple<T> {
     public T getT() {
         return t;
     }
+
+    public static <S, R> OSGi<R> flatMap(
+        OSGi<UpdateTuple<S>> tuple, BiFunction<UpdateSelector, S, OSGi<R>> biFunction) {
+
+        return tuple.flatMap(updateTuple -> biFunction.apply(updateTuple.updateSelector, updateTuple.t));
+    }
+
+    public static <T> UpdateTuple<T> fromStatic(T t) {
+        return new UpdateTuple<>(UpdateSelector.STATIC, t);
+    }
+
 }


[aries-component-dsl] 01/09: Add update support to OSGi result

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csierra pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-component-dsl.git

commit 50de3d5e26d04a39d07b910326107f387991b18f
Author: Carlos Sierra Andrés <ca...@liferay.com>
AuthorDate: Thu Feb 25 12:33:34 2021 +0100

    Add update support to OSGi result
---
 .../java/org/apache/aries/component/dsl/OSGi.java  |  17 ++-
 .../org/apache/aries/component/dsl/OSGiResult.java |   4 +
 ...SGiResultImpl.java => AggregateOSGiResult.java} |  49 ++++++---
 .../aries/component/dsl/internal/AllOSGi.java      |   3 +-
 .../aries/component/dsl/internal/BaseOSGiImpl.java | 121 ++++++++++++++-------
 .../aries/component/dsl/internal/BundleOSGi.java   |  22 ++--
 .../component/dsl/internal/CoalesceOSGiImpl.java   |  14 ++-
 .../dsl/internal/ConfigurationOSGiImpl.java        |  14 ++-
 .../dsl/internal/ConfigurationsOSGiImpl.java       |  18 ++-
 .../component/dsl/internal/DistributeOSGiImpl.java |  23 ++--
 .../aries/component/dsl/internal/EffectsOSGi.java  |  59 ++++++----
 .../component/dsl/internal/HighestRankingOSGi.java |  60 +++++-----
 .../aries/component/dsl/internal/JustOSGiImpl.java |   4 +-
 .../component/dsl/internal/NothingOSGiImpl.java    |   2 +-
 .../component/dsl/internal/OSGiResultImpl.java     |  16 ++-
 .../component/dsl/internal/OnlyLastPublisher.java  |  24 ++--
 .../apache/aries/component/dsl/internal/Pad.java   |   9 +-
 .../aries/component/dsl/internal/ProbeImpl.java    |   6 +-
 .../dsl/internal/ServiceReferenceOSGi.java         |  15 ++-
 .../dsl/internal/ServiceRegistrationOSGiImpl.java  |   7 +-
 .../UpdateQuery.java}                              |  48 ++++----
 .../UpdateSelector.java}                           |  15 +--
 .../{OSGiResult.java => update/package-info.java}  |  18 +--
 itests-run/itest.bndrun                            |   3 +-
 24 files changed, 361 insertions(+), 210 deletions(-)

diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
index 619e22f..50502ba 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
@@ -44,6 +44,7 @@ import org.apache.aries.component.dsl.function.Function26;
 import org.apache.aries.component.dsl.function.Function3;
 import org.apache.aries.component.dsl.function.Function5;
 import org.apache.aries.component.dsl.function.Function7;
+import org.apache.aries.component.dsl.update.UpdateQuery;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceFactory;
@@ -303,11 +304,12 @@ public interface OSGi<T> extends OSGiRunnable<T> {
 			() -> effect.getOnIncoming().accept(null),
 			NOOP,
 			NOOP,
-			() -> effect.getOnLeaving().accept(null));
+			() -> effect.getOnLeaving().accept(null),
+			UpdateQuery.onUpdate());
 	}
 
 	static OSGi<Void> effects(Runnable onAdding, Runnable onRemoving) {
-		return new EffectsOSGi(onAdding, NOOP, NOOP, onRemoving);
+		return new EffectsOSGi(onAdding, NOOP, NOOP, onRemoving, UpdateQuery.onUpdate());
 	}
 
 	static OSGi<Void> effects(
@@ -315,7 +317,16 @@ public interface OSGi<T> extends OSGiRunnable<T> {
 		Runnable onRemovingBefore, Runnable onRemovingAfter) {
 
 		return new EffectsOSGi(
-			onAddingBefore, onAddingAfter, onRemovingBefore, onRemovingAfter);
+			onAddingBefore, onAddingAfter, onRemovingBefore, onRemovingAfter,
+			UpdateQuery.onUpdate());
+	}
+
+	static OSGi<Void> effects(
+		Runnable onAddingBefore, Runnable onAddingAfter,
+		Runnable onRemovingBefore, Runnable onRemovingAfter, UpdateQuery<Void> updateQuery) {
+
+		return new EffectsOSGi(
+			onAddingBefore, onAddingAfter, onRemovingBefore, onRemovingAfter, updateQuery);
 	}
 
 	static <T> OSGi<T> fromOsgiRunnable(OSGiRunnable<T> runnable) {
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java
index 0434e2b..ad56515 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java
@@ -17,6 +17,8 @@
 
 package org.apache.aries.component.dsl;
 
+import org.apache.aries.component.dsl.update.UpdateSelector;
+
 /**
  * @author Carlos Sierra Andrés
  */
@@ -29,4 +31,6 @@ public interface OSGiResult extends AutoCloseable, Runnable {
 		close();
 	}
 
+	public default void update(UpdateSelector updateSelector) {};
+
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AggregateOSGiResult.java
similarity index 52%
copy from component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java
copy to component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AggregateOSGiResult.java
index 8851c66..24e5124 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AggregateOSGiResult.java
@@ -18,26 +18,45 @@
 package org.apache.aries.component.dsl.internal;
 
 import org.apache.aries.component.dsl.OSGiResult;
+import org.apache.aries.component.dsl.update.UpdateSelector;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * @author Carlos Sierra Andrés
  */
-public class OSGiResultImpl implements OSGiResult {
-
-	public OSGiResultImpl(OSGiResult close) {
-		this.close = close;
-	}
-
-	@Override
-	public void close() {
-		if (_closed.compareAndSet(false, true)) {
-			close.run();
-		}
-	}
-
-	private final Runnable close;
-	private AtomicBoolean _closed = new AtomicBoolean();
+public class AggregateOSGiResult implements OSGiResult {
+
+    private OSGiResult[] results;
+
+    public AggregateOSGiResult(OSGiResult ... results) {
+        this.results = results;
+    }
+
+    @Override
+    public void close() {
+        if (_closed.compareAndSet(false, true)) {
+            for (OSGiResult result : results) {
+                try {
+                    result.close();
+                } catch (Exception e) {
+                }
+            }
+        }
+    }
+
+    @Override
+    public void update(UpdateSelector updateSelector) {
+        if (!_closed.get()) {
+            for (OSGiResult result : results) {
+                try {
+                    result.update(updateSelector);
+                } catch (Exception e) {
+                }
+            }
+        }
+    }
+
+    private final AtomicBoolean _closed = new AtomicBoolean();
 
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AllOSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AllOSGi.java
index 3c3e502..aa652c6 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AllOSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/AllOSGi.java
@@ -45,7 +45,8 @@ public class AllOSGi<T> extends OSGiImpl<T> {
             }
 
             return new OSGiResultImpl(
-                () -> cleanUp(results)
+                () -> cleanUp(results),
+                us -> results.forEach(result -> result.update(us))
             );
         });
     }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BaseOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BaseOSGiImpl.java
index 1b68e2a..cb554a2 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BaseOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BaseOSGiImpl.java
@@ -18,6 +18,8 @@
 package org.apache.aries.component.dsl.internal;
 
 import org.apache.aries.component.dsl.*;
+import org.apache.aries.component.dsl.update.UpdateQuery;
+import org.apache.aries.component.dsl.update.UpdateSelector;
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
 
@@ -104,7 +106,7 @@ public class BaseOSGiImpl<T> implements OSGi<T> {
 		return new BaseOSGiImpl<>((executionContext, op) -> {
 			ConcurrentDoublyLinkedList<T> identities = new ConcurrentDoublyLinkedList<>();
 			ConcurrentDoublyLinkedList<Function<T,S>> functions = new ConcurrentDoublyLinkedList<>();
-			IdentityHashMap<T, IdentityHashMap<Function<T, S>, Runnable>>
+			IdentityHashMap<T, IdentityHashMap<Function<T, S>, OSGiResult>>
 				terminators = new IdentityHashMap<>();
 
 			OSGiResult funRun = fun.run(
@@ -114,23 +116,35 @@ public class BaseOSGiImpl<T> implements OSGi<T> {
 						ConcurrentDoublyLinkedList.Node node = functions.addLast(f);
 
 						for (T t : identities) {
-							IdentityHashMap<Function<T, S>, Runnable> terminatorMap =
+							IdentityHashMap<Function<T, S>, OSGiResult> terminatorMap =
 								terminators.computeIfAbsent(
 									t, __ -> new IdentityHashMap<>());
 							terminatorMap.put(f, op.apply(f.apply(t)));
 						}
 
-						return () -> {
-							synchronized (identities) {
-								node.remove();
+						return new OSGiResultImpl(
+							() -> {
+								synchronized (identities) {
+									node.remove();
 
-								identities.forEach(t -> {
-									Runnable terminator = terminators.get(t).remove(f);
+									identities.forEach(t -> {
+										Runnable terminator = terminators.get(t).remove(f);
 
-									terminator.run();
-								});
+										terminator.run();
+									});
+								}
+							},
+							us -> {
+								synchronized (identities) {
+
+									identities.forEach(t -> {
+										OSGiResult terminator = terminators.get(t).get(f);
+
+										terminator.update(us);
+									});
+								}
 							}
-						};
+						);
 					}
 				}
 			));
@@ -142,32 +156,39 @@ public class BaseOSGiImpl<T> implements OSGi<T> {
 						ConcurrentDoublyLinkedList.Node node = identities.addLast(t);
 
 						for (Function<T, S> f : functions) {
-							IdentityHashMap<Function<T, S>, Runnable> terminatorMap =
+							IdentityHashMap<Function<T, S>, OSGiResult> terminatorMap =
 								terminators.computeIfAbsent(
 									t, __ -> new IdentityHashMap<>());
 							terminatorMap.put(f, op.apply(f.apply(t)));
 						}
 
-						return () -> {
-							synchronized (identities) {
-								node.remove();
-
-								functions.forEach(f -> {
-									Runnable terminator = terminators.get(t).remove(f);
-
-									terminator.run();
-								});
+						return new OSGiResultImpl(
+							() -> {
+								synchronized (identities) {
+									node.remove();
+
+									functions.forEach(f -> {
+										Runnable terminator = terminators.get(t).remove(f);
+
+										terminator.run();
+									});
+								}
+							},
+							us -> {
+								synchronized (identities) {
+									functions.forEach(f -> {
+										OSGiResult terminator = terminators.get(t).get(f);
+
+										terminator.update(us);
+									});
+								}
 							}
-						};
+						);
 					}
 				})
 			);
 
-			return () -> {
-				myRun.close();
-
-				funRun.close();
-			};
+			return new AggregateOSGiResult(myRun, funRun);
 		});
 	}
 
@@ -192,11 +213,7 @@ public class BaseOSGiImpl<T> implements OSGi<T> {
                         }
                     }
                 )));
-			return () -> {
-				thenPad.close();
-				elsePad.close();
-				result.close();
-			};
+			return new AggregateOSGiResult(thenPad, elsePad, result);
 		});
 	}
 
@@ -211,6 +228,15 @@ public class BaseOSGiImpl<T> implements OSGi<T> {
 		Consumer<? super T> onRemovedBefore,
 		Consumer<? super T> onRemovedAfter) {
 
+		return effects(onAddedBefore, onAddedAfter, onRemovedBefore, onRemovedAfter, UpdateQuery.onUpdate());
+	}
+
+	public OSGi<T> effects(
+		Consumer<? super T> onAddedBefore, Consumer<? super T> onAddedAfter,
+		Consumer<? super T> onRemovedBefore,
+		Consumer<? super T> onRemovedAfter,
+		UpdateQuery<T> updateQuery) {
+
 		//TODO: logging
 		//TODO: logging
 		//TODO: logging
@@ -222,9 +248,9 @@ public class BaseOSGiImpl<T> implements OSGi<T> {
 					onAddedBefore.accept(t);
 
 					try {
-						Runnable terminator = op.publish(t);
+						OSGiResult terminator = op.publish(t);
 
-						OSGiResult result = () -> {
+						OSGiResult result = new OSGiResultImpl(() -> {
 							try {
 								onRemovedBefore.accept(t);
 							}
@@ -245,7 +271,19 @@ public class BaseOSGiImpl<T> implements OSGi<T> {
 							catch (Exception e) {
 								//TODO: logging
 							}
-						};
+						},
+							us -> {
+								UpdateQuery.From<T>[] froms = updateQuery.froms;
+
+								for (UpdateQuery.From<T> from : froms) {
+									if (from.selector == us || from.selector == UpdateSelector.ALL) {
+										from.consumer.accept(t);
+									}
+								}
+
+								terminator.update(us);
+							}
+						);
 
 						try {
 							onAddedAfter.accept(t);
@@ -353,11 +391,18 @@ public class BaseOSGiImpl<T> implements OSGi<T> {
 				)
 			));
 
-			return () -> {
-				pads.values().forEach(Pad::close);
+			return new OSGiResultImpl(
+				() -> {
+					pads.values().forEach(Pad::close);
+
+					result.close();
+				},
+				us -> {
+					pads.values().forEach(pad -> pad.update(us));
 
-				result.close();
-			};
+					result.close();
+				}
+			);
 		});
 	}
 
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BundleOSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BundleOSGi.java
index 48de45f..2b5ca5c 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BundleOSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/BundleOSGi.java
@@ -17,6 +17,8 @@
 
 package org.apache.aries.component.dsl.internal;
 
+import org.apache.aries.component.dsl.OSGiResult;
+import org.apache.aries.component.dsl.update.UpdateSelector;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleEvent;
 import org.osgi.util.tracker.BundleTracker;
@@ -29,13 +31,15 @@ public class BundleOSGi extends OSGiImpl<Bundle> {
 
 	public BundleOSGi(int stateMask) {
 		super((executionContext, op) -> {
-			BundleTracker<Runnable> bundleTracker =
+			UpdateSelector updateSelector = new UpdateSelector() {};
+
+			BundleTracker<OSGiResult> bundleTracker =
 				new BundleTracker<>(
 					executionContext.getBundleContext(), stateMask,
-					new BundleTrackerCustomizer<Runnable>() {
+					new BundleTrackerCustomizer<OSGiResult>() {
 
 						@Override
-						public Runnable addingBundle(
+						public OSGiResult addingBundle(
 							Bundle bundle, BundleEvent bundleEvent) {
 
 							return op.apply(bundle);
@@ -44,22 +48,26 @@ public class BundleOSGi extends OSGiImpl<Bundle> {
 						@Override
 						public void modifiedBundle(
 							Bundle bundle, BundleEvent bundleEvent,
-							Runnable runnable) {
+							OSGiResult osgiResult) {
 
+							osgiResult.update(updateSelector);
 						}
 
 						@Override
 						public void removedBundle(
 							Bundle bundle, BundleEvent bundleEvent,
-							Runnable runnable) {
+							OSGiResult osgiResult) {
 
-							runnable.run();
+							osgiResult.run();
 						}
 					});
 
 			bundleTracker.open();
 
-			return new OSGiResultImpl(bundleTracker::close);
+			return new OSGiResultImpl(
+				bundleTracker::close,
+				us -> bundleTracker.getTracked().values().forEach(result -> result.update(us))
+			);
 		});
 
 	}
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/CoalesceOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/CoalesceOSGiImpl.java
index 2c44cbf..3aff2be 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/CoalesceOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/CoalesceOSGiImpl.java
@@ -70,7 +70,7 @@ public class CoalesceOSGiImpl<T> extends OSGiImpl<T> {
                             () -> result.set(op.publish(t)));
                     }
 
-                    return () -> UpdateSupport.deferTermination(() -> {
+                    return new OSGiResultImpl(() -> UpdateSupport.deferTermination(() -> {
                         synchronized (initialized) {
                             result.get().close();
 
@@ -93,6 +93,11 @@ public class CoalesceOSGiImpl<T> extends OSGiImpl<T> {
                                 }
                             }
                         }
+                    }),
+                    us -> {
+                        synchronized (initialized) {
+                            result.get().update(us);
+                        }
                     });
                 };
             }
@@ -123,6 +128,13 @@ public class CoalesceOSGiImpl<T> extends OSGiImpl<T> {
                             results[i].close();
                         }
                     }
+                },
+                us -> {
+                    synchronized (initialized) {
+                        for (int i = 0; i <= index.get(); i++) {
+                            results[i].update(us);
+                        }
+                    }
                 }
             );
         });
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
index 817c617..26cefbe 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
@@ -17,6 +17,7 @@
 
 package org.apache.aries.component.dsl.internal;
 
+import org.apache.aries.component.dsl.OSGiResult;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
@@ -42,8 +43,9 @@ public class ConfigurationOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 			AtomicReference<Configuration> atomicReference =
 				new AtomicReference<>(null);
 
-			AtomicReference<Runnable>
-				terminatorAtomicReference = new AtomicReference<>(() -> {});
+			AtomicReference<OSGiResult>
+				terminatorAtomicReference = new AtomicReference<>(
+					new OSGiResultImpl(NOOP, __ -> {}));
 
 			AtomicBoolean closed = new AtomicBoolean();
 
@@ -138,7 +140,9 @@ public class ConfigurationOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 					serviceRegistration.unregister();
 
 					signalLeave(terminatorAtomicReference);
-				});
+				},
+				us -> terminatorAtomicReference.get().update(us))
+			;
 		});
 	}
 
@@ -180,9 +184,9 @@ public class ConfigurationOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 	}
 
 	private static void signalLeave(
-		AtomicReference<Runnable> terminatorAtomicReference) {
+		AtomicReference<OSGiResult> terminatorAtomicReference) {
 
-		Runnable old = terminatorAtomicReference.getAndSet(null);
+		OSGiResult old = terminatorAtomicReference.getAndSet(null);
 
 		if (old != null) {
             old.run();
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
index 2991daa..fe16e10 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
@@ -17,6 +17,7 @@
 
 package org.apache.aries.component.dsl.internal;
 
+import org.apache.aries.component.dsl.OSGiResult;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
@@ -42,7 +43,7 @@ public class ConfigurationsOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 			ConcurrentHashMap<String, Configuration> configurations =
 				new ConcurrentHashMap<>();
 
-			ConcurrentHashMap<String, Runnable> terminators =
+			ConcurrentHashMap<String, OSGiResult> terminators =
 				new ConcurrentHashMap<>();
 
 			AtomicBoolean closed = new AtomicBoolean();
@@ -148,6 +149,13 @@ public class ConfigurationsOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 							runnable.run();
 						}
 					}
+				},
+				us -> {
+					for (OSGiResult osgiResult : terminators.values()) {
+						if (osgiResult != null) {
+							osgiResult.run();
+						}
+					}
 				});
 		});
 	}
@@ -218,12 +226,12 @@ public class ConfigurationsOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 	}
 
 	private static void signalLeave(
-		String factoryPid, ConcurrentHashMap<String, Runnable> terminators) {
+		String factoryPid, ConcurrentHashMap<String, OSGiResult> terminators) {
 
-		Runnable runnable = terminators.remove(factoryPid);
+		OSGiResult osgiResult = terminators.remove(factoryPid);
 
-		if (runnable != null) {
-			runnable.run();
+		if (osgiResult != null) {
+			osgiResult.run();
 		}
 	}
 
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/DistributeOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/DistributeOSGiImpl.java
index ee5f800..5f21e76 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/DistributeOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/DistributeOSGiImpl.java
@@ -44,7 +44,7 @@ public class DistributeOSGiImpl<T, S> extends BaseOSGiImpl<S> {
             OSGiResult result = operation.run(
                 executionContext,
                 publisher.pipe(t -> {
-                    List<Runnable> terminators = new ArrayList<>(funs.length);
+                    List<OSGiResult> terminators = new ArrayList<>(funs.length);
 
                     int i = 0;
 
@@ -59,25 +59,18 @@ public class DistributeOSGiImpl<T, S> extends BaseOSGiImpl<S> {
                         throw e;
                     }
 
-                    return () -> cleanUp(terminators);
+                    return new OSGiResultImpl(
+                        () -> cleanUp(terminators),
+                        us -> terminators.forEach(os -> os.update(us))
+                    );
                 }));
 
-            return () -> {
-                result.close();
-
-                for (Pad<T, S> pad : pads) {
-                    try {
-                        pad.close();
-                    }
-                    catch (Exception e) {
-                    }
-                }
-            };
+            return new AggregateOSGiResult(result, new AggregateOSGiResult(pads));
         });
     }
 
-    private static void cleanUp(List<Runnable> terminators) {
-        ListIterator<Runnable> iterator =
+    private static void cleanUp(List<OSGiResult> terminators) {
+        ListIterator<OSGiResult> iterator =
             terminators.listIterator(terminators.size());
 
         while (iterator.hasPrevious()) {
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/EffectsOSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/EffectsOSGi.java
index 8f9f910..932f29c 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/EffectsOSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/EffectsOSGi.java
@@ -18,6 +18,8 @@
 package org.apache.aries.component.dsl.internal;
 
 import org.apache.aries.component.dsl.OSGiResult;
+import org.apache.aries.component.dsl.update.UpdateQuery;
+import org.apache.aries.component.dsl.update.UpdateSelector;
 
 /**
  * @author Carlos Sierra Andrés
@@ -26,36 +28,49 @@ public class EffectsOSGi extends OSGiImpl<Void> {
 
     public EffectsOSGi(
         Runnable onAddingBefore, Runnable onAddingAfter,
-        Runnable onRemovingBefore, Runnable onRemovingAfter) {
+        Runnable onRemovingBefore, Runnable onRemovingAfter, UpdateQuery<Void> updateQuery) {
 
         super((executionContext, op) -> {
             onAddingBefore.run();
 
             try {
-                Runnable terminator = op.publish(null);
+                OSGiResult terminator = op.publish(null);
 
-                OSGiResult result = () -> {
-                    try {
-                        onRemovingBefore.run();
-                    }
-                    catch (Exception e) {
-                        //TODO: logging
-                    }
+                OSGiResult result = new OSGiResultImpl(
+                    () -> {
+                        try {
+                            onRemovingBefore.run();
+                        }
+                        catch (Exception e) {
+                            //TODO: logging
+                        }
 
-                    try {
-                        terminator.run();
-                    }
-                    catch (Exception e) {
-                        //TODO: logging
-                    }
+                        try {
+                            terminator.run();
+                        }
+                        catch (Exception e) {
+                            //TODO: logging
+                        }
 
-                    try {
-                        onRemovingAfter.run();
-                    }
-                    catch (Exception e) {
-                        //TODO: logging
+                        try {
+                            onRemovingAfter.run();
+                        }
+                        catch (Exception e) {
+                            //TODO: logging
+                        }
+                    },
+                    us -> {
+                        UpdateQuery.From<Void>[] froms = updateQuery.froms;
+
+                        for (UpdateQuery.From<Void> from : froms) {
+                            if (from.selector == us || from.selector == UpdateSelector.ALL) {
+                                from.consumer.accept(null);
+                            }
+                        }
+
+                        terminator.update(us);
                     }
-                };
+                );
 
                 try {
                     onAddingAfter.run();
@@ -66,7 +81,7 @@ public class EffectsOSGi extends OSGiImpl<Void> {
                     throw e;
                 }
 
-                return new OSGiResultImpl(result);
+                return result;
             }
             catch (Exception e) {
                 try {
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/HighestRankingOSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/HighestRankingOSGi.java
index 99cd1dc..e9dc9fb 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/HighestRankingOSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/HighestRankingOSGi.java
@@ -56,64 +56,68 @@ public class HighestRankingOSGi<T> extends OSGiImpl<T> {
                             Tuple<T> old = sent.get();
 
                             if (old != null) {
-                                old._runnable.run();
+                                old.osgiResult.run();
                             }
 
-                            tuple._runnable = publisher.apply(t);
+                            tuple.osgiResult = publisher.apply(t);
 
                             if (old != null) {
-                                old._runnable = notHighestPad.publish(old._t);
+                                old.osgiResult = notHighestPad.publish(old.t);
                             }
 
                             sent.set(tuple);
                         } else {
-                            tuple._runnable = notHighestPad.publish(t);
+                            tuple.osgiResult = notHighestPad.publish(t);
                         }
                     }
 
-                    return () -> {
-                        synchronized (set) {
-                            Tuple<T> old = set.peek();
+                    return new OSGiResultImpl(
+                        () -> {
+                            synchronized (set) {
+                                Tuple<T> old = set.peek();
 
-                            set.remove(tuple);
+                                set.remove(tuple);
 
-                            Tuple<T> current = set.peek();
+                                Tuple<T> current = set.peek();
 
-                            tuple._runnable.run();
+                                tuple.osgiResult.run();
 
-                            if (current != old && current != null) {
-                                current._runnable.run();
-                                current._runnable = publisher.apply(
-                                    current._t);
-                                sent.set(current);
+                                if (current != old && current != null) {
+                                    current.osgiResult.run();
+                                    current.osgiResult = publisher.apply(
+                                        current.t);
+                                    sent.set(current);
+                                }
+                                if (current == null) {
+                                    sent.set(null);
+                                }
                             }
-                            if (current == null) {
-                                sent.set(null);
+                        },
+                        us -> {
+                            synchronized (set) {
+                                Tuple<T> current = set.peek();
+
+                                current.osgiResult.update(us);
                             }
                         }
-                    };
+                    );
                 }));
 
-            return new OSGiResultImpl(
-                () -> {
-                    result.close();
-
-                    notHighestPad.close();
-                });
+            return new AggregateOSGiResult(result, notHighestPad);
         });
     }
 
     private static class Tuple<T> {
 
         Tuple(T t) {
-            _t = t;
+            this.t = t;
         }
 
         public T getT() {
-            return _t;
+            return t;
         }
-        T _t;
-        Runnable _runnable;
+        T t;
+        OSGiResult osgiResult;
 
     }
 
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/JustOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/JustOSGiImpl.java
index 047e9bf..8b4dae7 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/JustOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/JustOSGiImpl.java
@@ -52,7 +52,9 @@ public class JustOSGiImpl<T> extends OSGiImpl<T> {
 			}
 
 			return new OSGiResultImpl(
-				() -> cleanUp(references));
+				() -> cleanUp(references),
+				us -> {}
+			);
 		});
 	}
 
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/NothingOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/NothingOSGiImpl.java
index 54aa504..5c2dfd3 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/NothingOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/NothingOSGiImpl.java
@@ -25,6 +25,6 @@ import org.apache.aries.component.dsl.OSGi;
 public class NothingOSGiImpl<S> extends OSGiImpl<S> {
 
 	public NothingOSGiImpl() {
-		super((executionContext, __) -> new OSGiResultImpl(OSGi.NOOP));
+		super((executionContext, __) -> new OSGiResultImpl(OSGi.NOOP,  ___ -> {}));
 	}
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java
index 8851c66..bce94c3 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java
@@ -18,16 +18,19 @@
 package org.apache.aries.component.dsl.internal;
 
 import org.apache.aries.component.dsl.OSGiResult;
+import org.apache.aries.component.dsl.update.UpdateSelector;
 
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
 
 /**
  * @author Carlos Sierra Andrés
  */
 public class OSGiResultImpl implements OSGiResult {
 
-	public OSGiResultImpl(OSGiResult close) {
+	public OSGiResultImpl(Runnable close, Consumer<UpdateSelector> onUpdate) {
 		this.close = close;
+		this.onUpdate = onUpdate;
 	}
 
 	@Override
@@ -37,7 +40,18 @@ public class OSGiResultImpl implements OSGiResult {
 		}
 	}
 
+	@Override
+	public void update(UpdateSelector updateSelector) {
+		if (_closed.get()) {
+			return;
+		}
+
+		onUpdate.accept(updateSelector);
+	}
+
 	private final Runnable close;
+	private Consumer<UpdateSelector> onUpdate;
+	private Runnable update;
 	private AtomicBoolean _closed = new AtomicBoolean();
 
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OnlyLastPublisher.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OnlyLastPublisher.java
index 50bf7f4..cd316da 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OnlyLastPublisher.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OnlyLastPublisher.java
@@ -44,7 +44,7 @@ public class OnlyLastPublisher<T> implements Publisher<T> {
     private final Publisher<? super T> _op;
     private AtomicLong _counter = new AtomicLong();
     private Supplier<T> _injectOnLeave;
-    private Runnable _terminator;
+    private OSGiResult _terminator;
 
     @Override
     public synchronized OSGiResult publish(T t) {
@@ -58,16 +58,24 @@ public class OnlyLastPublisher<T> implements Publisher<T> {
         else {
             _counter.incrementAndGet();
 
-            return () -> {
-                synchronized (this) {
-                    _terminator.run();
+            return new OSGiResultImpl(
+                () -> {
+                    synchronized (this) {
+                        _terminator.run();
 
-                    if (_counter.decrementAndGet() > 0) {
-                        _terminator = _op.publish(_injectOnLeave.get());
+                        if (_counter.decrementAndGet() > 0) {
+                            _terminator = _op.publish(_injectOnLeave.get());
+                        }
                     }
-                }
-            };
+                },
+                us -> _terminator.update(us)
+            );
         }
     }
 
+    @Override
+    public <E extends Exception> OSGiResult error(T t, Exception e) throws E {
+        return _op.error(t, e);
+    }
+
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/Pad.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/Pad.java
index d9615a7..fd6f305 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/Pad.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/Pad.java
@@ -21,8 +21,8 @@ import org.apache.aries.component.dsl.OSGi;
 import org.apache.aries.component.dsl.OSGiResult;
 import org.apache.aries.component.dsl.OSGiRunnable.ExecutionContext;
 import org.apache.aries.component.dsl.Publisher;
+import org.apache.aries.component.dsl.update.UpdateSelector;
 
-import java.io.Closeable;
 import java.util.function.Function;
 
 import static org.apache.aries.component.dsl.OSGi.NOOP;
@@ -30,7 +30,7 @@ import static org.apache.aries.component.dsl.OSGi.NOOP;
 /**
  * @author Carlos Sierra Andrés
  */
-public class Pad<T, S> implements Publisher<T>, Closeable {
+public class Pad<T, S> implements Publisher<T>, OSGiResult {
 
     public Pad(
         ExecutionContext bundleContext,
@@ -56,6 +56,11 @@ public class Pad<T, S> implements Publisher<T>, Closeable {
     }
 
     @Override
+    public void update(UpdateSelector updateSelector) {
+        _result.update(updateSelector);
+    }
+
+    @Override
     public OSGiResult publish(T t) {
         return _publisher.publish(t);
     }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ProbeImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ProbeImpl.java
index 1ee95ab..b825dc3 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ProbeImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ProbeImpl.java
@@ -36,7 +36,7 @@ public class ProbeImpl<T> extends BaseOSGiImpl<T> {
 
     private static class ProbeOperationImpl<T> implements OSGiRunnable<T> {
 
-        private OSGiResult _onClose = NOOP;
+        private volatile OSGiResult _onClose = NOOP;
 
         @Override
         public OSGiResultImpl run(
@@ -44,7 +44,9 @@ public class ProbeImpl<T> extends BaseOSGiImpl<T> {
             _op = op;
 
             return new OSGiResultImpl(
-                () -> {_onClose.close(); _onClose = NOOP;});
+                () -> {_onClose.close(); _onClose = NOOP;},
+                us -> _onClose.update(us)
+            );
         }
 
         Publisher<? super T> _op;
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java
index 37ffe30..a5ac0d2 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java
@@ -17,6 +17,7 @@
 
 package org.apache.aries.component.dsl.internal;
 
+import org.apache.aries.component.dsl.OSGiResult;
 import org.apache.aries.component.dsl.Refresher;
 import org.apache.aries.component.dsl.CachingServiceReference;
 import org.apache.aries.component.dsl.Publisher;
@@ -41,7 +42,7 @@ public class ServiceReferenceOSGi<T>
 		Refresher<? super CachingServiceReference<T>> refresher) {
 
 		super((executionContext, op) -> {
-			ServiceTracker<T, ?>
+			ServiceTracker<T, Tracked<T>>
 				serviceTracker = new ServiceTracker<>(
 					executionContext.getBundleContext(),
 					buildFilter(executionContext, filterString, clazz),
@@ -49,7 +50,11 @@ public class ServiceReferenceOSGi<T>
 
 			serviceTracker.open();
 
-			return new OSGiResultImpl(serviceTracker::close);
+			return new OSGiResultImpl(
+				serviceTracker::close,
+				us -> serviceTracker.getTracked().forEach(
+					(__, tracked) -> tracked.runnable.update(us))
+			);
 		});
 	}
 
@@ -105,14 +110,14 @@ public class ServiceReferenceOSGi<T>
 
 		public Tracked(
 			CachingServiceReference<T> cachingServiceReference,
-			Runnable runnable) {
+			OSGiResult osgiResult) {
 
 			this.cachingServiceReference = cachingServiceReference;
-			this.runnable = runnable;
+			this.runnable = osgiResult;
 		}
 
 		volatile CachingServiceReference<T> cachingServiceReference;
-		volatile Runnable runnable;
+		volatile OSGiResult runnable;
 
 	}
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceRegistrationOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceRegistrationOSGiImpl.java
index df5cb23..d4479e8 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceRegistrationOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceRegistrationOSGiImpl.java
@@ -17,6 +17,7 @@
 
 package org.apache.aries.component.dsl.internal;
 
+import org.apache.aries.component.dsl.OSGiResult;
 import org.apache.aries.component.dsl.Publisher;
 import org.osgi.framework.ServiceFactory;
 import org.osgi.framework.ServiceRegistration;
@@ -86,7 +87,7 @@ public class ServiceRegistrationOSGiImpl<T>
 		ServiceRegistration<?> serviceRegistration,
 		Publisher<? super ServiceRegistration<T>> op) {
 
-		Runnable terminator = ((Publisher)op).publish(serviceRegistration);
+		OSGiResult terminator = ((Publisher)op).publish(serviceRegistration);
 
 		return new OSGiResultImpl(
             () -> {
@@ -98,7 +99,9 @@ public class ServiceRegistrationOSGiImpl<T>
                 finally {
                     terminator.run();
                 }
-            });
+            },
+			terminator::update
+		);
 	}
 
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateQuery.java
similarity index 51%
copy from component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java
copy to component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateQuery.java
index 8851c66..d6e3870 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/OSGiResultImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateQuery.java
@@ -15,29 +15,37 @@
  * limitations under the License.
  */
 
-package org.apache.aries.component.dsl.internal;
+package org.apache.aries.component.dsl.update;
 
-import org.apache.aries.component.dsl.OSGiResult;
-
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
 
 /**
  * @author Carlos Sierra Andrés
  */
-public class OSGiResultImpl implements OSGiResult {
-
-	public OSGiResultImpl(OSGiResult close) {
-		this.close = close;
-	}
-
-	@Override
-	public void close() {
-		if (_closed.compareAndSet(false, true)) {
-			close.run();
-		}
-	}
-
-	private final Runnable close;
-	private AtomicBoolean _closed = new AtomicBoolean();
-
+public final class UpdateQuery<T> {
+    public final From<T>[] froms;
+
+    @SafeVarargs
+    public UpdateQuery(From<T>... froms) {
+        this.froms = froms;
+    }
+
+    @SafeVarargs
+    public static <T> UpdateQuery<T> onUpdate(From<T> ... froms) {
+        return new UpdateQuery<>(froms);
+    }
+
+    public static class From<T> {
+        public final UpdateSelector selector;
+        public final Consumer<T> consumer;
+
+        public From(UpdateSelector selector, Consumer<T> consumer) {
+            this.selector = selector;
+            this.consumer = consumer;
+        }
+
+        public static <T> From<T> from(UpdateSelector selector, Consumer<T> consumer) {
+            return new From<>(selector, consumer);
+        }
+    }
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateSelector.java
similarity index 79%
copy from component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java
copy to component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateSelector.java
index 0434e2b..2478759 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/update/UpdateSelector.java
@@ -15,18 +15,9 @@
  * limitations under the License.
  */
 
-package org.apache.aries.component.dsl;
+package org.apache.aries.component.dsl.update;
 
-/**
- * @author Carlos Sierra Andrés
- */
-public interface OSGiResult extends AutoCloseable, Runnable {
-
-	@Override
-	public void close();
-
-	default void run() {
-		close();
-	}
+public interface UpdateSelector {
 
+    public static final UpdateSelector ALL = new UpdateSelector() {};
 }
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/update/package-info.java
similarity index 78%
copy from component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java
copy to component-dsl/src/main/java/org/apache/aries/component/dsl/update/package-info.java
index 0434e2b..4a45062 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGiResult.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/update/package-info.java
@@ -15,18 +15,6 @@
  * limitations under the License.
  */
 
-package org.apache.aries.component.dsl;
-
-/**
- * @author Carlos Sierra Andrés
- */
-public interface OSGiResult extends AutoCloseable, Runnable {
-
-	@Override
-	public void close();
-
-	default void run() {
-		close();
-	}
-
-}
+@org.osgi.annotation.bundle.Export
+@org.osgi.annotation.versioning.Version("1.0.0")
+package org.apache.aries.component.dsl.update;
diff --git a/itests-run/itest.bndrun b/itests-run/itest.bndrun
index 930f56e..a200c08 100644
--- a/itests-run/itest.bndrun
+++ b/itests-run/itest.bndrun
@@ -32,6 +32,7 @@
 	org.apache.servicemix.bundles.junit;version='[4.12.0,4.12.1)',\
 	org.apache.felix.configadmin;version='[1.9.14,1.9.15)',\
 	org.osgi.service.cm;version='[1.6.0,1.6.1)',\
-	org.apache.aries.component-dsl.itests;version='[2.0.0,2.0.1)'
+	org.apache.aries.component-dsl.itests;version='[2.0.0,2.0.1)',\
+	org.apache.aries.component-dsl.component-dsl;version='[2.0.0,2.0.1)'
 
 -include: -personal.bnd


[aries-component-dsl] 06/09: Add configuration holder

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csierra pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-component-dsl.git

commit f6dc866ecc292a901a8a2c0af4e9b43d8d27c9f3
Author: Carlos Sierra Andrés <ca...@liferay.com>
AuthorDate: Tue Mar 2 15:59:47 2021 +0100

    Add configuration holder
---
 .../java/org/apache/aries/component/dsl/OSGi.java  |  5 +-
 .../dsl/configuration/ConfigurationHolder.java     | 37 ++++++++++
 .../component/dsl/configuration/package-info.java  | 20 ++++++
 .../dsl/internal/ConfigurationHolderImpl.java      | 78 ++++++++++++++++++++++
 .../dsl/internal/ConfigurationOSGiImpl.java        | 12 +++-
 .../dsl/internal/ConfigurationsOSGiImpl.java       | 21 ++++--
 6 files changed, 162 insertions(+), 11 deletions(-)

diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
index 9da249a..4476539 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
@@ -18,6 +18,7 @@
 
 package org.apache.aries.component.dsl;
 
+import org.apache.aries.component.dsl.configuration.ConfigurationHolder;
 import org.apache.aries.component.dsl.function.Function10;
 import org.apache.aries.component.dsl.function.Function14;
 import org.apache.aries.component.dsl.function.Function16;
@@ -297,7 +298,7 @@ public interface OSGi<T> extends OSGiRunnable<T> {
 		).map(
 			UpdateTuple::getT
 		).map(
-			Configuration::getProperties
+			ConfigurationHolder::getUpdatedProperties
 		);
 	}
 
@@ -308,7 +309,7 @@ public interface OSGi<T> extends OSGiRunnable<T> {
 		).map(
 			UpdateTuple::getT
 		).map(
-			Configuration::getProperties
+			ConfigurationHolder::getUpdatedProperties
 		);
 	}
 
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/ConfigurationHolder.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/ConfigurationHolder.java
new file mode 100644
index 0000000..f114fb1
--- /dev/null
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/ConfigurationHolder.java
@@ -0,0 +1,37 @@
+/*
+ * 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 org.apache.aries.component.dsl.configuration;
+
+import java.util.Dictionary;
+
+public interface ConfigurationHolder {
+
+    String getPid();
+
+    Dictionary<String, ?> getProperties();
+
+    String getFactoryPid();
+
+    long getChangeCount();
+
+    void refresh();
+
+    long getUpdatedChangeCount();
+
+    Dictionary<String, ?> getUpdatedProperties();
+}
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/package-info.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/package-info.java
new file mode 100644
index 0000000..d7fd4d3
--- /dev/null
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/configuration/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+@org.osgi.annotation.bundle.Export
+@org.osgi.annotation.versioning.Version("1.0.0")
+package org.apache.aries.component.dsl.configuration;
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationHolderImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationHolderImpl.java
new file mode 100644
index 0000000..891c27d
--- /dev/null
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationHolderImpl.java
@@ -0,0 +1,78 @@
+/*
+ * 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 org.apache.aries.component.dsl.internal;
+
+import org.apache.aries.component.dsl.configuration.ConfigurationHolder;
+import org.osgi.service.cm.Configuration;
+
+import java.util.Dictionary;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class ConfigurationHolderImpl implements ConfigurationHolder {
+
+    private Configuration configuration;
+    private AtomicReference<Dictionary<String, ?>> properties;
+    private AtomicLong changeCount = new AtomicLong(-1);
+
+    public ConfigurationHolderImpl(Configuration configuration) {
+        this.configuration = configuration;
+    }
+
+    @Override
+    public String getPid() {
+        return configuration.getPid();
+    }
+
+    @Override
+    public Dictionary<String, ?> getProperties() {
+        properties.compareAndSet(null, configuration.getProperties());
+
+        return properties.get();
+    }
+
+    @Override
+    public String getFactoryPid() {
+        return configuration.getFactoryPid();
+    }
+
+    @Override
+    public long getChangeCount() {
+        changeCount.compareAndSet(-1, configuration.getChangeCount());
+
+        return changeCount.get();
+    }
+
+    @Override
+    public void refresh() {
+        changeCount.set(-1);
+
+        properties.set(null);
+    }
+
+    @Override
+    public long getUpdatedChangeCount() {
+        return configuration.getChangeCount();
+    }
+
+    @Override
+    public Dictionary<String, ?> getUpdatedProperties() {
+        return configuration.getProperties();
+    }
+
+}
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
index 6ac0a90..7080fb7 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
@@ -18,6 +18,7 @@
 package org.apache.aries.component.dsl.internal;
 
 import org.apache.aries.component.dsl.OSGiResult;
+import org.apache.aries.component.dsl.configuration.ConfigurationHolder;
 import org.apache.aries.component.dsl.update.UpdateSelector;
 import org.apache.aries.component.dsl.update.UpdateTuple;
 import org.osgi.framework.BundleContext;
@@ -38,7 +39,7 @@ import java.util.concurrent.atomic.AtomicReference;
 /**
  * @author Carlos Sierra Andrés
  */
-public class ConfigurationOSGiImpl extends OSGiImpl<UpdateTuple<Configuration>> {
+public class ConfigurationOSGiImpl extends OSGiImpl<UpdateTuple<ConfigurationHolder>> {
 
 	public ConfigurationOSGiImpl(String pid) {
 		super((executionContext, op) -> {
@@ -109,7 +110,9 @@ public class ConfigurationOSGiImpl extends OSGiImpl<UpdateTuple<Configuration>>
 
 								terminatorAtomicReference.set(
 									op.apply(
-										new UpdateTuple<>(updateSelector, configuration)));
+										new UpdateTuple<>(
+											updateSelector,
+											new ConfigurationHolderImpl(configuration))));
 
 							});
 
@@ -138,7 +141,10 @@ public class ConfigurationOSGiImpl extends OSGiImpl<UpdateTuple<Configuration>>
                     initialCounter.set(configuration.getChangeCount());
 
                     terminatorAtomicReference.set(
-                        op.apply(new UpdateTuple<>(updateSelector, configuration)));
+                        op.apply(
+                        	new UpdateTuple<>(
+                        		updateSelector,
+								new ConfigurationHolderImpl(configuration))));
                 }
 			}
 
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
index 7413c0e..e91d373 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
@@ -18,6 +18,7 @@
 package org.apache.aries.component.dsl.internal;
 
 import org.apache.aries.component.dsl.OSGiResult;
+import org.apache.aries.component.dsl.configuration.ConfigurationHolder;
 import org.apache.aries.component.dsl.update.UpdateSelector;
 import org.apache.aries.component.dsl.update.UpdateTuple;
 import org.osgi.framework.BundleContext;
@@ -38,7 +39,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
 /**
  * @author Carlos Sierra Andrés
  */
-public class ConfigurationsOSGiImpl extends OSGiImpl<UpdateTuple<Configuration>> {
+public class ConfigurationsOSGiImpl extends OSGiImpl<UpdateTuple<ConfigurationHolder>> {
 
 	public ConfigurationsOSGiImpl(String factoryPid) {
 		super((executionContext, op) -> {
@@ -107,7 +108,11 @@ public class ConfigurationsOSGiImpl extends OSGiImpl<UpdateTuple<Configuration>>
 							UpdateSupport.runUpdate(() -> {
 								signalLeave(pid, terminators);
 
-								terminators.put(pid, op.apply(new UpdateTuple<>(updateSelector, configuration)));
+								terminators.put(
+									pid, op.apply(
+										new UpdateTuple<>(
+											updateSelector,
+											new ConfigurationHolderImpl(configuration))));
 							});
 
 							if (closed.get()) {
@@ -129,12 +134,16 @@ public class ConfigurationsOSGiImpl extends OSGiImpl<UpdateTuple<Configuration>>
 				Configuration[] configurations = getConfigurations(
 					bundleContext, factoryPid, serviceReference);
 
-				for (Configuration c : configurations) {
-					configurationCounters.put(c.getPid(), c.getChangeCount());
+				for (Configuration configuration : configurations) {
+					configurationCounters.put(
+						configuration.getPid(), configuration.getChangeCount());
 
 					terminators.put(
-						c.getPid(),
-						op.publish(new UpdateTuple<>(updateSelector, c)));
+						configuration.getPid(),
+						op.publish(
+							new UpdateTuple<>(
+								updateSelector,
+								new ConfigurationHolderImpl(configuration))));
 				}
 			}
 


[aries-component-dsl] 05/09: Add update support for configurations

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csierra pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-component-dsl.git

commit f5f3aa4d0df23da5070807a598c6d2c7b2762778
Author: Carlos Sierra Andrés <ca...@liferay.com>
AuthorDate: Tue Mar 2 15:08:44 2021 +0100

    Add update support for configurations
---
 .../java/org/apache/aries/component/dsl/OSGi.java  | 19 ++++++++-
 .../dsl/internal/ConfigurationOSGiImpl.java        | 33 ++++++++++-----
 .../dsl/internal/ConfigurationsOSGiImpl.java       | 48 +++++++++++-----------
 3 files changed, 64 insertions(+), 36 deletions(-)

diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
index 4ba192b..9da249a 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/OSGi.java
@@ -53,6 +53,7 @@ import org.osgi.framework.ServiceFactory;
 import org.osgi.framework.ServiceObjects;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
 
 import java.util.*;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -290,11 +291,25 @@ public interface OSGi<T> extends OSGiRunnable<T> {
 	}
 	
 	static OSGi<Dictionary<String, ?>> configuration(String pid) {
-		return new ConfigurationOSGiImpl(pid);
+		return refreshWhen(
+			new ConfigurationOSGiImpl(pid),
+			(__, ___) -> true
+		).map(
+			UpdateTuple::getT
+		).map(
+			Configuration::getProperties
+		);
 	}
 
 	static OSGi<Dictionary<String, ?>> configurations(String factoryPid) {
-		return new ConfigurationsOSGiImpl(factoryPid);
+		return refreshWhen(
+			new ConfigurationsOSGiImpl(factoryPid),
+			(__, ___) -> true
+		).map(
+			UpdateTuple::getT
+		).map(
+			Configuration::getProperties
+		);
 	}
 
 	static OSGi<Void> effect(Effect<Void> effect) {
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
index 36c8514..6ac0a90 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java
@@ -18,6 +18,8 @@
 package org.apache.aries.component.dsl.internal;
 
 import org.apache.aries.component.dsl.OSGiResult;
+import org.apache.aries.component.dsl.update.UpdateSelector;
+import org.apache.aries.component.dsl.update.UpdateTuple;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
@@ -26,17 +28,17 @@ 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.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * @author Carlos Sierra Andrés
  */
-public class ConfigurationOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
+public class ConfigurationOSGiImpl extends OSGiImpl<UpdateTuple<Configuration>> {
 
 	public ConfigurationOSGiImpl(String pid) {
 		super((executionContext, op) -> {
@@ -49,6 +51,10 @@ public class ConfigurationOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 
 			AtomicBoolean closed = new AtomicBoolean();
 
+			UpdateSelector updateSelector = new UpdateSelector() {};
+
+			AtomicLong initialCounter = new AtomicLong();
+
 			CountDownLatch countDownLatch = new CountDownLatch(1);
 
 			BundleContext bundleContext = executionContext.getBundleContext();
@@ -83,24 +89,27 @@ public class ConfigurationOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 							 configuration = getConfiguration(
 								 bundleContext, configurationEvent);
 
-							if (configuration == null) {
+							if (configuration == null ||
+								configuration.getChangeCount() == initialCounter.get()) {
+
 								return;
 							}
 
-							Configuration old = atomicReference.get();
-
-							if (old == null ||
-								configuration.getChangeCount() !=
-									old.getChangeCount()) {
-
+							if (atomicReference.get() == null) {
 								atomicReference.set(configuration);
 							}
+							else {
+								if (!terminatorAtomicReference.get().update(updateSelector)) {
+									return;
+								}
+							}
 
 							UpdateSupport.runUpdate(() -> {
 								signalLeave(terminatorAtomicReference);
 
 								terminatorAtomicReference.set(
-									op.apply(configuration.getProperties()));
+									op.apply(
+										new UpdateTuple<>(updateSelector, configuration)));
 
 							});
 
@@ -126,8 +135,10 @@ public class ConfigurationOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 				if (configuration != null) {
                     atomicReference.set(configuration);
 
+                    initialCounter.set(configuration.getChangeCount());
+
                     terminatorAtomicReference.set(
-                        op.apply(configuration.getProperties()));
+                        op.apply(new UpdateTuple<>(updateSelector, configuration)));
                 }
 			}
 
diff --git a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
index 850533d..7413c0e 100644
--- a/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
+++ b/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java
@@ -18,6 +18,8 @@
 package org.apache.aries.component.dsl.internal;
 
 import org.apache.aries.component.dsl.OSGiResult;
+import org.apache.aries.component.dsl.update.UpdateSelector;
+import org.apache.aries.component.dsl.update.UpdateTuple;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
@@ -36,11 +38,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
 /**
  * @author Carlos Sierra Andrés
  */
-public class ConfigurationsOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
+public class ConfigurationsOSGiImpl extends OSGiImpl<UpdateTuple<Configuration>> {
 
 	public ConfigurationsOSGiImpl(String factoryPid) {
 		super((executionContext, op) -> {
-			ConcurrentHashMap<String, Configuration> configurations =
+			ConcurrentHashMap<String, Long> configurationCounters =
 				new ConcurrentHashMap<>();
 
 			ConcurrentHashMap<String, OSGiResult> terminators =
@@ -48,6 +50,8 @@ public class ConfigurationsOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 
 			AtomicBoolean closed = new AtomicBoolean();
 
+			UpdateSelector updateSelector = new UpdateSelector() {};
+
 			CountDownLatch countDownLatch = new CountDownLatch(1);
 
 			final BundleContext bundleContext = executionContext.getBundleContext();
@@ -59,9 +63,7 @@ public class ConfigurationsOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 						String incomingFactoryPid =
 							configurationEvent.getFactoryPid();
 
-						if (incomingFactoryPid == null ||
-							!factoryPid.equals(incomingFactoryPid)) {
-
+						if (!factoryPid.equals(incomingFactoryPid)) {
 							return;
 						}
 
@@ -79,7 +81,7 @@ public class ConfigurationsOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 						if (configurationEvent.getType() ==
 							ConfigurationEvent.CM_DELETED) {
 
-							configurations.remove(pid);
+							configurationCounters.remove(pid);
 
 							signalLeave(pid, terminators);
 						}
@@ -87,27 +89,25 @@ public class ConfigurationsOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 							configuration = getConfiguration(
 								bundleContext, configurationEvent);
 
-							Dictionary<String, Object> properties =
-								configuration.getProperties();
+							Long oldChangeCount = configurationCounters.putIfAbsent(
+								pid, configuration.getChangeCount());
 
-							configurations.compute(
-								pid,
-								(__, old) -> {
-									if (old == null ||
-										configuration.getChangeCount() !=
-											old.getChangeCount()) {
+							if (oldChangeCount != null) {
+								if (oldChangeCount == configuration.getChangeCount()) {
+									return;
+								}
 
-										return configuration;
-									}
+								OSGiResult osgiResult = terminators.get(pid);
 
-									return old;
+								if (osgiResult != null && !osgiResult.update(updateSelector)) {
+									return;
 								}
-							);
+							}
 
 							UpdateSupport.runUpdate(() -> {
 								signalLeave(pid, terminators);
 
-								terminators.put(pid, op.apply(properties));
+								terminators.put(pid, op.apply(new UpdateTuple<>(updateSelector, configuration)));
 							});
 
 							if (closed.get()) {
@@ -126,13 +126,15 @@ public class ConfigurationsOSGiImpl extends OSGiImpl<Dictionary<String, ?>> {
 				bundleContext.getServiceReference(ConfigurationAdmin.class);
 
 			if (serviceReference != null) {
-				Configuration[] configuration = getConfigurations(
+				Configuration[] configurations = getConfigurations(
 					bundleContext, factoryPid, serviceReference);
 
-				for (Configuration c : configuration) {
-					configurations.put(c.getPid(), c);
+				for (Configuration c : configurations) {
+					configurationCounters.put(c.getPid(), c.getChangeCount());
 
-					terminators.put(c.getPid(), op.apply(c.getProperties()));
+					terminators.put(
+						c.getPid(),
+						op.publish(new UpdateTuple<>(updateSelector, c)));
 				}
 			}