You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2024/11/22 11:38:49 UTC
(sling-org-apache-sling-installer-factory-configuration) branch feature/streamline-hiding-redundant-properties created (now a704311)
This is an automated email from the ASF dual-hosted git repository.
kwin pushed a change to branch feature/streamline-hiding-redundant-properties
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-configuration.git
at a704311 SLING-12495 Clean up logic to hide redundant properties
This branch includes the following new commits:
new a704311 SLING-12495 Clean up logic to hide redundant properties
The 1 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.
(sling-org-apache-sling-installer-factory-configuration) 01/01: SLING-12495 Clean up logic to hide redundant properties
Posted by kw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kwin pushed a commit to branch feature/streamline-hiding-redundant-properties
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-configuration.git
commit a704311dd9641e9268ab787900e5b42a3adbbe22
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Fri Nov 22 12:38:39 2024 +0100
SLING-12495 Clean up logic to hide redundant properties
No longer consider metatype default values
Either hide both merged/inherited and component properties from
description or don't hide anything.
Individual hiding may lead to false configurations due to the order of
precedence.
Update to Parent 62
---
pom.xml | 8 +-
.../ConfigurationSerializerWebConsolePlugin.java | 234 +++++++++------------
2 files changed, 110 insertions(+), 132 deletions(-)
diff --git a/pom.xml b/pom.xml
index 243282b..e5a3411 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
<parent>
<groupId>org.apache.sling</groupId>
<artifactId>sling-bundle-parent</artifactId>
- <version>61</version>
+ <version>62</version>
<relativePath />
</parent>
@@ -78,6 +78,12 @@
<artifactId>org.osgi.service.component</artifactId>
<scope>provided</scope>
</dependency>
+ <!-- transitive dependency of DS 1.4-->
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.dto</artifactId>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.service.cm</artifactId>
diff --git a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigurationSerializerWebConsolePlugin.java b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigurationSerializerWebConsolePlugin.java
index 7eb8ecc..e449ead 100644
--- a/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigurationSerializerWebConsolePlugin.java
+++ b/src/main/java/org/apache/sling/installer/factories/configuration/impl/ConfigurationSerializerWebConsolePlugin.java
@@ -27,27 +27,22 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Hashtable;
-import java.util.stream.Collectors;
+import java.util.Map;
import org.apache.sling.installer.api.info.InfoProvider;
import org.apache.sling.installer.api.serializer.ConfigurationSerializerFactory;
import org.apache.sling.installer.api.serializer.ConfigurationSerializerFactory.Format;
-import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.runtime.ServiceComponentRuntime;
import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO;
-import org.osgi.service.metatype.MetaTypeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -67,9 +62,7 @@ public class ConfigurationSerializerWebConsolePlugin extends GenericServlet {
private static final String RES_LOC = LABEL + "/res/ui/";
private static final String PARAMETER_PID = "pid";
private static final String PARAMETER_FORMAT = "format";
- private static final String PARAMETER_REMOVE_COMPONENT_DEFAULT_PROPERTIES = "removeComponentDefaultProps";
- private static final String PARAMETER_REMOVE_METATYPE_DEFAULT_PROPERTIES = "removeMetatypeDefaultProps";
- private static final String PARAMETER_REMOVE_MERGED_DEFAULT_PROPERTIES = "removeMergedDefaultProps";
+ private static final String PARAMETER_HIDE_REDUNDANT_PROPERTIES = "hideRedundantProperties";
/** The logger */
private final Logger LOGGER = LoggerFactory.getLogger(ConfigurationSerializerWebConsolePlugin.class);
@@ -77,52 +70,24 @@ public class ConfigurationSerializerWebConsolePlugin extends GenericServlet {
@Reference
ConfigurationAdmin configurationAdmin;
- @Reference
- MetaTypeService metatypeService;
-
@Reference
private InfoProvider infoProvider;
@Reference
private ServiceComponentRuntime scr;
- private final BundleContext bundleContext;
-
- @Activate
- public ConfigurationSerializerWebConsolePlugin(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-
@Override
public void service(final ServletRequest request, final ServletResponse response) throws IOException {
-
final String pid = request.getParameter(PARAMETER_PID);
- final String format = request.getParameter(PARAMETER_FORMAT);
- // initial loading
- final boolean removeMetatypeDefaultProperties;
- final boolean removeComponentDefaultProperties;
- final boolean removeMergedDefaultProperties;
- // initial loading?
- if (format == null) {
- removeMetatypeDefaultProperties = true;
- removeComponentDefaultProperties = true;
- removeMergedDefaultProperties = true;
- } else {
- removeMetatypeDefaultProperties =
- Boolean.parseBoolean(request.getParameter(PARAMETER_REMOVE_METATYPE_DEFAULT_PROPERTIES));
- removeComponentDefaultProperties =
- Boolean.parseBoolean(request.getParameter(PARAMETER_REMOVE_COMPONENT_DEFAULT_PROPERTIES));
- removeMergedDefaultProperties =
- Boolean.parseBoolean(request.getParameter(PARAMETER_REMOVE_MERGED_DEFAULT_PROPERTIES));
- }
- Collection<ComponentDescriptionDTO> allComponentDescriptions;
- if (removeComponentDefaultProperties) {
- allComponentDescriptions = scr.getComponentDescriptionDTOs();
+ final Configuration configuration;
+ if (pid != null && !pid.trim().isEmpty()) {
+ // normalize PID to detect factory configurations with "-" separator
+
+ configuration = configurationAdmin.getConfiguration(pid, null);
} else {
- allComponentDescriptions = Collections.emptyList();
+ configuration = null;
}
-
- MetatypeHandler metatypeHandler = new MetatypeHandler(metatypeService, bundleContext);
+ final String format = request.getParameter(PARAMETER_FORMAT);
ConfigurationSerializerFactory.Format serializationFormat = Format.JSON;
if (format != null && !format.trim().isEmpty()) {
try {
@@ -131,7 +96,28 @@ public class ConfigurationSerializerWebConsolePlugin extends GenericServlet {
LOGGER.warn("Illegal parameter 'format' given, falling back to default '{}'", serializationFormat, e);
}
}
- final PrintWriter pw = response.getWriter();
+ final boolean hideRedundantProperties;
+ if (format == null) {
+ hideRedundantProperties = true;
+ } else {
+ hideRedundantProperties = Boolean.parseBoolean(request.getParameter(PARAMETER_HIDE_REDUNDANT_PROPERTIES));
+ }
+ dumpConfiguration(configuration, serializationFormat, hideRedundantProperties, response.getWriter());
+ }
+
+ private void dumpConfiguration(
+ Configuration configuration,
+ ConfigurationSerializerFactory.Format serializationFormat,
+ boolean hideRedundantProperties,
+ PrintWriter pw) {
+ // map with key = configuration pid and value = ComponentDescriptionDTO
+ Map<String, ComponentDescriptionDTO> allComponentDescriptions = new HashMap<>();
+ String pid = configuration != null ? configuration.getPid() : "";
+ scr.getComponentDescriptionDTOs().stream().forEach(dto -> {
+ for (String configPid : dto.configurationPid) {
+ allComponentDescriptions.put(configPid, dto);
+ }
+ });
pw.println("<script type=\"text/javascript\" src=\"" + RES_LOC + "clipboard.js\"></script>");
pw.print("<form method='get'>");
@@ -146,66 +132,67 @@ public class ConfigurationSerializerWebConsolePlugin extends GenericServlet {
tdLabel(pw, "PID");
tdContent(pw);
- pw.print("<input type='text' name='");
- pw.print(PARAMETER_PID);
- pw.print("' value='");
- if (pid != null) {
- pw.print(escapeXml(pid));
- }
-
- pw.println("' class='input' size='120' minlength='3'>");
+ pw.printf("<input type='text' name='%s' ' value='%s' class='input' size='120' minlength='3'>", PARAMETER_PID, escapeXml(pid));
+ pw.println();
+ pw.println("<p>For factory PIDs use the factory PID followed by a tilde and the configuration name, e.g. 'my.factory.pid~myname'</p>");
closeTd(pw);
closeTr(pw);
tr(pw);
- tdLabel(pw, "Remove Properties");
+
+ tdLabel(pw, "Hide Properties");
tdContent(pw);
- pw.print("<input type='checkbox' name='");
- pw.print(PARAMETER_REMOVE_METATYPE_DEFAULT_PROPERTIES);
- pw.print("'");
- if (removeMetatypeDefaultProperties) {
+ pw.append("<input type='checkbox' name='");
+ pw.append(PARAMETER_HIDE_REDUNDANT_PROPERTIES);
+ pw.append("'");
+ if (hideRedundantProperties) {
pw.print(" checked");
}
- pw.println(" id='");
- pw.print(PARAMETER_REMOVE_METATYPE_DEFAULT_PROPERTIES);
- pw.println("' class='input' value='true'>");
- pw.println("<label for='");
- pw.println(PARAMETER_REMOVE_METATYPE_DEFAULT_PROPERTIES);
- pw.println("'>Metatype Default Properties</label>");
-
- pw.print("<input type='checkbox' name='");
- pw.print(PARAMETER_REMOVE_COMPONENT_DEFAULT_PROPERTIES);
- pw.print("'");
- if (removeComponentDefaultProperties) {
- pw.print(" checked");
+ pw.append(" id='");
+ pw.append(PARAMETER_HIDE_REDUNDANT_PROPERTIES);
+ pw.append("' class='input' value='true'>").println();
+ pw.append("<label for='");
+ pw.append(PARAMETER_HIDE_REDUNDANT_PROPERTIES);
+ pw.append("'>");
+
+
+ StringBuilder sb = new StringBuilder("Redundant Properties (");
+ // these configs come from inherited sources
+ Dictionary<String, Object> mergedProperties =
+ ConfigTaskCreator.getDefaultProperties(infoProvider, pid);
+ if (mergedProperties == null) {
+ mergedProperties = new Hashtable<>();
}
-
- pw.println(" id='");
- pw.print(PARAMETER_REMOVE_COMPONENT_DEFAULT_PROPERTIES);
- pw.println("' class='input' value='true'>");
- pw.println("<label for='");
- pw.println(PARAMETER_REMOVE_COMPONENT_DEFAULT_PROPERTIES);
- pw.println("'>Declarative Services Component Properties</label>");
-
- if (Activator.MERGE_SCHEMES != null) {
- pw.print("<input type='checkbox' name='");
- pw.print(PARAMETER_REMOVE_MERGED_DEFAULT_PROPERTIES);
- pw.print("'");
- if (removeMergedDefaultProperties) {
- pw.print(" checked");
+ if (mergedProperties.size() > 0) {
+ sb.append(
+ "from <a href=\"https://sling.apache.org/documentation/bundles/configuration-installer-factory.html#merging-of-configurations\">Merge Schemes</a> ");
+ sb.append("\"").append(String.join(", ", Activator.MERGE_SCHEMES)).append("\"");
+ }
+ final String pidReferencedFromComponentDescription;
+ if (configuration != null) {
+ pidReferencedFromComponentDescription = configuration.getFactoryPid() != null ? configuration.getFactoryPid() : configuration.getPid();
+ ComponentDescriptionDTO componentDescription = allComponentDescriptions.get(pidReferencedFromComponentDescription);
+ if (componentDescription != null) {
+ if (sb.length() > 0) {
+ sb.append(" and ");
+ }
+ sb.append(String.format(
+ "from component description of <a href=\"components/%s\">component \"%s\" with configuration pid(s) \"%s\"</a>",
+ componentDescription.name,
+ componentDescription.name,
+ String.join(", ", componentDescription.configurationPid)));
}
-
- pw.println(" id='");
- pw.print(PARAMETER_REMOVE_MERGED_DEFAULT_PROPERTIES);
- pw.println("' class='input' value='true'>");
- pw.println("<label for='");
- pw.println(PARAMETER_REMOVE_MERGED_DEFAULT_PROPERTIES);
- pw.println("'>Merged Properties</label>");
+ } else {
+ pidReferencedFromComponentDescription = "";
+ }
+ if (sb.length() == 0) {
+ sb.append("no fallback sources found");
}
+ pw.append(sb.toString()).append(")</label>").println();
pw.println(
- "<p>Selecting any of these options strips those properties which have the same name and value as one from any of the selected sources. The removed properties are very likely being redundant and therefore do not need to be added to serialized configs.</a>");
+ "<p>Enabling it hides those properties which have the same name and value as any of their fallback values.</p>");
closeTd(pw);
closeTr(pw);
@@ -215,10 +202,10 @@ public class ConfigurationSerializerWebConsolePlugin extends GenericServlet {
pw.print("<select name='");
pw.print(PARAMETER_FORMAT);
pw.println("'>");
- option(pw, "JSON", "OSGi Configurator JSON", format);
- option(pw, "CONFIG", "Apache Felix Config", format);
- option(pw, "PROPERTIES", "Java Properties", format);
- option(pw, "PROPERTIES_XML", "Java Properties (XML)", format);
+ option(pw, "JSON", "OSGi Configurator JSON", serializationFormat.name());
+ option(pw, "CONFIG", "Apache Felix Config", serializationFormat.name());
+ option(pw, "PROPERTIES", "Java Properties", serializationFormat.name());
+ option(pw, "PROPERTIES_XML", "Java Properties (XML)", serializationFormat.name());
pw.println("</select>");
pw.println(" <input type='submit' value='Print' class='submit'>");
@@ -226,15 +213,11 @@ public class ConfigurationSerializerWebConsolePlugin extends GenericServlet {
closeTd(pw);
closeTr(pw);
- if (pid != null && !pid.trim().isEmpty()) {
+ if (configuration != null) {
tr(pw);
tdLabel(pw, "Serialized Configuration Properties");
tdContent(pw);
- Configuration configuration = configurationAdmin.getConfiguration(pid, null);
- Dictionary<String, Object> mergedProperties = ConfigTaskCreator.getDefaultProperties(infoProvider, pid);
- if (mergedProperties == null) {
- mergedProperties = new Hashtable<>();
- }
+
Dictionary<String, Object> properties = configuration.getProperties();
if (properties == null) {
pw.print("<p class='ui-state-error-text'>");
@@ -242,22 +225,16 @@ public class ConfigurationSerializerWebConsolePlugin extends GenericServlet {
pw.println("</p>");
} else {
properties = ConfigUtil.cleanConfiguration(properties);
+ if (hideRedundantProperties) {
+ removeComponentDefaultProperties(
+ allComponentDescriptions,
+ pidReferencedFromComponentDescription,
+ properties,
+ mergedProperties);
+ ConfigUtil.removeRedundantProperties(properties, mergedProperties);
+ }
+
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
- if (removeMetatypeDefaultProperties) {
- metatypeHandler.updateConfiguration(
- configuration.getFactoryPid(), configuration.getPid(), properties, mergedProperties);
- }
- if (removeComponentDefaultProperties) {
- removeComponentDefaultProperties(
- allComponentDescriptions,
- configuration.getPid(),
- configuration.getFactoryPid(),
- properties,
- mergedProperties);
- }
- if (removeMergedDefaultProperties) {
- ConfigUtil.removeRedundantProperties(properties, mergedProperties);
- }
// always emit in alphabetical order of keys
ConfigurationSerializerFactory.create(serializationFormat)
.serialize(new SortedDictionary<>(properties), baos);
@@ -275,7 +252,6 @@ public class ConfigurationSerializerWebConsolePlugin extends GenericServlet {
closeTd(pw);
closeTr(pw);
}
-
pw.println("</table>");
pw.print("</form>");
}
@@ -371,25 +347,21 @@ public class ConfigurationSerializerWebConsolePlugin extends GenericServlet {
* @param mergedProperties
*/
private void removeComponentDefaultProperties(
- final Collection<ComponentDescriptionDTO> componentDescriptions,
- final String pid,
- final String factoryPid,
+ final Map<String, ComponentDescriptionDTO> componentDescriptions,
+ final String pidReferencedFromComponentDescription,
final Dictionary<String, Object> dict,
final Dictionary<String, Object> mergedProperties) {
- String effectivePid = factoryPid != null ? factoryPid : pid;
- Collection<ComponentDescriptionDTO> relevantComponentDescriptions = componentDescriptions.stream()
- // find all with a matching pid
- .filter(c -> Arrays.asList(c.configurationPid).contains(effectivePid))
- .collect(Collectors.toList());
+ ComponentDescriptionDTO relevantComponentDescriptions = componentDescriptions.get(pidReferencedFromComponentDescription);
final Enumeration<String> e = dict.keys();
while (e.hasMoreElements()) {
final String key = e.nextElement();
final Object newValue = dict.get(key);
- if (relevantComponentDescriptions.stream()
- .allMatch(c -> ConfigUtil.isSameValue(newValue, c.properties.get(key))
- && mergedProperties.get(key) == null)) {
- dict.remove(key);
+ if (relevantComponentDescriptions != null) {
+ Object defaultValue = relevantComponentDescriptions.properties.get(key);
+ if (ConfigUtil.isSameValue(newValue, defaultValue) && mergedProperties.get(key) == null) {
+ dict.remove(key);
+ }
}
}
}