/*
 * 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 11 specifications, even when building with later JDK
    options.release = 11
    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"
        ])
    }
}
