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

davidb pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-cpconverter.git


The following commit(s) were added to refs/heads/master by this push:
     new 98f31c5  SLING-9881 - adding typehandling for sling:OsgiConfig nodes & 
corresponding test
     new 4691dba  Merge pull request #32 from DominikSuess/issue/SLING-9881
98f31c5 is described below

commit 98f31c5c8ef4ee17c8a6128a5e779d85977d3a19
Author: Dominik Suess <[email protected]>
AuthorDate: Wed Nov 11 10:14:19 2020 +0100

    SLING-9881 - adding typehandling for sling:OsgiConfig nodes & corresponding 
test
---
 .../handlers/XmlConfigurationEntryHandler.java     | 84 ++++++++++++++++++++--
 .../handlers/ConfigurationEntryHandlerTest.java    | 62 +++++++++++-----
 ...sermapping.impl.ServiceUserMapperImpl.typed.xml | 25 +++++++
 3 files changed, 148 insertions(+), 23 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/feature/cpconverter/handlers/XmlConfigurationEntryHandler.java
 
b/src/main/java/org/apache/sling/feature/cpconverter/handlers/XmlConfigurationEntryHandler.java
index 9e4c1b6..d023ac9 100644
--- 
a/src/main/java/org/apache/sling/feature/cpconverter/handlers/XmlConfigurationEntryHandler.java
+++ 
b/src/main/java/org/apache/sling/feature/cpconverter/handlers/XmlConfigurationEntryHandler.java
@@ -17,14 +17,24 @@
 package org.apache.sling.feature.cpconverter.handlers;
 
 import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Calendar;
 import java.util.Dictionary;
 import java.util.Hashtable;
+import java.util.List;
 
+import javax.jcr.PropertyType;
+
+import org.apache.jackrabbit.util.ISO8601;
 import org.apache.jackrabbit.vault.util.DocViewProperty;
 import org.apache.sling.feature.cpconverter.shared.AbstractJcrNodeParser;
+import org.codehaus.plexus.util.StringUtils;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+
 public final class XmlConfigurationEntryHandler extends 
AbstractConfigurationEntryHandler {
 
     public XmlConfigurationEntryHandler() {
@@ -42,7 +52,7 @@ public final class XmlConfigurationEntryHandler extends 
AbstractConfigurationEnt
         }
     }
 
-    private static final class JcrConfigurationHandler extends 
AbstractJcrNodeParser<Dictionary<String, Object>> {
+    protected static final class JcrConfigurationHandler extends 
AbstractJcrNodeParser<Dictionary<String, Object>> {
 
         private static final String SLING_OSGICONFIG = "sling:OsgiConfig";
 
@@ -65,13 +75,73 @@ public final class XmlConfigurationEntryHandler extends 
AbstractConfigurationEnt
 
                     if (attributeValue != null && !attributeValue.isEmpty()) {
                         DocViewProperty property = 
DocViewProperty.parse(attributeQName, attributeValue);
-
+                        Object value = property.values;
+                        List<String> strValues = 
Arrays.asList(property.values);
+                        switch (property.type) {
+                            case PropertyType.DATE:
+                                // Date was never properly supported as osgi 
configs don't support dates so converting to millis 
+                                // Scenario should just be theoretical
+                                attributeQName += ":Long";
+                                value = Lists.transform(strValues, new 
Function<String, Long>() {
+                                   public Long apply(String s) {
+                                      Long res = null;
+                                      if (s != null) {
+                                           Calendar cal = ISO8601.parse(s);
+                                           if (cal != null) {
+                                               res = cal.getTimeInMillis();
+                                           }
+                                      } 
+                                      return res;
+                                   }
+                                }).toArray();
+                                break;
+                            case PropertyType.DOUBLE:
+                                attributeQName += ":Double";
+                                value = Lists.transform(strValues, new 
Function<String, Double>() {
+                                   public Double apply(String s) {
+                                      Double res = null;
+                                      if (StringUtils.isNotEmpty(s)) {
+                                          res = Double.parseDouble(s);
+                                      }
+                                      return res;
+                                   }
+                                }).toArray();
+                                break;
+                            case PropertyType.LONG:
+                                attributeQName += ":Long";
+                                value = Lists.transform(strValues, new 
Function<String, Long>() {
+                                    public Long apply(String s) {
+                                       Long res = null;
+                                       if (StringUtils.isNotEmpty(s)) {
+                                          res = Long.parseLong(s);
+                                       }
+                                       return res;
+                                    }
+                                 }).toArray();
+                                break;
+                            case PropertyType.BOOLEAN:
+                                attributeQName += ":Boolean";
+                                value = Lists.transform(strValues, new 
Function<String, Boolean>() {
+                                    public Boolean apply(String s) {
+                                       Boolean res = null;
+                                       if (s != null) {
+                                          res = Boolean.valueOf(s);
+                                       } 
+                                       return res;
+                                    }
+                                 }).toArray();
+                                break;
+                        }
+                        if(property.isMulti) {
+                            attributeQName+="[]";
+                        } else {
+                            // first element to be used in case of singlevalue
+                            value = ((Object[])value)[0];
+                        }
+                         
+                        
                         if (property.values.length > 0) {
-                            if (property.isMulti) {
-                                configuration.put(attributeQName, 
property.values);
-                            } else {
-                                configuration.put(attributeQName, 
property.values[0]);
-                            }
+                            configuration.put(attributeQName, value);
                         }
                     }
                 }
diff --git 
a/src/test/java/org/apache/sling/feature/cpconverter/handlers/ConfigurationEntryHandlerTest.java
 
b/src/test/java/org/apache/sling/feature/cpconverter/handlers/ConfigurationEntryHandlerTest.java
index 7351f22..4c57c05 100644
--- 
a/src/test/java/org/apache/sling/feature/cpconverter/handlers/ConfigurationEntryHandlerTest.java
+++ 
b/src/test/java/org/apache/sling/feature/cpconverter/handlers/ConfigurationEntryHandlerTest.java
@@ -26,6 +26,8 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import java.io.StringWriter;
+import java.io.Writer;
 import java.util.Arrays;
 import java.util.Collection;
 
@@ -39,6 +41,7 @@ import org.apache.sling.feature.Feature;
 import 
org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter;
 import org.apache.sling.feature.cpconverter.features.DefaultFeaturesManager;
 import org.apache.sling.feature.cpconverter.features.FeaturesManager;
+import org.apache.sling.feature.io.json.ConfigurationJSONWriter;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -50,6 +53,7 @@ public class ConfigurationEntryHandlerTest {
     private static final String EXPECTED_PID = 
"org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl";
     private static final String REPOINIT_PID = 
"org.apache.sling.jcr.repoinit.RepositoryInitializer";
     private static final String REPOINIT_TESTCONFIG_PATH = 
"/jcr_root/apps/asd/config.author/" + REPOINIT_PID + "-test.config";
+    private static final String TYPED_TESTCONFIG_PATH = 
"/jcr_root/apps/asd/config/" + EXPECTED_PID + ".typed.xml";
     private static final String EXPECTED_REPOINIT = "create service user 
test-user\n" + 
         "    set ACL for test-user\n" + 
         "        allow    jcr:read    on /conf\n" + 
@@ -59,20 +63,36 @@ public class ConfigurationEntryHandlerTest {
         "        allow    jcr:read    on /conf\n" + 
         "    end";
 
+    private static final String EXPECTED_TYPED_CONFIG = "{\n" + 
+        "  
\"org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.typed\":  {\n" 
+ 
+        "    \"test.longproperty:Long\":123,\n" + 
+        "    \"user.mapping[]\":[\n" + 
+        "      \"com.adobe.acs.acs-aem-samples-bundle=admin\",\n" + 
+        "      
\"com.adobe.acs.acs-aem-samples-bundle:sample-service=oauthservice\"\n" + 
+        "    ],\n" + 
+        "    \"test.booleanproperty:Boolean\":true,\n" + 
+        "    \"test.dateproperty:Long\":1604743842669,\n" + 
+        "    \"user.default\":\"admin\",\n" + 
+        "    \"test.doubleproperty:Double\":1.23\n" + 
+        "  }\n" + 
+        "}";
     
     private final String resourceConfiguration;
 
     private final int expectedConfigurationsSize;
+    private final int expectedConfigurationsEntrySize;
 
     private final AbstractConfigurationEntryHandler configurationEntryHandler;
     private final String expectedRunMode;
 
     public ConfigurationEntryHandlerTest(String resourceConfiguration,
                                          int expectedConfigurationsSize,
+                                         int expectedConfigurationsEntrySize,
                                          AbstractConfigurationEntryHandler 
configurationEntryHandler, 
                                          String expectedRunMode) {
         this.resourceConfiguration = resourceConfiguration;
         this.expectedConfigurationsSize = expectedConfigurationsSize;
+        this.expectedConfigurationsEntrySize = expectedConfigurationsEntrySize;
         this.configurationEntryHandler = configurationEntryHandler;
         this.expectedRunMode = expectedRunMode;
     }
@@ -121,8 +141,15 @@ public class ConfigurationEntryHandlerTest {
         if (configuration.getPid().contains(".empty")) {
             assertTrue(configuration.getProperties().isEmpty());
         } else {
-            assertEquals("Unmatching size: " + 
configuration.getProperties().size(), 2, configuration.getProperties().size());
+            assertEquals("Unmatching size: " + 
configuration.getProperties().size(), expectedConfigurationsEntrySize, 
configuration.getProperties().size());
         }
+        // type & value check for typed configuration
+        if (this.resourceConfiguration.equals(TYPED_TESTCONFIG_PATH)) {
+            Writer writer = new StringWriter();
+            ConfigurationJSONWriter.write(writer, configurations);
+            assertEquals(EXPECTED_TYPED_CONFIG, writer.toString());
+        }
+
     }
 }
 
@@ -131,29 +158,32 @@ public class ConfigurationEntryHandlerTest {
         String path = "/jcr_root/apps/asd/config/";
 
         return Arrays.asList(new Object[][] {
-            { path + EXPECTED_PID + ".empty.cfg", 1, new 
PropertiesConfigurationEntryHandler(), null },
-            { path + EXPECTED_PID + ".cfg", 1, new 
PropertiesConfigurationEntryHandler(), null },
+            { path + EXPECTED_PID + ".empty.cfg", 1, 2, new 
PropertiesConfigurationEntryHandler(), null },
+            { path + EXPECTED_PID + ".cfg", 1, 2, new 
PropertiesConfigurationEntryHandler(), null },
 
-            { path + EXPECTED_PID + ".empty.cfg.json", 1, new 
JsonConfigurationEntryHandler(), null },
-            { path + EXPECTED_PID + ".cfg.json", 1, new 
JsonConfigurationEntryHandler(), null },
+            { path + EXPECTED_PID + ".empty.cfg.json", 1, 2, new 
JsonConfigurationEntryHandler(), null },
+            { path + EXPECTED_PID + ".cfg.json", 1, 2, new 
JsonConfigurationEntryHandler(), null },
 
-            { path + EXPECTED_PID + ".empty.config", 1, new 
ConfigurationEntryHandler(), null },
-            { path + EXPECTED_PID + ".config", 1, new 
ConfigurationEntryHandler(), null },
+            { path + EXPECTED_PID + ".empty.config", 1, 2, new 
ConfigurationEntryHandler(), null },
+            { path + EXPECTED_PID + ".config", 1, 2, new 
ConfigurationEntryHandler(), null },
 
-            { path + EXPECTED_PID + ".empty.xml", 1, new 
XmlConfigurationEntryHandler(), null },
-            { path + EXPECTED_PID + ".xml", 1, new 
XmlConfigurationEntryHandler(), null },
+            { path + EXPECTED_PID + ".empty.xml", 1, 2, new 
XmlConfigurationEntryHandler(), null },
+            { path + EXPECTED_PID + ".xml", 1, 2, new 
XmlConfigurationEntryHandler(), null },
 
-            { path + EXPECTED_PID + ".empty.config.xml", 1, new 
XmlConfigurationEntryHandler(), null },
-            { path + EXPECTED_PID + ".config.xml", 1, new 
XmlConfigurationEntryHandler(), null },
+            { path + EXPECTED_PID + ".empty.config.xml", 1, 2, new 
XmlConfigurationEntryHandler(), null },
+            { path + EXPECTED_PID + ".config.xml", 1, 2, new 
XmlConfigurationEntryHandler(), null },
 
             
-            { path + EXPECTED_PID + ".empty.xml.cfg", 1, new 
PropertiesConfigurationEntryHandler(), null },
-            { path + EXPECTED_PID + ".xml.cfg", 1, new 
PropertiesConfigurationEntryHandler(), null },
+            { path + EXPECTED_PID + ".empty.xml.cfg", 1, 2, new 
PropertiesConfigurationEntryHandler(), null },
+            { path + EXPECTED_PID + ".xml.cfg", 1, 2, new 
PropertiesConfigurationEntryHandler(), null },
 
             // runmode aware folders
-            { "/jcr_root/apps/asd/config.author/" + EXPECTED_PID + ".config", 
1, new ConfigurationEntryHandler(), "author" },
-            { REPOINIT_TESTCONFIG_PATH, 0, new ConfigurationEntryHandler() , 
"author"},
-            { "/jcr_root/apps/asd/config.publish/" + EXPECTED_PID + ".config", 
1, new ConfigurationEntryHandler(), "publish" }
+            { "/jcr_root/apps/asd/config.author/" + EXPECTED_PID + ".config", 
1, 2, new ConfigurationEntryHandler(), "author" },
+            { REPOINIT_TESTCONFIG_PATH, 0, 2, new ConfigurationEntryHandler() 
, "author"},
+            { "/jcr_root/apps/asd/config.publish/" + EXPECTED_PID + ".config", 
1, 2, new ConfigurationEntryHandler(), "publish" },
+
+            //test typed config
+            { TYPED_TESTCONFIG_PATH, 1, 6, new XmlConfigurationEntryHandler(), 
null }
         });
     }
 
diff --git 
a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/apps/asd/config/org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.typed.xml
 
b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/apps/asd/config/org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.typed.xml
new file mode 100644
index 0000000..91ed2cf
--- /dev/null
+++ 
b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/apps/asd/config/org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.typed.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"; 
xmlns:jcr="http://www.jcp.org/jcr/1.0";
+    jcr:primaryType="sling:OsgiConfig"
+    user.default="admin"
+    test.longproperty="{Long}123"
+    test.doubleproperty="{Double}1.23"
+    test.dateproperty="{Date}2020-11-07T10:10:42.669"
+    test.booleanproperty="{Boolean}true"
+    
user.mapping="[com.adobe.acs.acs-aem-samples-bundle=admin,com.adobe.acs.acs-aem-samples-bundle:sample-service=oauthservice]"/>

Reply via email to