1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.model.interpolation;
20
21 import javax.inject.Inject;
22
23 import java.io.File;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Properties;
30
31 import org.apache.maven.model.Model;
32 import org.apache.maven.model.building.ModelBuildingRequest;
33 import org.apache.maven.model.building.ModelProblemCollector;
34 import org.apache.maven.model.path.PathTranslator;
35 import org.apache.maven.model.path.UrlNormalizer;
36 import org.codehaus.plexus.interpolation.AbstractValueSource;
37 import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
38 import org.codehaus.plexus.interpolation.MapBasedValueSource;
39 import org.codehaus.plexus.interpolation.ObjectBasedValueSource;
40 import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
41 import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
42 import org.codehaus.plexus.interpolation.PrefixedValueSourceWrapper;
43 import org.codehaus.plexus.interpolation.RecursionInterceptor;
44 import org.codehaus.plexus.interpolation.ValueSource;
45
46
47
48
49
50
51 @Deprecated(since = "4.0.0")
52 public abstract class AbstractStringBasedModelInterpolator implements ModelInterpolator {
53
54
55
56
57
58 private static final String FULL_EXTERNAL_INTERPOLATION_PROPERTY = "maven.model.dependencyInterpolation.full";
59
60 private static final List<String> PROJECT_PREFIXES = Arrays.asList("pom.", "project.");
61
62 private static final Collection<String> TRANSLATED_PATH_EXPRESSIONS;
63
64 static {
65 Collection<String> translatedPrefixes = new HashSet<>();
66
67
68
69
70
71
72 translatedPrefixes.add("build.directory");
73 translatedPrefixes.add("build.outputDirectory");
74 translatedPrefixes.add("build.testOutputDirectory");
75 translatedPrefixes.add("build.sourceDirectory");
76 translatedPrefixes.add("build.testSourceDirectory");
77 translatedPrefixes.add("build.scriptSourceDirectory");
78 translatedPrefixes.add("reporting.outputDirectory");
79
80 TRANSLATED_PATH_EXPRESSIONS = translatedPrefixes;
81 }
82
83 @Inject
84 private PathTranslator pathTranslator;
85
86 @Inject
87 private UrlNormalizer urlNormalizer;
88
89 @Inject
90 private ModelVersionProcessor versionProcessor;
91
92 public AbstractStringBasedModelInterpolator() {}
93
94 public AbstractStringBasedModelInterpolator setPathTranslator(PathTranslator pathTranslator) {
95 this.pathTranslator = pathTranslator;
96 return this;
97 }
98
99 public AbstractStringBasedModelInterpolator setUrlNormalizer(UrlNormalizer urlNormalizer) {
100 this.urlNormalizer = urlNormalizer;
101 return this;
102 }
103
104 public AbstractStringBasedModelInterpolator setVersionPropertiesProcessor(ModelVersionProcessor processor) {
105 this.versionProcessor = processor;
106 return this;
107 }
108
109 protected List<ValueSource> createValueSources(
110 final Model model,
111 final File projectDir,
112 final ModelBuildingRequest config,
113 final ModelProblemCollector problems) {
114 Properties modelProperties = model.getProperties();
115
116 ValueSource modelValueSource1 = new PrefixedObjectValueSource(PROJECT_PREFIXES, model, false);
117 if (config.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
118 modelValueSource1 = new ProblemDetectingValueSource(modelValueSource1, "pom.", "project.", problems);
119 }
120
121 ValueSource modelValueSource2 = new ObjectBasedValueSource(model);
122 if (config.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
123 modelValueSource2 = new ProblemDetectingValueSource(modelValueSource2, "", "project.", problems);
124 }
125
126
127 List<ValueSource> valueSources = new ArrayList<>(9);
128
129 if (projectDir != null) {
130 ValueSource basedirValueSource = new PrefixedValueSourceWrapper(
131 new AbstractValueSource(false) {
132 @Override
133 public Object getValue(String expression) {
134 if ("basedir".equals(expression)) {
135 return projectDir.getAbsolutePath();
136 }
137 return null;
138 }
139 },
140 PROJECT_PREFIXES,
141 true);
142 valueSources.add(basedirValueSource);
143
144 ValueSource baseUriValueSource = new PrefixedValueSourceWrapper(
145 new AbstractValueSource(false) {
146 @Override
147 public Object getValue(String expression) {
148 if ("baseUri".equals(expression)) {
149 return projectDir
150 .getAbsoluteFile()
151 .toPath()
152 .toUri()
153 .toASCIIString();
154 }
155 return null;
156 }
157 },
158 PROJECT_PREFIXES,
159 false);
160 valueSources.add(baseUriValueSource);
161 valueSources.add(new BuildTimestampValueSource(config.getBuildStartTime(), modelProperties));
162 }
163
164 valueSources.add(modelValueSource1);
165
166
167
168
169
170
171
172 boolean restricted = restrictExternalModelInterpolation(config);
173
174 ValueSource userPropertiesValueSource = new MapBasedValueSource(config.getUserProperties());
175 valueSources.add(restricted ? restrictToSafeExpressions(userPropertiesValueSource) : userPropertiesValueSource);
176
177
178
179 versionProcessor.overwriteModelProperties(modelProperties, config);
180 valueSources.add(new MapBasedValueSource(modelProperties));
181
182 ValueSource systemPropertiesValueSource = new MapBasedValueSource(config.getSystemProperties());
183 valueSources.add(
184 restricted ? restrictToSafeExpressions(systemPropertiesValueSource) : systemPropertiesValueSource);
185
186 if (!restricted) {
187 valueSources.add(new AbstractValueSource(false) {
188 @Override
189 public Object getValue(String expression) {
190 return config.getSystemProperties().getProperty("env." + expression);
191 }
192 });
193 }
194
195 valueSources.add(modelValueSource2);
196
197 return valueSources;
198 }
199
200 private static boolean restrictExternalModelInterpolation(ModelBuildingRequest config) {
201 return config.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0
202 && !Boolean.parseBoolean(config.getSystemProperties().getProperty(FULL_EXTERNAL_INTERPOLATION_PROPERTY))
203 && !Boolean.parseBoolean(config.getUserProperties().getProperty(FULL_EXTERNAL_INTERPOLATION_PROPERTY));
204 }
205
206 private static ValueSource restrictToSafeExpressions(ValueSource source) {
207 return new AbstractValueSource(false) {
208 @Override
209 public Object getValue(String expression) {
210 return isSafeExternalExpression(expression) ? source.getValue(expression) : null;
211 }
212 };
213 }
214
215
216
217
218
219
220 private static boolean isSafeExternalExpression(String expression) {
221 return expression.startsWith("java.")
222 || expression.startsWith("os.")
223 || expression.startsWith("maven.")
224 || "file.separator".equals(expression)
225 || "path.separator".equals(expression)
226 || "line.separator".equals(expression)
227 || "revision".equals(expression)
228 || "changelist".equals(expression)
229 || "sha1".equals(expression);
230 }
231
232 protected List<? extends InterpolationPostProcessor> createPostProcessors(
233 final Model model, final File projectDir, final ModelBuildingRequest config) {
234 List<InterpolationPostProcessor> processors = new ArrayList<>(2);
235 if (projectDir != null) {
236 processors.add(new PathTranslatingPostProcessor(
237 PROJECT_PREFIXES, TRANSLATED_PATH_EXPRESSIONS,
238 projectDir, pathTranslator));
239 }
240 processors.add(new UrlNormalizingPostProcessor(urlNormalizer));
241 return processors;
242 }
243
244 protected RecursionInterceptor createRecursionInterceptor() {
245 return new PrefixAwareRecursionInterceptor(PROJECT_PREFIXES);
246 }
247 }