buildscript {
	repositories {
		gradlePluginPortal()
		maven { url "https://repo.spring.io/plugins-release" }
	}
	dependencies {
		classpath("io.spring.gradle:propdeps-plugin:0.0.9.RELEASE")
		classpath("io.spring.gradle:docbook-reference-plugin:0.3.1")
		classpath("org.asciidoctor:asciidoctor-gradle-plugin:1.5.2")
		classpath("ws.antonov.gradle.plugins:gradle-plugin-protobuf:0.9.1")
	}
}

ext {
	linkHomepage = 'https://projects.spring.io/spring-framework'
	linkCi = 'https://build.spring.io/browse/SPR'
	linkIssue = 'https://jira.spring.io/browse/SPR'
	linkScmUrl = 'https://github.com/spring-projects/spring-framework'
	linkScmConnection = 'scm:git:git://github.com/spring-projects/spring-framework.git'
	linkScmDevConnection = 'scm:git:ssh://git@github.com:spring-projects/spring-framework.git'

	moduleProjects = subprojects.findAll {
		!it.name.equals('spring-build-src') && !it.name.equals('spring-framework-bom')
	}
}

configure(allprojects) { project ->
	group = "org.springframework"
	version = qualifyVersionIfNecessary(version)

	ext.aspectjVersion       = "1.8.9"
	ext.caffeineVersion      = "2.3.5"
	ext.eclipselinkVersion   = "2.4.2"
	ext.ehcacheVersion       = "2.10.4"
	ext.ehcachejcacheVersion = "1.0.1"
	ext.ehcache3Version      = "3.1.4"
	ext.ejbVersion           = "3.0"
	ext.fileuploadVersion    = "1.3.3"
	ext.freemarkerVersion    = "2.3.23"
	ext.groovyVersion        = "2.4.17"
	ext.gsonVersion          = "2.8.5"
	ext.guavaVersion         = "20.0"
	ext.hamcrestVersion      = "1.3"
	ext.hibernate3Version    = "3.6.10.Final"
	ext.hibernate4Version    = "4.3.11.Final"
	ext.hibernate5Version    = "5.2.10.Final"
	ext.hibval4Version       = "4.3.2.Final"
	ext.hibval5Version       = "5.2.5.Final"
	ext.hsqldbVersion        = "2.3.4"
	ext.httpasyncVersion     = "4.1.4"
	ext.httpclientVersion    = "4.5.6"
	ext.jackson2Version      = "2.8.11.3"
	ext.jasperreportsVersion = "6.2.1"  // our tests fail with JR-internal NPEs against 6.2.2 and higher
	ext.javamailVersion      = "1.5.6"
	ext.jettyVersion         = "9.3.14.v20161028"  // as of 9.3.15, Jetty has hard Servlet 3.1 requirement
	ext.jetty94Version       = "9.4.6.v20170531"  // for spring-websocket support, optimized for Jetty 9.4
	ext.jodaVersion          = "2.9.9"
	ext.jrubyVersion         = "1.7.27"  // JRuby 9000 primarily supported through JSR-223 (StandardScriptFactory)
	ext.jtaVersion           = "1.2"
	ext.junitVersion         = "4.12"
	ext.log4jVersion         = "1.2.17"
	ext.nettyVersion         = "4.1.39.Final"
	ext.okhttpVersion        = "2.7.5"
	ext.okhttp3Version       = "3.8.1"
	ext.openjpaVersion       = "2.4.2"
	ext.poiVersion           = "3.17"
	ext.reactorVersion       = "2.0.8.RELEASE"
	ext.romeVersion          = "1.7.4"
	ext.slf4jVersion         = "1.7.25"
	ext.snakeyamlVersion     = "1.17"
	ext.snifferVersion       = "1.18"
	ext.testngVersion        = "6.9.10"
	ext.tiles2Version        = "2.2.2"
	ext.tiles3Version        = "3.0.8"
	ext.tomcatVersion        = "8.5.45"
	ext.tyrusVersion         = "1.3.5"  // constrained by WebLogic 12.1.3 support
	ext.undertowVersion      = "1.3.33.Final"
	ext.xmlunitVersion       = "1.6"
	ext.xstreamVersion       = "1.4.9"

	ext.gradleScriptDir = "${rootProject.projectDir}/gradle"

	apply plugin: "propdeps"
	apply plugin: "java"
	apply plugin: "test-source-set-dependencies"
	apply from: "${gradleScriptDir}/ide.gradle"

	configurations {
		sniffer
		javaApiSignature
	}

	compileJava.options*.compilerArgs = [
		"-Xlint:serial", "-Xlint:varargs", "-Xlint:cast", "-Xlint:classfile",
		"-Xlint:dep-ann", "-Xlint:divzero", "-Xlint:empty", "-Xlint:finally",
		"-Xlint:overrides", "-Xlint:path", "-Xlint:processing", "-Xlint:static",
		"-Xlint:try", "-Xlint:fallthrough", "-Xlint:rawtypes", "-Xlint:deprecation",
		"-Xlint:unchecked", "-Xlint:-options", "-Werror"
	]

	compileTestJava.options*.compilerArgs = [
		"-Xlint:serial", "-Xlint:-varargs", "-Xlint:cast", "-Xlint:classfile",
		"-Xlint:dep-ann", "-Xlint:divzero", "-Xlint:empty", "-Xlint:finally",
		"-Xlint:overrides", "-Xlint:path", "-Xlint:processing", "-Xlint:static",
		"-Xlint:try", "-Xlint:-fallthrough", "-Xlint:-rawtypes", "-Xlint:-deprecation",
		"-Xlint:-unchecked", "-Xlint:-options"]

	compileJava {
		sourceCompatibility = 1.6
		targetCompatibility = 1.6
		options.encoding = 'UTF-8'
	}

	compileTestJava {
		sourceCompatibility = 1.8
		targetCompatibility = 1.8
		options.encoding = 'UTF-8'
		options.compilerArgs += "-parameters"
	}

	test {
		systemProperty("java.awt.headless", "true")
		systemProperty("testGroups", project.properties.get("testGroups"))
		scanForTestClasses = false
		include(["**/*Tests.class", "**/*Test.class"])
		// Since we set scanForTestClasses to false, we need to filter out inner
		// classes with the "$" pattern; otherwise, using -Dtest.single=MyTests to
		// run MyTests by itself will fail if MyTests contains any inner classes.
		exclude(["**/Abstract*.class", '**/*$*'])
	}

	repositories {
		mavenCentral()
		maven { url "https://repo.spring.io/libs-spring-framework-build" }
	}

	dependencies {
		testCompile("junit:junit:${junitVersion}") {
			exclude group:'org.hamcrest', module:'hamcrest-core'
		}
		testCompile("org.mockito:mockito-core:1.10.19") {
			exclude group:'org.hamcrest', module:'hamcrest-core'
		}
		testCompile("org.hamcrest:hamcrest-all:${hamcrestVersion}")

		sniffer("org.codehaus.mojo:animal-sniffer-ant-tasks:${snifferVersion}")
		javaApiSignature("org.codehaus.mojo.signature:java16:1.1@signature")  // API level from JDK 6 update 18
	}

	task copyJavaApiSignature(type: Copy) {
		ext.to = file("$buildDir/javaApiSignature/")
		description "Copy the resolved Animal Sniffer signature dependency artifact to a known location and name"
		from configurations.javaApiSignature
		into to
		rename '.*signature', 'javaApi.signature'
	}

	task sniff {
		group = "Verification"
		description = "Checks the Java API signatures"

		dependsOn compileJava
		dependsOn copyJavaApiSignature

		inputs.dir sourceSets.main.output.classesDir
		inputs.dir copyJavaApiSignature.to

		doLast {
			ant.taskdef(
				name: 'animalSniffer',
				classname: 'org.codehaus.mojo.animal_sniffer.ant.CheckSignatureTask',
				classpath: configurations.sniffer.asPath
			)

			ant.animalSniffer(
					signature: "$buildDir/javaApiSignature/javaApi.signature",
					classpath: sourceSets.main.compileClasspath.asPath) {
				path(path: sourceSets.main.output.classesDir)
				annotation(className: "org.springframework.lang.UsesJava7")
				annotation(className: "org.springframework.lang.UsesJava8")
				annotation(className: "org.springframework.lang.UsesSunHttpServer")
			}
		}
	}

	ext.javadocLinks = [
		"https://docs.oracle.com/javase/8/docs/api/",
		"https://docs.oracle.com/javaee/7/api/",
		"https://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/",  // CommonJ
		"https://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/",
		"https://glassfish.java.net/nonav/docs/v3/api/",
		"https://docs.jboss.org/jbossas/javadoc/4.0.5/connector/",
		"https://docs.jboss.org/jbossas/javadoc/7.1.2.Final/",
		"https://commons.apache.org/proper/commons-lang/javadocs/api-2.5/",
		"https://commons.apache.org/proper/commons-codec/apidocs/",
		"https://commons.apache.org/proper/commons-dbcp/apidocs/",
		"https://portals.apache.org/pluto/portlet-2.0-apidocs/",
		"https://tiles.apache.org/tiles-request/apidocs/",
		"https://tiles.apache.org/framework/apidocs/",
		"https://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
		"https://www.ehcache.org/apidocs/${ehcacheVersion}/",
		"https://www.ehcache.org/apidocs/${ehcache3Version}/",
		"https://www.quartz-scheduler.org/api/2.2.3/",
		"https://fasterxml.github.io/jackson-core/javadoc/2.8/",
		"https://fasterxml.github.io/jackson-databind/javadoc/2.8/",
		"https://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.8/",
		"https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/",
		"https://junit.org/junit4/javadoc/${junitVersion}/"
	] as String[]
}

configure(subprojects - project(":spring-build-src")) { subproject ->
	apply plugin: "merge"
	apply from: "${gradleScriptDir}/publish-maven.gradle"

	configurations {
		jacoco
	}
	dependencies {
		jacoco("org.jacoco:org.jacoco.agent:0.7.5.201505241946:runtime")
	}

	jar {
		manifest.attributes["Created-By"] =
			"${System.getProperty("java.version")} (${System.getProperty("java.specification.vendor")})"
		manifest.attributes["Implementation-Title"] = subproject.name
		manifest.attributes["Implementation-Version"] = subproject.version

		from("${rootProject.projectDir}/src/dist") {
			include "license.txt"
			include "notice.txt"
			into "META-INF"
			expand(copyright: new Date().format("yyyy"), version: project.version)
		}
	}

	javadoc {
		description = "Generates project-level javadoc for use in -javadoc jar"

		options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
		options.author = true
		options.header = project.name
		options.links(project.ext.javadocLinks)
		options.addStringOption('Xdoclint:none', '-quiet')

		// Suppress warnings due to cross-module @see and @link references.
		// Note that global 'api' task does display all warnings.
		logging.captureStandardError LogLevel.INFO
		logging.captureStandardOutput LogLevel.INFO  // suppress "## warnings" message
	}

	task sourcesJar(type: Jar, dependsOn: classes) {
		classifier = 'sources'
		from sourceSets.main.allSource
		// Don't include or exclude anything explicitly by default. See SPR-12085.
	}

	task javadocJar(type: Jar) {
		classifier = "javadoc"
		from javadoc
	}

	artifacts {
		archives sourcesJar
		archives javadocJar
	}
}

project("spring-build-src") {
	description = "Exposes gradle buildSrc for IDE support"

	apply plugin: "groovy"

	dependencies {
		compile gradleApi()
		compile localGroovy()
	}

	configurations.archives.artifacts.clear()
}

project("spring-core") {
	description = "Spring Core"

	// spring-core includes asm and repackages cglib, inlining both into the spring-core jar.
	// cglib itself depends on asm and is therefore further transformed by the JarJar task to
	// depend on org.springframework.asm; this avoids including two different copies of asm.
	def cglibVersion = "3.2.6"
	def objenesisVersion = "2.6"

	configurations {
		jarjar
		cglib
		objenesis
	}

	task cglibRepackJar(type: Jar) { repackJar ->
		repackJar.baseName = "spring-cglib-repack"
		repackJar.version = cglibVersion

		doLast() {
			project.ant {
				taskdef name: "jarjar", classname: "com.tonicsystems.jarjar.JarJarTask",
					classpath: configurations.jarjar.asPath
				jarjar(destfile: repackJar.archivePath) {
					configurations.cglib.each { originalJar ->
						zipfileset(src: originalJar)
					}
					// Repackage net.sf.cglib => org.springframework.cglib
					rule(pattern: "net.sf.cglib.**", result: "org.springframework.cglib.@1")
					// As mentioned above, transform cglib's internal asm dependencies from
					// org.objectweb.asm => org.springframework.asm. Doing this counts on the
					// the fact that Spring and cglib depend on the same version of asm!
					rule(pattern: "org.objectweb.asm.**", result: "org.springframework.asm.@1")
				}
			}
		}
	}

	task objenesisRepackJar(type: Jar) { repackJar ->
		repackJar.baseName = "spring-objenesis-repack"
		repackJar.version = objenesisVersion

		doLast() {
			project.ant {
				taskdef name: "jarjar", classname: "com.tonicsystems.jarjar.JarJarTask",
					classpath: configurations.jarjar.asPath
				jarjar(destfile: repackJar.archivePath) {
					configurations.objenesis.each { originalJar ->
						zipfileset(src: originalJar)
					}
					// Repackage org.objenesis => org.springframework.objenesis
					rule(pattern: "org.objenesis.**", result: "org.springframework.objenesis.@1")
				}
			}
		}
	}

	dependencies {
		cglib("cglib:cglib:${cglibVersion}@jar")
		objenesis("org.objenesis:objenesis:${objenesisVersion}@jar")
		jarjar("com.googlecode.jarjar:jarjar:1.3")

		compile(files(cglibRepackJar))
		compile(files(objenesisRepackJar))
		compile("commons-logging:commons-logging:1.2")
		optional("commons-codec:commons-codec:1.10")
		optional("org.aspectj:aspectjweaver:${aspectjVersion}")
		optional("net.sf.jopt-simple:jopt-simple:5.0.3")
		optional("log4j:log4j:${log4jVersion}")
		testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
		testCompile("xmlunit:xmlunit:${xmlunitVersion}")
		testCompile("com.fasterxml.woodstox:woodstox-core:5.0.3") {
			exclude group: "stax", module: "stax-api"
		}
	}

	jar {
		// Inline repackaged cglib classes directly into spring-core jar
		dependsOn cglibRepackJar
		from(zipTree(cglibRepackJar.archivePath)) {
			include "org/springframework/cglib/**"
		}

		dependsOn objenesisRepackJar
		from(zipTree(objenesisRepackJar.archivePath)) {
			include "org/springframework/objenesis/**"
		}
	}
}

project("spring-beans") {
	description = "Spring Beans"

	dependencies {
		compile(project(":spring-core"))
		compile(files(project(":spring-core").cglibRepackJar))
		optional("javax.inject:javax.inject:1")
		optional("javax.el:javax.el-api:2.2.5")
		optional("org.yaml:snakeyaml:${snakeyamlVersion}")
		testCompile("log4j:log4j:${log4jVersion}")
		testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
	}
}

project("spring-beans-groovy") {
	description "Groovy Bean Definitions"

	merge.into = project(":spring-beans")
	apply plugin: "groovy"

	dependencies {
		compile(project(":spring-core"))
		optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
	}

	// This module's Java and Groovy sources need to be compiled together.
	compileJava.enabled = false
	sourceSets {
		main {
			groovy {
				srcDir "src/main/java"
			}
		}
	}

	compileGroovy {
		sourceCompatibility = 1.6
		targetCompatibility = 1.6
	}
}

project("spring-aop") {
	description = "Spring AOP"

	dependencies {
		compile(project(":spring-beans"))
		compile(project(":spring-core"))
		compile(files(project(":spring-core").cglibRepackJar))
		compile(files(project(":spring-core").objenesisRepackJar))
		optional("org.aspectj:aspectjweaver:${aspectjVersion}")
		optional("commons-pool:commons-pool:1.6")
		optional("org.apache.commons:commons-pool2:2.4.2")
		optional("com.jamonapi:jamon:2.81")
	}
}

project("spring-expression") {
	description = "Spring Expression Language (SpEL)"

	dependencies {
		compile(project(":spring-core"))
	}
}

project("spring-instrument") {
	description = "Spring Instrument"

	jar {
		manifest.attributes["Premain-Class"] =
			"org.springframework.instrument.InstrumentationSavingAgent"
		manifest.attributes["Agent-Class"] =
			"org.springframework.instrument.InstrumentationSavingAgent"
		manifest.attributes["Can-Redefine-Classes"] = "true"
		manifest.attributes["Can-Retransform-Classes"] = "true"
		manifest.attributes["Can-Set-Native-Method-Prefix"] = "false"
	}
}

project("spring-instrument-tomcat") {
	description = "Spring Instrument Tomcat"

	dependencies {
		provided("org.apache.tomcat:catalina:6.0.16")
	}

	jar {
		exclude("org/apache/**")  // exclude the mock used to bridge between pre-7.0.63 and 7.0.63+
	}
}

project("spring-context") {
	description = "Spring Context"

	apply plugin: "groovy"

	dependencies {
		compile(project(":spring-aop"))
		compile(project(":spring-beans"))
		compile(project(":spring-core"))
		compile(project(":spring-expression"))
		compile(files(project(":spring-core").cglibRepackJar))
		optional(project(":spring-instrument"))
		optional("javax.inject:javax.inject:1")
		optional("javax.ejb:ejb-api:${ejbVersion}")
		optional("javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0")
		optional("javax.money:money-api:1.0.1")
		optional("org.eclipse.persistence:javax.persistence:2.0.0")
		optional("javax.validation:validation-api:1.0.0.GA")
		optional("org.hibernate:hibernate-validator:${hibval4Version}")
		optional("joda-time:joda-time:${jodaVersion}")
		optional("org.aspectj:aspectjweaver:${aspectjVersion}")
		optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
		optional("org.beanshell:bsh:2.0b5")
		optional("org.jruby:jruby:${jrubyVersion}")
		testCompile("javax.inject:javax.inject-tck:1")
		testCompile("org.javamoney:moneta:1.1")
		testCompile("commons-dbcp:commons-dbcp:1.4")
		testCompile("org.apache.commons:commons-pool2:2.4.2")
		testCompile("org.slf4j:slf4j-api:${slf4jVersion}")
	}
}

project("spring-oxm") {
	description = "Spring Object/XML Marshalling"
	apply from: "oxm.gradle"

	dependencies {
		compile(project(":spring-beans"))
		compile(project(":spring-core"))
		optional("org.codehaus.castor:castor-xml:1.4.1")  {
			exclude group: 'stax', module: 'stax-api'
			exclude group: "org.springframework", module: "spring-context"
		}
		optional("org.apache.xmlbeans:xmlbeans:2.6.0") {
			exclude group: 'stax', module: 'stax-api'
		}
		optional("com.thoughtworks.xstream:xstream:${xstreamVersion}") {
			exclude group: 'xpp3', module: 'xpp3_min'
			exclude group: 'xmlpull', module: 'xmlpull'
		}
		optional("org.jibx:jibx-run:1.2.6")
		testCompile(project(":spring-context"))
		testCompile("org.ogce:xpp3:1.1.6")
		testCompile("org.codehaus.jettison:jettison:1.3.8") {
			exclude group: 'stax', module: 'stax-api'
		}
		testCompile("xmlunit:xmlunit:${xmlunitVersion}")
		testCompile(files(genCastor.classesDir).builtBy(genCastor))
		testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
		testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans))
	}
}

project("spring-messaging") {
	description = "Spring Messaging"

	dependencies {
		compile(project(":spring-beans"))
		compile(project(":spring-context"))
		compile(project(":spring-core"))
		optional(project(":spring-oxm"))
		optional("io.projectreactor:reactor-core:${reactorVersion}")
		optional("io.projectreactor:reactor-net:${reactorVersion}") {
			exclude group: "io.netty", module: "netty-all"
		}
		optional("io.netty:netty-all:${nettyVersion}")
		optional("org.eclipse.jetty.websocket:websocket-server:${jettyVersion}") {
			exclude group: "javax.servlet", module: "javax.servlet-api"
		}
		optional("org.eclipse.jetty.websocket:websocket-client:${jettyVersion}")
		optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
		testCompile("javax.inject:javax.inject-tck:1")
		testCompile("javax.servlet:javax.servlet-api:3.1.0")
		testCompile("javax.validation:validation-api:1.0.0.GA")
		testCompile("com.thoughtworks.xstream:xstream:${xstreamVersion}")
		testCompile("org.apache.activemq:activemq-broker:5.8.0")
		testCompile("org.apache.activemq:activemq-kahadb-store:5.8.0") {
			exclude group: "org.springframework", module: "spring-context"
		}
		testCompile("org.apache.activemq:activemq-stomp:5.8.0")
		testCompile("org.eclipse.jetty:jetty-webapp:${jettyVersion}") {
			exclude group: "javax.servlet", module: "javax.servlet-api"
		}
		testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
		testCompile("org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}")
		testCompile("io.netty:netty-all:${nettyVersion}")
		testCompile("commons-dbcp:commons-dbcp:1.4")
		testCompile("log4j:log4j:${log4jVersion}")
		testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
		testCompile("xmlunit:xmlunit:${xmlunitVersion}")
	}
}

project("spring-tx") {
	description = "Spring Transaction"

	dependencies {
		compile(project(":spring-beans"))
		compile(project(":spring-core"))
		optional(project(":spring-aop"))
		optional(project(":spring-context"))  // for JCA, @EnableTransactionManagement
		optional("javax.transaction:javax.transaction-api:${jtaVersion}")
		optional("javax.resource:connector-api:1.5")
		optional("javax.ejb:ejb-api:${ejbVersion}")
		optional("com.ibm.websphere:uow:6.0.2.17")
		testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
		testCompile("org.eclipse.persistence:javax.persistence:2.0.0")
		testCompile("org.codehaus.groovy:groovy-all:${groovyVersion}")
	}
}

project("spring-jms") {
	description = "Spring JMS"

	dependencies {
		compile(project(":spring-aop"))
		compile(project(":spring-beans"))
		compile(project(":spring-context"))
		compile(project(":spring-core"))
		compile(project(":spring-messaging"))
		compile(project(":spring-tx"))
		provided("javax.jms:jms-api:1.1-rev-1")
		optional(project(":spring-oxm"))
		optional("javax.transaction:javax.transaction-api:${jtaVersion}")
		optional("javax.resource:connector-api:1.5")
		optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
	}
}

project("spring-jdbc") {
	description = "Spring JDBC"

	dependencies {
		compile(project(":spring-beans"))
		compile(project(":spring-core"))
		compile(project(":spring-tx"))
		optional(project(":spring-context"))  // for JndiDataSourceLookup
		optional("javax.transaction:javax.transaction-api:${jtaVersion}")
		optional("com.mchange:c3p0:0.9.5.2")
		optional("org.hsqldb:hsqldb:${hsqldbVersion}")
		optional("com.h2database:h2:1.4.193")
		optional("org.apache.derby:derby:10.13.1.1")
		optional("org.apache.derby:derbyclient:10.13.1.1")
	}
}

project("spring-context-support") {
	description = "Spring Context Support"

	dependencies {
		compile(project(":spring-beans"))
		compile(project(":spring-context"))
		compile(project(":spring-core"))
		optional(project(":spring-jdbc"))  // for Quartz support
		optional(project(":spring-tx"))  // for Quartz support
		optional("javax.mail:javax.mail-api:${javamailVersion}")
		optional("javax.cache:cache-api:1.0.0")
		optional("com.google.guava:guava:${guavaVersion}")
		optional("com.github.ben-manes.caffeine:caffeine:${caffeineVersion}")
		optional("net.sf.ehcache:ehcache:${ehcacheVersion}")
		optional("org.quartz-scheduler:quartz:2.2.3")
		optional("org.codehaus.fabric3.api:commonj:1.1.0")
		optional("org.apache.velocity:velocity:1.7")
		optional("org.freemarker:freemarker:${freemarkerVersion}")
		optional("com.lowagie:itext:2.1.7")
		optional("net.sf.jasperreports:jasperreports:$jasperreportsVersion") {
			exclude group: "com.fasterxml.jackson.core", module: "jackson-annotations"
			exclude group: "com.fasterxml.jackson.core", module: "jackson-core"
			exclude group: "com.fasterxml.jackson.core", module: "jackson-databind"
			exclude group: "org.olap4j", module: "olap4j"
			exclude group: "xml-apis", module: "xml-apis"
			exclude group: "org.springframework", module: "spring-context"
		}
		testCompile(project(":spring-context"))
		testCompile("org.apache.poi:poi:${poiVersion}")
		testCompile("commons-beanutils:commons-beanutils:1.8.0")  // for Velocity/JasperReports
		testCompile("commons-digester:commons-digester:1.8.1")  // for Velocity/JasperReports
		testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
		testCompile("org.slf4j:slf4j-api:${slf4jVersion}")
		testRuntime("com.sun.mail:javax.mail:${javamailVersion}")
		testRuntime("org.ehcache:jcache:${ehcachejcacheVersion}")
		testRuntime("org.ehcache:ehcache:${ehcache3Version}")
		testRuntime("org.terracotta:management-model:2.3.0")
	}
}

project("spring-web") {
	description = "Spring Web"

	apply plugin: "groovy"

	// Re-generate Protobuf classes from *.proto files and move them in test sources
	if (project.hasProperty('genProtobuf')) {
		apply plugin: 'protobuf'

		task updateGenProtobuf(type:Copy, dependsOn: ":spring-web:generateTestProto") {
			from "${project.buildDir}/generated-sources/test/"
			into "${projectDir}/src/test/java"
			doLast {
				project.delete "${project.buildDir}/generated-sources/test"
			}
		}

		tasks.getByPath("compileTestJava").dependsOn "updateGenProtobuf"
	}

	dependencies {
		compile(project(":spring-aop"))  // for JaxWsPortProxyFactoryBean
		compile(project(":spring-beans"))  // for MultipartFilter
		compile(project(":spring-context"))
		compile(project(":spring-core"))
		provided("javax.servlet:javax.servlet-api:3.0.1")
		optional(project(":spring-oxm"))  // for MarshallingHttpMessageConverter
		optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
		optional("javax.portlet:portlet-api:2.0")
		optional("javax.el:javax.el-api:2.2.5")
		optional("javax.faces:javax.faces-api:2.2")
		optional("javax.validation:validation-api:1.0.0.GA")
		optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
		optional("com.caucho:hessian:4.0.38")
		optional("commons-fileupload:commons-fileupload:${fileuploadVersion}")
		optional("org.apache.httpcomponents:httpclient:${httpclientVersion}")
		optional("org.apache.httpcomponents:httpasyncclient:${httpasyncVersion}")
		optional("io.netty:netty-all:${nettyVersion}")
		optional("com.squareup.okhttp:okhttp:${okhttpVersion}")
		optional("com.squareup.okhttp3:okhttp:${okhttp3Version}")
		optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
		optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.8.11")
		optional("com.google.code.gson:gson:${gsonVersion}")
		optional("com.rometools:rome:${romeVersion}")
		optional("org.eclipse.jetty:jetty-servlet:${jettyVersion}") {
			exclude group: "javax.servlet", module: "javax.servlet-api"
		}
		optional("org.eclipse.jetty:jetty-server:${jettyVersion}") {
			exclude group: "javax.servlet", module: "javax.servlet-api"
		}
		optional("log4j:log4j:${log4jVersion}")
		optional("com.google.protobuf:protobuf-java:2.6.1")
		optional("com.googlecode.protobuf-java-format:protobuf-java-format:1.4")
		optional("javax.mail:javax.mail-api:${javamailVersion}")
		testCompile(project(":spring-context-support"))  // for JafMediaTypeFactory
		testCompile("xmlunit:xmlunit:${xmlunitVersion}")
		testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
		testCompile("org.skyscreamer:jsonassert:1.4.0")
		testCompile("org.apache.taglibs:taglibs-standard-jstlel:1.2.1") {
			exclude group: "org.apache.taglibs", module: "taglibs-standard-spec"
		}
		testCompile("com.fasterxml.jackson.datatype:jackson-datatype-joda:2.8.11")
		testCompile("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.8.11")
		testCompile("com.fasterxml.jackson.module:jackson-module-kotlin:2.8.11.1")
		testCompile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.11")
    	testCompile("com.squareup.okhttp3:mockwebserver:${okhttp3Version}")
		testRuntime("com.sun.mail:javax.mail:${javamailVersion}")
	}
}

project("spring-orm") {
	description = "Spring Object/Relational Mapping"

	dependencies {
		compile(project(":spring-beans"))
		compile(project(":spring-core"))
		compile(project(":spring-jdbc"))
		compile(project(":spring-tx"))
		optional(project(":spring-aop"))
		optional(project(":spring-context"))
		optional(project(":spring-web"))
		optional("org.eclipse.persistence:javax.persistence:2.0.5")
		optional("org.eclipse.persistence:org.eclipse.persistence.core:${eclipselinkVersion}")
		optional("org.eclipse.persistence:org.eclipse.persistence.jpa:${eclipselinkVersion}") {
			exclude group: 'org.eclipse.persistence', module: 'javax.persistence'
		}
		optional("org.hibernate:hibernate-core:${hibernate3Version}") {
			exclude group: 'org.hibernate.javax.persistence', module: 'hibernate-jpa-2.0-api'
			exclude group: 'javax.transaction', module: 'jta'
		}
		optional("org.hibernate:hibernate-entitymanager:${hibernate3Version}") {
			exclude group: 'org.hibernate.javax.persistence', module: 'hibernate-jpa-2.0-api'
		}
		optional("org.apache.openjpa:openjpa:${openjpaVersion}") {
			exclude group: 'junit', module: 'junit'
			exclude group: 'org.apache.geronimo.specs', module: 'geronimo-jpa_2.0_spec'
			exclude group: 'org.apache.geronimo.specs', module: 'geronimo-jta_1.1_spec'
			exclude group: 'org.apache.geronimo.specs', module: 'geronimo-jms_1.1_spec'
		}
		optional("javax.jdo:jdo-api:3.1") {
			exclude group: 'javax.transaction', module: 'transaction-api'
		}
		optional("javax.servlet:javax.servlet-api:3.0.1")
		testCompile("commons-dbcp:commons-dbcp:1.4")
		testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
		testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
		testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
	}
}

project("spring-orm-hibernate4") {
	description = "Spring Object/Relational Mapping - Hibernate 4 support"
	merge.into = project(":spring-orm")

	dependencies {
		provided(project(":spring-jdbc"))
		provided(project(":spring-tx"))
		optional(project(":spring-web"))
		optional("org.hibernate:hibernate-core:${hibernate4Version}")
		optional("org.hibernate:hibernate-entitymanager:${hibernate4Version}")
		optional("javax.servlet:javax.servlet-api:3.0.1")
		testCompile("javax.validation:validation-api:1.1.0.GA")
		testCompile("org.hibernate:hibernate-validator:${hibval5Version}")
		testCompile("javax.el:javax.el-api:2.2.5")
		testCompile("org.glassfish.web:javax.el:2.2.6")
	}
}

project("spring-orm-hibernate5") {
	description = "Spring Object/Relational Mapping - Hibernate 5 support"
	merge.into = project(":spring-orm")

	dependencies {
		provided(project(":spring-jdbc"))
		provided(project(":spring-tx"))
		optional(project(":spring-web"))
		optional("org.hibernate:hibernate-core:${hibernate5Version}")
		optional("javax.servlet:javax.servlet-api:3.0.1")
		optional("javax.transaction:javax.transaction-api:${jtaVersion}")
	}
}

project("spring-webmvc") {
	description = "Spring Web MVC"

	dependencies {
		compile(project(":spring-aop"))
		compile(project(":spring-beans"))
		compile(project(":spring-context"))
		compile(project(":spring-core"))
		compile(files(project(":spring-core").objenesisRepackJar))
		compile(project(":spring-expression"))
		compile(project(":spring-web"))
		provided("javax.servlet:javax.servlet-api:3.1.0")
		optional(project(":spring-context-support"))  // for Velocity support
		optional(project(":spring-oxm"))  // for MarshallingView
		optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
		optional("javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1")
		optional("net.sourceforge.jexcelapi:jxl:2.6.12")
		optional("org.apache.poi:poi:${poiVersion}")
		optional("org.apache.poi:poi-ooxml:${poiVersion}")
		optional("org.apache.velocity:velocity:1.7")
		optional("velocity-tools:velocity-tools-view:1.4")
		optional("org.freemarker:freemarker:${freemarkerVersion}")
		optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
		optional("com.lowagie:itext:2.1.7")
		optional("net.sf.jasperreports:jasperreports:$jasperreportsVersion") {
			exclude group: "com.fasterxml.jackson.core", module: "jackson-annotations"
			exclude group: "com.fasterxml.jackson.core", module: "jackson-core"
			exclude group: "com.fasterxml.jackson.core", module: "jackson-databind"
			exclude group: "org.olap4j", module: "olap4j"
			exclude group: "xml-apis", module: "xml-apis"
			exclude group: "org.springframework", module: "spring-context"
		}
		optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
		optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.8.11")
		optional("com.rometools:rome:${romeVersion}")
		optional("javax.el:javax.el-api:2.2.5")
		optional("org.apache.tiles:tiles-api:${tiles3Version}")
		optional("org.apache.tiles:tiles-core:${tiles3Version}") {
			exclude group: "org.slf4j", module: "jcl-over-slf4j"
		}
		optional("org.apache.tiles:tiles-servlet:${tiles3Version}") {
			exclude group: "org.slf4j", module: "jcl-over-slf4j"
		}
		optional("org.apache.tiles:tiles-jsp:${tiles3Version}") {
			exclude group: "org.slf4j", module: "jcl-over-slf4j"
		}
		optional("org.apache.tiles:tiles-el:${tiles3Version}") {
			exclude group: "org.slf4j", module: "jcl-over-slf4j"
		}
		optional("org.apache.tiles:tiles-extras:${tiles3Version}") {
			exclude group: "org.slf4j", module: "jcl-over-slf4j"
			exclude group: "org.springframework", module: "spring-web"
		}
		optional('org.webjars:webjars-locator:0.32-1')
		testCompile("xmlunit:xmlunit:${xmlunitVersion}")
		testCompile("dom4j:dom4j:1.6.1") {
			exclude group: "xml-apis", module: "xml-apis"
		}
		testCompile("jaxen:jaxen:1.1.1") {
			exclude group: "xml-apis", module: "xml-apis"
			exclude group: "xom", module: "xom"
			exclude group: "xerces", module: "xercesImpl"
		}
		testCompile("org.eclipse.jetty:jetty-servlet:${jettyVersion}") {
			exclude group: "javax.servlet", module: "javax.servlet"
		}
		testCompile("org.eclipse.jetty:jetty-server:${jettyVersion}") {
			exclude group: "javax.servlet", module: "javax.servlet"
		}
		testCompile("javax.validation:validation-api:1.0.0.GA")
		testCompile("org.hibernate:hibernate-validator:${hibval4Version}")
		testCompile("org.apache.httpcomponents:httpclient:${httpclientVersion}")
		testCompile("commons-fileupload:commons-fileupload:${fileuploadVersion}")
		testCompile("commons-io:commons-io:1.4")
		testCompile("joda-time:joda-time:${jodaVersion}")
		testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
		testCompile("org.mozilla:rhino:1.7.7.2")
		testRuntime("org.jruby:jruby:${jrubyVersion}")
		testRuntime("org.python:jython-standalone:2.5.3")
		testRuntime("org.webjars:underscorejs:1.8.3")
	}
}

project("spring-webmvc-tiles2") {
	description = "Spring Framework Tiles2 Integration"
	merge.into = project(":spring-webmvc")

	dependencies {
		provided(project(":spring-context"))
		provided(project(":spring-web"))
		provided("javax.servlet:javax.servlet-api:3.0.1")
		optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
		optional("javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1")
		optional("org.apache.tiles:tiles-api:${tiles2Version}")
		optional("org.apache.tiles:tiles-core:${tiles2Version}") {
			exclude group: "org.slf4j", module: "jcl-over-slf4j"
		}
		optional("org.apache.tiles:tiles-servlet:${tiles2Version}") {
			exclude group: "org.slf4j", module: "jcl-over-slf4j"
		}
		optional("org.apache.tiles:tiles-jsp:${tiles2Version}") {
			exclude group: "org.slf4j", module: "jcl-over-slf4j"
		}
		optional("org.apache.tiles:tiles-el:${tiles2Version}") {
			exclude group: "org.slf4j", module: "jcl-over-slf4j"
		}
		optional("org.apache.tiles:tiles-extras:${tiles2Version}") {
			exclude group: "org.slf4j", module: "jcl-over-slf4j"
			exclude group: "org.apache.velocity", module: "velocity-tools"
			exclude group: "org.springframework", module: "spring-web"
		}
		testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
	}
}

project("spring-webmvc-portlet") {
	description = "Spring Web Portlet"

	dependencies {
		compile(project(":spring-beans"))
		compile(project(":spring-context"))
		compile(project(":spring-core"))
		compile(project(":spring-web"))
		compile(project(":spring-webmvc"))
		provided("javax.servlet:javax.servlet-api:3.0.1")
		provided("javax.portlet:portlet-api:2.0")
		optional("commons-fileupload:commons-fileupload:${fileuploadVersion}")
	}
}

project("spring-websocket") {
	description = "Spring WebSocket"

	dependencies {
		compile(project(":spring-context"))
		compile(project(":spring-core"))
		compile(project(":spring-web"))
		optional(project(":spring-messaging"))
		optional(project(":spring-webmvc"))
		optional("javax.servlet:javax.servlet-api:3.1.0")
		optional("javax.websocket:javax.websocket-api:1.0")
		optional("org.apache.tomcat:tomcat-websocket:${tomcatVersion}") {
			exclude group: "org.apache.tomcat", module: "tomcat-websocket-api"
			exclude group: "org.apache.tomcat", module: "tomcat-servlet-api"
		}
		optional("org.glassfish.tyrus:tyrus-spi:${tyrusVersion}")
		optional("org.glassfish.tyrus:tyrus-core:${tyrusVersion}")
		optional("org.glassfish.tyrus:tyrus-server:${tyrusVersion}")
		optional("org.glassfish.tyrus:tyrus-container-servlet:${tyrusVersion}")
		optional("org.eclipse.jetty:jetty-webapp:${jettyVersion}") {
			exclude group: "javax.servlet", module: "javax.servlet"
		}
		optional("org.eclipse.jetty.websocket:websocket-server:${jetty94Version}") {
			exclude group: "javax.servlet", module: "javax.servlet"
		}
		optional("org.eclipse.jetty.websocket:websocket-client:${jetty94Version}")
		optional("org.eclipse.jetty:jetty-client:${jetty94Version}")
		optional("io.undertow:undertow-core:${undertowVersion}")
		optional("io.undertow:undertow-servlet:${undertowVersion}") {
			exclude group: "org.jboss.spec.javax.servlet", module: "jboss-servlet-api_3.1_spec"
			exclude group: "org.jboss.spec.javax.annotation", module: "jboss-annotations-api_1.2_spec"
		}
		optional("io.undertow:undertow-websockets-jsr:${undertowVersion}") {
			exclude group: "org.jboss.spec.javax.websocket", module: "jboss-websocket-api_1.1_spec"
		}
		optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
		testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
		testCompile("org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}")
		testCompile("io.projectreactor:reactor-net:${reactorVersion}")
		testCompile("io.netty:netty-all:${nettyVersion}")
		testCompile("log4j:log4j:${log4jVersion}")
		testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
	}
}

project("spring-test") {
	description = "Spring TestContext Framework"

	// Disable warning for annotation processing in order to get the
	// build passing again after it mysteriously started failing in 2020.
	compileJava.options.compilerArgs -= "-Xlint:processing"

	dependencies {
		compile(project(":spring-core"))
		optional(project(":spring-aop"))
		optional(project(":spring-beans"))
		optional(project(":spring-context"))
		optional(project(":spring-jdbc"))
		optional(project(":spring-orm"))
		optional(project(":spring-tx"))
		optional(project(":spring-web"))
		optional(project(":spring-webmvc"))
		optional(project(":spring-webmvc-portlet"))
		optional(project(":spring-websocket"))
		optional("junit:junit:${junitVersion}")
		optional("org.testng:testng:${testngVersion}")
		optional("javax.inject:javax.inject:1")
		optional("javax.servlet:javax.servlet-api:3.0.1")
		optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
		optional("javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1")
		optional("org.apache.taglibs:taglibs-standard-jstlel:1.2.1") {
			exclude group: "org.apache.taglibs", module: "taglibs-standard-spec"
		}
		optional("javax.portlet:portlet-api:2.0")
		optional("javax.el:javax.el-api:2.2.5")
		optional("javax.websocket:javax.websocket-api:1.0")
		optional("org.aspectj:aspectjweaver:${aspectjVersion}")
		optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
		optional("org.hamcrest:hamcrest-core:${hamcrestVersion}")
		optional("xmlunit:xmlunit:${xmlunitVersion}")
		optional("net.sourceforge.htmlunit:htmlunit:2.23")
		optional("org.seleniumhq.selenium:htmlunit-driver:2.23.2")
		optional("org.seleniumhq.selenium:selenium-java:2.53.1")
		optional("org.skyscreamer:jsonassert:1.4.0")
		optional("com.jayway.jsonpath:json-path:2.3.0")
		testCompile(project(":spring-context-support"))
		testCompile(project(":spring-oxm"))
		testCompile("javax.mail:javax.mail-api:${javamailVersion}")
		testCompile("javax.ejb:ejb-api:${ejbVersion}")
		testCompile("org.hibernate:hibernate-core:${hibernate4Version}")
		testCompile("org.hibernate:hibernate-entitymanager:${hibernate4Version}")
		testCompile("org.hibernate:hibernate-validator:${hibval5Version}")
		testCompile("com.thoughtworks.xstream:xstream:${xstreamVersion}")
		testCompile("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
		testCompile("com.rometools:rome:${romeVersion}")
		testCompile("org.apache.tiles:tiles-api:${tiles3Version}")
		testCompile("org.apache.tiles:tiles-core:${tiles3Version}") {
			exclude group: "org.slf4j", module: "jcl-over-slf4j"
		}
		testCompile("org.apache.tiles:tiles-servlet:${tiles3Version}") {
			exclude group: "org.slf4j", module: "jcl-over-slf4j"
		}
		testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
		testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
		testCompile("org.apache.httpcomponents:httpclient:${httpclientVersion}")
		testCompile("javax.cache:cache-api:1.0.0")
		testRuntime("log4j:log4j:${log4jVersion}")
	}

	task testNG(type: Test) {
		description = 'Runs TestNG tests.'
		useTestNG()
		scanForTestClasses = false
		include(["**/testng/**/*Tests.class", "**/testng/**/*Test.class"])
		// Show STD_OUT & STD_ERR of the test JVM(s) on the console:
		// testLogging.showStandardStreams = true
		// forkEvery 1
	}

	test {
		description = 'Runs JUnit tests.'
		dependsOn testNG
		useJUnit()
		exclude "**/testng/**/*.*"
	}

	task aggregateTestReports(type: TestReport) {
		description = 'Aggregates JUnit and TestNG test reports.'
		destinationDir = test.reports.html.destination
		reportOn test, testNG
	}

	check.dependsOn aggregateTestReports
}

project("spring-aspects") {
	description = "Spring Aspects"
	apply from: "aspects.gradle"

	dependencies {
		aspects(project(":spring-orm"))
		ajc("org.aspectj:aspectjtools:${aspectjVersion}")
		rt("org.aspectj:aspectjrt:${aspectjVersion}")
		compile("org.aspectj:aspectjweaver:${aspectjVersion}")
		provided("org.eclipse.persistence:javax.persistence:2.0.0")
		optional(project(":spring-aop"))  // for @Async support
		optional(project(":spring-beans"))  // for @Configurable support
		optional(project(":spring-context"))  // for @Enable* support
		optional(project(":spring-context-support"))  // for JavaMail and JSR-107 support
		optional(project(":spring-orm"))  // for JPA exception translation support
		optional(project(":spring-tx"))  // for JPA, @Transactional support
		optional("javax.transaction:javax.transaction-api:${jtaVersion}")  // for @javax.transaction.Transactional support
		optional("javax.cache:cache-api:1.0.0")
		testCompile(project(":spring-core"))  // for CodeStyleAspect
		testCompile(project(":spring-test"))
		testCompile("javax.mail:javax.mail-api:${javamailVersion}")
	}

	eclipse.project {
		natures += "org.eclipse.ajdt.ui.ajnature"
		buildCommands = [new org.gradle.plugins.ide.eclipse.model.BuildCommand("org.eclipse.ajdt.core.ajbuilder")]
	}
}

project("spring-framework-bom") {
	description = "Spring Framework (Bill of Materials)"

	configurations.archives.artifacts.clear()
	artifacts {
		// work around GRADLE-2406 by attaching text artifact
		archives(file("spring-framework-bom.txt"))
	}

	install {
		repositories.mavenInstaller {
			pom.whenConfigured {
				packaging = "pom"
				withXml {
					asNode().children().last() + {
						delegate.dependencyManagement {
							delegate.dependencies {
								parent.subprojects.sort { "$it.name" }.each { p ->
									if (p.hasProperty("merge") && p.merge.into == null && p != project) {
										delegate.dependency {
											delegate.groupId(p.group)
											delegate.artifactId(p.name)
											delegate.version(p.version)
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
}

configure(rootProject) {
	description = "Spring Framework"

	apply plugin: "org.asciidoctor.convert"
	apply plugin: "docbook-reference"
	apply plugin: "groovy"

	// apply plugin: "detect-split-packages"
	apply from: "${gradleScriptDir}/jdiff.gradle"

	asciidoctor {
		sourceDir project.file('src/asciidoc')
		separateOutputDirs = false
		backends = ['docbook']
		options doctype: 'book', eruby: 'erubis'
		attributes 'spring-version': project.version, 'revnumber': project.version, 'docinfo': ""
	}

	reference {
		sourceDir = asciidoctor.outputDir
		pdfFilename = "spring-framework-reference.pdf"
		epubFilename = "spring-framework-reference.epub"
		expandPlaceholders = ""
	}

	afterEvaluate {
		tasks.findAll { it.name.startsWith("reference") }.each{ it.dependsOn.add("asciidoctor") }
	}

	// TODO: DetectSplitPackagesPlugin fails in line 154 due to method not found on java.io.File.
	// TODO: Possibly related to user rights or OS differences; passes on local Windows machine.
	// detectSplitPackages {
	//	projectsToScan -= project(":spring-instrument-tomcat")
	// }

	// don't publish the default jar for the root project
	configurations.archives.artifacts.clear()

	dependencies {  // for integration tests
		testCompile(project(":spring-aop"))
		testCompile(project(":spring-beans"))
		testCompile(project(":spring-context"))
		testCompile(project(":spring-core"))
		testCompile(project(":spring-expression"))
		testCompile(project(":spring-jdbc"))
		testCompile(project(":spring-orm"))
		testCompile(project(":spring-test"))
		testCompile(project(":spring-tx"))
		testCompile(project(":spring-web"))
		testCompile(project(":spring-webmvc-portlet"))
		testCompile("javax.servlet:javax.servlet-api:3.0.1")
		testCompile("javax.portlet:portlet-api:2.0")
		testCompile("javax.inject:javax.inject:1")
		testCompile("javax.resource:connector-api:1.5")
		testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
		testCompile("org.hibernate:hibernate-core:${hibernate4Version}")
		testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
	}

	task api(type: Javadoc) {
		group = "Documentation"
		description = "Generates aggregated Javadoc API documentation."
		title = "${rootProject.description} ${version} API"

		dependsOn {
			subprojects.collect {
				it.tasks.getByName("jar")
			}
		}
		options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
		options.author = true
		options.header = rootProject.description
		options.overview = "src/api/overview.html"
		options.stylesheetFile = file("src/api/stylesheet.css")
		options.splitIndex = true
		options.links(project.ext.javadocLinks)
		options.addStringOption('Xdoclint:none', '-quiet')

		source subprojects.collect { project ->
			project.sourceSets.main.allJava
		}

		maxMemory = "1024m"
		destinationDir = new File(buildDir, "api")

		doFirst {
			classpath = files(
				// Ensure Servlet 3.x and Hibernate 4.x have precedence on the javadoc
				// classpath over their respective 2.5 and 3.x variants
				project(":spring-webmvc").sourceSets.main.compileClasspath.files.find { it =~ "servlet-api" },
				rootProject.sourceSets.test.compileClasspath.files.find { it =~ "hibernate-core" },
				// Ensure the javadoc process can resolve types compiled from .aj sources
				project(":spring-aspects").sourceSets.main.output
			)
			classpath += files(subprojects.collect { it.sourceSets.main.compileClasspath })
		}
	}

	task docsZip(type: Zip, dependsOn: 'reference') {
		group = "Distribution"
		baseName = "spring-framework"
		classifier = "docs"
		description = "Builds -${classifier} archive containing api and reference " +
			"for deployment at https://docs.spring.io/spring-framework/docs."

		from("src/dist") {
			include "changelog.txt"
		}

		from (api) {
			into "javadoc-api"
		}

		from (reference) {
			into "spring-framework-reference"
		}
	}

	task schemaZip(type: Zip) {
		group = "Distribution"
		baseName = "spring-framework"
		classifier = "schema"
		description = "Builds -${classifier} archive containing all " +
			"XSDs for deployment at https://springframework.org/schema."
		duplicatesStrategy 'exclude'
		moduleProjects.each { subproject ->
			def Properties schemas = new Properties();

			subproject.sourceSets.main.resources.find {
				(it.path.endsWith("META-INF/spring.schemas") || it.path.endsWith("META-INF\\spring.schemas"))
			}?.withInputStream { schemas.load(it) }

			for (def key : schemas.keySet()) {
				def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
				assert shortName != key
				File xsdFile = subproject.sourceSets.main.resources.find {
					(it.path.endsWith(schemas.get(key)) || it.path.endsWith(schemas.get(key).replaceAll('\\/','\\\\')))
				}
				assert xsdFile != null
				into (shortName) {
					from xsdFile.path
				}
			}
		}
	}

	task distZip(type: Zip, dependsOn: [docsZip, schemaZip]) {
		group = "Distribution"
		baseName = "spring-framework"
		classifier = "dist"
		description = "Builds -${classifier} archive, containing all jars and docs, " +
			"suitable for community download page."

		ext.baseDir = "${baseName}-${project.version}";

		from("src/dist") {
			include "readme.txt"
			include "license.txt"
			include "notice.txt"
			into "${baseDir}"
			expand(copyright: new Date().format("yyyy"), version: project.version)
		}

		from(zipTree(docsZip.archivePath)) {
			into "${baseDir}/docs"
		}

		from(zipTree(schemaZip.archivePath)) {
			into "${baseDir}/schema"
		}

		moduleProjects.each { subproject ->
			into ("${baseDir}/libs") {
				from subproject.jar
				if (subproject.tasks.findByPath("sourcesJar")) {
					from subproject.sourcesJar
				}
				if (subproject.tasks.findByPath("javadocJar")) {
					from subproject.javadocJar
				}
			}
		}
	}

	// Create a distribution that contains all dependencies (required and optional).
	// Not published by default; only for use when building from source.
	task depsZip(type: Zip, dependsOn: distZip) { zipTask ->
		group = "Distribution"
		baseName = "spring-framework"
		classifier = "dist-with-deps"
		description = "Builds -${classifier} archive, containing everything " +
			"in the -${distZip.classifier} archive plus all runtime dependencies."

		from zipTree(distZip.archivePath)

		gradle.taskGraph.whenReady { taskGraph ->
			if (taskGraph.hasTask(":${zipTask.name}")) {
				def projectNames = rootProject.subprojects*.name
				def artifacts = new HashSet()
				subprojects.each { subproject ->
					(subproject.configurations.runtime.resolvedConfiguration.resolvedArtifacts +
					subproject.configurations.optional.resolvedConfiguration.resolvedArtifacts).each { artifact ->
						def dependency = artifact.moduleVersion.id
						if (!projectNames.contains(dependency.name)) {
							artifacts << artifact.file
						}
					}
				}

				zipTask.from(artifacts) {
					into "${distZip.baseDir}/deps"
				}
			}
		}
	}

	artifacts {
		archives docsZip
		archives schemaZip
		archives distZip
	}

	wrapper {
		description = "Generates gradlew[.bat] scripts"
		gradleVersion = "4.10.2"

		doLast() {
			def gradleOpts = "-XX:MaxMetaspaceSize=1024m -Xmx1024m"
			def gradleBatOpts = "$gradleOpts -XX:MaxHeapSize=256m"
			File wrapperFile = file("gradlew")
			wrapperFile.text = wrapperFile.text.replace("DEFAULT_JVM_OPTS=",
				"GRADLE_OPTS=\"$gradleOpts \$GRADLE_OPTS\"\nDEFAULT_JVM_OPTS=")
			File wrapperBatFile = file("gradlew.bat")
			wrapperBatFile.text = wrapperBatFile.text.replace("set DEFAULT_JVM_OPTS=",
				"set GRADLE_OPTS=$gradleBatOpts %GRADLE_OPTS%\nset DEFAULT_JVM_OPTS=")
		}
	}

}

/*
 * Support publication of artifacts versioned by topic branch.
 * CI builds supply `-P BRANCH_NAME=<TOPIC>` to gradle at build time.
 * If <TOPIC> starts with 'SPR-', change version
 *     from BUILD-SNAPSHOT => <TOPIC>-SNAPSHOT
 *     e.g. 3.2.1.BUILD-SNAPSHOT => 3.2.1.SPR-1234-SNAPSHOT
 */
def qualifyVersionIfNecessary(version) {
	if (rootProject.hasProperty("BRANCH_NAME")) {
		def qualifier = rootProject.getProperty("BRANCH_NAME")
		if (qualifier.startsWith("SPR-")) {
			return version.replace('BUILD', qualifier)
		}
	}
	return version
}
