View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.compress.archivers;
19  
20  import static org.junit.jupiter.api.Assertions.assertTrue;
21  import static org.junit.jupiter.api.Assertions.fail;
22  
23  import java.io.BufferedInputStream;
24  import java.io.BufferedReader;
25  import java.io.File;
26  import java.net.URISyntaxException;
27  import java.nio.file.Files;
28  import java.util.ArrayList;
29  import java.util.Collection;
30  import java.util.stream.Stream;
31  
32  import org.apache.commons.compress.AbstractTest;
33  import org.apache.commons.compress.archivers.ar.ArArchiveInputStream;
34  import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream;
35  import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
36  import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
37  import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
38  import org.junit.jupiter.api.BeforeAll;
39  import org.junit.jupiter.params.ParameterizedTest;
40  import org.junit.jupiter.params.provider.Arguments;
41  import org.junit.jupiter.params.provider.MethodSource;
42  
43  /**
44   * Test that can read various tar file examples.
45   *
46   * Files must be in resources/longsymlink, and there must be a file.txt containing the list of files in the archives.
47   */
48  public class LongSymLinkTest extends AbstractTest {
49  
50      private static final ClassLoader CLASSLOADER = LongSymLinkTest.class.getClassLoader();
51      private static final File ARCDIR;
52      private static final ArrayList<String> FILELIST = new ArrayList<>();
53  
54      static {
55          try {
56              ARCDIR = new File(CLASSLOADER.getResource("longsymlink").toURI());
57          } catch (final URISyntaxException e) {
58              throw new AssertionError(e);
59          }
60      }
61  
62      public static Stream<Arguments> data() {
63          final Collection<Arguments> params = new ArrayList<>();
64          for (final String fileName : ARCDIR.list((dir, name) -> !name.endsWith(".txt"))) {
65              params.add(Arguments.of(new File(ARCDIR, fileName)));
66          }
67          return params.stream();
68      }
69  
70      @BeforeAll
71      public static void setUpFileList() throws Exception {
72          assertTrue(ARCDIR.exists());
73          final File listing = new File(ARCDIR, "files.txt");
74          assertTrue(listing.canRead(), "files.txt is readable");
75          try (BufferedReader br = new BufferedReader(Files.newBufferedReader(listing.toPath()))) {
76              String line;
77              while ((line = br.readLine()) != null) {
78                  if (!line.startsWith("#")) {
79                      FILELIST.add(line);
80                  }
81              }
82          }
83      }
84  
85      @Override
86      protected String getExpectedString(final ArchiveEntry entry) {
87          if (entry instanceof TarArchiveEntry) {
88              final TarArchiveEntry tarEntry = (TarArchiveEntry) entry;
89              if (tarEntry.isSymbolicLink()) {
90                  return tarEntry.getName() + " -> " + tarEntry.getLinkName();
91              }
92          }
93          return entry.getName();
94      }
95  
96      @ParameterizedTest
97      @MethodSource("data")
98      public void testArchive(final File file) throws Exception {
99          @SuppressWarnings("unchecked") // fileList is of correct type
100         final ArrayList<String> expected = (ArrayList<String>) FILELIST.clone();
101         final String name = file.getName();
102         if ("minotaur.jar".equals(name) || "minotaur-0.jar".equals(name)) {
103             expected.add("META-INF/");
104             expected.add("META-INF/MANIFEST.MF");
105         }
106         try (ArchiveInputStream<?> ais = factory.createArchiveInputStream(new BufferedInputStream(Files.newInputStream(file.toPath())))) {
107             // check if expected type recognized
108             if (name.endsWith(".tar")) {
109                 assertTrue(ais instanceof TarArchiveInputStream);
110             } else if (name.endsWith(".jar") || name.endsWith(".zip")) {
111                 assertTrue(ais instanceof ZipArchiveInputStream);
112             } else if (name.endsWith(".cpio")) {
113                 assertTrue(ais instanceof CpioArchiveInputStream);
114                 // Hack: cpio does not add trailing "/" to directory names
115                 for (int i = 0; i < expected.size(); i++) {
116                     final String ent = expected.get(i);
117                     if (ent.endsWith("/")) {
118                         expected.set(i, ent.substring(0, ent.length() - 1));
119                     }
120                 }
121             } else if (name.endsWith(".ar")) {
122                 assertTrue(ais instanceof ArArchiveInputStream);
123                 // CPIO does not store directories or directory names
124                 expected.clear();
125                 for (final String ent : FILELIST) {
126                     if (!ent.endsWith("/")) {
127                         // not a directory
128                         final int lastSlash = ent.lastIndexOf('/');
129                         if (lastSlash >= 0) {
130                             // extract path name
131                             expected.add(ent.substring(lastSlash + 1));
132                         } else {
133                             expected.add(ent);
134                         }
135                     }
136                 }
137             } else {
138                 fail("Unexpected file type: " + name);
139             }
140         }
141     }
142 }