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  
20  package org.apache.commons.compress.archivers;
21  
22  import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
23  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  import static org.junit.jupiter.api.Assertions.fail;
26  
27  import java.io.BufferedInputStream;
28  import java.io.BufferedReader;
29  import java.io.File;
30  import java.net.URISyntaxException;
31  import java.nio.file.Files;
32  import java.util.ArrayList;
33  import java.util.Collection;
34  import java.util.stream.Stream;
35  
36  import org.apache.commons.compress.AbstractTest;
37  import org.apache.commons.compress.archivers.ar.ArArchiveInputStream;
38  import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream;
39  import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
40  import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
41  import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
42  import org.junit.jupiter.api.BeforeAll;
43  import org.junit.jupiter.params.ParameterizedTest;
44  import org.junit.jupiter.params.provider.Arguments;
45  import org.junit.jupiter.params.provider.MethodSource;
46  
47  /**
48   * Test that can read various tar file examples.
49   *
50   * Files must be in resources/longpath, and there must be a file.txt containing the list of files in the archives.
51   */
52  class LongPathTest extends AbstractTest {
53  
54      private static final ClassLoader CLASS_LOADER = LongPathTest.class.getClassLoader();
55      private static final File ARC_DIR;
56      private static final ArrayList<String> FILE_LIST = new ArrayList<>();
57  
58      static {
59          try {
60              ARC_DIR = new File(CLASS_LOADER.getResource("longpath").toURI());
61          } catch (final URISyntaxException e) {
62              throw new AssertionError(e);
63          }
64      }
65  
66      public static Stream<Arguments> data() {
67          final Collection<Arguments> params = new ArrayList<>();
68          for (final String fileName : ARC_DIR.list((dir, name) -> !name.endsWith(".txt"))) {
69              params.add(Arguments.of(new File(ARC_DIR, fileName)));
70          }
71          return params.stream();
72      }
73  
74      @BeforeAll
75      public static void setUpFileList() throws Exception {
76          assertTrue(ARC_DIR.exists());
77          final File listing = new File(ARC_DIR, "files.txt");
78          assertTrue(listing.canRead(), "files.txt is readable");
79          try (BufferedReader br = new BufferedReader(Files.newBufferedReader(listing.toPath()))) {
80              String line;
81              while ((line = br.readLine()) != null) {
82                  if (!line.startsWith("#")) {
83                      FILE_LIST.add(line);
84                  }
85              }
86          }
87      }
88  
89      @Override
90      protected String getExpectedString(final ArchiveEntry entry) {
91          if (entry instanceof TarArchiveEntry) {
92              final TarArchiveEntry tarEntry = (TarArchiveEntry) entry;
93              if (tarEntry.isSymbolicLink()) {
94                  return tarEntry.getName() + " -> " + tarEntry.getLinkName();
95              }
96          }
97          return entry.getName();
98      }
99  
100     @ParameterizedTest
101     @MethodSource("data")
102     void testArchive(final File file) throws Exception {
103         @SuppressWarnings("unchecked") // fileList is of correct type
104         final ArrayList<String> expected = (ArrayList<String>) FILE_LIST.clone();
105         final String name = file.getName();
106         if ("minotaur.jar".equals(name) || "minotaur-0.jar".equals(name)) {
107             expected.add("META-INF/");
108             expected.add("META-INF/MANIFEST.MF");
109         }
110         try (ArchiveInputStream<?> ais = factory.createArchiveInputStream(new BufferedInputStream(Files.newInputStream(file.toPath())))) {
111             // check if expected type recognized
112             if (name.endsWith(".tar")) {
113                 assertInstanceOf(TarArchiveInputStream.class, ais);
114             } else if (name.endsWith(".jar") || name.endsWith(".zip")) {
115                 assertInstanceOf(ZipArchiveInputStream.class, ais);
116             } else if (name.endsWith(".cpio")) {
117                 assertInstanceOf(CpioArchiveInputStream.class, ais);
118                 // Hack: cpio does not add trailing "/" to directory names
119                 for (int i = 0; i < expected.size(); i++) {
120                     final String ent = expected.get(i);
121                     if (ent.endsWith("/")) {
122                         expected.set(i, ent.substring(0, ent.length() - 1));
123                     }
124                 }
125             } else if (name.endsWith(".ar")) {
126                 assertInstanceOf(ArArchiveInputStream.class, ais);
127                 // CPIO does not store directories or directory names
128                 expected.clear();
129                 for (final String ent : FILE_LIST) {
130                     if (!ent.endsWith("/")) {
131                         // not a directory
132                         final int lastSlash = ent.lastIndexOf('/');
133                         if (lastSlash >= 0) {
134                             // extract path name
135                             expected.add(ent.substring(lastSlash + 1));
136                         } else {
137                             expected.add(ent);
138                         }
139                     }
140                 }
141             } else {
142                 fail("Unexpected file type: " + name);
143             }
144             assertDoesNotThrow(() -> checkArchiveContent(ais, expected), "Error processing " + file.getName());
145         }
146     }
147 }