blob: df5588f6b40fa6c2f7e255f6e241312b9bf1cb0c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.codehaus.groovy.gradle
import groovy.transform.CompileStatic
import org.gradle.api.Action
import org.gradle.api.DefaultTask
import org.gradle.api.file.FileCollection
import org.gradle.api.java.archives.Manifest
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
@CacheableTask
class JarJarTask extends DefaultTask {
private final static String JARJAR_CLASS_NAME = 'org.pantsbuild.jarjar.JarJarTask'
String description = "Repackages dependencies into a shaded jar"
private List<Action<? super Manifest>> manifestTweaks = []
@Input
File from
@Input
FileCollection repackagedLibraries
@Input
FileCollection jarjarToolClasspath
@Input
@org.gradle.api.tasks.Optional
List<String> untouchedFiles = []
@Input
@org.gradle.api.tasks.Optional
List<String> excludes = []
@Input
Map<String, String> patterns
@Input
@org.gradle.api.tasks.Optional
Map<String, List<String>> excludesPerLibrary = [:]
@Input
@org.gradle.api.tasks.Optional
Map<String, List<String>> includesPerLibrary = [:]
@Input
@org.gradle.api.tasks.Optional
Map<String, String> includedResources = [:]
@OutputFile
File outputFile
@Input
@org.gradle.api.tasks.Optional
boolean createManifest = true
void withManifest(Action<? super Manifest> action) {
manifestTweaks << action
}
String getArchiveName() {
outputFile.name
}
@TaskAction
void generateDescriptor() {
def originalJar = from
def tmpJar = new File(temporaryDir, "${outputFile.name}.${Integer.toHexString(UUID.randomUUID().hashCode())}.tmp")
def manifestFile = new File(temporaryDir, 'MANIFEST.MF')
// First step is to create a repackaged jar
outputFile.parentFile.mkdirs()
try {
project.ant {
taskdef name: 'jarjar', classname: JARJAR_CLASS_NAME, classpath: jarjarToolClasspath.asPath
jarjar(jarfile: tmpJar, filesonly: true) {
zipfileset(
src: originalJar,
excludes: (untouchedFiles+excludes).join(','))
includedResources.each { String resource, String path ->
String dir = resource.substring(0, resource.lastIndexOf('/') + 1)
String filename = resource.substring(resource.lastIndexOf('/') + 1)
zipfileset(dir: dir, includes: filename, fullpath: path)
}
repackagedLibraries.files.each { File library ->
def libraryName = JarJarTask.baseName(library)
def includes = includesPerLibrary[libraryName]
def excludes = excludesPerLibrary[libraryName]
if (includes) {
zipfileset(src: library, includes: includes.join(','))
} else if (excludes) {
zipfileset(src: library, excludes: excludes.join(','))
} else {
zipfileset(src: library, excludes: excludesPerLibrary['*'].join(','))
}
}
patterns.each { pattern, result ->
rule pattern: pattern, result: result
}
}
}
if (createManifest) {
// next step is to generate an OSGI manifest using the newly repackaged classes
def mf = project.rootProject.convention.plugins.osgi.osgiManifest {
symbolicName = project.name
instruction 'Import-Package', '*;resolution:=optional'
classesDir = tmpJar
}
manifestTweaks.each {
it.execute(mf)
}
// then we need to generate the manifest file
mf.writeTo(manifestFile)
} else {
manifestFile << ''
}
// so that we can put it into the final jar
project.ant.copy(file: tmpJar, tofile: outputFile)
project.ant.jar(destfile: outputFile, update: true, index: true, manifest: manifestFile) {
manifest {
// because we don't want to use JDK 1.8.0_91, we don't care and it will
// introduce cache misses
attribute(name:'Created-By', value:'Gradle')
}
if (untouchedFiles) {
zipfileset(
src: originalJar,
includes: untouchedFiles.join(','))
}
}
} finally {
manifestFile.delete()
project.ant.delete(file: tmpJar, quiet: true, deleteonexit: true)
}
}
@CompileStatic
private static String baseName(File file) {
file.name.substring(0, file.name.lastIndexOf('-'))
}
}