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;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  
26  import java.io.BufferedInputStream;
27  import java.io.ByteArrayOutputStream;
28  import java.io.File;
29  import java.io.InputStream;
30  import java.io.OutputStream;
31  import java.nio.file.Files;
32  
33  import org.apache.commons.compress.AbstractTest;
34  import org.apache.commons.compress.archivers.ar.ArArchiveEntry;
35  import org.apache.commons.compress.archivers.ar.ArArchiveInputStream;
36  import org.apache.commons.compress.archivers.ar.ArArchiveOutputStream;
37  import org.apache.commons.io.IOUtils;
38  import org.junit.jupiter.api.Disabled;
39  import org.junit.jupiter.api.Test;
40  
41  public final class ArTest extends AbstractTest {
42  
43      @Test
44      void testArArchiveCreation() throws Exception {
45          final File output = newTempFile("bla.ar");
46  
47          final File file1 = getFile("test1.xml");
48          final File file2 = getFile("test2.xml");
49  
50          try (OutputStream out = Files.newOutputStream(output.toPath());
51                  ArArchiveOutputStream os = ArchiveStreamFactory.DEFAULT.createArchiveOutputStream("ar", out)) {
52              // file 1
53              os.putArchiveEntry(new ArArchiveEntry("test1.xml", file1.length()));
54              os.write(file1);
55              os.closeArchiveEntry();
56              // file 2
57              os.putArchiveEntry(new ArArchiveEntry("test2.xml", file2.length()));
58              os.write(file2);
59              os.closeArchiveEntry();
60          }
61      }
62  
63      @Test
64      void testArDelete() throws Exception {
65          final File output = newTempFile("bla.ar");
66  
67          final File file1 = getFile("test1.xml");
68          final File file2 = getFile("test2.xml");
69          {
70              // create
71              try (OutputStream out = Files.newOutputStream(output.toPath());
72                      ArchiveOutputStream<ArArchiveEntry> os = ArchiveStreamFactory.DEFAULT.createArchiveOutputStream("ar", out)) {
73                  // file 1
74                  os.putArchiveEntry(new ArArchiveEntry("test1.xml", file1.length()));
75                  os.write(file1);
76                  os.closeArchiveEntry();
77                  // file 2
78                  os.putArchiveEntry(new ArArchiveEntry("test2.xml", file2.length()));
79                  os.write(file2);
80                  os.closeArchiveEntry();
81              }
82          }
83  
84          assertEquals(8 + 60 + file1.length() + file1.length() % 2 + 60 + file2.length() + file2.length() % 2, output.length());
85  
86          final File output2 = newTempFile("bla2.ar");
87  
88          int copied = 0;
89          int deleted = 0;
90  
91          // remove all but one file
92  
93          try (OutputStream os = Files.newOutputStream(output2.toPath());
94                  InputStream is = Files.newInputStream(output.toPath());
95                  ArchiveOutputStream<ArArchiveEntry> aos = new ArchiveStreamFactory().createArchiveOutputStream("ar", os);
96                  ArchiveInputStream<ArArchiveEntry> ais = new ArchiveStreamFactory().createArchiveInputStream(new BufferedInputStream(is))) {
97              while (true) {
98                  final ArArchiveEntry entry = ais.getNextEntry();
99                  if (entry == null) {
100                     break;
101                 }
102                 if ("test1.xml".equals(entry.getName())) {
103                     aos.putArchiveEntry(entry);
104                     IOUtils.copy(ais, aos);
105                     aos.closeArchiveEntry();
106                     copied++;
107                 } else {
108                     IOUtils.copy(ais, new ByteArrayOutputStream());
109                     deleted++;
110                 }
111             }
112         }
113 
114         assertEquals(1, copied);
115         assertEquals(1, deleted);
116         assertEquals(8 + 60 + file1.length() + file1.length() % 2, output2.length());
117 
118         long files = 0;
119         long sum = 0;
120 
121         {
122             try (InputStream is = Files.newInputStream(output2.toPath());
123                     ArchiveInputStream<ArArchiveEntry> ais = new ArchiveStreamFactory().createArchiveInputStream(new BufferedInputStream(is))) {
124                 while (true) {
125                     final ArArchiveEntry entry = ais.getNextEntry();
126                     if (entry == null) {
127                         break;
128                     }
129 
130                     IOUtils.copy(ais, new ByteArrayOutputStream());
131 
132                     sum += entry.getLength();
133                     files++;
134                 }
135             }
136         }
137 
138         assertEquals(1, files);
139         assertEquals(file1.length(), sum);
140     }
141 
142     @Test
143     void testArUnarchive() throws Exception {
144         final File output = newTempFile("bla.ar");
145         {
146             final File file1 = getFile("test1.xml");
147             final File file2 = getFile("test2.xml");
148 
149             try (OutputStream out = Files.newOutputStream(output.toPath());
150                     ArchiveOutputStream<ArArchiveEntry> os = ArchiveStreamFactory.DEFAULT.createArchiveOutputStream("ar", out)) {
151                 // file 1
152                 os.putArchiveEntry(new ArArchiveEntry("test1.xml", file1.length()));
153                 os.write(file1);
154                 os.closeArchiveEntry();
155                 // file 2
156                 os.putArchiveEntry(new ArArchiveEntry("test2.xml", file2.length()));
157                 os.write(file2);
158                 os.closeArchiveEntry();
159             }
160         }
161 
162         // UnArArchive Operation
163         try (InputStream is = Files.newInputStream(output.toPath());
164                 ArchiveInputStream<ArArchiveEntry> in = new ArchiveStreamFactory().createArchiveInputStream(new BufferedInputStream(is))) {
165             final ArArchiveEntry entry = in.getNextEntry();
166             final File target = newTempFile(entry.getName());
167             Files.copy(in, target.toPath());
168         }
169     }
170 
171     @Test
172     void testExplicitFileEntry() throws Exception {
173         final File file = createTempFile();
174         final File archive = createTempFile("test.", ".ar");
175         try (ArArchiveOutputStream aos = new ArArchiveOutputStream(Files.newOutputStream(archive.toPath()))) {
176             final ArArchiveEntry in = new ArArchiveEntry("foo", file.length(), 0, 0, 0, file.lastModified() / 1000);
177             aos.putArchiveEntry(in);
178             aos.write(file);
179             aos.closeArchiveEntry();
180         }
181         //
182         final ArArchiveEntry out;
183         try (ArArchiveInputStream ais = new ArArchiveInputStream(Files.newInputStream(archive.toPath()))) {
184             out = ais.getNextArEntry();
185         }
186         assertNotNull(out);
187         assertEquals("foo", out.getName());
188         assertEquals(file.length(), out.getSize());
189         assertEquals(file.lastModified() / 1000, out.getLastModifiedDate().getTime() / 1000);
190         assertFalse(out.isDirectory());
191     }
192 
193     @Test
194     void testFileEntryFromFile() throws Exception {
195         final File file = createTempFile();
196         final File archive = createTempFile("test.", ".ar");
197         try (ArArchiveOutputStream aos = new ArArchiveOutputStream(Files.newOutputStream(archive.toPath()))) {
198             final ArArchiveEntry in = new ArArchiveEntry(file, "foo");
199             aos.putArchiveEntry(in);
200             aos.write(file);
201             aos.closeArchiveEntry();
202         }
203         final ArArchiveEntry out;
204         try (ArArchiveInputStream ais = new ArArchiveInputStream(Files.newInputStream(archive.toPath()))) {
205             out = ais.getNextArEntry();
206         }
207         assertNotNull(out);
208         assertEquals("foo", out.getName());
209         assertEquals(file.length(), out.getSize());
210         // AR stores time with a granularity of 1 second
211         assertEquals(file.lastModified() / 1000, out.getLastModifiedDate().getTime() / 1000);
212         assertFalse(out.isDirectory());
213     }
214 
215     @Test
216     void testFileEntryFromPath() throws Exception {
217         final File file = createTempFile();
218         final File archive = createTempFile("test.", ".ar");
219         try (ArArchiveOutputStream aos = new ArArchiveOutputStream(Files.newOutputStream(archive.toPath()))) {
220             final ArArchiveEntry in = new ArArchiveEntry(file.toPath(), "foo");
221             aos.putArchiveEntry(in);
222             aos.write(file);
223             aos.closeArchiveEntry();
224         }
225         final ArArchiveEntry out;
226         try (ArArchiveInputStream ais = new ArArchiveInputStream(Files.newInputStream(archive.toPath()))) {
227             out = ais.getNextArEntry();
228         }
229         assertNotNull(out);
230         assertEquals("foo", out.getName());
231         assertEquals(file.length(), out.getSize());
232         // AR stores time with a granularity of 1 second
233         assertEquals(file.lastModified() / 1000, out.getLastModifiedDate().getTime() / 1000);
234         assertFalse(out.isDirectory());
235     }
236 
237     // TODO: revisit - does AR not support storing directories?
238     @Disabled
239     @Test
240     void testXtestDirectoryEntryFromFile() throws Exception {
241         final File tmp = createTempFile();
242         final File archive = createTempFile("test.", ".ar");
243         final long beforeArchiveWrite;
244         try (ArArchiveOutputStream aos = new ArArchiveOutputStream(Files.newOutputStream(archive.toPath()))) {
245             beforeArchiveWrite = tmp.lastModified();
246             final ArArchiveEntry in = new ArArchiveEntry(tmp, "foo");
247             aos.putArchiveEntry(in);
248             aos.closeArchiveEntry();
249         }
250         final ArArchiveEntry out;
251         try (ArArchiveInputStream ais = new ArArchiveInputStream(Files.newInputStream(archive.toPath()))) {
252             out = ais.getNextArEntry();
253         }
254         assertNotNull(out);
255         assertEquals("foo/", out.getName());
256         assertEquals(0, out.getSize());
257         // AR stores time with a granularity of 1 second
258         assertEquals(beforeArchiveWrite / 1000, out.getLastModifiedDate().getTime() / 1000);
259         assertTrue(out.isDirectory());
260     }
261 
262     // TODO: revisit - does AR not support storing directories?
263     @Disabled
264     @Test
265     void testXtestExplicitDirectoryEntry() throws Exception {
266         final File tmp = createTempFile();
267         final File archive = createTempFile("test.", ".ar");
268         final long beforeArchiveWrite;
269         try (ArArchiveOutputStream aos = new ArArchiveOutputStream(Files.newOutputStream(archive.toPath()))) {
270             beforeArchiveWrite = getTempDirFile().lastModified();
271             final ArArchiveEntry in = new ArArchiveEntry("foo", 0, 0, 0, 0, tmp.lastModified() / 1000);
272             aos.putArchiveEntry(in);
273             aos.closeArchiveEntry();
274         }
275         final ArArchiveEntry out;
276         try (ArArchiveInputStream ais = new ArArchiveInputStream(Files.newInputStream(archive.toPath()))) {
277             out = ais.getNextArEntry();
278         }
279         assertNotNull(out);
280         assertEquals("foo/", out.getName());
281         assertEquals(0, out.getSize());
282         assertEquals(beforeArchiveWrite / 1000, out.getLastModifiedDate().getTime() / 1000);
283         assertTrue(out.isDirectory());
284     }
285 }