THRIFT-5581: use gradle 7 for java/kotlin (#2601)

* upgrade gradle version to 7.4
* migrate from `maven` plugin to `maven-publish` plugin as required for Gradle 7
* add guard to ktfmt, since it can't run with JDK 8

Co-authored-by: Christopher Tubbs <ctubbsii@apache.org>
diff --git a/lib/java/gradle/additionalArtifacts.gradle b/lib/java/gradle/additionalArtifacts.gradle
deleted file mode 100644
index 201469d..0000000
--- a/lib/java/gradle/additionalArtifacts.gradle
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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
-
-task sourcesJar(type: Jar, group: 'Build') {
-    description = 'Assembles a jar archive containing the main Java sources.'
-
-    classifier 'sources'
-    from sourceSets.main.allSource
-}
-
-task javadocJar(type: Jar, dependsOn: javadoc, group: 'Build') {
-    description = 'Assembles a jar archive containing the JavaDoc.'
-
-    classifier 'javadoc'
-    from javadoc.destinationDir
-}
-
-artifacts {
-    archives sourcesJar
-    archives javadocJar
-}
-
diff --git a/lib/java/gradle/codeQualityChecks.gradle b/lib/java/gradle/codeQualityChecks.gradle
index f633413..b8d13f9 100644
--- a/lib/java/gradle/codeQualityChecks.gradle
+++ b/lib/java/gradle/codeQualityChecks.gradle
@@ -39,8 +39,8 @@
 
 tasks.withType(Pmd) {
     reports {
-        html.enabled = true
-        xml.enabled = false
+        html.required = true
+        xml.required = false
     }
 }
 
diff --git a/lib/java/gradle/functionalTests.gradle b/lib/java/gradle/functionalTests.gradle
index e8a3e89..0c27078 100644
--- a/lib/java/gradle/functionalTests.gradle
+++ b/lib/java/gradle/functionalTests.gradle
@@ -67,7 +67,6 @@
     dependsOn 'generateRunnerScriptForClient', 'generateRunnerScriptForServer', 'generateRunnerScriptForNonblockingServer', 'generateRunnerScriptForTServletServer'
     archiveBaseName.set('functionalTest')
     destinationDirectory = file("$buildDir/functionalTestJar")
-    archiveClassifier.set(null)
     // We do not need a version number for this internal jar
     archiveVersion.set(null)
     // Bundle the complete set of unit test classes including generated code
diff --git a/lib/java/gradle/publishing.gradle b/lib/java/gradle/publishing.gradle
index 7be7de4..91f456a 100644
--- a/lib/java/gradle/publishing.gradle
+++ b/lib/java/gradle/publishing.gradle
@@ -27,7 +27,7 @@
     destinationDir = file(installPath)
 
     from jar
-    from configurations.compile
+    from configurations.implementation
 }
 
 task installJavadoc(type: Copy, group: 'Install', dependsOn: javadoc) {
@@ -38,84 +38,66 @@
     from javadoc.destinationDir
 }
 
-// This is not needed by Gradle builds but the remaining Ant builds seem to
-// need access to the generated test classes for Thrift unit tests so we
-// assist them to use it this way.
-task copyDependencies(type: Copy, group: 'Build') {
-    description = 'Copy runtime dependencies in a common location for other Ant based projects'
-    project.assemble.dependsOn it
-
-    destinationDir = file("$buildDir/deps")
-    from configurations.testRuntime
-    // exclude some very specific unit test dependencies
-    exclude '**/junit*.jar', '**/mockito*.jar', '**/hamcrest*.jar'
+java {
+    withJavadocJar()
+    withSourcesJar()
 }
 
-// ----------------------------------------------------------------------------
-// Allow this configuration to be shared between install and uploadArchives tasks
-def configurePom(pom) {
-    pom.project {
-        name 'Apache Thrift'
-        description 'Thrift is a software framework for scalable cross-language services development.'
-        packaging 'jar'
-        url 'http://thrift.apache.org'
-
-        scm {
-            url 'https://github.com/apache/thrift'
-            connection 'scm:git:https://github.com/apache/thrift.git'
-            developerConnection 'scm:git:git@github.com:apache/thrift.git'
-        }
-
-        licenses {
-            license {
-                name 'The Apache Software License, Version 2.0'
-                url "${project.license}"
-                distribution 'repo'
-            }
-        }
-
-        developers {
-            developer {
-                id 'dev'
-                name 'Apache Thrift Developers'
-                email 'dev@thrift.apache.org'
+publishing {
+    publications {
+        mavenJava(MavenPublication) {
+            artifactId = "libthrift"
+            // explicitly set 3 jars because calling "from components.java" will include shadow jar which isn't what we want
+            artifact jar
+            artifact sourcesJar
+            artifact javadocJar
+            pom {
+                name = 'Apache Thrift'
+                description = 'Thrift is a software framework for scalable cross-language services development.'
+                url = 'http://thrift.apache.org'
+                licenses {
+                    license {
+                        name = 'The Apache Software License, Version 2.0'
+                        url = "${project.license}"
+                        distribution = 'repo'
+                    }
+                }
+                developers {
+                    developer {
+                        id = 'dev'
+                        name = 'Apache Thrift Developers'
+                        email = 'dev@thrift.apache.org'
+                    }
+                }
+                scm {
+                    url = 'https://github.com/apache/thrift'
+                    connection = 'scm:git:https://github.com/apache/thrift.git'
+                    developerConnection = 'scm:git:git@github.com:apache/thrift.git'
+                }
             }
         }
     }
-
-    pom.whenConfigured {
-        // Fixup the scope for servlet-api to be 'provided' instead of 'compile'
-        dependencies.find { dep -> dep.groupId == 'javax.servlet' && dep.artifactId == 'javax.servlet-api' }.with {
-            if(it != null) {
-              // it.optional = true
-              it.scope = 'provided'
+    repositories {
+        maven {
+            url = mavenRepositoryUrl
+            if (project.hasProperty("mavenUser") && project.hasProperty("mavenPassword")) {
+                credentials {
+                    username = mavenUser
+                    password = mavenPassword
+                }
             }
         }
     }
 }
 
-install {
-    repositories.mavenInstaller {
-        configurePom(pom)
-    }
-}
-
-uploadArchives {
-    dependsOn test // make sure we run unit tests when publishing
-    repositories.mavenDeployer {
-        // signPom will silently do nothing when no signing information is provided
-        beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
-        repository(url: project.mavenRepositoryUrl) {
-            if (project.hasProperty('mavenUser') && project.hasProperty('mavenPassword')) {
-                authentication(userName: mavenUser, password: mavenPassword)
-            }
-        }
-        configurePom(pom)
-    }
-}
-
-// Signing configuration, optional, only when release and uploadArchives is activated
+// Signing configuration, optional, only when release and publish is activated
 signing {
-    required { !version.endsWith("SNAPSHOT") && gradle.taskGraph.hasTask("uploadArchives") }
-    sign configurations.archives
+    required { !version.endsWith("SNAPSHOT") && gradle.taskGraph.hasTask("publish") }
+    sign publishing.publications.mavenJava
+}
+
+javadoc {
+    if(JavaVersion.current().isJava9Compatible()) {
+        options.addBooleanOption('html5', true)
+    }
 }
diff --git a/lib/java/gradle/sourceConfiguration.gradle b/lib/java/gradle/sourceConfiguration.gradle
index 827e926..97ce1b9 100644
--- a/lib/java/gradle/sourceConfiguration.gradle
+++ b/lib/java/gradle/sourceConfiguration.gradle
@@ -70,7 +70,7 @@
             "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=\"${version}\",${project.group}.protocol;uses:=\"${project.group}.transport,${project.group},${project.group}.scheme\";version=\"${version}\",${project.group}.server;uses:=\"${project.group}.transport,${project.group}.protocol,${project.group},org.slf4j,javax.servlet,javax.servlet.http\";version=\"${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=\"${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=\"${version}\",${project.group}.meta_data;uses:=\"${project.group}\";version=\"${version}\",${project.group}.scheme;uses:=\"${project.group}.protocol,${project.group}\";version=\"${version}\",${project.group}.annotation;version=\"${version}\"",
+            "Export-Package": "${project.group}.async;uses:=\"${project.group}.protocol,${project.group}.transport,org.slf4j,${project.group}\";version=\"${archiveVersion}\",${project.group}.protocol;uses:=\"${project.group}.transport,${project.group},${project.group}.scheme\";version=\"${archiveVersion}\",${project.group}.server;uses:=\"${project.group}.transport,${project.group}.protocol,${project.group},org.slf4j,javax.servlet,javax.servlet.http\";version=\"${archiveVersion}\",${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=\"${archiveVersion}\",${project.group};uses:=\"${project.group}.protocol,${project.group}.async,${project.group}.server,${project.group}.transport,org.slf4j,org.apache.log4j,${project.group}.scheme\";version=\"${archiveVersion}\",${project.group}.meta_data;uses:=\"${project.group}\";version=\"${archiveVersion}\",${project.group}.scheme;uses:=\"${project.group}.protocol,${project.group}\";version=\"${archiveVersion}\",${project.group}.annotation;version=\"${archiveVersion}\"",
             "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"
         ])
     }
diff --git a/lib/java/gradle/unitTests.gradle b/lib/java/gradle/unitTests.gradle
index 0f09aa9..db9ad82 100644
--- a/lib/java/gradle/unitTests.gradle
+++ b/lib/java/gradle/unitTests.gradle
@@ -44,14 +44,14 @@
 task deprecatedEqualityTest(type: JavaExec, group: 'Verification') {
     description = 'Run the non-JUnit test suite '
     classpath = sourceSets.test.runtimeClasspath
-    main 'org.apache.thrift.test.EqualityTest'
+    mainClass.set('org.apache.thrift.test.EqualityTest')
     markTaskDone(it)
 }
 
 task deprecatedJavaBeansTest(type: JavaExec, group: 'Verification') {
     description = 'Run the non-JUnit test suite '
     classpath = sourceSets.test.runtimeClasspath
-    main 'org.apache.thrift.test.JavaBeansTest'
+    mainClass.set('org.apache.thrift.test.JavaBeansTest')
     markTaskDone(it)
 }