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