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.harmony.pack200;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  
24  import java.io.BufferedReader;
25  import java.io.File;
26  import java.io.FileInputStream;
27  import java.io.FileOutputStream;
28  import java.io.IOException;
29  import java.io.InputStream;
30  import java.io.InputStreamReader;
31  import java.net.URISyntaxException;
32  import java.nio.file.Files;
33  import java.nio.file.Path;
34  import java.nio.file.Paths;
35  import java.util.Enumeration;
36  import java.util.jar.JarEntry;
37  import java.util.jar.JarFile;
38  import java.util.jar.JarInputStream;
39  import java.util.jar.JarOutputStream;
40  import java.util.stream.Stream;
41  
42  import org.apache.commons.compress.AbstractTempDirTest;
43  import org.apache.commons.compress.harmony.unpack200.Segment;
44  import org.junit.jupiter.api.Test;
45  import org.junit.jupiter.params.ParameterizedTest;
46  import org.junit.jupiter.params.provider.Arguments;
47  import org.junit.jupiter.params.provider.MethodSource;
48  
49  class ArchiveTest extends AbstractTempDirTest {
50  
51      @SuppressWarnings("resource") // Caller closes
52      static Stream<Arguments> loadMultipleJars() throws URISyntaxException, IOException {
53          return Files.list(Paths.get(Archive.class.getResource("/pack200/jars").toURI())).filter(child -> {
54              final String fileName = child.getFileName().toString();
55              return fileName.endsWith(".jar") && !fileName.endsWith("Unpacked.jar");
56          }).map(Arguments::of);
57      }
58  
59      private void compareFiles(final JarFile jarFile, final JarFile jarFile2) throws IOException {
60          final Enumeration<JarEntry> entries = jarFile.entries();
61          while (entries.hasMoreElements()) {
62  
63              final JarEntry entry = entries.nextElement();
64              assertNotNull(entry);
65  
66              final String name = entry.getName();
67              final JarEntry entry2 = jarFile2.getJarEntry(name);
68              assertNotNull(entry2, "Missing Entry: " + name);
69  //            assertEquals(entry.getTime(), entry2.getTime());
70              if (!name.equals("META-INF/MANIFEST.MF")) {
71                  // Manifests aren't necessarily byte-for-byte identical
72                  final InputStream ours = jarFile.getInputStream(entry);
73                  final InputStream expected = jarFile2.getInputStream(entry2);
74  
75                  try (BufferedReader reader1 = new BufferedReader(new InputStreamReader(ours));
76                          BufferedReader reader2 = new BufferedReader(new InputStreamReader(expected))) {
77                      String line1 = reader1.readLine();
78                      String line2 = reader2.readLine();
79                      while (line1 != null || line2 != null) {
80                          assertEquals(line2, line1, "Unpacked files differ for " + name);
81                          line1 = reader1.readLine();
82                          line2 = reader2.readLine();
83                      }
84                  }
85              }
86          }
87      }
88  
89      private void compareJarEntries(final JarFile jarFile, final JarFile jarFile2) {
90          final Enumeration<JarEntry> entries = jarFile.entries();
91          while (entries.hasMoreElements()) {
92  
93              final JarEntry entry = entries.nextElement();
94              assertNotNull(entry);
95  
96              final String name = entry.getName();
97              final JarEntry entry2 = jarFile2.getJarEntry(name);
98              assertNotNull(entry2, "Missing Entry: " + name);
99          }
100     }
101 
102     @Test
103     void testAlternativeConstructor() throws IOException, URISyntaxException, Pack200Exception {
104         final File file = createTempFile("sql", ".pack.gz");
105         try (JarInputStream inStream = new JarInputStream(new FileInputStream(new File(Archive.class.getResource("/pack200/sqlUnpacked.jar").toURI())));
106                 FileOutputStream out = new FileOutputStream(file);) {
107             new Archive(inStream, out, null).pack();
108         }
109     }
110 
111     @Test
112     void testAnnotations() throws IOException, Pack200Exception, URISyntaxException {
113         final File file = createTempFile("annotations", ".pack");
114         try (JarFile in = new JarFile(new File(Archive.class.getResource("/pack200/annotationsUnpacked.jar").toURI()));
115                 FileOutputStream out = new FileOutputStream(file)) {
116             final PackingOptions options = new PackingOptions();
117             options.setGzip(false);
118             new Archive(in, out, options).pack();
119         }
120         // now unpack
121         final File file2 = createTempFile("annotationsout", ".jar");
122         try (InputStream in2 = new FileInputStream(file);
123                 JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2))) {
124             final org.apache.commons.compress.harmony.unpack200.Archive archive = new org.apache.commons.compress.harmony.unpack200.Archive(in2, out2);
125             archive.unpack();
126         }
127         try (JarFile jarFile = new JarFile(file2);
128                 JarFile jarFile2 = new JarFile(new File(Archive.class.getResource("/pack200/annotationsUnpacked.jar").toURI()))) {
129             compareFiles(jarFile, jarFile2);
130         }
131     }
132 
133     @Test
134     void testAnnotations2() throws IOException, Pack200Exception, URISyntaxException {
135         final File file = createTempFile("annotations", ".pack");
136         try (JarFile in = new JarFile(new File(Archive.class.getResource("/pack200/annotations.jar").toURI()));
137                 FileOutputStream out = new FileOutputStream(file)) {
138             final PackingOptions options = new PackingOptions();
139             options.setGzip(false);
140             new Archive(in, out, options).pack();
141         }
142 
143         // now unpack
144         final File file2 = createTempFile("annotationsout", ".jar");
145         try (InputStream in2 = new FileInputStream(file);
146                 JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2))) {
147             final org.apache.commons.compress.harmony.unpack200.Archive archive = new org.apache.commons.compress.harmony.unpack200.Archive(in2, out2);
148             archive.unpack();
149         }
150         // TODO: This isn't quite right - to fix
151         try (JarFile jarFile = new JarFile(file2);
152                 JarFile jarFile2 = new JarFile(new File(Archive.class.getResource("/pack200/annotationsRI.jar").toURI()))) {
153             compareFiles(jarFile, jarFile2);
154         }
155     }
156 
157     @Test
158     void testHelloWorld() throws IOException, Pack200Exception, URISyntaxException {
159         final File file = createTempFile("helloworld", ".pack.gz");
160         try (JarFile in = new JarFile(new File(Archive.class.getResource("/pack200/hw.jar").toURI()));
161                 FileOutputStream out = new FileOutputStream(file);) {
162             new Archive(in, out, null).pack();
163         }
164 
165         // now unpack
166         final File file2 = createTempFile("helloworld", ".jar");
167         try (InputStream in2 = new FileInputStream(file);
168                 JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2))) {
169             final org.apache.commons.compress.harmony.unpack200.Archive archive = new org.apache.commons.compress.harmony.unpack200.Archive(in2, out2);
170             archive.unpack();
171         }
172 
173         try (JarFile jarFile = new JarFile(file2)) {
174             final JarEntry entry = jarFile.getJarEntry("org/apache/harmony/archive/tests/internal/pack200/HelloWorld.class");
175             assertNotNull(entry);
176             try (InputStream ours = jarFile.getInputStream(entry)) {
177 
178                 try (JarFile jarFile2 = new JarFile(new File(Segment.class.getResource("/pack200/hw.jar").toURI()))) {
179                     final JarEntry entry2 = jarFile2.getJarEntry("org/apache/harmony/archive/tests/internal/pack200/HelloWorld.class");
180                     assertNotNull(entry2);
181 
182                     final InputStream expected = jarFile2.getInputStream(entry2);
183 
184                     try (BufferedReader reader1 = new BufferedReader(new InputStreamReader(ours));
185                             BufferedReader reader2 = new BufferedReader(new InputStreamReader(expected))) {
186                         String line1 = reader1.readLine();
187                         String line2 = reader2.readLine();
188                         int i = 1;
189                         while (line1 != null || line2 != null) {
190                             assertEquals(line2, line1, "Unpacked class files differ, i = " + i);
191                             line1 = reader1.readLine();
192                             line2 = reader2.readLine();
193                             i++;
194                         }
195                     }
196                 }
197             }
198         }
199     }
200 
201     @Test
202     void testJNDI() throws IOException, Pack200Exception, URISyntaxException {
203         final File file = createTempFile("jndi", ".pack");
204         try (JarFile in = new JarFile(new File(Archive.class.getResource("/pack200/jndi.jar").toURI()))) {
205             try (FileOutputStream out = new FileOutputStream(file)) {
206                 final PackingOptions options = new PackingOptions();
207                 options.setGzip(false);
208                 new Archive(in, out, options).pack();
209             }
210         }
211 
212         // now unpack
213         final File file2 = createTempFile("jndiout", ".jar");
214         try (InputStream in2 = new FileInputStream(file);
215                 JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2))) {
216             final org.apache.commons.compress.harmony.unpack200.Archive archive = new org.apache.commons.compress.harmony.unpack200.Archive(in2, out2);
217             archive.unpack();
218         }
219         try (JarFile jarFile = new JarFile(file2);
220                 JarFile jarFile2 = new JarFile(new File(Archive.class.getResource("/pack200/jndiUnpacked.jar").toURI()))) {
221             compareFiles(jarFile, jarFile2);
222         }
223     }
224 
225     @Test
226     void testLargeClass() throws IOException, Pack200Exception, URISyntaxException {
227         final File file = createTempFile("largeClass", ".pack");
228         try (JarFile in = new JarFile(new File(Archive.class.getResource("/pack200/largeClassUnpacked.jar").toURI()));
229                 FileOutputStream out = new FileOutputStream(file)) {
230             final PackingOptions options = new PackingOptions();
231             options.setGzip(false);
232             new Archive(in, out, options).pack();
233         }
234 
235         // now unpack
236         final File file2 = createTempFile("largeClassOut", ".jar");
237         try (InputStream in2 = new FileInputStream(file);
238                 JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2))) {
239             final org.apache.commons.compress.harmony.unpack200.Archive archive = new org.apache.commons.compress.harmony.unpack200.Archive(in2, out2);
240             archive.unpack();
241         }
242         final File compareFile = new File(Archive.class.getResource("/pack200/largeClassUnpacked.jar").toURI());
243         try (JarFile jarFile = new JarFile(file2);
244                 JarFile jarFile2 = new JarFile(compareFile)) {
245             assertEquals(jarFile2.size(), jarFile.size());
246             compareFiles(jarFile, jarFile2);
247         }
248     }
249 
250     @ParameterizedTest
251     @MethodSource("loadMultipleJars")
252     void testMultipleJars(final Path path) throws IOException, Pack200Exception {
253         final File file = createTempFile("temp", ".pack.gz");
254         final File inputFile = path.toFile();
255         try (JarFile in = new JarFile(inputFile);
256                 FileOutputStream out = new FileOutputStream(file)) {
257             // System.out.println("packing " + children[i]);
258             new Archive(in, out, null).pack();
259         }
260         // unpack and compare
261     }
262 
263     @Test
264     void testSQL() throws IOException, Pack200Exception, URISyntaxException {
265         final File file = createTempFile("sql", ".pack");
266         try (JarFile in = new JarFile(new File(Archive.class.getResource("/pack200/sqlUnpacked.jar").toURI()));
267                 FileOutputStream out = new FileOutputStream(file)) {
268             final PackingOptions options = new PackingOptions();
269             options.setGzip(false);
270             new Archive(in, out, options).pack();
271         }
272 
273         // now unpack
274         final File file2 = createTempFile("sqlout", ".jar");
275         try (InputStream in2 = new FileInputStream(file);
276                 JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2))) {
277             final org.apache.commons.compress.harmony.unpack200.Archive archive = new org.apache.commons.compress.harmony.unpack200.Archive(in2, out2);
278             archive.unpack();
279         }
280         final File compareFile = new File(Archive.class.getResource("/pack200/sqlUnpacked.jar").toURI());
281         try (JarFile jarFile = new JarFile(file2);
282                 JarFile jarFile2 = new JarFile(compareFile)) {
283             assertEquals(jarFile2.size(), jarFile.size());
284             compareFiles(jarFile, jarFile2);
285         }
286     }
287 
288     // Test with an archive containing Annotations
289     @Test
290     void testWithAnnotations2() throws Exception {
291         final File file = createTempFile("annotations", ".jar");
292         try (InputStream input = Archive.class.getResourceAsStream("/pack200/annotationsRI.pack.gz");
293                 JarOutputStream jout = new JarOutputStream(new FileOutputStream(file))) {
294             final org.apache.commons.compress.harmony.unpack200.Archive archive = new org.apache.commons.compress.harmony.unpack200.Archive(input, jout);
295             archive.unpack();
296         }
297         try (JarFile jarFile = new JarFile(file);
298                 JarFile jarFile2 = new JarFile(new File(Archive.class.getResource("/pack200/annotationsRI.jar").toURI()))) {
299             compareFiles(jarFile, jarFile2);
300         }
301     }
302 
303 }