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