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.archive.archiver;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.nio.charset.Charset;
25 import java.nio.file.Files;
26 import java.nio.file.attribute.FileTime;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Comparator;
30 import java.util.Date;
31 import java.util.List;
32 import java.util.Map;
33
34 import org.apache.maven.plugins.assembly.filter.ContainerDescriptorHandler;
35 import org.codehaus.plexus.archiver.ArchiveEntry;
36 import org.codehaus.plexus.archiver.ArchiveFinalizer;
37 import org.codehaus.plexus.archiver.ArchivedFileSet;
38 import org.codehaus.plexus.archiver.Archiver;
39 import org.codehaus.plexus.archiver.ArchiverException;
40 import org.codehaus.plexus.archiver.FileSet;
41 import org.codehaus.plexus.archiver.FinalizerEnabled;
42 import org.codehaus.plexus.archiver.ResourceIterator;
43 import org.codehaus.plexus.archiver.util.DefaultArchivedFileSet;
44 import org.codehaus.plexus.archiver.util.DefaultFileSet;
45 import org.codehaus.plexus.components.io.fileselectors.FileInfo;
46 import org.codehaus.plexus.components.io.fileselectors.FileSelector;
47 import org.codehaus.plexus.components.io.resources.PlexusIoResource;
48 import org.codehaus.plexus.components.io.resources.PlexusIoResourceCollection;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52
53
54
55
56
57
58
59
60
61
62
63 public class AssemblyProxyArchiver implements Archiver {
64 private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyProxyArchiver.class);
65
66 private final Archiver delegate;
67
68 private final ThreadLocal<Boolean> inPublicApi = new ThreadLocal<>();
69
70 private final String assemblyWorkPath;
71
72 private String rootPrefix;
73
74 private FileSelector[] selectors;
75
76 private boolean forced;
77
78
79
80
81 private boolean useJvmChmod;
82
83 public AssemblyProxyArchiver(
84 final String rootPrefix,
85 final Archiver delegate,
86 final List<ContainerDescriptorHandler> containerDescriptorHandlers,
87 final List<FileSelector> extraSelectors,
88 final List<ArchiveFinalizer> extraFinalizers,
89 final File assemblyWorkDir) {
90 this.rootPrefix = rootPrefix;
91 this.delegate = delegate;
92
93 assemblyWorkPath = assemblyWorkDir.getAbsolutePath().replace('\\', '/');
94
95 if (!"".equals(rootPrefix) && !rootPrefix.endsWith("/")) {
96 this.rootPrefix += "/";
97 }
98
99 final List<FileSelector> selectors = new ArrayList<>();
100
101 FinalizerEnabled finalizer = (delegate instanceof FinalizerEnabled) ? (FinalizerEnabled) delegate : null;
102
103 if (containerDescriptorHandlers != null) {
104 for (final ContainerDescriptorHandler handler : containerDescriptorHandlers) {
105 selectors.add(handler);
106
107 if (finalizer != null) {
108 finalizer.addArchiveFinalizer(handler);
109 }
110 }
111 }
112
113 if (extraSelectors != null) {
114 selectors.addAll(extraSelectors);
115 }
116
117 if ((extraFinalizers != null) && finalizer != null) {
118 for (ArchiveFinalizer extraFinalizer : extraFinalizers) {
119 finalizer.addArchiveFinalizer(extraFinalizer);
120 }
121 }
122
123 if (!selectors.isEmpty()) {
124 this.selectors = selectors.toArray(new FileSelector[0]);
125 }
126 }
127
128
129
130
131 @Override
132 @Deprecated
133 public void addArchivedFileSet(
134 final File archiveFile, final String prefix, final String[] includes, final String[] excludes) {
135 inPublicApi.set(Boolean.TRUE);
136 try {
137 final DefaultArchivedFileSet fs = new DefaultArchivedFileSet(archiveFile);
138
139 fs.setIncludes(includes);
140 fs.setExcludes(excludes);
141 fs.setPrefix(rootPrefix + prefix);
142 fs.setFileSelectors(selectors);
143
144 debug("Adding archived file-set in: " + archiveFile + " to archive location: " + fs.getPrefix());
145
146 delegate.addArchivedFileSet(fs);
147 } finally {
148 inPublicApi.set(null);
149 }
150 }
151
152 private void debug(final String message) {
153 if (LOGGER.isDebugEnabled()) {
154 LOGGER.debug(message);
155 }
156 }
157
158
159
160
161 @Override
162 @Deprecated
163 public void addArchivedFileSet(final File archiveFile, final String prefix) {
164 inPublicApi.set(Boolean.TRUE);
165 try {
166 final DefaultArchivedFileSet fs = new DefaultArchivedFileSet(archiveFile);
167
168 fs.setPrefix(rootPrefix + prefix);
169 fs.setFileSelectors(selectors);
170
171 debug("Adding archived file-set in: " + archiveFile + " to archive location: " + fs.getPrefix());
172
173 delegate.addArchivedFileSet(fs);
174 } finally {
175 inPublicApi.set(null);
176 }
177 }
178
179
180
181
182 @Override
183 @Deprecated
184 public void addArchivedFileSet(final File archiveFile, final String[] includes, final String[] excludes) {
185 inPublicApi.set(Boolean.TRUE);
186 try {
187 final DefaultArchivedFileSet fs = new DefaultArchivedFileSet(archiveFile);
188
189 fs.setIncludes(includes);
190 fs.setExcludes(excludes);
191 fs.setPrefix(rootPrefix);
192 fs.setFileSelectors(selectors);
193
194 debug("Adding archived file-set in: " + archiveFile + " to archive location: " + fs.getPrefix());
195
196 delegate.addArchivedFileSet(fs);
197 } finally {
198 inPublicApi.set(null);
199 }
200 }
201
202
203
204
205 @Override
206 @Deprecated
207 public void addArchivedFileSet(final File archiveFile) {
208 inPublicApi.set(Boolean.TRUE);
209 try {
210 final DefaultArchivedFileSet fs = new DefaultArchivedFileSet(archiveFile);
211
212 fs.setPrefix(rootPrefix);
213 fs.setFileSelectors(selectors);
214
215 debug("Adding archived file-set in: " + archiveFile + " to archive location: " + fs.getPrefix());
216
217 delegate.addArchivedFileSet(fs);
218 } finally {
219 inPublicApi.set(null);
220 }
221 }
222
223
224
225
226 @Override
227 @Deprecated
228 public void addDirectory(
229 final File directory, final String prefix, final String[] includes, final String[] excludes) {
230 inPublicApi.set(Boolean.TRUE);
231 try {
232 final DefaultFileSet fs = new DefaultFileSet();
233
234 fs.setDirectory(directory);
235 fs.setIncludes(includes);
236 fs.setExcludes(excludes);
237 fs.setPrefix(rootPrefix + prefix);
238 fs.setFileSelectors(selectors);
239
240 debug("Adding directory file-set in: " + directory + " to archive location: " + fs.getPrefix());
241
242 doAddFileSet(fs);
243 } finally {
244 inPublicApi.set(null);
245 }
246 }
247
248
249
250
251 @Override
252 public void addSymlink(String symlinkName, String symlinkDestination) {
253 inPublicApi.set(Boolean.TRUE);
254 try {
255 delegate.addSymlink(symlinkName, symlinkDestination);
256 } finally {
257 inPublicApi.set(null);
258 }
259 }
260
261
262
263
264 @Override
265 public void addSymlink(String symlinkName, int permissions, String symlinkDestination) {
266 inPublicApi.set(Boolean.TRUE);
267 try {
268 delegate.addSymlink(symlinkName, permissions, symlinkDestination);
269 } finally {
270 inPublicApi.set(null);
271 }
272 }
273
274
275
276
277 @Override
278 @Deprecated
279 public void addDirectory(final File directory, final String prefix) {
280 inPublicApi.set(Boolean.TRUE);
281 try {
282 final DefaultFileSet fs = new DefaultFileSet();
283
284 fs.setDirectory(directory);
285 fs.setPrefix(rootPrefix + prefix);
286 fs.setFileSelectors(selectors);
287
288 debug("Adding directory file-set in: " + directory + " to archive location: " + fs.getPrefix());
289
290 doAddFileSet(fs);
291 } finally {
292 inPublicApi.set(null);
293 }
294 }
295
296
297
298
299 @Override
300 @Deprecated
301 public void addDirectory(final File directory, final String[] includes, final String[] excludes) {
302 inPublicApi.set(Boolean.TRUE);
303 try {
304 final DefaultFileSet fs = new DefaultFileSet();
305
306 fs.setDirectory(directory);
307 fs.setIncludes(includes);
308 fs.setExcludes(excludes);
309 fs.setPrefix(rootPrefix);
310 fs.setFileSelectors(selectors);
311
312 debug("Adding directory file-set in: " + directory + " to archive location: " + fs.getPrefix());
313
314 doAddFileSet(fs);
315 } finally {
316 inPublicApi.set(null);
317 }
318 }
319
320
321
322
323 @Override
324 @Deprecated
325 public void addDirectory(final File directory) {
326 inPublicApi.set(Boolean.TRUE);
327 try {
328 final DefaultFileSet fs = new DefaultFileSet();
329
330 fs.setDirectory(directory);
331 fs.setPrefix(rootPrefix);
332 fs.setFileSelectors(selectors);
333
334 debug("Adding directory file-set in: " + directory + " to archive location: " + fs.getPrefix());
335
336 doAddFileSet(fs);
337 } finally {
338 inPublicApi.set(null);
339 }
340 }
341
342
343
344
345 @Override
346 public void addFile(final File inputFile, final String destFileName, final int permissions) {
347 if (acceptFile(inputFile)) {
348 inPublicApi.set(Boolean.TRUE);
349 try {
350 debug("Adding file: " + inputFile + " to archive location: " + rootPrefix + destFileName);
351
352 delegate.addFile(inputFile, rootPrefix + destFileName, permissions);
353 } finally {
354 inPublicApi.set(null);
355 }
356 }
357 }
358
359
360
361
362 @Override
363 public void addFile(final File inputFile, final String destFileName) {
364 if (acceptFile(inputFile)) {
365 inPublicApi.set(Boolean.TRUE);
366 try {
367 debug("Adding file: " + inputFile + " to archive location: " + rootPrefix + destFileName);
368
369 delegate.addFile(inputFile, rootPrefix + destFileName);
370 } finally {
371 inPublicApi.set(null);
372 }
373 }
374 }
375
376
377
378
379 @Override
380 public void createArchive() throws IOException {
381 inPublicApi.set(Boolean.TRUE);
382 try {
383 delegate.setForced(forced);
384 delegate.createArchive();
385 } finally {
386 inPublicApi.set(null);
387 }
388 }
389
390
391
392
393 @Override
394 public int getDefaultDirectoryMode() {
395 inPublicApi.set(Boolean.TRUE);
396 try {
397 return delegate.getDefaultDirectoryMode();
398 } finally {
399 inPublicApi.set(null);
400 }
401 }
402
403
404
405
406 @Override
407 public void setDefaultDirectoryMode(final int mode) {
408 inPublicApi.set(Boolean.TRUE);
409 try {
410 delegate.setDefaultDirectoryMode(mode);
411 } finally {
412 inPublicApi.set(null);
413 }
414 }
415
416
417
418
419 @Override
420 public int getDefaultFileMode() {
421 inPublicApi.set(Boolean.TRUE);
422 try {
423 return delegate.getDefaultFileMode();
424 } finally {
425 inPublicApi.set(null);
426 }
427 }
428
429
430
431
432 @Override
433 public void setDefaultFileMode(final int mode) {
434 inPublicApi.set(Boolean.TRUE);
435 try {
436 delegate.setDefaultFileMode(mode);
437 } finally {
438 inPublicApi.set(null);
439 }
440 }
441
442
443
444
445 @Override
446 public File getDestFile() {
447 inPublicApi.set(Boolean.TRUE);
448 try {
449 return delegate.getDestFile();
450 } finally {
451 inPublicApi.set(null);
452 }
453 }
454
455
456
457
458 @Override
459 public void setDestFile(final File destFile) {
460 inPublicApi.set(Boolean.TRUE);
461 try {
462 delegate.setDestFile(destFile);
463 } finally {
464 inPublicApi.set(null);
465 }
466 }
467
468 @Override
469 @SuppressWarnings({"deprecation"})
470 public Map<String, ArchiveEntry> getFiles() {
471 inPublicApi.set(Boolean.TRUE);
472 try {
473 return delegate.getFiles();
474 } finally {
475 inPublicApi.set(null);
476 }
477 }
478
479
480
481
482 @Override
483 public boolean getIncludeEmptyDirs() {
484 inPublicApi.set(Boolean.TRUE);
485 try {
486 return delegate.getIncludeEmptyDirs();
487 } finally {
488 inPublicApi.set(null);
489 }
490 }
491
492
493
494
495 @Override
496 public void setIncludeEmptyDirs(final boolean includeEmptyDirs) {
497 inPublicApi.set(Boolean.TRUE);
498 try {
499 delegate.setIncludeEmptyDirs(includeEmptyDirs);
500 } finally {
501 inPublicApi.set(null);
502 }
503 }
504
505
506
507
508 @Override
509 public boolean isForced() {
510 inPublicApi.set(Boolean.TRUE);
511 try {
512 return delegate.isForced();
513 } finally {
514 inPublicApi.set(null);
515 }
516 }
517
518
519
520
521 @Override
522 public void setForced(final boolean forced) {
523 inPublicApi.set(Boolean.TRUE);
524 try {
525 this.forced = forced;
526 delegate.setForced(forced);
527 } finally {
528 inPublicApi.set(null);
529 }
530 }
531
532
533
534
535 @Override
536 public boolean isSupportingForced() {
537 inPublicApi.set(Boolean.TRUE);
538 try {
539 return delegate.isSupportingForced();
540 } finally {
541 inPublicApi.set(null);
542 }
543 }
544
545
546
547
548 @Override
549 public void setDotFileDirectory(final File dotFileDirectory) {
550 throw new UnsupportedOperationException("Undocumented feature of plexus-archiver; this is not yet supported.");
551 }
552
553
554
555
556 @Override
557 public void addArchivedFileSet(final ArchivedFileSet fileSet) {
558 inPublicApi.set(Boolean.TRUE);
559 try {
560 final PrefixedArchivedFileSet fs = new PrefixedArchivedFileSet(fileSet, rootPrefix, selectors);
561
562 debug("Adding archived file-set in: " + fileSet.getArchive() + " to archive location: " + fs.getPrefix());
563
564 delegate.addArchivedFileSet(fs);
565 } finally {
566 inPublicApi.set(null);
567 }
568 }
569
570 @Override
571 public void addArchivedFileSet(ArchivedFileSet archivedFileSet, Charset charset) {
572 inPublicApi.set(Boolean.TRUE);
573 try {
574 final PrefixedArchivedFileSet fs = new PrefixedArchivedFileSet(archivedFileSet, rootPrefix, selectors);
575
576 debug("Adding archived file-set in: " + archivedFileSet.getArchive() + " to archive location: "
577 + fs.getPrefix());
578
579 delegate.addArchivedFileSet(fs, charset);
580 } finally {
581 inPublicApi.set(null);
582 }
583 }
584
585
586
587
588 @Override
589 public void addFileSet(final FileSet fileSet) {
590 inPublicApi.set(Boolean.TRUE);
591 try {
592 final PrefixedFileSet fs = new PrefixedFileSet(fileSet, rootPrefix, selectors);
593
594 debug("Adding file-set in: " + fileSet.getDirectory() + " to archive location: " + fs.getPrefix());
595
596 doAddFileSet(fs);
597 } finally {
598 inPublicApi.set(null);
599 }
600 }
601
602 private void doAddFileSet(final FileSet fs) {
603 final String fsPath = fs.getDirectory().getAbsolutePath().replace('\\', '/');
604
605 if (fsPath.equals(assemblyWorkPath)) {
606 LOGGER.debug("SKIPPING fileset with source directory matching assembly working-directory: " + fsPath);
607 } else if (assemblyWorkPath.startsWith(fsPath)) {
608 final List<String> newEx = new ArrayList<>();
609 if (fs.getExcludes() != null) {
610 newEx.addAll(Arrays.asList(fs.getExcludes()));
611 }
612
613 final String workDirExclude = assemblyWorkPath.substring(fsPath.length() + 1);
614
615 LOGGER.debug("Adding exclude for assembly working-directory: " + workDirExclude
616 + "\nFile-Set source directory: " + fsPath);
617
618 newEx.add(workDirExclude);
619
620 final List<String> newIn = new ArrayList<>();
621 if (fs.getIncludes() != null) {
622 for (final String include : fs.getIncludes()) {
623 if (!include.startsWith(workDirExclude)) {
624 newIn.add(include);
625 }
626 }
627 }
628
629 final DefaultFileSet dfs = new DefaultFileSet();
630
631 dfs.setCaseSensitive(fs.isCaseSensitive());
632 dfs.setDirectory(fs.getDirectory());
633 dfs.setExcludes(newEx.toArray(new String[0]));
634 dfs.setFileSelectors(fs.getFileSelectors());
635 dfs.setIncludes(newIn.toArray(new String[0]));
636 dfs.setIncludingEmptyDirectories(fs.isIncludingEmptyDirectories());
637 dfs.setPrefix(fs.getPrefix());
638 dfs.setStreamTransformer(fs.getStreamTransformer());
639
640 delegate.addFileSet(dfs);
641 } else {
642 delegate.addFileSet(fs);
643 }
644 }
645
646 private boolean acceptFile(final File inputFile) {
647 if (!Boolean.TRUE.equals(inPublicApi.get())) {
648 if (selectors != null) {
649 final FileInfo fileInfo = new DefaultFileInfo(inputFile);
650
651 for (final FileSelector selector : selectors) {
652 try {
653 if (!selector.isSelected(fileInfo)) {
654 return false;
655 }
656 } catch (final IOException e) {
657 throw new ArchiverException(
658 "Error processing file: " + inputFile + " using selector: " + selector, e);
659 }
660 }
661 }
662 }
663
664 return true;
665 }
666
667
668
669
670 @Override
671 public void addResource(final PlexusIoResource resource, final String destFileName, final int permissions) {
672 File file = new File(resource.getName());
673 if (acceptFile(file)) {
674
675 inPublicApi.set(Boolean.TRUE);
676 try {
677 delegate.addResource(resource, rootPrefix + destFileName, permissions);
678 } finally {
679 inPublicApi.set(null);
680 }
681 }
682 }
683
684
685
686
687 @Override
688 public void addResources(final PlexusIoResourceCollection resources) {
689 inPublicApi.set(Boolean.TRUE);
690 try {
691 delegate.addResources(resources);
692 } finally {
693 inPublicApi.set(null);
694 }
695 }
696
697
698
699
700 @Override
701 public ResourceIterator getResources() {
702 return delegate.getResources();
703 }
704
705
706
707
708 @Override
709 public String getDuplicateBehavior() {
710 return delegate.getDuplicateBehavior();
711 }
712
713
714
715
716 @Override
717 public void setDuplicateBehavior(final String duplicate) {
718 inPublicApi.set(Boolean.TRUE);
719 try {
720 delegate.setDuplicateBehavior(duplicate);
721 } finally {
722 inPublicApi.set(null);
723 }
724 }
725
726
727
728
729 @Override
730 public int getDirectoryMode() {
731 return delegate.getDirectoryMode();
732 }
733
734
735
736
737 @Override
738 public void setDirectoryMode(final int mode) {
739 inPublicApi.set(Boolean.TRUE);
740 try {
741 delegate.setDirectoryMode(mode);
742 } finally {
743 inPublicApi.set(null);
744 }
745 }
746
747
748
749
750 @Override
751 public int getFileMode() {
752 return delegate.getFileMode();
753 }
754
755
756
757
758 @Override
759 public void setFileMode(final int mode) {
760 inPublicApi.set(Boolean.TRUE);
761 try {
762 delegate.setFileMode(mode);
763 } finally {
764 inPublicApi.set(null);
765 }
766 }
767
768
769
770
771 @Override
772 public int getOverrideDirectoryMode() {
773 return delegate.getOverrideDirectoryMode();
774 }
775
776
777
778
779 @Override
780 public int getOverrideFileMode() {
781 return delegate.getOverrideFileMode();
782 }
783
784
785
786
787 @Override
788 @Deprecated
789 public boolean isUseJvmChmod() {
790 return useJvmChmod;
791 }
792
793
794
795
796 @Override
797 @Deprecated
798 public void setUseJvmChmod(final boolean useJvmChmod) {
799 this.useJvmChmod = useJvmChmod;
800 }
801
802
803
804
805 @Override
806 public boolean isIgnorePermissions() {
807 return delegate.isIgnorePermissions();
808 }
809
810
811
812
813 @Override
814 public void setIgnorePermissions(final boolean ignorePermissions) {
815 delegate.setIgnorePermissions(ignorePermissions);
816 }
817
818 private static final class DefaultFileInfo implements FileInfo {
819
820 private final File inputFile;
821
822 DefaultFileInfo(final File inputFile) {
823 this.inputFile = inputFile;
824 }
825
826 @Override
827 public InputStream getContents() throws IOException {
828 return Files.newInputStream(inputFile.toPath());
829 }
830
831 @Override
832 public String getName() {
833 return inputFile.getName();
834 }
835
836 @Override
837 public boolean isDirectory() {
838 return inputFile.isDirectory();
839 }
840
841 @Override
842 public boolean isFile() {
843 return inputFile.isFile();
844 }
845
846 @Override
847 public boolean isSymbolicLink() {
848 return false;
849 }
850 }
851
852 @Override
853 @Deprecated
854 public void setLastModifiedDate(Date lastModifiedDate) {
855 delegate.setLastModifiedDate(lastModifiedDate);
856 }
857
858 @Override
859 @Deprecated
860 public Date getLastModifiedDate() {
861 return delegate.getLastModifiedDate();
862 }
863
864 @Override
865 public void setFilenameComparator(Comparator<String> filenameComparator) {
866 delegate.setFilenameComparator(filenameComparator);
867 }
868
869 @Override
870 @Deprecated
871 public void configureReproducible(Date outputTimestamp) {
872 delegate.configureReproducible(outputTimestamp);
873 }
874
875 @Override
876 public void setOverrideUid(int uid) {
877 delegate.setOverrideUid(uid);
878 }
879
880 @Override
881 public void setOverrideUserName(String userName) {
882 delegate.setOverrideUserName(userName);
883 }
884
885 @Override
886 public int getOverrideUid() {
887 return delegate.getOverrideUid();
888 }
889
890 @Override
891 public String getOverrideUserName() {
892 return delegate.getOverrideUserName();
893 }
894
895 @Override
896 public void setOverrideGid(int gid) {
897 delegate.setOverrideGid(gid);
898 }
899
900 @Override
901 public void setOverrideGroupName(String groupName) {
902 delegate.setOverrideGroupName(groupName);
903 }
904
905 @Override
906 public int getOverrideGid() {
907 return delegate.getOverrideGid();
908 }
909
910 @Override
911 public String getOverrideGroupName() {
912 return delegate.getOverrideGroupName();
913 }
914
915 @Override
916 public void setLastModifiedTime(FileTime fileTime) {
917 delegate.setLastModifiedTime(fileTime);
918 }
919
920 @Override
921 public FileTime getLastModifiedTime() {
922 return delegate.getLastModifiedTime();
923 }
924
925 @Override
926 public void setUmask(int umask) {
927 delegate.setUmask(umask);
928 }
929
930 @Override
931 public int getUmask() {
932 return delegate.getUmask();
933 }
934
935 @Override
936 public void configureReproducibleBuild(FileTime fileTime) {
937 delegate.configureReproducibleBuild(fileTime);
938 }
939 }