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