diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy new file mode 100644 index 000000000..f81b64a2b --- /dev/null +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy @@ -0,0 +1,32 @@ +/* + * Source https://stackoverflow.com/a/39043903/519333 + */ +package com.github.jengelman.gradle.plugins.shadow.internal + +class CleanProperties extends Properties { + private static class StripFirstLineStream extends FilterOutputStream { + + private boolean firstLineSeen = false + + StripFirstLineStream(final OutputStream out) { + super(out) + } + + @Override + void write(final int b) throws IOException { + if (firstLineSeen) { + super.write(b); + } else if (b == '\n') { + super.write(b); + + firstLineSeen = true; + } + } + + } + + @Override + void store(final OutputStream out, final String comments) throws IOException { + super.store(new StripFirstLineStream(out), null) + } +} diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.groovy index 31e1a5452..2d113ac2f 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.groovy @@ -19,6 +19,7 @@ package com.github.jengelman.gradle.plugins.shadow.transformers +import com.github.jengelman.gradle.plugins.shadow.internal.CleanProperties import org.apache.tools.zip.ZipEntry import org.apache.tools.zip.ZipOutputStream import org.codehaus.plexus.util.IOUtil @@ -117,7 +118,7 @@ import static groovy.lang.Closure.IDENTITY class PropertiesFileTransformer implements Transformer { private static final String PROPERTIES_SUFFIX = '.properties' - private Map propertiesEntries = [:] + private Map propertiesEntries = [:] @Input List paths = [] @@ -179,15 +180,17 @@ class PropertiesFileTransformer implements Transformer { } private Properties loadAndTransformKeys(InputStream is) { - Properties props = new Properties() - props.load(is) + Properties props = new CleanProperties() + if (is != null) { + props.load(is) + } return transformKeys(props) } private Properties transformKeys(Properties properties) { if (keyTransformer == IDENTITY) return properties - def result = new Properties() + def result = new CleanProperties() properties.each { key, value -> result.put(keyTransformer.call(key), value) } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy new file mode 100644 index 000000000..ff23aed96 --- /dev/null +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy @@ -0,0 +1,76 @@ +package com.github.jengelman.gradle.plugins.shadow.transformers + +import com.github.jengelman.gradle.plugins.shadow.ShadowStats +import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator +import org.apache.tools.zip.ZipOutputStream +import org.junit.Before +import org.junit.Test + +import java.util.zip.ZipFile + +import static java.util.Arrays.asList +import static org.junit.Assert.* + +/** + * Test for {@link PropertiesFileTransformer}. + */ +final class PropertiesFileTransformerTest extends TransformerTestSupport { + static final String MANIFEST_NAME = "META-INF/MANIFEST.MF" + + private PropertiesFileTransformer transformer + + @Before + void setUp() { + transformer = new PropertiesFileTransformer() + } + + @Test + void testHasTransformedResource() { + transformer.transform(new TransformerContext(MANIFEST_NAME)) + + assertTrue(transformer.hasTransformedResource()) + } + + @Test + void testHasNotTransformedResource() { + assertFalse(transformer.hasTransformedResource()) + } + + @Test + void testTransformation() { + transformer.transform(new TransformerContext(MANIFEST_NAME, getResourceStream(MANIFEST_NAME), Collections.emptyList(), new ShadowStats())) + + def testableZipFile = File.createTempFile("testable-zip-file-", ".jar") + def fileOutputStream = new FileOutputStream(testableZipFile) + def bufferedOutputStream = new BufferedOutputStream(fileOutputStream) + def zipOutputStream = new ZipOutputStream(bufferedOutputStream) + + try { + transformer.modifyOutputStream(zipOutputStream, false) + } finally { + zipOutputStream.close() + } + def targetLines = readFrom(testableZipFile, MANIFEST_NAME) + + assertFalse(targetLines.isEmpty()) + + assertTrue(targetLines.contains("Manifest-Version=1.0")) + } + + static List readFrom(File jarFile, String resourceName) { + def zip = new ZipFile(jarFile) + try { + def entry = zip.getEntry(resourceName) + if (!entry) { + return Collections.emptyList() + } + return zip.getInputStream(entry).readLines() + } finally { + zip.close() + } + } + + InputStream getResourceStream(String resource) { + this.class.classLoader.getResourceAsStream(resource) + } +}