View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one or more
3    *  contributor license agreements.  See the NOTICE file distributed with
4    *  this work for additional information regarding copyright ownership.
5    *  The ASF licenses this file to You under the Apache License, Version 2.0
6    *  (the "License"); you may not use this file except in compliance with
7    *  the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   *
17   */
18  
19  package org.apache.commons.compress.archivers.zip;
20  
21  import static org.apache.commons.compress.AbstractTestCase.getFile;
22  import static org.junit.Assert.*;
23  
24  import java.io.ByteArrayOutputStream;
25  import java.io.File;
26  import java.io.FileInputStream;
27  import java.io.FileOutputStream;
28  import java.io.IOException;
29  import java.io.InputStream;
30  import java.io.OutputStream;
31  import java.nio.charset.Charset;
32  import java.util.ArrayList;
33  import java.util.Arrays;
34  import java.util.Collections;
35  import java.util.Enumeration;
36  import java.util.HashMap;
37  import java.util.Map;
38  import java.util.TreeMap;
39  import java.util.concurrent.atomic.AtomicInteger;
40  import java.util.zip.CRC32;
41  import java.util.zip.ZipEntry;
42  
43  import org.apache.commons.compress.utils.IOUtils;
44  import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
45  import org.junit.After;
46  import org.junit.Assert;
47  import org.junit.Test;
48  
49  public class ZipFileTest {
50      private ZipFile zf = null;
51  
52      @After
53      public void tearDown() {
54          ZipFile.closeQuietly(zf);
55      }
56  
57      @Test
58      public void testCDOrder() throws Exception {
59          readOrderTest();
60          final ArrayList<ZipArchiveEntry> l = Collections.list(zf.getEntries());
61          assertEntryName(l, 0, "AbstractUnicodeExtraField");
62          assertEntryName(l, 1, "AsiExtraField");
63          assertEntryName(l, 2, "ExtraFieldUtils");
64          assertEntryName(l, 3, "FallbackZipEncoding");
65          assertEntryName(l, 4, "GeneralPurposeBit");
66          assertEntryName(l, 5, "JarMarker");
67          assertEntryName(l, 6, "NioZipEncoding");
68          assertEntryName(l, 7, "Simple8BitZipEncoding");
69          assertEntryName(l, 8, "UnicodeCommentExtraField");
70          assertEntryName(l, 9, "UnicodePathExtraField");
71          assertEntryName(l, 10, "UnixStat");
72          assertEntryName(l, 11, "UnparseableExtraFieldData");
73          assertEntryName(l, 12, "UnrecognizedExtraField");
74          assertEntryName(l, 13, "ZipArchiveEntry");
75          assertEntryName(l, 14, "ZipArchiveInputStream");
76          assertEntryName(l, 15, "ZipArchiveOutputStream");
77          assertEntryName(l, 16, "ZipEncoding");
78          assertEntryName(l, 17, "ZipEncodingHelper");
79          assertEntryName(l, 18, "ZipExtraField");
80          assertEntryName(l, 19, "ZipUtil");
81          assertEntryName(l, 20, "ZipLong");
82          assertEntryName(l, 21, "ZipShort");
83          assertEntryName(l, 22, "ZipFile");
84      }
85  
86      @Test
87      public void testCDOrderInMemory() throws Exception {
88          byte[] data = null;
89          try (FileInputStream fis = new FileInputStream(getFile("ordertest.zip"))) {
90              data = IOUtils.toByteArray(fis);
91          }
92  
93          zf = new ZipFile(new SeekableInMemoryByteChannel(data), ZipEncodingHelper.UTF8);
94          final ArrayList<ZipArchiveEntry> l = Collections.list(zf.getEntries());
95          assertEntryName(l, 0, "AbstractUnicodeExtraField");
96          assertEntryName(l, 1, "AsiExtraField");
97          assertEntryName(l, 2, "ExtraFieldUtils");
98          assertEntryName(l, 3, "FallbackZipEncoding");
99          assertEntryName(l, 4, "GeneralPurposeBit");
100         assertEntryName(l, 5, "JarMarker");
101         assertEntryName(l, 6, "NioZipEncoding");
102         assertEntryName(l, 7, "Simple8BitZipEncoding");
103         assertEntryName(l, 8, "UnicodeCommentExtraField");
104         assertEntryName(l, 9, "UnicodePathExtraField");
105         assertEntryName(l, 10, "UnixStat");
106         assertEntryName(l, 11, "UnparseableExtraFieldData");
107         assertEntryName(l, 12, "UnrecognizedExtraField");
108         assertEntryName(l, 13, "ZipArchiveEntry");
109         assertEntryName(l, 14, "ZipArchiveInputStream");
110         assertEntryName(l, 15, "ZipArchiveOutputStream");
111         assertEntryName(l, 16, "ZipEncoding");
112         assertEntryName(l, 17, "ZipEncodingHelper");
113         assertEntryName(l, 18, "ZipExtraField");
114         assertEntryName(l, 19, "ZipUtil");
115         assertEntryName(l, 20, "ZipLong");
116         assertEntryName(l, 21, "ZipShort");
117         assertEntryName(l, 22, "ZipFile");
118     }
119 
120     @Test
121     public void testPhysicalOrder() throws Exception {
122         readOrderTest();
123         final ArrayList<ZipArchiveEntry> l = Collections.list(zf.getEntriesInPhysicalOrder());
124         assertEntryName(l, 0, "AbstractUnicodeExtraField");
125         assertEntryName(l, 1, "AsiExtraField");
126         assertEntryName(l, 2, "ExtraFieldUtils");
127         assertEntryName(l, 3, "FallbackZipEncoding");
128         assertEntryName(l, 4, "GeneralPurposeBit");
129         assertEntryName(l, 5, "JarMarker");
130         assertEntryName(l, 6, "NioZipEncoding");
131         assertEntryName(l, 7, "Simple8BitZipEncoding");
132         assertEntryName(l, 8, "UnicodeCommentExtraField");
133         assertEntryName(l, 9, "UnicodePathExtraField");
134         assertEntryName(l, 10, "UnixStat");
135         assertEntryName(l, 11, "UnparseableExtraFieldData");
136         assertEntryName(l, 12, "UnrecognizedExtraField");
137         assertEntryName(l, 13, "ZipArchiveEntry");
138         assertEntryName(l, 14, "ZipArchiveInputStream");
139         assertEntryName(l, 15, "ZipArchiveOutputStream");
140         assertEntryName(l, 16, "ZipEncoding");
141         assertEntryName(l, 17, "ZipEncodingHelper");
142         assertEntryName(l, 18, "ZipExtraField");
143         assertEntryName(l, 19, "ZipFile");
144         assertEntryName(l, 20, "ZipLong");
145         assertEntryName(l, 21, "ZipShort");
146         assertEntryName(l, 22, "ZipUtil");
147     }
148 
149     @Test
150     public void testDoubleClose() throws Exception {
151         readOrderTest();
152         zf.close();
153         try {
154             zf.close();
155         } catch (final Exception ex) {
156             fail("Caught exception of second close");
157         }
158     }
159 
160     @Test
161     public void testReadingOfStoredEntry() throws Exception {
162         final File f = File.createTempFile("commons-compress-zipfiletest", ".zip");
163         f.deleteOnExit();
164         OutputStream o = null;
165         InputStream i = null;
166         try {
167             o = new FileOutputStream(f);
168             final ZipArchiveOutputStream zo = new ZipArchiveOutputStream(o);
169             ZipArchiveEntry ze = new ZipArchiveEntry("foo");
170             ze.setMethod(ZipEntry.STORED);
171             ze.setSize(4);
172             ze.setCrc(0xb63cfbcdl);
173             zo.putArchiveEntry(ze);
174             zo.write(new byte[] { 1, 2, 3, 4 });
175             zo.closeArchiveEntry();
176             zo.close();
177             o.close();
178             o  = null;
179 
180             zf = new ZipFile(f);
181             ze = zf.getEntry("foo");
182             assertNotNull(ze);
183             i = zf.getInputStream(ze);
184             final byte[] b = new byte[4];
185             assertEquals(4, i.read(b));
186             assertEquals(-1, i.read());
187         } finally {
188             if (o != null) {
189                 o.close();
190             }
191             if (i != null) {
192                 i.close();
193             }
194             f.delete();
195         }
196     }
197 
198     /**
199      * @see "https://issues.apache.org/jira/browse/COMPRESS-176"
200      */
201     @Test
202     public void testWinzipBackSlashWorkaround() throws Exception {
203         final File archive = getFile("test-winzip.zip");
204         zf = new ZipFile(archive);
205         assertNull(zf.getEntry("\u00e4\\\u00fc.txt"));
206         assertNotNull(zf.getEntry("\u00e4/\u00fc.txt"));
207     }
208 
209     /**
210      * Test case for 
211      * <a href="https://issues.apache.org/jira/browse/COMPRESS-208"
212      * >COMPRESS-208</a>.
213      */
214     @Test
215     public void testSkipsPK00Prefix() throws Exception {
216         final File archive = getFile("COMPRESS-208.zip");
217         zf = new ZipFile(archive);
218         assertNotNull(zf.getEntry("test1.xml"));
219         assertNotNull(zf.getEntry("test2.xml"));
220     }
221 
222     @Test
223     public void testUnixSymlinkSampleFile() throws Exception {
224         final String entryPrefix = "COMPRESS-214_unix_symlinks/";
225         final TreeMap<String, String> expectedVals = new TreeMap<>();
226 
227         // I threw in some Japanese characters to keep things interesting.
228         expectedVals.put(entryPrefix + "link1", "../COMPRESS-214_unix_symlinks/./a/b/c/../../../\uF999");
229         expectedVals.put(entryPrefix + "link2", "../COMPRESS-214_unix_symlinks/./a/b/c/../../../g");
230         expectedVals.put(entryPrefix + "link3", "../COMPRESS-214_unix_symlinks/././a/b/c/../../../\u76F4\u6A39");
231         expectedVals.put(entryPrefix + "link4", "\u82B1\u5B50/\u745B\u5B50");
232         expectedVals.put(entryPrefix + "\uF999", "./\u82B1\u5B50/\u745B\u5B50/\u5897\u8C37/\uF999");
233         expectedVals.put(entryPrefix + "g", "./a/b/c/d/e/f/g");
234         expectedVals.put(entryPrefix + "\u76F4\u6A39", "./g");
235 
236         // Notice how a directory link might contain a trailing slash, or it might not.
237         // Also note:  symlinks are always stored as files, even if they link to directories.
238         expectedVals.put(entryPrefix + "link5", "../COMPRESS-214_unix_symlinks/././a/b");
239         expectedVals.put(entryPrefix + "link6", "../COMPRESS-214_unix_symlinks/././a/b/");
240 
241         // I looked into creating a test with hard links, but zip does not appear to
242         // support hard links, so nevermind.
243 
244         final File archive = getFile("COMPRESS-214_unix_symlinks.zip");
245 
246         zf = new ZipFile(archive);
247         final Enumeration<ZipArchiveEntry> en = zf.getEntries();
248         while (en.hasMoreElements()) {
249             final ZipArchiveEntry zae = en.nextElement();
250             final String link = zf.getUnixSymlink(zae);
251             if (zae.isUnixSymlink()) {
252                 final String name = zae.getName();
253                 final String expected = expectedVals.get(name);
254                 assertEquals(expected, link);
255             } else {
256                 // Should be null if it's not a symlink!
257                 assertNull(link);
258             }
259         }
260     }
261 
262     /**
263      * @see "https://issues.apache.org/jira/browse/COMPRESS-227"
264      */
265     @Test
266     public void testDuplicateEntry() throws Exception {
267         final File archive = getFile("COMPRESS-227.zip");
268         zf = new ZipFile(archive);
269 
270         final ZipArchiveEntry ze = zf.getEntry("test1.txt");
271         assertNotNull(ze);
272         assertNotNull(zf.getInputStream(ze));
273 
274         int numberOfEntries = 0;
275         for (final ZipArchiveEntry entry : zf.getEntries("test1.txt")) {
276             numberOfEntries++;
277             assertNotNull(zf.getInputStream(entry));
278         }
279         assertEquals(2, numberOfEntries);
280     }
281 
282     /**
283      * @see "https://issues.apache.org/jira/browse/COMPRESS-228"
284      */
285     @Test
286     public void testExcessDataInZip64ExtraField() throws Exception {
287         final File archive = getFile("COMPRESS-228.zip");
288         zf = new ZipFile(archive);
289         // actually, if we get here, the test already has passed
290 
291         final ZipArchiveEntry ze = zf.getEntry("src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java");
292         assertEquals(26101, ze.getSize());
293     }
294 
295     @Test
296     public void testUnshrinking() throws Exception {
297         zf = new ZipFile(getFile("SHRUNK.ZIP"));
298         ZipArchiveEntry test = zf.getEntry("TEST1.XML");
299         FileInputStream original = new FileInputStream(getFile("test1.xml"));
300         try {
301             assertArrayEquals(IOUtils.toByteArray(original),
302                               IOUtils.toByteArray(zf.getInputStream(test)));
303         } finally {
304             original.close();
305         }
306         test = zf.getEntry("TEST2.XML");
307         original = new FileInputStream(getFile("test2.xml"));
308         try {
309             assertArrayEquals(IOUtils.toByteArray(original),
310                               IOUtils.toByteArray(zf.getInputStream(test)));
311         } finally {
312             original.close();
313         }
314     }
315 
316     /**
317      * Test case for 
318      * <a href="https://issues.apache.org/jira/browse/COMPRESS-264"
319      * >COMPRESS-264</a>.
320      */
321     @Test
322     public void testReadingOfFirstStoredEntry() throws Exception {
323         final File archive = getFile("COMPRESS-264.zip");
324         zf = new ZipFile(archive);
325         final ZipArchiveEntry ze = zf.getEntry("test.txt");
326         assertEquals(5, ze.getSize());
327         assertArrayEquals(new byte[] {'d', 'a', 't', 'a', '\n'},
328                           IOUtils.toByteArray(zf.getInputStream(ze)));
329     }
330 
331     @Test
332     public void testUnzipBZip2CompressedEntry() throws Exception {
333         final File archive = getFile("bzip2-zip.zip");
334         zf = new ZipFile(archive);
335         final ZipArchiveEntry ze = zf.getEntry("lots-of-as");
336         assertEquals(42, ze.getSize());
337         final byte[] expected = new byte[42];
338         Arrays.fill(expected , (byte)'a');
339         assertArrayEquals(expected, IOUtils.toByteArray(zf.getInputStream(ze)));
340     }
341 
342     @Test
343     public void testConcurrentReadSeekable() throws Exception {
344         // mixed.zip contains both inflated and stored files
345         byte[] data = null;
346         try (FileInputStream fis = new FileInputStream(getFile("mixed.zip"))) {
347             data = IOUtils.toByteArray(fis);
348         }
349         zf = new ZipFile(new SeekableInMemoryByteChannel(data), ZipEncodingHelper.UTF8);
350 
351         final Map<String, byte[]> content = new HashMap<String, byte[]>();
352         for (ZipArchiveEntry entry: Collections.list(zf.getEntries())) {
353             content.put(entry.getName(), IOUtils.toByteArray(zf.getInputStream(entry)));
354         }
355 
356         final AtomicInteger passedCount = new AtomicInteger();
357         Runnable run = new Runnable() {
358             @Override
359             public void run() {
360                 for (ZipArchiveEntry entry: Collections.list(zf.getEntries())) {
361                     assertAllReadMethods(content.get(entry.getName()), zf, entry);
362                 }
363                 passedCount.incrementAndGet();
364             }
365         };
366         Thread t0 = new Thread(run);
367         Thread t1 = new Thread(run);
368         t0.start();
369         t1.start();
370         t0.join();
371         t1.join();
372         assertEquals(2, passedCount.get());
373     }
374 
375     @Test
376     public void testConcurrentReadFile() throws Exception {
377         // mixed.zip contains both inflated and stored files
378         final File archive = getFile("mixed.zip");
379         zf = new ZipFile(archive);
380 
381         final Map<String, byte[]> content = new HashMap<String, byte[]>();
382         for (ZipArchiveEntry entry: Collections.list(zf.getEntries())) {
383             content.put(entry.getName(), IOUtils.toByteArray(zf.getInputStream(entry)));
384         }
385 
386         final AtomicInteger passedCount = new AtomicInteger();
387         Runnable run = new Runnable() {
388             @Override
389             public void run() {
390                 for (ZipArchiveEntry entry: Collections.list(zf.getEntries())) {
391                     assertAllReadMethods(content.get(entry.getName()), zf, entry);
392                 }
393                 passedCount.incrementAndGet();
394             }
395         };
396         Thread t0 = new Thread(run);
397         Thread t1 = new Thread(run);
398         t0.start();
399         t1.start();
400         t0.join();
401         t1.join();
402         assertEquals(2, passedCount.get());
403     }
404 
405     /**
406      * Test correct population of header and data offsets.
407      */
408     @Test
409     public void testOffsets() throws Exception {
410         // mixed.zip contains both inflated and stored files
411         final File archive = getFile("mixed.zip");
412         try (ZipFile zf = new ZipFile(archive)) {
413             ZipArchiveEntry inflatedEntry = zf.getEntry("inflated.txt");
414             Assert.assertEquals(0x0000, inflatedEntry.getLocalHeaderOffset());
415             Assert.assertEquals(0x0046, inflatedEntry.getDataOffset());
416             Assert.assertTrue(inflatedEntry.isStreamContiguous());
417             ZipArchiveEntry storedEntry = zf.getEntry("stored.txt");
418             Assert.assertEquals(0x5892, storedEntry.getLocalHeaderOffset());
419             Assert.assertEquals(0x58d6, storedEntry.getDataOffset());
420             Assert.assertTrue(inflatedEntry.isStreamContiguous());
421         }
422     }
423 
424     /**
425      * Test correct population of header and data offsets when they are written after stream.
426      */
427     @Test
428     public void testDelayedOffsetsAndSizes() throws Exception {
429         ByteArrayOutputStream zipContent = new ByteArrayOutputStream();
430         try (ZipArchiveOutputStream zipOutput = new ZipArchiveOutputStream(zipContent)) {
431             ZipArchiveEntry inflatedEntry = new ZipArchiveEntry("inflated.txt");
432             inflatedEntry.setMethod(ZipEntry.DEFLATED);
433             zipOutput.putArchiveEntry(inflatedEntry);
434             zipOutput.write("Hello Deflated\n".getBytes());
435             zipOutput.closeArchiveEntry();
436 
437             byte[] storedContent = "Hello Stored\n".getBytes();
438             ZipArchiveEntry storedEntry = new ZipArchiveEntry("stored.txt");
439             storedEntry.setMethod(ZipEntry.STORED);
440             storedEntry.setSize(storedContent.length);
441             storedEntry.setCrc(calculateCrc32(storedContent));
442             zipOutput.putArchiveEntry(storedEntry);
443             zipOutput.write("Hello Stored\n".getBytes());
444             zipOutput.closeArchiveEntry();
445 
446         }
447 
448         try (ZipFile zf = new ZipFile(new SeekableInMemoryByteChannel(zipContent.toByteArray()))) {
449             ZipArchiveEntry inflatedEntry = zf.getEntry("inflated.txt");
450             Assert.assertNotEquals(-1L, inflatedEntry.getLocalHeaderOffset());
451             Assert.assertNotEquals(-1L, inflatedEntry.getDataOffset());
452             Assert.assertTrue(inflatedEntry.isStreamContiguous());
453             Assert.assertNotEquals(-1L, inflatedEntry.getCompressedSize());
454             Assert.assertNotEquals(-1L, inflatedEntry.getSize());
455             ZipArchiveEntry storedEntry = zf.getEntry("stored.txt");
456             Assert.assertNotEquals(-1L, storedEntry.getLocalHeaderOffset());
457             Assert.assertNotEquals(-1L, storedEntry.getDataOffset());
458             Assert.assertTrue(inflatedEntry.isStreamContiguous());
459             Assert.assertNotEquals(-1L, storedEntry.getCompressedSize());
460             Assert.assertNotEquals(-1L, storedEntry.getSize());
461         }
462     }
463 
464     /**
465      * Test entries alignment.
466      */
467     @Test
468     public void testEntryAlignment() throws Exception {
469         SeekableInMemoryByteChannel zipContent = new SeekableInMemoryByteChannel();
470         try (ZipArchiveOutputStream zipOutput = new ZipArchiveOutputStream(zipContent)) {
471             ZipArchiveEntry inflatedEntry = new ZipArchiveEntry("inflated.txt");
472             inflatedEntry.setMethod(ZipEntry.DEFLATED);
473             inflatedEntry.setAlignment(1024);
474             zipOutput.putArchiveEntry(inflatedEntry);
475             zipOutput.write("Hello Deflated\n".getBytes(Charset.forName("UTF-8")));
476             zipOutput.closeArchiveEntry();
477 
478             ZipArchiveEntry storedEntry = new ZipArchiveEntry("stored.txt");
479             storedEntry.setMethod(ZipEntry.STORED);
480             storedEntry.setAlignment(1024);
481             zipOutput.putArchiveEntry(storedEntry);
482             zipOutput.write("Hello Stored\n".getBytes(Charset.forName("UTF-8")));
483             zipOutput.closeArchiveEntry();
484 
485             ZipArchiveEntry storedEntry2 = new ZipArchiveEntry("stored2.txt");
486             storedEntry2.setMethod(ZipEntry.STORED);
487             storedEntry2.setAlignment(1024);
488             storedEntry2.addExtraField(new ResourceAlignmentExtraField(1));
489             zipOutput.putArchiveEntry(storedEntry2);
490             zipOutput.write("Hello overload-alignment Stored\n".getBytes(Charset.forName("UTF-8")));
491             zipOutput.closeArchiveEntry();
492 
493             ZipArchiveEntry storedEntry3 = new ZipArchiveEntry("stored3.txt");
494             storedEntry3.setMethod(ZipEntry.STORED);
495             storedEntry3.addExtraField(new ResourceAlignmentExtraField(1024));
496             zipOutput.putArchiveEntry(storedEntry3);
497             zipOutput.write("Hello copy-alignment Stored\n".getBytes(Charset.forName("UTF-8")));
498             zipOutput.closeArchiveEntry();
499 
500         }
501 
502         try (ZipFile zf = new ZipFile(new SeekableInMemoryByteChannel(
503                         Arrays.copyOfRange(zipContent.array(), 0, (int)zipContent.size())
504         ))) {
505             ZipArchiveEntry inflatedEntry = zf.getEntry("inflated.txt");
506             ResourceAlignmentExtraField inflatedAlignmentEx =
507                             (ResourceAlignmentExtraField)inflatedEntry.getExtraField(ResourceAlignmentExtraField.ID);
508             assertNotEquals(-1L, inflatedEntry.getCompressedSize());
509             assertNotEquals(-1L, inflatedEntry.getSize());
510             assertEquals(0L, inflatedEntry.getDataOffset()%1024);
511             assertNotNull(inflatedAlignmentEx);
512             assertEquals(1024, inflatedAlignmentEx.getAlignment());
513             assertFalse(inflatedAlignmentEx.allowMethodChange());
514             try (InputStream stream = zf.getInputStream(inflatedEntry)) {
515                 Assert.assertEquals("Hello Deflated\n",
516                                 new String(IOUtils.toByteArray(stream), Charset.forName("UTF-8")));
517             }
518             ZipArchiveEntry storedEntry = zf.getEntry("stored.txt");
519             ResourceAlignmentExtraField storedAlignmentEx =
520                             (ResourceAlignmentExtraField)storedEntry.getExtraField(ResourceAlignmentExtraField.ID);
521             assertNotEquals(-1L, storedEntry.getCompressedSize());
522             assertNotEquals(-1L, storedEntry.getSize());
523             assertEquals(0L, storedEntry.getDataOffset()%1024);
524             assertNotNull(storedAlignmentEx);
525             assertEquals(1024, storedAlignmentEx.getAlignment());
526             assertFalse(storedAlignmentEx.allowMethodChange());
527             try (InputStream stream = zf.getInputStream(storedEntry)) {
528                 Assert.assertEquals("Hello Stored\n",
529                                 new String(IOUtils.toByteArray(stream), Charset.forName("UTF-8")));
530             }
531 
532             ZipArchiveEntry storedEntry2 = zf.getEntry("stored2.txt");
533             ResourceAlignmentExtraField stored2AlignmentEx =
534                             (ResourceAlignmentExtraField)storedEntry2.getExtraField(ResourceAlignmentExtraField.ID);
535             assertNotEquals(-1L, storedEntry2.getCompressedSize());
536             assertNotEquals(-1L, storedEntry2.getSize());
537             assertEquals(0L, storedEntry2.getDataOffset()%1024);
538             assertNotNull(stored2AlignmentEx);
539             assertEquals(1024, stored2AlignmentEx.getAlignment());
540             assertFalse(stored2AlignmentEx.allowMethodChange());
541             try (InputStream stream = zf.getInputStream(storedEntry2)) {
542                 Assert.assertEquals("Hello overload-alignment Stored\n",
543                                 new String(IOUtils.toByteArray(stream), Charset.forName("UTF-8")));
544             }
545 
546             ZipArchiveEntry storedEntry3 = zf.getEntry("stored3.txt");
547             ResourceAlignmentExtraField stored3AlignmentEx =
548                             (ResourceAlignmentExtraField)storedEntry3.getExtraField(ResourceAlignmentExtraField.ID);
549             assertNotEquals(-1L, storedEntry3.getCompressedSize());
550             assertNotEquals(-1L, storedEntry3.getSize());
551             assertEquals(0L, storedEntry3.getDataOffset()%1024);
552             assertNotNull(stored3AlignmentEx);
553             assertEquals(1024, stored3AlignmentEx.getAlignment());
554             assertFalse(stored3AlignmentEx.allowMethodChange());
555             try (InputStream stream = zf.getInputStream(storedEntry3)) {
556                 Assert.assertEquals("Hello copy-alignment Stored\n",
557                                 new String(IOUtils.toByteArray(stream), Charset.forName("UTF-8")));
558             }
559         }
560     }
561 
562     /**
563      * Test too big alignment, resulting into exceeding extra field limit.
564      */
565     @Test(expected = IllegalArgumentException.class)
566     public void testEntryAlignmentExceed() throws Exception {
567         SeekableInMemoryByteChannel zipContent = new SeekableInMemoryByteChannel();
568         try (ZipArchiveOutputStream zipOutput = new ZipArchiveOutputStream(zipContent)) {
569             ZipArchiveEntry inflatedEntry = new ZipArchiveEntry("inflated.txt");
570             inflatedEntry.setMethod(ZipEntry.STORED);
571             inflatedEntry.setAlignment(0x20000);
572         }
573     }
574 
575     /**
576      * Test non power of 2 alignment.
577      */
578     @Test(expected = IllegalArgumentException.class)
579     public void testInvalidAlignment() throws Exception {
580         ZipArchiveEntry entry = new ZipArchiveEntry("dummy");
581         entry.setAlignment(3);
582     }
583 
584     private void assertAllReadMethods(byte[] expected, ZipFile zipFile, ZipArchiveEntry entry) {
585         // simple IOUtil read
586         try (InputStream stream = zf.getInputStream(entry)) {
587             byte[] full = IOUtils.toByteArray(stream);
588             assertArrayEquals(expected, full);
589         }
590         catch (IOException ex) {
591             throw new RuntimeException(ex);
592         }
593 
594         // big buffer at the beginning and then chunks by IOUtils read
595         try (InputStream stream = zf.getInputStream(entry)) {
596             byte[] full;
597             byte[] bytes = new byte[0x40000];
598             int read = stream.read(bytes);
599             if (read < 0) {
600                 full = new byte[0];
601             }
602             else {
603                 full = readStreamRest(bytes, read, stream);
604             }
605             assertArrayEquals(expected, full);
606         }
607         catch (IOException ex) {
608             throw new RuntimeException(ex);
609         }
610 
611         // small chunk / single byte and big buffer then
612         try (InputStream stream = zf.getInputStream(entry)) {
613             byte[] full;
614             int single = stream.read();
615             if (single < 0) {
616                 full = new byte[0];
617             }
618             else {
619                 byte[] big = new byte[0x40000];
620                 big[0] = (byte)single;
621                 int read = stream.read(big, 1, big.length-1);
622                 if (read < 0) {
623                     full = new byte[]{ (byte)single };
624                 }
625                 else {
626                     full = readStreamRest(big, read+1, stream);
627                 }
628             }
629             assertArrayEquals(expected, full);
630         }
631         catch (IOException ex) {
632             throw new RuntimeException(ex);
633         }
634     }
635 
636     /**
637      * Utility to append the rest of the stream to already read data.
638      */
639     private byte[] readStreamRest(byte[] beginning, int length, InputStream stream) throws IOException {
640         byte[] rest = IOUtils.toByteArray(stream);
641         byte[] full = new byte[length+rest.length];
642         System.arraycopy(beginning, 0, full, 0, length);
643         System.arraycopy(rest, 0, full, length, rest.length);
644         return full;
645     }
646 
647     private long calculateCrc32(byte[] content) {
648         CRC32 crc = new CRC32();
649         crc.update(content);
650         return crc.getValue();
651     }
652 
653     /*
654      * ordertest.zip has been handcrafted.
655      *
656      * It contains enough files so any random coincidence of
657      * entries.keySet() and central directory order would be unlikely
658      * - in fact testCDOrder fails in svn revision 920284.
659      *
660      * The central directory has ZipFile and ZipUtil swapped so
661      * central directory order is different from entry data order.
662      */
663     private void readOrderTest() throws Exception {
664         final File archive = getFile("ordertest.zip");
665         zf = new ZipFile(archive);
666     }
667 
668     private static void assertEntryName(final ArrayList<ZipArchiveEntry> entries,
669                                         final int index,
670                                         final String expectedName) {
671         final ZipArchiveEntry ze = entries.get(index);
672         assertEquals("src/main/java/org/apache/commons/compress/archivers/zip/"
673                      + expectedName + ".java",
674                      ze.getName());
675     }
676 }