001/* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014 015package org.basepom.mojo.propertyhelper; 016 017import static com.google.common.base.Preconditions.checkNotNull; 018import static java.lang.String.format; 019import static org.basepom.mojo.propertyhelper.IgnoreWarnFail.checkIgnoreWarnFailState; 020 021import java.io.IOException; 022import java.util.List; 023import java.util.Map; 024import java.util.function.Function; 025import java.util.regex.Matcher; 026import java.util.regex.Pattern; 027 028import com.google.common.collect.ImmutableList; 029import org.apache.maven.model.Model; 030import org.codehaus.plexus.interpolation.EnvarBasedValueSource; 031import org.codehaus.plexus.interpolation.InterpolationException; 032import org.codehaus.plexus.interpolation.Interpolator; 033import org.codehaus.plexus.interpolation.MapBasedValueSource; 034import org.codehaus.plexus.interpolation.ObjectBasedValueSource; 035import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor; 036import org.codehaus.plexus.interpolation.PrefixedValueSourceWrapper; 037import org.codehaus.plexus.interpolation.PropertiesBasedValueSource; 038import org.codehaus.plexus.interpolation.StringSearchInterpolator; 039 040public final class InterpolatorFactory { 041 042 private static final List<String> SYNONYM_PREFIXES = ImmutableList.of("project", "pom"); 043 private static final String PREFIX = "@{"; 044 private static final String POSTFIX = "}"; 045 046 private final Model model; 047 048 public InterpolatorFactory(final Model model) { 049 this.model = checkNotNull(model, "model is null"); 050 } 051 052 public static InterpolatorFactory forTesting() { 053 return new InterpolatorFactory(new Model()); 054 } 055 056 public Function<String, String> interpolate(String name, final IgnoreWarnFail onMissingField, final Map<String, String> properties) { 057 return value -> { 058 try { 059 return interpolate(name, value, onMissingField, properties); 060 } catch (Exception e) { 061 throw Sneaky.throwAnyway(e); 062 } 063 }; 064 } 065 066 private String interpolate(final String name, final String value, final IgnoreWarnFail onMissingField, final Map<String, String> properties) 067 throws IOException, InterpolationException { 068 checkNotNull(name, "name is null"); 069 checkNotNull(value, "value is null"); 070 checkNotNull(properties, "properties is null"); 071 072 final Interpolator interpolator = new StringSearchInterpolator(PREFIX, POSTFIX); 073 interpolator.addValueSource(new EnvarBasedValueSource()); 074 interpolator.addValueSource(new PropertiesBasedValueSource(System.getProperties())); 075 076 interpolator.addValueSource(new PrefixedValueSourceWrapper(new ObjectBasedValueSource(model), 077 SYNONYM_PREFIXES, 078 true)); 079 080 interpolator.addValueSource(new PrefixedValueSourceWrapper(new PropertiesBasedValueSource(model.getProperties()), 081 SYNONYM_PREFIXES, 082 true)); 083 084 interpolator.addValueSource(new MapBasedValueSource(properties)); 085 086 final String result = interpolator.interpolate(value, new PrefixAwareRecursionInterceptor(SYNONYM_PREFIXES, true)); 087 088 Matcher matcher = Pattern.compile(Pattern.quote(PREFIX) + ".*?" + Pattern.quote(POSTFIX)).matcher(result); 089 090 checkIgnoreWarnFailState(!matcher.find(), onMissingField, 091 () -> format("template %s evaluated to %s", value, result), 092 () -> format("could not evaluate %s! (result is %s)", value, result)); 093 094 return matcher.replaceAll(""); 095 } 096}