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