1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.assembly.mojos;
20
21 import java.io.File;
22 import java.nio.file.attribute.FileTime;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.Properties;
26
27 import org.apache.maven.archiver.MavenArchiveConfiguration;
28 import org.apache.maven.archiver.MavenArchiver;
29 import org.apache.maven.artifact.repository.ArtifactRepository;
30 import org.apache.maven.execution.MavenSession;
31 import org.apache.maven.plugin.AbstractMojo;
32 import org.apache.maven.plugin.MojoExecutionException;
33 import org.apache.maven.plugin.MojoFailureException;
34 import org.apache.maven.plugin.logging.Log;
35 import org.apache.maven.plugins.annotations.Component;
36 import org.apache.maven.plugins.annotations.Parameter;
37 import org.apache.maven.plugins.assembly.AssemblerConfigurationSource;
38 import org.apache.maven.plugins.assembly.InvalidAssemblerConfigurationException;
39 import org.apache.maven.plugins.assembly.archive.ArchiveCreationException;
40 import org.apache.maven.plugins.assembly.archive.AssemblyArchiver;
41 import org.apache.maven.plugins.assembly.format.AssemblyFormattingException;
42 import org.apache.maven.plugins.assembly.io.AssemblyReadException;
43 import org.apache.maven.plugins.assembly.io.AssemblyReader;
44 import org.apache.maven.plugins.assembly.model.Assembly;
45 import org.apache.maven.plugins.assembly.utils.AssemblyFormatUtils;
46 import org.apache.maven.plugins.assembly.utils.InterpolationConstants;
47 import org.apache.maven.project.MavenProject;
48 import org.apache.maven.project.MavenProjectHelper;
49 import org.apache.maven.shared.filtering.MavenReaderFilter;
50 import org.codehaus.plexus.configuration.PlexusConfiguration;
51 import org.codehaus.plexus.interpolation.fixed.FixedStringSearchInterpolator;
52 import org.codehaus.plexus.interpolation.fixed.PrefixedPropertiesValueSource;
53 import org.codehaus.plexus.interpolation.fixed.PropertiesBasedValueSource;
54 import org.codehaus.plexus.util.cli.CommandLineUtils;
55
56
57
58
59
60 public abstract class AbstractAssemblyMojo extends AbstractMojo implements AssemblerConfigurationSource {
61
62 protected FixedStringSearchInterpolator commandLinePropertiesInterpolator;
63
64 protected FixedStringSearchInterpolator envInterpolator;
65
66 protected FixedStringSearchInterpolator mainProjectInterpolator;
67
68 protected FixedStringSearchInterpolator rootInterpolator;
69
70
71
72
73
74
75 @Parameter(property = "assembly.appendAssemblyId", defaultValue = "true")
76 boolean appendAssemblyId;
77
78
79
80
81 @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}")
82 private String encoding;
83
84
85
86
87
88
89
90 @Parameter(property = "assembly.escapeString")
91 private String escapeString;
92
93
94
95
96
97 @Parameter(property = "assembly.skipAssembly", defaultValue = "false")
98 private boolean skipAssembly;
99
100
101
102
103 @Parameter(property = "assembly.dryRun", defaultValue = "false")
104 private boolean dryRun;
105
106
107
108
109
110
111 @Parameter(defaultValue = "true")
112 private boolean ignoreDirFormatExtensions;
113
114
115
116
117 @Parameter(defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true)
118 private List<ArtifactRepository> remoteRepositories;
119
120
121
122
123 @Parameter(defaultValue = "${reactorProjects}", required = true, readonly = true)
124 private List<MavenProject> reactorProjects;
125
126
127
128
129 @Parameter(defaultValue = "${project.build.directory}", required = true)
130 private File outputDirectory;
131
132
133
134
135
136
137 @Parameter(defaultValue = "${project.build.finalName}", required = true)
138 private String finalName;
139
140
141
142
143 @Parameter(defaultValue = "${project.build.directory}/assembly/work", required = true)
144 private File workDirectory;
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161 @Parameter
162 private List<String> formats;
163
164
165
166
167 @Parameter
168 private String[] descriptors;
169
170
171
172
173
174
175
176 @Parameter
177 private String[] descriptorRefs;
178
179
180
181
182 @Parameter
183 private File descriptorSourceDirectory;
184
185
186
187
188
189 @Parameter
190 private File archiveBaseDirectory;
191
192
193
194
195
196 @Parameter(property = "assembly.tarLongFileMode", defaultValue = "warn")
197 private String tarLongFileMode;
198
199
200
201
202 @Parameter(defaultValue = "${project.basedir}", required = true, readonly = true)
203 private File basedir;
204
205
206
207
208 @Component
209 private MavenProjectHelper projectHelper;
210
211
212
213
214 @Component
215 private MavenReaderFilter mavenReaderFilter;
216
217
218
219
220 @Parameter(defaultValue = "${session}", readonly = true, required = true)
221 private MavenSession mavenSession;
222
223
224
225
226 @Parameter(defaultValue = "${project.build.directory}/archive-tmp", required = true, readonly = true)
227 private File tempRoot;
228
229
230
231
232 @Parameter(defaultValue = "${project.reporting.outputDirectory}", readonly = true)
233 private File siteDirectory;
234
235
236
237
238 @Parameter(property = "assembly.ignoreMissingDescriptor", defaultValue = "false")
239 private boolean ignoreMissingDescriptor;
240
241
242
243
244
245
246 @Parameter
247 private MavenArchiveConfiguration archive;
248
249
250
251
252
253
254
255 @Parameter
256 private List<String> filters;
257
258
259
260
261
262
263 @Parameter
264 private Properties additionalProperties;
265
266
267
268
269
270
271
272 @Parameter(property = "assembly.includeProjectBuildFilters", defaultValue = "true")
273 private boolean includeProjectBuildFilters;
274
275
276
277
278
279
280 @Parameter(property = "assembly.attach", defaultValue = "true")
281 private boolean attach;
282
283
284
285
286
287
288
289 @Parameter(defaultValue = "true")
290 private boolean recompressZippedFiles;
291
292
293
294
295
296
297 @Parameter
298 private String mergeManifestMode;
299
300
301
302
303 @Component
304 private AssemblyArchiver assemblyArchiver;
305
306
307
308
309 @Component
310 private AssemblyReader assemblyReader;
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329 @Parameter
330 private PlexusConfiguration archiverConfig;
331
332
333
334
335
336
337
338 @Parameter(property = "assembly.runOnlyAtExecutionRoot", defaultValue = "false")
339 private boolean runOnlyAtExecutionRoot;
340
341
342
343
344
345
346
347
348
349
350 @Parameter(property = "assembly.updateOnly", defaultValue = "false")
351 private boolean updateOnly;
352
353
354
355
356
357 @Parameter(property = "assembly.useJvmChmod", defaultValue = "false")
358 private boolean useJvmChmod;
359
360
361
362
363
364
365
366
367
368
369
370
371
372 @Parameter(property = "assembly.ignorePermissions", defaultValue = "false")
373 private boolean ignorePermissions;
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396 @Parameter
397 private List<String> delimiters;
398
399
400
401
402
403
404
405
406 @Parameter(defaultValue = "${project.build.outputTimestamp}")
407 private String outputTimestamp;
408
409
410
411
412 @Parameter
413 private Integer overrideUid;
414
415
416
417
418 @Parameter
419 private String overrideUserName;
420
421
422
423
424 @Parameter
425 private Integer overrideGid;
426
427
428
429
430 @Parameter
431 private String overrideGroupName;
432
433 public static FixedStringSearchInterpolator mainProjectInterpolator(MavenProject mainProject) {
434 if (mainProject != null) {
435
436 return FixedStringSearchInterpolator.create(
437 new org.codehaus.plexus.interpolation.fixed.PrefixedObjectValueSource(
438 InterpolationConstants.PROJECT_PREFIXES, mainProject, true),
439
440
441 new org.codehaus.plexus.interpolation.fixed.PrefixedPropertiesValueSource(
442 InterpolationConstants.PROJECT_PROPERTIES_PREFIXES, mainProject.getProperties(), true));
443 } else {
444 return FixedStringSearchInterpolator.empty();
445 }
446 }
447
448
449
450
451 @Override
452 public void execute() throws MojoExecutionException, MojoFailureException {
453
454 if (skipAssembly) {
455 getLog().info("Assemblies have been skipped per configuration of the skipAssembly parameter.");
456 return;
457 }
458
459
460 if (runOnlyAtExecutionRoot && !isThisTheExecutionRoot()) {
461 getLog().info("Skipping the assembly in this project because it's not the Execution Root");
462 return;
463 }
464
465 List<Assembly> assemblies;
466 try {
467 assemblies = assemblyReader.readAssemblies(this);
468 } catch (final AssemblyReadException e) {
469 throw new MojoExecutionException("Error reading assemblies: " + e.getMessage(), e);
470 } catch (final InvalidAssemblerConfigurationException e) {
471 throw new MojoFailureException(
472 assemblyReader, e.getMessage(), "Mojo configuration is invalid: " + e.getMessage());
473 }
474
475
476
477
478 FileTime outputDate = MavenArchiver.parseBuildOutputTimestamp(outputTimestamp)
479 .map(FileTime::from)
480 .orElse(null);
481
482 boolean warnedAboutMainProjectArtifact = false;
483 for (final Assembly assembly : assemblies) {
484 try {
485 final String fullName = AssemblyFormatUtils.getDistributionName(assembly, this);
486
487 List<String> effectiveFormats = formats;
488 if (effectiveFormats == null || effectiveFormats.isEmpty()) {
489 effectiveFormats = assembly.getFormats();
490 }
491 if (effectiveFormats == null || effectiveFormats.isEmpty()) {
492 throw new MojoFailureException(
493 "No formats specified in the execution parameters or the assembly descriptor.");
494 }
495
496 for (final String format : effectiveFormats) {
497 final File destFile = assemblyArchiver.createArchive(
498 assembly,
499 fullName,
500 format,
501 this,
502 isRecompressZippedFiles(),
503 getMergeManifestMode(),
504 outputDate);
505
506 final MavenProject project = getProject();
507 final String type = project.getArtifact().getType();
508
509 if (attach && destFile.isFile()) {
510 if (isAssemblyIdAppended()) {
511 projectHelper.attachArtifact(project, format, assembly.getId(), destFile);
512 } else if (!"pom".equals(type) && format.equals(type)) {
513 if (!warnedAboutMainProjectArtifact) {
514 final StringBuilder message = new StringBuilder();
515
516 message.append("Configuration option 'appendAssemblyId' is set to false.");
517 message.append("\nInstead of attaching the assembly file: ")
518 .append(destFile);
519 message.append(", it will become the file for main project artifact.");
520 message.append("\nNOTE: If multiple descriptors or descriptor-formats are provided "
521 + "for this project, the value of this file will be "
522 + "non-deterministic!");
523
524 getLog().warn(message);
525 warnedAboutMainProjectArtifact = true;
526 }
527
528 final File existingFile = project.getArtifact().getFile();
529 if ((existingFile != null) && existingFile.exists()) {
530 getLog().warn("Replacing pre-existing project main-artifact file: " + existingFile
531 + "\nwith assembly file: " + destFile);
532 }
533
534 project.getArtifact().setFile(destFile);
535 } else {
536 projectHelper.attachArtifact(project, format, null, destFile);
537 }
538 } else if (attach) {
539 getLog().warn("Assembly file: " + destFile + " is not a regular file (it may be a directory). "
540 + "It cannot be attached to the project build for installation or "
541 + "deployment.");
542 }
543 }
544 } catch (final ArchiveCreationException | AssemblyFormattingException e) {
545 throw new MojoExecutionException("Failed to create assembly: " + e.getMessage(), e);
546 } catch (final InvalidAssemblerConfigurationException e) {
547 throw new MojoFailureException(
548 assembly,
549 "Assembly is incorrectly configured: " + assembly.getId(),
550 "Assembly: " + assembly.getId() + " is not configured correctly: " + e.getMessage());
551 }
552 }
553 }
554
555 private FixedStringSearchInterpolator createRepositoryInterpolator() {
556 final Properties settingsProperties = new Properties();
557 final MavenSession session = getMavenSession();
558 final File basedir = session.getRepositorySession()
559 .getLocalRepositoryManager()
560 .getRepository()
561 .getBasedir();
562
563 settingsProperties.setProperty("localRepository", basedir.toString());
564 settingsProperties.setProperty("settings.localRepository", basedir.toString());
565
566 return FixedStringSearchInterpolator.create(new PropertiesBasedValueSource(settingsProperties));
567 }
568
569 private FixedStringSearchInterpolator createCommandLinePropertiesInterpolator() {
570 Properties commandLineProperties = System.getProperties();
571 final MavenSession session = getMavenSession();
572
573 if (session != null) {
574 commandLineProperties = new Properties();
575 commandLineProperties.putAll(session.getSystemProperties());
576 commandLineProperties.putAll(session.getUserProperties());
577 }
578
579 PropertiesBasedValueSource cliProps = new PropertiesBasedValueSource(commandLineProperties);
580 return FixedStringSearchInterpolator.create(cliProps);
581 }
582
583 private FixedStringSearchInterpolator createEnvInterpolator() {
584 PrefixedPropertiesValueSource envProps = new PrefixedPropertiesValueSource(
585 Collections.singletonList("env."), CommandLineUtils.getSystemEnvVars(false), true);
586 return FixedStringSearchInterpolator.create(envProps);
587 }
588
589
590
591
592
593
594 boolean isThisTheExecutionRoot() {
595 final Log log = getLog();
596 log.debug("Root Folder:" + mavenSession.getExecutionRootDirectory());
597 log.debug("Current Folder:" + basedir);
598 final boolean result = mavenSession.getExecutionRootDirectory().equalsIgnoreCase(basedir.toString());
599 if (result) {
600 log.debug("This is the execution root.");
601 } else {
602 log.debug("This is NOT the execution root.");
603 }
604
605 return result;
606 }
607
608 @Override
609 public File getBasedir() {
610 return basedir;
611 }
612
613 public void setBasedir(final File basedir) {
614 this.basedir = basedir;
615 }
616
617 @Override
618 public String[] getDescriptorReferences() {
619 return descriptorRefs;
620 }
621
622 @Override
623 public File getDescriptorSourceDirectory() {
624 return descriptorSourceDirectory;
625 }
626
627 @Override
628 public String[] getDescriptors() {
629 return descriptors;
630 }
631
632 public void setDescriptors(final String[] descriptors) {
633 this.descriptors = descriptors;
634 }
635
636 @Override
637 public abstract MavenProject getProject();
638
639 @Override
640 public File getSiteDirectory() {
641 return siteDirectory;
642 }
643
644 public void setSiteDirectory(final File siteDirectory) {
645 this.siteDirectory = siteDirectory;
646 }
647
648 @Override
649 public String getFinalName() {
650 return finalName;
651 }
652
653 public void setFinalName(final String finalName) {
654 this.finalName = finalName;
655 }
656
657 @Override
658 public boolean isAssemblyIdAppended() {
659 return appendAssemblyId;
660 }
661
662 @Override
663 public String getTarLongFileMode() {
664 return tarLongFileMode;
665 }
666
667 public void setTarLongFileMode(final String tarLongFileMode) {
668 this.tarLongFileMode = tarLongFileMode;
669 }
670
671 @Override
672 public File getOutputDirectory() {
673 return outputDirectory;
674 }
675
676 public void setOutputDirectory(final File outputDirectory) {
677 this.outputDirectory = outputDirectory;
678 }
679
680 @Override
681 public MavenArchiveConfiguration getJarArchiveConfiguration() {
682 return archive;
683 }
684
685 @Override
686 public File getWorkingDirectory() {
687 return workDirectory;
688 }
689
690 @Override
691 public File getTemporaryRootDirectory() {
692 return tempRoot;
693 }
694
695 @Override
696 public File getArchiveBaseDirectory() {
697 return archiveBaseDirectory;
698 }
699
700 @Override
701 public List<String> getFilters() {
702 if (filters == null) {
703 filters = getProject().getBuild().getFilters();
704 if (filters == null) {
705 filters = Collections.emptyList();
706 }
707 }
708 return filters;
709 }
710
711 public void setFilters(final List<String> filters) {
712 this.filters = filters;
713 }
714
715 public Properties getAdditionalProperties() {
716 return additionalProperties;
717 }
718
719 @Override
720 public boolean isIncludeProjectBuildFilters() {
721 return includeProjectBuildFilters;
722 }
723
724 @Override
725 public List<MavenProject> getReactorProjects() {
726 return reactorProjects;
727 }
728
729 public void setReactorProjects(final List<MavenProject> reactorProjects) {
730 this.reactorProjects = reactorProjects;
731 }
732
733 public void setAppendAssemblyId(final boolean appendAssemblyId) {
734 this.appendAssemblyId = appendAssemblyId;
735 }
736
737 public void setArchive(final MavenArchiveConfiguration archive) {
738 this.archive = archive;
739 }
740
741 public void setDescriptorRefs(final String[] descriptorRefs) {
742 this.descriptorRefs = descriptorRefs;
743 }
744
745 public void setTempRoot(final File tempRoot) {
746 this.tempRoot = tempRoot;
747 }
748
749 public void setWorkDirectory(final File workDirectory) {
750 this.workDirectory = workDirectory;
751 }
752
753 @Override
754 public List<ArtifactRepository> getRemoteRepositories() {
755 return remoteRepositories;
756 }
757
758 @Override
759 public boolean isDryRun() {
760 return dryRun;
761 }
762
763 @Override
764 public boolean isIgnoreDirFormatExtensions() {
765 return ignoreDirFormatExtensions;
766 }
767
768 @Override
769 public boolean isIgnoreMissingDescriptor() {
770 return ignoreMissingDescriptor;
771 }
772
773 @Override
774 public MavenSession getMavenSession() {
775 return mavenSession;
776 }
777
778 @Override
779 public String getArchiverConfig() {
780 return archiverConfig == null ? null : archiverConfig.toString();
781 }
782
783 @Override
784 public MavenReaderFilter getMavenReaderFilter() {
785 return mavenReaderFilter;
786 }
787
788 @Override
789 public boolean isUpdateOnly() {
790 return updateOnly;
791 }
792
793 @Override
794 @Deprecated
795 public boolean isUseJvmChmod() {
796 return useJvmChmod;
797 }
798
799 @Override
800 public boolean isIgnorePermissions() {
801 return ignorePermissions;
802 }
803
804 @Override
805 public String getEncoding() {
806 return encoding;
807 }
808
809 boolean isRecompressZippedFiles() {
810 return recompressZippedFiles;
811 }
812
813 public String getMergeManifestMode() {
814 return mergeManifestMode;
815 }
816
817 @Override
818 public String getEscapeString() {
819 return escapeString;
820 }
821
822 @Override
823 public List<String> getDelimiters() {
824 return delimiters;
825 }
826
827 public void setDelimiters(List<String> delimiters) {
828 this.delimiters = delimiters;
829 }
830
831 @Override
832 public synchronized FixedStringSearchInterpolator getCommandLinePropsInterpolator() {
833 if (commandLinePropertiesInterpolator == null) {
834 this.commandLinePropertiesInterpolator = createCommandLinePropertiesInterpolator();
835 }
836 return commandLinePropertiesInterpolator;
837 }
838
839 @Override
840 public synchronized FixedStringSearchInterpolator getEnvInterpolator() {
841 if (envInterpolator == null) {
842 this.envInterpolator = createEnvInterpolator();
843 }
844 return envInterpolator;
845 }
846
847 @Override
848 public synchronized FixedStringSearchInterpolator getRepositoryInterpolator() {
849 if (rootInterpolator == null) {
850 this.rootInterpolator = createRepositoryInterpolator();
851 }
852 return rootInterpolator;
853 }
854
855 @Override
856 public synchronized FixedStringSearchInterpolator getMainProjectInterpolator() {
857 if (mainProjectInterpolator == null) {
858 this.mainProjectInterpolator = mainProjectInterpolator(getProject());
859 }
860 return mainProjectInterpolator;
861 }
862
863 @Override
864 public Integer getOverrideUid() {
865 return this.overrideUid;
866 }
867
868 @Override
869 public String getOverrideUserName() {
870 return this.overrideUserName;
871 }
872
873 @Override
874 public Integer getOverrideGid() {
875 return this.overrideGid;
876 }
877
878 @Override
879 public String getOverrideGroupName() {
880 return this.overrideGroupName;
881 }
882 }