1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.shade;
20
21 import java.io.BufferedReader;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.OutputStream;
29 import java.lang.reflect.Field;
30 import java.net.URL;
31 import java.net.URLClassLoader;
32 import java.nio.charset.StandardCharsets;
33 import java.nio.file.Files;
34 import java.nio.file.attribute.FileTime;
35 import java.time.temporal.ChronoUnit;
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Collections;
39 import java.util.Enumeration;
40 import java.util.LinkedHashSet;
41 import java.util.List;
42 import java.util.Set;
43 import java.util.jar.JarEntry;
44 import java.util.jar.JarFile;
45 import java.util.jar.JarInputStream;
46 import java.util.jar.JarOutputStream;
47 import java.util.stream.Collectors;
48 import java.util.zip.CRC32;
49 import java.util.zip.ZipEntry;
50
51 import org.apache.maven.plugin.MojoExecutionException;
52 import org.apache.maven.plugins.shade.filter.Filter;
53 import org.apache.maven.plugins.shade.relocation.Relocator;
54 import org.apache.maven.plugins.shade.relocation.SimpleRelocator;
55 import org.apache.maven.plugins.shade.resource.AppendingTransformer;
56 import org.apache.maven.plugins.shade.resource.ComponentsXmlResourceTransformer;
57 import org.apache.maven.plugins.shade.resource.ResourceTransformer;
58 import org.apache.maven.plugins.shade.resource.ServicesResourceTransformer;
59 import org.codehaus.plexus.util.IOUtil;
60 import org.codehaus.plexus.util.Os;
61 import org.junit.Assert;
62 import org.junit.ClassRule;
63 import org.junit.Test;
64 import org.junit.rules.TemporaryFolder;
65 import org.mockito.ArgumentCaptor;
66 import org.objectweb.asm.ClassReader;
67 import org.objectweb.asm.ClassVisitor;
68 import org.objectweb.asm.Opcodes;
69 import org.slf4j.Logger;
70
71 import static java.util.Arrays.asList;
72 import static java.util.Collections.singleton;
73 import static java.util.Objects.requireNonNull;
74 import static org.codehaus.plexus.util.FileUtils.forceMkdir;
75 import static org.hamcrest.CoreMatchers.containsString;
76 import static org.hamcrest.CoreMatchers.hasItem;
77 import static org.hamcrest.CoreMatchers.hasItems;
78 import static org.hamcrest.CoreMatchers.is;
79 import static org.hamcrest.MatcherAssert.assertThat;
80 import static org.junit.Assert.assertEquals;
81 import static org.junit.Assert.assertFalse;
82 import static org.junit.Assert.assertTrue;
83 import static org.mockito.Mockito.doNothing;
84 import static org.mockito.Mockito.mock;
85 import static org.mockito.Mockito.when;
86
87
88
89
90
91 public class DefaultShaderTest {
92 private static final String[] EXCLUDES =
93 new String[] {"org/codehaus/plexus/util/xml/Xpp3Dom", "org/codehaus/plexus/util/xml/pull.*"};
94
95 @ClassRule
96 public static final TemporaryFolder tmp = new TemporaryFolder();
97
98 private final String NEWLINE = "\n";
99
100 @Test
101 public void testNoopWhenNotRelocated() throws IOException, MojoExecutionException {
102 final File plexusJar = new File("src/test/jars/plexus-utils-1.4.1.jar");
103 final File shadedOutput = new File("target/foo-custom_testNoopWhenNotRelocated.jar");
104
105 final Set<File> jars = new LinkedHashSet<>();
106 jars.add(new File("src/test/jars/test-project-1.0-SNAPSHOT.jar"));
107 jars.add(plexusJar);
108
109 final Relocator relocator = new SimpleRelocator(
110 "org/codehaus/plexus/util/cli",
111 "relocated/plexus/util/cli",
112 Collections.<String>emptyList(),
113 Collections.<String>emptyList());
114
115 final ShadeRequest shadeRequest = new ShadeRequest();
116 shadeRequest.setJars(jars);
117 shadeRequest.setRelocators(Collections.singletonList(relocator));
118 shadeRequest.setResourceTransformers(Collections.<ResourceTransformer>emptyList());
119 shadeRequest.setFilters(Collections.<Filter>emptyList());
120 shadeRequest.setUberJar(shadedOutput);
121
122 final DefaultShader shader = newShader();
123 shader.shade(shadeRequest);
124
125 try (final JarFile originalJar = new JarFile(plexusJar);
126 final JarFile shadedJar = new JarFile(shadedOutput)) {
127
128
129
130
131
132 assertTrue(areEqual(originalJar, shadedJar, "org/codehaus/plexus/util/Expand.class"));
133
134
135
136
137 assertFalse(areEqual(
138 originalJar,
139 shadedJar,
140 "org/codehaus/plexus/util/cli/Arg.class",
141 "relocated/plexus/util/cli/Arg.class"));
142 }
143 int result = 0;
144 for (final String msg : debugMessages.getAllValues()) {
145 if ("Rewrote class bytecode: org/codehaus/plexus/util/cli/Arg.class".equals(msg)) {
146 result |= 1;
147 } else if ("Keeping original class bytecode: org/codehaus/plexus/util/Expand.class".equals(msg)) {
148 result |= 2;
149 }
150 }
151 assertEquals(3 , result);
152 }
153
154 @Test
155 public void testOverlappingResourcesAreLogged() throws IOException, MojoExecutionException {
156 final DefaultShader shader = newShader();
157
158
159
160 final Set<File> set = new LinkedHashSet<>();
161 set.add(new File("src/test/jars/test-project-1.0-SNAPSHOT.jar"));
162 set.add(new File("src/test/jars/plexus-utils-1.4.1.jar"));
163
164 final ShadeRequest shadeRequest = new ShadeRequest();
165 shadeRequest.setJars(set);
166 shadeRequest.setRelocators(Collections.<Relocator>emptyList());
167 shadeRequest.setResourceTransformers(Collections.<ResourceTransformer>emptyList());
168 shadeRequest.setFilters(Collections.<Filter>emptyList());
169 shadeRequest.setUberJar(new File("target/foo-custom_testOverlappingResourcesAreLogged.jar"));
170 shader.shade(shadeRequest);
171
172 assertThat(
173 warnMessages.getAllValues(),
174 hasItem(containsString(
175 "plexus-utils-1.4.1.jar, test-project-1.0-SNAPSHOT.jar define 1 overlapping resource:")));
176 assertThat(warnMessages.getAllValues(), hasItem(containsString("- META-INF/MANIFEST.MF")));
177 if (Os.isFamily(Os.FAMILY_WINDOWS)) {
178 assertThat(
179 debugMessages.getAllValues(),
180 hasItem(containsString(
181 "We have a duplicate META-INF/MANIFEST.MF in src\\test\\jars\\plexus-utils-1.4.1.jar")));
182 } else {
183 assertThat(
184 debugMessages.getAllValues(),
185 hasItem(containsString(
186 "We have a duplicate META-INF/MANIFEST.MF in src/test/jars/plexus-utils-1.4.1.jar")));
187 }
188 }
189
190 @Test
191 public void testOverlappingResourcesAreLoggedExceptATransformerHandlesIt() throws Exception {
192 TemporaryFolder temporaryFolder = new TemporaryFolder();
193 try {
194 Set<File> set = new LinkedHashSet<>();
195 temporaryFolder.create();
196 File j1 = temporaryFolder.newFile("j1.jar");
197 try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(j1))) {
198 jos.putNextEntry(new JarEntry("foo.txt"));
199 jos.write("c1".getBytes(StandardCharsets.UTF_8));
200 jos.closeEntry();
201 }
202 File j2 = temporaryFolder.newFile("j2.jar");
203 try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(j2))) {
204 jos.putNextEntry(new JarEntry("foo.txt"));
205 jos.write("c2".getBytes(StandardCharsets.UTF_8));
206 jos.closeEntry();
207 }
208 set.add(j1);
209 set.add(j2);
210
211 AppendingTransformer transformer = new AppendingTransformer();
212 Field resource = AppendingTransformer.class.getDeclaredField("resource");
213 resource.setAccessible(true);
214 resource.set(transformer, "foo.txt");
215
216 ShadeRequest shadeRequest = new ShadeRequest();
217 shadeRequest.setJars(set);
218 shadeRequest.setRelocators(Collections.<Relocator>emptyList());
219 shadeRequest.setResourceTransformers(Collections.<ResourceTransformer>singletonList(transformer));
220 shadeRequest.setFilters(Collections.<Filter>emptyList());
221 shadeRequest.setUberJar(new File("target/foo-custom_testOverlappingResourcesAreLogged.jar"));
222
223 DefaultShader shaderWithTransformer = newShader();
224 shaderWithTransformer.shade(shadeRequest);
225
226 assertThat(warnMessages.getAllValues().size(), is(0));
227
228 DefaultShader shaderWithoutTransformer = newShader();
229 shadeRequest.setResourceTransformers(Collections.<ResourceTransformer>emptyList());
230 shaderWithoutTransformer.shade(shadeRequest);
231
232 assertThat(
233 warnMessages.getAllValues(),
234 hasItems(containsString("j1.jar, j2.jar define 1 overlapping resource:")));
235 assertThat(warnMessages.getAllValues(), hasItems(containsString("- foo.txt")));
236 } finally {
237 temporaryFolder.delete();
238 }
239 }
240
241 @Test
242 public void testShaderWithDefaultShadedPattern() throws Exception {
243 shaderWithPattern(null, new File("target/foo-default.jar"), EXCLUDES);
244 }
245
246 @Test
247 public void testShaderWithStaticInitializedClass() throws Exception {
248 Shader s = newShader();
249
250 Set<File> set = new LinkedHashSet<>();
251
252 set.add(new File("src/test/jars/test-artifact-1.0-SNAPSHOT.jar"));
253
254 List<Relocator> relocators = new ArrayList<>();
255
256 relocators.add(new SimpleRelocator("org.apache.maven.plugins.shade", null, null, null));
257
258 List<ResourceTransformer> resourceTransformers = new ArrayList<>();
259
260 List<Filter> filters = new ArrayList<>();
261
262 File file = new File("target/testShaderWithStaticInitializedClass.jar");
263
264 ShadeRequest shadeRequest = new ShadeRequest();
265 shadeRequest.setJars(set);
266 shadeRequest.setUberJar(file);
267 shadeRequest.setFilters(filters);
268 shadeRequest.setRelocators(relocators);
269 shadeRequest.setResourceTransformers(resourceTransformers);
270
271 s.shade(shadeRequest);
272
273 try (URLClassLoader cl = new URLClassLoader(new URL[] {file.toURI().toURL()})) {
274 Class<?> c = cl.loadClass("hidden.org.apache.maven.plugins.shade.Lib");
275 Object o = c.newInstance();
276 assertEquals("foo.bar/baz", c.getDeclaredField("CONSTANT").get(o));
277 }
278 }
279
280 @Test
281 public void testShaderWithCustomShadedPattern() throws Exception {
282 shaderWithPattern("org/shaded/plexus/util", new File("target/foo-custom.jar"), EXCLUDES);
283 }
284
285 @Test
286 public void testShaderWithoutExcludesShouldRemoveReferencesOfOriginalPattern() throws Exception {
287
288
289 shaderWithPattern(
290 "org/shaded/plexus/util", new File("target/foo-custom-without-excludes.jar"), new String[] {});
291 }
292
293 @Test
294 public void testHandleDirectory() throws Exception {
295 final File dir = tmp.getRoot();
296
297 try (final JarInputStream in =
298 new JarInputStream(new FileInputStream("src/test/jars/test-artifact-1.0-SNAPSHOT.jar"))) {
299 JarEntry nextJarEntry;
300 while ((nextJarEntry = in.getNextJarEntry()) != null) {
301 if (nextJarEntry.isDirectory()) {
302 continue;
303 }
304 final File out = new File(dir, nextJarEntry.getName());
305 forceMkdir(out.getParentFile());
306 try (final OutputStream outputStream = new FileOutputStream(out)) {
307 IOUtil.copy(in, outputStream, (int) Math.max(nextJarEntry.getSize(), 512));
308 }
309 }
310 }
311
312
313 final File shade = new File("target/testHandleDirectory.jar");
314 shaderWithPattern("org/shaded/plexus/util", shade, new String[0], singleton(dir));
315
316
317 try (final JarFile jar = new JarFile(shade)) {
318 final List<String> entries = new ArrayList<>();
319 final Enumeration<JarEntry> jarEntryEnumeration = jar.entries();
320 while (jarEntryEnumeration.hasMoreElements()) {
321 final JarEntry jarEntry = jarEntryEnumeration.nextElement();
322 if (jarEntry.isDirectory()) {
323 continue;
324 }
325 entries.add(jarEntry.getName());
326 }
327 Collections.sort(entries);
328 assertEquals(
329 asList(
330 "META-INF/maven/org.apache.maven.plugins.shade/test-artifact/pom.properties",
331 "META-INF/maven/org.apache.maven.plugins.shade/test-artifact/pom.xml",
332 "org/apache/maven/plugins/shade/Lib.class"),
333 entries);
334 }
335 }
336
337 @Test
338 public void testShaderWithRelocatedClassname() throws Exception {
339 DefaultShader s = newShader();
340
341 Set<File> set = new LinkedHashSet<>();
342
343 set.add(new File("src/test/jars/test-project-1.0-SNAPSHOT.jar"));
344
345 set.add(new File("src/test/jars/plexus-utils-1.4.1.jar"));
346
347 List<Relocator> relocators = new ArrayList<>();
348
349 relocators.add(new SimpleRelocator(
350 "org/codehaus/plexus/util/", "_plexus/util/__", null, Collections.<String>emptyList()));
351
352 List<ResourceTransformer> resourceTransformers = new ArrayList<>();
353
354 resourceTransformers.add(new ComponentsXmlResourceTransformer());
355
356 List<Filter> filters = new ArrayList<>();
357
358 File file = new File("target/foo-relocate-class.jar");
359
360 ShadeRequest shadeRequest = new ShadeRequest();
361 shadeRequest.setJars(set);
362 shadeRequest.setUberJar(file);
363 shadeRequest.setFilters(filters);
364 shadeRequest.setRelocators(relocators);
365 shadeRequest.setResourceTransformers(resourceTransformers);
366
367 s.shade(shadeRequest);
368
369 try (URLClassLoader cl = new URLClassLoader(new URL[] {file.toURI().toURL()})) {
370 Class<?> c = cl.loadClass("_plexus.util.__StringUtils");
371
372 Object o = c.newInstance();
373 assertEquals("", c.getMethod("clean", String.class).invoke(o, (String) null));
374
375
376 final String[] source = {null};
377 final ClassReader classReader = new ClassReader(cl.getResourceAsStream("_plexus/util/__StringUtils.class"));
378 classReader.accept(
379 new ClassVisitor(Opcodes.ASM4) {
380 @Override
381 public void visitSource(String arg0, String arg1) {
382 super.visitSource(arg0, arg1);
383 source[0] = arg0;
384 }
385 },
386 ClassReader.SKIP_CODE);
387 assertEquals("__StringUtils.java", source[0]);
388 }
389 }
390
391 @Test
392 public void testShaderWithNestedJar() throws Exception {
393 TemporaryFolder temporaryFolder = new TemporaryFolder();
394
395 final String innerJarFileName = "inner.jar";
396
397 temporaryFolder.create();
398 File innerJar = temporaryFolder.newFile(innerJarFileName);
399 try (JarOutputStream jos = new JarOutputStream(Files.newOutputStream(innerJar.toPath()))) {
400 jos.putNextEntry(new JarEntry("foo.txt"));
401 jos.write("c1".getBytes(StandardCharsets.UTF_8));
402 jos.closeEntry();
403 }
404
405 ShadeRequest shadeRequest = new ShadeRequest();
406 shadeRequest.setJars(new LinkedHashSet<>(Collections.singleton(innerJar)));
407 shadeRequest.setFilters(Collections.emptyList());
408 shadeRequest.setRelocators(Collections.emptyList());
409 shadeRequest.setResourceTransformers(Collections.emptyList());
410 File shadedFile = temporaryFolder.newFile("shaded.jar");
411 shadeRequest.setUberJar(shadedFile);
412
413 DefaultShader shader = newShader();
414 shader.shade(shadeRequest);
415
416 FileTime lastModified = FileTime.from(
417 Files.getLastModifiedTime(shadedFile.toPath()).toInstant().minus(5, ChronoUnit.SECONDS));
418
419 Files.setLastModifiedTime(shadedFile.toPath(), lastModified);
420
421 shader.shade(shadeRequest);
422 assertEquals(lastModified, Files.getLastModifiedTime(shadedFile.toPath()));
423
424 temporaryFolder.delete();
425 }
426
427 @Test
428 public void testShaderNoOverwrite() throws Exception {
429 TemporaryFolder temporaryFolder = new TemporaryFolder();
430
431 final String innerJarFileName = "inner.jar";
432
433 temporaryFolder.create();
434 File innerJar = temporaryFolder.newFile(innerJarFileName);
435 try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(innerJar))) {
436 jos.putNextEntry(new JarEntry("foo.txt"));
437 jos.write("c1".getBytes(StandardCharsets.UTF_8));
438 jos.closeEntry();
439 }
440
441 File outerJar = temporaryFolder.newFile("outer.jar");
442 try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(outerJar))) {
443 FileInputStream innerStream = new FileInputStream(innerJar);
444 byte[] bytes = IOUtil.toByteArray(innerStream, 32 * 1024);
445 innerStream.close();
446 writeEntryWithoutCompression(innerJarFileName, bytes, jos);
447 }
448
449 ShadeRequest shadeRequest = new ShadeRequest();
450 shadeRequest.setJars(new LinkedHashSet<>(Collections.singleton(outerJar)));
451 shadeRequest.setFilters(new ArrayList<Filter>());
452 shadeRequest.setRelocators(new ArrayList<Relocator>());
453 shadeRequest.setResourceTransformers(new ArrayList<ResourceTransformer>());
454 File shadedFile = temporaryFolder.newFile("shaded.jar");
455 shadeRequest.setUberJar(shadedFile);
456
457 DefaultShader shader = newShader();
458 shader.shade(shadeRequest);
459
460 JarFile shadedJarFile = new JarFile(shadedFile);
461 JarEntry entry = shadedJarFile.getJarEntry(innerJarFileName);
462
463
464 Assert.assertEquals(entry.getMethod(), ZipEntry.STORED);
465
466 temporaryFolder.delete();
467 }
468
469 @Test
470 public void testShaderWithDuplicateService() throws Exception {
471 TemporaryFolder temporaryFolder = new TemporaryFolder();
472 temporaryFolder.create();
473
474 String serviceEntryName = "META-INF/services/my.foo.Service";
475 String serviceEntryValue = "my.foo.impl.Service1";
476
477 File innerJar1 = temporaryFolder.newFile("inner1.jar");
478 try (JarOutputStream jos = new JarOutputStream(Files.newOutputStream(innerJar1.toPath()))) {
479 jos.putNextEntry(new JarEntry(serviceEntryName));
480 jos.write((serviceEntryValue + NEWLINE).getBytes(StandardCharsets.UTF_8));
481 jos.closeEntry();
482 }
483
484 File innerJar2 = temporaryFolder.newFile("inner2.jar");
485 try (JarOutputStream jos = new JarOutputStream(Files.newOutputStream(innerJar2.toPath()))) {
486 jos.putNextEntry(new JarEntry(serviceEntryName));
487 jos.write((serviceEntryValue + NEWLINE).getBytes(StandardCharsets.UTF_8));
488 jos.closeEntry();
489 }
490
491 ShadeRequest shadeRequest = new ShadeRequest();
492 shadeRequest.setJars(new LinkedHashSet<>(Arrays.asList(innerJar1, innerJar2)));
493 shadeRequest.setFilters(Collections.emptyList());
494 shadeRequest.setRelocators(Collections.emptyList());
495 shadeRequest.setResourceTransformers(Collections.singletonList(new ServicesResourceTransformer()));
496 File shadedFile = temporaryFolder.newFile("shaded.jar");
497 shadeRequest.setUberJar(shadedFile);
498
499 DefaultShader shader = newShader();
500 shader.shade(shadeRequest);
501
502 JarFile shadedJarFile = new JarFile(shadedFile);
503 JarEntry entry = shadedJarFile.getJarEntry(serviceEntryName);
504
505 List<String> lines = new BufferedReader(
506 new InputStreamReader(shadedJarFile.getInputStream(entry), StandardCharsets.UTF_8))
507 .lines()
508 .collect(Collectors.toList());
509
510
511 Assert.assertEquals(Collections.singletonList(serviceEntryValue), lines);
512
513 temporaryFolder.delete();
514 }
515
516 @Test
517 public void testShaderWithSmallEntries() throws Exception {
518 TemporaryFolder temporaryFolder = new TemporaryFolder();
519
520 final String innerJarFileName = "inner.jar";
521 int len;
522
523 temporaryFolder.create();
524 File innerJar = temporaryFolder.newFile(innerJarFileName);
525 try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(innerJar))) {
526 jos.putNextEntry(new JarEntry("foo.txt"));
527 byte[] bytes = "c1".getBytes(StandardCharsets.UTF_8);
528 len = bytes.length;
529 jos.write(bytes);
530 jos.closeEntry();
531 }
532
533 ShadeRequest shadeRequest = new ShadeRequest();
534 shadeRequest.setJars(new LinkedHashSet<>(Collections.singleton(innerJar)));
535 shadeRequest.setFilters(new ArrayList<Filter>());
536 shadeRequest.setRelocators(new ArrayList<Relocator>());
537 shadeRequest.setResourceTransformers(new ArrayList<ResourceTransformer>());
538 File shadedFile = temporaryFolder.newFile("shaded.jar");
539 shadeRequest.setUberJar(shadedFile);
540
541 DefaultShader shader = newShader();
542 shader.shade(shadeRequest);
543
544 JarFile shadedJarFile = new JarFile(shadedFile);
545 JarEntry entry = shadedJarFile.getJarEntry("foo.txt");
546
547
548 Assert.assertEquals(entry.getSize(), len);
549
550 temporaryFolder.delete();
551 }
552
553 private void writeEntryWithoutCompression(String entryName, byte[] entryBytes, JarOutputStream jos)
554 throws IOException {
555 final JarEntry entry = new JarEntry(entryName);
556 final int size = entryBytes.length;
557 final CRC32 crc = new CRC32();
558 crc.update(entryBytes, 0, size);
559 entry.setSize(size);
560 entry.setCompressedSize(size);
561 entry.setMethod(ZipEntry.STORED);
562 entry.setCrc(crc.getValue());
563 jos.putNextEntry(entry);
564 jos.write(entryBytes);
565 jos.closeEntry();
566 }
567
568 private void shaderWithPattern(String shadedPattern, File jar, String[] excludes) throws Exception {
569 Set<File> set = new LinkedHashSet<>();
570 set.add(new File("src/test/jars/test-project-1.0-SNAPSHOT.jar"));
571 set.add(new File("src/test/jars/plexus-utils-1.4.1.jar"));
572 shaderWithPattern(shadedPattern, jar, excludes, set);
573 }
574
575 private void shaderWithPattern(String shadedPattern, File jar, String[] excludes, Set<File> set) throws Exception {
576 DefaultShader s = newShader();
577
578 List<Relocator> relocators = new ArrayList<>();
579
580 relocators.add(new SimpleRelocator("org/codehaus/plexus/util", shadedPattern, null, Arrays.asList(excludes)));
581
582 List<ResourceTransformer> resourceTransformers = new ArrayList<>();
583
584 resourceTransformers.add(new ComponentsXmlResourceTransformer());
585
586 List<Filter> filters = new ArrayList<>();
587
588 ShadeRequest shadeRequest = new ShadeRequest();
589 shadeRequest.setJars(set);
590 shadeRequest.setUberJar(jar);
591 shadeRequest.setFilters(filters);
592 shadeRequest.setRelocators(relocators);
593 shadeRequest.setResourceTransformers(resourceTransformers);
594
595 s.shade(shadeRequest);
596 }
597
598 private DefaultShader newShader() {
599 return new DefaultShader(mockLogger());
600 }
601
602 private ArgumentCaptor<String> debugMessages;
603
604 private ArgumentCaptor<String> warnMessages;
605
606 private Logger mockLogger() {
607 debugMessages = ArgumentCaptor.forClass(String.class);
608 warnMessages = ArgumentCaptor.forClass(String.class);
609 Logger logger = mock(Logger.class);
610 when(logger.isDebugEnabled()).thenReturn(true);
611 when(logger.isWarnEnabled()).thenReturn(true);
612 doNothing().when(logger).debug(debugMessages.capture());
613 doNothing().when(logger).warn(warnMessages.capture());
614 return logger;
615 }
616
617 private boolean areEqual(final JarFile jar1, final JarFile jar2, final String entry) throws IOException {
618 return areEqual(jar1, jar2, entry, entry);
619 }
620
621 private boolean areEqual(final JarFile jar1, final JarFile jar2, final String entry1, String entry2)
622 throws IOException {
623 try (final InputStream s1 = jar1.getInputStream(
624 requireNonNull(jar1.getJarEntry(entry1), entry1 + " in " + jar1.getName()));
625 final InputStream s2 = jar2.getInputStream(
626 requireNonNull(jar2.getJarEntry(entry2), entry2 + " in " + jar2.getName()))) {
627 return Arrays.equals(IOUtil.toByteArray(s1), IOUtil.toByteArray(s2));
628 }
629 }
630 }