1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.basepom.mojo.propertyhelper;
16
17 import static com.google.common.base.Preconditions.checkNotNull;
18 import static java.lang.String.format;
19 import static org.basepom.mojo.propertyhelper.IgnoreWarnFail.checkIgnoreWarnFailState;
20
21 import java.io.IOException;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.function.Function;
25 import java.util.regex.Matcher;
26 import java.util.regex.Pattern;
27
28 import com.google.common.collect.ImmutableList;
29 import org.apache.maven.model.Model;
30 import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
31 import org.codehaus.plexus.interpolation.InterpolationException;
32 import org.codehaus.plexus.interpolation.Interpolator;
33 import org.codehaus.plexus.interpolation.MapBasedValueSource;
34 import org.codehaus.plexus.interpolation.ObjectBasedValueSource;
35 import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
36 import org.codehaus.plexus.interpolation.PrefixedValueSourceWrapper;
37 import org.codehaus.plexus.interpolation.PropertiesBasedValueSource;
38 import org.codehaus.plexus.interpolation.StringSearchInterpolator;
39
40 public final class InterpolatorFactory {
41
42 private static final List<String> SYNONYM_PREFIXES = ImmutableList.of("project", "pom");
43 private static final String PREFIX = "@{";
44 private static final String POSTFIX = "}";
45
46 private final Model model;
47
48 public InterpolatorFactory(final Model model) {
49 this.model = checkNotNull(model, "model is null");
50 }
51
52 public static InterpolatorFactory forTesting() {
53 return new InterpolatorFactory(new Model());
54 }
55
56 public Function<String, String> interpolate(String name, final IgnoreWarnFail onMissingField, final Map<String, String> properties) {
57 return value -> {
58 try {
59 return interpolate(name, value, onMissingField, properties);
60 } catch (Exception e) {
61 throw Sneaky.throwAnyway(e);
62 }
63 };
64 }
65
66 private String interpolate(final String name, final String value, final IgnoreWarnFail onMissingField, final Map<String, String> properties)
67 throws IOException, InterpolationException {
68 checkNotNull(name, "name is null");
69 checkNotNull(value, "value is null");
70 checkNotNull(properties, "properties is null");
71
72 final Interpolator interpolator = new StringSearchInterpolator(PREFIX, POSTFIX);
73 interpolator.addValueSource(new EnvarBasedValueSource());
74 interpolator.addValueSource(new PropertiesBasedValueSource(System.getProperties()));
75
76 interpolator.addValueSource(new PrefixedValueSourceWrapper(new ObjectBasedValueSource(model),
77 SYNONYM_PREFIXES,
78 true));
79
80 interpolator.addValueSource(new PrefixedValueSourceWrapper(new PropertiesBasedValueSource(model.getProperties()),
81 SYNONYM_PREFIXES,
82 true));
83
84 interpolator.addValueSource(new MapBasedValueSource(properties));
85
86 final String result = interpolator.interpolate(value, new PrefixAwareRecursionInterceptor(SYNONYM_PREFIXES, true));
87
88 Matcher matcher = Pattern.compile(Pattern.quote(PREFIX) + ".*?" + Pattern.quote(POSTFIX)).matcher(result);
89
90 checkIgnoreWarnFailState(!matcher.find(), onMissingField,
91 () -> format("template %s evaluated to %s", value, result),
92 () -> format("could not evaluate %s! (result is %s)", value, result));
93
94 return matcher.replaceAll("");
95 }
96 }