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.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   * Delegating archiver implementation that supports:
52   * <ul>
53   * <li>dry-running (where the delegate archiver is never actually called)</li>
54   * <li>prefixing (where all paths have a set global prefix prepended before addition)</li>
55   * <li>duplication checks on archive additions (for archive-file path + prefix)</li>
56   * </ul>
57   *
58   * @author jdcasey
59   *
60   */
61  public class AssemblyProxyArchiver
62      implements Archiver
63  {
64  
65      private final Archiver delegate;
66  
67      private final ThreadLocal<Boolean> inPublicApi = new ThreadLocal<>();
68  
69      private final Logger logger;
70  
71      private final String assemblyWorkPath;
72  
73      private String rootPrefix;
74  
75      private FileSelector[] selectors;
76  
77      private boolean forced;
78  
79      /**
80       * @since 2.2
81       */
82      private boolean useJvmChmod;
83  
84      public AssemblyProxyArchiver( final String rootPrefix, final Archiver delegate,
85                                    final List<ContainerDescriptorHandler> containerDescriptorHandlers,
86                                    final List<FileSelector> extraSelectors, final List<ArchiveFinalizer> extraFinalizers,
87                                    final File assemblyWorkDir, final Logger logger )
88      {
89          this.rootPrefix = rootPrefix;
90          this.delegate = delegate;
91  
92          assemblyWorkPath = assemblyWorkDir.getAbsolutePath().replace( '\\', '/' );
93  
94          this.logger = logger;
95  
96          if ( !"".equals( rootPrefix ) && !rootPrefix.endsWith( "/" ) )
97          {
98              this.rootPrefix += "/";
99          }
100 
101         final List<FileSelector> selectors = new ArrayList<>();
102 
103         FinalizerEnabled finalizer = ( delegate instanceof FinalizerEnabled ) ? (FinalizerEnabled) delegate : null;
104 
105         if ( containerDescriptorHandlers != null )
106         {
107             for ( final ContainerDescriptorHandler handler : containerDescriptorHandlers )
108             {
109                 selectors.add( handler );
110 
111                 if ( finalizer != null )
112                 {
113                     finalizer.addArchiveFinalizer( handler );
114                 }
115             }
116         }
117 
118         if ( extraSelectors != null )
119         {
120             selectors.addAll( extraSelectors );
121         }
122 
123         if ( ( extraFinalizers != null ) && finalizer != null )
124         {
125             for ( ArchiveFinalizer extraFinalizer : extraFinalizers )
126             {
127                 finalizer.addArchiveFinalizer( extraFinalizer );
128             }
129         }
130 
131         if ( !selectors.isEmpty() )
132         {
133             this.selectors = selectors.toArray( new FileSelector[selectors.size()] );
134         }
135     }
136 
137     /**
138      * {@inheritDoc}
139      */
140     @Override
141     public void addArchivedFileSet( @Nonnull final File archiveFile, final String prefix, final String[] includes,
142                                     final String[] excludes )
143     {
144         inPublicApi.set( Boolean.TRUE );
145         try
146         {
147             final DefaultArchivedFileSet fs = new DefaultArchivedFileSet( archiveFile );
148 
149             fs.setIncludes( includes );
150             fs.setExcludes( excludes );
151             fs.setPrefix( rootPrefix + prefix );
152             fs.setFileSelectors( selectors );
153 
154             debug( "Adding archived file-set in: " + archiveFile + " to archive location: " + fs.getPrefix() );
155 
156             delegate.addArchivedFileSet( fs );
157         }
158         finally
159         {
160             inPublicApi.set( null );
161         }
162     }
163 
164     private void debug( final String message )
165     {
166         if ( ( logger != null ) && logger.isDebugEnabled() )
167         {
168             logger.debug( message );
169         }
170     }
171 
172     /**
173      * {@inheritDoc}
174      */
175     @Override
176     public void addArchivedFileSet( @Nonnull final File archiveFile, final String prefix )
177     {
178         inPublicApi.set( Boolean.TRUE );
179         try
180         {
181             final DefaultArchivedFileSet fs = new DefaultArchivedFileSet( archiveFile );
182 
183             fs.setPrefix( rootPrefix + prefix );
184             fs.setFileSelectors( selectors );
185 
186             debug( "Adding archived file-set in: " + archiveFile + " to archive location: " + fs.getPrefix() );
187 
188             delegate.addArchivedFileSet( fs );
189         }
190         finally
191         {
192             inPublicApi.set( null );
193         }
194     }
195 
196     /**
197      * {@inheritDoc}
198      */
199     @Override
200     public void addArchivedFileSet( final File archiveFile, final String[] includes, final String[] excludes )
201     {
202         inPublicApi.set( Boolean.TRUE );
203         try
204         {
205             final DefaultArchivedFileSet fs = new DefaultArchivedFileSet( archiveFile );
206 
207             fs.setIncludes( includes );
208             fs.setExcludes( excludes );
209             fs.setPrefix( rootPrefix );
210             fs.setFileSelectors( selectors );
211 
212             debug( "Adding archived file-set in: " + archiveFile + " to archive location: " + fs.getPrefix() );
213 
214             delegate.addArchivedFileSet( fs );
215         }
216         finally
217         {
218             inPublicApi.set( null );
219         }
220     }
221 
222     /**
223      * {@inheritDoc}
224      */
225     @Override
226     public void addArchivedFileSet( @Nonnull final File archiveFile )
227     {
228         inPublicApi.set( Boolean.TRUE );
229         try
230         {
231             final DefaultArchivedFileSet fs = new DefaultArchivedFileSet( archiveFile );
232 
233             fs.setPrefix( rootPrefix );
234             fs.setFileSelectors( selectors );
235 
236             debug( "Adding archived file-set in: " + archiveFile + " to archive location: " + fs.getPrefix() );
237 
238             delegate.addArchivedFileSet( fs );
239         }
240         finally
241         {
242             inPublicApi.set( null );
243         }
244     }
245 
246     /**
247      * {@inheritDoc}
248      */
249     @Override
250     public void addDirectory( @Nonnull final File directory, final String prefix, final String[] includes,
251                               final String[] excludes )
252     {
253         inPublicApi.set( Boolean.TRUE );
254         try
255         {
256             final DefaultFileSet fs = new DefaultFileSet();
257 
258             fs.setDirectory( directory );
259             fs.setIncludes( includes );
260             fs.setExcludes( excludes );
261             fs.setPrefix( rootPrefix + prefix );
262             fs.setFileSelectors( selectors );
263 
264             debug( "Adding directory file-set in: " + directory + " to archive location: " + fs.getPrefix() );
265 
266             doAddFileSet( fs );
267         }
268         finally
269         {
270             inPublicApi.set( null );
271         }
272     }
273 
274     /**
275      * {@inheritDoc}
276      */
277     @Override
278     public void addSymlink( String symlinkName, String symlinkDestination )
279     {
280         inPublicApi.set( Boolean.TRUE );
281         try
282         {
283             delegate.addSymlink( symlinkName, symlinkDestination );
284         }
285         finally
286         {
287             inPublicApi.set( null );
288         }
289 
290     }
291 
292     /**
293      * {@inheritDoc}
294      */
295     @Override
296     public void addSymlink( String symlinkName, int permissions, String symlinkDestination )
297     {
298         inPublicApi.set( Boolean.TRUE );
299         try
300         {
301             delegate.addSymlink( symlinkName, permissions, symlinkDestination );
302         }
303         finally
304         {
305             inPublicApi.set( null );
306         }
307 
308     }
309 
310     /**
311      * {@inheritDoc}
312      */
313     @Override
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      * {@inheritDoc}
337      */
338     @Override
339     public void addDirectory( @Nonnull final File directory, final String[] includes, final String[] excludes )
340     {
341         inPublicApi.set( Boolean.TRUE );
342         try
343         {
344             final DefaultFileSet fs = new DefaultFileSet();
345 
346             fs.setDirectory( directory );
347             fs.setIncludes( includes );
348             fs.setExcludes( excludes );
349             fs.setPrefix( rootPrefix );
350             fs.setFileSelectors( selectors );
351 
352             debug( "Adding directory file-set in: " + directory + " to archive location: " + fs.getPrefix() );
353 
354             doAddFileSet( fs );
355         }
356         finally
357         {
358             inPublicApi.set( null );
359         }
360     }
361 
362     /**
363      * {@inheritDoc}
364      */
365     @Override
366     public void addDirectory( @Nonnull final File directory )
367     {
368         inPublicApi.set( Boolean.TRUE );
369         try
370         {
371             final DefaultFileSet fs = new DefaultFileSet();
372 
373             fs.setDirectory( directory );
374             fs.setPrefix( rootPrefix );
375             fs.setFileSelectors( selectors );
376 
377             debug( "Adding directory file-set in: " + directory + " to archive location: " + fs.getPrefix() );
378 
379             doAddFileSet( fs );
380         }
381         finally
382         {
383             inPublicApi.set( null );
384         }
385     }
386 
387     /**
388      * {@inheritDoc}
389      */
390     @Override
391     public void addFile( @Nonnull final File inputFile, @Nonnull final String destFileName, final int permissions )
392     {
393         if ( acceptFile( inputFile ) )
394         {
395             inPublicApi.set( Boolean.TRUE );
396             try
397             {
398                 debug( "Adding file: " + inputFile + " to archive location: " + rootPrefix + destFileName );
399 
400                 delegate.addFile( inputFile, rootPrefix + destFileName, permissions );
401             }
402             finally
403             {
404                 inPublicApi.set( null );
405             }
406         }
407     }
408 
409     /**
410      * {@inheritDoc}
411      */
412     @Override
413     public void addFile( @Nonnull final File inputFile, @Nonnull final String destFileName )
414     {
415         if ( acceptFile( inputFile ) )
416         {
417             inPublicApi.set( Boolean.TRUE );
418             try
419             {
420                 debug( "Adding file: " + inputFile + " to archive location: " + rootPrefix + destFileName );
421 
422                 delegate.addFile( inputFile, rootPrefix + destFileName );
423             }
424             finally
425             {
426                 inPublicApi.set( null );
427             }
428         }
429     }
430 
431     /**
432      * {@inheritDoc}
433      */
434     @Override
435     public void createArchive()
436         throws IOException
437     {
438         inPublicApi.set( Boolean.TRUE );
439         try
440         {
441             delegate.setForced( forced );
442             delegate.createArchive();
443         }
444         finally
445         {
446             inPublicApi.set( null );
447         }
448     }
449 
450     /**
451      * {@inheritDoc}
452      */
453     @Override
454     public int getDefaultDirectoryMode()
455     {
456         inPublicApi.set( Boolean.TRUE );
457         try
458         {
459             return delegate.getDefaultDirectoryMode();
460         }
461         finally
462         {
463             inPublicApi.set( null );
464         }
465     }
466 
467     /**
468      * {@inheritDoc}
469      */
470     @Override
471     public void setDefaultDirectoryMode( final int mode )
472     {
473         inPublicApi.set( Boolean.TRUE );
474         try
475         {
476             delegate.setDefaultDirectoryMode( mode );
477         }
478         finally
479         {
480             inPublicApi.set( null );
481         }
482     }
483 
484     /**
485      * {@inheritDoc}
486      */
487     @Override
488     public int getDefaultFileMode()
489     {
490         inPublicApi.set( Boolean.TRUE );
491         try
492         {
493             return delegate.getDefaultFileMode();
494         }
495         finally
496         {
497             inPublicApi.set( null );
498         }
499     }
500 
501     /**
502      * {@inheritDoc}
503      */
504     @Override
505     public void setDefaultFileMode( final int mode )
506     {
507         inPublicApi.set( Boolean.TRUE );
508         try
509         {
510             delegate.setDefaultFileMode( mode );
511         }
512         finally
513         {
514             inPublicApi.set( null );
515         }
516     }
517 
518     /**
519      * {@inheritDoc}
520      */
521     @Override
522     public File getDestFile()
523     {
524         inPublicApi.set( Boolean.TRUE );
525         try
526         {
527             return delegate.getDestFile();
528         }
529         finally
530         {
531             inPublicApi.set( null );
532         }
533     }
534 
535     /**
536      * {@inheritDoc}
537      */
538     @Override
539     public void setDestFile( final File destFile )
540     {
541         inPublicApi.set( Boolean.TRUE );
542         try
543         {
544             delegate.setDestFile( destFile );
545         }
546         finally
547         {
548             inPublicApi.set( null );
549         }
550     }
551 
552     @Override
553     @SuppressWarnings( { "deprecation" } )
554     public Map<String, ArchiveEntry> getFiles()
555     {
556         inPublicApi.set( Boolean.TRUE );
557         try
558         {
559             return delegate.getFiles();
560         }
561         finally
562         {
563             inPublicApi.set( null );
564         }
565     }
566 
567     /**
568      * {@inheritDoc}
569      */
570     @Override
571     public boolean getIncludeEmptyDirs()
572     {
573         inPublicApi.set( Boolean.TRUE );
574         try
575         {
576             return delegate.getIncludeEmptyDirs();
577         }
578         finally
579         {
580             inPublicApi.set( null );
581         }
582     }
583 
584     /**
585      * {@inheritDoc}
586      */
587     @Override
588     public void setIncludeEmptyDirs( final boolean includeEmptyDirs )
589     {
590         inPublicApi.set( Boolean.TRUE );
591         try
592         {
593             delegate.setIncludeEmptyDirs( includeEmptyDirs );
594         }
595         finally
596         {
597             inPublicApi.set( null );
598         }
599     }
600 
601     /**
602      * {@inheritDoc}
603      */
604     @Override
605     public boolean isForced()
606     {
607         inPublicApi.set( Boolean.TRUE );
608         try
609         {
610             return delegate.isForced();
611         }
612         finally
613         {
614             inPublicApi.set( null );
615         }
616     }
617 
618     /**
619      * {@inheritDoc}
620      */
621     @Override
622     public void setForced( final boolean forced )
623     {
624         inPublicApi.set( Boolean.TRUE );
625         try
626         {
627             this.forced = forced;
628             delegate.setForced( forced );
629         }
630         finally
631         {
632             inPublicApi.set( null );
633         }
634     }
635 
636     /**
637      * {@inheritDoc}
638      */
639     @Override
640     public boolean isSupportingForced()
641     {
642         inPublicApi.set( Boolean.TRUE );
643         try
644         {
645             return delegate.isSupportingForced();
646         }
647         finally
648         {
649             inPublicApi.set( null );
650         }
651     }
652 
653     /**
654      * {@inheritDoc}
655      */
656     @Override
657     public void setDotFileDirectory( final File dotFileDirectory )
658     {
659         throw new UnsupportedOperationException(
660             "Undocumented feature of plexus-archiver; this is not yet supported." );
661     }
662 
663     /**
664      * {@inheritDoc}
665      */
666     @Override
667     public void addArchivedFileSet( final ArchivedFileSet fileSet )
668     {
669         inPublicApi.set( Boolean.TRUE );
670         try
671         {
672             final PrefixedArchivedFileSet fs = new PrefixedArchivedFileSet( fileSet, rootPrefix, selectors );
673 
674             debug( "Adding archived file-set in: " + fileSet.getArchive() + " to archive location: " + fs.getPrefix() );
675 
676             delegate.addArchivedFileSet( fs );
677         }
678         finally
679         {
680             inPublicApi.set( null );
681         }
682     }
683 
684     @Override
685     public void addArchivedFileSet( ArchivedFileSet archivedFileSet, Charset charset )
686     {
687         inPublicApi.set( Boolean.TRUE );
688         try
689         {
690             final PrefixedArchivedFileSet fs = new PrefixedArchivedFileSet( archivedFileSet, rootPrefix, selectors );
691 
692             debug( "Adding archived file-set in: " + archivedFileSet.getArchive() + " to archive location: "
693                        + fs.getPrefix() );
694 
695             delegate.addArchivedFileSet( fs, charset );
696         }
697         finally
698         {
699             inPublicApi.set( null );
700         }
701     }
702 
703     /**
704      * {@inheritDoc}
705      */
706     @Override
707     public void addFileSet( @Nonnull final FileSet fileSet )
708     {
709         inPublicApi.set( Boolean.TRUE );
710         try
711         {
712             final PrefixedFileSet fs = new PrefixedFileSet( fileSet, rootPrefix, selectors );
713 
714             debug( "Adding file-set in: " + fileSet.getDirectory() + " to archive location: " + fs.getPrefix() );
715 
716             doAddFileSet( fs );
717         }
718         finally
719         {
720             inPublicApi.set( null );
721         }
722     }
723 
724     private void doAddFileSet( final FileSet fs )
725     {
726         final String fsPath = fs.getDirectory().getAbsolutePath().replace( '\\', '/' );
727 
728         if ( fsPath.equals( assemblyWorkPath ) )
729         {
730             logger.debug( "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[newEx.size()] ) );
765             dfs.setFileSelectors( fs.getFileSelectors() );
766             dfs.setIncludes( newIn.toArray( new String[newIn.size()] ) );
767             dfs.setIncludingEmptyDirectories( fs.isIncludingEmptyDirectories() );
768             dfs.setPrefix( fs.getPrefix() );
769             dfs.setUsingDefaultExcludes( fs.isUsingDefaultExcludes() );
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     @Nonnull
852     public ResourceIterator getResources()
853     {
854         return delegate.getResources();
855     }
856 
857     /**
858      * {@inheritDoc}
859      */
860     @Override
861     public String getDuplicateBehavior()
862     {
863         return delegate.getDuplicateBehavior();
864     }
865 
866     /**
867      * {@inheritDoc}
868      */
869     @Override
870     public void setDuplicateBehavior( final String duplicate )
871     {
872         inPublicApi.set( Boolean.TRUE );
873         try
874         {
875             delegate.setDuplicateBehavior( duplicate );
876         }
877         finally
878         {
879             inPublicApi.set( null );
880         }
881     }
882 
883     /**
884      * {@inheritDoc}
885      */
886     @Override
887     public int getDirectoryMode()
888     {
889         return delegate.getDirectoryMode();
890     }
891 
892     /**
893      * {@inheritDoc}
894      */
895     @Override
896     public void setDirectoryMode( final int mode )
897     {
898         inPublicApi.set( Boolean.TRUE );
899         try
900         {
901             delegate.setDirectoryMode( mode );
902         }
903         finally
904         {
905             inPublicApi.set( null );
906         }
907     }
908 
909     /**
910      * {@inheritDoc}
911      */
912     @Override
913     public int getFileMode()
914     {
915         return delegate.getFileMode();
916     }
917 
918     /**
919      * {@inheritDoc}
920      */
921     @Override
922     public void setFileMode( final int mode )
923     {
924         inPublicApi.set( Boolean.TRUE );
925         try
926         {
927             delegate.setFileMode( mode );
928         }
929         finally
930         {
931             inPublicApi.set( null );
932         }
933     }
934 
935     /**
936      * {@inheritDoc}
937      */
938     @Override
939     public int getOverrideDirectoryMode()
940     {
941         return delegate.getOverrideDirectoryMode();
942     }
943 
944     /**
945      * {@inheritDoc}
946      */
947     @Override
948     public int getOverrideFileMode()
949     {
950         return delegate.getOverrideFileMode();
951     }
952 
953     /**
954      * {@inheritDoc}
955      */
956     @Override
957     public boolean isUseJvmChmod()
958     {
959         return useJvmChmod;
960     }
961 
962     /**
963      * {@inheritDoc}
964      */
965     @Override
966     public void setUseJvmChmod( final boolean useJvmChmod )
967     {
968         this.useJvmChmod = useJvmChmod;
969     }
970 
971     /**
972      * {@inheritDoc}
973      */
974     @Override
975     public boolean isIgnorePermissions()
976     {
977         return delegate.isIgnorePermissions();
978     }
979 
980     /**
981      * {@inheritDoc}
982      */
983     @Override
984     public void setIgnorePermissions( final boolean ignorePermissions )
985     {
986         delegate.setIgnorePermissions( ignorePermissions );
987     }
988 
989     private static final class DefaultFileInfo
990         implements FileInfo
991     {
992 
993         private final File inputFile;
994 
995         DefaultFileInfo( final File inputFile )
996         {
997             this.inputFile = inputFile;
998         }
999 
1000         @Override
1001         public InputStream getContents()
1002             throws IOException
1003         {
1004             return new FileInputStream( inputFile );
1005         }
1006 
1007         @Override
1008         public String getName()
1009         {
1010             return inputFile.getName();
1011         }
1012 
1013         @Override
1014         public boolean isDirectory()
1015         {
1016             return inputFile.isDirectory();
1017         }
1018 
1019         @Override
1020         public boolean isFile()
1021         {
1022             return inputFile.isFile();
1023         }
1024 
1025         @Override
1026         public boolean isSymbolicLink()
1027         {
1028             return false;
1029         }
1030     }
1031 
1032 }