Author: sseifert Date: Tue Jul 14 09:10:39 2015 New Revision: 1690881 URL: http://svn.apache.org/r1690881 Log: SLING-4879 move resolver/replace logic to separate class ModelResolverUtility
Added: sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/ModelResolveUtility.java (with props) sling/trunk/tooling/support/provisioning-model/src/test/java/org/apache/sling/provisioning/model/ModelResolveUtilityReplaceTest.java - copied, changed from r1690877, sling/trunk/tooling/support/provisioning-model/src/test/java/org/apache/sling/provisioning/model/ModelUtilityReplaceTest.java Removed: sling/trunk/tooling/support/provisioning-model/src/test/java/org/apache/sling/provisioning/model/ModelUtilityReplaceTest.java Modified: sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/EffectiveModelProcessor.java sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/ModelUtility.java Modified: sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/EffectiveModelProcessor.java URL: http://svn.apache.org/viewvc/sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/EffectiveModelProcessor.java?rev=1690881&r1=1690880&r2=1690881&view=diff ============================================================================== --- sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/EffectiveModelProcessor.java (original) +++ sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/EffectiveModelProcessor.java Tue Jul 14 09:10:39 2015 @@ -18,11 +18,16 @@ */ package org.apache.sling.provisioning.model; +import static org.apache.sling.provisioning.model.ModelResolveUtility.getProcessedConfiguration; +import static org.apache.sling.provisioning.model.ModelResolveUtility.replace; +import static org.apache.sling.provisioning.model.ModelResolveUtility.resolveArtifactVersion; + import java.util.Map.Entry; import org.apache.sling.provisioning.model.ModelUtility.ResolverOptions; import org.apache.sling.provisioning.model.ModelUtility.VariableResolver; + class EffectiveModelProcessor extends ModelProcessor { private final ResolverOptions options; @@ -36,12 +41,12 @@ class EffectiveModelProcessor extends Mo @Override protected Artifact processArtifact(Artifact artifact, Feature newFeature, RunMode newRunMode) { - final String groupId = ModelUtility.replace(newFeature, artifact.getGroupId(), options.getVariableResolver()); - final String artifactId = ModelUtility.replace(newFeature, artifact.getArtifactId(), options.getVariableResolver()); - final String version = ModelUtility.replace(newFeature, artifact.getVersion(), options.getVariableResolver()); - final String classifier = ModelUtility.replace(newFeature, artifact.getClassifier(), options.getVariableResolver()); - final String type = ModelUtility.replace(newFeature, artifact.getType(), options.getVariableResolver()); - final String resolvedVersion = ModelUtility.resolveArtifactVersion(groupId, artifactId, version, classifier, type, + final String groupId = replace(newFeature, artifact.getGroupId(), options.getVariableResolver()); + final String artifactId = replace(newFeature, artifact.getArtifactId(), options.getVariableResolver()); + final String version = replace(newFeature, artifact.getVersion(), options.getVariableResolver()); + final String classifier = replace(newFeature, artifact.getClassifier(), options.getVariableResolver()); + final String type = replace(newFeature, artifact.getType(), options.getVariableResolver()); + final String resolvedVersion = resolveArtifactVersion(groupId, artifactId, version, classifier, type, options.getArtifactVersionResolver()); return new Artifact(groupId, artifactId, resolvedVersion, classifier, type); } @@ -49,7 +54,7 @@ class EffectiveModelProcessor extends Mo @Override protected Configuration processConfiguration(Configuration config, Feature newFeature, RunMode newRunMode) { Configuration newConfig = new Configuration(config.getPid(), config.getFactoryPid()); - ModelUtility.getProcessedConfiguration(newFeature, newConfig, config, options.getVariableResolver()); + getProcessedConfiguration(newFeature, newConfig, config, options.getVariableResolver()); return newConfig; } @@ -57,7 +62,7 @@ class EffectiveModelProcessor extends Mo protected KeyValueMap<String> processSettings(KeyValueMap<String> settings, final Feature newFeature, final RunMode newRunMode) { KeyValueMap<String> newSettings = new KeyValueMap<String>(); for (final Entry<String, String> entry : settings) { - newSettings.put(entry.getKey(), ModelUtility.replace(newFeature, entry.getValue(), + newSettings.put(entry.getKey(), replace(newFeature, entry.getValue(), new VariableResolver() { @Override public String resolve(final Feature feature, final String name) { Added: sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/ModelResolveUtility.java URL: http://svn.apache.org/viewvc/sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/ModelResolveUtility.java?rev=1690881&view=auto ============================================================================== --- sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/ModelResolveUtility.java (added) +++ sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/ModelResolveUtility.java Tue Jul 14 09:10:39 2015 @@ -0,0 +1,190 @@ +/* + * 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.provisioning.model; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.LineNumberReader; +import java.io.StringReader; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.Properties; + +import org.apache.felix.cm.file.ConfigurationHandler; +import org.apache.sling.provisioning.model.ModelUtility.ArtifactVersionResolver; +import org.apache.sling.provisioning.model.ModelUtility.VariableResolver; + +class ModelResolveUtility { + + /** + * Replace properties in the string. + * + * @param feature The feature + * @param v The variable name + * @param resolver Optional resolver + * @result The value of the variable + * @throws IllegalArgumentException If variable can't be found. + */ + static String replace(final Feature feature, final String v, final VariableResolver resolver) { + if ( v == null ) { + return null; + } + String msg = v; + // check for variables + int pos = -1; + int start = 0; + while ( ( pos = msg.indexOf('$', start) ) != -1 ) { + boolean escapedVariable = (pos > 0 && msg.charAt(pos - 1) == '\\'); + if ( msg.length() > pos && msg.charAt(pos + 1) == '{' && (pos == 0 || msg.charAt(pos - 1) != '$') ) { + final int endPos = msg.indexOf('}', pos); + if ( endPos != -1 ) { + final String name = msg.substring(pos + 2, endPos); + final String value; + if (escapedVariable) { + value = "\\${" + name + "}"; + } else if ( resolver != null ) { + value = resolver.resolve(feature, name); + } else { + value = feature.getVariables().get(name); + } + if ( value == null ) { + throw new IllegalArgumentException("Unknown variable: " + name); + } + int startPos = escapedVariable ? pos - 1 : pos; + msg = msg.substring(0, startPos) + value + msg.substring(endPos + 1); + } + } + start = pos + 1; + } + return msg; + } + + /** + * Tries to resolves artifact version via {@link ArtifactVersionResolver} if no version was defined in provisioning file. + * @param groupId Group ID + * @param artifactId Artifact ID + * @param version Version + * @param classifier Classifier + * @param type Type + * @param artifactVersionResolver Artifact Version Resolver (may be null) + * @return Version to use for this artifact + */ + static String resolveArtifactVersion(final String groupId, final String artifactId, final String version, + final String classifier, final String type, ArtifactVersionResolver artifactVersionResolver) { + if (artifactVersionResolver != null && "LATEST".equals(version)) { + String newVersion = artifactVersionResolver.resolve(new Artifact(groupId, artifactId, version, classifier, type)); + if (newVersion != null) { + return newVersion; + } + } + return version; + } + + /** + * Replaces variables in configuration. + * @param feature Feature + * @param newConfig New configuration with replaced variables + * @param config Source configuration which may contain variable placeholders + * @param resolver Variable resolver + */ + static void getProcessedConfiguration( + final Feature feature, + final Configuration newConfig, + final Configuration config, + final VariableResolver resolver) { + newConfig.setComment(config.getComment()); + newConfig.setLocation(config.getLocation()); + + // check for raw configuration + String rawConfig = (String)config.getProperties().get(ModelConstants.CFG_UNPROCESSED); + if ( rawConfig != null ) { + if ( resolver != null ) { + rawConfig = replace(feature, rawConfig, resolver); + } + if ( config.isSpecial() ) { + newConfig.getProperties().put(config.getPid(), rawConfig); + } else { + final String format = (String)config.getProperties().get(ModelConstants.CFG_UNPROCESSED_FORMAT); + + if ( ModelConstants.CFG_FORMAT_PROPERTIES.equals(format) ) { + // properties + final Properties props = new Properties(); + try { + props.load(new StringReader(rawConfig)); + } catch ( final IOException ioe) { + throw new IllegalArgumentException("Unable to read configuration properties.", ioe); + } + final Enumeration<Object> i = props.keys(); + while ( i.hasMoreElements() ) { + final String key = (String)i.nextElement(); + newConfig.getProperties().put(key, props.get(key)); + } + } else { + // Apache Felix CA format + // the raw format might have comments, we have to remove them first + final StringBuilder sb = new StringBuilder(); + try { + final LineNumberReader lnr = new LineNumberReader(new StringReader(rawConfig)); + String line = null; + while ((line = lnr.readLine()) != null ) { + line = line.trim(); + if ( line.isEmpty() || line.startsWith("#")) { + continue; + } + sb.append(line); + sb.append('\n'); + } + } catch ( final IOException ioe) { + throw new IllegalArgumentException("Unable to read configuration properties: " + config, ioe); + } + + ByteArrayInputStream bais = null; + try { + bais = new ByteArrayInputStream(sb.toString().getBytes("UTF-8")); + @SuppressWarnings("unchecked") + final Dictionary<String, Object> props = ConfigurationHandler.read(bais); + final Enumeration<String> i = props.keys(); + while ( i.hasMoreElements() ) { + final String key = i.nextElement(); + newConfig.getProperties().put(key, props.get(key)); + } + } catch ( final IOException ioe) { + throw new IllegalArgumentException("Unable to read configuration properties: " + config, ioe); + } finally { + if ( bais != null ) { + try { + bais.close(); + } catch ( final IOException ignore ) { + // ignore + } + } + } + } + } + } else { + // simply copy + final Enumeration<String> i = config.getProperties().keys(); + while ( i.hasMoreElements() ) { + final String key = i.nextElement(); + newConfig.getProperties().put(key, config.getProperties().get(key)); + } + } + } + +} Propchange: sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/ModelResolveUtility.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/ModelResolveUtility.java ------------------------------------------------------------------------------ --- svn:keywords (added) +++ svn:keywords Tue Jul 14 09:10:39 2015 @@ -0,0 +1 @@ +LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author Propchange: sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/ModelResolveUtility.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/ModelUtility.java URL: http://svn.apache.org/viewvc/sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/ModelUtility.java?rev=1690881&r1=1690880&r2=1690881&view=diff ============================================================================== --- sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/ModelUtility.java (original) +++ sling/trunk/tooling/support/provisioning-model/src/main/java/org/apache/sling/provisioning/model/ModelUtility.java Tue Jul 14 09:10:39 2015 @@ -16,22 +16,15 @@ */ package org.apache.sling.provisioning.model; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.LineNumberReader; -import java.io.StringReader; +import static org.apache.sling.provisioning.model.ModelResolveUtility.getProcessedConfiguration; + import java.util.Arrays; -import java.util.Dictionary; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import java.util.Properties; import java.util.Set; -import org.apache.felix.cm.file.ConfigurationHandler; - - /** * Merge two models */ @@ -349,70 +342,6 @@ public abstract class ModelUtility { } /** - * Replace properties in the string. - * - * @param feature The feature - * @param v The variable name - * @param resolver Optional resolver - * @result The value of the variable - * @throws IllegalArgumentException If variable can't be found. - */ - static String replace(final Feature feature, final String v, final VariableResolver resolver) { - if ( v == null ) { - return null; - } - String msg = v; - // check for variables - int pos = -1; - int start = 0; - while ( ( pos = msg.indexOf('$', start) ) != -1 ) { - boolean escapedVariable = (pos > 0 && msg.charAt(pos - 1) == '\\'); - if ( msg.length() > pos && msg.charAt(pos + 1) == '{' && (pos == 0 || msg.charAt(pos - 1) != '$') ) { - final int endPos = msg.indexOf('}', pos); - if ( endPos != -1 ) { - final String name = msg.substring(pos + 2, endPos); - final String value; - if (escapedVariable) { - value = "\\${" + name + "}"; - } else if ( resolver != null ) { - value = resolver.resolve(feature, name); - } else { - value = feature.getVariables().get(name); - } - if ( value == null ) { - throw new IllegalArgumentException("Unknown variable: " + name); - } - int startPos = escapedVariable ? pos - 1 : pos; - msg = msg.substring(0, startPos) + value + msg.substring(endPos + 1); - } - } - start = pos + 1; - } - return msg; - } - - /** - * Tries to resolves artifact version via {@link ArtifactVersionResolver} if no version was defined in provisioning file. - * @param groupId Group ID - * @param artifactId Artifact ID - * @param version Version - * @param classifier Classifier - * @param type Type - * @param artifactVersionResolver Artifact Version Resolver (may be null) - * @return Version to use for this artifact - */ - static String resolveArtifactVersion(final String groupId, final String artifactId, final String version, - final String classifier, final String type, ArtifactVersionResolver artifactVersionResolver) { - if (artifactVersionResolver != null && "LATEST".equals(version)) { - String newVersion = artifactVersionResolver.resolve(new Artifact(groupId, artifactId, version, classifier, type)); - if (newVersion != null) { - return newVersion; - } - } - return version; - } - - /** * Validates the model. * @param model The model to validate * @return A map with errors or {@code null}. @@ -487,88 +416,4 @@ public abstract class ModelUtility { return errors; } - static void getProcessedConfiguration( - final Feature feature, - final Configuration newConfig, - final Configuration config, - final VariableResolver resolver) { - newConfig.setComment(config.getComment()); - newConfig.setLocation(config.getLocation()); - - // check for raw configuration - String rawConfig = (String)config.getProperties().get(ModelConstants.CFG_UNPROCESSED); - if ( rawConfig != null ) { - if ( resolver != null ) { - rawConfig = replace(feature, rawConfig, resolver); - } - if ( config.isSpecial() ) { - newConfig.getProperties().put(config.getPid(), rawConfig); - } else { - final String format = (String)config.getProperties().get(ModelConstants.CFG_UNPROCESSED_FORMAT); - - if ( ModelConstants.CFG_FORMAT_PROPERTIES.equals(format) ) { - // properties - final Properties props = new Properties(); - try { - props.load(new StringReader(rawConfig)); - } catch ( final IOException ioe) { - throw new IllegalArgumentException("Unable to read configuration properties.", ioe); - } - final Enumeration<Object> i = props.keys(); - while ( i.hasMoreElements() ) { - final String key = (String)i.nextElement(); - newConfig.getProperties().put(key, props.get(key)); - } - } else { - // Apache Felix CA format - // the raw format might have comments, we have to remove them first - final StringBuilder sb = new StringBuilder(); - try { - final LineNumberReader lnr = new LineNumberReader(new StringReader(rawConfig)); - String line = null; - while ((line = lnr.readLine()) != null ) { - line = line.trim(); - if ( line.isEmpty() || line.startsWith("#")) { - continue; - } - sb.append(line); - sb.append('\n'); - } - } catch ( final IOException ioe) { - throw new IllegalArgumentException("Unable to read configuration properties: " + config, ioe); - } - - ByteArrayInputStream bais = null; - try { - bais = new ByteArrayInputStream(sb.toString().getBytes("UTF-8")); - @SuppressWarnings("unchecked") - final Dictionary<String, Object> props = ConfigurationHandler.read(bais); - final Enumeration<String> i = props.keys(); - while ( i.hasMoreElements() ) { - final String key = i.nextElement(); - newConfig.getProperties().put(key, props.get(key)); - } - } catch ( final IOException ioe) { - throw new IllegalArgumentException("Unable to read configuration properties: " + config, ioe); - } finally { - if ( bais != null ) { - try { - bais.close(); - } catch ( final IOException ignore ) { - // ignore - } - } - } - } - } - } else { - // simply copy - final Enumeration<String> i = config.getProperties().keys(); - while ( i.hasMoreElements() ) { - final String key = i.nextElement(); - newConfig.getProperties().put(key, config.getProperties().get(key)); - } - } - } - } Copied: sling/trunk/tooling/support/provisioning-model/src/test/java/org/apache/sling/provisioning/model/ModelResolveUtilityReplaceTest.java (from r1690877, sling/trunk/tooling/support/provisioning-model/src/test/java/org/apache/sling/provisioning/model/ModelUtilityReplaceTest.java) URL: http://svn.apache.org/viewvc/sling/trunk/tooling/support/provisioning-model/src/test/java/org/apache/sling/provisioning/model/ModelResolveUtilityReplaceTest.java?p2=sling/trunk/tooling/support/provisioning-model/src/test/java/org/apache/sling/provisioning/model/ModelResolveUtilityReplaceTest.java&p1=sling/trunk/tooling/support/provisioning-model/src/test/java/org/apache/sling/provisioning/model/ModelUtilityReplaceTest.java&r1=1690877&r2=1690881&rev=1690881&view=diff ============================================================================== --- sling/trunk/tooling/support/provisioning-model/src/test/java/org/apache/sling/provisioning/model/ModelUtilityReplaceTest.java (original) +++ sling/trunk/tooling/support/provisioning-model/src/test/java/org/apache/sling/provisioning/model/ModelResolveUtilityReplaceTest.java Tue Jul 14 09:10:39 2015 @@ -16,12 +16,13 @@ */ package org.apache.sling.provisioning.model; +import static org.apache.sling.provisioning.model.ModelResolveUtility.replace; import static org.junit.Assert.assertEquals; import org.apache.sling.provisioning.model.ModelUtility.VariableResolver; import org.junit.Test; -public class ModelUtilityReplaceTest { +public class ModelResolveUtilityReplaceTest { private static final Feature TEST_FEATURE = new Feature("testFeature"); static { @@ -31,34 +32,34 @@ public class ModelUtilityReplaceTest { @Test public void testNoReplace() { - assertEquals("nothing to replace", ModelUtility.replace(TEST_FEATURE, "nothing to replace", null)); + assertEquals("nothing to replace", replace(TEST_FEATURE, "nothing to replace", null)); } @Test public void testOneReplace() { - assertEquals("one value1 variable", ModelUtility.replace(TEST_FEATURE, "one ${var1} variable", null)); - assertEquals("value1 one variable", ModelUtility.replace(TEST_FEATURE, "${var1} one variable", null)); - assertEquals("value1 one variable value1", ModelUtility.replace(TEST_FEATURE, "${var1} one variable ${var1}", null)); + assertEquals("one value1 variable", replace(TEST_FEATURE, "one ${var1} variable", null)); + assertEquals("value1 one variable", replace(TEST_FEATURE, "${var1} one variable", null)); + assertEquals("value1 one variable value1", replace(TEST_FEATURE, "${var1} one variable ${var1}", null)); } @Test public void testTwoReplaces() { - assertEquals("two value1 variables value2", ModelUtility.replace(TEST_FEATURE, "two ${var1} variables ${var2}", null)); - assertEquals("value1value2 two variables", ModelUtility.replace(TEST_FEATURE, "${var1}${var2} two variables", null)); - assertEquals("value2 two variables value1", ModelUtility.replace(TEST_FEATURE, "${var2} two variables ${var1}", null)); + assertEquals("two value1 variables value2", replace(TEST_FEATURE, "two ${var1} variables ${var2}", null)); + assertEquals("value1value2 two variables", replace(TEST_FEATURE, "${var1}${var2} two variables", null)); + assertEquals("value2 two variables value1", replace(TEST_FEATURE, "${var2} two variables ${var1}", null)); } @Test(expected = IllegalArgumentException.class) public void testInvalidVariable() { - assertEquals("one value1 variable", ModelUtility.replace(TEST_FEATURE, "one ${var99} variable", null)); + assertEquals("one value1 variable", replace(TEST_FEATURE, "one ${var99} variable", null)); } @Test public void testEscapedVariable() { - assertEquals("escaped \\${var99} variable", ModelUtility.replace(TEST_FEATURE, "escaped \\${var99} variable", null)); - assertEquals("\\${var99} escaped variable", ModelUtility.replace(TEST_FEATURE, "\\${var99} escaped variable", null)); - assertEquals("escaped variable \\${var99}", ModelUtility.replace(TEST_FEATURE, "escaped variable \\${var99}", null)); - assertEquals("escaped \\${var1} variable value2", ModelUtility.replace(TEST_FEATURE, "escaped \\${var1} variable ${var2}", null)); + assertEquals("escaped \\${var99} variable", replace(TEST_FEATURE, "escaped \\${var99} variable", null)); + assertEquals("\\${var99} escaped variable", replace(TEST_FEATURE, "\\${var99} escaped variable", null)); + assertEquals("escaped variable \\${var99}", replace(TEST_FEATURE, "escaped variable \\${var99}", null)); + assertEquals("escaped \\${var1} variable value2", replace(TEST_FEATURE, "escaped \\${var1} variable ${var2}", null)); } @Test @@ -69,9 +70,9 @@ public class ModelUtilityReplaceTest { return name.toUpperCase(); } }; - assertEquals("one VAR1 variable", ModelUtility.replace(TEST_FEATURE, "one ${var1} variable", resolver)); - assertEquals("VAR1 one variable", ModelUtility.replace(TEST_FEATURE, "${var1} one variable", resolver)); - assertEquals("VAR1 one variable VAR2", ModelUtility.replace(TEST_FEATURE, "${var1} one variable ${var2}", resolver)); + assertEquals("one VAR1 variable", replace(TEST_FEATURE, "one ${var1} variable", resolver)); + assertEquals("VAR1 one variable", replace(TEST_FEATURE, "${var1} one variable", resolver)); + assertEquals("VAR1 one variable VAR2", replace(TEST_FEATURE, "${var1} one variable ${var2}", resolver)); } }