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.commons.compress.archivers;
20  
21  import java.io.File;
22  import java.io.FileInputStream;
23  import java.io.FileOutputStream;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.io.OutputStream;
27  import java.util.ArrayList;
28  import java.util.List;
29  
30  import org.apache.commons.compress.AbstractTestCase;
31  import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
32  import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
33  import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
34  import org.apache.commons.compress.archivers.zip.ZipFile;
35  import org.apache.commons.compress.utils.IOUtils;
36  
37  public final class ZipTestCase extends AbstractTestCase {
38      /**
39       * Archives 2 files and unarchives it again. If the file length of result
40       * and source is the same, it looks like the operations have worked
41       * @throws Exception
42       */
43      public void testZipArchiveCreation() throws Exception {
44          // Archive
45          final File output = new File(dir, "bla.zip");
46          final File file1 = getFile("test1.xml");
47          final File file2 = getFile("test2.xml");
48  
49          final OutputStream out = new FileOutputStream(output);
50          ArchiveOutputStream os = null;
51          try {
52              os = new ArchiveStreamFactory()
53                  .createArchiveOutputStream("zip", out);
54              os.putArchiveEntry(new ZipArchiveEntry("testdata/test1.xml"));
55              IOUtils.copy(new FileInputStream(file1), os);
56              os.closeArchiveEntry();
57  
58              os.putArchiveEntry(new ZipArchiveEntry("testdata/test2.xml"));
59              IOUtils.copy(new FileInputStream(file2), os);
60              os.closeArchiveEntry();
61          } finally {
62              if (os != null) {
63                  os.close();
64              }
65          }
66          out.close();
67  
68          // Unarchive the same
69          List<File> results = new ArrayList<File>();
70  
71          final InputStream is = new FileInputStream(output);
72          ArchiveInputStream in = null;
73          try {
74              in = new ArchiveStreamFactory()
75                  .createArchiveInputStream("zip", is);
76  
77              ZipArchiveEntry entry = null;
78              while((entry = (ZipArchiveEntry)in.getNextEntry()) != null) {
79                  File outfile = new File(resultDir.getCanonicalPath() + "/result/" + entry.getName());
80                  outfile.getParentFile().mkdirs();
81                  OutputStream o = new FileOutputStream(outfile);
82                  try {
83                      IOUtils.copy(in, o);
84                  } finally {
85                      o.close();
86                  }
87                  results.add(outfile);
88              }
89          } finally {
90              if (in != null) {
91                  in.close();
92              }
93          }
94          is.close();
95  
96          assertEquals(results.size(), 2);
97          File result = results.get(0);
98          assertEquals(file1.length(), result.length());
99          result = results.get(1);
100         assertEquals(file2.length(), result.length());
101     }
102 
103     /**
104      * Simple unarchive test. Asserts nothing.
105      * @throws Exception
106      */
107     public void testZipUnarchive() throws Exception {
108         final File input = getFile("bla.zip");
109         final InputStream is = new FileInputStream(input);
110         final ArchiveInputStream in = new ArchiveStreamFactory().createArchiveInputStream("zip", is);
111         final ZipArchiveEntry entry = (ZipArchiveEntry)in.getNextEntry();
112         final OutputStream out = new FileOutputStream(new File(dir, entry.getName()));
113         IOUtils.copy(in, out);
114         out.close();
115         in.close();
116     }
117 
118     /**
119      * Test case for 
120      * <a href="https://issues.apache.org/jira/browse/COMPRESS-208"
121      * >COMPRESS-208</a>.
122      */
123     public void testSkipsPK00Prefix() throws Exception {
124         final File input = getFile("COMPRESS-208.zip");
125         InputStream is = new FileInputStream(input);
126         ArrayList<String> al = new ArrayList<String>();
127         al.add("test1.xml");
128         al.add("test2.xml");
129         try {
130             checkArchiveContent(new ZipArchiveInputStream(is), al);
131         } finally {
132             is.close();
133         }
134     }
135 
136     /**
137      * Test case for
138      * <a href="https://issues.apache.org/jira/browse/COMPRESS-93"
139      * >COMPRESS-93</a>.
140      */
141     public void testSupportedCompressionMethod() throws IOException {
142         ZipFile bla = new ZipFile(getFile("bla.zip"));
143         assertTrue(bla.canReadEntryData(bla.getEntry("test1.xml")));
144         bla.close();
145 
146         ZipFile moby = new ZipFile(getFile("moby.zip"));
147         assertFalse(moby.canReadEntryData(moby.getEntry("README")));
148         moby.close();
149     }
150 
151     /**
152      * Test case for being able to skip an entry in an 
153      * {@link ZipArchiveInputStream} even if the compression method of that
154      * entry is unsupported.
155      *
156      * @see <a href="https://issues.apache.org/jira/browse/COMPRESS-93"
157      *        >COMPRESS-93</a>
158      */
159     public void testSkipEntryWithUnsupportedCompressionMethod()
160             throws IOException {
161         ZipArchiveInputStream zip =
162             new ZipArchiveInputStream(new FileInputStream(getFile("moby.zip")));
163         try {
164             ZipArchiveEntry entry = zip.getNextZipEntry();
165             assertEquals("README", entry.getName());
166             assertFalse(zip.canReadEntryData(entry));
167             try {
168                 assertNull(zip.getNextZipEntry());
169             } catch (IOException e) {
170                 e.printStackTrace();
171                 fail("COMPRESS-93: Unable to skip an unsupported zip entry");
172             }
173         } finally {
174             zip.close();
175         }
176     }
177 
178     /**
179      * Checks if all entries from a nested archive can be read.
180      * The archive: OSX_ArchiveWithNestedArchive.zip contains:
181      * NestedArchiv.zip and test.xml3.
182      * 
183      * The nested archive:  NestedArchive.zip contains test1.xml and test2.xml
184      * 
185      * @throws Exception
186      */
187     public void testListAllFilesWithNestedArchive() throws Exception {
188         final File input = getFile("OSX_ArchiveWithNestedArchive.zip");
189 
190         List<String> results = new ArrayList<String>();
191 
192         final InputStream is = new FileInputStream(input);
193         ArchiveInputStream in = null;
194         try {
195             in = new ArchiveStreamFactory().createArchiveInputStream("zip", is);
196 
197             ZipArchiveEntry entry = null;
198             while((entry = (ZipArchiveEntry)in.getNextEntry()) != null) {
199                 results.add((entry.getName()));
200 
201                 ArchiveInputStream nestedIn = new ArchiveStreamFactory().createArchiveInputStream("zip", in);
202                 ZipArchiveEntry nestedEntry = null;
203                 while((nestedEntry = (ZipArchiveEntry)nestedIn.getNextEntry()) != null) {
204                     results.add(nestedEntry.getName());
205                 }
206                // nested stream must not be closed here
207             }
208         } finally {
209             if (in != null) {
210                 in.close();
211             }
212         }
213         is.close();
214 
215         results.contains("NestedArchiv.zip");
216         results.contains("test1.xml");
217         results.contains("test2.xml");
218         results.contains("test3.xml");
219     }
220 
221     public void testDirectoryEntryFromFile() throws Exception {
222         File[] tmp = createTempDirAndFile();
223         File archive = null;
224         ZipArchiveOutputStream zos = null;
225         ZipFile zf = null;
226         try {
227             archive = File.createTempFile("test.", ".zip", tmp[0]);
228             archive.deleteOnExit();
229             zos = new ZipArchiveOutputStream(archive);
230             long beforeArchiveWrite = tmp[0].lastModified();
231             ZipArchiveEntry in = new ZipArchiveEntry(tmp[0], "foo");
232             zos.putArchiveEntry(in);
233             zos.closeArchiveEntry();
234             zos.close();
235             zos = null;
236             zf = new ZipFile(archive);
237             ZipArchiveEntry out = zf.getEntry("foo/");
238             assertNotNull(out);
239             assertEquals("foo/", out.getName());
240             assertEquals(0, out.getSize());
241             // ZIP stores time with a granularity of 2 seconds
242             assertEquals(beforeArchiveWrite / 2000,
243                          out.getLastModifiedDate().getTime() / 2000);
244             assertTrue(out.isDirectory());
245         } finally {
246             ZipFile.closeQuietly(zf);
247             if (zos != null) {
248                 zos.close();
249             }
250             tryHardToDelete(archive);
251             tryHardToDelete(tmp[1]);
252             rmdir(tmp[0]);
253         }
254     }
255 
256     public void testExplicitDirectoryEntry() throws Exception {
257         File[] tmp = createTempDirAndFile();
258         File archive = null;
259         ZipArchiveOutputStream zos = null;
260         ZipFile zf = null;
261         try {
262             archive = File.createTempFile("test.", ".zip", tmp[0]);
263             archive.deleteOnExit();
264             zos = new ZipArchiveOutputStream(archive);
265             long beforeArchiveWrite = tmp[0].lastModified();
266             ZipArchiveEntry in = new ZipArchiveEntry("foo/");
267             in.setTime(beforeArchiveWrite);
268             zos.putArchiveEntry(in);
269             zos.closeArchiveEntry();
270             zos.close();
271             zos = null;
272             zf = new ZipFile(archive);
273             ZipArchiveEntry out = zf.getEntry("foo/");
274             assertNotNull(out);
275             assertEquals("foo/", out.getName());
276             assertEquals(0, out.getSize());
277             assertEquals(beforeArchiveWrite / 2000,
278                          out.getLastModifiedDate().getTime() / 2000);
279             assertTrue(out.isDirectory());
280         } finally {
281             ZipFile.closeQuietly(zf);
282             if (zos != null) {
283                 zos.close();
284             }
285             tryHardToDelete(archive);
286             tryHardToDelete(tmp[1]);
287             rmdir(tmp[0]);
288         }
289     }
290 
291     public void testFileEntryFromFile() throws Exception {
292         File[] tmp = createTempDirAndFile();
293         File archive = null;
294         ZipArchiveOutputStream zos = null;
295         ZipFile zf = null;
296         FileInputStream fis = null;
297         try {
298             archive = File.createTempFile("test.", ".zip", tmp[0]);
299             archive.deleteOnExit();
300             zos = new ZipArchiveOutputStream(archive);
301             ZipArchiveEntry in = new ZipArchiveEntry(tmp[1], "foo");
302             zos.putArchiveEntry(in);
303             byte[] b = new byte[(int) tmp[1].length()];
304             fis = new FileInputStream(tmp[1]);
305             while (fis.read(b) > 0) {
306                 zos.write(b);
307             }
308             fis.close();
309             fis = null;
310             zos.closeArchiveEntry();
311             zos.close();
312             zos = null;
313             zf = new ZipFile(archive);
314             ZipArchiveEntry out = zf.getEntry("foo");
315             assertNotNull(out);
316             assertEquals("foo", out.getName());
317             assertEquals(tmp[1].length(), out.getSize());
318             assertEquals(tmp[1].lastModified() / 2000,
319                          out.getLastModifiedDate().getTime() / 2000);
320             assertFalse(out.isDirectory());
321         } finally {
322             ZipFile.closeQuietly(zf);
323             if (zos != null) {
324                 zos.close();
325             }
326             tryHardToDelete(archive);
327             if (fis != null) {
328                 fis.close();
329             }
330             tryHardToDelete(tmp[1]);
331             rmdir(tmp[0]);
332         }
333     }
334 
335     public void testExplicitFileEntry() throws Exception {
336         File[] tmp = createTempDirAndFile();
337         File archive = null;
338         ZipArchiveOutputStream zos = null;
339         ZipFile zf = null;
340         FileInputStream fis = null;
341         try {
342             archive = File.createTempFile("test.", ".zip", tmp[0]);
343             archive.deleteOnExit();
344             zos = new ZipArchiveOutputStream(archive);
345             ZipArchiveEntry in = new ZipArchiveEntry("foo");
346             in.setTime(tmp[1].lastModified());
347             in.setSize(tmp[1].length());
348             zos.putArchiveEntry(in);
349             byte[] b = new byte[(int) tmp[1].length()];
350             fis = new FileInputStream(tmp[1]);
351             while (fis.read(b) > 0) {
352                 zos.write(b);
353             }
354             fis.close();
355             fis = null;
356             zos.closeArchiveEntry();
357             zos.close();
358             zos = null;
359             zf = new ZipFile(archive);
360             ZipArchiveEntry out = zf.getEntry("foo");
361             assertNotNull(out);
362             assertEquals("foo", out.getName());
363             assertEquals(tmp[1].length(), out.getSize());
364             assertEquals(tmp[1].lastModified() / 2000,
365                          out.getLastModifiedDate().getTime() / 2000);
366             assertFalse(out.isDirectory());
367         } finally {
368             ZipFile.closeQuietly(zf);
369             if (zos != null) {
370                 zos.close();
371             }
372             tryHardToDelete(archive);
373             if (fis != null) {
374                 fis.close();
375             }
376             tryHardToDelete(tmp[1]);
377             rmdir(tmp[0]);
378         }
379     }
380 }