This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch GROOVY-11571 in repository https://gitbox.apache.org/repos/asf/groovy.git
commit eb936b97e824ce6192c8f4cafbe5b1042cfe2402 Author: Eric Milles <[email protected]> AuthorDate: Tue Feb 25 16:38:03 2025 -0600 remove excess manifest attributes * Bundle-ClassPath * DynamicImport-Package * Eclipse-BuddyPolicy * Eclipse-ExtensibleAPI * Extension-Name --- .../src/main/groovy/org.apache.groovy-base.gradle | 69 +++++----- .../src/main/groovy/org.apache.groovy-core.gradle | 17 +-- .../main/groovy/org.apache.groovy-library.gradle | 23 ++-- .../groovy/gradle/GroovyLibraryExtension.groovy | 54 ++++---- .../org/apache/groovy/gradle/JarJarTask.groovy | 150 ++++++++++----------- 5 files changed, 147 insertions(+), 166 deletions(-) diff --git a/build-logic/src/main/groovy/org.apache.groovy-base.gradle b/build-logic/src/main/groovy/org.apache.groovy-base.gradle index 687c461d93..8be3e653d8 100644 --- a/build-logic/src/main/groovy/org.apache.groovy-base.gradle +++ b/build-logic/src/main/groovy/org.apache.groovy-base.gradle @@ -47,16 +47,16 @@ if (sharedConfiguration.hasCodeCoverage.get()) { pluginManager.apply(JacocoPlugin) } -def groovyLibrary = project.extensions.create("groovyLibrary", GroovyLibraryExtension, sharedConfiguration, java) +def groovyLibrary = project.extensions.create('groovyLibrary', GroovyLibraryExtension, sharedConfiguration, java) java { withSourcesJar() withJavadocJar() } -def generateReleaseInfo = tasks.register("generateReleaseInfo", ReleaseInfoGenerator) +def generateReleaseInfo = tasks.register('generateReleaseInfo', ReleaseInfoGenerator) -def groovydocJar = tasks.register("groovydocJar", Jar) { +def groovydocJar = tasks.register('groovydocJar', Jar) { from groovydoc archiveClassifier = 'groovydoc' group = 'build' @@ -70,7 +70,7 @@ configurations { attributes { attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.DOCUMENTATION)) attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL)) - attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, "groovydoc")) + attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, 'groovydoc')) attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME)) } outgoing { @@ -86,7 +86,7 @@ configurations { attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.DOCUMENTATION)) attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL)) attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, DocsType.SOURCES)) - attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, "aggregation")) + attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, 'aggregation')) } outgoing { sourceSets.main.java.srcDirs.each { @@ -104,7 +104,7 @@ configurations { attributes { attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.LIBRARY)) attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL)) - attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, "javadocClasspath")) + attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, 'javadocClasspath')) } outgoing { artifact tasks.named('jar') @@ -112,12 +112,12 @@ configurations { } codenarc { resolutionStrategy.dependencySubstitution { - substitute module("org.codehaus.groovy:groovy") using project(":") - substitute module("org.codehaus.groovy:groovy-ant") using project(":groovy-ant") - substitute module("org.codehaus.groovy:groovy-templates") using project(":groovy-templates") - substitute module("org.codehaus.groovy:groovy-xml") using project(":groovy-xml") - substitute module("org.codehaus.groovy:groovy-json") using project(":groovy-json") - substitute module("org.codehaus.groovy:groovy-groovydoc") using project(":groovy-groovydoc") + substitute module('org.codehaus.groovy:groovy') using project(':') + substitute module('org.codehaus.groovy:groovy-ant') using project(':groovy-ant') + substitute module('org.codehaus.groovy:groovy-xml') using project(':groovy-xml') + substitute module('org.codehaus.groovy:groovy-json') using project(':groovy-json') + substitute module('org.codehaus.groovy:groovy-groovydoc') using project(':groovy-groovydoc') + substitute module('org.codehaus.groovy:groovy-templates') using project(':groovy-templates') } exclude module: 'groovy-all' @@ -128,7 +128,7 @@ dependencies { compileOnly providers.provider { "com.github.spotbugs:spotbugs-annotations:${versions.spotbugs}" } codenarc "org.codenarc:CodeNarc:${versions.codenarc}" - codenarc project(":groovy-templates") + codenarc project(':groovy-templates') checkstyle "com.puppycrawl.tools:checkstyle:${versions.checkstyle}" spotbugs "com.github.spotbugs:spotbugs:${versions.spotbugs}" @@ -138,15 +138,16 @@ dependencies { } def excludedFromManifest = [ - 'Ant-Version', - 'Originally-Created-By', - 'Bnd-LastModified', - 'Created-By' + 'Ant-Version', + 'Bnd-LastModified', + 'Created-By', + 'Originally-Created-By', + 'Tool' ] tasks.named('jar') { archiveAppendix = 'raw' - archiveClassifier.set("raw") + archiveClassifier.set('raw') groovyLibrary.configureManifest(manifest, excludedFromManifest) } @@ -155,7 +156,7 @@ tasks.withType(AbstractArchiveTask).configureEach { reproducibleFileOrder = true } -tasks.withType(Jar).configureEach {jar -> +tasks.withType(Jar).configureEach { jar -> metaInf { if (jar.name == 'sourcesJar') { if (file("${projectDir}/LICENSE").exists()) { @@ -177,7 +178,7 @@ tasks.withType(Jar).configureEach {jar -> } } -tasks.register("jarjar", JarJarTask) { +tasks.register('jarjar', JarJarTask) { from = jar.archiveFile repackagedLibraries.from configurations.runtimeClasspath.incoming.artifactView { componentFilter { component -> @@ -208,9 +209,9 @@ tasks.register("jarjar", JarJarTask) { outputFile = tasks.named('jar').flatMap { layout.buildDirectory.file("libs/${it.archiveBaseName.get()}-${it.archiveVersion.get()}${(it.archiveClassifier.get() && it.archiveClassifier.get() != 'raw') ? '-' + it.archiveClassifier.get() : ''}.jar") } withManifest { - def extras = project.name == 'groovy' ? ['Main-Class': 'groovy.ui.GroovyMain'] : [:] - def moduleName = "org.apache.${project.name.replace('-', '.')}" - attributes('Automatic-Module-Name': moduleName, 'Bundle-Name': 'Groovy module: ' + project.name, *:extras) + String projectName = project.name + String autoModName = "org.apache.${projectName.replace('-','.')}" + attributes('Automatic-Module-Name': autoModName, 'Bundle-Name': "Groovy module: $projectName") groovyLibrary.configureManifest(it, excludedFromManifest) classpath = configurations.runtimeClasspath } @@ -225,17 +226,17 @@ tasks.withType(Javadoc).configureEach { options.source = sharedConfiguration.targetJavaVersion.get() } -tasks.named("compileTestGroovy") { - options.forkOptions.jvmArgs += ["-Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true"] +tasks.named('compileTestGroovy') { + options.forkOptions.jvmArgs += ['-Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true'] } tasks.withType(CodeNarc).configureEach { ignoreFailures = true - configFile = rootProject.file("config/codenarc/codenarc.groovy") + configFile = rootProject.file('config/codenarc/codenarc.groovy') } tasks.withType(SpotBugsTask).configureEach { - excludeFilter = rootProject.file("config/spotbugs/exclude.xml") + excludeFilter = rootProject.file('config/spotbugs/exclude.xml') ignoreFailures = true effort = Effort.valueOf('MAX') maxHeapSize = '2g' @@ -250,14 +251,14 @@ tasks.withType(SpotBugsTask).configureEach { } } -tasks.register("checkstyle") { +tasks.register('checkstyle') { dependsOn tasks.withType(Checkstyle) } tasks.withType(Checkstyle).configureEach {chk -> showViolations = false ignoreFailures = true - configFile = rootProject.file("config/checkstyle/checkstyle.xml") + configFile = rootProject.file('config/checkstyle/checkstyle.xml') configProperties = ['rootProject.projectDir': rootProject.projectDir] def reportFile = layout.buildDirectory.file("reports/checkstyle/${name}.xml") reports { @@ -271,7 +272,7 @@ tasks.withType(Checkstyle).configureEach {chk -> tasks.register("${name}Report", CheckstyleHtmlReport) { dependsOn chk source.from(chk.source) - configFile = rootProject.file("config/checkstyle/checkstyle-report.groovy") + configFile = rootProject.file('config/checkstyle/checkstyle-report.groovy') checkstyleReportFile = reportFile outputFile = layout.buildDirectory.file("reports/checkstyle/${chk.name}.html") } @@ -280,8 +281,8 @@ tasks.withType(Checkstyle).configureEach {chk -> // remove below if checkstyle fix up their dependency metadata to no longer have conflicts configurations.checkstyle { - resolutionStrategy.capabilitiesResolution.withCapability("com.google.collections:google-collections") { - select("com.google.guava:guava:0") + resolutionStrategy.capabilitiesResolution.withCapability('com.google.collections:google-collections') { + select('com.google.guava:guava:0') } } @@ -317,8 +318,8 @@ def shadowRuntime = createConsumableConfiguration(objects, tasks, configurations dependencies { // All Groovy modules depend on the Groovy BOM which itself has constraints on all // Groovy modules, which brings nice alignment features! - groovyApiElements platform(project(":groovy-bom")) - groovyRuntimeElements platform(project(":groovy-bom")) + groovyApiElements platform(project(':groovy-bom')) + groovyRuntimeElements platform(project(':groovy-bom')) } component.addVariantsFromConfiguration(shadowApi) { diff --git a/build-logic/src/main/groovy/org.apache.groovy-core.gradle b/build-logic/src/main/groovy/org.apache.groovy-core.gradle index a669c72e95..4aaab8e5c3 100644 --- a/build-logic/src/main/groovy/org.apache.groovy-core.gradle +++ b/build-logic/src/main/groovy/org.apache.groovy-core.gradle @@ -17,13 +17,10 @@ * under the License. */ - import org.apache.groovy.gradle.CoreExtension import org.apache.groovy.gradle.DgmConverter import org.apache.groovy.gradle.JarJarTask -import javax.inject.Inject - plugins { id 'org.apache.groovy-common' id 'org.apache.groovy-base' @@ -104,7 +101,7 @@ sourceSets { } } -def dgmConverter = tasks.register("dgmConverter", DgmConverter) { +def dgmConverter = tasks.register('dgmConverter', DgmConverter) { classpath.from files(compileJava, configurations.compileClasspath) sources.from('src/main').include('**/*GroovyMethods.java') } @@ -117,24 +114,22 @@ tasks.named('jar') { from dgmConverter } -tasks.named('jarjar') { JarJarTask it -> +tasks.named('jarjar') { JarJarTask jjt -> def groovyBundleVersion = sharedConfiguration.groovyBundleVersion.get() - it.withManifest { - version = groovyBundleVersion + jjt.withManifest { instruction '-nouses', 'true' instruction 'Export-Package', "*;version=${groovyBundleVersion}" - instruction 'Eclipse-ExtensibleAPI', 'true' } } // Gradle classloading magic with Groovy will only work if it finds a *jar* // on classpath. This "bootstrap jar" contains the minimal compiler, without .groovy compiled files -def bootstrapJar = tasks.register("bootstrapJar", Jar) { +def bootstrapJar = tasks.register('bootstrapJar', Jar) { from compileJava from dgmConverter - destinationDirectory = layout.buildDirectory.dir("bootstrap") + destinationDirectory = layout.buildDirectory.dir('bootstrap') archiveClassifier = 'bootstrap' } @@ -155,7 +150,7 @@ allprojects { } interface CoreServices { - @Inject + @javax.inject.Inject ExecOperations getExecOperations() } diff --git a/build-logic/src/main/groovy/org.apache.groovy-library.gradle b/build-logic/src/main/groovy/org.apache.groovy-library.gradle index 44ee89f65a..12232b12fe 100644 --- a/build-logic/src/main/groovy/org.apache.groovy-library.gradle +++ b/build-logic/src/main/groovy/org.apache.groovy-library.gradle @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import org.apache.groovy.gradle.JarJarTask plugins { @@ -29,23 +30,19 @@ dependencies { testImplementation testFixtures(project(":")) } -tasks.named('jarjar') { JarJarTask it -> +tasks.named('jarjar') { JarJarTask jjt -> def groovyBundleVersion = sharedConfiguration.groovyBundleVersion.get() - def symbolicName = project.name - it.withManifest { - version = groovyBundleVersion + jjt.withManifest { instruction '-nouses', 'true' instruction 'Export-Package', "*;version=${groovyBundleVersion}" - instruction 'Fragment-Host', 'groovy' + instruction 'Fragment-Host', 'groovy' // GROOVY-9402, GROOVY-11570 def folder = file("${projectDir}/src/main/resources/META-INF/services") - if (folder.exists()) { - if (folder.listFiles().count { it.name ==~ /^(?!(org.codehaus.groovy.transform.ASTTransformation)$).*$/ } > 0) { - instruction 'Require-Capability', 'osgi.extender;filter:="(osgi.extender=osgi.serviceloader.registrar)"' - instruction 'Require-Capability', 'osgi.extender;filter:="(osgi.extender=osgi.serviceloader.processor)"' - folder.eachFileMatch(~/^(?!(org.codehaus.groovy.transform.ASTTransformation)$).*$/) { - instruction 'Require-Capability', "osgi.serviceloader;filter:=\"(osgi.serviceloader=${it.name})\";cardinality:=multiple" - instruction 'Provide-Capability', "osgi.serviceloader;osgi.serviceloader=\"${it.name}\"" - } + if (folder.exists() && folder.listFiles().count { it.name ==~ /^(?!(org.codehaus.groovy.transform.ASTTransformation)$).*$/ } > 0) { + instruction 'Require-Capability', 'osgi.extender;filter:="(osgi.extender=osgi.serviceloader.processor)"' + instruction 'Require-Capability', 'osgi.extender;filter:="(osgi.extender=osgi.serviceloader.registrar)"' + folder.eachFileMatch(~/^(?!(org.codehaus.groovy.transform.ASTTransformation)$).*$/) { + instruction 'Require-Capability', "osgi.serviceloader;filter:=\"(osgi.serviceloader=${it.name})\";cardinality:=multiple" + instruction 'Provide-Capability', "osgi.serviceloader;osgi.serviceloader=\"${it.name}\"" } } } diff --git a/build-logic/src/main/groovy/org/apache/groovy/gradle/GroovyLibraryExtension.groovy b/build-logic/src/main/groovy/org/apache/groovy/gradle/GroovyLibraryExtension.groovy index c306b1a61b..68fc48b589 100644 --- a/build-logic/src/main/groovy/org/apache/groovy/gradle/GroovyLibraryExtension.groovy +++ b/build-logic/src/main/groovy/org/apache/groovy/gradle/GroovyLibraryExtension.groovy @@ -20,6 +20,7 @@ package org.apache.groovy.gradle import groovy.transform.CompileStatic import org.gradle.api.Action +import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.ConfigurationContainer @@ -60,20 +61,20 @@ class GroovyLibraryExtension { final JavaPluginExtension javaPluginExtension final SoftwareComponentContainer components final ConfigurationContainer configurations - final TaskContainer tasks + private final String projectName final ProjectLayout layout + final TaskContainer tasks @Inject GroovyLibraryExtension(ObjectFactory factory, - ProjectLayout layout, SharedConfiguration sharedConfiguration, JavaPluginExtension javaPluginExtension, SoftwareComponentContainer components, ConfigurationContainer configurations, + Project project, ProjectLayout layout, TaskContainer tasks ) { this.objects = factory - this.layout = layout this.sharedConfiguration = sharedConfiguration this.includeInGroovyAll = factory.property(Boolean).convention(true) this.grooid = factory.property(Boolean).convention(false) @@ -82,6 +83,8 @@ class GroovyLibraryExtension { this.javaPluginExtension = javaPluginExtension this.components = components this.configurations = configurations + this.projectName = project.name + this.layout = layout this.tasks = tasks } @@ -192,7 +195,7 @@ class GroovyLibraryExtension { void configureManifest(Manifest manifest, List<String> exclusions) { manifest.from(createBaseManifest()) { ManifestMergeSpec spec -> spec.eachEntry { ManifestMergeDetails details -> - if (exclusions.any { it == details.key }) { + if (exclusions.contains(details.getKey())) { details.exclude() } } @@ -201,25 +204,24 @@ class GroovyLibraryExtension { private Manifest createBaseManifest() { def groovyBundleVersion = sharedConfiguration.groovyBundleVersion.get() - javaPluginExtension.manifest { Manifest mn -> - mn.attributes( - 'Extension-Name': 'groovy', - 'Specification-Title': 'Groovy: a powerful, multi-faceted language for the JVM', - 'Specification-Version': groovyBundleVersion, - 'Specification-Vendor': 'The Apache Software Foundation', - 'Implementation-Title': 'Groovy: a powerful, multi-faceted language for the JVM', - 'Implementation-Version': groovyBundleVersion, - 'Implementation-Vendor': 'The Apache Software Foundation', - 'Bundle-ManifestVersion': '2', - 'Bundle-Description': 'Groovy Runtime', - 'Bundle-License': 'Apache-2.0', - 'Bundle-Version': groovyBundleVersion, - 'Bundle-Vendor': 'The Apache Software Foundation', - 'Bundle-ClassPath': '.', - 'Eclipse-BuddyPolicy': 'dependent', - 'DynamicImport-Package': '*') + javaPluginExtension.manifest { + attributes( + 'Bundle-ManifestVersion': '2', + 'Bundle-Description' : 'Groovy Runtime', + 'Bundle-Vendor' : 'The Apache Software Foundation', + 'Bundle-Version' : groovyBundleVersion, + 'Bundle-License' : 'Apache-2.0', + 'Specification-Title' : 'Groovy: a powerful, multi-faceted language for the JVM', + 'Specification-Vendor' : 'The Apache Software Foundation', + 'Specification-Version' : groovyBundleVersion, + 'Implementation-Title' : 'Groovy: a powerful, multi-faceted language for the JVM', + 'Implementation-Vendor' : 'The Apache Software Foundation', + 'Implementation-Version': groovyBundleVersion + ) + if (projectName == 'groovy') { + attributes('Main-Class': 'groovy.ui.GroovyMain') + } } - } class ModuleDescriptorSpec { @@ -227,11 +229,11 @@ class GroovyLibraryExtension { String staticExtensionClasses = '' private void build() { - def moduleDescriptor = tasks.register("moduleDescriptor", WriteExtensionDescriptorTask) { - it.extensionClasses = extensionClasses - it.staticExtensionClasses = staticExtensionClasses + def moduleDescriptor = tasks.register('moduleDescriptor', WriteExtensionDescriptorTask) { t -> + t.extensionClasses = extensionClasses + t.staticExtensionClasses = staticExtensionClasses } - tasks.named("processResources") { Task t -> + tasks.named('processResources') { Task t -> t.dependsOn(moduleDescriptor) } } diff --git a/build-logic/src/main/groovy/org/apache/groovy/gradle/JarJarTask.groovy b/build-logic/src/main/groovy/org/apache/groovy/gradle/JarJarTask.groovy index 8f661b3518..e5b879bd27 100644 --- a/build-logic/src/main/groovy/org/apache/groovy/gradle/JarJarTask.groovy +++ b/build-logic/src/main/groovy/org/apache/groovy/gradle/JarJarTask.groovy @@ -18,7 +18,10 @@ */ package org.apache.groovy.gradle -import groovy.transform.CompileStatic +import groovy.transform.AutoFinal + +import javax.inject.Inject + import org.gradle.api.Action import org.gradle.api.DefaultTask import org.gradle.api.file.ConfigurableFileCollection @@ -31,22 +34,15 @@ import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction -import javax.inject.Inject - -@CacheableTask +@AutoFinal @CacheableTask class JarJarTask extends DefaultTask { - private final static String JARJAR_CLASS_NAME = 'com.eed3si9n.jarjar.JarJarTask' @Internal - String description = "Repackages dependencies into a shaded jar" - - private List<Action<? super Manifest>> manifestTweaks = [] - - private final FileSystemOperations fs + String description = 'Repackages dependencies into a shaded jar' @InputFile @Classpath @@ -90,13 +86,17 @@ class JarJarTask extends DefaultTask { @Input boolean createManifest = true + private final FileSystemOperations fs + + private List<Action<? super Manifest>> manifestTweaks = [] + @Inject JarJarTask(FileSystemOperations fileSystemOperations) { this.fs = fileSystemOperations } void withManifest(Action<? super Manifest> action) { - manifestTweaks << action + manifestTweaks.add(action) } @Internal @@ -106,89 +106,75 @@ class JarJarTask extends DefaultTask { @TaskAction void generateDescriptor() { - def originalJar = from.get() - def outputFile = this.outputFile.get().asFile - def tmpJar = new File(temporaryDir, "${outputFile.name}.${Integer.toHexString(UUID.randomUUID().hashCode())}.tmp") - tmpJar.deleteOnExit() - def manifestFile = new File(temporaryDir, 'MANIFEST.MF') - // First step is to create a repackaged jar + File outputFile = this.outputFile.get().asFile outputFile.parentFile.mkdirs() - def tstamp = Date.parse('yyyy-MM-dd HH:mm', '1980-02-01 00:00').time.toString() - try { - project.ant { - taskdef name: 'jarjar', classname: JARJAR_CLASS_NAME, classpath: jarjarToolClasspath.asPath - jarjar(jarfile: tmpJar, filesonly: true, modificationtime: tstamp) { - 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.extensions.osgi.osgiManifest { - symbolicName = project.name - instruction 'Import-Package', '*;resolution:=optional' - classesDir = tmpJar - } + File tmpJar = new File(temporaryDir, "${archiveName}.${Integer.toHexString(UUID.randomUUID().hashCode())}.tmp") + tmpJar.deleteOnExit() - manifestTweaks.each { - it.execute(mf) + File manifestFile = new File(temporaryDir, 'MANIFEST.MF') + manifestFile.deleteOnExit() + + // TODO: add note to explain the fixed date-time timestamp + String tstamp = Date.parse('yyyy-MM-dd HH:mm', '1980-02-01 00:00').getTime().toString() + + // Step 1: create a repackaged jar + project.ant { + taskdef name: 'jarjar', classname: 'com.eed3si9n.jarjar.JarJarTask', classpath: jarjarToolClasspath.asPath + jarjar(jarfile: tmpJar, filesonly: true, modificationtime: tstamp) { + zipfileset(src: from.get(), 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 } + } + } - // then we need to generate the manifest file - mf.writeTo(manifestFile) + fs.copy { spec -> + spec.from(tmpJar) + spec.into(outputFile.parentFile) + spec.rename { this.archiveName } + } - } else { - manifestFile << '' + // Step 2: update the archive with a class index and any untouched files + project.ant.jar(destfile: outputFile, index: true, modificationtime: tstamp, update: true) { + if (untouchedFiles) { + zipfileset(src: from.get(), includes: untouchedFiles.join(',')) } + } - // so that we can put it into the final jar - fs.copy { - it.from(tmpJar) - it.into(outputFile.parentFile) - it.rename { outputFile.name } + // Step 3: generate an OSGi manifest referencing the repackaged classes + if (createManifest) { + def mf = project.rootProject.extensions.osgi.osgiManifest { + symbolicName = project.name + instruction 'Import-Package', '*;resolution:=optional' + classesDir = tmpJar } - project.ant.jar(destfile: outputFile, update: true, index: true, manifest: manifestFile, modificationtime: tstamp) { - 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 { - fs.delete { - it.delete(manifestFile) + manifestTweaks*.execute(mf) + mf.writeTo(manifestFile) + + project.ant.zip(destfile: outputFile, modificationtime: tstamp, update: true) { + zipfileset(dir: manifestFile.parent, includes: manifestFile.name, prefix: 'META-INF') } } } - @CompileStatic private static String baseName(File file) { file.name.substring(0, file.name.lastIndexOf('-')) }
