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