Skip to content

Commit

Permalink
[bug] close #82 - merge shadowJar manifest using jar.manifest as parent.
Browse files Browse the repository at this point in the history
  • Loading branch information
johnrengelman committed Aug 26, 2014
1 parent 2741143 commit bb8ccd8
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,12 @@ class ShadowJavaPlugin implements Plugin<Project> {
map('classifier') {
'all'
}
map('manifest') {
project.tasks.jar.manifest
}
}
shadow.manifest.inheritFrom project.tasks.jar.manifest
shadow.doFirst {
def files = project.configurations.findByName(ShadowBasePlugin.CONFIGURATION_NAME).files
if (files) {
def value = manifest.attributes.get('Class-Path')
def value = project.tasks.jar.manifest.attributes.get('Class-Path')
manifest.attributes 'Class-Path': [value, files.collect { "lib/${it.name}" }.join(' ')].join(' ')
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.github.jengelman.gradle.plugins.shadow.tasks

import org.gradle.api.internal.file.FileResolver
import org.gradle.api.java.archives.internal.DefaultManifest
import org.gradle.api.java.archives.internal.DefaultManifestMergeSpec
import org.gradle.util.ConfigureUtil

class DefaultInheritManifest extends DefaultManifest implements InheritManifest {

private List<DefaultManifestMergeSpec> inheritMergeSpecs = []

private final FileResolver fileResolver

DefaultInheritManifest(FileResolver fileResolver) {
super(fileResolver)
this.fileResolver = fileResolver
}

public InheritManifest inheritFrom(Object... inheritPaths) {
inheritFrom(inheritPaths, null)
return this
}

public InheritManifest inheritFrom(Object inheritPaths, Closure closure) {
DefaultManifestMergeSpec mergeSpec = new DefaultManifestMergeSpec()
mergeSpec.from(inheritPaths)
inheritMergeSpecs.add(mergeSpec)
ConfigureUtil.configure(closure, mergeSpec)
return this
}

@Override
public DefaultManifest getEffectiveManifest() {
DefaultManifest base = new DefaultManifest(fileResolver)
inheritMergeSpecs.each {
base = it.merge(base, fileResolver)
}
base.from this.asDefaultManifest()
return base.getEffectiveManifest()
}

private DefaultManifest asDefaultManifest() {
DefaultManifest newManifest = new DefaultManifest(fileResolver)
newManifest.attributes this.attributes
this.sections.each { section, attrs ->
newManifest.attributes attrs, section
}
newManifest.mergeSpecs.addAll(this.mergeSpecs)
return newManifest
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.github.jengelman.gradle.plugins.shadow.tasks

import org.gradle.api.java.archives.Manifest

public interface InheritManifest extends Manifest {

InheritManifest inheritFrom(Object... inheritPaths)

InheritManifest inheritFrom(Object inheritPaths, Closure closure)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer
import org.gradle.api.artifacts.Configuration
import org.gradle.api.file.FileCollection
import org.gradle.api.internal.DocumentationRegistry
import org.gradle.api.internal.file.FileResolver
import org.gradle.api.internal.file.copy.CopyAction
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Optional
Expand All @@ -31,6 +32,14 @@ class ShadowJar extends Jar implements ShadowSpec {

ShadowJar() {
dependencyFilter = new DefaultDependencyFilter(project)
manifest = new DefaultInheritManifest(getServices().get(FileResolver))
}

@Override
// This should really return InheritManifest but cannot due to https://jira.codehaus.org/browse/GROOVY-5418
// TODO - change return type after upgrade to Gradle 2
public DefaultInheritManifest getManifest() {
return super.getManifest()
}

@Override
Expand Down Expand Up @@ -147,8 +156,12 @@ class ShadowJar extends Jar implements ShadowSpec {
* Append content to the JAR Manifest created by the Jar task.
* @param configureClosure
* @return
*
* @deprecated Use manifest {} instead
*/
@Deprecated
ShadowJar appendManifest(Closure configureClosure) {
logger.warn 'The appendManifest method is deprecated and will be removed in the next major version. Use manifest(Closure) instead.'
ConfigureUtil.configure(configureClosure, getManifest())
return this
}
Expand Down Expand Up @@ -189,5 +202,4 @@ class ShadowJar extends Jar implements ShadowSpec {
relocators << relocator
return this
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface ShadowSpec extends CopySpec {

ShadowSpec append(String resourcePath)

@Deprecated
ShadowSpec appendManifest(Closure configure)

ShadowSpec relocate(String pattern, String destination)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,144 @@ class TransformerSpec extends PluginSpecification {
|'''.stripMargin()
}

@Issue('SHADOW-82')
def 'shadow.manifest leaks to jar.manifest'() {
given:
File main = file('src/main/java/shadow/Main.java')
main << '''
|package shadow;
|
|public class Main {
|
| public static void main(String[] args) { }
|}
'''.stripMargin()

buildFile << """
|apply plugin: 'java'
|apply plugin: ${ShadowPlugin.name}
|
|jar {
| baseName = 'jar'
| manifest {
| attributes 'Main-Class': 'shadow.Main'
| attributes 'Test-Entry': 'FAILED'
| }
|}
|
|shadowJar {
| baseName = 'shadow'
| classifier = null
| manifest {
| attributes 'Test-Entry': 'PASSED'
| attributes 'New-Entry': 'NEW'
| }
|}
""".stripMargin()

when:
runner.arguments << 'jar'
runner.arguments << 'shadowJar'
ExecutionResult result = runner.run()

then:
success(result)
File jar = file('build/libs/jar.jar')
assert jar.exists()
assert output.exists()

then: 'Check contents of Shadow jar manifest'
JarInputStream jis = new JarInputStream(output.newInputStream())
Manifest mf = jis.manifest

assert mf
assert mf.mainAttributes.getValue('Test-Entry') == 'PASSED'
assert mf.mainAttributes.getValue('Main-Class') == 'shadow.Main'
assert mf.mainAttributes.getValue('New-Entry') == 'NEW'

then: 'Check contents of jar manifest'
JarInputStream jis2 = new JarInputStream(jar.newInputStream())
Manifest mf2 = jis2.manifest

assert mf2
assert mf2.mainAttributes.getValue('Test-Entry') == 'FAILED'
assert mf2.mainAttributes.getValue('Main-Class') == 'shadow.Main'
assert !mf2.mainAttributes.getValue('New-Entry')

cleanup:
jis?.close()
jis2?.close()
}

@Issue('SHADOW-82')
def 'shadow.appendManifest leaks to jar.manifest'() {
given:
File main = file('src/main/java/shadow/Main.java')
main << '''
|package shadow;
|
|public class Main {
|
| public static void main(String[] args) { }
|}
'''.stripMargin()

buildFile << """
|apply plugin: 'java'
|apply plugin: ${ShadowPlugin.name}
|
|jar {
| baseName = 'jar'
| manifest {
| attributes 'Main-Class': 'shadow.Main'
| attributes 'Test-Entry': 'FAILED'
| }
|}
|
|shadowJar {
| baseName = 'shadow'
| classifier = null
| appendManifest {
| attributes 'Test-Entry': 'PASSED'
| attributes 'New-Entry': 'NEW'
| }
|}
""".stripMargin()

when:
runner.arguments << 'jar'
runner.arguments << 'shadowJar'
ExecutionResult result = runner.run()

then:
success(result)
File jar = file('build/libs/jar.jar')
assert jar.exists()
assert output.exists()

then: 'Check contents of Shadow jar manifest'
JarInputStream jis = new JarInputStream(output.newInputStream())
Manifest mf = jis.manifest

assert mf
assert mf.mainAttributes.getValue('Test-Entry') == 'PASSED'
assert mf.mainAttributes.getValue('Main-Class') == 'shadow.Main'
assert mf.mainAttributes.getValue('New-Entry') == 'NEW'

then: 'Check contents of jar manifest'
JarInputStream jis2 = new JarInputStream(jar.newInputStream())
Manifest mf2 = jis2.manifest

assert mf2
assert mf2.mainAttributes.getValue('Test-Entry') == 'FAILED'
assert mf2.mainAttributes.getValue('Main-Class') == 'shadow.Main'
assert !mf2.mainAttributes.getValue('New-Entry')

cleanup:
jis?.close()
jis2?.close()
}

def 'Groovy extension module transformer'() {
given:
def one = buildJar('one.jar')
Expand Down

0 comments on commit bb8ccd8

Please sign in to comment.