1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.shared.filtering;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.Reader;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.LinkedHashSet;
27 import java.util.List;
28 import java.util.Properties;
29 import java.util.TreeSet;
30 import java.util.function.Consumer;
31
32 import org.apache.maven.execution.MavenSession;
33 import org.apache.maven.project.MavenProject;
34 import org.apache.maven.settings.Settings;
35 import org.codehaus.plexus.interpolation.Interpolator;
36 import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
37 import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
38 import org.codehaus.plexus.interpolation.PropertiesBasedValueSource;
39 import org.codehaus.plexus.interpolation.RecursionInterceptor;
40 import org.codehaus.plexus.interpolation.SimpleRecursionInterceptor;
41 import org.codehaus.plexus.interpolation.SingleResponseValueSource;
42 import org.codehaus.plexus.interpolation.ValueSource;
43 import org.codehaus.plexus.interpolation.multi.MultiDelimiterStringSearchInterpolator;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 class BaseFilter implements DefaultFilterInfo {
48 private final Logger logger = LoggerFactory.getLogger(getClass());
49
50 protected Logger getLogger() {
51 return logger;
52 }
53
54 @Override
55 public List<FilterWrapper> getDefaultFilterWrappers(
56 final MavenProject mavenProject,
57 List<String> filters,
58 final boolean escapedBackslashesInFilePath,
59 MavenSession mavenSession,
60 MavenResourcesExecution mavenResourcesExecution)
61 throws MavenFilteringException {
62
63 MavenResourcesExecution mre =
64 mavenResourcesExecution == null ? new MavenResourcesExecution() : mavenResourcesExecution.copyOf();
65
66 mre.setMavenProject(mavenProject);
67 mre.setMavenSession(mavenSession);
68 mre.setFilters(filters);
69 mre.setEscapedBackslashesInFilePath(escapedBackslashesInFilePath);
70
71 return getDefaultFilterWrappers(mre);
72 }
73
74 @Override
75 public List<FilterWrapper> getDefaultFilterWrappers(final AbstractMavenFilteringRequest request)
76 throws MavenFilteringException {
77
78 boolean supportMultiLineFiltering = request.isSupportMultiLineFiltering();
79
80 request.setSupportMultiLineFiltering(supportMultiLineFiltering);
81
82
83
84
85
86
87
88 final Properties baseProps = new Properties();
89
90
91 if (request.getMavenProject() != null) {
92 baseProps.putAll(
93 request.getMavenProject().getProperties() == null
94 ? Collections.emptyMap()
95 : request.getMavenProject().getProperties());
96 }
97
98
99
100
101
102
103
104
105
106
107
108
109 if (request.getMavenSession() != null) {
110
111 putAll(baseProps, request.getMavenSession().getSystemProperties());
112 putAll(baseProps, request.getMavenSession().getUserProperties());
113 }
114
115
116
117 final Properties filterProperties = new Properties();
118
119 File basedir =
120 request.getMavenProject() != null ? request.getMavenProject().getBasedir() : new File(".");
121
122 loadProperties(filterProperties, basedir, request.getFileFilters(), baseProps);
123 if (filterProperties.isEmpty()) {
124 putAll(filterProperties, baseProps);
125 }
126
127 if (request.getMavenProject() != null) {
128 if (request.isInjectProjectBuildFilters()) {
129 List<String> buildFilters =
130 new ArrayList<>(request.getMavenProject().getBuild().getFilters());
131
132
133 if (request.getFileFilters() != null) {
134 buildFilters.removeAll(request.getFileFilters());
135 }
136
137 loadProperties(filterProperties, basedir, buildFilters, baseProps);
138 }
139
140
141 filterProperties.putAll(
142 request.getMavenProject().getProperties() == null
143 ? Collections.emptyMap()
144 : request.getMavenProject().getProperties());
145 }
146 if (request.getMavenSession() != null) {
147
148 putAll(filterProperties, request.getMavenSession().getSystemProperties());
149 putAll(filterProperties, request.getMavenSession().getUserProperties());
150 }
151
152 if (request.getAdditionalProperties() != null) {
153
154 putAll(filterProperties, request.getAdditionalProperties());
155 }
156
157 List<FilterWrapper> defaultFilterWrappers =
158 new ArrayList<>(request.getDelimiters().size() + 1);
159
160 if (getLogger().isDebugEnabled()) {
161 getLogger().debug("properties used:");
162 for (String s : new TreeSet<>(filterProperties.stringPropertyNames())) {
163 getLogger().debug(s + ": " + filterProperties.getProperty(s));
164 }
165 }
166
167 final ValueSource propertiesValueSource = new PropertiesBasedValueSource(filterProperties);
168
169 FilterWrapper wrapper = new Wrapper(
170 request.getDelimiters(),
171 request.getMavenProject(),
172 request.getMavenSession(),
173 propertiesValueSource,
174 request.getProjectStartExpressions(),
175 request.getEscapeString(),
176 request.isEscapeWindowsPaths(),
177 request.isSupportMultiLineFiltering(),
178 request.getInterpolatorCustomizer());
179
180 defaultFilterWrappers.add(wrapper);
181
182 return defaultFilterWrappers;
183 }
184
185 @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
186 private static void putAll(Properties filterProperties, Properties request) {
187 synchronized (request) {
188 filterProperties.putAll(request);
189 }
190 }
191
192
193
194
195 void loadProperties(
196 Properties filterProperties, File basedir, List<String> propertiesFilePaths, Properties baseProps)
197 throws MavenFilteringException {
198 if (propertiesFilePaths != null) {
199 Properties workProperties = new Properties();
200 putAll(workProperties, baseProps);
201
202 for (String filterFile : propertiesFilePaths) {
203 if (filterFile == null || filterFile.trim().isEmpty()) {
204
205 continue;
206 }
207 try {
208 File propFile = FilteringUtils.resolveFile(basedir, filterFile);
209 Properties properties = PropertyUtils.loadPropertyFile(propFile, workProperties, getLogger());
210 putAll(filterProperties, properties);
211 putAll(workProperties, properties);
212 } catch (IOException e) {
213 throw new MavenFilteringException("Error loading property file '" + filterFile + "'", e);
214 }
215 }
216 }
217 }
218
219 private static final class Wrapper extends FilterWrapper {
220
221 private LinkedHashSet<String> delimiters;
222
223 private MavenProject project;
224
225 private ValueSource propertiesValueSource;
226
227 private List<String> projectStartExpressions;
228
229 private String escapeString;
230
231 private boolean escapeWindowsPaths;
232
233 private final MavenSession mavenSession;
234
235 private boolean supportMultiLineFiltering;
236
237 private Consumer<Interpolator> interpolatorCustomizer;
238
239 Wrapper(
240 LinkedHashSet<String> delimiters,
241 MavenProject project,
242 MavenSession mavenSession,
243 ValueSource propertiesValueSource,
244 List<String> projectStartExpressions,
245 String escapeString,
246 boolean escapeWindowsPaths,
247 boolean supportMultiLineFiltering,
248 Consumer<Interpolator> interpolatorCustomizer) {
249 super();
250 this.delimiters = delimiters;
251 this.project = project;
252 this.mavenSession = mavenSession;
253 this.propertiesValueSource = propertiesValueSource;
254 this.projectStartExpressions = projectStartExpressions;
255 this.escapeString = escapeString;
256 this.escapeWindowsPaths = escapeWindowsPaths;
257 this.supportMultiLineFiltering = supportMultiLineFiltering;
258 this.interpolatorCustomizer = interpolatorCustomizer;
259 }
260
261 @Override
262 public Reader getReader(Reader reader) {
263 Interpolator interpolator = createInterpolator(
264 delimiters,
265 projectStartExpressions,
266 propertiesValueSource,
267 project,
268 mavenSession,
269 escapeString,
270 escapeWindowsPaths);
271 if (interpolatorCustomizer != null) {
272 interpolatorCustomizer.accept(interpolator);
273 }
274
275 MultiDelimiterInterpolatorFilterReaderLineEnding filterReader =
276 new MultiDelimiterInterpolatorFilterReaderLineEnding(
277 reader, interpolator, supportMultiLineFiltering);
278
279 final RecursionInterceptor ri;
280 if (projectStartExpressions != null && !projectStartExpressions.isEmpty()) {
281 ri = new PrefixAwareRecursionInterceptor(projectStartExpressions, true);
282 } else {
283 ri = new SimpleRecursionInterceptor();
284 }
285
286 filterReader.setRecursionInterceptor(ri);
287 filterReader.setDelimiterSpecs(delimiters);
288
289 filterReader.setInterpolateWithPrefixPattern(false);
290 filterReader.setEscapeString(escapeString);
291
292 return filterReader;
293 }
294 }
295
296 private static Interpolator createInterpolator(
297 LinkedHashSet<String> delimiters,
298 List<String> projectStartExpressions,
299 ValueSource propertiesValueSource,
300 MavenProject project,
301 MavenSession mavenSession,
302 String escapeString,
303 boolean escapeWindowsPaths) {
304 MultiDelimiterStringSearchInterpolator interpolator = new MultiDelimiterStringSearchInterpolator();
305 interpolator.setDelimiterSpecs(delimiters);
306
307 interpolator.addValueSource(propertiesValueSource);
308
309 if (project != null) {
310 interpolator.addValueSource(new PrefixedObjectValueSource(projectStartExpressions, project, true));
311 }
312
313 if (mavenSession != null) {
314 interpolator.addValueSource(new PrefixedObjectValueSource("session", mavenSession));
315
316 final Settings settings = mavenSession.getSettings();
317 if (settings != null) {
318 interpolator.addValueSource(new PrefixedObjectValueSource("settings", settings));
319 interpolator.addValueSource(
320 new SingleResponseValueSource("localRepository", settings.getLocalRepository()));
321 }
322 }
323
324 interpolator.setEscapeString(escapeString);
325
326 if (escapeWindowsPaths) {
327 interpolator.addPostProcessor((expression, value) ->
328 (value instanceof String) ? FilteringUtils.escapeWindowsPath((String) value) : value);
329 }
330 return interpolator;
331 }
332 }