View Javadoc
1   /*
2    * The MIT License
3    *
4    * Copyright (c) 2004, The Codehaus
5    *
6    * Permission is hereby granted, free of charge, to any person obtaining a copy of
7    * this software and associated documentation files (the "Software"), to deal in
8    * the Software without restriction, including without limitation the rights to
9    * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10   * of the Software, and to permit persons to whom the Software is furnished to do
11   * so, subject to the following conditions:
12   *
13   * The above copyright notice and this permission notice shall be included in all
14   * copies or substantial portions of the Software.
15   *
16   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22   * SOFTWARE.
23   */
24  package org.codehaus.plexus.archiver.zip;
25  
26  import java.io.ByteArrayInputStream;
27  import java.io.ByteArrayOutputStream;
28  import java.io.File;
29  import java.io.FileInputStream;
30  import java.io.FileWriter;
31  import java.io.IOException;
32  import java.io.InputStream;
33  import java.util.Arrays;
34  import java.util.Date;
35  import java.util.Enumeration;
36  import java.util.Map;
37  import java.util.zip.ZipEntry;
38  import java.util.zip.ZipInputStream;
39  import java.util.zip.ZipOutputStream;
40  import javax.annotation.Nonnull;
41  import org.apache.commons.compress.archivers.zip.ExtraFieldUtils;
42  import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
43  import org.apache.commons.compress.archivers.zip.ZipExtraField;
44  import org.apache.commons.compress.archivers.zip.ZipFile;
45  import org.apache.commons.compress.utils.BoundedInputStream;
46  import org.codehaus.plexus.archiver.Archiver;
47  import org.codehaus.plexus.archiver.ArchiverException;
48  import org.codehaus.plexus.archiver.BasePlexusArchiverTest;
49  import org.codehaus.plexus.archiver.UnArchiver;
50  import org.codehaus.plexus.archiver.UnixStat;
51  import org.codehaus.plexus.archiver.exceptions.EmptyArchiveException;
52  import org.codehaus.plexus.archiver.tar.TarArchiver;
53  import org.codehaus.plexus.archiver.tar.TarFile;
54  import org.codehaus.plexus.archiver.util.ArchiveEntryUtils;
55  import org.codehaus.plexus.archiver.util.DefaultArchivedFileSet;
56  import org.codehaus.plexus.archiver.util.DefaultFileSet;
57  import org.codehaus.plexus.archiver.util.Streams;
58  import org.codehaus.plexus.components.io.attributes.FileAttributes;
59  import org.codehaus.plexus.components.io.attributes.PlexusIoResourceAttributeUtils;
60  import org.codehaus.plexus.components.io.attributes.PlexusIoResourceAttributes;
61  import org.codehaus.plexus.components.io.attributes.SimpleResourceAttributes;
62  import org.codehaus.plexus.components.io.functions.InputStreamTransformer;
63  import org.codehaus.plexus.components.io.resources.PlexusIoFileResourceCollection;
64  import org.codehaus.plexus.components.io.resources.PlexusIoResource;
65  import org.codehaus.plexus.components.io.resources.ResourceFactory;
66  import org.codehaus.plexus.util.FileUtils;
67  import org.codehaus.plexus.util.IOUtil;
68  import org.codehaus.plexus.util.Os;
69  
70  /**
71   * @author Emmanuel Venisse
72   */
73  @SuppressWarnings( "OctalInteger" )
74  public class ZipArchiverTest
75      extends BasePlexusArchiverTest
76  {
77  
78      public void testImplicitPermissions()
79          throws IOException
80      {
81          File zipFile = getTestFile( "target/output/zip-with-implicit-dirmode.zip" );
82  
83          ZipArchiver archiver = getZipArchiver( zipFile );
84  
85          archiver.setDefaultDirectoryMode( 0777 );
86          archiver.setDirectoryMode( 0641 );
87          archiver.setFileMode( 0222 );
88          archiver.addFile( new File( "pom.xml" ), "fizz/buzz/pom.xml" );
89          archiver.setDefaultDirectoryMode( 0530 );
90          archiver.setDirectoryMode( -1 ); // Not forced mode
91          archiver.setFileMode( 0111 );
92          archiver.addFile( new File( "pom.xml" ), "fazz/bazz/pam.xml" );
93          archiver.createArchive();
94  
95          assertTrue( zipFile.exists() );
96          ZipFile zf = new ZipFile( zipFile );
97          ZipArchiveEntry fizz = zf.getEntry( "fizz/" );
98          assertEquals( 040641, fizz.getUnixMode() );
99          ZipArchiveEntry pom = zf.getEntry( "fizz/buzz/pom.xml" );
100         assertEquals( 0100222, pom.getUnixMode() );
101 
102         ZipArchiveEntry fazz = zf.getEntry( "fazz/" );
103         assertEquals( 040530, fazz.getUnixMode() );
104         ZipArchiveEntry pam = zf.getEntry( "fazz/bazz/pam.xml" );
105         assertEquals( 0100111, pam.getUnixMode() );
106     }
107 
108     public void testOveriddenPermissions()
109         throws IOException
110     {
111         if ( !Os.isFamily( Os.FAMILY_WINDOWS ) )
112         {
113             File zipFile = getTestFile( "target/output/zip-with-overriden-modes.zip" );
114 
115             ZipArchiver archiver = getZipArchiver( zipFile );
116             archiver.setDefaultDirectoryMode( 0777 );
117             archiver.setDirectoryMode( 0641 );
118             archiver.setFileMode( 0777 );
119             archiver.addDirectory( new File( "src/test/resources/symlinks/src" ) );
120             archiver.createArchive();
121 
122             assertTrue( zipFile.exists() );
123             ZipFile zf = new ZipFile( zipFile );
124             ZipArchiveEntry fizz = zf.getEntry( "symDir" );
125             assertTrue( fizz.isUnixSymlink() );
126             ZipArchiveEntry symR = zf.getEntry( "symR" );
127             assertTrue( symR.isUnixSymlink() );
128         }
129     }
130 
131     public void testCreateArchiveWithDetectedModes()
132         throws Exception
133     {
134 
135         String[] executablePaths =
136         {
137             "path/to/executable", "path/to/executable.bat"
138         };
139 
140         String[] confPaths =
141         {
142             "path/to/etc/file", "path/to/etc/file2"
143         };
144 
145         String[] logPaths =
146         {
147             "path/to/logs/log.txt"
148         };
149 
150         int exeMode = 0777;
151         int confMode = 0600;
152         int logMode = 0640;
153 
154         if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
155         {
156             StackTraceElement e = new Throwable().getStackTrace()[0];
157             System.out.println(
158                 "Cannot execute test: " + e.getMethodName() + " on " + System.getProperty( "os.name" ) );
159             return;
160         }
161 
162         File tmpDir = null;
163         try
164         {
165             tmpDir = File.createTempFile( "zip-with-chmod.", ".dir" );
166             tmpDir.delete();
167 
168             tmpDir.mkdirs();
169 
170             for ( String executablePath : executablePaths )
171             {
172                 writeFile( tmpDir, executablePath, exeMode );
173             }
174 
175             for ( String confPath : confPaths )
176             {
177                 writeFile( tmpDir, confPath, confMode );
178             }
179 
180             for ( String logPath : logPaths )
181             {
182                 writeFile( tmpDir, logPath, logMode );
183             }
184 
185             {
186                 Map<String, PlexusIoResourceAttributes> attributesByPath =
187                     PlexusIoResourceAttributeUtils.getFileAttributesByPath( tmpDir );
188                 for ( String path : executablePaths )
189                 {
190                     PlexusIoResourceAttributes attrs = attributesByPath.get( path );
191                     if ( attrs == null )
192                     {
193                         attrs = attributesByPath.get( new File( tmpDir, path ).getAbsolutePath() );
194                     }
195 
196                     assertNotNull( attrs );
197                     assertEquals( "Wrong mode for: " + path + "; expected: " + exeMode, exeMode, attrs.getOctalMode() );
198                 }
199 
200                 for ( String path : confPaths )
201                 {
202                     PlexusIoResourceAttributes attrs = attributesByPath.get( path );
203                     if ( attrs == null )
204                     {
205                         attrs = attributesByPath.get( new File( tmpDir, path ).getAbsolutePath() );
206                     }
207 
208                     assertNotNull( attrs );
209                     assertEquals( "Wrong mode for: " + path + "; expected: " + confMode, confMode,
210                                   attrs.getOctalMode() );
211                 }
212 
213                 for ( String path : logPaths )
214                 {
215                     PlexusIoResourceAttributes attrs = attributesByPath.get( path );
216                     if ( attrs == null )
217                     {
218                         attrs = attributesByPath.get( new File( tmpDir, path ).getAbsolutePath() );
219                     }
220 
221                     assertNotNull( attrs );
222                     assertEquals( "Wrong mode for: " + path + "; expected: " + logMode, logMode, attrs.getOctalMode() );
223                 }
224             }
225 
226             File zipFile = getTestFile( "target/output/zip-with-modes.zip" );
227 
228             ZipArchiver archiver = getZipArchiver( zipFile );
229 
230             archiver.addDirectory( tmpDir );
231             archiver.createArchive();
232 
233             assertTrue( zipFile.exists() );
234 
235             File zipFile2 = getTestFile( "target/output/zip-with-modes-L2.zip" );
236 
237             archiver = getZipArchiver();
238             archiver.setDestFile( zipFile2 );
239 
240             archiver.addArchivedFileSet( zipFile );
241             archiver.createArchive();
242 
243             ZipFile zf = new ZipFile( zipFile2 );
244 
245             for ( String path : executablePaths )
246             {
247                 ZipArchiveEntry ze = zf.getEntry( path );
248 
249                 int mode = ze.getUnixMode() & UnixStat.PERM_MASK;
250 
251                 assertEquals( "Wrong mode for: " + path + "; expected: " + exeMode, exeMode, mode );
252             }
253 
254             for ( String path : confPaths )
255             {
256                 ZipArchiveEntry ze = zf.getEntry( path );
257 
258                 int mode = ze.getUnixMode() & UnixStat.PERM_MASK;
259 
260                 assertEquals( "Wrong mode for: " + path + "; expected: " + confMode, confMode, mode );
261             }
262 
263             for ( String path : logPaths )
264             {
265                 ZipArchiveEntry ze = zf.getEntry( path );
266 
267                 int mode = ze.getUnixMode() & UnixStat.PERM_MASK;
268 
269                 assertEquals( "Wrong mode for: " + path + "; expected: " + logMode, logMode, mode );
270             }
271         }
272         finally
273         {
274             if ( tmpDir != null && tmpDir.exists() )
275             {
276                 try
277                 {
278                     FileUtils.forceDelete( tmpDir );
279                 }
280                 catch ( IOException e )
281                 {
282                     e.printStackTrace();
283                 }
284             }
285         }
286     }
287 
288     public void testCreateEmptyArchive()
289         throws Exception
290     {
291         ZipArchiver archiver = getZipArchiver();
292         archiver.setDestFile( getTestFile( "target/output/empty.zip" ) );
293         try
294         {
295             archiver.createArchive();
296 
297             fail( "Creating empty archive should throw EmptyArchiveException" );
298         }
299         catch ( EmptyArchiveException ignore )
300         {
301         }
302     }
303 
304     private ZipArchiver getZipArchiver()
305     {
306         try
307         {
308             return (ZipArchiver) lookup( Archiver.ROLE, "zip" );
309         }
310         catch ( Exception e )
311         {
312             throw new RuntimeException( e );
313         }
314     }
315 
316     private ZipArchiver getZipArchiver( File destFile )
317     {
318         final ZipArchiver zipArchiver = getZipArchiver();
319         zipArchiver.setDestFile( destFile );
320         return zipArchiver;
321     }
322 
323     private ZipUnArchiver getZipUnArchiver( File testJar )
324         throws Exception
325     {
326         ZipUnArchiver zu = (ZipUnArchiver) lookup( UnArchiver.ROLE, "zip" );
327         zu.setSourceFile( testJar );
328         return zu;
329     }
330 
331     private void writeFile( File dir, String fname, int mode )
332         throws IOException, ArchiverException
333     {
334         File file = new File( dir, fname );
335         FileWriter writer = null;
336 
337         try
338         {
339             if ( file.getParentFile() != null )
340             {
341                 file.getParentFile().mkdirs();
342             }
343 
344             writer = new FileWriter( file );
345             writer.write( "This is a test file." );
346             writer.close();
347             writer = null;
348         }
349         finally
350         {
351             IOUtil.close( writer );
352         }
353 
354         ArchiveEntryUtils.chmod( file, mode );
355     }
356 
357     public void testCreateArchive()
358         throws Exception
359     {
360         ZipArchiver archiver = newArchiver( "archive1.zip" );
361 
362         createArchive( archiver );
363     }
364 
365     public void testRecompressAddedZips() throws Exception
366     {
367         // check that by default the zip archives are re-compressed
368 
369         final File zipFileRecompress = getTestFile( "target/output/recompress-added-zips.zip" );
370         final ZipArchiver zipArchiverRecompress = getZipArchiver( zipFileRecompress );
371         zipArchiverRecompress.addDirectory( getTestFile( "src/test/jars" ) );
372         FileUtils.removePath( zipFileRecompress.getPath() );
373         zipArchiverRecompress.createArchive();
374 
375         final ZipFile zfRecompress = new ZipFile( zipFileRecompress );
376         assertEquals( ZipEntry.DEFLATED, zfRecompress.getEntry( "test.zip" ).getMethod() );
377         assertEquals( ZipEntry.DEFLATED, zfRecompress.getEntry( "test.jar" ).getMethod() );
378         assertEquals( ZipEntry.DEFLATED, zfRecompress.getEntry( "test.rar" ).getMethod() );
379         assertEquals( ZipEntry.DEFLATED, zfRecompress.getEntry( "test.tar.gz" ).getMethod() );
380         zfRecompress.close();
381 
382         // make sure the zip files are not re-compressed when recompressAddedZips is set to false
383 
384         final File zipFileDontRecompress = getTestFile( "target/output/dont-recompress-added-zips.zip" );
385         ZipArchiver zipArchiver = getZipArchiver( zipFileDontRecompress );
386         zipArchiver.addDirectory( getTestFile( "src/test/jars" ) );
387         zipArchiver.setRecompressAddedZips( false );
388         FileUtils.removePath( zipFileDontRecompress.getPath() );
389         zipArchiver.createArchive();
390 
391         final ZipFile zfDontRecompress = new ZipFile( zipFileDontRecompress );
392         final ZipArchiveEntry zipEntry = zfDontRecompress.getEntry( "test.zip" );
393         final ZipArchiveEntry jarEntry = zfDontRecompress.getEntry( "test.jar" );
394         final ZipArchiveEntry rarEntry = zfDontRecompress.getEntry( "test.rar" );
395         final ZipArchiveEntry tarEntry = zfDontRecompress.getEntry( "test.tar.gz" );
396         // check if only zip files are not compressed...
397         assertEquals( ZipEntry.STORED, zipEntry.getMethod() );
398         assertEquals( ZipEntry.STORED, jarEntry.getMethod() );
399         assertEquals( ZipEntry.STORED, rarEntry.getMethod() );
400         assertEquals( ZipEntry.DEFLATED, tarEntry.getMethod() );
401         // ...and no file is corrupted in the process
402         assertTrue( IOUtil.contentEquals( new FileInputStream( getTestFile( "src/test/jars/test.zip" ) ),
403                     zfDontRecompress.getInputStream( zipEntry ) ) );
404         assertTrue( IOUtil.contentEquals( new FileInputStream( getTestFile( "src/test/jars/test.jar" ) ),
405                 zfDontRecompress.getInputStream( jarEntry ) ) );
406         assertTrue( IOUtil.contentEquals( new FileInputStream( getTestFile( "src/test/jars/test.rar" ) ),
407                 zfDontRecompress.getInputStream( rarEntry ) ) );
408         assertTrue( IOUtil.contentEquals( new FileInputStream( getTestFile( "src/test/jars/test.tar.gz" ) ),
409                 zfDontRecompress.getInputStream( tarEntry ) ) );
410         zfDontRecompress.close();
411     }
412 
413     public void testAddArchivedFileSet()
414         throws Exception
415     {
416         File toBeAdded = new File( "src/test/resources/test.zip" );
417         DefaultArchivedFileSet sfd = DefaultArchivedFileSet.archivedFileSet( toBeAdded );
418         File zipFIle = getTestFile( "target/output/withZip.zip" );
419         final ZipArchiver zipArchiver = getZipArchiver( zipFIle );
420         InputStreamTransformer is = new InputStreamTransformer()
421         {
422 
423             @Nonnull
424             public InputStream transform( @Nonnull PlexusIoResource resource, @Nonnull InputStream inputStream )
425                 throws IOException
426             {
427                 return new BoundedInputStream( inputStream, 3 );
428             }
429 
430         };
431         sfd.setStreamTransformer( is );
432         zipArchiver.addArchivedFileSet( sfd );
433         zipArchiver.createArchive();
434 
435         final ZipUnArchiver zipUnArchiver = getZipUnArchiver( zipFIle );
436         File destFile = new File( "target/output/withZip" );
437         destFile.mkdirs();
438         zipUnArchiver.setDestFile( destFile );
439         zipUnArchiver.extract();
440         File a3byteFile = new File( destFile,
441                                     "Users/kristian/lsrc/plexus/plexus-archiver/src/main/java/org/codehaus/plexus/archiver/zip/ZipArchiver.java" );
442         assertTrue( a3byteFile.exists() );
443         assertTrue( a3byteFile.length() == 3 );
444     }
445 
446     public void testCreateArchiveWithStreamTransformer()
447         throws IOException
448     {
449         InputStreamTransformer is = new InputStreamTransformer()
450         {
451 
452             @Nonnull
453             @Override
454             public InputStream transform( @Nonnull PlexusIoResource resource, @Nonnull InputStream inputStream )
455                 throws IOException
456             {
457                 return new BoundedInputStream( inputStream, 3 );
458             }
459 
460         };
461 
462         final ZipArchiver zipArchiver = getZipArchiver( getTestFile( "target/output/all3bytes.zip" ) );
463         File zipFIle = new File( "src/test/resources/test.zip" );
464         DefaultArchivedFileSet afs = new DefaultArchivedFileSet( zipFIle );
465         afs.setStreamTransformer( is );
466         afs.setPrefix( "azip/" );
467         zipArchiver.addArchivedFileSet( afs );
468 
469         DefaultFileSet dfs = new DefaultFileSet( new File( "src/test/resources/mjar179" ) );
470         dfs.setStreamTransformer( is );
471         dfs.setPrefix( "mj179/" );
472         zipArchiver.addFileSet( dfs );
473 
474         PlexusIoFileResourceCollection files = new PlexusIoFileResourceCollection();
475         files.setBaseDir( new File( "src/test/resources" ) );
476         files.setStreamTransformer( is );
477         files.setPrefix( "plexus/" );
478         zipArchiver.addResources( files );
479 
480         zipArchiver.createArchive();
481 
482     }
483 
484     private ZipArchiver newArchiver( String name )
485         throws Exception
486     {
487         ZipArchiver archiver = getZipArchiver( getTestFile( "target/output/" + name ) );
488 
489         archiver.setFileMode( 0640 );
490         archiver.addFile( getTestFile( "src/test/resources/manifests/manifest1.mf" ), "one.txt" );
491         archiver.addFile( getTestFile( "src/test/resources/manifests/manifest2.mf" ), "two.txt", 0664 );
492 
493         // reset default file mode for files included from now on
494         archiver.setFileMode( 0400 );
495         archiver.setDirectoryMode( 0777 );
496         archiver.addDirectory( getTestFile( "src/test/resources/world-writable/" ), "worldwritable/" );
497 
498         archiver.setDirectoryMode( 0070 );
499         archiver.addDirectory( getTestFile( "src/test/resources/group-writable/" ), "groupwritable/" );
500 
501         archiver.setDirectoryMode( 0500 );
502         archiver.setFileMode( 0400 );
503         archiver.addDirectory( getTestFile( "src" ) );
504 
505         return archiver;
506     }
507 
508     private void fileModeAssert( int expected, int actual )
509     {
510         assertEquals( Integer.toString( expected, 8 ), Integer.toString( actual, 8 ) );
511     }
512 
513     private void createArchive( ZipArchiver archiver )
514         throws ArchiverException, IOException
515     {
516         archiver.createArchive();
517 
518         ZipFile zf = new ZipFile( archiver.getDestFile() );
519 
520         Enumeration e = zf.getEntries();
521 
522         while ( e.hasMoreElements() )
523         {
524             ZipArchiveEntry ze = (ZipArchiveEntry) e.nextElement();
525             if ( ze.isDirectory() )
526             {
527                 if ( ze.getName().startsWith( "worldwritable" ) )
528                 {
529                     fileModeAssert( 0777, UnixStat.PERM_MASK & ze.getUnixMode() );
530                 }
531                 else if ( ze.getName().startsWith( "groupwritable" ) )
532                 {
533                     fileModeAssert( 0070, UnixStat.PERM_MASK & ze.getUnixMode() );
534                 }
535                 else
536                 {
537                     fileModeAssert( 0500, UnixStat.PERM_MASK & ze.getUnixMode() );
538                 }
539             }
540             else
541             {
542                 if ( ze.getName().equals( "one.txt" ) )
543                 {
544                     fileModeAssert( 0640, UnixStat.PERM_MASK & ze.getUnixMode() );
545                 }
546                 else if ( ze.getName().equals( "two.txt" ) )
547                 {
548                     fileModeAssert( 0664, UnixStat.PERM_MASK & ze.getUnixMode() );
549                 }
550                 else if ( ze.isUnixSymlink() )
551                 {
552                     //         assertEquals( ze.getName(), 0500, UnixStat.PERM_MASK & ze.getUnixMode() );
553                 }
554                 else
555                 {
556                     fileModeAssert( 0400, UnixStat.PERM_MASK & ze.getUnixMode() );
557                 }
558             }
559 
560         }
561     }
562 
563     public void testSymlinkZip()
564         throws Exception
565     {
566         if ( !Os.isFamily( Os.FAMILY_WINDOWS ) )
567         {
568             final File zipFile = getTestFile( "target/output/pasymlinks.zip" );
569             final ZipArchiver zipArchiver = getZipArchiver( zipFile );
570             PlexusIoFileResourceCollection files = new PlexusIoFileResourceCollection();
571             files.setFollowingSymLinks( false );
572             files.setBaseDir( new File( "src/test/resources/symlinks" ) );
573             files.setPrefix( "plexus/" );
574             zipArchiver.addResources( files );
575             zipArchiver.createArchive();
576             final File output = getTestFile( "target/output/unzipped" );
577             output.mkdirs();
578             final ZipUnArchiver zipUnArchiver = getZipUnArchiver( zipFile );
579             zipUnArchiver.setDestFile( output );
580             zipUnArchiver.extract();
581             File symDir = new File( "target/output/unzipped/plexus/src/symDir" );
582             PlexusIoResourceAttributes fa = FileAttributes.uncached( symDir );
583             assertTrue( fa.isSymbolicLink() );
584         }
585     }
586 
587     @SuppressWarnings( "ResultOfMethodCallIgnored" )
588     public void testSymlinkFileSet()
589         throws Exception
590     {
591         if ( !Os.isFamily( Os.FAMILY_WINDOWS ) )
592         {
593             final File zipFile = getTestFile( "target/output/pasymlinks-fileset.zip" );
594             final ZipArchiver zipArchiver = getZipArchiver( zipFile );
595             final DefaultFileSet fs = new DefaultFileSet();
596             fs.setPrefix( "bzz/" );
597             fs.setDirectory( new File( "src/test/resources/symlinks/src" ) );
598             zipArchiver.addFileSet( fs );
599             zipArchiver.createArchive();
600             final File output = getTestFile( "target/output/unzipped/symlFs" );
601             output.mkdirs();
602             final ZipUnArchiver zipUnArchiver = getZipUnArchiver( zipFile );
603             zipUnArchiver.setDestFile( output );
604             zipUnArchiver.extract();
605             File symDir = new File( output, "bzz/symDir" );
606             PlexusIoResourceAttributes fa = FileAttributes.uncached( symDir );
607             assertTrue( fa.isSymbolicLink() );
608         }
609     }
610 
611     public void testSymlinkArchivedFileSet()
612         throws Exception
613     {
614         final File zipFile = getTestFile( "src/test/resources/symlinks/symlinks.zip" );
615         final File zipFile2 = getTestFile( "target/output/pasymlinks-archivedFileset.zip" );
616         final ZipArchiver zipArchiver = getZipArchiver( zipFile2 );
617         zipArchiver.addArchivedFileSet( zipFile );
618         zipArchiver.createArchive();
619 
620         final ZipFile cmp1 = new ZipFile( zipFile );
621         final ZipFile cmp2 = new ZipFile( zipFile2 );
622         ArchiveFileComparator.assertEquals( cmp1, cmp2, "" );
623     }
624 
625     /*
626      */
627     public void testForced()
628         throws Exception
629     {
630         ZipArchiver archiver = newArchiver( "archive2.zip" );
631 
632         assertTrue( archiver.isForced() );
633         File f = archiver.getDestFile();
634         if ( f.exists() )
635         {
636             FileUtils.fileDelete( f.getPath() );
637         }
638         assertFalse( f.exists() );
639         createArchive( archiver );
640         long l1 = f.lastModified();
641         assertTrue( f.exists() );
642 
643         archiver = newArchiver( "archive2.zip" );
644         waitUntilNewTimestamp( archiver.getDestFile(), l1 );
645         createArchive( archiver );
646         long l2 = f.lastModified();
647         assertTrue( f.exists() );
648         assertTrue( l2 > l1 );
649 
650         archiver = newArchiver( "archive2.zip" );
651         assertTrue( archiver.isSupportingForced() );
652         archiver.setForced( false );
653         assertFalse( archiver.isForced() );
654 
655         createArchive( archiver );
656         long l3 = f.lastModified();
657         assertTrue( f.exists() );
658         assertEquals( l2, l3 );
659     }
660 
661     // Used to investigate extrafields
662     public void testLookAtExtraZipFields_from_macos()
663         throws IOException
664     {
665         InputStream fis = Streams.fileInputStream( new File( "src/test/resources/zip-timestamp/macOsZipFile.zip" ) );
666         ZipInputStream zis = new ZipInputStream( fis );
667         final java.util.zip.ZipEntry evenEntry = zis.getNextEntry();
668         final ZipExtraField[] parse = ExtraFieldUtils.parse( evenEntry.getExtra() );
669         System.out.println( Arrays.asList( parse ) );
670         final java.util.zip.ZipEntry oddEntry = zis.getNextEntry();
671 
672         System.out.println( Arrays.asList( ExtraFieldUtils.parse( oddEntry.getExtra() ) ) );
673 
674         System.out.println( "oddEntry.getTime() = " + new Date( oddEntry.getTime() ).toString() );
675         System.out.println( "oddEntry.getName() = " + oddEntry.getName() );
676         System.out.println( "new String(oddEntry.getExtra()) = " + new String( oddEntry.getExtra() ) );
677         System.out.println( "evenEntry.getName() = " + evenEntry.getName() );
678         System.out.println( "evenEntry.getTime() = " + new Date( evenEntry.getTime() ).toString() );
679         System.out.println( "new String(evenEntry.getExtra()) = " + new String( evenEntry.getExtra() ) );
680 
681     }
682 
683     // Used to investigate date roundtrip behaviour across zip versions
684     public void testZipStuff()
685         throws IOException
686     {
687         ByteArrayOutputStream baos = new ByteArrayOutputStream();
688         ZipOutputStream zos = new ZipOutputStream( baos );
689         // name the file inside the zip  file
690         final File oddFile = new File( "src/test/resources/zip-timestamp/file-with-odd-time.txt" );
691         final File evenFile = new File( "src/test/resources/zip-timestamp/file-with-even-time.txt" );
692         final ZipEntry oddZe = new ZipEntry( oddFile.getName() );
693         oddZe.setTime( oddFile.lastModified() );
694         zos.putNextEntry( oddZe );
695         final ZipEntry evenZe = new ZipEntry( evenFile.getName() );
696         evenZe.setTime( evenFile.lastModified() );
697         zos.putNextEntry( evenZe );
698         zos.close();
699 
700         ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
701         ZipInputStream zipInputStream = new ZipInputStream( bais );
702         final java.util.zip.ZipEntry oddEntry = zipInputStream.getNextEntry();
703         System.out.println( "oddEntry.getTime() = " + new Date( oddEntry.getTime() ).toString() );
704         System.out.println( "oddEntry.getName() = " + oddEntry.getName() );
705         final java.util.zip.ZipEntry evenEntry = zipInputStream.getNextEntry();
706         System.out.println( "evenEntry.getName() = " + evenEntry.getName() );
707         System.out.println( "evenEntry.getTime() = " + new Date( evenEntry.getTime() ).toString() );
708     }
709 
710     public void notestJustThatOne()
711         throws Exception
712     {
713         final File srcDir = new File( "src" );
714         String[] inc =
715         {
716             "test/java/org/codehaus/plexus/archiver/zip/ZipShortTest.java"
717         };
718         final File zipFile = new File( "target/output/zz1.zip" );
719 
720         final File zipFile2 = new File( "target/output/zz2.zip" );
721         ZipArchiver zipArchiver2 = getZipArchiver( zipFile2 );
722 
723         // Bugbug: This does not work on 1.8....?
724         zipArchiver2.addArchivedFileSet( zipFile );
725         FileUtils.removePath( zipFile2.getPath() );
726         zipArchiver2.createArchive();
727     }
728 
729     public void testCreateResourceCollection()
730         throws Exception
731     {
732         final File srcDir = new File( "src" );
733         final File zipFile = new File( "target/output/src.zip" );
734         ZipArchiver zipArchiver = getZipArchiver( zipFile );
735         zipArchiver.addDirectory( srcDir, null, FileUtils.getDefaultExcludes() );
736         zipArchiver.setEncoding( "UTF-8" );
737         FileUtils.removePath( zipFile.getPath() );
738         zipArchiver.createArchive();
739 
740         final File zipFile2 = new File( "target/output/src2.zip" );
741         ZipArchiver zipArchiver2 = getZipArchiver( zipFile2 );
742         zipArchiver2.addArchivedFileSet( zipFile, "prfx/" );
743         zipArchiver2.setEncoding( "UTF-8" );
744         FileUtils.removePath( zipFile2.getPath() );
745         zipArchiver2.createArchive();
746 
747         final ZipFile cmp1 = new ZipFile( zipFile );
748         final ZipFile cmp2 = new ZipFile( zipFile2 );
749         ArchiveFileComparator.assertEquals( cmp1, cmp2, "prfx/" );
750         cmp1.close();
751         cmp2.close();
752     }
753 
754     public void testZipNonConcurrentResourceCollection()
755         throws Exception
756     {
757         final File tarFile = getTestFile( "target/output/zip-non-concurrent.tar" );
758         TarArchiver tarArchiver = (TarArchiver) lookup( Archiver.ROLE, "tar" );
759         tarArchiver.setDestFile( tarFile );
760         // We're testing concurrency issue so we need large amount of files
761         for ( int i = 0; i < 100; i++ )
762         {
763             tarArchiver.addFile( getTestFile( "src/test/resources/manifests/manifest1.mf" ),
764                                  "manifest1.mf" + i );
765             // Directories are added separately so let's test them too
766             tarArchiver.addFile( getTestFile( "src/test/resources/manifests/manifest2.mf" ),
767                                  "subdir" + i + "/manifest2.mf" );
768         }
769         tarArchiver.createArchive();
770 
771         final File zipFile = new File( "target/output/zip-non-concurrent.zip" );
772         ZipArchiver zipArchive = getZipArchiver( zipFile );
773         zipArchive.addArchivedFileSet( tarFile, "prfx/" );
774         zipArchive.setEncoding( "UTF-8" );
775         zipArchive.createArchive();
776 
777         final TarFile cmp1 = new TarFile( tarFile );
778         final ZipFile cmp2 = new ZipFile( zipFile );
779         ArchiveFileComparator.assertEquals( cmp1, cmp2, "prfx/" );
780         cmp1.close();
781         cmp2.close();
782     }
783 
784     public void testDefaultUTF8()
785         throws IOException
786     {
787         final ZipArchiver zipArchiver = getZipArchiver( new File( "target/output/utf8-default.zip" ) );
788         zipArchiver.addDirectory( new File( "src/test/resources/miscUtf8" ) );
789         zipArchiver.createArchive();
790     }
791 
792     public void testDefaultUTF8withUTF8()
793         throws IOException
794     {
795         final ZipArchiver zipArchiver = getZipArchiver( new File( "target/output/utf8-with_utf.zip" ) );
796         zipArchiver.setEncoding( "UTF-8" );
797         zipArchiver.addDirectory( new File( "src/test/resources/miscUtf8" ) );
798         zipArchiver.createArchive();
799     }
800 
801     public void testForcedFileModes()
802         throws IOException
803     {
804         File step1file = new File( "target/output/forced-file-mode.zip" );
805         {
806             final ZipArchiver zipArchiver = getZipArchiver( step1file );
807             zipArchiver.setFileMode( 0077 );
808             zipArchiver.setDirectoryMode( 0007 );
809             PlexusIoResourceAttributes attrs = new SimpleResourceAttributes( 123, "fred", 22, "filntstones", 0111 );
810             PlexusIoResource resource =
811                 ResourceFactory.createResource( new File( "src/test/resources/folders/File.txt" ), "Test.txt", null,
812                                                 attrs );
813             zipArchiver.addResource( resource, "Test2.txt", 0707 );
814             PlexusIoFileResourceCollection files = new PlexusIoFileResourceCollection();
815             files.setBaseDir( new File( "src/test/resources/folders" ) );
816             files.setPrefix( "sixsixsix/" );
817             zipArchiver.addResources( files );
818 
819             zipArchiver.createArchive();
820 
821             ZipFile zf = new ZipFile( step1file );
822             fileModeAssert( 040007, zf.getEntry( "sixsixsix/a/" ).getUnixMode() );
823             fileModeAssert( 0100077, zf.getEntry( "sixsixsix/b/FileInB.txt" ).getUnixMode() );
824             fileModeAssert( 0100707, zf.getEntry( "Test2.txt" ).getUnixMode() );
825             zf.close();
826         }
827 
828         File Step2file = new File( "target/output/forced-file-mode-from-zip.zip" );
829         {
830             final ZipArchiver za2 = getZipArchiver( Step2file );
831             za2.setFileMode( 0666 );
832             za2.setDirectoryMode( 0676 );
833 
834             PlexusIoZipFileResourceCollection zipSrc = new PlexusIoZipFileResourceCollection();
835             zipSrc.setFile( step1file );
836             zipSrc.setPrefix( "zz/" );
837             za2.addResources( zipSrc );
838             za2.createArchive();
839             ZipFile zf = new ZipFile( Step2file );
840             fileModeAssert( 040676, zf.getEntry( "zz/sixsixsix/a/" ).getUnixMode() );
841             fileModeAssert( 0100666, zf.getEntry( "zz/Test2.txt" ).getUnixMode() );
842             zf.close();
843         }
844 
845         File step3file = new File( "target/output/forced-file-mode-from-zip2.zip" );
846         {
847             final ZipArchiver za2 = getZipArchiver( step3file );
848             za2.setFileMode( 0666 );
849             za2.setDirectoryMode( 0676 );
850 
851             PlexusArchiverZipFileResourceCollection zipSrc = new PlexusArchiverZipFileResourceCollection();
852             zipSrc.setFile( step1file );
853             zipSrc.setPrefix( "zz/" );
854             za2.addResources( zipSrc );
855             za2.createArchive();
856             ZipFile zf = new ZipFile( Step2file );
857             fileModeAssert( 040676, zf.getEntry( "zz/sixsixsix/a/" ).getUnixMode() );
858             fileModeAssert( 0100666, zf.getEntry( "zz/Test2.txt" ).getUnixMode() );
859             zf.close();
860         }
861     }
862 
863 }