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