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

// This configures application of forbidden API rules
// via https://github.com/policeman-tools/forbidden-apis

def resources = scriptResources(buildscript)

// Only apply forbidden-apis to java projects.
allprojects { prj ->
  plugins.withId("java", {
    prj.apply plugin: libs.plugins.thetaphi.forbiddenapis.get().pluginId

    // This helper method appends signature files based on a set of true
    // dependencies from a given configuration.
    def dynamicSignatures = { configuration, suffix ->
      def resolvedMods = configuration.resolvedConfiguration.resolvedArtifacts
          .collect { a -> a.moduleVersion.id }
      def deps = resolvedMods
          .collect { id -> [
              "${id.group}.${id.name}.all.txt",
              "${id.group}.${id.name}.${suffix}.txt",
          ]}
          .flatten()
          .sort()

      deps += ["defaults.all.txt", "defaults.${suffix}.txt"]

      deps.each { sig ->
        def signaturesFile = file("${resources}/${sig}")
        if (signaturesFile.exists()) {
          logger.info("Signature file applied: ${sig}")
          signaturesFiles += files(signaturesFile)
        } else {
          logger.debug("Signature file omitted (does not exist): ${sig}")
        }
      }
      
      // commons-io is special: forbiddenapis has a versioned bundledSignature.
      bundledSignatures += resolvedMods
        .findAll { id -> id.group == 'commons-io' && id.name == 'commons-io' }
        .collect { id -> "${id.name}-unsafe-${id.version}" as String }
    }

    // Configure defaults for all sourceSets (main and test)
    forbiddenApis {
      bundledSignatures += [
          'jdk-unsafe',
          'jdk-deprecated',
          'jdk-non-portable',
          'jdk-reflection',
      ]

      suppressAnnotations += [
          "**.SuppressForbidden"
      ]

      ignoreSignaturesOfMissingClasses = true
    }

    // Configure defaults for sourceSets.main
    forbiddenApisMain {
      bundledSignatures += [
          'jdk-system-out'
      ]
    }

    // Configure defaults for sourceSets.test
    forbiddenApisTest {
      signaturesFiles = files(
          file("${resources}/defaults.tests.txt")
      )
    }

    // Configure defaults for sourceSets.tools (if present).
    tasks.matching { it.name == "forbiddenApisTools" }.all {
      bundledSignatures += [
          'jdk-unsafe',
          'jdk-deprecated',
          'jdk-non-portable',
          'jdk-reflection',
      ]

      suppressAnnotations += [
          "**.SuppressForbidden"
      ]

      doFirst dynamicSignatures.curry(configurations.toolsCompileClasspath, "lucene")
      inputs.dir(file(resources))
    }

    // Disable sysout signatures for these projects.
    if (prj.path in [
        ":solr:solr-ref-guide",
        ":solr:test-framework"
    ]) {
      forbiddenApisMain.bundledSignatures -= [
          'jdk-system-out'
      ]
    }

    // Configure solr-specific rules.
    if (prj.path.startsWith(":solr")) {
      forbiddenApisMain {
        doFirst dynamicSignatures.curry(configurations.compileClasspath, "solr")
        signaturesFiles += files(file("${resources}/java.solr.txt"))
      }

      forbiddenApisTest {
        doFirst dynamicSignatures.curry(configurations.testCompileClasspath, "solr")
      }
    }

    // Disable checks on JMH generated files.
    if (prj.path == ":solr:benchmark") {
      forbiddenApisMain.exclude("**/jmh_generated/**")
    }

    // We rely on resolved configurations to compute the relevant set of rule
    // files for forbiddenApis. Since we don't want to resolve these configurations until
    // the task is executed, we can't really use them as task inputs properly. This is a
    // chicken-and-egg problem.
    //
    // This is the simplest workaround possible: just point at all the rule files and indicate
    // them as inputs. This way if a rule is modified, checks will be reapplied.
    configure([forbiddenApisMain, forbiddenApisTest]) { task ->
      task.inputs.dir(file(resources))
    }
  })
}
