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