1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.basepom.mojo.propertyhelper;
16
17 import static com.google.common.base.Preconditions.checkState;
18 import static java.lang.String.format;
19 import static org.basepom.mojo.propertyhelper.IgnoreWarnFail.checkIgnoreWarnFailState;
20
21 import org.basepom.mojo.propertyhelper.definitions.DateDefinition;
22 import org.basepom.mojo.propertyhelper.definitions.FieldDefinition;
23 import org.basepom.mojo.propertyhelper.definitions.MacroDefinition;
24 import org.basepom.mojo.propertyhelper.definitions.NumberDefinition;
25 import org.basepom.mojo.propertyhelper.definitions.PropertyGroupDefinition;
26 import org.basepom.mojo.propertyhelper.definitions.StringDefinition;
27 import org.basepom.mojo.propertyhelper.definitions.UuidDefinition;
28 import org.basepom.mojo.propertyhelper.fields.NumberField;
29 import org.basepom.mojo.propertyhelper.groups.PropertyGroup;
30 import org.basepom.mojo.propertyhelper.groups.PropertyResult;
31 import org.basepom.mojo.propertyhelper.macros.MacroType;
32
33 import java.io.File;
34 import java.io.IOException;
35 import java.util.Arrays;
36 import java.util.LinkedHashSet;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Properties;
40 import java.util.Set;
41 import javax.inject.Inject;
42
43 import com.google.common.collect.ImmutableList;
44 import com.google.common.collect.ImmutableMap;
45 import com.google.common.collect.ImmutableSet;
46 import com.google.common.flogger.FluentLogger;
47 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
48 import org.apache.maven.plugin.AbstractMojo;
49 import org.apache.maven.plugin.MojoExecutionException;
50 import org.apache.maven.plugins.annotations.Parameter;
51 import org.apache.maven.project.MavenProject;
52 import org.apache.maven.settings.Settings;
53
54 public abstract class AbstractPropertyHelperMojo extends AbstractMojo implements FieldContext {
55
56 private static final FluentLogger LOG = FluentLogger.forEnclosingClass();
57
58 protected final ValueCache valueCache = new ValueCache();
59 private IgnoreWarnFail onDuplicateField = IgnoreWarnFail.FAIL;
60
61
62
63
64
65
66
67
68
69
70
71 @Parameter(defaultValue = "fail", alias = "onDuplicateProperty")
72 public void setOnDuplicateField(String onDuplicateField) {
73 this.onDuplicateField = IgnoreWarnFail.forString(onDuplicateField);
74 }
75
76 private List<String> activeGroups = List.of();
77
78
79
80
81
82
83
84
85
86
87
88 @Parameter
89 public void setActiveGroups(String... activeGroups) {
90 this.activeGroups = Arrays.asList(activeGroups);
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 @Parameter
120 public void setPropertyGroups(PropertyGroupDefinition... propertyGroups) {
121 this.propertyGroupDefinitions = Arrays.asList(propertyGroups);
122 }
123
124 private List<PropertyGroupDefinition> propertyGroupDefinitions = List.of();
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 @Parameter
154 public void setNumbers(NumberDefinition... numberDefinitions) {
155 this.numberDefinitions = Arrays.asList(numberDefinitions);
156 }
157
158 private List<NumberDefinition> numberDefinitions = List.of();
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191 @Parameter
192 public void setStrings(StringDefinition... stringDefinitions) {
193 this.stringDefinitions = Arrays.asList(stringDefinitions);
194 }
195
196 private List<StringDefinition> stringDefinitions = List.of();
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225 @Parameter
226 public void setDates(DateDefinition... dateDefinitions) {
227 this.dateDefinitions = Arrays.asList(dateDefinitions);
228 }
229
230 private List<DateDefinition> dateDefinitions = List.of();
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264 @Parameter
265 public void setMacros(MacroDefinition... macroDefinitions) {
266 this.macroDefinitions = Arrays.asList(macroDefinitions);
267 }
268
269 private List<MacroDefinition> macroDefinitions = List.of();
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297 @Parameter
298 public void setUuids(UuidDefinition... uuidDefinitions) {
299 this.uuidDefinitions = Arrays.asList(uuidDefinitions);
300 }
301
302 private List<UuidDefinition> uuidDefinitions = List.of();
303
304
305
306
307 @Parameter(defaultValue = "false")
308 boolean skip;
309
310
311
312
313 @Parameter(defaultValue = "${project}", readonly = true)
314 MavenProject project;
315
316 @Parameter(defaultValue = "${settings}", readonly = true)
317 Settings settings;
318
319 @Parameter(required = true, readonly = true, defaultValue = "${project.basedir}")
320 File basedir;
321
322 @Inject
323 public void setMacroMap(Map<String, MacroType> macroMap) {
324 this.macroMap = ImmutableMap.copyOf(macroMap);
325 }
326
327 private Map<String, MacroType> macroMap = Map.of();
328
329
330 private boolean isSnapshot;
331 private InterpolatorFactory interpolatorFactory;
332 private TransformerRegistry transformerRegistry;
333
334 private Map<String, FieldDefinition<?>> fieldDefinitions = Map.of();
335 private List<NumberField> numberFields = List.of();
336 private Map<String, String> values = Map.of();
337
338 @Override
339 public void execute() throws MojoExecutionException {
340 this.isSnapshot = project.getArtifact().isSnapshot();
341 this.interpolatorFactory = new InterpolatorFactory(project.getModel());
342 this.transformerRegistry = TransformerRegistry.INSTANCE;
343
344 LOG.atFine().log("Current build is a %s project.", isSnapshot ? "snapshot" : "release");
345 LOG.atFiner().log("On duplicate field definitions: %s", onDuplicateField);
346
347 try {
348 if (skip) {
349 LOG.atFine().log("skipping plugin execution!");
350 } else {
351 doExecute();
352 }
353 } catch (IOException e) {
354 throw new MojoExecutionException("While running mojo: ", e);
355 }
356 }
357
358 @Override
359 public MavenProject getProject() {
360 return project;
361 }
362
363 @Override
364 public File getBasedir() {
365 return basedir;
366 }
367
368 @Override
369 public Settings getSettings() {
370 return settings;
371 }
372
373 @Override
374 public Map<String, MacroType> getMacros() {
375 return macroMap;
376 }
377
378 @Override
379 public Properties getProjectProperties() {
380 return project.getProperties();
381 }
382
383 @Override
384 public InterpolatorFactory getInterpolatorFactory() {
385 return interpolatorFactory;
386 }
387
388 @Override
389 public TransformerRegistry getTransformerRegistry() {
390 return transformerRegistry;
391 }
392
393 protected List<NumberField> getNumbers() {
394 return numberFields;
395 }
396
397
398
399
400 protected abstract void doExecute() throws IOException, MojoExecutionException;
401
402 private void addDefinitions(ImmutableMap.Builder<String, FieldDefinition<?>> builder, List<? extends FieldDefinition<?>> newDefinitions) {
403 Map<String, FieldDefinition<?>> existingDefinitions = builder.build();
404
405 for (FieldDefinition<?> definition : newDefinitions) {
406 if (definition.isSkip()) {
407 continue;
408 }
409
410 String propertyName = definition.getId();
411
412 if (checkIgnoreWarnFailState(!existingDefinitions.containsKey(propertyName), onDuplicateField,
413 () -> format("field definition '%s' does not exist", propertyName),
414 () -> format("field definition '%s' already exists!", propertyName))) {
415 builder.put(propertyName, definition);
416 }
417 }
418 }
419
420 protected void createFieldDefinitions() {
421
422 ImmutableMap.Builder<String, FieldDefinition<?>> builder = ImmutableMap.builder();
423 addDefinitions(builder, numberDefinitions);
424 addDefinitions(builder, stringDefinitions);
425 addDefinitions(builder, macroDefinitions);
426 addDefinitions(builder, dateDefinitions);
427 addDefinitions(builder, uuidDefinitions);
428
429 this.fieldDefinitions = builder.build();
430 }
431
432 protected void createFields() throws MojoExecutionException, IOException {
433 ImmutableList.Builder<NumberField> numberFields = ImmutableList.builder();
434
435 var builder = ImmutableMap.<String, String>builder();
436
437 for (FieldDefinition<?> definition : fieldDefinitions.values()) {
438 Field<?, ?> field = definition.createField(this, valueCache);
439
440 if (field instanceof NumberField) {
441 numberFields.add((NumberField) field);
442 }
443
444 var fieldValue = field.getValue();
445 builder.put(field.getFieldName(), fieldValue);
446
447 if (field.isExposeAsProperty()) {
448 project.getProperties().setProperty(field.getFieldName(), fieldValue);
449 LOG.atFine().log("Exporting Property name: %s, value: %s", field.getFieldName(), fieldValue);
450 } else {
451 LOG.atFine().log("Property name: %s, value: %s", field.getFieldName(), fieldValue);
452 }
453 }
454
455 this.numberFields = numberFields.build();
456 this.values = builder.build();
457 }
458
459
460 @SuppressFBWarnings(value = "WMI_WRONG_MAP_ITERATOR")
461 public void createGroups() {
462 var groupMapBuilder = ImmutableMap.<String, PropertyGroup>builder();
463 var resultMapBuilder = ImmutableMap.<String, Set<PropertyResult>>builder();
464
465 Set<String> exportedFields = fieldDefinitions.values().stream()
466 .filter(FieldDefinition::isExport)
467 .map(FieldDefinition::getId).collect(ImmutableSet.toImmutableSet());
468
469 Set<String> propertyNames = new LinkedHashSet<>(exportedFields);
470
471 propertyGroupDefinitions.forEach(propertyGroupDefinition -> {
472 PropertyGroup propertyGroup = propertyGroupDefinition.createGroup(this);
473 Set<PropertyResult> propertyResults = propertyGroup.createProperties(values);
474 groupMapBuilder.put(propertyGroup.getId(), propertyGroup);
475 resultMapBuilder.put(propertyGroup.getId(), propertyResults);
476 });
477
478 var groupMap = groupMapBuilder.build();
479 var resultMap = resultMapBuilder.build();
480
481 var groupsToAdd = this.activeGroups == null
482 ? groupMap.keySet()
483 : this.activeGroups;
484
485 for (String groupToAdd : groupsToAdd) {
486
487 var activeGroup = groupMap.get(groupToAdd);
488 checkState(activeGroup != null, "activated group '%s' does not exist", groupToAdd);
489 var activeResult = resultMap.get(groupToAdd);
490 checkState(activeResult != null, "activated group '%s' has no result", groupToAdd);
491
492 if (activeGroup.checkActive(isSnapshot)) {
493 for (PropertyResult propertyResult : activeResult) {
494 String propertyName = propertyResult.getPropertyName();
495
496 if (checkIgnoreWarnFailState(!propertyNames.contains(propertyName), activeGroup.getOnDuplicateProperty(),
497 () -> format("property '%s' is not exposed", propertyName),
498 () -> format("property '%s' is already exposed!", propertyName))) {
499
500 project.getProperties().setProperty(propertyName, propertyResult.getPropertyValue());
501 }
502 }
503 } else {
504 LOG.atFine().log("Skipping property group %s, not active", activeGroup);
505 }
506 }
507 }
508 }