From df720cdeb86e671ac336d337dfedda1cf2d1f711 Mon Sep 17 00:00:00 2001
From: Mikolaj Izdebski <mizdebsk@redhat.com>
Date: Wed, 28 Oct 2015 13:08:23 +0100
Subject: [PATCH 2/5] Add duplicated ZIP entry hack for OpenJDK
---
.../xmvn/tools/install/impl/JarUtils.java | 29 ++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/xmvn-tools/xmvn-install/src/main/java/org/fedoraproject/xmvn/tools/install/impl/JarUtils.java b/xmvn-tools/xmvn-install/src/main/java/org/fedoraproject/xmvn/tools/install/impl/JarUtils.java
index 5dd09ea..ae2a5a6 100644
--- a/xmvn-tools/xmvn-install/src/main/java/org/fedoraproject/xmvn/tools/install/impl/JarUtils.java
+++ b/xmvn-tools/xmvn-install/src/main/java/org/fedoraproject/xmvn/tools/install/impl/JarUtils.java
@@ -16,8 +16,10 @@
package org.fedoraproject.xmvn.tools.install.impl;
import java.io.IOException;
+import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.Collection;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
@@ -25,6 +27,7 @@ import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
@@ -165,6 +168,31 @@ class JarUtils
}
/**
+ * OpenJDK has a sanity check that prevents adding duplicate entries to ZIP streams. The problem is that some of
+ * JARs we try to inject manifests to (especially the ones created by Gradle) already contain duplicate entries, so
+ * manifest injection would always fail for them with "ZipException: duplicate entry".
+ * <p>
+ * This function tries to work around this OpenJDK sanity check, effectively allowing creating ZIP files with
+ * duplicated entries. It should be called on particular ZIP output stream before adding each duplicate entry.
+ *
+ * @param zipOutputStream ZIP stream to hack
+ */
+ private static void openJdkAvoidDuplicateEntryHack( ZipOutputStream zipOutputStream )
+ {
+ try
+ {
+ Field namesField = ZipOutputStream.class.getDeclaredField( "names" );
+ namesField.setAccessible( true );
+ Collection<?> names = (Collection<?>) namesField.get( zipOutputStream );
+ names.clear();
+ }
+ catch ( ReflectiveOperationException e )
+ {
+ // This hack relies on OpenJDK internals and therefore is not ugarranteed to work. Ignore failures.
+ }
+ }
+
+ /**
* Inject artifact coordinates into manifest of specified JAR (or WAR, EAR, ...) file. The file is modified
* in-place.
*
@@ -200,6 +228,7 @@ class JarUtils
JarEntry entry;
while ( ( entry = jis.getNextJarEntry() ) != null )
{
+ openJdkAvoidDuplicateEntryHack( jos );
jos.putNextEntry( entry );
int sz;
--
2.7.4