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 2019/12/23 08:30:10 UTC

[sling-org-apache-sling-feature-io] branch master updated: SLING-8419 move JSON configuration serialization code to dedicated package with no dependencies to Sling Feature

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 726b0b5  SLING-8419 move JSON configuration serialization code to dedicated package with no dependencies to Sling Feature
726b0b5 is described below

commit 726b0b537e35c6ef37b4d15bc01f843cc32a1a9b
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Mon Dec 23 09:30:00 2019 +0100

    SLING-8419 move JSON configuration serialization code to dedicated
    package with no dependencies to Sling Feature
---
 ...rationJSONWriter.java => ConfiguratorUtil.java} |  72 ++++++------
 .../feature/io/json/ConfigurationJSONWriter.java   | 127 +--------------------
 .../sling/feature/io/json/JSONWriterBase.java      |   3 +-
 ...ONWriterTest.java => ConfiguratorUtilTest.java} |   7 +-
 4 files changed, 41 insertions(+), 168 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java b/src/main/java/org/apache/sling/feature/io/ConfiguratorUtil.java
similarity index 72%
copy from src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java
copy to src/main/java/org/apache/sling/feature/io/ConfiguratorUtil.java
index 2e57abe..dfba0b5 100644
--- a/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java
+++ b/src/main/java/org/apache/sling/feature/io/ConfiguratorUtil.java
@@ -1,71 +1,67 @@
 /*
  * 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
+ * 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
+ *      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.
+ * 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.feature.io.json;
+package org.apache.sling.feature.io;
 
-import java.io.IOException;
 import java.io.Writer;
 import java.lang.reflect.Array;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.Iterator;
 
+import javax.json.Json;
 import javax.json.stream.JsonGenerator;
+import javax.json.stream.JsonGeneratorFactory;
 
 import org.apache.sling.feature.Configuration;
-import org.apache.sling.feature.Configurations;
 
-/** JSON writer for configurations */
-public class ConfigurationJSONWriter extends JSONWriterBase {
+/**
+ * Helper class to write JSON structures as defined in
+ * <a href="https://osgi.org/specification/osgi.cmpn/7.0.0/service.configurator.html#d0e131765">OSGi Configurator Specification 1.0</a>.
+ *
+ */
+public class ConfiguratorUtil {
 
-    /** Writes the configurations to the writer. The writer is not closed.
-     * 
-     * @param writer Writer
-     * @param configs List of configurations
-     * @throws IOException If writing fails */
-    public static void write(final Writer writer, final Configurations configs)
-            throws IOException {
-        final ConfigurationJSONWriter w = new ConfigurationJSONWriter();
-        w.writeConfigurations(writer, configs);
+    private ConfiguratorUtil() {
     }
 
-    private void writeConfigurations(final Writer writer, final Configurations configs)
-            throws IOException {
-        JsonGenerator generator = newGenerator(writer);
-        writeConfigurations(generator, configs);
-        generator.close();
+    protected static final JsonGenerator newGenerator(final Writer writer) {
+        JsonGeneratorFactory generatorFactory = Json.createGeneratorFactory(Collections.singletonMap(JsonGenerator.PRETTY_PRINTING, true));
+
+        // prevent closing of the underlying writer
+        Writer closeShieldWriter = new CloseShieldWriter(writer);
+        return generatorFactory.createGenerator(closeShieldWriter);
     }
 
-    /** Write the OSGi configuration to a JSON structure as defined in
-     * <a href="https://osgi.org/specification/osgi.cmpn/7.0.0/service.configurator.html#d0e131765">OSGi Configurator Specification 1.0</a>.
+    /** Write the OSGi configuration to a JSON structure.
      * The writer is not closed.
      * 
      * @param writer Writer
      * @param props The configuration properties to write */
     public static void writeConfiguration(final Writer writer, final Dictionary<String, Object> props) {
-        final ConfigurationJSONWriter w = new ConfigurationJSONWriter();
-        JsonGenerator generator = w.newGenerator(writer);
-        generator.writeStartObject();
-        writeConfiguration(generator, props);
-        generator.writeEnd();
-        generator.close();
+        try (JsonGenerator generator = newGenerator(writer)) {
+            generator.writeStartObject();
+            writeConfiguration(generator, props);
+            generator.writeEnd();
+        }
     }
 
-    protected static void writeConfiguration(final JsonGenerator generator, final Dictionary<String, Object> props) {
+    public static void writeConfiguration(final JsonGenerator generator, final Dictionary<String, Object> props) {
         final Enumeration<String> e = props.keys();
         while (e.hasMoreElements()) {
             final String name = e.nextElement();
diff --git a/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java b/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java
index 2e57abe..fa3572d 100644
--- a/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java
+++ b/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java
@@ -50,130 +50,5 @@ public class ConfigurationJSONWriter extends JSONWriterBase {
         generator.close();
     }
 
-    /** Write the OSGi configuration to a JSON structure as defined in
-     * <a href="https://osgi.org/specification/osgi.cmpn/7.0.0/service.configurator.html#d0e131765">OSGi Configurator Specification 1.0</a>.
-     * The writer is not closed.
-     * 
-     * @param writer Writer
-     * @param props The configuration properties to write */
-    public static void writeConfiguration(final Writer writer, final Dictionary<String, Object> props) {
-        final ConfigurationJSONWriter w = new ConfigurationJSONWriter();
-        JsonGenerator generator = w.newGenerator(writer);
-        generator.writeStartObject();
-        writeConfiguration(generator, props);
-        generator.writeEnd();
-        generator.close();
-    }
-
-    protected static void writeConfiguration(final JsonGenerator generator, final Dictionary<String, Object> props) {
-        final Enumeration<String> e = props.keys();
-        while (e.hasMoreElements()) {
-            final String name = e.nextElement();
-            if (Configuration.PROP_ARTIFACT_ID.equals(name)) {
-                continue;
-            }
-            final Object val = props.get(name);
-            writeConfigurationProperty(generator, name, val);
-        }
-    }
-
-    private static void writeConfigurationProperty(JsonGenerator generator, String name, Object val) {
-        String dataType = getDataType(val);
-        writeConfigurationProperty(generator, name, dataType, val);
-    }
-
-    private static void writeConfigurationProperty(JsonGenerator generator, String name, String dataType, Object val) {
-        String nameWithDataPostFix = name;
-        if (dataType != null) {
-            nameWithDataPostFix += ":" + dataType;
-        }
-        if (val.getClass().isArray()) {
-            generator.writeStartArray(nameWithDataPostFix);
-            for (int i = 0; i < Array.getLength(val); i++) {
-                writeArrayItem(generator, Array.get(val, i));
-            }
-            generator.writeEnd();
-        } else if (val instanceof Collection) {
-            generator.writeStartArray(nameWithDataPostFix);
-            for (Object item : Collection.class.cast(val)) {
-                writeArrayItem(generator, item);
-            }
-            generator.writeEnd();
-        } else {
-            writeNameValuePair(generator, nameWithDataPostFix, val);
-        }
-    }
-
-    private static void writeNameValuePair(JsonGenerator generator, String name, Object item) {
-        if (item instanceof Boolean) {
-            generator.write(name, (Boolean) item);
-        } else if (item instanceof Long || item instanceof Integer || item instanceof Byte || item instanceof Short) {
-            generator.write(name, ((Number)item).longValue());
-        } else if (item instanceof Double) {
-            generator.write(name, (Double) item);
-        } else if (item instanceof Float) {
-            generator.write(name, (Float) item);
-        } else {
-            generator.write(name, item.toString());
-        }
-    }
-
-    private static void writeArrayItem(JsonGenerator generator, Object item) {
-        if (item instanceof Boolean) {
-            generator.write((Boolean) item);
-        } else if (item instanceof Long || item instanceof Integer || item instanceof Byte || item instanceof Short) {
-            generator.write(((Number)item).longValue());
-        } else if (item instanceof Double) {
-            generator.write((Double) item);
-        } else if (item instanceof Float) {
-            generator.write((Float) item);
-        } else {
-            generator.write(item.toString());
-        }
-    }
-
-    private static String getDataType(Object object) {
-        if (object instanceof Collection) {
-            // check class of first item
-            Iterator<?> it = ((Collection<?>) object).iterator();
-            if (it.hasNext()) {
-                Class<?> itemClass = it.next().getClass();
-                return "Collection<" + getDataType(itemClass, false) + ">";
-            } else {
-                throw new IllegalStateException("Empty collections are invalid");
-            }
-        } else {
-            return getDataType(object.getClass(), true);
-        }
-    }
-
-    private static String getDataType(Class<?> clazz, boolean allowEmpty) {
-        if (clazz.isArray()) {
-            String dataType = getDataType(clazz.getComponentType(), false);
-            if (dataType != null) {
-                return dataType + "[]";
-            } else {
-                return null;
-            }
-        }
-        // default classes used by native JSON types
-        else if (clazz.isAssignableFrom(Boolean.class) || clazz.isAssignableFrom(boolean.class) || clazz.isAssignableFrom(Long.class) || clazz.isAssignableFrom(long.class) ||
-                clazz.isAssignableFrom(Double.class) || clazz.isAssignableFrom(double.class) || clazz.isAssignableFrom(String.class)) {
-            // no data type necessary except when being used in an array/collection
-            if (!allowEmpty) {
-                // for all other cases just use the simple name
-                return clazz.getSimpleName();
-            }
-
-        } else if (clazz.isAssignableFrom(Integer.class) || clazz.isAssignableFrom(int.class) || clazz.isAssignableFrom(Float.class) || clazz.isAssignableFrom(float.class)
-                || clazz.isAssignableFrom(Byte.class) || clazz.isAssignableFrom(byte.class) || clazz.isAssignableFrom(Short.class) || clazz.isAssignableFrom(short.class)
-                || clazz.isAssignableFrom(Character.class) || clazz.isAssignableFrom(char.class)) {
-            return clazz.getSimpleName();
-        }
-        if (!allowEmpty) {
-            throw new IllegalStateException("Class does not have a valid type " + clazz);
-        }
-        return null;
-
-    }
+    
 }
diff --git a/src/main/java/org/apache/sling/feature/io/json/JSONWriterBase.java b/src/main/java/org/apache/sling/feature/io/json/JSONWriterBase.java
index d88f288..b74a4db 100644
--- a/src/main/java/org/apache/sling/feature/io/json/JSONWriterBase.java
+++ b/src/main/java/org/apache/sling/feature/io/json/JSONWriterBase.java
@@ -36,6 +36,7 @@ import org.apache.sling.feature.ExtensionType;
 import org.apache.sling.feature.MatchingRequirement;
 import org.apache.sling.feature.Prototype;
 import org.apache.sling.feature.io.CloseShieldWriter;
+import org.apache.sling.feature.io.ConfiguratorUtil;
 import org.osgi.resource.Capability;
 import org.osgi.resource.Requirement;
 
@@ -105,7 +106,7 @@ abstract class JSONWriterBase {
 
         for(final Configuration cfg : cfgs) {
             generator.writeStartObject(cfg.getPid());
-            ConfigurationJSONWriter.writeConfiguration(generator, cfg.getConfigurationProperties());
+            ConfiguratorUtil.writeConfiguration(generator, cfg.getConfigurationProperties());
             generator.writeEnd();
         }
 
diff --git a/src/test/java/org/apache/sling/feature/io/json/ConfigurationJSONWriterTest.java b/src/test/java/org/apache/sling/feature/io/ConfiguratorUtilTest.java
similarity index 97%
rename from src/test/java/org/apache/sling/feature/io/json/ConfigurationJSONWriterTest.java
rename to src/test/java/org/apache/sling/feature/io/ConfiguratorUtilTest.java
index 8dac7c1..46b6ba8 100644
--- a/src/test/java/org/apache/sling/feature/io/json/ConfigurationJSONWriterTest.java
+++ b/src/test/java/org/apache/sling/feature/io/ConfiguratorUtilTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.feature.io.json;
+package org.apache.sling.feature.io;
 
 import java.io.IOException;
 import java.io.StringWriter;
@@ -30,6 +30,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.felix.configurator.impl.json.JSONUtil;
 import org.apache.felix.configurator.impl.json.TypeConverter;
 import org.apache.felix.configurator.impl.model.ConfigurationFile;
+import org.apache.sling.feature.io.ConfiguratorUtil;
 import org.hamcrest.Description;
 import org.hamcrest.TypeSafeDiagnosingMatcher;
 import org.hamcrest.core.Every;
@@ -39,7 +40,7 @@ import org.osgi.util.converter.Converter;
 import org.osgi.util.converter.Converters;
 import org.osgi.util.converter.TypeReference;
 
-public class ConfigurationJSONWriterTest {
+public class ConfiguratorUtilTest {
 
     @Test
     public void testConfigurationWriteReadRoundtrip() throws IOException {
@@ -80,7 +81,7 @@ public class ConfigurationJSONWriterTest {
         props.put("String-array", new String[]{"test1", "test2"});
         props.put("String-list", Arrays.asList("test1", "test2"));
         StringWriter writer = new StringWriter();
-        ConfigurationJSONWriter.writeConfiguration(writer, props);
+        ConfiguratorUtil.writeConfiguration(writer, props);
         writer.close();
         assertConfigurationJson(writer.toString(), props);
     }