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