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

apply from: "${rootDir}/${scriptDir}/standard-subproject-configuration.gradle"
apply from: "${rootDir}/${scriptDir}/warnings.gradle"

import org.apache.geode.gradle.plugins.DependencyConstraints

import java.nio.file.Paths

// This project aggressively reaches into many other projects and must wait for those configurations
// to be evaluated and resolved.  Evaluation depends on each of these subprojects.

// This list is used in a loop to defined the /lib copySpec
def dependentProjectNames = [
  ':geode-common',
  ':geode-connectors',
  ':geode-core',
  ':geode-cq',
  ':geode-gfsh',
  ':geode-log4j',
  ':geode-logging',
  ':geode-lucene',
  ':geode-memcached',
  ':geode-old-client-support',
  ':geode-protobuf',
  ':geode-protobuf-messages',
  ':geode-rebalancer',
  ':geode-redis',
  ':geode-serialization',
  ':geode-tcp-server',
  ':geode-wan'
]

// These other dependencies are explicitly referenced throughout other copySpec
def otherDependentProjectNames = [
  ':extensions:geode-modules',
  ':extensions:geode-modules-assembly',
  ':extensions:geode-modules-session',
  ':extensions:geode-modules-session',
  ':extensions:geode-modules-tomcat7',
  ':extensions:geode-modules-tomcat8',
  ':extensions:geode-modules-tomcat9',
  ':geode-experimental-driver',
  ':geode-management',
  ':geode-pulse',
  ':geode-web',
  ':geode-web-api',
  ':geode-web-management',
]

evaluationDependsOnChildren()
(dependentProjectNames + otherDependentProjectNames).each { neighborProjectName ->
  project.evaluationDependsOn(neighborProjectName)
}

apply plugin: 'distribution'
apply plugin: 'com.palantir.docker'
apply from: "${rootDir}/${scriptDir}/publish-common.gradle"


// This subproject's 'publication' is not a jar and should not be constrained to match versions
// in the geode-all-bom.
project.ext.set('constrainVersionInBom', false)

project.ext {artifactName = 'apache-geode'}

configurations {
  compositeTarget {
    setDescription("Composite builds wishing to consume this apache-geode@tgz artifact must specify \"targetConfiguration = 'compositeTarget'\" for correct composite task dependency detection.")
  }

  gfshDependencies

  // Configurations used to download and cache web application servers for session module testing
  webServerTomcat6
  webServerTomcat7
  webServerTomcat8
  webServerTomcat9
  webServerJetty

  geodeArchives {
    setDescription("An 'archives' configuration without the legacy publication implications")
  }

  javadocOnly {
    setDescription('Projects that must be included in the JavaDocs.')
    extendsFrom geodeArchives
  }
}

publishing {
  publications {
    maven(MavenPublication) {
      artifactId = artifactName
      artifact source: distTar, extension: 'tgz'
    }
  }
}

gradle.taskGraph.whenReady( { graph ->
  tasks.withType(AbstractArchiveTask).findAll {
    it.name.toLowerCase().contains("dist")
  }.each { archive ->
    archive.doLast {
      ant.checksum file:"${archive.archivePath}", algorithm:"sha-256", format: 'MD5SUM', fileext: '.sha256'
    }
  }
})

artifacts {
  compositeTarget distTar
}

//This "repository" only exists to download tomcat-6, because the zip for tomcat 6 is
//not in a maven repo. Later versions of tomcat are.
repositories {
  ivy {
    url 'https://archive.apache.org/'
    patternLayout {
      artifact '/dist/tomcat/tomcat-6/v6.0.37/bin/[organisation]-[module]-[revision].[ext]'
    }
  }
  // For gradle tooling dependencies
  maven {
    url 'https://repo.gradle.org/gradle/libs-releases'
  }
}

def webServersDir = "$buildDir/generated-resources/webservers"

sourceSets {
  distributedTest {
    resources {
      srcDirs webServersDir
    }
    output.dir(webServersDir, builtBy: 'downloadWebServers')
  }
}

task downloadWebServers(type:Copy) {
  from {configurations.findAll {it.name.startsWith("webServer")}}
  into webServersDir
}

dependencies {
  compile(platform(project(':boms:geode-all-bom')))
  gfshDependencies(platform(project(':boms:geode-all-bom')))

  dependentProjectNames.each {
    geodeArchives(project(it))
  }
  geodeArchives project(':geode-management')
  geodeArchives project(path: ':geode-web', configuration: 'war')
  geodeArchives project(path: ':geode-web-api', configuration: 'war')
  geodeArchives project(path: ':geode-web-management', configuration: 'war')

  javadocOnly project(':extensions:geode-modules')
  javadocOnly project(':extensions:geode-modules-session')
  javadocOnly project(':extensions:geode-modules-session')
  javadocOnly project(':extensions:geode-modules-tomcat7')
  javadocOnly project(':extensions:geode-modules-tomcat9')
  javadocOnly project(':extensions:geode-modules-tomcat8')
  javadocOnly project(':geode-experimental-driver')

  testImplementation(project(':geode-core'))
  testImplementation(project(':geode-gfsh'))
  testImplementation(project(':geode-junit')) {
    exclude module: 'geode-core'
  }
  testImplementation(project(':geode-log4j')) {
    exclude module: 'geode-core'
  }
  testRuntime(project(path: ':geode-old-versions', configuration: 'testOutput'))


  acceptanceTestRuntimeOnly(project(path: ':geode-old-versions', configuration: 'testOutput'))


  integrationTestImplementation(project(':geode-core'))
  integrationTestImplementation(project(':geode-gfsh'))
  integrationTestImplementation(project(':geode-log4j')) {
    exclude module: 'geode-core'
  }
  integrationTestImplementation(project(':geode-junit')) {
    exclude module: 'geode-core'
  }
  integrationTestImplementation(project(':geode-dunit')) {
    exclude module: 'geode-core'
  }
  integrationTestImplementation(project(':geode-pulse'))
  integrationTestImplementation(project(':geode-assembly:geode-assembly-test'))
  integrationTestImplementation(project(':geode-logging'))
  integrationTestImplementation('org.apache.httpcomponents:httpclient')
  integrationTestImplementation('org.springframework:spring-beans')
  integrationTestImplementation('org.springframework:spring-context')
  integrationTestImplementation('org.springframework:spring-web')
  integrationTestImplementation('org.springframework.security:spring-security-oauth2-core')
  integrationTestImplementation('org.springframework.security:spring-security-oauth2-client')
  integrationTestImplementation('org.springframework.security:spring-security-oauth2-jose')
  integrationTestImplementation('javax.annotation:javax.annotation-api')
  integrationTestImplementation('javax.servlet:javax.servlet-api')


  integrationTestRuntimeOnly('io.swagger:swagger-annotations')
  // these two modules are for testing only
  integrationTestRuntimeOnly('com.fasterxml.jackson.datatype:jackson-datatype-joda')
  integrationTestRuntimeOnly('joda-time:joda-time')


  distributedTestCompileOnly(platform(project(':boms:geode-all-bom')))
  distributedTestCompileOnly('io.swagger:swagger-annotations')
  distributedTestImplementation(project(':geode-gfsh'))
  distributedTestImplementation(project(':geode-logging'))
  distributedTestImplementation(project(':geode-membership'))
  distributedTestImplementation(project(':geode-serialization'))
  distributedTestImplementation(project(':geode-tcp-server'))
  distributedTestImplementation(project(':geode-core'))
  distributedTestImplementation(project(':geode-log4j')) {
    exclude module: 'geode-core'
  }
  distributedTestImplementation(project(':geode-dunit')){
    exclude module: 'geode-core'
  }
  distributedTestImplementation(project(':extensions:session-testing-war'))
  distributedTestImplementation(project(':geode-assembly:geode-assembly-test'))
  distributedTestImplementation('org.apache.httpcomponents:httpclient')
  distributedTestImplementation('org.springframework:spring-web')
  distributedTestImplementation(project(':geode-management'))
  distributedTestImplementation(project(':geode-web-management'))
  distributedTestImplementation('com.arakelian:java-jq')
  distributedTestImplementation('javax.servlet:javax.servlet-api')

  distributedTestRuntimeOnly(project(':extensions:geode-modules-session-internal')) {
    exclude group: 'org.apache.tomcat'
  }
  distributedTestRuntimeOnly('org.codehaus.cargo:cargo-core-uberjar')
  distributedTestRuntimeOnly('io.swagger:swagger-annotations')
  distributedTestRuntimeOnly(project(':geode-wan'))


  // geodeArchives is a direct reflection of what is contained in geode-dependencies.jar. To that
  // end only add _test_ dependencies to acceptanceTestCompile/Runtime. All other product
  // dependencies should be a part of geodeArchives and should not need to be added as individual
  // dependencies here.
  acceptanceTestImplementation(configurations.geodeArchives)
  acceptanceTestImplementation(project(':geode-dunit')) {
    exclude module: 'geode-core'
  }
  acceptanceTestImplementation(project(':geode-assembly:geode-assembly-test'))

  // This is used by 'gradle within gradle' tests. No need to bump this version; but if you do,
  // don't have it be the same version as the outer gradle version.
  acceptanceTestImplementation('org.gradle:gradle-tooling-api:5.1.1')

  acceptanceTestImplementation('org.testcontainers:testcontainers')

  uiTestImplementation(project(':geode-core'))
  uiTestImplementation(project(':geode-dunit')) {
    exclude module: 'geode-core'
  }
  uiTestImplementation(project(':geode-pulse'))
  uiTestImplementation(project(':geode-pulse:geode-pulse-test'))
  uiTestImplementation(project(':geode-assembly:geode-assembly-test'))
  uiTestImplementation('org.seleniumhq.selenium:selenium-api')
  uiTestImplementation('org.seleniumhq.selenium:selenium-remote-driver')
  uiTestImplementation('org.seleniumhq.selenium:selenium-support')

  uiTestRuntimeOnly(project(':geode-core'))
  uiTestRuntimeOnly('org.seleniumhq.selenium:selenium-chrome-driver')

  upgradeTestImplementation(project(':geode-gfsh'))
  upgradeTestImplementation(project(':geode-logging'))
  upgradeTestImplementation(project(':geode-serialization'))
  upgradeTestImplementation(project(':geode-core'))
  upgradeTestImplementation(project(':geode-dunit')) {
    exclude module: 'geode-core'
  }
  upgradeTestImplementation(project(':geode-assembly:geode-assembly-test'))

  upgradeTestCompileOnly(platform(project(':boms:geode-all-bom')))
  upgradeTestCompileOnly('io.swagger:swagger-annotations')
  upgradeTestRuntimeOnly(project(path: ':geode-old-versions', configuration: 'testOutput'))
  distributedTestRuntimeOnly(project(path: ':geode-old-versions', configuration: 'testOutput'))
  testImplementation('org.assertj:assertj-core')
  upgradeTestRuntimeOnly(project(':extensions:session-testing-war'))
  upgradeTestRuntimeOnly('org.codehaus.cargo:cargo-core-uberjar')
  upgradeTestRuntimeOnly('org.apache.httpcomponents:httpclient')
  upgradeTestRuntime files({ downloadWebServers } )

  //Web servers used for session module testing
  webServerTomcat6('apache:tomcat:' + DependencyConstraints.get('tomcat6.version') + '@zip')
  webServerTomcat7('org.apache.tomcat:tomcat:' + DependencyConstraints.get('tomcat7.version') + '@zip')
  webServerTomcat8('org.apache.tomcat:tomcat:' + DependencyConstraints.get('tomcat8.version') + '@zip')
  webServerTomcat9('org.apache.tomcat:tomcat:' + DependencyConstraints.get('tomcat9.version') + '@zip')
  webServerJetty('org.eclipse.jetty:jetty-distribution:' + DependencyConstraints.get('jetty.version') + '@zip')

  gfshDependencies ('org.springframework:spring-web') {
    exclude module: 'spring-core'
    exclude module: 'commons-logging'
  }
}

acceptanceTest {
    // This is specifically used by GradleBuildWithGeodeCoreAcceptanceTest
    systemProperty 'projectGroup', project.group
}

tasks.register('defaultDistributionConfig', JavaExec) {
  inputs.files {
    project(':geode-core').sourceSets.main.runtimeClasspath
  }
  outputs.file file("$buildDir/gemfire.properties")
  main 'org.apache.geode.distributed.internal.DefaultPropertiesGenerator'
  classpath project(':geode-core').sourceSets.main.runtimeClasspath
  workingDir buildDir

  doFirst {
    buildDir.mkdirs()
  }
}

tasks.register('defaultCacheConfig', JavaExec) {
  inputs.files {
    project(':geode-core').sourceSets.main.runtimeClasspath
  }
  outputs.file file("$buildDir/cache.xml")
  main 'org.apache.geode.internal.cache.xmlcache.CacheXmlGenerator'
  classpath project(':geode-core').sourceSets.main.runtimeClasspath
  workingDir buildDir

  doFirst {
    buildDir.mkdirs()
  }
}

// This closure sets the geode classpath.  If we add another jar to the classpath it must
// be included in the filter logic below.
def cp = {
  // first add all the dependent project jars
  def jars = configurations.geodeArchives.dependencies.collect { it.dependencyProject }
    .findAll { !(it.name.contains('geode-web') || it.name.contains('geode-pulse')) }
    .collect { it.jar.archiveName }

  // then add all the dependencies of the dependent jars
  def depJars = configurations.geodeArchives.dependencies.collect {
    it.dependencyProject.findAll {
      !(it.name.contains('geode-web') ||
        it.name.contains('geode-pulse'))
    }.collect {
      it.configurations.runtimeClasspath.collect { it.getName() }.findAll { !(
          it.contains('geode-all-bom') ||

            // exclude mx4j, once the deprecated code is deleted we can remove these entirely
            it.contains('commons-digester') ||
            it.contains('commons-modeler') ||
            it.contains('javax.mail-api') ||
            it.contains('mx4j') ||

            // misc jars, these should be removed from the lib dir
            it.contains('findbugs-annotations') ||
            it.contains('geode-dependencies') ||
            it.contains('geode-jca') ||
            it.contains('geode-web') ||
            it.contains('gfsh-dependencies') ||
            it.contains('ra.jar') ||

            // spring web deps that shouldn't be here either
            it.contains('spring-aop') ||
            it.contains('spring-beans') ||
            it.contains('spring-context') ||
            it.contains('spring-expression') ||
            it.contains('spring-web')
        )}
    }
  }.flatten()

  return jars.plus(depJars).unique().join(' ')
}

tasks.register('configureDepsJar') {
  inputs.files {
    configurations.geodeArchives
  }

  def output = project.buildDir.toPath().resolve('reports').resolve('deps_jar_cp.txt')
  outputs.file {
    output
  }
  doLast {
    output.write(cp())
  }
}

tasks.register('configureGfshDepsJar') {
  inputs.files {
    configurations.gfshDependencies
  }

  inputs.files {
    configureDepsJar
  }

  def output = project.buildDir.toPath().resolve('reports').resolve('gfsh_deps_jar_cp.txt')
  outputs.file {
    output
  }
  doLast {
    def classpath = configureDepsJar.outputs.files.singleFile.text + ' ' +
        configurations.gfshDependencies.collect { it.getName() }.findAll {
          !it.contains('geode-all-bom')
        }.flatten().unique().join(' ')
    output.write(classpath)
  }
}

// Configure the manifest contents in a separate always-running task to ensure correctness of
// these dependency jars
tasks.register('depsJar', Jar) {
  inputs.files {
    configureDepsJar
  }
  description 'Assembles the jar archive that defines the gemfire classpath.'
  archiveName 'geode-dependencies.jar'
  doFirst {
    manifest {
      attributes("Class-Path": configureDepsJar.outputs.files.singleFile.text)
    }
  }
}

tasks.register('gfshDepsJar', Jar) {
  inputs.files {
    configureGfshDepsJar
  }
  description 'Assembles the jar archive that defines the gfsh classpath.'
  archiveName 'gfsh-dependencies.jar'
  doFirst {
    manifest {
      attributes("Class-Path": configureGfshDepsJar.outputs.files.singleFile.text)
    }
  }
}

tasks.register('docs', Javadoc) {
  def docsDir = file("$buildDir/javadocs")
  options.addStringOption('Xdoclint:none', '-quiet')
  options.links("https://lucene.apache.org/core/6_4_1/core/")
  options.links("https://lucene.apache.org/core/6_4_1/queryparser/")
  options.links("https://docs.oracle.com/javase/8/docs/api/")
  options.encoding = 'UTF-8'
  title = "${productName} ${project.version}"
  destinationDir = docsDir

  configurations.getByName("javadocOnly").allDependencies.each() { proj ->
    proj.dependencyProject.tasks.withType(Javadoc).findAll { it.enabled }.each { javadocTask ->
      source += javadocTask.source
      classpath += javadocTask.classpath
      excludes += javadocTask.excludes
      includes += javadocTask.includes
    }
  }

  include 'org/apache/geode/**/'

  doLast {
    rootProject.subprojects.each { project ->
      copy {
        if (project.hasProperty('sourceSets')) {
          from project.sourceSets.main.resources.srcDirs
        }
        include 'javadoc-images/*'
        into docsDir
      }
    }
  }
}

distributions {
  src {
    baseName = 'apache-geode'
    contents {
      from rootProject.tasks.writeBuildInfo
      from (rootDir) {
        exclude 'KEYS'
        exclude '**/gradlew'
        exclude '**/gradlew.bat'
        exclude '**/gradle/wrapper/gradle-wrapper.jar'
        exclude '**/.gradle'
        exclude '**/.project'
        exclude '**/.classpath'
        exclude '**/.settings/**'
        exclude '**/build-eclipse/**'
        exclude '**/.idea/**'
        exclude '**/*.iml'
        exclude '**/*.ipr'
        exclude '**/*.iws'
        exclude '**/.travis.yml'
        exclude '**/tags'

        //These directories are generated on the jenkins server by gradle
        exclude 'caches'
        exclude 'daemon'
        exclude 'native'
        exclude 'wrapper'

        // These exclude the 'build' and 'out' artifact directories from Gradle and IntelliJ for each project
        exclude 'buildSrc/build'
        exclude 'buildSrc/out'
        rootProject.allprojects.each {
          def relPath = Paths.get(rootDir.getPath()).relativize(Paths.get(it.projectDir.getPath()))
          def relOut = relPath.resolve("out").toString()
          def relBuild = relPath.resolve("build").toString()
          exclude relOut
          exclude relBuild
        }
      }
    }
  }
  named('main') {
    baseName = 'apache-geode'
    contents {
      duplicatesStrategy 'exclude'
      exclude '*.asc'

      exclude '*.asc'
      exclude '*-sources.jar'
      exclude '*-javadoc.jar'

      from rootProject.file('README.md')

      from "${projectDir}/src/main/dist/"

      with copySpec {
        into('config')
        from {defaultCacheConfig}
        from {defaultDistributionConfig}
        from {
          (project(':geode-log4j').sourceSets.main.resources.files.find {
            it.name == 'log4j2.xml'
          })
        }
      }

      with copySpec {
        into('lib')
        from { dependentProjectNames.collect {
            [
              project(':'.concat(it)).configurations.runtimeClasspath,
              project(':'.concat(it)).configurations.archives.allArtifacts.files
            ]
          }.flatten()
        }

        from configurations.gfshDependencies

        //These tasks are included as closures (wrapped in {}) because gradle may evaluate
        //this CopySpec before it evaluates the geode-core build file.
        from {project(':geode-core').tasks.named('raJar')}
        from {project(':geode-core').tasks.named('jcaJar')}

        // dependency jars
        from tasks.named('depsJar')
        from tasks.named('gfshDepsJar')
      }

      with copySpec {
        into('tools/Extensions')

        from {project(':geode-web').configurations.archives.allArtifacts.files}
        from {project(':geode-web-api').configurations.archives.allArtifacts.files}
        from {project(':geode-web-management').configurations.archives.allArtifacts.files}

        exclude '*.jar'
      }

      with copySpec {
        into('tools/ClientProtocol')
        from {project(':geode-protobuf-messages').zip.outputs.files}
      }

      with copySpec {
        into('javadoc')
        from { docs }
      }

      with copySpec {
        into('tools/Pulse')
        from {project(':geode-pulse').configurations.archives.allArtifacts.files}
      }

      with copySpec {
        into('tools/Modules')

        from { project(':extensions:geode-modules-assembly').distTcServer }
        from { project(':extensions:geode-modules-assembly').distTcServer30 }
        from { project(':extensions:geode-modules-assembly').distTomcat }
        from { project(':extensions:geode-modules-assembly').distAppServer }
      }
    }
  }

}
// Distribution plugin does not allow configuring of the task, only the contents. So we set
// compression and classifier here
[tasks.named('distTar'),
 tasks.named('srcDistTar'),
]*.configure {
  compression Compression.GZIP
  extension 'tgz'
  build.dependsOn(it)
}
// Make build final task to generate all test and product resources
build.dependsOn(installDist)

tasks.named('srcDistTar').configure {
  classifier 'src'
}

[tasks.named('distZip'),
 tasks.named('srcDistZip'),
 tasks.named('dockerfileZip'),
 ]*.configure {
  enabled = false
}

tasks.withType(Test) {
  dependsOn installDist
  environment 'GEODE_HOME', "$buildDir/install/${distributions.main.baseName}"
}


acceptanceTest.dependsOn(rootProject.getTasksByName("publishToMavenLocal", true))
installDist.dependsOn ':extensions:geode-modules-assembly:dist'
distributedTest.dependsOn ':extensions:session-testing-war:war'
distributedTest.dependsOn ':geode-old-versions:build'
upgradeTest.dependsOn ':extensions:session-testing-war:war'
upgradeTest.dependsOn ':geode-old-versions:build'

/**Print the names of all jar files in a fileTree */
def printJars(tree) {
  tree.matching {include("**/*.jar")}.visit{ file ->
    if(!file.isDirectory()) {
      println file.name
    }
  }
}

task dumpInstalledJars(dependsOn: installDist) {
  doLast {
    description "Dump a list of all of the jars shipped with the binary distribution, for validation purposes"

    FileTree installDir = fileTree(dir: installDist.destinationDir)

    println("Jars in the binary install")
    println("==========================")
    printJars(installDir)

    installDir.include("**/*.war").visit{ file ->
      if(!file.isDirectory()) {
          FileTree warContents = zipTree(file.file)
          println ""
          println file.name
          println("==========================")
          printJars(warContents)
      }
    }
  }
}

docker {
  dependsOn(tasks.installDist)
  name geodeDockerImageName
  copySpec.from(tasks.installDist.outputs).into('geode')
}

acceptanceTest {
  dependsOn(tasks.docker)
}

apply from: Paths.get("${rootDir}", 'gradle', 'japicmp.gradle')
