diff --git a/bundles/org.eclipse.equinox.cm/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.cm/META-INF/MANIFEST.MF index 84a50cbb60e..6d95f2232bc 100644 --- a/bundles/org.eclipse.equinox.cm/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.cm/META-INF/MANIFEST.MF @@ -8,8 +8,9 @@ Bundle-Version: 1.6.0.qualifier Bundle-Activator: org.eclipse.equinox.internal.cm.Activator Import-Package: org.osgi.framework;version="1.7.0", org.osgi.service.cm;version="[1.6,1.7)", + org.osgi.service.coordinator;version="[1.0.0,2.0.0]", + org.osgi.service.event;version="1.0";resolution:=optional, org.osgi.service.log;version="1.3.0", - org.osgi.service.event;version="1.0"; resolution:=optional, org.osgi.util.tracker;version="1.3.1" Bundle-RequiredExecutionEnvironment: JavaSE-17 Provide-Capability: diff --git a/bundles/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationAdminFactory.java b/bundles/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationAdminFactory.java index 14e1dfce0e4..2731e567cb7 100644 --- a/bundles/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationAdminFactory.java +++ b/bundles/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationAdminFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2019 Cognos Incorporated, IBM Corporation and others. + * Copyright (c) 2005, 2024 Cognos Incorporated, IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -11,14 +11,19 @@ * Contributors: * Cognos Incorporated - initial API and implementation * IBM Corporation - bug fixes and enhancements + * Christoph Läubrich - add support for Coordinator *******************************************************************************/ package org.eclipse.equinox.internal.cm; import java.security.Permission; -import java.util.Dictionary; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Predicate; import org.osgi.framework.*; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.cm.ConfigurationPermission; +import org.osgi.service.coordinator.*; +import org.osgi.util.tracker.ServiceTracker; /** * ConfigurationAdminFactory provides a Configuration Admin ServiceFactory but @@ -37,6 +42,9 @@ public class ConfigurationAdminFactory implements ServiceFactory coordinationServiceTracker; + + private final Map coordinationParticipants = new ConcurrentHashMap<>(); public ConfigurationAdminFactory(BundleContext context, LogTracker log) { this.log = log; @@ -45,9 +53,11 @@ public ConfigurationAdminFactory(BundleContext context, LogTracker log) { pluginManager = new PluginManager(context); managedServiceTracker = new ManagedServiceTracker(this, configurationStore, context); managedServiceFactoryTracker = new ManagedServiceFactoryTracker(this, configurationStore, context); + coordinationServiceTracker = new ServiceTracker<>(context, Coordinator.class, null); } void start() { + coordinationServiceTracker.open(); eventDispatcher.start(); pluginManager.start(); managedServiceTracker.open(); @@ -59,6 +69,7 @@ void stop() { managedServiceFactoryTracker.close(); eventDispatcher.stop(); pluginManager.stop(); + coordinationServiceTracker.close(); } @Override @@ -137,17 +148,24 @@ void dispatchEvent(int type, String factoryPid, String pid) { } void notifyConfigurationUpdated(ConfigurationImpl config, boolean isFactory) { - if (isFactory) + if (isFactory) { managedServiceFactoryTracker.notifyUpdated(config); - else + } else { managedServiceTracker.notifyUpdated(config); + } + } + + ConfigurationAdminParticipant coordinationParticipant(Coordination coordination) { + return coordinationParticipants.computeIfAbsent(coordination.getId(), + c -> new ConfigurationAdminParticipant(coordination)); } void notifyConfigurationDeleted(ConfigurationImpl config, boolean isFactory) { - if (isFactory) + if (isFactory) { managedServiceFactoryTracker.notifyDeleted(config); - else + } else { managedServiceTracker.notifyDeleted(config); + } } void notifyLocationChanged(ConfigurationImpl config, String oldLocation, boolean isFactory) { @@ -161,4 +179,50 @@ void notifyLocationChanged(ConfigurationImpl config, String oldLocation, boolean Dictionary modifyConfiguration(ServiceReference reference, ConfigurationImpl config) { return pluginManager.modifyConfiguration(reference, config); } + + Optional coordinate() { + return Optional.ofNullable(coordinationServiceTracker.getService()).map(Coordinator::peek) + .filter(Predicate.not(Coordination::isTerminated)); + } + + private final class ConfigurationAdminParticipant implements Participant { + + private Map tasks = new HashMap<>(); + + public ConfigurationAdminParticipant(Coordination coordination) { + coordination.addParticipant(this); + } + + @Override + public void ended(Coordination coordination) throws Exception { + finish(coordination); + } + + @Override + public void failed(Coordination coordination) throws Exception { + finish(coordination); + } + + private void finish(Coordination coordination) { + tasks.values().forEach(Runnable::run); + tasks.clear(); + } + + public void cancelTask(Object key) { + tasks.remove(key); + } + + public void addTask(Object key, Runnable runnable) { + tasks.put(key, runnable); + } + } + + void executeCoordinated(Object key, Runnable runnable) { + coordinate().ifPresentOrElse(coordination -> coordinationParticipant(coordination).addTask(key, runnable), + () -> runnable.run()); + } + + void cancelExecuteCoordinated(Object key) { + coordinate().ifPresent(coordination -> coordinationParticipant(coordination).cancelTask(key)); + } } diff --git a/bundles/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ManagedServiceFactoryTracker.java b/bundles/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ManagedServiceFactoryTracker.java index 11559251ad1..625f75e50c4 100644 --- a/bundles/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ManagedServiceFactoryTracker.java +++ b/bundles/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ManagedServiceFactoryTracker.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2018 Cognos Incorporated, IBM Corporation and others. + * Copyright (c) 2005, 2024 Cognos Incorporated, IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -11,6 +11,7 @@ * Contributors: * Cognos Incorporated - initial API and implementation * IBM Corporation - bug fixes and enhancements + * Christoph Läubrich - add support for Coordinator *******************************************************************************/ package org.eclipse.equinox.internal.cm; @@ -289,9 +290,9 @@ private void asynchUpdated(final ManagedServiceFactory service, final String pid if (properties == null) { return; } - queue.put(new Runnable() { - @Override - public void run() { + configurationAdminFactory.cancelExecuteCoordinated(service); + configurationAdminFactory.executeCoordinated(service, () -> { + queue.put(() -> { try { service.updated(pid, properties); } catch (ConfigurationException e) { @@ -301,7 +302,7 @@ public void run() { } catch (Throwable t) { configurationAdminFactory.error(t.getMessage(), t); } - } + }); }); } } diff --git a/bundles/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ManagedServiceTracker.java b/bundles/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ManagedServiceTracker.java index 5201f0034d9..0b9eb679682 100644 --- a/bundles/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ManagedServiceTracker.java +++ b/bundles/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ManagedServiceTracker.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2018 Cognos Incorporated, IBM Corporation and others. + * Copyright (c) 2005, 2024 Cognos Incorporated, IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -11,6 +11,7 @@ * Contributors: * Cognos Incorporated - initial API and implementation * IBM Corporation - bug fixes and enhancements + * Christoph Läubrich - add support for Coordinator *******************************************************************************/ package org.eclipse.equinox.internal.cm; @@ -283,19 +284,17 @@ private List> getManagedServiceReferences(Strin } private void asynchUpdated(final ManagedService service, final Dictionary properties) { - queue.put(new Runnable() { - @Override - public void run() { - try { - service.updated(properties); - } catch (ConfigurationException e) { - // we might consider doing more for ConfigurationExceptions - Throwable cause = e.getCause(); - configurationAdminFactory.error(e.getMessage(), cause != null ? cause : e); - } catch (Throwable t) { - configurationAdminFactory.error(t.getMessage(), t); - } + configurationAdminFactory.cancelExecuteCoordinated(service); + configurationAdminFactory.executeCoordinated(service, () -> queue.put(() -> { + try { + service.updated(properties); + } catch (ConfigurationException e) { + // we might consider doing more for ConfigurationExceptions + Throwable cause = e.getCause(); + configurationAdminFactory.error(e.getMessage(), cause != null ? cause : e); + } catch (Throwable t) { + configurationAdminFactory.error(t.getMessage(), t); } - }); + })); } }