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 2017/09/01 15:02:41 UTC
svn commit: r1806972 - in
/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process:
ApplicationBuilder.java BuilderUtil.java FeatureBuilder.java
FeatureExtensionHandler.java
Author: cziegeler
Date: Fri Sep 1 15:02:41 2017
New Revision: 1806972
URL: http://svn.apache.org/viewvc?rev=1806972&view=rev
Log:
Add feature extension handler
Added:
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureExtensionHandler.java (with props)
Modified:
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/ApplicationBuilder.java
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/BuilderUtil.java
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureBuilder.java
Modified: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/ApplicationBuilder.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/ApplicationBuilder.java?rev=1806972&r1=1806971&r2=1806972&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/ApplicationBuilder.java (original)
+++ sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/ApplicationBuilder.java Fri Sep 1 15:02:41 2017
@@ -16,16 +16,16 @@
*/
package org.apache.sling.feature.process;
-import org.apache.sling.feature.Application;
-import org.apache.sling.feature.ArtifactId;
-import org.apache.sling.feature.Feature;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.sling.feature.Application;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Feature;
+
/**
* Build an application based on features.
*/
@@ -156,6 +156,6 @@ public class ApplicationBuilder {
BuilderUtil.mergeBundles(target.getBundles(), source.getBundles(), BuilderUtil.ArtifactMerge.HIGHEST);
BuilderUtil.mergeConfigurations(target.getConfigurations(), source.getConfigurations());
BuilderUtil.mergeFrameworkProperties(target.getFrameworkProperties(), source.getFrameworkProperties());
- BuilderUtil.mergeExtensions(target.getExtensions(), source.getExtensions(), BuilderUtil.ArtifactMerge.HIGHEST);
+ BuilderUtil.mergeExtensions(target, source, BuilderUtil.ArtifactMerge.HIGHEST);
}
}
Modified: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/BuilderUtil.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/BuilderUtil.java?rev=1806972&r1=1806971&r2=1806972&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/BuilderUtil.java (original)
+++ sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/BuilderUtil.java Fri Sep 1 15:02:41 2017
@@ -16,27 +16,29 @@
*/
package org.apache.sling.feature.process;
+import java.io.StringReader;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonStructure;
+import javax.json.JsonValue;
+import javax.json.JsonValue.ValueType;
+
+import org.apache.sling.feature.Application;
import org.apache.sling.feature.Artifact;
import org.apache.sling.feature.Bundles;
import org.apache.sling.feature.Capability;
import org.apache.sling.feature.Configuration;
import org.apache.sling.feature.Configurations;
import org.apache.sling.feature.Extension;
-import org.apache.sling.feature.Extensions;
+import org.apache.sling.feature.Feature;
import org.apache.sling.feature.KeyValueMap;
import org.apache.sling.feature.Requirement;
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonObject;
-import javax.json.JsonStructure;
-import javax.json.JsonValue;
-import javax.json.JsonValue.ValueType;
-import java.io.StringReader;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Map;
-
/**
* Utility methods for the builders
*/
@@ -114,80 +116,118 @@ class BuilderUtil {
}
}
- // extensions (add/merge)
- static void mergeExtensions(final Extensions target,
- final Extensions source,
+ // default merge for extensions
+ static void mergeExtensions(final Extension target,
+ final Extension source,
final ArtifactMerge artifactMergeAlg) {
- for(final Extension ext : source) {
+ switch ( target.getType() ) {
+ case TEXT : // simply append
+ target.setText(target.getText() + "\n" + source.getText());
+ break;
+ case JSON : final JsonStructure struct1;
+ try ( final StringReader reader = new StringReader(target.getJSON()) ) {
+ struct1 = Json.createReader(reader).read();
+ }
+ final JsonStructure struct2;
+ try ( final StringReader reader = new StringReader(source.getJSON()) ) {
+ struct2 = Json.createReader(reader).read();
+ }
+
+ if ( struct1.getValueType() != struct2.getValueType() ) {
+ throw new IllegalStateException("Found different JSON types for extension " + target.getName()
+ + " : " + struct1.getValueType() + " and " + struct2.getValueType());
+ }
+ if ( struct1.getValueType() == ValueType.ARRAY ) {
+ // array is append
+ final JsonArray a1 = (JsonArray)struct1;
+ final JsonArray a2 = (JsonArray)struct2;
+ for(final JsonValue val : a2) {
+ a1.add(val);
+ }
+ } else {
+ // object is merge
+ merge((JsonObject)struct1, (JsonObject)struct2);
+ }
+ break;
+
+ case ARTIFACTS : for(final Artifact a : source.getArtifacts()) {
+ // use artifactMergeAlg
+ boolean add = true;
+ for(final Artifact targetArtifact : target.getArtifacts()) {
+ if ( targetArtifact.getId().isSame(a.getId()) ) {
+ if ( artifactMergeAlg == ArtifactMerge.HIGHEST ) {
+ if ( targetArtifact.getId().getOSGiVersion().compareTo(a.getId().getOSGiVersion()) > 0 ) {
+ add = false;
+ } else {
+ target.getArtifacts().remove(targetArtifact);
+ }
+ } else { // latest
+
+ target.getArtifacts().remove(targetArtifact);
+ }
+ break;
+ }
+ }
+
+ if ( add ) {
+ target.getArtifacts().add(a);
+ }
+
+ }
+ break;
+ }
+ }
+
+ // extensions (add/merge)
+ static void mergeExtensions(final Feature target,
+ final Feature source,
+ final ArtifactMerge artifactMergeAlg,
+ final FeatureExtensionHandler... extensionMergers) {
+ for(final Extension ext : source.getExtensions()) {
boolean found = false;
- for(final Extension current : target) {
+ for(final Extension current : target.getExtensions()) {
if ( current.getName().equals(ext.getName()) ) {
found = true;
if ( current.getType() != ext.getType() ) {
throw new IllegalStateException("Found different types for extension " + current.getName()
+ " : " + current.getType() + " and " + ext.getType());
}
- switch ( current.getType() ) {
- case TEXT : // simply append
- current.setText(current.getText() + "\n" + ext.getText());
- break;
- case JSON : final JsonStructure struct1;
- try ( final StringReader reader = new StringReader(current.getJSON()) ) {
- struct1 = Json.createReader(reader).read();
- }
- final JsonStructure struct2;
- try ( final StringReader reader = new StringReader(ext.getJSON()) ) {
- struct2 = Json.createReader(reader).read();
- }
-
- if ( struct1.getValueType() != struct2.getValueType() ) {
- throw new IllegalStateException("Found different JSON types for extension " + current.getName()
- + " : " + struct1.getValueType() + " and " + struct2.getValueType());
- }
- if ( struct1.getValueType() == ValueType.ARRAY ) {
- // array is append
- final JsonArray a1 = (JsonArray)struct1;
- final JsonArray a2 = (JsonArray)struct2;
- for(final JsonValue val : a2) {
- a1.add(val);
- }
- } else {
- // object is merge
- merge((JsonObject)struct1, (JsonObject)struct2);
- }
- break;
-
- case ARTIFACTS : for(final Artifact a : ext.getArtifacts()) {
- // use artifactMergeAlg
- boolean add = true;
- for(final Artifact targetArtifact : current.getArtifacts()) {
- if ( targetArtifact.getId().isSame(a.getId()) ) {
- if ( artifactMergeAlg == ArtifactMerge.HIGHEST ) {
- if ( targetArtifact.getId().getOSGiVersion().compareTo(a.getId().getOSGiVersion()) > 0 ) {
- add = false;
- } else {
- current.getArtifacts().remove(targetArtifact);
- }
- } else { // latest
-
- current.getArtifacts().remove(targetArtifact);
- }
- break;
- }
- }
-
- if ( add ) {
- current.getArtifacts().add(a);
- }
-
- }
- break;
+ if ( extensionMergers != null ) {
+ for(final FeatureExtensionHandler fem : extensionMergers) {
+ if ( fem.canMerge(current.getName()) ) {
+ fem.merge(target, source, current.getName());
+ }
+ }
+ } else {
+ // default merge
+ mergeExtensions(current, ext, artifactMergeAlg);
+ }
+ }
+ }
+ if ( !found ) {
+ target.getExtensions().add(ext);
+ }
+ }
+ }
+ static void mergeExtensions(final Application target,
+ final Feature source,
+ final ArtifactMerge artifactMergeAlg) {
+ for(final Extension ext : source.getExtensions()) {
+ boolean found = false;
+ for(final Extension current : target.getExtensions()) {
+ if ( current.getName().equals(ext.getName()) ) {
+ found = true;
+ if ( current.getType() != ext.getType() ) {
+ throw new IllegalStateException("Found different types for extension " + current.getName()
+ + " : " + current.getType() + " and " + ext.getType());
}
+ // default merge
+ mergeExtensions(current, ext, artifactMergeAlg);
}
}
if ( !found ) {
- target.add(ext);
+ target.getExtensions().add(ext);
}
}
}
Modified: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureBuilder.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureBuilder.java?rev=1806972&r1=1806971&r2=1806972&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureBuilder.java (original)
+++ sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureBuilder.java Fri Sep 1 15:02:41 2017
@@ -16,6 +16,12 @@
*/
package org.apache.sling.feature.process;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
import org.apache.sling.feature.Artifact;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Configuration;
@@ -23,12 +29,6 @@ import org.apache.sling.feature.Extensio
import org.apache.sling.feature.Feature;
import org.apache.sling.feature.Include;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
public class FeatureBuilder {
/**
@@ -36,15 +36,18 @@ public class FeatureBuilder {
*
* @param feature The feature to start
* @param provider A provider providing the included features
+ * @param extensionMergers Optional feature mergers
* @return The assembled feature.
* @throws IllegalArgumentException If feature or provider is {@code null}
- * @throws IllegalStateException If an included feature can't be provided
+ * @throws IllegalStateException If an included feature can't be provided or merged.
*/
- public static Feature assemble(final Feature feature, final FeatureProvider provider) {
+ public static Feature assemble(final Feature feature,
+ final FeatureProvider provider,
+ final FeatureExtensionHandler... extensionMergers) {
if ( feature == null || provider == null ) {
throw new IllegalArgumentException("Feature and/or provider must not be null");
}
- return internalAssemble(new ArrayList<>(), feature, provider);
+ return internalAssemble(new ArrayList<>(), feature, provider, extensionMergers);
}
/**
@@ -64,7 +67,8 @@ public class FeatureBuilder {
*/
public static Feature assemble(final Feature feature,
final List<Feature> upgrades,
- final FeatureProvider provider) {
+ final FeatureProvider provider,
+ final FeatureExtensionHandler... extensionMergers) {
if ( feature == null || provider == null ) {
throw new IllegalArgumentException("Feature and/or provider must not be null");
}
@@ -100,7 +104,7 @@ public class FeatureBuilder {
}
// assemble feature without upgrades
- final Feature assembledFeature = internalAssemble(new ArrayList<>(), feature, provider);
+ final Feature assembledFeature = internalAssemble(new ArrayList<>(), feature, provider, extensionMergers);
// handle upgrades
if ( useUpdates != null ) {
@@ -125,7 +129,7 @@ public class FeatureBuilder {
final Feature auf = assemble(uf, provider);
// merge
- merge(assembledFeature, auf);
+ merge(assembledFeature, auf, extensionMergers);
}
}
@@ -134,7 +138,8 @@ public class FeatureBuilder {
private static Feature internalAssemble(final List<String> processedFeatures,
final Feature feature,
- final FeatureProvider provider) {
+ final FeatureProvider provider,
+ final FeatureExtensionHandler... extensionMergers) {
if ( feature.isAssembled() ) {
return feature;
}
@@ -187,15 +192,15 @@ public class FeatureBuilder {
if ( f == null ) {
throw new IllegalStateException("Unable to find included feature " + i.getId());
}
- final Feature af = internalAssemble(processedFeatures, f, provider);
+ final Feature af = internalAssemble(processedFeatures, f, provider, extensionMergers);
// process include instructions
include(af, i);
// and now merge
- merge(result, af);
+ merge(result, af, extensionMergers);
}
- merge(result, feature);
+ merge(result, feature, extensionMergers);
}
processedFeatures.remove(feature.getId().toMvnId());
@@ -203,13 +208,17 @@ public class FeatureBuilder {
return result;
}
- private static void merge(final Feature target, final Feature source) {
+ private static void merge(final Feature target, final Feature source,
+ final FeatureExtensionHandler... extensionMergers) {
BuilderUtil.mergeBundles(target.getBundles(), source.getBundles(), BuilderUtil.ArtifactMerge.LATEST);
BuilderUtil.mergeConfigurations(target.getConfigurations(), source.getConfigurations());
BuilderUtil.mergeFrameworkProperties(target.getFrameworkProperties(), source.getFrameworkProperties());
BuilderUtil.mergeRequirements(target.getRequirements(), source.getRequirements());
BuilderUtil.mergeCapabilities(target.getCapabilities(), source.getCapabilities());
- BuilderUtil.mergeExtensions(target.getExtensions(), source.getExtensions(), BuilderUtil.ArtifactMerge.LATEST);
+ BuilderUtil.mergeExtensions(target,
+ source,
+ BuilderUtil.ArtifactMerge.LATEST,
+ extensionMergers);
}
private static void include(final Feature base, final Include i) {
Added: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureExtensionHandler.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureExtensionHandler.java?rev=1806972&view=auto
==============================================================================
--- sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureExtensionHandler.java (added)
+++ sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureExtensionHandler.java Fri Sep 1 15:02:41 2017
@@ -0,0 +1,51 @@
+/*
+ * 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.process;
+
+import org.apache.sling.feature.Feature;
+
+public interface FeatureExtensionHandler {
+
+ /**
+ * Checks whether this merger can merge extensions with that name
+ * @param extensionName The extension name
+ * @return {@code true} if merger can handle this
+ */
+ boolean canMerge(String extensionName);
+
+ /**
+ * Merge the source extension into the target extension.
+ *
+ * The caller of this method already ensured that both
+ * extensions share the same name and type and that
+ * {@link #canMerge(String)} returned {@code true}.
+ *
+ * @param target The target feature
+ * @param source The source feature
+ * @param extensionName The extension name
+ * @throws IllegalStateException If the extensions can't be merged
+ */
+ void merge(Feature target, Feature source, String extensionName);
+
+ /**
+ * Post process the feature with respect to the extension
+ * @param feature The feature
+ * @param extensionName The extension name
+ * @throws IllegalStateException If post processing failed
+ */
+ void postProcess(Feature feature, String extensionName);
+}
Propchange: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureExtensionHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/process/FeatureExtensionHandler.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url