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

kwin pushed a commit to branch feature/SLING-11864-expose-merged-configs
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-configuration.git

commit b235d6577583f9e159b21e172622a43719c913e1
Author: Konrad Windszus <[email protected]>
AuthorDate: Tue May 9 19:22:25 2023 +0200

    SLING-11864 Add new exported interface for filtering default properties
---
 pom.xml                                            | 11 +++
 .../configuration/ConfigurationMerger.java         | 50 ++++++++++++
 .../configuration/impl/ConfigTaskCreator.java      | 58 ++------------
 .../impl/ConfigurationMergerImpl.java              | 91 ++++++++++++++++++++++
 .../configuration/impl/ServicesListener.java       | 18 ++---
 .../impl/WebconsoleConfigurationHandler.java       | 10 +--
 .../factories/configuration/package-info.java      |  2 +-
 7 files changed, 172 insertions(+), 68 deletions(-)

diff --git a/pom.xml b/pom.xml
index 0ebfccd..7cc44df 100644
--- a/pom.xml
+++ b/pom.xml
@@ -118,6 +118,17 @@
             <version>1.0.0</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.component.annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <!-- JetBrains annotations for null-analysis (SLING-7798), 
https://github.com/JetBrains/java-annotations -->
+        <dependency>
+            <groupId>org.jetbrains</groupId>
+            <artifactId>annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
diff --git 
a/src/main/java/org/apache/sling/installer/factories/configuration/ConfigurationMerger.java
 
b/src/main/java/org/apache/sling/installer/factories/configuration/ConfigurationMerger.java
new file mode 100644
index 0000000..28b1b6e
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/installer/factories/configuration/ConfigurationMerger.java
@@ -0,0 +1,50 @@
+/*
+ * 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.sling.installer.factories.configuration;
+
+import java.util.Dictionary;
+
+import org.jetbrains.annotations.NotNull;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Exposes helper methods to identify those configuration properties which are 
set through installer resources having a configured merge scheme.
+ * Those configuration properties are referred to as default properties. 
+ * Note though that both OSGi metatype and OSGi declarative services define 
default properties as well which are not meant here.
+ * @see <a 
href="https://sling.apache.org/documentation/bundles/configuration-installer-factory.html#merging-of-configurations";>Merging
 of Configurations</a>
+ */
+@ProviderType
+public interface ConfigurationMerger {
+
+    /**
+     * Modifies the given dictionary so that all properties which have values 
equal to one 
+     * of the same named property values provided by the inherited 
configurations are removed.
+     * @param pid the PID of the configuration
+     * @param dict the configuration properties to modify
+     */
+    void removeDefaultProperties(@NotNull final String pid, @NotNull final 
Dictionary<String, Object> dict);
+
+    /**
+     * Returns all properties for the given PID which are set through any of 
the resource with the configured merge schemes.
+     * @param pid the PID of the configuration
+     * @return the properties set through specific installer resources in a 
mutable dictionary
+     */
+    Dictionary<String, Object> getDefaultProperties(@NotNull final String pid);
+
+}
diff --git 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigTaskCreator.java
 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigTaskCreator.java
index e4bd388..147101b 100644
--- 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigTaskCreator.java
+++ 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigTaskCreator.java
@@ -18,10 +18,8 @@
  */
 package org.apache.sling.installer.factories.configuration.impl;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Dictionary;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.List;
@@ -29,9 +27,6 @@ import java.util.Map;
 
 import org.apache.sling.installer.api.InstallableResource;
 import org.apache.sling.installer.api.ResourceChangeListener;
-import org.apache.sling.installer.api.info.InfoProvider;
-import org.apache.sling.installer.api.info.Resource;
-import org.apache.sling.installer.api.info.ResourceGroup;
 import org.apache.sling.installer.api.tasks.ChangeStateTask;
 import org.apache.sling.installer.api.tasks.InstallTask;
 import org.apache.sling.installer.api.tasks.InstallTaskFactory;
@@ -42,6 +37,7 @@ import org.apache.sling.installer.api.tasks.TaskResource;
 import org.apache.sling.installer.api.tasks.TaskResourceGroup;
 import org.apache.sling.installer.api.tasks.TransformationResult;
 import 
org.apache.sling.installer.factories.configuration.ConfigurationConstants;
+import org.apache.sling.installer.factories.configuration.ConfigurationMerger;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
@@ -68,14 +64,14 @@ public class ConfigTaskCreator
     private final ResourceChangeListener changeListener;
 
     /** Info Provider */
-    private final InfoProvider infoProvider;
+    private final ConfigurationMerger configMerger;
 
     public ConfigTaskCreator(final ResourceChangeListener listener,
             final ConfigurationAdmin configAdmin,
-            final InfoProvider infoProvider) {
+            final ConfigurationMerger configMerger) {
         this.changeListener = listener;
         this.configAdmin = configAdmin;
-        this.infoProvider = infoProvider;
+        this.configMerger = configMerger;
     }
 
     public ServiceRegistration<?> register(final BundleContext bundleContext) {
@@ -164,7 +160,7 @@ public class ConfigTaskCreator
                             attrs.put(ConfigurationAdmin.SERVICE_FACTORYPID, 
event.getFactoryPid());
                         }
 
-                        removeDefaultProperties(this.infoProvider, 
event.getPid(), dict);
+                        configMerger.removeDefaultProperties(event.getPid(), 
dict);
                         
this.changeListener.resourceAddedOrUpdated(InstallableResource.TYPE_CONFIG, 
event.getPid(), null, dict, attrs);
 
                     } else {
@@ -177,50 +173,6 @@ public class ConfigTaskCreator
         }
     }
 
-    public static Dictionary<String, Object> getDefaultProperties(final 
InfoProvider infoProvider, final String pid) {
-        if ( Activator.MERGE_SCHEMES != null ) {
-            final List<Dictionary<String, Object>> propertiesList = new 
ArrayList<>();
-            final String entityId = 
InstallableResource.TYPE_CONFIG.concat(":").concat(pid);
-            boolean done = false;
-            for(final ResourceGroup group : 
infoProvider.getInstallationState().getInstalledResources()) {
-                for(final Resource rsrc : group.getResources()) {
-                    if ( rsrc.getEntityId().equals(entityId) ) {
-                        done = true;
-                        if ( 
Activator.MERGE_SCHEMES.contains(rsrc.getScheme()) ) {
-                            propertiesList.add(rsrc.getDictionary());
-                        }
-                    }
-                }
-                if ( done ) {
-                    break;
-                }
-            }
-            if ( !propertiesList.isEmpty() ) {
-                final Dictionary<String, Object> defaultProps = 
ConfigUtil.mergeReverseOrder(propertiesList);
-                return defaultProps;
-            }
-        }
-        return null;
-    }
-
-    public static void removeDefaultProperties(final InfoProvider 
infoProvider, final String pid, final Dictionary<String, Object> dict) {
-        if ( Activator.MERGE_SCHEMES != null ) {
-            final Dictionary<String, Object> defaultProps = 
getDefaultProperties(infoProvider, pid);
-            if ( defaultProps != null ) {
-                final Enumeration<String> keyEnum = defaultProps.keys();
-                while ( keyEnum.hasMoreElements() ) {
-                    final String key = keyEnum.nextElement();
-                    final Object value = defaultProps.get(key);
-
-                    final Object newValue = dict.get(key);
-                    if ( newValue != null && ConfigUtil.isSameValue(newValue, 
value)) {
-                        dict.remove(key);
-                    }
-                }
-            }
-        }
-    }
-
     /**
      * @see 
org.apache.sling.installer.api.tasks.ResourceTransformer#transform(org.apache.sling.installer.api.tasks.RegisteredResource)
      */
diff --git 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigurationMergerImpl.java
 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigurationMergerImpl.java
new file mode 100644
index 0000000..80f490e
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigurationMergerImpl.java
@@ -0,0 +1,91 @@
+/*
+ * 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.sling.installer.factories.configuration.impl;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+
+import org.apache.sling.installer.api.InstallableResource;
+import org.apache.sling.installer.api.info.InfoProvider;
+import org.apache.sling.installer.api.info.Resource;
+import org.apache.sling.installer.api.info.ResourceGroup;
+import org.apache.sling.installer.factories.configuration.ConfigurationMerger;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+@Component
+public class ConfigurationMergerImpl implements ConfigurationMerger {
+
+    private final InfoProvider infoProvider;
+
+    @Activate
+    public ConfigurationMergerImpl(@Reference InfoProvider infoProvider) {
+        this.infoProvider = infoProvider;
+    }
+
+    @Override
+    public void removeDefaultProperties(@NotNull final String pid, @NotNull 
final Dictionary<String, Object> dict) {
+        if ( Activator.MERGE_SCHEMES != null ) {
+            final Dictionary<String, Object> defaultProps = 
getDefaultProperties(pid);
+            if ( defaultProps != null ) {
+                final Enumeration<String> keyEnum = defaultProps.keys();
+                while ( keyEnum.hasMoreElements() ) {
+                    final String key = keyEnum.nextElement();
+                    final Object value = defaultProps.get(key);
+
+                    final Object newValue = dict.get(key);
+                    if ( newValue != null && ConfigUtil.isSameValue(newValue, 
value)) {
+                        dict.remove(key);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public Dictionary<String, Object> getDefaultProperties(@NotNull final 
String pid) {
+        if ( Activator.MERGE_SCHEMES != null ) {
+            final List<Dictionary<String, Object>> propertiesList = new 
ArrayList<>();
+            final String entityId = 
InstallableResource.TYPE_CONFIG.concat(":").concat(pid);
+            boolean done = false;
+            for(final ResourceGroup group : 
infoProvider.getInstallationState().getInstalledResources()) {
+                for(final Resource rsrc : group.getResources()) {
+                    if ( rsrc.getEntityId().equals(entityId) ) {
+                        done = true;
+                        if ( 
Activator.MERGE_SCHEMES.contains(rsrc.getScheme()) ) {
+                            propertiesList.add(rsrc.getDictionary());
+                        }
+                    }
+                }
+                if ( done ) {
+                    break;
+                }
+            }
+            if ( !propertiesList.isEmpty() ) {
+                final Dictionary<String, Object> defaultProps = 
ConfigUtil.mergeReverseOrder(propertiesList);
+                return defaultProps;
+            }
+        }
+        return null;
+    }
+}
diff --git 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ServicesListener.java
 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ServicesListener.java
index 139eb2f..216e41c 100644
--- 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ServicesListener.java
+++ 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ServicesListener.java
@@ -21,7 +21,7 @@ package 
org.apache.sling.installer.factories.configuration.impl;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.sling.installer.api.ResourceChangeListener;
-import org.apache.sling.installer.api.info.InfoProvider;
+import org.apache.sling.installer.factories.configuration.ConfigurationMerger;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -53,7 +53,7 @@ public class ServicesListener {
     private final Listener configAdminListener;
 
     /** The listener for the installer info service. */
-    private final Listener infoServiceListener;
+    private final Listener configMergerListener;
 
     /** Registration the service. */
     private volatile ServiceRegistration<?> configTaskCreatorRegistration;
@@ -69,8 +69,8 @@ public class ServicesListener {
         this.bundleContext = bundleContext;
         this.changeHandlerListener = new 
Listener(ResourceChangeListener.class.getName());
         this.configAdminListener = new 
Listener(ConfigurationAdmin.class.getName());
-        this.infoServiceListener = new Listener(InfoProvider.class.getName());
-        this.infoServiceListener.start();
+        this.configMergerListener = new 
Listener(ConfigurationMerger.class.getName());
+        this.configMergerListener.start();
         this.changeHandlerListener.start();
         this.configAdminListener.start();
     }
@@ -79,13 +79,13 @@ public class ServicesListener {
         // check if all services are available
         final ResourceChangeListener listener = 
(ResourceChangeListener)this.changeHandlerListener.getService();
         final ConfigurationAdmin configAdmin = 
(ConfigurationAdmin)this.configAdminListener.getService();
-        final InfoProvider infoProvider = 
(InfoProvider)this.infoServiceListener.getService();
+        final ConfigurationMerger configMerger = 
(ConfigurationMerger)this.configMergerListener.getService();
 
-        if ( configAdmin != null && listener != null && infoProvider != null ) 
{
+        if ( configAdmin != null && listener != null && configMerger != null ) 
{
             if ( configTaskCreator == null ) {
                 active.set(true);
                 // start and register osgi installer service
-                this.configTaskCreator = new ConfigTaskCreator(listener, 
configAdmin, infoProvider);
+                this.configTaskCreator = new ConfigTaskCreator(listener, 
configAdmin, configMerger);
                 final ConfigUpdateHandler handler = new 
ConfigUpdateHandler(configAdmin, this);
                 configTaskCreatorRegistration = 
handler.register(this.bundleContext);
                 if ( Activator.MERGE_SCHEMES != null ) {
@@ -93,7 +93,7 @@ public class ServicesListener {
 
                         @Override
                         public Object getService(final Bundle bundle, final 
ServiceRegistration<Object> registration) {
-                            return new 
WebconsoleConfigurationHandler(bundleContext, infoProvider);
+                            return new 
WebconsoleConfigurationHandler(bundleContext, configMerger);
                         }
 
                         @Override
@@ -138,7 +138,7 @@ public class ServicesListener {
      * Deactivate this listener.
      */
     public void deactivate() {
-        this.infoServiceListener.deactivate();
+        this.configMergerListener.deactivate();
         this.changeHandlerListener.deactivate();
         this.configAdminListener.deactivate();
         this.stop();
diff --git 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/WebconsoleConfigurationHandler.java
 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/WebconsoleConfigurationHandler.java
index 3aa0161..d9ee81b 100644
--- 
a/src/main/java/org/apache/sling/installer/factories/configuration/impl/WebconsoleConfigurationHandler.java
+++ 
b/src/main/java/org/apache/sling/installer/factories/configuration/impl/WebconsoleConfigurationHandler.java
@@ -23,7 +23,7 @@ import java.util.Dictionary;
 
 import org.apache.felix.webconsole.spi.ConfigurationHandler;
 import org.apache.felix.webconsole.spi.ValidationException;
-import org.apache.sling.installer.api.info.InfoProvider;
+import org.apache.sling.installer.factories.configuration.ConfigurationMerger;
 import org.osgi.framework.BundleContext;
 import org.osgi.util.tracker.ServiceTracker;
 
@@ -31,14 +31,14 @@ public class WebconsoleConfigurationHandler implements 
ConfigurationHandler {
 
     static final String META_TYPE_NAME = 
"org.osgi.service.metatype.MetaTypeService"; 
 
-    private final InfoProvider infoProvider;
+    private final ConfigurationMerger configMerger;
 
     private final ServiceTracker<Object, Object> metatypeTracker;
 
     private final BundleContext bundleContext;
 
-    public WebconsoleConfigurationHandler(final BundleContext context, final 
InfoProvider infoProvider) {
-        this.infoProvider = infoProvider;
+    public WebconsoleConfigurationHandler(final BundleContext context, final 
ConfigurationMerger configMerger) {
+        this.configMerger = configMerger;
         this.bundleContext = context;
         this.metatypeTracker = new ServiceTracker<>(context, META_TYPE_NAME, 
null);
         this.metatypeTracker.open();    
@@ -68,7 +68,7 @@ public class WebconsoleConfigurationHandler implements 
ConfigurationHandler {
             throws ValidationException, IOException {
         final Object mts = this.metatypeTracker.getService();
         if ( mts != null ) {
-            final Dictionary<String, Object> defaultProps = 
ConfigTaskCreator.getDefaultProperties(infoProvider, pid);
+            final Dictionary<String, Object> defaultProps = 
configMerger.getDefaultProperties(pid);
             final MetatypeHandler mt = new MetatypeHandler(mts, 
this.bundleContext);
             mt.updateConfiguration(factoryPid, pid, props, defaultProps);
         }        
diff --git 
a/src/main/java/org/apache/sling/installer/factories/configuration/package-info.java
 
b/src/main/java/org/apache/sling/installer/factories/configuration/package-info.java
index eb71c4d..747378d 100644
--- 
a/src/main/java/org/apache/sling/installer/factories/configuration/package-info.java
+++ 
b/src/main/java/org/apache/sling/installer/factories/configuration/package-info.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
[email protected]("1.1.2")
[email protected]("1.2.0")
 package org.apache.sling.installer.factories.configuration;
 
 

Reply via email to