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.net.URI;
25 import java.nio.file.Path;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Map;
33
34 import org.apache.maven.api.model.Model;
35 import org.apache.maven.model.building.ModelBuildingRequest;
36 import org.apache.maven.model.building.ModelProblemCollector;
37 import org.apache.maven.model.path.PathTranslator;
38 import org.apache.maven.model.path.UrlNormalizer;
39 import org.apache.maven.model.root.RootLocator;
40 import org.codehaus.plexus.interpolation.AbstractValueSource;
41 import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
42 import org.codehaus.plexus.interpolation.MapBasedValueSource;
43 import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
44 import org.codehaus.plexus.interpolation.PrefixedValueSourceWrapper;
45 import org.codehaus.plexus.interpolation.RecursionInterceptor;
46 import org.codehaus.plexus.interpolation.ValueSource;
47
48
49
50
51
52 public abstract class AbstractStringBasedModelInterpolator implements ModelInterpolator {
53 private static final String PREFIX_PROJECT = "project.";
54 private static final String PREFIX_POM = "pom.";
55 private static final List<String> PROJECT_PREFIXES_3_1 = Arrays.asList(PREFIX_POM, PREFIX_PROJECT);
56 private static final List<String> PROJECT_PREFIXES_4_0 = Collections.singletonList(PREFIX_PROJECT);
57
58 private static final Collection<String> TRANSLATED_PATH_EXPRESSIONS;
59
60 static {
61 Collection<String> translatedPrefixes = new HashSet<>();
62
63
64
65
66
67
68 translatedPrefixes.add("build.directory");
69 translatedPrefixes.add("build.outputDirectory");
70 translatedPrefixes.add("build.testOutputDirectory");
71 translatedPrefixes.add("build.sourceDirectory");
72 translatedPrefixes.add("build.testSourceDirectory");
73 translatedPrefixes.add("build.scriptSourceDirectory");
74 translatedPrefixes.add("reporting.outputDirectory");
75
76 TRANSLATED_PATH_EXPRESSIONS = translatedPrefixes;
77 }
78
79 private final PathTranslator pathTranslator;
80 private final UrlNormalizer urlNormalizer;
81
82 private final RootLocator rootLocator;
83
84 @Inject
85 public AbstractStringBasedModelInterpolator(
86 PathTranslator pathTranslator, UrlNormalizer urlNormalizer, RootLocator rootLocator) {
87 this.pathTranslator = pathTranslator;
88 this.urlNormalizer = urlNormalizer;
89 this.rootLocator = rootLocator;
90 }
91
92 @Override
93 public org.apache.maven.model.Model interpolateModel(
94 org.apache.maven.model.Model model,
95 File projectDir,
96 ModelBuildingRequest request,
97 ModelProblemCollector problems) {
98 return new org.apache.maven.model.Model(interpolateModel(model.getDelegate(), projectDir, request, problems));
99 }
100
101 protected List<String> getProjectPrefixes(ModelBuildingRequest config) {
102 return config.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_4_0
103 ? PROJECT_PREFIXES_4_0
104 : PROJECT_PREFIXES_3_1;
105 }
106
107 protected List<ValueSource> createValueSources(
108 final Model model,
109 final File projectDir,
110 final ModelBuildingRequest config,
111 ModelProblemCollector problems) {
112 Map<String, String> modelProperties = model.getProperties();
113
114 ValueSource projectPrefixValueSource;
115 ValueSource prefixlessObjectBasedValueSource;
116 if (config.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_4_0) {
117 projectPrefixValueSource = new PrefixedObjectValueSource(PROJECT_PREFIXES_4_0, model, false);
118 prefixlessObjectBasedValueSource = new ObjectBasedValueSource(model);
119 } else {
120 projectPrefixValueSource = new PrefixedObjectValueSource(PROJECT_PREFIXES_3_1, model, false);
121 if (config.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
122 projectPrefixValueSource =
123 new ProblemDetectingValueSource(projectPrefixValueSource, PREFIX_POM, PREFIX_PROJECT, problems);
124 }
125
126 prefixlessObjectBasedValueSource = new ObjectBasedValueSource(model);
127 if (config.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
128 prefixlessObjectBasedValueSource =
129 new ProblemDetectingValueSource(prefixlessObjectBasedValueSource, "", PREFIX_PROJECT, problems);
130 }
131 }
132
133
134 List<ValueSource> valueSources = new ArrayList<>(9);
135
136 if (projectDir != null) {
137 ValueSource basedirValueSource = new PrefixedValueSourceWrapper(
138 new AbstractValueSource(false) {
139 @Override
140 public Object getValue(String expression) {
141 if ("basedir".equals(expression)) {
142 return projectDir.getAbsoluteFile().toPath().toString();
143 } else if (expression.startsWith("basedir.")) {
144 Path basedir = projectDir.getAbsoluteFile().toPath();
145 return new ObjectBasedValueSource(basedir)
146 .getValue(expression.substring("basedir.".length()));
147 }
148 return null;
149 }
150 },
151 getProjectPrefixes(config),
152 true);
153 valueSources.add(basedirValueSource);
154
155 ValueSource baseUriValueSource = new PrefixedValueSourceWrapper(
156 new AbstractValueSource(false) {
157 @Override
158 public Object getValue(String expression) {
159 if ("baseUri".equals(expression)) {
160 return projectDir
161 .getAbsoluteFile()
162 .toPath()
163 .toUri()
164 .toASCIIString();
165 } else if (expression.startsWith("baseUri.")) {
166 URI baseUri =
167 projectDir.getAbsoluteFile().toPath().toUri();
168 return new ObjectBasedValueSource(baseUri)
169 .getValue(expression.substring("baseUri.".length()));
170 }
171 return null;
172 }
173 },
174 getProjectPrefixes(config),
175 false);
176 valueSources.add(baseUriValueSource);
177 valueSources.add(new BuildTimestampValueSource(config.getBuildStartTime(), modelProperties));
178 }
179
180 valueSources.add(new PrefixedValueSourceWrapper(
181 new AbstractValueSource(false) {
182 @Override
183 public Object getValue(String expression) {
184 if ("rootDirectory".equals(expression)) {
185 Path base = projectDir != null ? projectDir.toPath() : null;
186 Path root = rootLocator.findMandatoryRoot(base);
187 return root.toFile().getPath();
188 } else if (expression.startsWith("rootDirectory.")) {
189 Path base = projectDir != null ? projectDir.toPath() : null;
190 Path root = rootLocator.findMandatoryRoot(base);
191 return new ObjectBasedValueSource(root)
192 .getValue(expression.substring("rootDirectory.".length()));
193 }
194 return null;
195 }
196 },
197 getProjectPrefixes(config)));
198
199 valueSources.add(projectPrefixValueSource);
200
201 valueSources.add(new MapBasedValueSource(config.getUserProperties()));
202
203 valueSources.add(new MapBasedValueSource(modelProperties));
204
205 valueSources.add(new MapBasedValueSource(config.getSystemProperties()));
206
207 valueSources.add(new AbstractValueSource(false) {
208 @Override
209 public Object getValue(String expression) {
210 return config.getSystemProperties().getProperty("env." + expression);
211 }
212 });
213
214 valueSources.add(prefixlessObjectBasedValueSource);
215
216 return valueSources;
217 }
218
219 protected List<? extends InterpolationPostProcessor> createPostProcessors(
220 final Model model, final File projectDir, final ModelBuildingRequest config) {
221 List<InterpolationPostProcessor> processors = new ArrayList<>(2);
222 if (projectDir != null) {
223 processors.add(new PathTranslatingPostProcessor(
224 getProjectPrefixes(config), TRANSLATED_PATH_EXPRESSIONS, projectDir, pathTranslator));
225 }
226 processors.add(new UrlNormalizingPostProcessor(urlNormalizer));
227 return processors;
228 }
229
230 protected RecursionInterceptor createRecursionInterceptor(ModelBuildingRequest config) {
231 return new PrefixAwareRecursionInterceptor(getProjectPrefixes(config));
232 }
233 }