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   *   https://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.zip;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertTrue;
23  
24  import java.io.ByteArrayInputStream;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.OutputStream;
28  import java.nio.charset.StandardCharsets;
29  import java.nio.file.Files;
30  import java.nio.file.Path;
31  
32  import org.apache.commons.compress.AbstractTest;
33  import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
34  import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream;
35  import org.apache.commons.compress.compressors.xz.XZUtils;
36  import org.apache.commons.io.IOUtils;
37  import org.junit.jupiter.api.Test;
38  import org.junit.jupiter.api.io.TempDir;
39  
40  class ZipCompressMethodXzTest extends AbstractTest {
41  
42      private static final int DEFAULT_LEVEL = 6;
43  
44      @TempDir
45      static Path tempDir;
46  
47      /**
48       * Reads uncompressed data stream and writes it compressed to the output.
49       *
50       * @param input  the data stream with compressed data
51       * @param output the data stream for compressed output
52       * @throws IOException throws the exception which could be got from from IOUtils.copyLarge() or XZCompressorOutputStream constructor
53       */
54      private static void compress(final InputStream input, final OutputStream output) throws IOException {
55          @SuppressWarnings("resource")
56          final XZCompressorOutputStream outputStream = new XZCompressorOutputStream(output, DEFAULT_LEVEL);
57          IOUtils.copyLarge(input, outputStream);
58          outputStream.flush();
59      }
60  
61      @Test
62      void testXzInputStream() throws IOException {
63          // The file test-method-xz.zip was created with:
64          // "\Program Files\7-Zip\7z.exe" a test-method-xz.zip -mm=xz LICENSE.txt
65          // The "mm" option specifies the compress method
66          final Path file = getPath("org/apache/commons/compress/zip/test-method-xz.zip");
67          try (ZipFile zip = ZipFile.builder().setPath(file).get()) {
68              final ZipArchiveEntry entry = zip.getEntries().nextElement();
69              assertEquals("LICENSE.txt", entry.getName());
70              assertTrue(zip.canReadEntryData(entry));
71              assertEquals(ZipMethod.XZ.getCode(), entry.getMethod());
72              try (InputStream inputStream = zip.getInputStream(entry)) {
73                  final long actualSize = entry.getSize();
74                  final byte[] buf = new byte[(int) actualSize];
75                  inputStream.read(buf);
76                  final String text = new String(buf);
77                  assertTrue(text.startsWith("                                 Apache License"), text);
78                  assertTrue(text.endsWith("   limitations under the License.\n"), text);
79                  assertEquals(11357, text.length());
80              }
81          }
82      }
83  
84      @Test
85      void testXzMethodInZipFile() throws IOException {
86          final String zipContentFile = "testXzMethodInZipFile.txt";
87          final byte[] text = "The quick brown fox jumps over the lazy dog".getBytes(StandardCharsets.UTF_8);
88          final Path file = tempDir.resolve("testXzMethodInZipFile.zip");
89          // Create the Zip File
90          try (ZipArchiveOutputStream zipOutputStream = new ZipArchiveOutputStream(file)) {
91              final ZipArchiveEntry archiveEntry = new ZipArchiveEntry(zipContentFile);
92              archiveEntry.setMethod(ZipMethod.XZ.getCode());
93              archiveEntry.setSize(text.length);
94              zipOutputStream.putArchiveEntry(archiveEntry);
95              compress(new ByteArrayInputStream(text), zipOutputStream);
96              zipOutputStream.closeArchiveEntry();
97          }
98          // Read the Zip File
99          try (ZipFile zipFile = ZipFile.builder().setPath(file).get()) {
100             // Find the entry
101             final ZipArchiveEntry entry = zipFile.getEntry(zipContentFile);
102             // Check the compression method
103             assertEquals(entry.getMethod(), ZipMethod.XZ.getCode());
104             @SuppressWarnings("resource")
105             final InputStream inputStream = zipFile.getInputStream(entry);
106             assertTrue(inputStream instanceof XZCompressorInputStream);
107             final long dataOffset = entry.getDataOffset();
108             final int uncompressedSize = (int) entry.getSize();
109             assertEquals(text.length, uncompressedSize);
110             final byte[] uncompressedData = new byte[uncompressedSize];
111             inputStream.read(uncompressedData, 0, uncompressedSize);
112             // Check the uncompressed data
113             assertEquals(new String(text), new String(uncompressedData));
114             try (InputStream fileInputStream = Files.newInputStream(file)) {
115                 fileInputStream.skip(dataOffset);
116                 final byte[] compressedData = new byte[6];
117                 fileInputStream.read(compressedData);
118                 assertTrue(XZUtils.matches(compressedData, 6));
119             }
120         }
121     }
122 
123     @Test
124     void testXzMethodWriteRead() throws IOException {
125         final String zipContentFile = "testXzMethodWriteRead.txt";
126         final byte[] text = "The quick brown fox jumps over the lazy dog".getBytes(StandardCharsets.UTF_8);
127         final Path file = tempDir.resolve("testXzMethodWriteRead.zip");
128         // Create the Zip File
129         try (ZipArchiveOutputStream zipOutputStream = new ZipArchiveOutputStream(file)) {
130             final ZipArchiveEntry archiveEntry = new ZipArchiveEntry(zipContentFile);
131             archiveEntry.setMethod(ZipMethod.XZ.getCode());
132             archiveEntry.setSize(text.length);
133             zipOutputStream.putArchiveEntry(archiveEntry);
134             compress(new ByteArrayInputStream(text), zipOutputStream);
135             zipOutputStream.closeArchiveEntry();
136         }
137         // Read the Zip File
138         try (ZipFile zipFile = ZipFile.builder().setPath(file).get()) {
139             // Find the entry
140             final ZipArchiveEntry entry = zipFile.getEntry(zipContentFile);
141             // Check the compression method
142             assertEquals(entry.getMethod(), ZipMethod.XZ.getCode());
143             @SuppressWarnings("resource")
144             final InputStream inputStream = zipFile.getInputStream(entry);
145             assertTrue(inputStream instanceof XZCompressorInputStream);
146         }
147     }
148 }