/*
 * 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.
 */

// Following Gradle best practices to keep build logic organized
// ----------------------------------------------------------------------------
// Compiler configuration details

// We are using Java 17 (latest LTS) toolchain to compile.
// This enables decoupling from the Java version that gradle runs, from
// the actual JDK version for the project. For more details, see
// https://docs.gradle.org/current/userguide/toolchains.html
//
// The '--release' option added below makes sure that even if we are using
// the toolchain version > 11, the final artifact is at version 11. There is
// also a runtime CI that's based on Java 11 to ensure that.
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

tasks.withType(JavaCompile).configureEach {
    options.encoding = 'UTF-8'
    options.debug = true
    options.deprecation = true
    // the following is to build with Java 8 specifications, even when building with later JDK
    options.release = 8
    options.compilerArgs += [
            '-Werror',
            '-Xlint:deprecation',
            '-Xlint:cast',
            '-Xlint:empty',
            '-Xlint:fallthrough',
            '-Xlint:finally',
            '-Xlint:overrides',
            // we can't enable -Xlint:unchecked just yet
    ]
}

tasks.withType(Javadoc) {
    failOnError false
    options.addStringOption('Xdoclint:none', '-quiet')
    options.addStringOption('encoding', 'UTF-8')
    options.addStringOption('charSet', 'UTF-8')
}

// ----------------------------------------------------------------------------
// Jar packaging details
processResources {
    into('META-INF') {
        from "$thriftRoot/LICENSE"
        from "$thriftRoot/NOTICE"
        rename('(.+)', '$1.txt')
    }
}

jar {
    project.test.dependsOn it
    manifest {
        attributes([
            "Implementation-Version": "${project.version}",
            "Automatic-Module-Name": "${project.group}",
            "Bundle-ManifestVersion": "2",
            "Bundle-SymbolicName": "${project.group}",
            "Bundle-Name": "Apache Thrift",
            "Bundle-Version": "${project.version}",
            "Bundle-Description": "Apache Thrift library",
            "Bundle-License": "${project.license}",
            "Bundle-ActivationPolicy": "lazy",
            "Export-Package": "${project.group}.async;uses:=\"${project.group}.protocol,${project.group}.transport,org.slf4j,${project.group}\";version=\"${project.version}\",${project.group}.protocol;uses:=\"${project.group}.transport,${project.group},${project.group}.scheme\";version=\"${project.version}\",${project.group}.server;uses:=\"${project.group}.transport,${project.group}.protocol,${project.group},org.slf4j,javax.servlet,javax.servlet.http\";version=\"${project.version}\",${project.group}.transport;uses:=\"${project.group}.protocol,${project.group},org.apache.http.client,org.apache.http.params,org.apache.http.entity,org.apache.http.client.methods,org.apache.http,org.slf4j,javax.net.ssl,javax.net,javax.security.sasl,javax.security.auth.callback\";version=\"${project.version}\",${project.group};uses:=\"${project.group}.protocol,${project.group}.async,${project.group}.server,${project.group}.transport,org.slf4j,org.apache.log4j,${project.group}.scheme\";version=\"${project.version}\",${project.group}.meta_data;uses:=\"${project.group}\";version=\"${project.version}\",${project.group}.scheme;uses:=\"${project.group}.protocol,${project.group}\";version=\"${project.version}\",${project.group}.annotation;version=\"${project.version}\"",
            "Import-Package": "javax.net,javax.net.ssl,javax.security.auth.callback,javax.security.sasl,javax.servlet;resolution:=optional,javax.servlet.http;resolution:=optional,org.slf4j;resolution:=optional;version=\"[1.4,2)\",org.apache.http.client;resolution:=optional,org.apache.http.params;resolution:=optional,org.apache.http.entity;resolution:=optional,org.apache.http.client.methods;resolution:=optional,org.apache.http;resolution:=optional"
        ])
    }
}
