You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2020/04/22 07:08:35 UTC

[sling-slingfeature-maven-plugin] branch master updated: JSON-9362 : Use Apache Felix cm.json for JSON handling

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

cziegeler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git


The following commit(s) were added to refs/heads/master by this push:
     new a62897c  JSON-9362 : Use Apache Felix cm.json for JSON handling
a62897c is described below

commit a62897cec83062e423f676c395fb73e373d21862
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Wed Apr 22 09:08:23 2020 +0200

    JSON-9362 : Use Apache Felix cm.json for JSON handling
---
 pom.xml                                            |  27 +++--
 .../apache/sling/feature/maven/JSONFeatures.java   | 110 +++++++++++++++++++++
 .../apache/sling/feature/maven/ProjectHelper.java  |  71 ++-----------
 .../maven/mojos/AbstractIncludingFeatureMojo.java  |   2 +-
 .../feature/maven/mojos/UpdateVersionsMojo.java    |  84 ++--------------
 .../maven/mojos/AggregateFeaturesMojoTest.java     |  26 ++---
 6 files changed, 151 insertions(+), 169 deletions(-)

diff --git a/pom.xml b/pom.xml
index 11bc0bf..09e2af0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -136,7 +136,16 @@
             <groupId>org.osgi</groupId>
             <artifactId>osgi.core</artifactId>
             <version>6.0.0</version>
-            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-json_1.1_spec</artifactId>
+            <version>1.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.johnzon</groupId>
+            <artifactId>johnzon-core</artifactId>
+            <version>1.2.3</version>
         </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
@@ -146,17 +155,17 @@
          <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.converter</artifactId>
-            <version>1.0.10</version>
+            <version>1.0.14</version>
         </dependency>
         <dependency>
             <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.configurator</artifactId>
-            <version>1.0.10</version>
+            <artifactId>org.apache.felix.cm.json</artifactId>
+            <version>1.0.2</version>
         </dependency>
         <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.commons.johnzon</artifactId>
-            <version>1.1.0</version>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.util.function</artifactId>
+            <version>1.0.0</version>
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
@@ -166,7 +175,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.feature.io</artifactId>
-            <version>1.3.0</version>
+            <version>1.3.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
@@ -284,7 +293,7 @@
         <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.utils</artifactId>
-            <version>1.11.0</version>
+            <version>1.11.4</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven.scm</groupId>
diff --git a/src/main/java/org/apache/sling/feature/maven/JSONFeatures.java b/src/main/java/org/apache/sling/feature/maven/JSONFeatures.java
new file mode 100644
index 0000000..85160fd
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/JSONFeatures.java
@@ -0,0 +1,110 @@
+/*
+ * 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.feature.maven;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Map;
+
+import javax.json.Json;
+import javax.json.JsonException;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonReader;
+import javax.json.JsonValue;
+import javax.json.JsonWriter;
+import javax.json.stream.JsonGenerator;
+
+import org.apache.felix.cm.json.Configurations;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.io.json.FeatureJSONWriter;
+
+public class JSONFeatures {
+
+    public static final ArtifactId PLACEHOLDER_ID = new ArtifactId("_", "_", "1.0", null, null);
+
+    /**
+     * Read the feature and add the {@code id} attribute if missing
+     * @param reader The reader
+     * @param optionalId The artifact id to use if the {@code id} attribute is missing
+     * @param location The location
+     * @return The feature as a string
+     * @throws IOException If reading fails
+     */
+    public static String read(final Reader reader, final ArtifactId optionalId, final String location)
+    throws IOException {
+        JsonObject featureObj;
+        try (JsonReader jsonReader = Json.createReader(Configurations.jsonCommentAwareReader(reader))) {
+            featureObj = jsonReader.readObject();
+            if ( !featureObj.containsKey("id") ) {
+                final JsonObjectBuilder job = Json.createObjectBuilder();
+                job.add("id", optionalId.toMvnId());
+                for(final Map.Entry<String, JsonValue> prop : featureObj.entrySet() ) {
+                    job.add(prop.getKey(), prop.getValue());
+                }
+                featureObj = job.build();
+            }
+        } catch ( final JsonException je) {
+            throw new IOException(je.getMessage(), je);
+        }
+
+        try ( final StringWriter writer = new StringWriter()) {
+            try ( final JsonWriter jsonWriter = Json.createWriter(writer)) {
+                jsonWriter.writeObject(featureObj);
+            }
+            return writer.toString();
+        }
+    }
+
+    /**
+     * Write the feature. If the id is the {@link #PLACEHOLDER_ID} then the id is not written out
+     * @param writer The writer
+     * @param feature The feature
+     * @throws IOException If anything goes wrong
+     */
+    public static void write(final Writer writer, final Feature feature) throws IOException {
+        if ( feature.getId().equals(PLACEHOLDER_ID)) {
+            // write feature with placeholder id
+            try ( final StringWriter stringWriter = new StringWriter()) {
+                FeatureJSONWriter.write(stringWriter, feature);
+
+                // read feature as json object
+                try (JsonReader jsonReader = Json.createReader(new StringReader(stringWriter.toString()))) {
+                    final JsonObject featureObj = jsonReader.readObject();
+
+                    // write feature object, except id property
+                    try (final JsonGenerator generator = Json.createGenerator(writer)) {
+                        generator.writeStartObject();
+
+                        for (final Map.Entry<String, JsonValue> entry : featureObj.entrySet()) {
+                            if ( !"id".equals(entry.getKey()) ) {
+                                generator.write(entry.getKey(), entry.getValue());
+                            }
+                        }
+                        generator.writeEnd();
+                    }
+                }
+            }
+        } else {
+            FeatureJSONWriter.write(writer, feature);
+        }
+    }
+}
diff --git a/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java b/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
index c6b17fd..f55ef30 100644
--- a/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
+++ b/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
@@ -35,13 +35,6 @@ import java.util.Set;
 import java.util.TreeMap;
 import java.util.stream.Collectors;
 
-import javax.json.Json;
-import javax.json.JsonObject;
-import javax.json.JsonReader;
-import javax.json.JsonValue;
-import javax.json.stream.JsonGenerator;
-
-import org.apache.felix.configurator.impl.json.JSMin;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.DefaultArtifact;
 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
@@ -540,66 +533,18 @@ public abstract class ProjectHelper {
      */
     public static String readFeatureFile(final MavenProject project, final File file,
             final String suggestedClassifier) {
-        final StringBuilder sb = new StringBuilder();
-        try (final Reader reader = new FileReader(file)) {
-            final char[] buf = new char[4096];
-            int l = 0;
+        final ArtifactId fileId = new ArtifactId(project.getGroupId(),
+                project.getArtifactId(),
+                project.getVersion(),
+                suggestedClassifier,
+                FeatureConstants.PACKAGING_FEATURE);
 
-            while ((l = reader.read(buf)) > 0) {
-                sb.append(buf, 0, l);
-            }
-        } catch (final IOException io) {
-            throw new RuntimeException("Unable to read feature " + file.getAbsolutePath(), io);
-        }
-        final String readJson = sb.toString();
-
-        // minify JSON (remove comments)
-        String json;
-        try (final Writer out = new StringWriter(); final Reader in = new StringReader(readJson)) {
-            final JSMin min = new JSMin(in, out);
-            min.jsmin();
-            json = out.toString();
+        // replace variables
+        try ( final Reader reader = new FileReader(file) ) {
+            return Substitution.replaceMavenVars(project, JSONFeatures.read(reader, fileId, file.getAbsolutePath()));
         } catch (final IOException e) {
             throw new RuntimeException("Unable to read feature file " + file.getAbsolutePath(), e);
         }
-
-        // check if "id" is set
-        try (final JsonReader reader = Json.createReader(new StringReader(json))) {
-            final JsonObject obj = reader.readObject();
-            if (!obj.containsKey("id")) {
-                final StringBuilder isb = new StringBuilder();
-                isb.append(project.getGroupId());
-                isb.append(':');
-                isb.append(project.getArtifactId());
-                isb.append(':');
-                isb.append(FeatureConstants.PACKAGING_FEATURE);
-
-                if (suggestedClassifier != null) {
-                    isb.append(':');
-                    isb.append(suggestedClassifier);
-                }
-                isb.append(':');
-                isb.append(project.getVersion());
-
-                final StringWriter writer = new StringWriter();
-
-                try (final JsonGenerator generator = Json.createGenerator(writer)) {
-                    generator.writeStartObject();
-
-                    generator.write("id", isb.toString());
-
-                    for (final Map.Entry<String, JsonValue> entry : obj.entrySet()) {
-                        generator.write(entry.getKey(), entry.getValue());
-                    }
-                    generator.writeEnd();
-                }
-
-                json = writer.toString();
-            }
-        }
-
-        // replace variables
-        return Substitution.replaceMavenVars(project, json);
     }
 
     public static void checkFeatureId(final MavenProject project, final Feature feature) {
diff --git a/src/main/java/org/apache/sling/feature/maven/mojos/AbstractIncludingFeatureMojo.java b/src/main/java/org/apache/sling/feature/maven/mojos/AbstractIncludingFeatureMojo.java
index 2424321..6dcef11 100644
--- a/src/main/java/org/apache/sling/feature/maven/mojos/AbstractIncludingFeatureMojo.java
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/AbstractIncludingFeatureMojo.java
@@ -39,7 +39,7 @@ import edu.emory.mathcs.backport.java.util.Collections;
 public abstract class AbstractIncludingFeatureMojo extends AbstractFeatureMojo {
 
     /**
-     * Get all selected features for the provided configuratio
+     * Get all selected features for the provided configuration
      * @param config The selection configuration
      * @return An ordered map of features
      * @throws MojoExecutionException
diff --git a/src/main/java/org/apache/sling/feature/maven/mojos/UpdateVersionsMojo.java b/src/main/java/org/apache/sling/feature/maven/mojos/UpdateVersionsMojo.java
index e4280d4..dcb4244 100644
--- a/src/main/java/org/apache/sling/feature/maven/mojos/UpdateVersionsMojo.java
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/UpdateVersionsMojo.java
@@ -21,6 +21,7 @@ import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.Reader;
+import java.io.StringReader;
 import java.io.Writer;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -32,9 +33,6 @@ import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
 
-import javax.json.stream.JsonGenerator;
-import javax.json.stream.JsonParsingException;
-
 import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 import org.apache.maven.artifact.repository.ArtifactRepository;
@@ -53,7 +51,7 @@ import org.apache.sling.feature.Extension;
 import org.apache.sling.feature.ExtensionType;
 import org.apache.sling.feature.Feature;
 import org.apache.sling.feature.io.json.FeatureJSONReader;
-import org.apache.sling.feature.io.json.FeatureJSONWriter;
+import org.apache.sling.feature.maven.JSONFeatures;
 import org.apache.sling.feature.maven.ProjectHelper;
 import org.codehaus.mojo.versions.api.ArtifactVersions;
 import org.codehaus.mojo.versions.api.DefaultVersionsHelper;
@@ -208,9 +206,11 @@ public class UpdateVersionsMojo extends AbstractIncludingFeatureMojo {
 
     private Feature readRawFeature(final String fileName) throws MojoExecutionException {
         // we need to read the raw file
-        final File out = new File(fileName);
-        try (final Reader r = new FileReader(out)) {
-            return SimpleFeatureJSONReader.read(r, fileName);
+        try (final Reader r = new FileReader(new File(fileName))) {
+            final String json = JSONFeatures.read(r, JSONFeatures.PLACEHOLDER_ID, fileName);
+            try ( final Reader featureReader = new StringReader(json)) {
+                return FeatureJSONReader.read(featureReader, fileName);
+            }
         } catch (final IOException e) {
             throw new MojoExecutionException("Unable to read feature file " + fileName, e);
         }
@@ -280,7 +280,7 @@ public class UpdateVersionsMojo extends AbstractIncludingFeatureMojo {
 
                 if (updateVersions(entry.getKey(), rawFeature, result, globalPropertyUpdates) && !dryRun) {
                     try (final Writer w = new FileWriter(new File(entry.getKey()))) {
-                        SimpleFeatureJSONWriter.write(w, rawFeature);
+                        JSONFeatures.write(w, rawFeature);
                     } catch (final IOException e) {
                         throw new MojoExecutionException("Unable to write feature file " + entry.getValue(), e);
                     }
@@ -471,74 +471,6 @@ public class UpdateVersionsMojo extends AbstractIncludingFeatureMojo {
         public Map<String, String> propertyUpdates = new HashMap<>();
     }
 
-	public static class SimpleFeatureJSONReader extends FeatureJSONReader {
-
-		static final ArtifactId PLACEHOLDER_ID = new ArtifactId("_", "_", "1.0", null, null);
-
-		/**
-	     * Private constructor
-	     * @param location Optional location
-	     */
-	    protected SimpleFeatureJSONReader(final String location) {
-	        super(location);
-	    }
-
-	    @Override
-		protected ArtifactId getFeatureId(Map<String, Object> map) throws IOException {
-	    	final ArtifactId id;
-	        if ( !map.containsKey("id") ) {
-	        	id = PLACEHOLDER_ID;
-	        } else {
-	        	id = super.getFeatureId(map);
-	        }
-	        return id;
-	    }
-
-		/**
-	     * Read a new feature from the reader
-	     * The reader is not closed. It is up to the caller to close the reader.
-	     *
-	     * @param reader The reader for the feature
-	     * @param location Optional location
-	     * @return The read feature
-	     * @throws IOException If an IO errors occurs or the JSON is invalid.
-	     */
-	    public static Feature read(final Reader reader, final String location)
-	    throws IOException {
-	        try {
-	            final SimpleFeatureJSONReader mr = new SimpleFeatureJSONReader(location);
-	            return mr.readFeature(reader);
-	        } catch (final IllegalStateException | IllegalArgumentException | JsonParsingException e) {
-	            throw new IOException(e);
-	        }
-	    }
-	}
-
-	public static class SimpleFeatureJSONWriter extends FeatureJSONWriter {
-
-		private SimpleFeatureJSONWriter() {}
-
-	    /**
-	     * Writes the feature to the writer.
-	     * The writer is not closed.
-	     * @param writer Writer
-	     * @param feature Feature
-	     * @throws IOException If writing fails
-	     */
-	    public static void write(final Writer writer, final Feature feature)
-	    throws IOException {
-	        final SimpleFeatureJSONWriter w = new SimpleFeatureJSONWriter();
-	        w.writeFeature(writer, feature);
-	    }
-
-	    @Override
-		protected void writeFeatureId(JsonGenerator generator, Feature feature) {
-	    	if ( !feature.getId().equals(SimpleFeatureJSONReader.PLACEHOLDER_ID) ) {
-	            super.writeFeatureId(generator, feature);
-	        }
-	    }
-	}
-
     private String getVersion(final Map.Entry<Dependency, ArtifactVersions> entry, final UpdateScope scope) {
         ArtifactVersion latest;
         if (entry.getValue().isCurrentVersionDefined()) {
diff --git a/src/test/java/org/apache/sling/feature/maven/mojos/AggregateFeaturesMojoTest.java b/src/test/java/org/apache/sling/feature/maven/mojos/AggregateFeaturesMojoTest.java
index d4ecdfa..f1d0ce4 100644
--- a/src/test/java/org/apache/sling/feature/maven/mojos/AggregateFeaturesMojoTest.java
+++ b/src/test/java/org/apache/sling/feature/maven/mojos/AggregateFeaturesMojoTest.java
@@ -40,9 +40,8 @@ import java.util.Properties;
 import java.util.Set;
 
 import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
-import org.apache.maven.artifact.repository.ArtifactRepository;
-import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 import org.apache.maven.artifact.resolver.ArtifactResolver;
 import org.apache.maven.artifact.versioning.VersionRange;
 import org.apache.maven.execution.MavenSession;
@@ -62,8 +61,6 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
 
 @SuppressWarnings("deprecation")
 public class AggregateFeaturesMojoTest {
@@ -402,7 +399,6 @@ public class AggregateFeaturesMojoTest {
         assertEquals(expectedConfigs, actualConfigs);
     }
 
-    @SuppressWarnings("unchecked")
     @Test
     public void testReadFeatureFromArtifact() throws Exception {
        File featureFile = new File(
@@ -438,6 +434,11 @@ public class AggregateFeaturesMojoTest {
             .thenReturn(featureMap);
         Mockito.when(mockProj.getContextValue(Preprocessor.class.getName())).thenReturn(Boolean.TRUE);
 
+        final Artifact fileArtifact = new DefaultArtifact(dep.getGroupId(), dep.getArtifactId(),
+                dep.getVersion(), Artifact.SCOPE_COMPILE, dep.getType(), dep.getClassifier(), Mockito.mock(org.apache.maven.artifact.handler.ArtifactHandler.class));
+        fileArtifact.setFile(featureFile);
+
+        Mockito.when(mockProj.getAttachedArtifacts()).thenReturn(Collections.singletonList(fileArtifact));
         AggregateFeaturesMojo af = new AggregateFeaturesMojo();
         fc.classifier = "mynewfeature";
         af.aggregates = Collections.singletonList(fc);
@@ -448,21 +449,6 @@ public class AggregateFeaturesMojoTest {
         af.features = featureFile.getParentFile();
 
         af.artifactResolver = Mockito.mock(ArtifactResolver.class);
-        Mockito.doAnswer(new Answer<Void>() {
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                Artifact artifact = invocation.getArgumentAt(0, Artifact.class);
-                if (artifact.getGroupId().equals(dep.getGroupId())
-                        && artifact.getArtifactId().equals(dep.getArtifactId())
-                        && artifact.getVersion().equals(dep.getVersion())
-                        && artifact.getClassifier().equals(dep.getClassifier())
-                        && artifact.getType().equals(dep.getType())) {
-                    artifact.setFile(featureFile);
-                    return null;
-                }
-                throw new ArtifactResolutionException("Not found", artifact);
-            }
-        }).when(af.artifactResolver).resolve(Mockito.any(Artifact.class), Mockito.anyList(), Mockito.any(ArtifactRepository.class));
         af.execute();
 
         Feature genFeat = featureMap.get(":aggregate:mynewfeature:T");