You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by am...@apache.org on 2026/05/12 20:51:28 UTC
(aries-rsa) 02/02: ARIES-2214 Fix provider config type handling
This is an automated email from the ASF dual-hosted git repository.
amichair pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-rsa.git
commit d7b7d6b42c05c8f1dc9cd8106a45d5a12b0cee6c
Author: Amichai Rothman <am...@apache.org>
AuthorDate: Thu Mar 26 17:24:58 2026 +0200
ARIES-2214 Fix provider config type handling
---
.../apache/aries/rsa/provider/tcp/TcpEndpoint.java | 1 -
.../rsa/core/DistributionProviderTracker.java | 4 ++
.../aries/rsa/core/RemoteServiceAdminCore.java | 75 +++++++++-------------
.../aries/rsa/core/RemoteServiceAdminCoreTest.java | 4 +-
.../apache/aries/rsa/spi/DistributionProvider.java | 19 ++++--
5 files changed, 50 insertions(+), 53 deletions(-)
diff --git a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java
index e2edf05a..99ad5a17 100644
--- a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java
+++ b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java
@@ -61,7 +61,6 @@ public class TcpEndpoint implements Endpoint {
Config config = new Config(effectiveProperties);
String endpointId = String.format("tcp://%s:%s/%s", hostname, port, config.getId());
effectiveProperties.put(RemoteConstants.ENDPOINT_ID, endpointId);
- effectiveProperties.put(RemoteConstants.SERVICE_EXPORTED_CONFIGS, "");
effectiveProperties.put(RemoteConstants.SERVICE_INTENTS, Arrays.asList("osgi.basic", "osgi.async"));
// tck tests require at least one config-type specific property... so we provide this one
// (it also tests that we throw IllegalArgumentException when any config-type property value is garbage)
diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/DistributionProviderTracker.java b/rsa/src/main/java/org/apache/aries/rsa/core/DistributionProviderTracker.java
index 72714774..0ff478d6 100644
--- a/rsa/src/main/java/org/apache/aries/rsa/core/DistributionProviderTracker.java
+++ b/rsa/src/main/java/org/apache/aries/rsa/core/DistributionProviderTracker.java
@@ -63,6 +63,10 @@ public class DistributionProviderTracker extends ServiceTracker<DistributionProv
// Can happen if the service is created by a service factory and an exception occurs
return null;
}
+ if (provider.getSupportedTypes() == null || provider.getSupportedTypes().length == 0) {
+ LOG.warn("Invalid DistributionProvider {}: no supported config types", provider);
+ return null;
+ }
LOG.debug("Initializing RemoteServiceAdmin for DistributionProvider {} ({})",
provider, Arrays.asList(provider.getSupportedTypes()));
BundleContext apiContext = getAPIContext();
diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceAdminCore.java b/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceAdminCore.java
index 77b7188d..be719ae2 100644
--- a/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceAdminCore.java
+++ b/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceAdminCore.java
@@ -105,27 +105,35 @@ public class RemoteServiceAdminCore implements RemoteServiceAdmin {
@Override
@SuppressWarnings("unchecked")
- public List<ExportRegistration> exportService(ServiceReference serviceReference, Map additionalProperties)
+ public List<ExportRegistration> exportService(ServiceReference sref, Map additionalProperties)
throws IllegalArgumentException, UnsupportedOperationException {
- Map<String, Object> serviceProperties = getProperties(serviceReference);
+ Map<String, Object> serviceProperties = getProperties(sref);
if (additionalProperties != null) {
overlayProperties(serviceProperties, additionalProperties);
}
List<String> interfaceNames = getInterfaceNames(serviceProperties);
+ List<String> exportedConfigs = StringPlus.normalize(
+ serviceProperties.get(RemoteConstants.SERVICE_EXPORTED_CONFIGS));
+ List<String> configTypes = matchConfigTypes(exportedConfigs, true); // empty means pick one
- if (isImportedService(serviceReference) || !isExportConfigSupported(serviceProperties)) {
+ if (isImportedService(sref) || configTypes.isEmpty()) {
return Collections.emptyList();
}
Map<String, Object> key = makeKey(serviceProperties);
List<ExportRegistration> regs = getExistingOrLock(key, interfaceNames);
if (regs == null) {
- regs = new ArrayList<>();
try {
- ExportRegistration reg = exportService(interfaceNames, serviceReference, serviceProperties);
- if (reg != null) {
- regs.add(reg);
+ regs = new ArrayList<>();
+ for (String configType : configTypes) {
+ ExportRegistration reg = exportService(Arrays.asList(configType),
+ interfaceNames, sref, serviceProperties);
+ if (reg != null) {
+ regs.add(reg);
+ }
+ }
+ if (!regs.isEmpty()) {
store(key, regs);
}
} finally {
@@ -135,27 +143,6 @@ public class RemoteServiceAdminCore implements RemoteServiceAdmin {
return regs;
}
- private boolean isExportConfigSupported(Map<String, Object> serviceProperties) {
- if (provider == null) {
- return false;
- }
- List<String> exportedConfigs = StringPlus.normalize(serviceProperties.get(RemoteConstants.SERVICE_EXPORTED_CONFIGS));
- if (exportedConfigs == null || exportedConfigs.isEmpty()) {
- return true;
- }
- String[] supportedTypes = provider.getSupportedTypes();
- if (supportedTypes == null || supportedTypes.length == 0) {
- //if not set, all services should be accepted
- return true;
- }
- for (String supportedType : supportedTypes) {
- if (exportedConfigs.contains(supportedType)) {
- return true;
- }
- }
- return false;
- }
-
private void store(Map<String, Object> key, List<ExportRegistration> regs) {
// enlist initial export registrations in global list of exportRegistrations
synchronized (exportedServices) {
@@ -208,6 +195,7 @@ public class RemoteServiceAdminCore implements RemoteServiceAdmin {
}
private ExportRegistration exportService(
+ final List<String> configTypes,
final List<String> interfaceNames,
final ServiceReference<?> serviceReference,
final Map<String, Object> serviceProperties) {
@@ -221,7 +209,7 @@ public class RemoteServiceAdminCore implements RemoteServiceAdmin {
throw new IllegalStateException("service object is null (service was unregistered?)");
}
final Class<?>[] interfaces = getInterfaces(serviceO, interfaceNames);
- final Map<String, Object> eprops = createEndpointProps(serviceProperties, interfaces);
+ final Map<String, Object> eprops = createEndpointProps(serviceProperties, configTypes, interfaces);
Endpoint endpoint = AccessController.doPrivileged(
(PrivilegedAction<Endpoint>) () -> provider.exportService(serviceO, serviceContext, eprops, interfaces));
@@ -404,8 +392,9 @@ public class RemoteServiceAdminCore implements RemoteServiceAdmin {
return ir;
}
- if (determineConfigTypesForImport(endpoint).isEmpty()) {
- LOG.info("No matching handler can be found for remote endpoint {}.", endpoint.getId());
+ if (matchConfigTypes(endpoint.getConfigurationTypes(), false).isEmpty()) {
+ LOG.info("Ignoring endpoint {} as it has no compatible configuration types: {}",
+ endpoint.getId(), endpoint.getConfigurationTypes());
return null;
}
@@ -431,21 +420,14 @@ public class RemoteServiceAdminCore implements RemoteServiceAdmin {
}
}
- private List<String> determineConfigTypesForImport(EndpointDescription endpoint) {
- List<String> remoteConfigurationTypes = endpoint.getConfigurationTypes();
-
- List<String> usableConfigurationTypes = new ArrayList<>();
- for (String ct : provider.getSupportedTypes()) {
- if (remoteConfigurationTypes.contains(ct)) {
- usableConfigurationTypes.add(ct);
- }
- }
-
- if (usableConfigurationTypes.isEmpty()) {
- LOG.info("Ignoring endpoint {} as it has no compatible configuration types: {}.",
- endpoint.getId(), remoteConfigurationTypes);
+ private List<String> matchConfigTypes(List<String> types, boolean first) {
+ List<String> matched = new ArrayList<>();
+ Collections.addAll(matched, provider.getSupportedTypes());
+ if (types == null || types.isEmpty()) {
+ return matched.subList(0, first ? 1 : 0);
}
- return usableConfigurationTypes;
+ matched.retainAll(types);
+ return matched;
}
protected ImportRegistrationImpl exposeServiceFactory(String[] interfaceNames,
@@ -567,10 +549,11 @@ public class RemoteServiceAdminCore implements RemoteServiceAdmin {
}
protected Map<String, Object> createEndpointProps(Map<String, Object> effectiveProps,
- Class<?>[] ifaces) {
+ List<String> configTypes, Class<?>[] ifaces) {
Map<String, Object> props = new HashMap<>();
copyEndpointProperties(effectiveProps, props);
props.remove(org.osgi.framework.Constants.SERVICE_ID);
+ props.put(RemoteConstants.SERVICE_EXPORTED_CONFIGS, configTypes);
EndpointHelper.addObjectClass(props, ifaces);
props.put(RemoteConstants.ENDPOINT_SERVICE_ID, effectiveProps.get(org.osgi.framework.Constants.SERVICE_ID));
String frameworkUUID = bctx.getProperty(org.osgi.framework.Constants.FRAMEWORK_UUID);
diff --git a/rsa/src/test/java/org/apache/aries/rsa/core/RemoteServiceAdminCoreTest.java b/rsa/src/test/java/org/apache/aries/rsa/core/RemoteServiceAdminCoreTest.java
index bbccfb27..4b97c3f9 100644
--- a/rsa/src/test/java/org/apache/aries/rsa/core/RemoteServiceAdminCoreTest.java
+++ b/rsa/src/test/java/org/apache/aries/rsa/core/RemoteServiceAdminCoreTest.java
@@ -329,13 +329,15 @@ public class RemoteServiceAdminCoreTest {
c.replay();
Map<String, Object> sd = new HashMap<>();
sd.put(org.osgi.framework.Constants.SERVICE_ID, 42);
- Map<String, Object> props = rsaCore.createEndpointProps(sd, new Class[]{String.class});
+ Map<String, Object> props = rsaCore.createEndpointProps(
+ sd, Arrays.asList("myconfig"), new Class[]{String.class});
Assert.assertFalse(props.containsKey(org.osgi.framework.Constants.SERVICE_ID));
assertEquals(42, props.get(RemoteConstants.ENDPOINT_SERVICE_ID));
assertEquals("some_uuid1", props.get(RemoteConstants.ENDPOINT_FRAMEWORK_UUID));
assertEquals(Arrays.asList("java.lang.String"),
Arrays.asList((Object[]) props.get(org.osgi.framework.Constants.OBJECTCLASS)));
+ assertEquals(Arrays.asList("myconfig"), props.get(RemoteConstants.SERVICE_EXPORTED_CONFIGS));
assertEquals("1.2.3", props.get("endpoint.package.version.java.lang"));
c.verify();
}
diff --git a/spi/src/main/java/org/apache/aries/rsa/spi/DistributionProvider.java b/spi/src/main/java/org/apache/aries/rsa/spi/DistributionProvider.java
index 772add85..590f945a 100644
--- a/spi/src/main/java/org/apache/aries/rsa/spi/DistributionProvider.java
+++ b/spi/src/main/java/org/apache/aries/rsa/spi/DistributionProvider.java
@@ -26,6 +26,11 @@ import org.osgi.service.remoteserviceadmin.EndpointDescription;
@SuppressWarnings("rawtypes")
public interface DistributionProvider {
+ /**
+ * Returns config types supported by this provider.
+ *
+ * @return the config types supported by this provider
+ */
String[] getSupportedTypes();
/**
@@ -34,11 +39,15 @@ public interface DistributionProvider {
* The Distribution provider will be called if it supports the
* specified config type, or if no config type was specified.
* <p>
- * All config-type specific configuration properties in the returned endpoint
- * must have names of the form {@code <config>.*}, i.e. the property name
- * must be prefixed with the config type string itself.
- * If any of the config-type specific properties are invalid,
- * an IllegalArgumentException must be thrown.
+ * All config-type specific configuration properties in the returned
+ * endpoint must have names of the form {@code <config>.*}, i.e. the
+ * property name must be prefixed with the config type string itself.
+ * If any of the config-type specific properties are invalid, an
+ * IllegalArgumentException must be thrown.
+ * <p>
+ * The provider must set the {@code "service.imported.configs"}
+ * endpoint property to the config type that was actually exported
+ * (and its alias names, if any).
*
* @param serviceObject service instance to be exported
* @param serviceContext bundle context of the bundle exporting the service