Skip to content

Commit

Permalink
feat: allow ignoring duplicate entries in Jar files
Browse files Browse the repository at this point in the history
Add new member `duplicatesStrategy` to task signJars.

This member is unset by default, which is the same behavior as before.
Setting the value to `INCLUDE` would result in the same.

If the member is set to `EXCLUDE`, duplicate entries in jar files are
ignored and a debug message is printed to the log.

If it is `WARN`, a warning is printed to the log, but the build will fail
nonetheless, because the JarOutputStream will not allow duplicate entries.

If it is `FAIL`, the build will fail as well, but gracefully by throwing a
DuplicateFileCopyingException.

Closes: #37
  • Loading branch information
tschulte committed Jan 20, 2017
1 parent 0b5d427 commit d524573
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
package de.gliderpilot.gradle.jnlp

import groovyx.gpars.GParsPool
import org.gradle.api.file.DuplicateFileCopyingException
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.incremental.IncrementalTaskInputs

Expand All @@ -24,9 +27,10 @@ import java.util.jar.JarFile
import java.util.jar.JarOutputStream
import java.util.jar.Manifest


class SignJarsTask extends AbstractCopyJarsTask {

@Input
DuplicatesStrategy duplicatesStrategy = DuplicatesStrategy.INCLUDE

@TaskAction
void signJars(IncrementalTaskInputs inputs) {
Expand Down Expand Up @@ -64,6 +68,7 @@ class SignJarsTask extends AbstractCopyJarsTask {

File copyUnsignAndAlterManifest(File input) {
File output = new File(into, newName(input.name))
logger.info("Copying " + input + " to " + output)
JarFile jarFile = new JarFile(input)
Manifest manifest = jarFile.manifest ?: new Manifest()
def removeManifestEntries = { pattern, attributes ->
Expand All @@ -86,8 +91,21 @@ class SignJarsTask extends AbstractCopyJarsTask {
manifest.mainAttributes.putValue('Manifest-Version', '1.0')

new JarOutputStream(output.newOutputStream(), manifest).withStream { os ->
def entries = [] as Set
jarFile.entries().each { entry ->
if (entry.name != JarFile.MANIFEST_NAME && !(entry.name ==~ "(?i)META-INF/${project.jnlp.signJarFilteredMetaInfFiles}")) {
def duplicate = !entries.add(entry.name)
if (duplicate && duplicatesStrategy == DuplicatesStrategy.WARN) {
logger.warn("Duplicate entry found in jar: " + output + " entry: " + entry.name)
}
if (duplicate && duplicatesStrategy == DuplicatesStrategy.FAIL) {
throw new DuplicateFileCopyingException("Duplicate entry found in jar: " + output + " entry: " + entry.name)
}
if (duplicate && duplicatesStrategy == DuplicatesStrategy.EXCLUDE) {
logger.debug("Ignoring duplicate entry in jar: " + output + " entry: " + entry.name)
} else if (entry.name == JarFile.MANIFEST_NAME || entry.name ==~ "(?i)META-INF/${project.jnlp.signJarFilteredMetaInfFiles}") {
logger.debug("Ignoring entry jar: " + output + " entry: " + entry.name)
} else {
logger.debug("copying jar: " + input.name + " entry: " + entry.name)
os.putNextEntry(new JarEntry(entry.name))
os << jarFile.getInputStream(entry)
os.closeEntry()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.gliderpilot.gradle.jnlp

import org.gradle.api.file.DuplicatesStrategy
import spock.lang.Issue

@Issue("https://github.com/tschulte/gradle-jnlp-plugin/issues/37")
class SignJarsDuplicateEntriesSpec extends AbstractJnlpIntegrationSpec {

def setup() {
writeHelloWorld('de.gliderpilot.jnlp.test')
file('src/main/resources/test')
file('src/test/resources/test')
buildFile << """\
apply plugin: 'java'
apply plugin: 'application'
jnlp {
usePack200 = false
signJarRemovedNamedManifestEntries = ".*"
}
mainClassName = 'de.gliderpilot.jnlp.test.HelloWorld'
jar {
from sourceSets.test.output
}
""".stripIndent()
enableJarSigner()
}

def 'cannot sign jar without DuplicatesStrategy'() {
expect:
runTasksWithFailure(':createWebstartDir')
}

def 'cannot sign jar with DuplicatesStrategy.INCLUDE'() {
given:
duplicatesStrategy = DuplicatesStrategy.INCLUDE

expect:
runTasksWithFailure(':createWebstartDir')
}

def 'cannot sign jar with DuplicatesStrategy.FAIL'() {
given:
duplicatesStrategy = DuplicatesStrategy.FAIL

expect:
runTasksWithFailure(':createWebstartDir')
}

def 'cannot sign jar with duplicatesStrategy.WARN'() {
given:
duplicatesStrategy = DuplicatesStrategy.WARN

expect:
runTasksWithFailure(':createWebstartDir')
}

def 'can sign jar with DuplicatesStrategy.EXCLUDE'() {
given:
duplicatesStrategy = DuplicatesStrategy.EXCLUDE

expect:
runTasksSuccessfully(':createWebstartDir')
}

void setDuplicatesStrategy(DuplicatesStrategy duplicatesStrategy) {
buildFile << """\
tasks.signJars {
duplicatesStrategy = DuplicatesStrategy.${duplicatesStrategy}
}
""".stripIndent()
}

}

0 comments on commit d524573

Please sign in to comment.