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