View Javadoc
1   package org.apache.maven.plugins.assembly.archive.archiver;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.plugins.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.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
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.nio.file.attribute.FileTime;
46  import java.util.ArrayList;
47  import java.util.Arrays;
48  import java.util.Comparator;
49  import java.util.Date;
50  import java.util.List;
51  import java.util.Map;
52  
53  /**
54   * Delegating archiver implementation that supports:
55   * <ul>
56   * <li>dry-running (where the delegate archiver is never actually called)</li>
57   * <li>prefixing (where all paths have a set global prefix prepended before addition)</li>
58   * <li>duplication checks on archive additions (for archive-file path + prefix)</li>
59   * </ul>
60   *
61   * @author jdcasey
62   *
63   */
64  public class AssemblyProxyArchiver implements Archiver
65  {
66      private static final Logger LOGGER = LoggerFactory.getLogger( AssemblyProxyArchiver.class );
67  
68      private final Archiver delegate;
69  
70      private final ThreadLocal<Boolean> inPublicApi = new ThreadLocal<>();
71  
72      private final String assemblyWorkPath;
73  
74      private String rootPrefix;
75  
76      private FileSelector[] selectors;
77  
78      private boolean forced;
79  
80      /**
81       * @since 2.2
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 )
89      {
90          this.rootPrefix = rootPrefix;
91          this.delegate = delegate;
92  
93          assemblyWorkPath = assemblyWorkDir.getAbsolutePath().replace( '\\', '/' );
94  
95          if ( !"".equals( rootPrefix ) && !rootPrefix.endsWith( "/" ) )
96          {
97              this.rootPrefix += "/";
98          }
99  
100         final List<FileSelector> selectors = new ArrayList<>();
101 
102         FinalizerEnabled finalizer = ( delegate instanceof FinalizerEnabled ) ? (FinalizerEnabled) delegate : null;
103 
104         if ( containerDescriptorHandlers != null )
105         {
106             for ( final ContainerDescriptorHandler handler : containerDescriptorHandlers )
107             {
108                 selectors.add( handler );
109 
110                 if ( finalizer != null )
111                 {
112                     finalizer.addArchiveFinalizer( handler );
113                 }
114             }
115         }
116 
117         if ( extraSelectors != null )
118         {
119             selectors.addAll( extraSelectors );
120         }
121 
122         if ( ( extraFinalizers != null ) && finalizer != null )
123         {
124             for ( ArchiveFinalizer extraFinalizer : extraFinalizers )
125             {
126                 finalizer.addArchiveFinalizer( extraFinalizer );
127             }
128         }
129 
130         if ( !selectors.isEmpty() )
131         {
132             this.selectors = selectors.toArray( new FileSelector[0] );
133         }
134     }
135 
136     /**
137      * {@inheritDoc}
138      */
139     @Override
140     public void addArchivedFileSet( final File archiveFile, final String prefix, final String[] includes,
141                                     final String[] excludes )
142     {
143         inPublicApi.set( Boolean.TRUE );
144         try
145         {
146             final DefaultArchivedFileSet fs = new DefaultArchivedFileSet( archiveFile );
147 
148             fs.setIncludes( includes );
149             fs.setExcludes( excludes );
150             fs.setPrefix( rootPrefix + prefix );
151             fs.setFileSelectors( selectors );
152 
153             debug( "Adding archived file-set in: " + archiveFile + " to archive location: " + fs.getPrefix() );
154 
155             delegate.addArchivedFileSet( fs );
156         }
157         finally
158         {
159             inPublicApi.set( null );
160         }
161     }
162 
163     private void debug( final String message )
164     {
165         if ( LOGGER.isDebugEnabled() )
166         {
167             LOGGER.debug( message );
168         }
169     }
170 
171     /**
172      * {@inheritDoc}
173      */
174     @Override
175     public void addArchivedFileSet( final File archiveFile, final String prefix )
176     {
177         inPublicApi.set( Boolean.TRUE );
178         try
179         {
180             final DefaultArchivedFileSet fs = new DefaultArchivedFileSet( archiveFile );
181 
182             fs.setPrefix( rootPrefix + prefix );
183             fs.setFileSelectors( selectors );
184 
185             debug( "Adding archived file-set in: " + archiveFile + " to archive location: " + fs.getPrefix() );
186 
187             delegate.addArchivedFileSet( fs );
188         }
189         finally
190         {
191             inPublicApi.set( null );
192         }
193     }
194 
195     /**
196      * {@inheritDoc}
197      */
198     @Override
199     public void addArchivedFileSet( final File archiveFile, final String[] includes, final String[] excludes )
200     {
201         inPublicApi.set( Boolean.TRUE );
202         try
203         {
204             final DefaultArchivedFileSet fs = new DefaultArchivedFileSet( archiveFile );
205 
206             fs.setIncludes( includes );
207             fs.setExcludes( excludes );
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         }
215         finally
216         {
217             inPublicApi.set( null );
218         }
219     }
220 
221     /**
222      * {@inheritDoc}
223      */
224     @Override
225     public void addArchivedFileSet( final File archiveFile )
226     {
227         inPublicApi.set( Boolean.TRUE );
228         try
229         {
230             final DefaultArchivedFileSet fs = new DefaultArchivedFileSet( archiveFile );
231 
232             fs.setPrefix( rootPrefix );
233             fs.setFileSelectors( selectors );
234 
235             debug( "Adding archived file-set in: " + archiveFile + " to archive location: " + fs.getPrefix() );
236 
237             delegate.addArchivedFileSet( fs );
238         }
239         finally
240         {
241             inPublicApi.set( null );
242         }
243     }
244 
245     /**
246      * {@inheritDoc}
247      */
248     @Override
249     public void addDirectory( final File directory, final String prefix, final String[] includes,
250                               final String[] excludes )
251     {
252         inPublicApi.set( Boolean.TRUE );
253         try
254         {
255             final DefaultFileSet fs = new DefaultFileSet();
256 
257             fs.setDirectory( directory );
258             fs.setIncludes( includes );
259             fs.setExcludes( excludes );
260             fs.setPrefix( rootPrefix + prefix );
261             fs.setFileSelectors( selectors );
262 
263             debug( "Adding directory file-set in: " + directory + " to archive location: " + fs.getPrefix() );
264 
265             doAddFileSet( fs );
266         }
267         finally
268         {
269             inPublicApi.set( null );
270         }
271     }
272 
273     /**
274      * {@inheritDoc}
275      */
276     @Override
277     public void addSymlink( String symlinkName, String symlinkDestination )
278     {
279         inPublicApi.set( Boolean.TRUE );
280         try
281         {
282             delegate.addSymlink( symlinkName, symlinkDestination );
283         }
284         finally
285         {
286             inPublicApi.set( null );
287         }
288 
289     }
290 
291     /**
292      * {@inheritDoc}
293      */
294     @Override
295     public void addSymlink( String symlinkName, int permissions, String symlinkDestination )
296     {
297         inPublicApi.set( Boolean.TRUE );
298         try
299         {
300             delegate.addSymlink( symlinkName, permissions, symlinkDestination );
301         }
302         finally
303         {
304             inPublicApi.set( null );
305         }
306 
307     }
308 
309     /**
310      * {@inheritDoc}
311      */
312     @Override
313     public void addDirectory( final File directory, final String prefix )
314     {
315         inPublicApi.set( Boolean.TRUE );
316         try
317         {
318             final DefaultFileSet fs = new DefaultFileSet();
319 
320             fs.setDirectory( directory );
321             fs.setPrefix( rootPrefix + prefix );
322             fs.setFileSelectors( selectors );
323 
324             debug( "Adding directory file-set in: " + directory + " to archive location: " + fs.getPrefix() );
325 
326             doAddFileSet( fs );
327         }
328         finally
329         {
330             inPublicApi.set( null );
331         }
332     }
333 
334     /**
335      * {@inheritDoc}
336      */
337     @Override
338     public void addDirectory( 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      * {@inheritDoc}
363      */
364     @Override
365     public void addDirectory( final File directory )
366     {
367         inPublicApi.set( Boolean.TRUE );
368         try
369         {
370             final DefaultFileSet fs = new DefaultFileSet();
371 
372             fs.setDirectory( directory );
373             fs.setPrefix( rootPrefix );
374             fs.setFileSelectors( selectors );
375 
376             debug( "Adding directory file-set in: " + directory + " to archive location: " + fs.getPrefix() );
377 
378             doAddFileSet( fs );
379         }
380         finally
381         {
382             inPublicApi.set( null );
383         }
384     }
385 
386     /**
387      * {@inheritDoc}
388      */
389     @Override
390     public void addFile( final File inputFile, final String destFileName, final int permissions )
391     {
392         if ( acceptFile( inputFile ) )
393         {
394             inPublicApi.set( Boolean.TRUE );
395             try
396             {
397                 debug( "Adding file: " + inputFile + " to archive location: " + rootPrefix + destFileName );
398 
399                 delegate.addFile( inputFile, rootPrefix + destFileName, permissions );
400             }
401             finally
402             {
403                 inPublicApi.set( null );
404             }
405         }
406     }
407 
408     /**
409      * {@inheritDoc}
410      */
411     @Override
412     public void addFile( final File inputFile, final String destFileName )
413     {
414         if ( acceptFile( inputFile ) )
415         {
416             inPublicApi.set( Boolean.TRUE );
417             try
418             {
419                 debug( "Adding file: " + inputFile + " to archive location: " + rootPrefix + destFileName );
420 
421                 delegate.addFile( inputFile, rootPrefix + destFileName );
422             }
423             finally
424             {
425                 inPublicApi.set( null );
426             }
427         }
428     }
429 
430     /**
431      * {@inheritDoc}
432      */
433     @Override
434     public void createArchive()
435         throws IOException
436     {
437         inPublicApi.set( Boolean.TRUE );
438         try
439         {
440             delegate.setForced( forced );
441             delegate.createArchive();
442         }
443         finally
444         {
445             inPublicApi.set( null );
446         }
447     }
448 
449     /**
450      * {@inheritDoc}
451      */
452     @Override
453     public int getDefaultDirectoryMode()
454     {
455         inPublicApi.set( Boolean.TRUE );
456         try
457         {
458             return delegate.getDefaultDirectoryMode();
459         }
460         finally
461         {
462             inPublicApi.set( null );
463         }
464     }
465 
466     /**
467      * {@inheritDoc}
468      */
469     @Override
470     public void setDefaultDirectoryMode( final int mode )
471     {
472         inPublicApi.set( Boolean.TRUE );
473         try
474         {
475             delegate.setDefaultDirectoryMode( mode );
476         }
477         finally
478         {
479             inPublicApi.set( null );
480         }
481     }
482 
483     /**
484      * {@inheritDoc}
485      */
486     @Override
487     public int getDefaultFileMode()
488     {
489         inPublicApi.set( Boolean.TRUE );
490         try
491         {
492             return delegate.getDefaultFileMode();
493         }
494         finally
495         {
496             inPublicApi.set( null );
497         }
498     }
499 
500     /**
501      * {@inheritDoc}
502      */
503     @Override
504     public void setDefaultFileMode( final int mode )
505     {
506         inPublicApi.set( Boolean.TRUE );
507         try
508         {
509             delegate.setDefaultFileMode( mode );
510         }
511         finally
512         {
513             inPublicApi.set( null );
514         }
515     }
516 
517     /**
518      * {@inheritDoc}
519      */
520     @Override
521     public File getDestFile()
522     {
523         inPublicApi.set( Boolean.TRUE );
524         try
525         {
526             return delegate.getDestFile();
527         }
528         finally
529         {
530             inPublicApi.set( null );
531         }
532     }
533 
534     /**
535      * {@inheritDoc}
536      */
537     @Override
538     public void setDestFile( final File destFile )
539     {
540         inPublicApi.set( Boolean.TRUE );
541         try
542         {
543             delegate.setDestFile( destFile );
544         }
545         finally
546         {
547             inPublicApi.set( null );
548         }
549     }
550 
551     @Override
552     @SuppressWarnings( { "deprecation" } )
553     public Map<String, ArchiveEntry> getFiles()
554     {
555         inPublicApi.set( Boolean.TRUE );
556         try
557         {
558             return delegate.getFiles();
559         }
560         finally
561         {
562             inPublicApi.set( null );
563         }
564     }
565 
566     /**
567      * {@inheritDoc}
568      */
569     @Override
570     public boolean getIncludeEmptyDirs()
571     {
572         inPublicApi.set( Boolean.TRUE );
573         try
574         {
575             return delegate.getIncludeEmptyDirs();
576         }
577         finally
578         {
579             inPublicApi.set( null );
580         }
581     }
582 
583     /**
584      * {@inheritDoc}
585      */
586     @Override
587     public void setIncludeEmptyDirs( final boolean includeEmptyDirs )
588     {
589         inPublicApi.set( Boolean.TRUE );
590         try
591         {
592             delegate.setIncludeEmptyDirs( includeEmptyDirs );
593         }
594         finally
595         {
596             inPublicApi.set( null );
597         }
598     }
599 
600     /**
601      * {@inheritDoc}
602      */
603     @Override
604     public boolean isForced()
605     {
606         inPublicApi.set( Boolean.TRUE );
607         try
608         {
609             return delegate.isForced();
610         }
611         finally
612         {
613             inPublicApi.set( null );
614         }
615     }
616 
617     /**
618      * {@inheritDoc}
619      */
620     @Override
621     public void setForced( final boolean forced )
622     {
623         inPublicApi.set( Boolean.TRUE );
624         try
625         {
626             this.forced = forced;
627             delegate.setForced( forced );
628         }
629         finally
630         {
631             inPublicApi.set( null );
632         }
633     }
634 
635     /**
636      * {@inheritDoc}
637      */
638     @Override
639     public boolean isSupportingForced()
640     {
641         inPublicApi.set( Boolean.TRUE );
642         try
643         {
644             return delegate.isSupportingForced();
645         }
646         finally
647         {
648             inPublicApi.set( null );
649         }
650     }
651 
652     /**
653      * {@inheritDoc}
654      */
655     @Override
656     public void setDotFileDirectory( final File dotFileDirectory )
657     {
658         throw new UnsupportedOperationException(
659             "Undocumented feature of plexus-archiver; this is not yet supported." );
660     }
661 
662     /**
663      * {@inheritDoc}
664      */
665     @Override
666     public void addArchivedFileSet( final ArchivedFileSet fileSet )
667     {
668         inPublicApi.set( Boolean.TRUE );
669         try
670         {
671             final PrefixedArchivedFileSet fs = new PrefixedArchivedFileSet( fileSet, rootPrefix, selectors );
672 
673             debug( "Adding archived file-set in: " + fileSet.getArchive() + " to archive location: " + fs.getPrefix() );
674 
675             delegate.addArchivedFileSet( fs );
676         }
677         finally
678         {
679             inPublicApi.set( null );
680         }
681     }
682 
683     @Override
684     public void addArchivedFileSet( ArchivedFileSet archivedFileSet, Charset charset )
685     {
686         inPublicApi.set( Boolean.TRUE );
687         try
688         {
689             final PrefixedArchivedFileSet fs = new PrefixedArchivedFileSet( archivedFileSet, rootPrefix, selectors );
690 
691             debug( "Adding archived file-set in: " + archivedFileSet.getArchive() + " to archive location: "
692                        + fs.getPrefix() );
693 
694             delegate.addArchivedFileSet( fs, charset );
695         }
696         finally
697         {
698             inPublicApi.set( null );
699         }
700     }
701 
702     /**
703      * {@inheritDoc}
704      */
705     @Override
706     public void addFileSet( final FileSet fileSet )
707     {
708         inPublicApi.set( Boolean.TRUE );
709         try
710         {
711             final PrefixedFileSet fs = new PrefixedFileSet( fileSet, rootPrefix, selectors );
712 
713             debug( "Adding file-set in: " + fileSet.getDirectory() + " to archive location: " + fs.getPrefix() );
714 
715             doAddFileSet( fs );
716         }
717         finally
718         {
719             inPublicApi.set( null );
720         }
721     }
722 
723     private void doAddFileSet( final FileSet fs )
724     {
725         final String fsPath = fs.getDirectory().getAbsolutePath().replace( '\\', '/' );
726 
727         if ( fsPath.equals( assemblyWorkPath ) )
728         {
729             LOGGER.debug(
730                     "SKIPPING fileset with source directory matching assembly working-directory: " + fsPath );
731         }
732         else if ( assemblyWorkPath.startsWith( fsPath ) )
733         {
734             final List<String> newEx = new ArrayList<>();
735             if ( fs.getExcludes() != null )
736             {
737                 newEx.addAll( Arrays.asList( fs.getExcludes() ) );
738             }
739 
740             final String workDirExclude = assemblyWorkPath.substring( fsPath.length() + 1 );
741 
742             LOGGER.debug(
743                 "Adding exclude for assembly working-directory: " + workDirExclude + "\nFile-Set source directory: "
744                     + fsPath );
745 
746             newEx.add( workDirExclude );
747 
748             final List<String> newIn = new ArrayList<>();
749             if ( fs.getIncludes() != null )
750             {
751                 for ( final String include : fs.getIncludes() )
752                 {
753                     if ( !include.startsWith( workDirExclude ) )
754                     {
755                         newIn.add( include );
756                     }
757                 }
758             }
759 
760             final DefaultFileSet dfs = new DefaultFileSet();
761 
762             dfs.setCaseSensitive( fs.isCaseSensitive() );
763             dfs.setDirectory( fs.getDirectory() );
764             dfs.setExcludes( newEx.toArray( new String[0] ) );
765             dfs.setFileSelectors( fs.getFileSelectors() );
766             dfs.setIncludes( newIn.toArray( new String[0] ) );
767             dfs.setIncludingEmptyDirectories( fs.isIncludingEmptyDirectories() );
768             dfs.setPrefix( fs.getPrefix() );
769             dfs.setStreamTransformer( fs.getStreamTransformer() );
770 
771             delegate.addFileSet( dfs );
772         }
773         else
774         {
775             delegate.addFileSet( fs );
776         }
777     }
778 
779     private boolean acceptFile( final File inputFile )
780     {
781         if ( !Boolean.TRUE.equals( inPublicApi.get() ) )
782         {
783             if ( selectors != null )
784             {
785                 final FileInfo fileInfo = new DefaultFileInfo( inputFile );
786 
787                 for ( final FileSelector selector : selectors )
788                 {
789                     try
790                     {
791                         if ( !selector.isSelected( fileInfo ) )
792                         {
793                             return false;
794                         }
795                     }
796                     catch ( final IOException e )
797                     {
798                         throw new ArchiverException(
799                             "Error processing file: " + inputFile + " using selector: " + selector, e );
800                     }
801                 }
802             }
803         }
804 
805         return true;
806     }
807 
808     /**
809      * {@inheritDoc}
810      */
811     @Override
812     public void addResource( final PlexusIoResource resource, final String destFileName, final int permissions )
813     {
814         File file = new File( resource.getName() ); // zOMG.
815         if ( acceptFile( file ) )
816         {
817 
818             inPublicApi.set( Boolean.TRUE );
819             try
820             {
821                 delegate.addResource( resource, rootPrefix + destFileName, permissions );
822             }
823             finally
824             {
825                 inPublicApi.set( null );
826             }
827         }
828     }
829 
830     /**
831      * {@inheritDoc}
832      */
833     @Override
834     public void addResources( final PlexusIoResourceCollection resources )
835     {
836         inPublicApi.set( Boolean.TRUE );
837         try
838         {
839             delegate.addResources( resources );
840         }
841         finally
842         {
843             inPublicApi.set( null );
844         }
845     }
846 
847     /**
848      * {@inheritDoc}
849      */
850     @Override
851     public ResourceIterator getResources()
852     {
853         return delegate.getResources();
854     }
855 
856     /**
857      * {@inheritDoc}
858      */
859     @Override
860     public String getDuplicateBehavior()
861     {
862         return delegate.getDuplicateBehavior();
863     }
864 
865     /**
866      * {@inheritDoc}
867      */
868     @Override
869     public void setDuplicateBehavior( final String duplicate )
870     {
871         inPublicApi.set( Boolean.TRUE );
872         try
873         {
874             delegate.setDuplicateBehavior( duplicate );
875         }
876         finally
877         {
878             inPublicApi.set( null );
879         }
880     }
881 
882     /**
883      * {@inheritDoc}
884      */
885     @Override
886     public int getDirectoryMode()
887     {
888         return delegate.getDirectoryMode();
889     }
890 
891     /**
892      * {@inheritDoc}
893      */
894     @Override
895     public void setDirectoryMode( final int mode )
896     {
897         inPublicApi.set( Boolean.TRUE );
898         try
899         {
900             delegate.setDirectoryMode( mode );
901         }
902         finally
903         {
904             inPublicApi.set( null );
905         }
906     }
907 
908     /**
909      * {@inheritDoc}
910      */
911     @Override
912     public int getFileMode()
913     {
914         return delegate.getFileMode();
915     }
916 
917     /**
918      * {@inheritDoc}
919      */
920     @Override
921     public void setFileMode( final int mode )
922     {
923         inPublicApi.set( Boolean.TRUE );
924         try
925         {
926             delegate.setFileMode( mode );
927         }
928         finally
929         {
930             inPublicApi.set( null );
931         }
932     }
933 
934     /**
935      * {@inheritDoc}
936      */
937     @Override
938     public int getOverrideDirectoryMode()
939     {
940         return delegate.getOverrideDirectoryMode();
941     }
942 
943     /**
944      * {@inheritDoc}
945      */
946     @Override
947     public int getOverrideFileMode()
948     {
949         return delegate.getOverrideFileMode();
950     }
951 
952     /**
953      * {@inheritDoc}
954      */
955     @Override
956     public boolean isUseJvmChmod()
957     {
958         return useJvmChmod;
959     }
960 
961     /**
962      * {@inheritDoc}
963      */
964     @Override
965     public void setUseJvmChmod( final boolean useJvmChmod )
966     {
967         this.useJvmChmod = useJvmChmod;
968     }
969 
970     /**
971      * {@inheritDoc}
972      */
973     @Override
974     public boolean isIgnorePermissions()
975     {
976         return delegate.isIgnorePermissions();
977     }
978 
979     /**
980      * {@inheritDoc}
981      */
982     @Override
983     public void setIgnorePermissions( final boolean ignorePermissions )
984     {
985         delegate.setIgnorePermissions( ignorePermissions );
986     }
987 
988     private static final class DefaultFileInfo
989         implements FileInfo
990     {
991 
992         private final File inputFile;
993 
994         DefaultFileInfo( final File inputFile )
995         {
996             this.inputFile = inputFile;
997         }
998 
999         @Override
1000         public InputStream getContents()
1001             throws IOException
1002         {
1003             return new FileInputStream( inputFile );
1004         }
1005 
1006         @Override
1007         public String getName()
1008         {
1009             return inputFile.getName();
1010         }
1011 
1012         @Override
1013         public boolean isDirectory()
1014         {
1015             return inputFile.isDirectory();
1016         }
1017 
1018         @Override
1019         public boolean isFile()
1020         {
1021             return inputFile.isFile();
1022         }
1023 
1024         @Override
1025         public boolean isSymbolicLink()
1026         {
1027             return false;
1028         }
1029     }
1030 
1031     @Override
1032     public void setLastModifiedDate( Date lastModifiedDate )
1033     {
1034         delegate.setLastModifiedDate( lastModifiedDate );
1035     }
1036 
1037     @Override
1038     public Date getLastModifiedDate()
1039     {
1040         return delegate.getLastModifiedDate();
1041     }
1042 
1043     @Override
1044     public void setFilenameComparator( Comparator<String> filenameComparator )
1045     {
1046         delegate.setFilenameComparator( filenameComparator );
1047     }
1048 
1049     @Override
1050     public void configureReproducible( Date outputTimestamp )
1051     {
1052         delegate.configureReproducible( outputTimestamp );
1053     }
1054 
1055     @Override
1056     public void setOverrideUid( int uid )
1057     {
1058         delegate.setOverrideUid( uid );
1059     }
1060 
1061     @Override
1062     public void setOverrideUserName( String userName )
1063     {
1064         delegate.setOverrideUserName( userName );
1065     }
1066 
1067     @Override
1068     public int getOverrideUid()
1069     {
1070         return delegate.getOverrideUid();
1071     }
1072 
1073     @Override
1074     public String getOverrideUserName()
1075     {
1076         return delegate.getOverrideUserName();
1077     }
1078 
1079     @Override
1080     public void setOverrideGid( int gid )
1081     {
1082         delegate.setOverrideGid( gid );
1083     }
1084 
1085     @Override
1086     public void setOverrideGroupName( String groupName )
1087     {
1088         delegate.setOverrideGroupName( groupName );
1089     }
1090 
1091     @Override
1092     public int getOverrideGid()
1093     {
1094         return delegate.getOverrideGid();
1095     }
1096 
1097     @Override
1098     public String getOverrideGroupName()
1099     {
1100         return delegate.getOverrideGroupName();
1101     }
1102 
1103     @Override
1104     public void setLastModifiedTime( FileTime fileTime )
1105     {
1106         delegate.setLastModifiedTime( fileTime );
1107     }
1108 
1109     @Override
1110     public FileTime getLastModifiedTime()
1111     {
1112         return delegate.getLastModifiedTime();
1113     }
1114 
1115     @Override
1116     public void configureReproducibleBuild( FileTime fileTime )
1117     {
1118         delegate.configureReproducibleBuild( fileTime );
1119     }
1120 }