1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.maven.plugins.invoker;
20  
21  import java.io.File;
22  import java.util.Arrays;
23  import java.util.Collection;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Objects;
28  import java.util.Optional;
29  import java.util.Properties;
30  import java.util.function.Consumer;
31  import java.util.regex.Matcher;
32  import java.util.regex.Pattern;
33  
34  import org.apache.commons.lang3.StringUtils;
35  import org.apache.maven.shared.invoker.InvocationRequest;
36  
37  
38  
39  
40  
41  
42  class InvokerProperties {
43      private static final String SELECTOR_PREFIX = "selector.";
44  
45      private static final Pattern ENVIRONMENT_VARIABLES_PATTERN =
46              Pattern.compile("invoker\\.environmentVariables\\.([A-Za-z][^.]+)(\\.([0-9]+))?");
47  
48      
49      private Boolean defaultDebug;
50      private Boolean defaultQuiet;
51      private List<String> defaultGoals;
52      private List<String> defaultProfiles;
53      private String defaultMavenOpts;
54      private Integer defaultTimeoutInSeconds;
55      private Map<String, String> defaultEnvironmentVariables;
56      private File defaultMavenExecutable;
57      private Boolean defaultUpdateSnapshots;
58  
59      private enum InvocationProperty {
60          PROJECT("invoker.project"),
61          BUILD_RESULT("invoker.buildResult"),
62          GOALS("invoker.goals"),
63          PROFILES("invoker.profiles"),
64          MAVEN_EXECUTABLE("invoker.mavenExecutable"),
65          MAVEN_OPTS("invoker.mavenOpts"),
66          FAILURE_BEHAVIOR("invoker.failureBehavior"),
67          NON_RECURSIVE("invoker.nonRecursive"),
68          OFFLINE("invoker.offline"),
69          SYSTEM_PROPERTIES_FILE("invoker.systemPropertiesFile"),
70          DEBUG("invoker.debug"),
71          QUIET("invoker.quiet"),
72          SETTINGS_FILE("invoker.settingsFile"),
73          TIMEOUT_IN_SECONDS("invoker.timeoutInSeconds"),
74          UPDATE_SNAPSHOTS("invoker.updateSnapshots");
75  
76          private final String key;
77  
78          InvocationProperty(final String s) {
79              this.key = s;
80          }
81  
82          @Override
83          public String toString() {
84              return key;
85          }
86      }
87  
88      private enum SelectorProperty {
89          JAVA_VERSION(".java.version"),
90          MAVEN_VERSION(".maven.version"),
91          OS_FAMLY(".os.family");
92  
93          private final String suffix;
94  
95          SelectorProperty(String suffix) {
96              this.suffix = suffix;
97          }
98  
99          @Override
100         public String toString() {
101             return suffix;
102         }
103     }
104 
105     
106 
107 
108     private final Properties properties;
109 
110     
111 
112 
113 
114 
115 
116     InvokerProperties(Properties properties) {
117         this.properties = (properties != null) ? properties : new Properties();
118     }
119 
120     
121 
122 
123 
124     public void setDefaultDebug(boolean defaultDebug) {
125         this.defaultDebug = defaultDebug;
126     }
127 
128     
129 
130 
131 
132     public void setDefaultQuiet(boolean defaultQuiet) {
133         this.defaultQuiet = defaultQuiet;
134     }
135 
136     
137 
138 
139 
140     public void setDefaultGoals(List<String> defaultGoals) {
141         this.defaultGoals = defaultGoals;
142     }
143 
144     
145 
146 
147 
148     public void setDefaultProfiles(List<String> defaultProfiles) {
149         this.defaultProfiles = defaultProfiles;
150     }
151 
152     
153 
154 
155 
156     public void setDefaultMavenExecutable(String defaultMavenExecutable) {
157         if (StringUtils.isNotBlank(defaultMavenExecutable)) {
158             this.defaultMavenExecutable = new File(defaultMavenExecutable);
159         }
160     }
161 
162     
163 
164 
165 
166     public void setDefaultMavenOpts(String defaultMavenOpts) {
167         this.defaultMavenOpts = defaultMavenOpts;
168     }
169 
170     
171 
172 
173 
174     public void setDefaultTimeoutInSeconds(int defaultTimeoutInSeconds) {
175         this.defaultTimeoutInSeconds = defaultTimeoutInSeconds;
176     }
177 
178     
179 
180 
181 
182     public void setDefaultEnvironmentVariables(Map<String, String> defaultEnvironmentVariables) {
183         this.defaultEnvironmentVariables = defaultEnvironmentVariables;
184     }
185 
186     
187 
188 
189 
190     public void setDefaultUpdateSnapshots(boolean defaultUpdateSnapshots) {
191         this.defaultUpdateSnapshots = defaultUpdateSnapshots;
192     }
193 
194     
195 
196 
197 
198 
199     public Properties getProperties() {
200         return this.properties;
201     }
202 
203     
204 
205 
206 
207 
208     public String getJobName() {
209         return this.properties.getProperty("invoker.name", "");
210     }
211 
212     
213 
214 
215 
216 
217     public String getJobDescription() {
218         return this.properties.getProperty("invoker.description", "");
219     }
220 
221     
222 
223 
224 
225 
226     public int getOrdinal() {
227         return Integer.parseInt(this.properties.getProperty("invoker.ordinal", "0"));
228     }
229 
230     
231 
232 
233 
234 
235     public String getJreVersion() {
236         return this.properties.getProperty("invoker.java.version", "");
237     }
238 
239     
240 
241 
242 
243 
244     public String getJreVersion(int index) {
245         return this.properties.getProperty(SELECTOR_PREFIX + index + SelectorProperty.JAVA_VERSION, getJreVersion());
246     }
247 
248     
249 
250 
251 
252 
253 
254     public String getMavenVersion() {
255         return this.properties.getProperty("invoker.maven.version", "");
256     }
257 
258     
259 
260 
261 
262 
263     public String getMavenVersion(int index) {
264         return this.properties.getProperty(SELECTOR_PREFIX + index + SelectorProperty.MAVEN_VERSION, getMavenVersion());
265     }
266 
267     
268 
269 
270 
271 
272     public String getOsFamily() {
273         return this.properties.getProperty("invoker.os.family", "");
274     }
275 
276     
277 
278 
279 
280 
281 
282 
283     public String getOsFamily(int index) {
284         return this.properties.getProperty(SELECTOR_PREFIX + index + SelectorProperty.OS_FAMLY, getOsFamily());
285     }
286 
287     public Collection<InvokerToolchain> getToolchains() {
288         return getToolchains(Pattern.compile("invoker\\.toolchain\\.([^.]+)\\.(.+)"));
289     }
290 
291     public Collection<InvokerToolchain> getToolchains(int index) {
292         return getToolchains(Pattern.compile("selector\\." + index + "\\.invoker\\.toolchain\\.([^.]+)\\.(.+)"));
293     }
294 
295     private Collection<InvokerToolchain> getToolchains(Pattern p) {
296         Map<String, InvokerToolchain> toolchains = new HashMap<>();
297         for (Map.Entry<Object, Object> entry : this.properties.entrySet()) {
298             Matcher m = p.matcher(entry.getKey().toString());
299             if (m.matches()) {
300                 String type = m.group(1);
301                 String providesKey = m.group(2);
302                 String providesValue = entry.getValue().toString();
303 
304                 InvokerToolchain tc = toolchains.get(type);
305                 if (tc == null) {
306                     tc = new InvokerToolchain(type);
307                     toolchains.put(type, tc);
308                 }
309                 tc.addProvides(providesKey, providesValue);
310             }
311         }
312         return toolchains.values();
313     }
314 
315     
316 
317 
318 
319 
320 
321 
322     private Map<String, String> getEnvironmentVariables(int index) {
323 
324         Map<String, String> envItems = new HashMap<>();
325 
326         for (Map.Entry<Object, Object> entry : properties.entrySet()) {
327             Matcher matcher =
328                     ENVIRONMENT_VARIABLES_PATTERN.matcher(entry.getKey().toString());
329             if (matcher.matches()) {
330 
331                 if (String.valueOf(index).equals(matcher.group(3))) {
332                     
333                     envItems.put(matcher.group(1), entry.getValue().toString());
334                 } else if (matcher.group(3) == null) {
335                     
336                     if (!envItems.containsKey(matcher.group(1))) {
337                         envItems.put(matcher.group(1), entry.getValue().toString());
338                     }
339                 }
340             }
341         }
342         return envItems;
343     }
344 
345     
346 
347 
348 
349 
350 
351     public boolean isInvocationDefined(int index) {
352         return Arrays.stream(InvocationProperty.values())
353                 .map(InvocationProperty::toString)
354                 .map(v -> properties.getProperty(v + '.' + index))
355                 .anyMatch(Objects::nonNull);
356     }
357 
358     
359 
360 
361 
362 
363 
364 
365     public boolean isSelectorDefined(int index) {
366         return Arrays.stream(SelectorProperty.values())
367                 .map(v -> v.suffix)
368                 .map(v -> properties.getProperty(SELECTOR_PREFIX + index + v))
369                 .anyMatch(Objects::nonNull);
370     }
371 
372     private <T> void setIfNotNull(Consumer<T> consumer, T value) {
373         if (value != null) {
374             consumer.accept(value);
375         }
376     }
377 
378     
379 
380 
381 
382 
383 
384 
385     public void configureInvocation(InvocationRequest request, int index) {
386         get(InvocationProperty.PROJECT, index).ifPresent(project -> {
387             File file = new File(request.getBaseDirectory(), project);
388             if (file.isFile()) {
389                 request.setBaseDirectory(file.getParentFile());
390                 request.setPomFile(file);
391             } else {
392                 request.setBaseDirectory(file);
393                 request.setPomFile(null);
394             }
395         });
396 
397         setIfNotNull(
398                 request::setGoals,
399                 get(InvocationProperty.GOALS, index)
400                         .map(s -> StringUtils.split(s, ", \t\n\r\f"))
401                         .map(Arrays::asList)
402                         .filter(l -> !l.isEmpty())
403                         .orElse(defaultGoals));
404 
405         setIfNotNull(
406                 request::setProfiles,
407                 get(InvocationProperty.PROFILES, index)
408                         .map(s -> StringUtils.split(s, ", \t\n\r\f"))
409                         .map(Arrays::asList)
410                         .filter(l -> !l.isEmpty())
411                         .orElse(defaultProfiles));
412 
413         setIfNotNull(
414                 request::setMavenExecutable,
415                 get(InvocationProperty.MAVEN_EXECUTABLE, index).map(File::new).orElse(defaultMavenExecutable));
416 
417         setIfNotNull(
418                 request::setMavenOpts, get(InvocationProperty.MAVEN_OPTS, index).orElse(defaultMavenOpts));
419 
420         get(InvocationProperty.FAILURE_BEHAVIOR, index)
421                 .map(InvocationRequest.ReactorFailureBehavior::valueOfByLongOption)
422                 .ifPresent(request::setReactorFailureBehavior);
423 
424         get(InvocationProperty.NON_RECURSIVE, index)
425                 .map(Boolean::parseBoolean)
426                 .map(b -> !b)
427                 .ifPresent(request::setRecursive);
428 
429         get(InvocationProperty.OFFLINE, index).map(Boolean::parseBoolean).ifPresent(request::setOffline);
430 
431         setIfNotNull(
432                 request::setDebug,
433                 get(InvocationProperty.DEBUG, index).map(Boolean::parseBoolean).orElse(defaultDebug));
434 
435         setIfNotNull(
436                 request::setQuiet,
437                 get(InvocationProperty.QUIET, index).map(Boolean::parseBoolean).orElse(defaultQuiet));
438 
439         setIfNotNull(
440                 request::setTimeoutInSeconds,
441                 get(InvocationProperty.TIMEOUT_IN_SECONDS, index)
442                         .map(Integer::parseInt)
443                         .orElse(defaultTimeoutInSeconds));
444 
445         setIfNotNull(
446                 request::setUpdateSnapshots,
447                 get(InvocationProperty.UPDATE_SNAPSHOTS, index)
448                         .map(Boolean::parseBoolean)
449                         .orElse(defaultUpdateSnapshots));
450 
451         Optional.ofNullable(defaultEnvironmentVariables).ifPresent(evn -> evn.forEach(request::addShellEnvironment));
452 
453         getEnvironmentVariables(index).forEach(request::addShellEnvironment);
454     }
455 
456     
457 
458 
459 
460 
461 
462 
463 
464     public boolean isExpectedResult(int exitCode, int index) {
465         boolean nonZeroExit = "failure"
466                 .equalsIgnoreCase(get(InvocationProperty.BUILD_RESULT, index).orElse(null));
467         return (exitCode != 0) == nonZeroExit;
468     }
469 
470     
471 
472 
473 
474 
475 
476     public String getSystemPropertiesFile(int index) {
477         return get(InvocationProperty.SYSTEM_PROPERTIES_FILE, index).orElse(null);
478     }
479 
480     
481 
482 
483 
484 
485 
486     public String getSettingsFile(int index) {
487         return get(InvocationProperty.SETTINGS_FILE, index).orElse(null);
488     }
489 
490     
491 
492 
493 
494 
495 
496 
497 
498 
499 
500     Optional<String> get(String key, int index) {
501         if (index < 0) {
502             throw new IllegalArgumentException("invalid invocation index: " + index);
503         }
504 
505         
506         String value = Optional.ofNullable(properties.getProperty(key + '.' + index))
507                 .orElseGet(() -> properties.getProperty(key));
508 
509         return Optional.ofNullable(value).map(String::trim).filter(s -> !s.isEmpty());
510     }
511 
512     private Optional<String> get(InvocationProperty prop, int index) {
513         return get(prop.toString(), index);
514     }
515 }