/*
 *  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.
 */
import org.apache.tools.ant.filters.ReplaceTokens

apply plugin: 'osgi'

group = 'org.codehaus.groovy'
archivesBaseName = 'groovy'

ext.srcSpec = copySpec {
    from(projectDir) {
        exclude 'target',
                'benchmark',
                'subprojects/*/target',
                'buildSrc/target',
                buildDir.path,
                'classes/**',
                'cruise/**',
                'security/groovykeys',
                '.clover/*',
                'local.build.properties',
                'gradle/wrapper',
                'gradlew',
                'gradlew.bat',
                'cobertura.ser',
                'junitvmwatcher*.properties',
                'out',
                'bintray.properties', // generated by the CI server
                'gradle.properties.gz', // generated by the CI server
                '**/*.iml',         // used by Intellij IDEA
                '**/*.ipr',         // used by Intellij IDEA
                '**/*.iws',         // used by Intellij IDEA
                '.settings',        // used by Eclipse
                '.gradle',          // used by Gradle
                'buildSrc/.gradle'  // used by Gradle
    }
}

ext.docSpec = copySpec {
    into('pdf') {
        from 'src/wiki-snapshot.pdf'
    }
    into('html/api') {
        from javadocAll.destinationDir
    }
    into('html/gapi') {
        from groovydocAll.destinationDir
    }
    into('html/documentation') {
        from "$buildDir/asciidoc/html5"
    }
    into('html/groovy-jdk') {
        from docGDK.destinationDir
    }
    into('licenses') {
        from 'licenses'
        include 'asciidoc-style-license.txt'
        include 'jquery-js-license.txt'
        include 'normalize-stylesheet-license.txt'
    }
    from "$projectDir/licenses/LICENSE-DOC"
    from "$projectDir/notices/NOTICE-BASE"
    from "$projectDir/DISCLAIMER"
    rename 'LICENSE-DOC', 'LICENSE'
    rename 'NOTICE-BASE', 'NOTICE'
}

task copy(type: Copy) {
    into "$buildDir/meta"
}

ext.allManifest = manifest {
    attributes('Built-By': System.properties['user.name'],
            'Extension-Name': 'groovy',
            'Specification-Title': 'Groovy: a powerful, dynamic language for the JVM',
            'Specification-Version': groovyBundleVersion,
            'Specification-Vendor': 'The Apache Software Foundation',
            'Implementation-Title': 'Groovy: a powerful, dynamic language for the JVM',
            'Implementation-Version': groovyBundleVersion,
            'Implementation-Vendor': 'The Apache Software Foundation',
            'Bundle-ManifestVersion': '2',
            'Bundle-Name': 'Groovy Runtime',
            'Bundle-Description': 'Groovy Runtime',
            'Bundle-Version': groovyBundleVersion,
            'Bundle-Vendor': 'The Apache Software Foundation',
            'Bundle-ClassPath': '.',
            'Eclipse-BuddyPolicy': 'dependent',
            'DynamicImport-Package': '*',
            'Main-class': 'groovy.ui.GroovyMain')
}

ext.groovyOsgiManifest = {
    // Exclude the Bnd-LastModified attribute as it always triggers a rebuild without being really needed.
    from(allManifest) {
        eachEntry { details ->
            if (details.key == 'Bnd-LastModified') {
                details.exclude()
            }
        }
    }
    version = groovyBundleVersion
    instruction '-nouses', 'true'
    instruction 'Export-Package', "*;version=${groovyBundleVersion}"
    classpath = sourceSets.main.runtimeClasspath
}

ext.subprojectOsgiManifest = {
    // Exclude attributes not needed for subprojects.
    from(allManifest) {
        eachEntry { details ->
            if (details.key in ['Bnd-LastModified', 'Extension-Name', 'Bundle-Name', 'Bundle-Description', 'Main-class']) {
                details.exclude()
            }
        }
    }
    version = groovyBundleVersion
    instruction '-nouses', 'true'
    instruction 'Export-Package', "*;version=${groovyBundleVersion}"
    classpath = sourceSets.main.runtimeClasspath
}

jar {
    dependsOn('dgmConverter')
    metaInf {
        from("$projectDir/licenses/LICENSE-JARJAR")
        from("$projectDir/licenses") {
            into('licenses')
            include('asm-license.txt')
            include('antlr2-license.txt')
        }
        from("$projectDir/notices/NOTICE-JARJAR")
        from 'DISCLAIMER'
        from('src/main/META-INF/groovy-release-info.properties') {
            filter(rootProject.propertiesFilter, org.apache.tools.ant.filters.ReplaceTokens)
        }
        rename { String filename -> filename == 'LICENSE-JARJAR' ? 'LICENSE' : filename == 'NOTICE-JARJAR' ? 'NOTICE' : filename }
    }

    exclude '**/package-info.class', 'META-INF/groovy-release-info.properties'

}

allprojects {
    task jarjar(type:Jar, dependsOn: jar) {
        destinationDir = jar.destinationDir
        baseName = jar.baseName
        appendix = jar.appendix?"${jar.appendix}-jarjar":"jarjar"
        classifier = jar.classifier
        includeEmptyDirs = false
        def target = new File("${archivePath}.tmp")
        def targetTmp = new File("${archivePath}.tmp.1.tmp")

        doFirst {
            from zipTree(target)

            def keepUntouched = [
                    'org/codehaus/groovy/cli/GroovyPosixParser*.class',
                    'groovy/util/CliBuilder*.class',
                    'groovy/util/OptionAccessor*.class',
                    'org/codehaus/groovy/tools/shell/util/HelpFormatter*.class'
            ].join(',')
            boolean isRoot = project == rootProject
            def gradleProject = project
            ant {
                taskdef name: 'jarjar', classname: 'com.tonicsystems.jarjar.JarJarTask', classpath: rootProject.configurations.tools.asPath
                jarjar(jarfile: targetTmp) {
                    zipfileset(
                            src: jar.archivePath,
                            excludes: keepUntouched)

                    // only groovy core will include the dependencies repackaged
                    if (isRoot) {
                        configurations.runtime.files.findAll { file ->
                            ['antlr', 'asm', 'commons-cli'].any {
                                file.name.startsWith(it)
                            } && ['asm-attr', 'asm-util', 'asm-analysis'].every { !file.name.startsWith(it) }
                        }.each { jarjarFile ->
                            // GROOVY-7386 : excludes needed below to stop copy of incorrect maven meta info
                            zipfileset(src: jarjarFile, excludes: 'META-INF/maven/commons-cli/commons-cli/*,META-INF/*')
                        }

                        zipfileset(src: configurations.runtime.files.find { file -> file.name.startsWith('asm-util') },
                                includes: 'org/objectweb/asm/util/Printer.class,org/objectweb/asm/util/Textifier.class,org/objectweb/asm/util/Trace*')
                    }
                    rule pattern: 'antlr.**', result: 'groovyjarjarantlr.@1'
                    rule pattern: 'org.objectweb.**', result: 'groovyjarjarasm.@1'
                    rule pattern: 'org.apache.commons.cli.**', result: 'groovyjarjarcommonscli.@1'
                }
            }

            def manifestSpec = isRoot ? groovyOsgiManifest : subprojectOsgiManifest
            manifest = osgiManifest {
                symbolicName = gradleProject.name
                instruction 'Import-Package', '*;resolution:=optional'
                classesDir = targetTmp
            }
            manifest(manifestSpec)

            def manifestPath = "${temporaryDir}/META-INF/MANIFEST.MF"
            manifest.writeTo(manifestPath)

            ant.copy(file: targetTmp, tofile: target)
            ant.jar(destfile: target, update: true, manifest: manifestPath) {
                zipfileset(
                        src: jar.archivePath,
                        includes: keepUntouched)
            }

        }
        doLast {
            target.delete()
            ant.delete(file: targetTmp, quiet: true, deleteonexit: true)
        }
    }

    if (project.name in ['groovy', 'groovy-test']) {
        task grooidjar(type: Jar) {
            onlyIf {
                !rootProject.useIndy()
            }
            destinationDir = jar.destinationDir
            baseName = jar.baseName
            appendix = jar.appendix
            classifier = jar.classifier ? "${jar.classifier}grooid" : 'grooid'
            includeEmptyDirs = false
            def target = new File("${archivePath}.tmp")
            boolean isRootProject = project==rootProject

            doFirst {
                from zipTree(target)
                ant {
                    taskdef name: 'jarjar', classname: 'com.tonicsystems.jarjar.JarJarTask', classpath: rootProject.configurations.tools.asPath
                    jarjar(jarfile: target) {
                        zipfileset(dir: "$rootProject.projectDir/notices/", includes: isRootProject ? 'NOTICE-GROOIDJARJAR' : 'NOTICE-GROOID', fullpath: 'META-INF/NOTICE')
                        zipfileset(src: jarjar.archivePath, excludes: 'META-INF/NOTICE')
                        if (isRootProject) {
                            zipfileset(src: rootProject.configurations.runtime.files.find { it.name.startsWith('openbeans') }, excludes: 'META-INF/*')
                        }
                        rule pattern: 'com.googlecode.openbeans.**', result: 'groovyjarjaropenbeans.@1'
                        rule pattern: 'org.apache.harmony.beans.**', result: 'groovyjarjarharmonybeans.@1'
                        rule pattern: 'java.beans.**', result: 'groovyjarjaropenbeans.@1'
                    }
                }

            }
            doLast {
                target.delete()
            }
        }
        jarjar.finalizedBy(grooidjar)
    }
}

subprojects { sp ->
    jar {
        metaInf {
            if (file("${projectDir}/LICENSE").exists()) {
                from "${projectDir}/LICENSE"
            } else {
                from "${rootProject.projectDir}/licenses/LICENSE-BASE"
            }
            if (file("${projectDir}/NOTICE").exists()) {
                from "${projectDir}/NOTICE"
            } else {
                from "${rootProject.projectDir}/notices/NOTICE-BASE"
            }
            from "${rootProject.projectDir}/DISCLAIMER"
            from("${rootProject.projectDir}/src/main/META-INF/groovy-release-info.properties") {
                filter(rootProject.propertiesFilter, org.apache.tools.ant.filters.ReplaceTokens)
            }
            rename { String filename -> filename == 'LICENSE-BASE' ? 'LICENSE' : filename == 'NOTICE-BASE' ? 'NOTICE' : filename }
        }
        exclude '**/package-info.class', 'META-INF/groovy-release-info.properties'
    }
}

def moduleJars() {
    modules()*.jar.archivePath
}

def mergeModuleDescriptors() {
    new File("$buildDir/tmp/").mkdirs()

    def extensionClasses = []
    def staticExtensionClasses = []

    modules().collect {
        new File("${it.buildDir}/classes/main/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule")
    }.findAll { it.exists() }.each {
        def props = new Properties()
        props.load(it.newInputStream())
        extensionClasses += props.get('extensionClasses').split(',').findAll { it }
        staticExtensionClasses += props.get('staticExtensionClasses').split(',').findAll { it }
    }

    def descriptor = new File("$buildDir/tmp/org.codehaus.groovy.runtime.ExtensionModule")
    descriptor.withWriter('UTF-8') {
        it << '# This is a generated file, do not edit\n'
        it << 'moduleName=groovy-all\n'
        it << "moduleVersion=${project.version}\n"
        it << "extensionClasses=${extensionClasses.join(',')}\n"
        it << "staticExtensionClasses=${staticExtensionClasses.join(',')}\n"
    }

    descriptor
}

task replaceJarWithJarJar(dependsOn: allprojects.jarjar ) {
    description = "Overwrites normal JAR files with their JARJAR version"
    doLast {
        allprojects {
            def jarjarFile = tasks.jarjar.archivePath
            if (jarjarFile) {
                file(jar.archivePath).delete()
                ant.copy(file: jarjarFile, tofile: jar.archivePath)
                jarjarFile.delete()
            }
        }
    }
    inputs.files(allprojects.jarjar.archivePath)
    outputs.files(allprojects.jar.archivePath)
}

allprojects {
    rootProject.replaceJarWithJarJar.mustRunAfter(test)
}

task jarAll(type: Jar, dependsOn: replaceJarWithJarJar) {

    inputs.files(allprojects.jar.archivePath)

    ext.metaInfDir = "$buildDir/tmp/groovy-all-metainf"
    appendix = 'all'
    includeEmptyDirs = false
    if (rootProject.useIndy()) {
        classifier = 'indy'
    }
    doLast {
        def manifestPath = "$ext.metaInfDir/MANIFEST.MF"
        manifest.writeTo(manifestPath)
        copy {
            from "$projectDir/notices/NOTICE-ALLJARJAR"
            into owner.ext.metaInfDir
            rename('NOTICE-ALLJARJAR', 'NOTICE')
        }
        copy {
            from "$projectDir/licenses"
            into "$owner.ext.metaInfDir/licenses"
            include 'normalize-stylesheet-license.txt'
            include 'jsr223-license.txt'
            include 'jline2-license.txt'
        }
        copy {
            from "$projectDir/licenses/LICENSE-ALLJARJAR"
            into owner.ext.metaInfDir
            rename('LICENSE-ALLJARJAR', 'LICENSE')
        }
        copy {
            from(mergeModuleDescriptors())
            into "$owner.ext.metaInfDir/services"
        }
        copy {
            into "$owner.ext.metaInfDir"
        }
        logger.info 'Packaging with jarjar'

        def archivePathTmp = new File("${archivePath}.1.tmp")
        ant {
            taskdef name: 'jarjar', classname: 'com.tonicsystems.jarjar.JarJarTask', classpath: configurations.tools.asPath
            jarjar(jarfile: archivePathTmp, manifest: "$owner.ext.metaInfDir/MANIFEST.MF") {
                zipfileset(dir: "$owner.ext.metaInfDir", prefix: 'META-INF')
                zipfileset(src: jar.archivePath, excludes:'META-INF/NOTICE,META-INF/LICENSE')
                moduleJars().each {
                    zipfileset(src: it, excludes:'META-INF/NOTICE,META-INF/LICENSE')
                }
            }
        }

        manifest = osgiManifest {
            symbolicName = 'groovy-all'
            instruction 'Import-Package', '*;resolution:=optional'
            classesDir = archivePathTmp
        }
        manifest groovyOsgiManifest
        manifestPath = "${temporaryDir}/META-INF/MANIFEST.MF"
        manifest.writeTo(manifestPath)

        ant {
            copy(file: archivePathTmp, tofile: archivePath)
            jar(destfile: archivePath, update:true, manifest: manifestPath) {
                zipfileset(src: jar.archivePath, excludes:'META-INF')
            }
            delete(file: archivePathTmp, quiet: true, deleteonexit: true)
        }
    }
}

allprojects {
    task jarWithIndy(type: GradleBuild) {
        onlyIf rootProject.indyCapable
        description = 'Triggers an external build generating the indy jar'
        buildFile = 'build.gradle'
        startParameter.projectProperties['indy'] = true
        tasks = ['jar']
    }
}

task jarAllWithIndy(type: GradleBuild) {
    onlyIf rootProject.indyCapable
    description = 'Triggers an external build generating the indy jarAll'
    buildFile = 'build.gradle'
    startParameter.projectProperties['indy'] = true
    tasks = ['jarAll']
}

task jarAllAll(dependsOn: [jarAll, jarAllWithIndy]) {
    description = 'Generates groovy-all and groovy-all-indy jars'
    doFirst {
        if (useIndy()) {
            logger.lifecycle('InvokeDynamic support was activated but needs to be off for this pass. Disabling.')
            ext.useIndy = false
        }
    }
}

allprojects {
    tasks.withType(Test) { task ->
        jarAll.mustRunAfter(task)
        jarAllWithIndy.mustRunAfter(task)
    }
}

task sourceAllJar(type: Jar, dependsOn: { modules()*.sourceJar + rootProject.sourceJar }) {
    with sourceJar.rootSpec
    modules()*.sourceJar.each {
        with it.rootSpec
    }
    appendix = 'all'
    classifier = rootProject.useIndy() ? 'indy-sources' : 'sources'
}

allprojects {
    task javadocJar(type: Jar, dependsOn: javadoc) {
        classifier = rootProject.useIndy() ? 'indy-javadoc' : 'javadoc'
        from javadoc.destinationDir
    }
    task groovydocJar(type: Jar, dependsOn: groovydoc) {
        classifier = rootProject.useIndy() ? 'indy-groovydoc' : 'groovydoc'
        from groovydoc.destinationDir
    }
}

task javadocAllJar(type: Jar, dependsOn: javadocAll) {
    appendix = 'all'
    classifier = rootProject.useIndy() ? 'indy-javadoc' : 'javadoc'
    from javadocAll.destinationDir
}

task groovydocAllJar(type: Jar, dependsOn: groovydocAll) {
    appendix = 'all'
    classifier = rootProject.useIndy() ? 'indy-groovydoc' : 'groovydoc'
    from groovydocAll.destinationDir
}

ext.distSpec = copySpec {
    from("$projectDir/licenses/LICENSE-BINZIP")
    from("$projectDir/notices/NOTICE-BINZIP")
    from("$projectDir/DISCLAIMER")
    rename { String filename -> filename == 'LICENSE-BINZIP' ? 'LICENSE' : filename == 'NOTICE-BINZIP' ? 'NOTICE' : filename }
    into('lib') {
        from jar.archivePath
        from {
            configurations.runtime.findAll {
                it.name.endsWith('jar') && !it.name.startsWith('openbeans-') && !it.name.startsWith('asm-') && !it.name.startsWith('antlr-') } +
                    modules()*.jar.archivePath +
                    modules().configurations.runtime*.findAll {
                        it.name.endsWith('jar') && !it.name.contains('livetribe-jsr223') && !it.name.matches(/groovy-\d.*/) &&
                                !it.name.startsWith('asm-') && !it.name.startsWith('antlr-') && !it.name.startsWith('openbeans-')
                    }.flatten() as Set
        }
        from('src/bin/groovy.icns')
    }
    into('indy') {
        from { new File(jar.archivePath.parent, "${jar.baseName}-${jar.version}-indy.jar") }
        from {
            modules()*.jar.collect { j ->
                new File(j.archivePath.parent, "${j.baseName}-${j.version}-indy.jar")
            }
        }
    }
    into('grooid') {
        from { new File(jar.archivePath.parent, "${jar.baseName}-${jar.version}-grooid.jar") }
        from {
            modules()*.jar.collect { j ->
                new File(j.archivePath.parent, "${j.baseName}-${j.version}-grooid.jar")
            }
        }
    }
    into('conf') {
        from 'src/conf'
    }
    into('bin') {
        from('src/bin') {
            filter(ReplaceTokens, tokens: [GROOVYJAR:jar.archiveName])
            fileMode = 0755
            exclude 'groovy.icns'
        }
        from('src/tools/org/codehaus/groovy/tools/groovy.ico')
    }
    into('licenses') {
        from 'licenses'
        include 'antlr2-license.txt'
        include 'asm-license.txt'
        include 'hamcrest-license.txt'
        include 'jline2-license.txt'
        include 'jsr166y-license.txt'
        include 'jsr223-license.txt'
        include 'junit-license.txt'
        include 'xstream-license.txt'
    }
    into('embeddable') {
        from jarAll.archivePath
        from { new File(jarAll.archivePath.parent, "${jarAll.baseName}-${jarAll.appendix}-${jarAll.version}-indy.jar") }
    }
}

task distBin(type: Zip, dependsOn: [jar, jarAllAll, replaceJarWithJarJar]) {
    baseName = 'apache-groovy'
    appendix = 'binary'
    into("groovy-$version") {
        with distSpec
    }
}

task distDoc(type: Zip, dependsOn: doc) {
    baseName = 'apache-groovy'
    appendix = 'docs'
    into("groovy-$version") {
        with docSpec
    }
}

task syncDoc(type: Copy, dependsOn: doc) {
    inputs.files javadoc.outputs.files
    inputs.files groovydoc.outputs.files

    destinationDir(file("$buildDir/html"))
    into('api') {
        from javadoc.destinationDir
    }
    into('gapi') {
        from groovydoc.destinationDir
    }
    // groovy-jdk already at the correct place
}

task distSrc(type: Zip) {
    baseName = 'apache-groovy'
    appendix = 'src'
    classifier = 'incubating'
    into("groovy-$version")
    with srcSpec
}

def installDir = {
    project.hasProperty('groovy_installPath')?project.groovy_installPath:
        System.properties.installDirectory ?: "$buildDir/install"
}

task installGroovy(type: Sync, dependsOn: distBin) {
    description 'Generates a groovy distribution into an install directory'
    doLast {
        logger.lifecycle "Groovy installed under ${installDir()}"
    }
    with distSpec
    into installDir
}

import org.gradle.api.file.DuplicatesStrategy

task dist(type: Zip, dependsOn: [distBin, distSrc, distDoc, syncDoc]) {
    description = 'Generates the binary, sources, documentation and full distributions'
    baseName = 'apache-groovy'
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    appendix 'sdk'
    into "groovy-$version"
    from("$projectDir/licenses/LICENSE-SDK")
    from("$projectDir/notices/NOTICE-SDK")
    rename { String filename -> filename == 'LICENSE-SDK' ? 'LICENSE' : filename == 'NOTICE-SDK' ? 'NOTICE' : filename }
    with distSpec
    into('doc') {
        with docSpec
    }
    into('src') {
        with srcSpec
    }

    if ((version.endsWith('SNAPSHOT') && !groovyBundleVersion.endsWith('SNAPSHOT'))
        || (!version.endsWith('SNAPSHOT') && groovyBundleVersion.endsWith('SNAPSHOT'))) {
        throw new GradleException("Incoherent versions. Found groovyVersion=$version and groovyBundleVersion=$groovyBundleVersion")
    }
}

task updateLicenses {
    description = 'Updates the various LICENSE files'
    ext.licensesDir = "${projectDir}/licenses"
    ext.licenseBaseFile = "${licensesDir}/LICENSE-BASE"

    ext.licenseSrcFile = "${projectDir}/LICENSE"
    ext.licenseDocGeneratorFile = "${projectDir}/subprojects/groovy-docgenerator/LICENSE"
    ext.licenseGroovyDocFile = "${projectDir}/subprojects/groovy-groovydoc/LICENSE"
    ext.licenseGroovyshFile = "${projectDir}/subprojects/groovy-groovysh/LICENSE"
    ext.licenseJsr223File = "${projectDir}/subprojects/groovy-jsr223/LICENSE"
    ext.licenseAllJarJarFile = "${licensesDir}/LICENSE-ALLJARJAR"
    ext.licenseBinZipFile = "${licensesDir}/LICENSE-BINZIP"
    ext.licenseDocFile = "${licensesDir}/LICENSE-DOC"
    ext.licenseJarJarFile = "${licensesDir}/LICENSE-JARJAR"
    ext.licenseSdkFile = "${licensesDir}/LICENSE-SDK"
    inputs.files(licenseBaseFile, fileTree(licensesDir).include('*.txt'))
    outputs.files(licenseAllJarJarFile, licenseBinZipFile, licenseDocFile, licenseJarJarFile, licenseSrcFile,
            licenseDocGeneratorFile, licenseGroovyDocFile, licenseGroovyshFile, licenseJsr223File, licenseSdkFile)

    doLast {
        def srcFiles = fileTree(licensesDir).include('*-SRC*.txt').sort { it.name }
        def docFiles = fileTree(licensesDir).include('*-DOC*.txt').sort { it.name }
        def jarjarFiles = fileTree(licensesDir).include('*-JARJAR*.txt').sort { it.name }
        def allJarjarFiles = fileTree(licensesDir) {
            include '*-JARJAR*.txt'
            include '*-ALLJARJAR*.txt'
        }.sort { it.name }
        def binzipFiles = fileTree(licensesDir) {
            include '*-JARJAR*.txt'
            include '*-ALLJARJAR*.txt'
            include '*-BINZIP*.txt'
        }.sort { it.name }
        def docgeneratorFiles = fileTree(licensesDir).include('normalize-stylesheet-groovy-docgenerator.txt')
        def groovydocFiles = fileTree(licensesDir).include('normalize-stylesheet-groovy-groovydoc.txt')
        def groovyshFiles = fileTree(licensesDir).include('jline2-patch-ALLJARJAR-SRC.txt')
        def jsr223Files = fileTree(licensesDir).include('jsr223-ALLJARJAR-SRC.txt')
        def licenseHdr = '\n\n------------------------------------------------------------------------\n\n'
        [
                (licenseAllJarJarFile)  : allJarjarFiles,
                (licenseBinZipFile)     : binzipFiles,
                (licenseDocFile)        : docFiles,
                (licenseJarJarFile)     : jarjarFiles,
                (licenseSrcFile)        : srcFiles,
                (licenseDocGeneratorFile): docgeneratorFiles,
                (licenseGroovyDocFile)   : groovydocFiles,
                (licenseGroovyshFile)    : groovyshFiles,
                (licenseJsr223File)      : jsr223Files,
        ].each { outFile, inFiles ->
            file(outFile).withWriter('utf-8') { writer ->
                writer << ([file(licenseBaseFile)] + inFiles).collect { it.text.replaceAll(/[\n\r]*$/, '') }.join(licenseHdr) + '\n'
            }
        }
        file(licenseSdkFile).withWriter { writer ->
            writer << [
                    file(licenseBinZipFile).text,
                    "This convenience zip embeds Groovy's src and doc zips.\nSee also src/LICENSE " +
                            "and doc/LICENSE files for additional license information."
            ].join(licenseHdr) + '\n'
        }
    }
}

task updateNotices {
    description = 'Updates the various NOTICE files'
    ext.noticesDir = "${projectDir}/notices"
    ext.noticeBaseFile = "${noticesDir}/NOTICE-BASE"

    ext.noticeSrcFile = "${projectDir}/NOTICE"
    ext.noticeGroovyConsoleFile = "${projectDir}/subprojects/groovy-console/NOTICE"
    ext.noticeAllJarJarFile = "${noticesDir}/NOTICE-ALLJARJAR"
    ext.noticeBinZipFile = "${noticesDir}/NOTICE-BINZIP"
    ext.noticeGrooidFile = "${noticesDir}/NOTICE-GROOID"
    ext.noticeGrooidJarJarFile = "${noticesDir}/NOTICE-GROOIDJARJAR"
    ext.noticeJarJarFile = "${noticesDir}/NOTICE-JARJAR"
    ext.noticeSdkFile = "${noticesDir}/NOTICE-SDK"
    inputs.files(noticeBaseFile, fileTree(noticesDir).include('*.txt'))
    outputs.files(noticeAllJarJarFile, noticeBinZipFile, noticeGrooidFile, noticeGrooidJarJarFile,
            noticeJarJarFile, noticeSrcFile, noticeGroovyConsoleFile, noticeSdkFile)

    doLast {
        def srcFiles = fileTree(noticesDir).include('*-SRC*.txt').sort { it.name }
        def grooidFiles = fileTree(noticesDir).include('*-GROOID*.txt').sort { it.name }
        def jarjarFiles = fileTree(noticesDir).include('*-JARJAR*.txt').sort { it.name }
        def grooidJarjarFiles = fileTree(noticesDir) {
            include '*-JARJAR*.txt'
            include '*-GROOID*.txt'
        }.sort { it.name }
        def allJarjarFiles = fileTree(noticesDir) {
            include '*-JARJAR*.txt'
            include '*-ALLJARJAR*.txt'
        }.sort { it.name }
        def binzipFiles = fileTree(noticesDir) {
            include '*-JARJAR*.txt'
            include '*-ALLJARJAR*.txt'
            include '*-GROOID*.txt'
            include '*-BINZIP*.txt'
        }.sort { it.name }
        def groovyconsoleFiles = fileTree(noticesDir).include('silkicons-ALLJARJAR-SRC.txt')
        [
                (noticeAllJarJarFile): allJarjarFiles,
                (noticeBinZipFile): binzipFiles,
                (noticeGrooidFile): grooidFiles,
                (noticeGrooidJarJarFile): grooidJarjarFiles,
                (noticeJarJarFile): jarjarFiles,
                (noticeSrcFile): srcFiles,
                (noticeGroovyConsoleFile): groovyconsoleFiles,
        ].each { outFile, inFiles ->
            file(outFile).withWriter('utf-8') { writer ->
                writer << ([file(noticeBaseFile)] + inFiles).collect {
                    it.text.replaceAll(/[\n\r]*$/, '')
                }.join('\n\n')
            }
        }
        file(noticeSdkFile).withWriter { writer ->
            writer << [
                    file(noticeBinZipFile).text,
                    "This convenience zip embeds Groovy's src and doc zips.\nSee also src/NOTICE " +
                            "and doc/NOTICE files for additional notice information."
            ].join('\n\n')
        }
    }
}
