This is an automated email from the ASF dual-hosted git repository. benw pushed a commit to branch gradle-improvements-javax in repository https://gitbox.apache.org/repos/asf/tapestry-5.git
commit 12ae9918421cb480e9ff3d4b848e8bdebf42e8c8 Author: Ben Weidig <[email protected]> AuthorDate: Sat Sep 13 13:07:01 2025 +0200 TAP5-2809: basic gradle setup An attempt to replicate the basic gradle setup from (future) master. The project doesn't build, but Gradle itself is running clean without instantly failing. --- beanmodel/build.gradle | 60 +- build.gradle | 806 ++++++++------------- buildSrc/build.gradle | 20 + .../main/groovy/t5build/GenerateChecksums.groovy | 61 ++ buildSrc/src/main/groovy/t5build/SSshExec.groovy | 21 + buildSrc/src/main/groovy/t5build/Scp.groovy | 36 + buildSrc/src/main/groovy/t5build/SshTask.groovy | 94 +++ .../main/groovy/t5build/TapestryBuildLogic.groovy | 22 + .../main/groovy/tapestry.java-convention.gradle | 66 ++ .../tapestry.junit4-legacy-convention.gradle | 12 + .../main/groovy/tapestry.junit5-convention.gradle | 13 + .../groovy/tapestry.junit5-spock-convention.gradle | 9 + .../src/main/groovy/tapestry.ssh-convention.gradle | 15 + .../groovy/tapestry.testing-base-convention.gradle | 64 ++ .../main/groovy/tapestry.testng-convention.gradle | 27 + commons/build.gradle | 26 +- genericsresolver-guava/build.gradle | 16 +- gradle/libs.versions.toml | 168 +++++ gradle/wrapper/gradle-wrapper.jar | Bin 59821 -> 43462 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 41 +- gradlew.bat | 15 +- plastic/build.gradle | 23 +- quickstart/build.gradle | 24 +- settings.gradle | 87 ++- sha256.gradle | 25 - ssh.gradle | 124 ---- tapestry-beanvalidator/build.gradle | 44 +- tapestry-cdi/build.gradle | 91 ++- tapestry-clojure/build.gradle | 29 +- tapestry-core/build.gradle | 222 +++--- tapestry-func/build.gradle | 12 +- tapestry-hibernate-core/build.gradle | 21 +- tapestry-hibernate/build.gradle | 39 +- tapestry-http/build.gradle | 34 +- tapestry-internal-test/build.gradle | 6 +- tapestry-ioc-jcache/build.gradle | 54 +- tapestry-ioc-junit/build.gradle | 13 +- tapestry-ioc/build.gradle | 35 +- tapestry-javadoc/build.gradle | 51 +- tapestry-jmx/build.gradle | 17 +- tapestry-jpa/build.gradle | 53 +- tapestry-json/build.gradle | 18 +- tapestry-kaptcha/build.gradle | 18 +- tapestry-latest-java-tests/build.gradle | 26 +- tapestry-mongodb/build.gradle | 27 +- tapestry-openapi-viewer/build.gradle | 7 +- tapestry-rest-jackson/build.gradle | 16 +- tapestry-runner/build.gradle | 27 +- tapestry-spock/build.gradle | 22 +- tapestry-spring/build.gradle | 44 +- tapestry-test-data/build.gradle | 4 +- tapestry-test/build.gradle | 33 +- tapestry-upload/build.gradle | 25 +- tapestry-version-migrator/build.gradle | 18 +- tapestry-webresources/build.gradle | 78 +- tapestry5-annotations/build.gradle | 2 +- 57 files changed, 1710 insertions(+), 1255 deletions(-) diff --git a/beanmodel/build.gradle b/beanmodel/build.gradle index 5adf920bd..68391ae01 100644 --- a/beanmodel/build.gradle +++ b/beanmodel/build.gradle @@ -1,39 +1,47 @@ -import org.gradle.plugins.ide.idea.model.* -import t5build.* - -description = "Fast class property discovery, reading and writing library based on bytecode generation. Extracted from Apache Tapestry, but not dependent on the Web framework (tapestry-core) nor the IoC one (tapestry-ioc)." - -//apply plugin: JavaPlugin -apply plugin: 'antlr' +plugins { + id 'tapestry.junit5-convention' + id 'antlr' +} -buildDir = 'target/gradle-build' +description = 'Fast class property discovery, reading and writing library based on bytecode generation. Extracted from Apache Tapestry, but not dependent on the Web framework (tapestry-core) nor the IoC one (tapestry-ioc).' dependencies { - api project(":plastic") - api project(":tapestry5-annotations") - api project(":commons") - implementation "org.slf4j:slf4j-api:${versions.slf4j}" + implementation project(':plastic') + implementation project(':tapestry5-annotations') + implementation project(':commons') - // ANTLR tool path used with the generateGrammarSource task - antlr "org.antlr:antlr:3.5.2" + implementation libs.slf4j.api + + antlr libs.antlr // Transitive will bring in the unwanted string template library as well - implementation "org.antlr:antlr-runtime:3.5.2", { - exclude group: "org.antlr", module: "stringtemplate" + implementation(libs.antlr.runtime) { + exclude group: 'org.antlr', module: 'stringtemplate' } - testImplementation "org.testng:testng:${versions.testng}", { transitive = false } - testImplementation "org.easymock:easymock:${versions.easymock}" - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" - testImplementation "org.spockframework:spock-core:${versions.spock}" + testImplementation platform(libs.spock.bom) + testImplementation libs.spock.core } -clean.delete generateGrammarSource.outputDirectory +tasks.named('clean') { + delete generateGrammarSource.outputDirectory +} -compileJava { - options.fork(memoryMaximumSize: '512m') +tasks.named('compileJava', JavaCompile) { + dependsOn generateGrammarSource + options.fork = true + options.forkOptions.memoryMaximumSize = '512M' } -test { - useJUnit() -} \ No newline at end of file +tasks.named('sourcesJar') { + dependsOn 'generateGrammarSource' + duplicatesStrategy = DuplicatesStrategy.EXCLUDE +} + +sourceSets { + main { + java { + srcDir generateGrammarSource.outputDirectory + } + } +} diff --git a/build.gradle b/build.gradle index 184c8da88..300c62ef3 100755 --- a/build.gradle +++ b/build.gradle @@ -1,291 +1,125 @@ -description = "Apache Tapestry 5 Project" - +import t5build.GenerateChecksums +import t5build.TapestryBuildLogic import org.apache.tools.ant.filters.ReplaceTokens -apply plugin: "base" -apply plugin: "maven-publish" - -apply from: "ssh.gradle" -apply from: "md5.gradle" -apply from: "sha256.gradle" - -project.ext.versions = [ - jetty: "8.1.19.v20160209", - tomcat: "7.0.70", - testng: "7.5.1", - easymock: "5.4.0", - servletapi: "3.0.1", - spock: "2.3-groovy-3.0", - hibernate: "5.4.32.Final", - slf4j: "1.7.25", - geb: "2.0", - selenium: "4.5.0", - seleniumServer: "4.12.1", - jackson: "2.13.1", - jsonschemaGenerator: "4.20.0", - junitJupiter: "5.10.2", - commonsLang: "3.17.0", - commonsIo: "2.17.0", - webdriverManager: "5.3.1", - antlrRuntime: "3.5.3", - hsqldb: "2.7.3:jdk8", - snakeyaml: "2.3" -] - -def artifactSuffix = "" - -// Artifacts that have both an unsuffixed artifact from the javax branch -// and a suffixed one from the master branch -def suffixedArtifactNames = ["tapestry-core", "tapestry-http", "tapestry-test", - "tapestry-runner", "tapestry-spring", "tapestry-kaptcha", - "tapestry-openapi-viewer", "tapestry-upload", "tapestry-jmx", - "tapestry-jpa", "tapestry-kaptcha", "tapestry-openapi-viewer", - "tapestry-rest-jackson", "tapestry-webresources", "tapestry-cdi", - "tapestry-ioc", "tapestry-ioc-jcache", "tapestry-jmx", "tapestry-spock", - "tapestry-clojure", "tapestry-hibernate", "tapestry-hibernate-core", - "tapestry-ioc-junit", "tapestry-latest-java-tests", "tapestry-mongodb", - "tapestry-spock", "tapestry-beanvalidator"] - -ext.continuousIntegrationBuild = Boolean.getBoolean("ci") - -// Provided so that the CI server can override the normal version number for nightly builds. -project.version = tapestryVersion() - -// Remember that when generating a release, this should be incremented. Also don"t forget to -// tag the release in Git. -// Version number is always "5.x(.y)?-SNAPSHOT" and only gets fixed, e.g. to 5.4-alpha-1 -// during a release - -def tapestryVersion() { - - def major = "5.10.0" - def minor = "" - - // When building on the CI server, make sure -SNAPSHOT is appended, as it is a nightly build. - // When building normally, or for a release, no suffix is desired. - continuousIntegrationBuild ? major + "-SNAPSHOT" : major + minor +plugins { + id 'base' + id 'maven-publish' } -// Let analysis.apache.org get in touch with our builds - -project.ext { - - stagingUrl = "https://repository.apache.org/service/local/staging/deploy/maven2/" - snapshotUrl = "https://repository.apache.org/content/repositories/snapshots" - - doSign = !project.hasProperty("noSign") && project.hasProperty("signing.keyId") +description = 'Apache Tapestry 5 Project' + +ext { + tapestryMajorVersion = '5.10.0' + tapestryMinorVersion = '' // Use for release suffixes like '-alpha-1' + + artifactSuffix = '-jakarta' + + // Artifacts that have both an unsuffixed artifact from the javax branch + // and a suffixed one from the master branch + suffixedArtifactNames = [ + 'tapestry-beanvalidator', + 'tapestry-cdi', + 'tapestry-clojure', + 'tapestry-hibernate-core', + 'tapestry-hibernate', + 'tapestry-http', + 'tapestry-ioc-jcache', + 'tapestry-ioc-junit', + 'tapestry-ioc', + 'tapestry-jmx', + 'tapestry-jpa', + 'tapestry-kaptcha', + 'tapestry-latest-java-tests', + 'tapestry-mongodb', + 'tapestry-openapi-viewer', + 'tapestry-rest-jackson', + 'tapestry-runner', + 'tapestry-spock', + 'tapestry-spring', + 'tapestry-test', + 'tapestry-upload', + 'tapestry-webresources', + 'tapestry-core', + ] + + continuousIntegrationBuild = Boolean.getBoolean('ci') + stagingUrl = 'https://repository.apache.org/service/local/staging/deploy/maven2/' + snapshotUrl = 'https://repository.apache.org/content/repositories/snapshots' + doSign = !project.hasProperty('noSign') && project.hasProperty('signing.keyId') // apacheDeployUserName and apacheDeployPassword should be specified in ~/.gradle/gradle.properties - deployUsernameProperty = isSnapshot() ? "snapshotDeployUserName" : "apacheDeployUserName" - deployPasswordProperty = isSnapshot() ? "snapshotDeployPassword" : "apacheDeployPassword" - - canDeploy = [deployUsernameProperty, deployPasswordProperty, "apacheArchivesFolder"].every { project.hasProperty(it) } - - // These are all deferred inside closures, to allow people without the necessary values in their - // gradle.properties to build locally, just not deploy. getProperty() throws an exception if the property - // is not present. - deployUsername = { getProperty(deployUsernameProperty) } - deployPassword = { getProperty(deployPasswordProperty) } - - archiveDeployFolder = { getProperty("apacheArchivesFolder") } -} - -println "JDK: " + System.getProperty("java.version") - -//println "Can deploy? $canDeploy" -//println "Is snapshot? isSnapshot" -//println "deployUsernameProperty $deployUsernameProperty" -//println "deployPasswordProperty $deployPasswordProperty" -//println "continuousIntegrationBuild? $continuousIntegrationBuild" - -allprojects { - - apply plugin: "eclipse" - apply plugin: "idea" + def deployFlavor = TapestryBuildLogic.isSnapshot(project) ? 'snapshot' : 'apache' - repositories { - mavenLocal() - mavenCentral() - - // All things JBoss/Hibernate - maven { - name "JBoss" - url "https://repository.jboss.org/nexus/content/repositories/releases/" - } - } - - configurations { - // Non-code artifacts, such as sources JARs and zipped JavaDocs - meta - } + deployUsername = providers.gradleProperty("${deployFlavor}DeployUserName") + deployPassword = providers.gradleProperty("${deployFlavor}DeployPassword") + archiveDeployFolder = providers.gradleProperty('apacheArchivesFolder') + canDeploy = [ + deployUsername, + deployPassword, + archiveDeployFolder + ].every { it.present } } -idea { - project { - languageLevel = "1.8" - } -} +// Provided so that the CI server can override the normal version number for nightly builds. +version = TapestryBuildLogic.tapestryVersion(project) // Specific to top-level build, not set for subprojects: - configurations { javadoc published.extendsFrom archives, meta + if (doSign) { published.extendsFrom signatures } + binaries // additional dependencies included in the binary archive } dependencies { - if (JavaVersion.current() != JavaVersion.VERSION_1_8) { - javadoc project(":tapestry-javadoc") + if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_11)) { + javadoc project(':tapestry-javadoc') + meta providers.provider { + tasks.named('aggregateJavadoc').get().outputs.files + } } // From tapestry-ioc: - binaries "javax.inject:javax.inject:1" - binaries "org.slf4j:slf4j-api:${versions.slf4j}" - binaries "commons-codec:commons-codec:1.17.1" - binaries "org.antlr:antlr-runtime:${versions.antlrRuntime}", { transitive = false } + binaries libs.javax.inject + binaries libs.slf4j.api + binaries libs.commons.codec + binaries libs.antlr.runtime, { + transitive = false + } } -String jdkVersion = System.properties['java.version'] -def jdkMajorVersion = jdkVersion.substring(0, jdkVersion.indexOf(".")) // 1, 9, 10... - subprojects { - - def specifyMaxPermSize = jdkVersion ==~ /1\.[67].+/ - - apply plugin: "maven-publish" // for deployment + plugins.apply 'tapestry.java-convention' + plugins.apply 'maven-publish' + plugins.apply 'project-report' + plugins.apply 'jacoco' + plugins.apply 'groovy' - configurations { - provided - } - - apply plugin: "java" - apply plugin: "java-library" - apply plugin: "groovy" // mostly for testing - - apply plugin: "project-report" - apply plugin: "jacoco" - apply plugin: "base" - jacoco { - toolVersion = "0.8.7" - } - - sourceCompatibility = "1.8" - targetCompatibility = "1.8" - - // See http://jira.codehaus.org/browse/GRADLE-784 - - sourceSets { - main { - compileClasspath += configurations.provided - } - test { - compileClasspath += configurations.provided - runtimeClasspath += configurations.provided - } + toolVersion = '0.8.7' } - idea.module { - scopes.PROVIDED.plus += [configurations.provided] - } - - eclipse.classpath.plusConfigurations += [configurations.provided] - dependencies { - - // https://docs.gradle.org/7.3.3/userguide/upgrading_version_6.html#potential_breaking_changes, - // Table 1. Common configuration upgrades - testImplementation "org.spockframework:spock-core:${versions.spock}" - - testRuntimeOnly "org.slf4j:slf4j-log4j12:${versions.slf4j}" - } - - compileTestGroovy { - configure(groovyOptions.forkOptions) { - memoryMaximumSize = '1g' - jvmArgs = ['-Xms512m', '-Xmx1g'] - if (specifyMaxPermSize){ - jvmArgs << '-XX:MaxPermSize=512m' - } - } + implementation libs.slf4j.api } - tasks.withType(Test) { - useTestNG() - - options.suites("src/test/conf/testng.xml") - if (specifyMaxPermSize){ - maxHeapSize "400M" - jvmArgs("-XX:MaxPermSize=200m") - }else{ - maxHeapSize "600M" - } - - // Needed to have XMLTokenStreamTests.testStreamEncoding() passing on Java 9+ - if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_1_9)) { - jvmArgs("--add-opens=java.base/java.nio.charset=ALL-UNNAMED"); - } - - // Turn off live service reloading - - systemProperties["tapestry.service-reloading-enabled"] = "false" - systemProperties["java.io.tmpdir"] = temporaryDir.absolutePath - - jvmArgs("-Dfile.encoding=UTF-8") - - environment.LANG = 'en_US.UTF-8' - - if (continuousIntegrationBuild) { - // Travis runs our builds with TERM=dumb and kills it if we don't produce any - // output for 10 minutes, so we log some task execution progress - - testLogging { - exceptionFormat "full" - } - - def numberOfTestsExecuted = 0 - afterTest { descriptor, result-> - numberOfTestsExecuted++ - if (numberOfTestsExecuted % 25 == 0){ - logger.lifecycle "$numberOfTestsExecuted tests executed" - } - } + tasks.withType(GroovyCompile).configureEach { + if (name == 'compileTestGroovy') { + options.fork = true + options.forkOptions.memoryMaximumSize = '1g' + options.forkOptions.jvmArgs = ['-Xms512m', '-Xmx1g'] } } - jar { - // println "JAR projectDir: " + projectDir.getName().replaceAll("5", "").replaceAll("tapestry-", "").replaceAll("-", ""); - from(projectDir) { - include "*.txt" - into "META-INF" - } - manifest { - attributes("Automatic-Module-Name": "org.apache.tapestry." + projectDir.getName() - .replaceAll("tapestry5", "tapestry") - .replaceAll("tapestry-", "") - .replaceAll("-", "")) - if (projectDir.getName().equals("tapestry-version-migrator")) { - attributes("Main-Class": "org.apache.tapestry5.versionmigrator.Main") - } - } - } - - assemble.dependsOn(processResources, compileJava, jar) - - task sourcesJar(type: Jar) { - dependsOn classes - archiveClassifier = "sources" - from sourceSets.main.allSource - from(projectDir) { - include "*.txt" - into "META-INF" - } + tasks.named('assemble') { + dependsOn processResources, compileJava, jar } artifacts { @@ -301,42 +135,41 @@ subprojects { published.extendsFrom signatures } } - + publishing { publications { mavenJava(MavenPublication) { version = parent.version - groupId = "org.apache.tapestry" + groupId = 'org.apache.tapestry' if (suffixedArtifactNames.contains(project.name)) { artifactId = project.name + artifactSuffix } from components.java artifact sourcesJar - - + pom { name = project.name // TODO: find some way to get the subproject description here. - // description = - url = "https://tapestry.apache.org/" + // description = + url = 'https://tapestry.apache.org/' licenses { license { name = 'The Apache License, Version 2.0' - url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' } } scm { connection = 'scm:git:https://gitbox.apache.org/repos/asf/tapestry-5.git' - developerConnection = 'scm:git://gitbox.apache.org/repos/asf/tapestry-5.git' - url = 'https://git-wip-us.apache.org/repos/asf?p=tapestry-5.git;a=summary' + developerConnection = 'scm:git://gitbox.apache.org/repos/asf/tapestry-5.git' + url = 'https://git-wip-us.apache.org/repos/asf?p=tapestry-5.git;a=summary' } // Changes the generated pom.xml so its dependencies on suffixed artifacts // get properly updated with suffixed artifact ids withXml { def artifactIdQName = new groovy.namespace.QName( - "http://maven.apache.org/POM/4.0.0", "artifactId") - def node = asNode(); - def dependencies = node.get("dependencies")[0] + 'http://maven.apache.org/POM/4.0.0', 'artifactId') + def node = asNode() + def dependencies = node.get('dependencies')[0] if (dependencies != null) { dependencies.'*'.forEach { def artifactIdNode = it.getAt(artifactIdQName)[0] @@ -347,103 +180,87 @@ subprojects { } } } - matching { - it.name.endsWith(".jar") || it.name.endsWith(".pom") - } } } if (canDeploy) { repositories { mavenLocal() - if (continuousIntegrationBuild) { - maven { - name = "apacheSnapshots" - url = snapshotUrl - credentials { - username = deployUsername() - password = deployPassword() - } - } - } - else { - maven { - name = "apacheStaging" - url = stagingUrl - credentials { - username = deployUsername() - password = deployPassword() - } + + def repoUrl = continuousIntegrationBuild ? snapshotUrl : stagingUrl + def repoName = continuousIntegrationBuild ? 'apacheSnapshots' : 'apacheStaging' + + maven { + name = repoName + url = repoUrl + credentials { + username = deployUsername.get() + password = deployPassword.get() } } - } } } if (doSign) { - apply plugin: "signing" + apply plugin: 'signing' signing { sign publishing.publications.mavenJava } } - + def actuallyPublish = !artifactSuffix.isEmpty() || suffixedArtifactNames.contains(project.name) - // println "XXXXXX Actually publish? " + actuallyPublish + " project " + project.name + " " + "!artifactSuffix.isEmpty() " + !artifactSuffix.isEmpty() + // println 'XXXXXX Actually publish? ' + actuallyPublish + ' project ' + project.name + ' ' + '!artifactSuffix.isEmpty() ' + !artifactSuffix.isEmpty() if (!actuallyPublish) { - tasks.withType(PublishToMavenRepository).configureEach { it.enabled = false } - tasks.withType(PublishToMavenLocal).configureEach { it.enabled = false } + tasks.withType(PublishToMavenRepository).configureEach { + it.enabled = false + } + tasks.withType(PublishToMavenLocal).configureEach { + it.enabled = false + } } - task uploadPublished { - + tasks.register('uploadPublished') { doFirst { if (!canDeploy) { - throw new InvalidUserDataException("Missing upload credentials. Set '$deployUsernameProperty' and '$deployPasswordProperty' root project properties.") + throw new InvalidUserDataException("Missing upload credentials. Set '${deployUsernameProperty}' and '${deployPasswordProperty}' root project properties.") } } - } } -subprojects.each { project.evaluationDependsOn(it.name) } - -subprojects { - - configurations.all { - - resolutionStrategy.force "antlr:antlr:2.7.7", - "cglib:cglib-nodep:2.2", - "commons-codec:commons-codec:1.10", - "commons-io:commons-io:${versions.commonsIo}", - "commons-logging:commons-logging:1.1.3", - "org.hsqldb:hsqldb:${versions.hsqldb}", - "org.antlr:antlr-runtime:${versions.antlrRuntime}", - "org.apache.tomcat:dbcp:6.0.32", - "org.hamcrest:hamcrest-core:1.3", - "org.json:json:20140107", - "org.yaml:snakeyaml:${versions.snakeyaml}", - "xml-apis:xml-apis:1.4.01" - - } -} // Cribbed from https://github.com/hibernate/hibernate-core/blob/master/release/release.gradle#L19 -task aggregateJavadoc(type: Javadoc) { +tasks.register('aggregateJavadoc', Javadoc) { + group = 'Documentation' + description = 'Build the aggregated JavaDocs for all modules' + dependsOn configurations.javadoc - group "Documentation" - description "Build the aggregated JavaDocs for all modules" - maxMemory "512m" - destinationDir file("$buildDir/documentation/javadocs") + maxMemory = '512m' + destinationDir = layout.buildDirectory.dir('documentation/javadocs').get().asFile - def tapestryStylesheet = file("src/javadoc/stylesheet7.css") + def tapestryStylesheet = file('src/javadoc/stylesheet7.css') int thisYear = java.time.Year.now().getValue() def allMainSourceSets = subprojects*.sourceSets*.main.flatten() def allMainJavaFiles = allMainSourceSets*.java def allMainJavaSrcDirs = allMainJavaFiles*.srcDirs + if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) { + exclude 'org/apache/tapestry5/spring/**' + } + + exclude 'org/apache/tapestry5/internal/plastic/asm/**' + exclude 'org/apache/tapestry5/internal/webresources/**' + exclude 'org/apache/tapestry5/webresources/modules/**' + + source allMainJavaFiles + + classpath += files(allMainSourceSets*.compileClasspath) + + inputs.files allMainJavaSrcDirs + options { splitIndex true linkSource true @@ -452,28 +269,24 @@ task aggregateJavadoc(type: Javadoc) { header "Tapestry API - ${project.version}" docTitle "Tapestry API - ($project.version)" bottom "${project.version} - Copyright © 2003-${thisYear} <a href=\"http://tapestry.apache.org/\">The Apache Software Foundation</a>." - use = true // 'use' seems to be a reserved word for the DSL - links "https://docs.oracle.com/javase/8/docs/api/" - links "https://docs.oracle.com/javaee/7/api/" - if (JavaVersion.current() != JavaVersion.VERSION_1_8) { + setUse(use) + links 'https://docs.oracle.com/javase/8/docs/api/' + + if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_11)) { tagletPath Collections.unmodifiableList(new ArrayList<>((Set) configurations.javadoc.files)) } // Uncomment jFlags to debug `./gradlew aggregateJavadoc` -// jFlags '-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005' + // jFlags '-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005' addStringOption '-source-path', files(allMainJavaSrcDirs.flatten()).asPath addStringOption 'source', '8' - taglets "org.apache.tapestry5.javadoc.TapestryDocTaglet" - } - - exclude "org/apache/tapestry5/internal/plastic/asm/**" - exclude "org/apache/tapestry5/internal/webresources/**" - exclude "org/apache/tapestry5/webresources/modules/**" - - source allMainJavaFiles - - classpath += files(allMainSourceSets*.compileClasspath) + taglets 'org.apache.tapestry5.javadoc.TapestryDocTaglet' - inputs.files allMainJavaSrcDirs + // Javadoc became stricer, so lets do this to actually build for now + if (JavaVersion.current().isJava9Compatible()) { + addBooleanOption('html5', true) + addStringOption('Xdoclint:none', '-quiet') + } + } // As part of generating the documentation, ALSO copy any related files: // Any extra images (Tapestry logo) @@ -483,138 +296,159 @@ task aggregateJavadoc(type: Javadoc) { copy { from allMainJavaSrcDirs into aggregateJavadoc.destinationDir - exclude "**/*.java" - exclude "**/*.xdoc" - exclude "**/package.html" + exclude '**/*.java' + exclude '**/*.xdoc' + exclude '**/package.html' } copy { - from file("src/javadoc/images") + from file('src/javadoc/images') into aggregateJavadoc.destinationDir } } } -task typeScriptDocs() { - group "Documentation" - description "Builds typedoc documentation for all TypeScript sources" - dependsOn project(":tapestry-core").tasks.generateTypeScriptDocs +tasks.register('typeScriptDocs') { + group = 'Documentation' + description = 'Builds typedoc documentation for all TypeScript sources' + + dependsOn(project(':tapestry-core').tasks.named('generateTypeScriptDocs')) } -dependencies { - if (JavaVersion.current() != JavaVersion.VERSION_1_8) { - meta aggregateJavadoc.outputs.files +tasks.register('combinedJacocoReport', JacocoReport) { + group = 'Verification' + description = 'Generates combined JaCoCo coverage report for all subprojects' + + def excludedProjects = [ + 'quickstart', + 'beanmodel', + 'commons', + 'genericsresolver-guava', + 'tapestry5-annotations', + 'tapestry-internal-test', + 'tapestry-runner', + 'tapestry-test-constants', + 'tapestry-test-data', + 'tapestry-ioc-jcache' + ] + + def subprojectsToConsider = subprojects.findAll { + !excludedProjects.contains(it.name) + } + + dependsOn = subprojectsToConsider.test + + additionalSourceDirs.from(files(subprojectsToConsider.sourceSets.main.allSource.srcDirs)) + sourceDirectories.from(files(subprojectsToConsider.sourceSets.main.allSource.srcDirs)) + classDirectories.from(files(subprojectsToConsider.sourceSets.main.output)) + executionData.from(files(subprojectsToConsider.jacocoTestReport.executionData).filter { + it.exists() + }) + jacocoClasspath = files(subprojectsToConsider.jacocoTestReport.jacocoClasspath) + + reports { + html { + required = true + outputLocation = layout.buildDirectory.dir('reports/jacoco') + } + xml.required = false + csv.required = false } } -task combinedJacocoReport(type:JacocoReport){ - def subprojectsToConsider = subprojects.findAll {it.name != 'quickstart' && it.name != 'beanmodel' && it.name != 'commons' && it.name != 'genericsresolver-guava' && it.name != 'tapestry5-annotations' && it.name != 'tapestry-internal-test' && it.name != 'tapestry-runner' && it.name != 'tapestry-test-constants' && it.name != 'tapestry-test-data' && it.name != 'tapestry-ioc-jcache'} - dependsOn = subprojectsToConsider.test - additionalSourceDirs.from(files(subprojectsToConsider.sourceSets.main.allSource.srcDirs)) - sourceDirectories.from(files(subprojectsToConsider.sourceSets.main.allSource.srcDirs)) - classDirectories.from(files(subprojectsToConsider.sourceSets.main.output)) - executionData.from(files(subprojectsToConsider.jacocoTestReport.executionData).filter { it.exists() }) - jacocoClasspath = files(subprojectsToConsider.jacocoTestReport.jacocoClasspath) - reports { - html { - required = true - destination = file("$buildDir/reports/jacoco") - } - xml { - required = false - } - csv { - required = false - } - } - onlyIf = { - true - } -} +tasks.register('continuousIntegration') { + group = 'Verification' + description = 'Runs a full CI build: assembles all artifacts, runs all checks, and generates aggregate reports.' -task continuousIntegration { def dependants = [ - 'tapestry-core:testWithPrototypeAndRequireJsDisabled', - 'tapestry-core:testWithJqueryAndRequireJsDisabled', - subprojects.build, // jQuery and Require.js enabled - 'tapestry-core:testWithPrototypeAndRequireJsEnabled', - combinedJacocoReport] + 'tapestry-core:testWithPrototypeAndRequireJsDisabled', + 'tapestry-core:testWithJqueryAndRequireJsDisabled', + 'tapestry-core:testWithPrototypeAndRequireJsEnabled', + subprojects.check, // jQuery and Require.js enabled + combinedJacocoReport + ] + // tapestry-javadoc doesn't work with Java 8 anymore. That's why it's only added if != 8. if (JavaVersion.current() != JavaVersion.VERSION_1_8) { dependants << aggregateJavadoc } - dependsOn dependants - description "Task executed on Jenkins CI server after Git commits" + + dependsOn(dependants) } -task zippedSources(type: Zip) { - description "Creates a combined Zip file of all sub-project's sources" - group "Release artifact" + +tasks.register('zippedSources', Zip) { + group = 'Release artifact' + description = "Creates a combined Zip file of all sub-project's sources" - dependsOn("tapestry-core:compileTypeScript") + dependsOn 'tapestry-core:compileTypeScript' - destinationDirectory = buildDir - archiveBaseName = "apache-tapestry" + destinationDirectory = layout.buildDirectory + archiveBaseName = 'apache-tapestry' version project.version - archiveClassifier = "sources" + archiveClassifier = 'sources' from project.projectDir - exclude "out/**" - exclude "**/*.iml" - exclude "**/*.ipr" - exclude "**/*.iws" - exclude "**/.*/**" - exclude "**/bin/**" - exclude "**/target/**" - exclude "**/build/**" - exclude "**/test-output/**" // Left around by TestNG sometimes - exclude "**/modules/***.js" - exclude "**/es-modules/***.js" + exclude 'out/**' + exclude '**/*.iml' + exclude '**/*.ipr' + exclude '**/*.iws' + exclude '**/.*/**' + exclude '**/bin/**' + exclude '**/target/**' + exclude '**/build/**' + exclude '**/test-output/**' // Left around by TestNG sometime + exclude '**/modules/***.js' + exclude '**/es-modules/***.js' } -task zippedApidoc(type: Zip) { +tasks.register('zippedApidoc', Zip) { + group = 'Release artifact' + description = "Zip archive of the project's aggregate JavaDoc and TypeScript documentation" + dependsOn typeScriptDocs dependsOn aggregateJavadoc - description "Zip archive of the project's aggregate JavaDoc and TypeScript documentation" - group "Release artifact" - destinationDirectory = buildDir - archiveBaseName = "apache-tapestry" + destinationDirectory = layout.buildDirectory + archiveBaseName = 'apache-tapestry' version project.version - archiveClassifier = "apidocs" + archiveClassifier = 'apidocs' - from file("src/docroot-template"), { + from(file('src/docroot-template')) { filter ReplaceTokens, tokens: [version: project.version] - include "*.html" + include '*.html' } - from file("src/docroot-template"), { - exclude "*.html" + from(file('src/docroot-template')) { + exclude '*.html' } - into "apidocs", { from aggregateJavadoc.outputs.files } - - - into "typescript", { from typeScriptDocs.outputs.files } + into('apidocs') { + from aggregateJavadoc.outputs.files + } + into('typescript') { + from typeScriptDocs.outputs.files + } } -task zippedBinaries(type: Zip) { - description "Zip archive of binaries of each sub-project" +tasks.register('zippedBinaries', Zip) { + group 'Release artifact' + description 'Zip archive of binaries of each sub-project' + // TODO: Plus dependencies? - group "Release artifact" // This may create a few unwanted dependencies, but does // seem to ensure that the subprojects are created inputs.files subprojects*.configurations*.archives.artifacts.files - destinationDirectory = buildDir - archiveBaseName = "apache-tapestry" + destinationDirectory = layout.buildDirectory + archiveBaseName = 'apache-tapestry' version project.version - archiveClassifier = "bin" + archiveClassifier = 'bin' // This is via some experimentation from subprojects*.configurations*.archives.artifacts*.file*.findAll { - !(it.name.endsWith(".asc") || it.name.startsWith("quickstart")) + !(it.name.endsWith('.asc') || it.name.startsWith('quickstart')) } from configurations.binaries @@ -622,12 +456,12 @@ task zippedBinaries(type: Zip) { // Pick up various licenses and notices from(projectDir) { - include "*.txt" + include '*.txt' } subprojects.each { sub -> from(sub.projectDir) { - include "*.txt" + include '*.txt' into sub.name } } @@ -649,25 +483,19 @@ if (canDeploy) { upload.extendsFrom archives, signatures } - task generateMD5Checksums(type: GenMD5) { - group "Release artifact" - description "Creates MD5 checksums for archives of source and JavaDoc" - source tasks.withType(Zip) - outputDir "$buildDir/md5" - } + tasks.register('generateChecksums', GenerateChecksums) { + group 'Release artifact' + description 'Creates MD5/SHA256 checksums for archives of source and JavaDoc' - task generateSHA256Checksums(type: GenSHA256) { - group "Release artifact" - description "Creates SHA-256 checksums for archives of source and JavaDoc" source tasks.withType(Zip) - outputDir "$buildDir/sha256" + outputDir = layout.buildDirectory.dir('checksums') } // This requires that you have the apacheArchivesFolder property configured in your // ~/.gradle/gradle.properties. The folder should be a Subversion workspace for // https://dist.apache.org/repos/dist/dev/tapestry - // after the build, you must manually add the new files to the workspace (using "svn add") - // then commit ("svn commit"). + // after the build, you must manually add the new files to the workspace (using 'svn add') + // then commit ('svn commit'). // The files will be visible in https://dist.apache.org/repos/dist/dev/tapestry/, allowing // committers to download and verify them. @@ -677,75 +505,71 @@ if (canDeploy) { // there will publish them to http://www.apache.org/dist/tapestry ... and from there // to all Apache mirrors (after about a 24 hour delay). - task copyArchives(type: Copy) { - group "Release artifact" - description "Copies build archives (source, bin, docs) to a configured deployment folder, along with MD5 and SHA-256 checksums and PGP signatures (if signing is enabled)" + tasks.register('copyArchives', Copy) { + group 'Release artifact' + description 'Copies build archives (source, bin, docs) to a configured deployment folder, along with MD5 and SHA-256 checksums and PGP signatures (if signing is enabled)' - destinationDir file(archiveDeployFolder()) + destinationDirectory = file(archiveDeployFolder.get()) - from generateMD5Checksums - from generateSHA256Checksums + from tasks.generateChecksums from configurations.uploads.allArtifacts.files } - task generateRelease { + tasks.register('generateRelease') { + group 'Release artifact' + description 'Generates and uploads a final release to Apache Nexus and copies archives for deployment' + dependsOn subprojects.assemble, subprojects.uploadPublished, subprojects.publish, copyArchives - group "Release artifact" - description "Generates and uploads a final release to Apache Nexus and copies archives for deployment" } } -boolean isSnapshot() { - project.version.contains("SNAPSHOT") -} +tasks.register('updateBootstrap') { + group = 'Maintenance' + description = 'Updates the included Bootstrap dependencies from GitHub' -boolean isWindows() { - System.properties['os.name'].toLowerCase().contains('windows') -} + doLast { + def bootstrapVersion = '3.3.7' + def target = new File(temporaryDir, 'bootstrap.zip') + ant.get(src: "https://github.com/twbs/bootstrap/archive/v${bootstrapVersion}.zip", dest: target) + + def adjustDirectory = { + def relativePath = it.relativePath + if (relativePath.pathString.contains('/dist/')){ + relativePath = new RelativePath(!it.file.isDirectory(), relativePath.segments[2..-1] as String[]) + } else { + relativePath = new RelativePath(!it.file.isDirectory(), relativePath.segments[1..-1] as String[]) + } + println "copying ${it.relativePath} to ${relativePath}" + it.relativePath = relativePath + } + + copy { + from(zipTree(target)){ + include('*/js/*.js') + include('*/dist/fonts/*') + eachFile adjustDirectory + } + from(zipTree(target)){ + include('*/dist/css/bootstrap.css') + include('*/dist/css/bootstrap-theme.css') + eachFile adjustDirectory + // TAP5-2351: remove source map reference from css files + filter({ + (it ==~ /\/\*\s*# sourceMappingURL=[\S]+\s*\*\//) ? '' : it + }) + } + into('tapestry-core/src/main/resources/META-INF/assets/tapestry5/bootstrap/') + } -task updateBootstrap { - doLast { - def bootstrapVersion = '3.3.7' - def target = new File(temporaryDir, 'bootstrap.zip') - ant.get(src: "https://github.com/twbs/bootstrap/archive/v${bootstrapVersion}.zip", dest: target) - - def adjustDirectory = { - def relativePath = it.relativePath - if (relativePath.pathString.contains('/dist/')){ - relativePath = new RelativePath(!it.file.isDirectory(), relativePath.segments[2..-1] as String[]) - } else { - relativePath = new RelativePath(!it.file.isDirectory(), relativePath.segments[1..-1] as String[]) - } - println "copying $it.relativePath to $relativePath" - it.relativePath = relativePath - - } - - copy { - from(zipTree(target)){ - include('*/js/*.js') - include('*/dist/fonts/*') - eachFile adjustDirectory - } - from(zipTree(target)){ - include('*/dist/css/bootstrap.css') - include('*/dist/css/bootstrap-theme.css') - eachFile adjustDirectory - // TAP5-2351: remove source map reference from css files - filter({ (it ==~ /\/\*\s*# sourceMappingURL=[\S]+\s*\*\//) ? "" : it }) - } - into('tapestry-core/src/main/resources/META-INF/assets/tapestry5/bootstrap/') - } - - copy { - from(zipTree(target)){ - include('*/js/*.js') - include('*/dist/fonts/*') - include('*/less/**/*.less') - - eachFile adjustDirectory - } - into('tapestry-webresources/src/test/webapp/bootstrap/') - } - } + copy { + from(zipTree(target)){ + include('*/js/*.js') + include('*/dist/fonts/*') + include('*/less/**/*.less') + + eachFile adjustDirectory + } + into('tapestry-webresources/src/test/webapp/bootstrap/') + } + } } diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle new file mode 100644 index 000000000..a4c2a3726 --- /dev/null +++ b/buildSrc/build.gradle @@ -0,0 +1,20 @@ +plugins { + id 'groovy-gradle-plugin' +} + +repositories { + gradlePluginPortal() +} + +dependencies { + implementation('ro.isdc.wro4j:wro4j-extensions:1.8.0') { + exclude group: 'org.jruby' + exclude module: 'spring-web' + exclude module: 'closure-compiler' + exclude module: 'gmaven-runtime-1.7' + exclude module: 'less4j' + } + implementation 'org.apache.ant:ant-jsch:1.8.2' + + gradleApi() +} diff --git a/buildSrc/src/main/groovy/t5build/GenerateChecksums.groovy b/buildSrc/src/main/groovy/t5build/GenerateChecksums.groovy new file mode 100644 index 000000000..dd9f9997f --- /dev/null +++ b/buildSrc/src/main/groovy/t5build/GenerateChecksums.groovy @@ -0,0 +1,61 @@ +package t5build + +import org.gradle.api.DefaultTask +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.SourceTask +import org.gradle.api.file.ConfigurableFileCollection + +import java.security.MessageDigest + +class GenerateChecksums extends SourceTask { + + enum Algorithm { + MD5('MD5', 32, 'md5'), + SHA256('SHA-256', 64, 'sha256') + + final String name + final int padding + final String extension + + Algorithm(String name, int padding, String extension) { + this.name = name + this.padding = padding + this.extension = extension + } + } + + @OutputDirectory + File outputDir + + + @TaskAction + void generate() { + source.each { file -> + // Create a map of MessageDigest instances, one for each algorithm, + // so it's easier to update them and use later + def digests = Algorithm.values().collectEntries { alg -> + [(alg): MessageDigest.getInstance(alg.name)] + } + + // use inputstream so to avoid loading whole file into memory + file.withInputStream { is -> + byte[] buffer = new byte[8192] + int bytesRead + while ((bytesRead = is.read(buffer)) != -1) { + digests.values().each { digest -> + digest.update(buffer, 0, bytesRead) + } + } + } + + // Write checksum files + digests.each { algo, digest -> + def checksum = new BigInteger(1, digest.digest()).toString(16).padLeft(algo.padding, '0') + new File(outputDir, "${file.name}.${algo.extension}").text = checksum + } + } + } +} diff --git a/buildSrc/src/main/groovy/t5build/SSshExec.groovy b/buildSrc/src/main/groovy/t5build/SSshExec.groovy new file mode 100644 index 000000000..e985b4591 --- /dev/null +++ b/buildSrc/src/main/groovy/t5build/SSshExec.groovy @@ -0,0 +1,21 @@ +package t5build + +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction + +class SshExec extends SshTask { + + @Input + List<String[]> commandLines = [] + + void commandLine(String... commandLine) { + commandLines << commandLine + } + + @TaskAction + void doActions() { + commandLines.each { commandLine -> + ssh(*commandLine) + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/groovy/t5build/Scp.groovy b/buildSrc/src/main/groovy/t5build/Scp.groovy new file mode 100644 index 000000000..3280cfb9d --- /dev/null +++ b/buildSrc/src/main/groovy/t5build/Scp.groovy @@ -0,0 +1,36 @@ +package t5build + +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.SkipWhenEmpty +import org.gradle.api.tasks.TaskAction +import java.io.File + +class Scp extends SshTask { + + @InputFiles @SkipWhenEmpty + def source + + @Input + String destination + + @Input + boolean isDir = false + + @TaskAction + void doActions() { + if (isDir) { + scpDir(source, destination) + return + } + project.files(source).each { doFile(it) } + } + + private void doFile(File file) { + if (file.isDirectory()) { + file.eachFile { doFile(it) } + } else { + scpFile(file, destination) + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/groovy/t5build/SshTask.groovy b/buildSrc/src/main/groovy/t5build/SshTask.groovy new file mode 100644 index 000000000..769b32adf --- /dev/null +++ b/buildSrc/src/main/groovy/t5build/SshTask.groovy @@ -0,0 +1,94 @@ +package t5build + +import org.gradle.api.DefaultTask +import org.gradle.api.file.FileCollection +import org.gradle.api.logging.LogLevel +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal + +abstract class SshTask extends DefaultTask { + + @InputFiles + FileCollection sshAntClasspath + + @Input + String host + + @Input + String userName + + // TODO: Passwords should not be plain @Input. + @Input + String password + + @Input + boolean verbose = false + + private boolean antInited = false + + protected void initAnt() { + if (antInited) { + return + } + ant.taskdef(name: 'scp', + classname: 'org.apache.tools.ant.taskdefs.optional.ssh.Scp', + classpath: sshAntClasspath.asPath, + loaderref: 'ssh') + + ant.taskdef(name: 'sshexec', + classname: 'org.apache.tools.ant.taskdefs.optional.ssh.SSHExec', + classpath: sshAntClasspath.asPath, + loaderref: 'ssh') + antInited = true + } + + protected void withInfoLogging(Closure action) { + def oldLogLevel = getLogging().getLevel() + getLogging().setLevel([LogLevel.INFO, oldLogLevel].min()) + try { + action() + } finally { + if (oldLogLevel != null) { + getLogging().setLevel(oldLogLevel) + } + } + } + + protected void scpFile(Object source, String destination) { + initAnt() + withInfoLogging { + // TODO: This keyfile is hardcoded and uses an old algorithm (dsa) + ant.scp(localFile: project.files(source).singleFile, + remoteToFile: "${userName}@${host}:${destination}", + keyfile: "${System.properties['user.home']}/.ssh/id_dsa", + verbose: verbose) + } + } + + protected void scpDir(Object source, String destination) { + initAnt() + withInfoLogging { + ant.sshexec(host: host, + username: userName, + password: password, + command: "mkdir -p ${destination}") + + ant.scp(remoteTodir: "${userName}@${host}:${destination}", + keyfile: "${System.properties['user.home']}/.ssh/id_dsa", + verbose: verbose) { + project.files(source).addToAntBuilder(ant, 'fileSet', FileCollection.AntType.FileSet) + } + } + } + + protected void ssh(Object... commandLine) { + initAnt() + withInfoLogging { + ant.sshexec(host: host, + username: userName, + password: password, + command: commandLine.join(' ')) + } + } +} diff --git a/buildSrc/src/main/groovy/t5build/TapestryBuildLogic.groovy b/buildSrc/src/main/groovy/t5build/TapestryBuildLogic.groovy new file mode 100644 index 000000000..13f9b935a --- /dev/null +++ b/buildSrc/src/main/groovy/t5build/TapestryBuildLogic.groovy @@ -0,0 +1,22 @@ +package t5build + +import org.gradle.api.Project + +class TapestryBuildLogic { + + static boolean isSnapshot(Project project) { + return tapestryVersion(project).endsWith('SNAPSHOT') + } + + static boolean isWindows() { + return System.properties['os.name'].toLowerCase().contains('windows') + } + + static String tapestryVersion(Project project) { + String major = project.rootProject.ext.tapestryMajorVersion + String minor = project.rootProject.ext.tapestryMinorVersion + + boolean isCiBuild = project.rootProject.hasProperty('continuousIntegrationBuild') && project.rootProject.continuousIntegrationBuild + return isCiBuild ? major + '-SNAPSHOT' : major + minor + } +} \ No newline at end of file diff --git a/buildSrc/src/main/groovy/tapestry.java-convention.gradle b/buildSrc/src/main/groovy/tapestry.java-convention.gradle new file mode 100644 index 000000000..b94a82142 --- /dev/null +++ b/buildSrc/src/main/groovy/tapestry.java-convention.gradle @@ -0,0 +1,66 @@ +plugins { + id 'java-library' + id 'eclipse' + id 'idea' + id 'groovy' +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + + withSourcesJar() +} + +configurations { + provided + meta +} + +// Ensure the 'provided' dependencies are available on the compile classpaths. +sourceSets { + main.compileClasspath += configurations.provided + test.compileClasspath += configurations.provided + test.runtimeClasspath += configurations.provided +} + +// Ensure IDEs understand the 'provided' configuration and more IDE setup +idea { + module { + scopes.PROVIDED.plus += [configurations.provided] + } +} +eclipse.classpath.plusConfigurations += [configurations.provided] + + +// Enforce consistent dependency versions across all modules using constraints. +// This prevents multiple versions of the same library from appearing in the classpath. +// The versions themselves are defined in `gradle/libs.versions.toml`. +dependencies { + constraints { + implementation libs.cglib.nodep + implementation libs.commons.codec + implementation libs.commons.io + implementation libs.commons.logging + implementation("${libs.hsqldb.get().module.group}:${libs.hsqldb.get().module.name}:${libs.hsqldb.get().version}:jdk8") + implementation libs.hamcrest.core + implementation libs.json + implementation libs.snakeyaml + implementation libs.xml.apis + } +} + +tasks.withType(Jar).configureEach { + // Include license/notice files in the final JAR. + from(project.projectDir) { + include '*.txt' + into 'META-INF' + } + + // JPMS compatibility + manifest { + attributes("Automatic-Module-Name": "org.apache.tapestry.${project.name}" + .replace('tapestry-', '') + .replace('-', '.')) + } +} diff --git a/buildSrc/src/main/groovy/tapestry.junit4-legacy-convention.gradle b/buildSrc/src/main/groovy/tapestry.junit4-legacy-convention.gradle new file mode 100644 index 000000000..436efdc53 --- /dev/null +++ b/buildSrc/src/main/groovy/tapestry.junit4-legacy-convention.gradle @@ -0,0 +1,12 @@ +plugins { + id 'tapestry.testing-base-convention' +} + +dependencies { + testImplementation libs.junit4 + testImplementation libs.hamcrest.core +} + +tasks.withType(Test).configureEach { + useJUnit() +} diff --git a/buildSrc/src/main/groovy/tapestry.junit5-convention.gradle b/buildSrc/src/main/groovy/tapestry.junit5-convention.gradle new file mode 100644 index 000000000..0d2bf88de --- /dev/null +++ b/buildSrc/src/main/groovy/tapestry.junit5-convention.gradle @@ -0,0 +1,13 @@ +plugins { + id 'tapestry.testing-base-convention' +} + +dependencies { + testImplementation platform(libs.junit.bom) + testImplementation libs.bundles.junit.jupiter.essentials + testRuntimeOnly libs.junit.jupiter.engine +} + +tasks.withType(Test).configureEach { + useJUnitPlatform() +} diff --git a/buildSrc/src/main/groovy/tapestry.junit5-spock-convention.gradle b/buildSrc/src/main/groovy/tapestry.junit5-spock-convention.gradle new file mode 100644 index 000000000..3f58f33c0 --- /dev/null +++ b/buildSrc/src/main/groovy/tapestry.junit5-spock-convention.gradle @@ -0,0 +1,9 @@ +plugins { + id 'tapestry.junit5-convention' + id 'groovy' +} + +dependencies { + testImplementation platform(libs.spock.bom) + testImplementation libs.spock.core +} diff --git a/buildSrc/src/main/groovy/tapestry.ssh-convention.gradle b/buildSrc/src/main/groovy/tapestry.ssh-convention.gradle new file mode 100644 index 000000000..2f6aa7c8a --- /dev/null +++ b/buildSrc/src/main/groovy/tapestry.ssh-convention.gradle @@ -0,0 +1,15 @@ +import t5build.SshTask + +// This configuration will hold the ant-jsch.jar at runtime +configurations { + sshAntTask +} + +dependencies { + sshAntTask libs.ant.jsch +} + +// Configure all SshTask instances to use the files from the configuration +tasks.withType(SshTask).configureEach { + it.sshAntClasspath = configurations.sshAntTask +} diff --git a/buildSrc/src/main/groovy/tapestry.testing-base-convention.gradle b/buildSrc/src/main/groovy/tapestry.testing-base-convention.gradle new file mode 100644 index 000000000..7a3efcd79 --- /dev/null +++ b/buildSrc/src/main/groovy/tapestry.testing-base-convention.gradle @@ -0,0 +1,64 @@ +plugins { + id 'java-library' +} + +dependencies { + testRuntimeOnly libs.slf4j.simple +} + +tasks.withType(Test).configureEach { testTask -> + maxHeapSize = '600M' + + systemProperties['tapestry.service-reloading-enabled'] = 'false' + systemProperties['java.io.tmpdir'] = temporaryDir.absolutePath + + jvmArgs '-Dfile.encoding=UTF-8' + environment.LANG = 'en_US.UTF-8' + + // TAP5-2722 + systemProperty 'user.language', 'en' + + testLogging { + exceptionFormat 'full' + events 'passed', 'skipped', 'failed' + showStandardStreams = true + } + + def total = 0, passed = 0, failed = 0, skipped = 0 + + afterTest { descriptor, result -> + switch (result.resultType) { + case org.gradle.api.tasks.testing.TestResult.ResultType.SUCCESS: + passed++ + break + case org.gradle.api.tasks.testing.TestResult.ResultType.FAILURE: + failed++ + break + case org.gradle.api.tasks.testing.TestResult.ResultType.SKIPPED: + skipped++ + break + } + total++ + if (total % 25 == 0) { + logger.lifecycle "Project ${project.name}: Tests run: ${total}, Passed: ${passed}, Failed: ${failed}, Skipped: ${skipped}" + } + } + + afterSuite { descriptor, result -> + // The root suite has a null parent. We only want to log the final summary. + if (descriptor.parent == null) { + total = passed + failed + skipped + // Using project.path gives a clear identifier like ":tapestry-core" + def projectName = project.path + + // Don't log if no tests were run + if (total > 0) { + logger.lifecycle "------------------------------------------------------------------------" + logger.lifecycle "Test Results for ${projectName}" + logger.lifecycle " Tests run: ${total}, Passed: ${passed}, Failed: ${failed}, Skipped: ${skipped}" + logger.lifecycle "------------------------------------------------------------------------" + } + } + } +} + diff --git a/buildSrc/src/main/groovy/tapestry.testng-convention.gradle b/buildSrc/src/main/groovy/tapestry.testng-convention.gradle new file mode 100644 index 000000000..90dac3640 --- /dev/null +++ b/buildSrc/src/main/groovy/tapestry.testng-convention.gradle @@ -0,0 +1,27 @@ +plugins { + id 'tapestry.testing-base-convention' +} + +dependencies { + testImplementation libs.testng + testImplementation libs.easymock + testImplementation libs.hamcrest.core +} + +tasks.withType(Test).configureEach { testTask -> + + def suiteFile = [ + 'src/test/resources/testng.xml', + 'src/test/conf/testng.xml' + ].find { path -> + project.file(path).exists() + } + + if (suiteFile) { + testTask.useTestNG { + suites suiteFile + } + } else { + testTask.useTestNG() + } +} diff --git a/commons/build.gradle b/commons/build.gradle index 99cb1d4d9..ecc9bf194 100644 --- a/commons/build.gradle +++ b/commons/build.gradle @@ -1,24 +1,12 @@ -import org.gradle.plugins.ide.idea.model.* -import t5build.* - -description = "Project including common classes for tapestry-core, tapestry-ioc and beanmodel." +plugins { + id 'tapestry.junit5-spock-convention' +} -//apply plugin: JavaPlugin +description = 'Project including common classes for tapestry-core, tapestry-ioc and beanmodel.' -buildDir = 'target/gradle-build' - dependencies { - api project(":plastic") - api project(":tapestry5-annotations") - implementation project(":tapestry-func") - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" -} + api project(':plastic') + api project(':tapestry5-annotations') -jar { - manifest { - } + implementation project(':tapestry-func') } - -test { - useJUnit() -} \ No newline at end of file diff --git a/genericsresolver-guava/build.gradle b/genericsresolver-guava/build.gradle index a20be0d48..90892270a 100644 --- a/genericsresolver-guava/build.gradle +++ b/genericsresolver-guava/build.gradle @@ -1,9 +1,13 @@ +plugins { + id 'tapestry.testng-convention' +} description = "Replaces the Tapestry Commons's own Java Generics resolution code with the one from Google Guava's one" dependencies { - implementation project(':commons') - testImplementation project(':tapestry-core') - testImplementation project(':tapestry-test') - provided implementation ('com.google.guava:guava:27.0.1-jre') - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" -} \ No newline at end of file + implementation project(':commons') + + provided libs.guava + + testImplementation project(':tapestry-core') + testImplementation project(':tapestry-test') +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..b0055439f --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,168 @@ +[versions] + +# LOGGING + +slf4j = "1.7.25" + +# JAVAX/JAKARTA + +javax-inject = "1" +javax-servlet-api = "3.0.1" +javax-validation-api = "1.0.0.GA" + +jakarta-annotation-api = "1.3.4" +jakarta-persistence-api = "3.0.0" +jakarta-xml-bind-api = "2.3.2" + +# APACHE COMMONS + +commons-cli = "1.2" +commons-codec = "1.18.0" +commons-httpclient = "4.1" +commons-io = "2.19.0" +commons-lang3 = "3.17.0" +commons-logging = "1.3.5" +commons-text = "1.13.1" + +# HIBERNATE + +hibernate = "5.4.32.Final" +hibernate-validator = "4.3.2.Final" + +hsqldb = "2.7.3" + +# ANTLR + +antlr = "3.5.3" + +# MISC + +snakeyaml = "2.3" +cglib = "2.2" +hamcrest-core = "1.3" +json = "20140107" +xml-apis = "1.4.01" +guice = "3.0" +ant-jsch = "1.8.2" +guava = "27.0.1-jre" +jackson = "2.13.1" +clojure = "1.6.0" +httpcomponents-httpclient = "4.5.14" + +# TESTING + +slf4j-simple = "2.0.17" +junit5 = "5.10.2" +junit4 = "4.13.2" +testng = "7.5.1" +easymock = "5.4.0" +spock = "2.3-groovy-3.0" +geb = "2.0" +webdrivermanager = "5.3.1" +selenium = "4.5.0" +selenium-java = "4.12.1" +selenium-server = "4.12.1" + +# QUICKSTART + +quickstart-spring-boot = "2.5.4" +quickstart-json = "1.1.4" +quickstart-log4j = "2.17.2" +quickstart-yasson = "2.0.4" +quickstart-maven-compiler = "3.8.1" +quickstart-maven-surefire = "3.1" +quickstart-maven-war = "3.3.1" +quickstart-maven-jetty = "10.0.6" +quickstart-gretty = "3.0.6" + +[libraries] + +# LOGGING + +slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } +slf4j-log4j12 = { module = "org.slf4j:slf4j-log4j12", version.ref = "slf4j" } + +# JAVAX/JAKARTA + +javax-inject = { module = "javax.inject:javax.inject", version.ref = "javax-inject" } +javax-servlet-api = { module = "javax.servlet:javax.servlet-api", version.ref = "javax-servlet-api" } +javax-validation-api = { module = "javax.validation:validation-api", version.ref = "javax-validation-api" } + +jakarta-annotation-api = { module = "jakarta.annotation:jakarta.annotation-api", version.ref = "jakarta-annotation-api" } +jakarta-persistence-api = { module = "jakarta.persistence:jakarta.persistence-api", version.ref = "jakarta-persistence-api" } +jakarta-xml-bind-api = { module = "jakarta.xml.bind:jakarta.xml.bind-api", version.ref = "jakarta-xml-bind-api" } + +# APACHE COMMONS + +commons-cli = { module = "commons-cli:commons-cli", version.ref = "commons-cli" } +commons-codec = { module = "commons-codec:commons-codec", version.ref = "commons-codec" } +commons-httpclient = { module = "commons-httpclient:commons-httpclient", version.ref = "commons-httpclient" } +commons-io = { module = "commons-io:commons-io", version.ref = "commons-io" } +commons-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "commons-lang3" } +commons-logging = { module = "commons-logging:commons-logging", version.ref = "commons-logging" } +commons-text = { module = "org.apache.commons:commons-text", version.ref = "commons-text" } + +# HIBERNATE + +hibernate-core = { module = "org.hibernate:hibernate-core", version.ref = "hibernate" } +hibernate-validator = { module = "org.hibernate:hibernate-validator", version.ref = "hibernate-validator" } + +hsqldb = { module = "org.hsqldb:hsqldb", version.ref = "hsqldb" } + +# ANTLR + +antlr = { module = "org.antlr:antlr", version.ref = "antlr" } +antlr-runtime = { module = "org.antlr:antlr-runtime", version.ref = "antlr" } + +# MISC + +snakeyaml = { module = "org.yaml:snakeyaml", version.ref = "snakeyaml" } +cglib-nodep = { module = "cglib:cglib-nodep", version.ref = "cglib" } +hamcrest-core = { module = "org.hamcrest:hamcrest-core", version.ref = "hamcrest-core" } +json = { module = "org.json:json", version.ref = "json" } +xml-apis = { module = "xml-apis:xml-apis", version.ref = "xml-apis" } +guice = { module = "com.google.inject:guice", version.ref = "guice" } +ant-jsch = { module = "org.apache.ant:ant-jsch", version.ref = "ant-jsch" } +guava = { module = "com.google.guava:guava", version.ref = "guava" } +clojure = { module = "org.clojure:clojure", version.ref = "clojure" } +httpcomponents-httpclient = { module = "org.apache.httpcomponents:httpclient", version.ref = "httpcomponents-httpclient" } + +# JACKSON + +jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" } + +# TESTING + +slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j-simple" } + +junit-bom = { module = "org.junit:junit-bom", version.ref = "junit5" } +junit-jupiter = { module = "org.junit.jupiter:junit-jupiter"} +junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api" } +junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params" } +junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine" } + +junit4 = { module = "junit:junit", version.ref = "junit4" } + +testng = { module = "org.testng:testng", version.ref = "testng" } + +easymock = { module = "org.easymock:easymock", version.ref = "easymock" } + +spock-bom = { module = "org.spockframework:spock-bom", version.ref = "spock" } +spock-core = { module = "org.spockframework:spock-core" } + +geb-spock = { module = "org.gebish:geb-spock", version.ref = "geb" } + +selenium-legrc = { module = "org.seleniumhq.selenium:selenium-leg-rc", version.ref = "selenium" } +selenium-api = { module = "org.seleniumhq.selenium:selenium-api", version.ref = "selenium" } +selenium-java = { module = "org.seleniumhq.selenium:selenium-java", version.ref = "selenium-java" } +selenium-server = { module = "org.seleniumhq.selenium:selenium-server", version.ref = "selenium-server" } + +webdrivermanager = { module = "io.github.bonigarcia:webdrivermanager", version.ref = "webdrivermanager" } + + +[bundles] + +junit-jupiter-essentials = [ + "junit-jupiter-api", + "junit-jupiter-params" +] diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927a4..d64cd4917 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a59520664..ff23a68d7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c78733..1aa94a426 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -205,6 +214,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f93..6689b85be 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/plastic/build.gradle b/plastic/build.gradle index f5bdee139..35f5d8103 100644 --- a/plastic/build.gradle +++ b/plastic/build.gradle @@ -1,15 +1,18 @@ -description = "High-level runtime transformations of Java classes" +plugins { + id 'tapestry.junit5-spock-convention' +} + +description = 'High-level runtime transformations of Java classes' dependencies { - implementation "org.slf4j:slf4j-api:${versions.slf4j}" - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" + implementation libs.slf4j.api } -test { - useJUnit() +// add vendored ASM +sourceSets { + main { + java { + srcDir 'src/external/java' + } + } } - -// Add the source directory for the imported/repackaged ASM 7.0.1 code - -sourceSets.main.java.srcDir "src/external/java" - diff --git a/quickstart/build.gradle b/quickstart/build.gradle index 98225bf97..a88fe8054 100644 --- a/quickstart/build.gradle +++ b/quickstart/build.gradle @@ -50,18 +50,18 @@ task processFiltered(type: Copy) { filter(ReplaceTokens, tokens: [ quickstartVersion: project.parent.version, tapestryVersion: project.parent.version, - springBootVersion: '2.5.4', - junitVersion: '5.8.2', - jacksonVersion: '2.13.1', - jsonVersion: '1.1.4', - log4jVersion: '2.17.2', - yassonVersion: '2.0.4', - servletVersion: '3.1.0', - mavenCompilerVersion: '3.8.1', - mavenSurefireVersion: '3.0.0-M5', - mavenWarVersion: '3.3.1', - mavenJettyVersion: '10.0.6', - grettyVersion: '3.0.6' + springBootVersion: libs.versions.quickstart.spring.boot.get(), + junitVersion: libs.versions.junit5.get(), + jacksonVersion: libs.versions.jackson.get(), + jsonVersion: libs.versions.quickstart.json.get(), + log4jVersion: libs.versions.quickstart.log4j.get(), + yassonVersion: libs.versions.quickstart.yasson.get(), + servletVersion: libs.versions.javax.servlet.api.get(), + mavenCompilerVersion: libs.versions.quickstart.maven.compiler.get(), + mavenSurefireVersion: libs.versions.quickstart.maven.surefire.get(), + mavenWarVersion: libs.versions.quickstart.maven.war.get(), + mavenJettyVersion: libs.versions.quickstart.maven.jetty.get(), + grettyVersion: libs.versions.quickstart.gretty.get() ]) } diff --git a/settings.gradle b/settings.gradle index 58d041ac8..5f4f20356 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,20 +3,83 @@ plugins { id 'com.gradle.common-custom-user-data-gradle-plugin' version '2.0.2' } +rootProject.name = 'tapestry-5' + +dependencyResolutionManagement { + repositories { + mavenLocal() + mavenCentral() + maven { + name = 'JBoss' + url = 'https://repository.jboss.org/nexus/content/repositories/releases/' + } + maven { + // tapestry-jpa + name = 'EclipseLink' + url = 'https://download.eclipse.org/rt/eclipselink/maven.repo/' + } + } +} + +include('plastic', + 'tapestry5-annotations', + 'tapestry-test', + 'tapestry-func', + 'tapestry-ioc', + 'tapestry-json', + 'tapestry-http', + 'tapestry-core', + 'tapestry-hibernate-core', + 'tapestry-hibernate', + 'tapestry-jmx', + 'tapestry-upload', + 'tapestry-beanvalidator', + 'tapestry-jpa', + 'tapestry-kaptcha', + 'quickstart', + 'tapestry-clojure', + 'tapestry-mongodb', + 'tapestry-test-data', + 'tapestry-internal-test', + 'tapestry-ioc-junit', + 'tapestry-webresources', + 'tapestry-runner', + 'tapestry-test-constants', + 'tapestry-ioc-jcache', + 'beanmodel', + 'commons', + 'genericsresolver-guava', + 'tapestry-version-migrator', + 'tapestry-spock', + 'tapestry-openapi-viewer', + 'tapestry-rest-jackson') + +if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_11)) { + include('tapestry-javadoc') +} + +if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) { + include('tapestry-latest-java-tests', 'tapestry-spring') +} + def isTravisCI = System.getenv('TRAVIS_JOB_ID') != null def isJenkins = System.getenv('JENKINS_URL') != null def isCI = isTravisCI || isJenkins develocity { - server = "https://develocity.apache.org" - projectId = "tapestry" + server = 'https://develocity.apache.org' + projectId = 'tapestry' buildScan { uploadInBackground = !isCI publishing.onlyIf { it.authenticated } obfuscation { // This obfuscates the IP addresses of the build machine in the build scan. // Alternatively, the build scan will provide the hostname for troubleshooting host-specific issues. - ipAddresses { addresses -> addresses.collect { address -> "0.0.0.0"} } + ipAddresses { addresses -> + addresses.collect { address -> + '0.0.0.0' + } + } } } } @@ -30,21 +93,3 @@ buildCache { enabled = false } } - -rootProject.name = "tapestry-5" - -include "plastic", "tapestry5-annotations", "tapestry-test", "tapestry-func", "tapestry-ioc", "tapestry-json", "tapestry-http", "tapestry-core" -include "tapestry-hibernate-core", "tapestry-hibernate", "tapestry-jmx", "tapestry-upload", "tapestry-spring" -include "tapestry-beanvalidator", "tapestry-jpa", "tapestry-kaptcha" -if (JavaVersion.current() != JavaVersion.VERSION_1_8) { - include "tapestry-javadoc" -} -if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) { - include "tapestry-latest-java-tests" -} -include "quickstart", "tapestry-clojure", "tapestry-mongodb" -include "tapestry-test-data", 'tapestry-internal-test', "tapestry-ioc-junit" -include "tapestry-webresources", "tapestry-runner", "tapestry-test-constants" -include "tapestry-ioc-jcache", "beanmodel", "commons", "genericsresolver-guava", "tapestry-version-migrator" -// include "tapestry-cdi" -include "tapestry-spock", "tapestry-openapi-viewer", "tapestry-rest-jackson" diff --git a/sha256.gradle b/sha256.gradle deleted file mode 100644 index 8abaec5ff..000000000 --- a/sha256.gradle +++ /dev/null @@ -1,25 +0,0 @@ -import java.security.MessageDigest - -class GenSHA256 extends SourceTask { - - def outputDir - - @OutputDirectory - File getOutputDir() { project.file(outputDir) } - - @TaskAction - void writeSHA256s() { - - source.each { file -> - MessageDigest digest = MessageDigest.getInstance("SHA-256") - - digest.update(file.bytes) - - def checksum = new BigInteger(1, digest.digest()).toString(16).padLeft(32, "0") - - new File(outputDir, file.name + ".sha256").text = checksum - } - } -} - -project.ext.GenSHA256 = GenSHA256.class \ No newline at end of file diff --git a/ssh.gradle b/ssh.gradle deleted file mode 100644 index e367719ce..000000000 --- a/ssh.gradle +++ /dev/null @@ -1,124 +0,0 @@ -project.ext.Scp = Scp.class -project.ext.SshExec = SshExec.class -project.ext.SshTask = SshTask.class - -configurations { - sshAntTask -} - -dependencies { - sshAntTask "org.apache.ant:ant-jsch:1.8.2" -} - -tasks.withType(SshTask) { - sshAntClasspath = configurations.sshAntTask -} - -class SshTask extends DefaultTask { - @InputFiles - FileCollection sshAntClasspath - - @Input - String host - - @Input - String userName - - @Input - String password - - boolean verbose = false - - private boolean antInited = false - - protected initAnt() { - if (!antInited) { - ant.taskdef(name: 'scp', - classname: 'org.apache.tools.ant.taskdefs.optional.ssh.Scp', - classpath: sshAntClasspath.asPath, - loaderref: 'ssh') - ant.taskdef(name: 'sshexec', - classname: 'org.apache.tools.ant.taskdefs.optional.ssh.SSHExec', - classpath: sshAntClasspath.asPath, - loaderref: 'ssh') - antInited = true - } - } - - protected withInfoLogging(Closure action) { - def oldLogLevel = logging.level - logging.level = [LogLevel.INFO, oldLogLevel].min() - try { - action() - } finally { - if (oldLogLevel) { - logging.level = oldLogLevel - } - } - } - - def scpFile(source, destination) { - initAnt() - withInfoLogging { - ant.scp(localFile: project.files(source).singleFile, remoteToFile: "${userName}@${host}:${destination}", keyfile : "${System.properties['user.home']}/.ssh/id_dsa", verbose: verbose) - } - } - - def scpDir(source, destination) { - initAnt() - withInfoLogging { - ant.sshexec(host: host, username: userName, password: password, command: "mkdir -p ${destination}") - ant.scp(remoteTodir: "${userName}@${host}:${destination}", keyfile : "${System.properties['user.home']}/.ssh/id_dsa", verbose: verbose) { - project.files(source).addToAntBuilder(ant, "fileSet", FileCollection.AntType.FileSet) - } - } - } - - def ssh(Object... commandLine) { - initAnt() - withInfoLogging { - ant.sshexec(host: host, username: userName, password: password, command: commandLine.join(' ')) - } - } -} - -class Scp extends SshTask { - @InputFiles @SkipWhenEmpty source - @Input destination - boolean isDir = false - - @TaskAction - void doActions() { - if (isDir) { - scpDir(source, destination) - return - } - - project.files(source).each { doFile(it) } - } - - void doFile(File file) { - - if (file.directory) { - file.eachFile { doFile(it) } - } else { - scpFile(file, destination) - } - } -} - -class SshExec extends SshTask { - @Input - List<String[]> commandLines = [] - - void commandLine(String... commandLine) { - commandLines << commandLine - } - - @TaskAction - void doActions() { - commandLines.each { commandLine -> - ssh(* commandLine) - } - } -} \ No newline at end of file diff --git a/tapestry-beanvalidator/build.gradle b/tapestry-beanvalidator/build.gradle index 82ba5f0b9..b11ffabcd 100644 --- a/tapestry-beanvalidator/build.gradle +++ b/tapestry-beanvalidator/build.gradle @@ -1,28 +1,34 @@ +plugins { + id 'tapestry.testng-convention' +} + import t5build.* -description = "Support for JSR-303 Bean Validation via the Hibernate validator implementation" +description = 'Support for JSR-303 Bean Validation via the Hibernate validator implementation' dependencies { - implementation project(':tapestry-core') - - implementation "javax.validation:validation-api:1.0.0.GA" - implementation "org.hibernate:hibernate-validator:4.3.2.Final" - - testImplementation project(':tapestry-test') - implementation "org.seleniumhq.selenium:selenium-leg-rc:${versions.selenium}", { - exclude group: "org.seleniumhq.selenium", module: "jetty-repacked" - exclude group: "org.testng", module: "testng" - exclude group: "javax.servlet", module: "javax.servlet-api" - } - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" - + implementation project(':tapestry-core') + + implementation libs.javax.validation.api + implementation libs.hibernate.validator + + implementation(libs.selenium.legrc) { + exclude group: 'org.seleniumhq.selenium', module: 'jetty-repacked' + exclude group: 'org.testng', module: 'testng' + } + + testImplementation project(':tapestry-test') } // Start up the test app, useful when debugging failing integration tests -task runTestApp303(type:JavaExec) { - main = 'org.apache.tapestry5.test.JettyRunner' - args "-d", "src/test/webapp", "-p", "8080" - classpath += project.sourceSets.test.runtimeClasspath +tasks.register('runTestApp303', JavaExec) { + mainClass = 'org.apache.tapestry5.test.JettyRunner' + args '-d', 'src/test/webapp', '-p', '8080' + classpath += project.sourceSets.test.runtimeClasspath } -jar.manifest.attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.beanvalidator.modules.BeanValidatorModule' +tasks.named('jar', Jar) { + manifest { + attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.beanvalidator.modules.BeanValidatorModule' + } +} diff --git a/tapestry-cdi/build.gradle b/tapestry-cdi/build.gradle index 2e51bd96c..d40e22e16 100644 --- a/tapestry-cdi/build.gradle +++ b/tapestry-cdi/build.gradle @@ -8,22 +8,20 @@ apply plugin: JavaPlugin buildDir = 'target/gradle-build' project.ext.libraryVersions = [ - javaeeapi: '6.0-4', - tomee: '1.6.0', - ziplock: '1.5.1', - junit: '4.8.1', - commonsHttpclient: '3.1', - arquillian: '1.1.1.Final', - jbossJavaeeSpec: '1.0.0.Final', - arquillianGlassfish: '1.0.0.CR4', - glassfishDistrib: '3.1.1-b04', - jbossDistrib: '7.1.1.Final', - cdi: '1.0-SP4', - jbossAS7: '7.1.1.Final', - shrinkwrapDesc: '2.0.0-alpha-3' + tomee: 'org.apache.openejb:arquillian-tomee-embedded:1.6.0', + ziplock: 'org.apache.openejb:ziplock:1.5.1', + commonsHttpclient: 'commons-httpclient:commons-httpclient:3.1', + arquillianJunitContainer: 'org.jboss.arquillian.junit:arquillian-junit-container:1.1.1.Final', + arquillianGlassfish: 'org.jboss.arquillian.container:arquillian-glassfish-managed-3.1:1.0.0.CR4', + glassfishDistrib: 'org.glassfish.distributions:glassfish:3.1.1-b04@zip', + jbossAS7: 'org.jboss.as:jboss-as-arquillian-container-managed:7.1.1.Final', + jbossDistrib: 'org.jboss.as:jboss-as-dist:7.1.1.Final@zip', + jbossJavaeeSpec: 'org.jboss.spec:jboss-javaee-6.0:1.0.0.Final', + cdiApi: 'jakarta.enterprise:cdi-api:1.0-SP4', + shrinkwrapDescriptorsApi: 'org.jboss.shrinkwrap.descriptors:shrinkwrap-descriptors-api-javaee:2.0.0-alpha-3', + shrinkwrapDescriptorsImpl: 'org.jboss.shrinkwrap.descriptors:shrinkwrap-descriptors-impl-javaee:2.0.0-alpha-3', ] - configurations { compileOnly jboss @@ -36,30 +34,28 @@ configurations { dependencies { compile project(':tapestry-core') compile project(':tapestry-ioc') - testCompile (project(':tapestry-test')){ - transitive = false - } - - // replace javax.enterprise:cdi-api with group: 'org.jboss.spec', name: 'jboss-javaee-6.0', version: libraryVersions.jbossJavaeeSpec to compile against full Java EE API - compileOnly group: 'javax.enterprise', name: 'cdi-api', version: libraryVersions.cdi - - - testCompile group: 'org.apache.openejb', name: 'ziplock', version: libraryVersions.ziplock - testCompile group: 'junit', name: 'junit', version: libraryVersions.junit - testCompile group: 'commons-httpclient', name: 'commons-httpclient', version: libraryVersions.commonsHttpclient + testCompile (project(':tapestry-test')) { + transitive = false + } + + // replace jakarta.enterprise:cdi-api with group: 'org.jboss.spec', name: 'jboss-javaee-6.0', version: libraryVersions.jbossJavaeeSpec to compile against full Java EE API + compileOnly moduleLibs.cdiApi + + testCompile moduleLibs.ziplock + testCompile moduleLibs.commonsHttpclient - testCompile group: 'org.jboss.arquillian.junit', name: 'arquillian-junit-container', version: libraryVersions.arquillian - testCompile group: 'org.jboss.shrinkwrap.descriptors', name: 'shrinkwrap-descriptors-api-javaee', version: libraryVersions.shrinkwrapDesc - testRuntime group: 'org.jboss.shrinkwrap.descriptors', name: 'shrinkwrap-descriptors-impl-javaee', version: libraryVersions.shrinkwrapDesc + testCompile moduleLibs.arquillianJunitContainer + testCompile moduleLibs.shrinkwrapDescriptorsApi + testRuntime moduleLibs.shrinkwrapDescriptorsImpl - tomeeEmbeddedTestRuntime group: 'org.apache.openejb', name: 'arquillian-tomee-embedded', version: libraryVersions.tomee + tomeeEmbeddedTestRuntime mopduleLibs.tomee - jbossAS7ManagedTestRuntime group: 'org.jboss.as', name: 'jboss-as-arquillian-container-managed', version: libraryVersions.jbossAS7 - jbossAS7ManagedTestRuntime group: 'org.jboss.spec', name: 'jboss-javaee-6.0', version: libraryVersions.jbossJavaeeSpec - jboss "org.jboss.as:jboss-as-dist:$libraryVersions.jbossDistrib@zip" + jbossAS7ManagedTestRuntime moduleLibs.jbossAS7 + jbossAS7ManagedTestRuntime moduleLibs.jbossJavaeeSpec + jboss moduleLibs.jbossDistrib - glassfishManagedTestRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-glassfish-managed-3.1', version: libraryVersions.arquillianGlassfish - glassfish "org.glassfish.distributions:glassfish:$libraryVersions.glassfishDistrib@zip" + glassfishManagedTestRuntime moduleLibs.arquillianGlassfish + glassfish moduleLibs.glassfishDistrib } sourceSets { @@ -72,10 +68,10 @@ sourceSets { } idea { - module { - scopes.PROVIDED.plus += configurations.compileOnly - } + module { + scopes.PROVIDED.plus += configurations.compileOnly } +} eclipse { classpath { @@ -83,8 +79,8 @@ eclipse { } } -task resolveJBoss(type: Copy) { - destinationDir = file('target') +task resolveJBoss(type: Copy) { + destinationDir = file('target') from { zipTree(configurations.jboss.singleFile) } } @@ -95,16 +91,16 @@ task resolveGlassfish(type: Copy) { task tomeeEmbeddedTest(type: Test) { - systemProperty 'arquillian.launch', "tomee_embedded" + systemProperty 'arquillian.launch', 'tomee_embedded' } task jbossAS7ManagedTest(type: Test) { - systemProperty 'arquillian.launch', "jbossas_managed" + systemProperty 'arquillian.launch', 'jbossas_managed' dependsOn { resolveJBoss } } task glassfishManagedTest(type: Test){ - systemProperty 'arquillian.launch', "glassfish_managed" + systemProperty 'arquillian.launch', 'glassfish_managed' dependsOn { resolveGlassfish } } @@ -118,9 +114,8 @@ test { setEnabled(false) } -jar { - - manifest { - attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.cdi.CDIInjectModule' - } - } +jar { + manifest { + attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.cdi.CDIInjectModule' + } +} diff --git a/tapestry-clojure/build.gradle b/tapestry-clojure/build.gradle index d1f044446..0d7c7c95f 100644 --- a/tapestry-clojure/build.gradle +++ b/tapestry-clojure/build.gradle @@ -1,21 +1,22 @@ -description = "Allows Clojure functions to be injected into Tapestry services and components" +plugins { + id 'tapestry.junit5-spock-convention' +} + +description = 'Allows Clojure functions to be injected into Tapestry services and components' dependencies { - implementation project(':tapestry-ioc') - implementation "org.clojure:clojure:1.6.0" + implementation project(':tapestry-ioc') - // Added just to prove that it works (TAP5-1945) - testImplementation project(':tapestry-core') - testRuntimeOnly "javax.servlet:javax.servlet-api:${versions.servletapi}" - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" -} + implementation libs.clojure -test { - useJUnit() + // Added just to prove that it works (TAP5-1945) + testImplementation project(':tapestry-core') + + testRuntimeOnly libs.javax.servlet.api } jar { - manifest { - attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.clojure.modules.ClojureModule' - } -} \ No newline at end of file + manifest { + attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.clojure.modules.ClojureModule' + } +} diff --git a/tapestry-core/build.gradle b/tapestry-core/build.gradle index e985abf06..c5ed7c95e 100644 --- a/tapestry-core/build.gradle +++ b/tapestry-core/build.gradle @@ -1,15 +1,15 @@ -import org.gradle.plugins.ide.idea.model.* -import org.apache.tools.ant.filters.ReplaceTokens -//import t5build.* +plugins { + id 'tapestry.junit5-convention' + id 'tapestry.testng-convention' +} -description = "Central module for Tapestry, containing all core services and components" +import t5build.TapestryBuildLogic +import org.apache.tools.ant.filters.ReplaceTokens -project.ext { - mainGeneratedDir = "src/main/generated" - testGeneratedDir = "src/test/generated" -} +description = 'Central module for Tapestry, containing all core services and components' -clean.delete mainGeneratedDir, testGeneratedDir +def npmWorkingDir = 'src/main/typescript/' +def npmExec = TapestryBuildLogic.isWindows() ? 'npm.cmd' : 'npm' dependencies { api project(':tapestry-ioc') @@ -17,148 +17,152 @@ dependencies { api project(':beanmodel') api project(':tapestry-http') - api "org.apache.commons:commons-lang3:${versions.commonsLang}" + implementation libs.jakarta.annotation.api + implementation libs.jakarta.xml.bind.api - - implementation 'jakarta.annotation:jakarta.annotation-api:1.3.4' - implementation 'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2' - implementation 'org.glassfish.jaxb:jaxb-runtime:2.3.2' - implementation 'com.sun.xml.ws:jaxws-rt:2.3.2' - implementation 'javax.xml.ws:jaxws-api:2.3.1' + implementation libs.commons.codec + implementation libs.commons.lang3 - provided project(":tapestry-test") - provided project(":tapestry-test-constants") + provided project(':tapestry-test') + provided project(':tapestry-test-constants') - provided "javax.servlet:javax.servlet-api:${versions.servletapi}" + provided libs.javax.servlet.api - implementation "commons-codec:commons-codec:1.10" - - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" - testImplementation "org.apache.httpcomponents:httpclient:4.5.14" - testRuntimeOnly project(':tapestry-spock') + testImplementation libs.httpcomponents.httpclient + testImplementation project(":tapestry-spock") - testRuntimeOnly "org.hsqldb:hsqldb:${versions.hsqldb}" - testRuntimeOnly 'com.google.inject:guice:3.0' + testRuntimeOnly("${libs.hsqldb.get().module.group}:${libs.hsqldb.get().module.name}:${libs.hsqldb.get().version}:jdk8") + testRuntimeOnly libs.guice } -def npmWorkingDir = "src/main/typescript/" - -task npmInstall(type: Exec) { - group "TypeScript" - description "Runs npm install" +tasks.register('npmInstall', Exec) { + group = 'TypeScript' + description = 'Runs npm install' workingDir = npmWorkingDir - commandLine isWindows() ? "npm.cmd" : "npm", 'install' + commandLine npmExec, 'install' } -task compileTypeScriptToAmd(type: Exec) { +tasks.register('compileTypeScriptToAmd', Exec) { + group = 'TypeScript' + description = 'Compiles TypeScript to AMD modules' + dependsOn npmInstall workingDir = npmWorkingDir - commandLine isWindows() ? "npm.cmd" : "npm", 'run', 'build-amd' + commandLine npmExec, 'run', 'build-amd' } -task compileTypeScriptToEsModule(type: Exec) { +tasks.register('compileTypeScriptToEsModule', Exec) { + group = 'TypeScript' + description = 'Compiles TypeScript to ES modules' + dependsOn npmInstall workingDir = npmWorkingDir - commandLine isWindows() ? "npm.cmd" : "npm", 'run', 'build-es-module' + commandLine npmExec, 'run', 'build-es-module' } -task compileTypeScript() { - dependsOn compileTypeScriptToAmd - dependsOn compileTypeScriptToEsModule +tasks.register('compileTypeScript', Delete) { + group = 'TypeScript' + description = 'Compiles all TypeScript variants' + + dependsOn compileTypeScriptToAmd, compileTypeScriptToEsModule } -task generateTypeScriptDocs(type: Exec) { +tasks.named('sourcesJar') { + dependsOn compileTypeScript +} + +tasks.register('generateTypeScriptDocs', Exec) { + group = 'TypeScript' + description = 'Generates TypeScript documentation' + dependsOn npmInstall - + workingDir = npmWorkingDir - commandLine isWindows() ? "npm.cmd" : "npm", 'run', 'docs' + commandLine npmExec, 'run', 'docs' } -task cleanTypeScriptFiles(type: Delete) { - delete fileTree("src/main/resources/META-INF/assets/es-modules/t5/core") { - include '**.js' +tasks.register('cleanTypeScriptFiles', Delete) { + group = 'TypeScript' + description = 'Cleans generated TypeScript files' + + delete fileTree('src/main/resources/META-INF/assets/es-modules/t5/core') { + include '**/*.js' } - delete fileTree("src/main/resources/META-INF/modules/t5/core") { - include '**.js' + delete fileTree('src/main/resources/META-INF/modules/t5/core') { + include '**/*.js' } - delete "src/main/typescript/docs" + delete 'src/main/typescript/docs' +} + +tasks.named('processResources') { + dependsOn compileTypeScript +} + +tasks.named('clean') { + dependsOn cleanTypeScriptFiles } -processResources.dependsOn compileTypeScript -clean.dependsOn cleanTypeScriptFiles // Not sure why this is necessary: -compileTestGroovy.dependsOn compileTestJava +tasks.named('compileTestGroovy') { + dependsOn compileTestJava +} test { - // Needed to have XMLTokenStreamTests.testStreamEncoding() passing on Java 9+ + // Needed to have XMLTokenStreamTests.testStreamEncoding() passing on Java 9+ if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_1_9)) { - jvmArgs("--add-opens=java.base/java.nio.charset=ALL-UNNAMED"); + jvmArgs('--add-opens=java.base/java.nio.charset=ALL-UNNAMED') + } + + // TAP5-2722 + systemProperty 'user.language', 'en' +} + +[ + 'app1', + 'app2', + 'app3', + 'app4', + 'app5', + 'app7', + 'appfolder' +].each { appName -> + tasks.register("runTest${appName.capitalize()}", JavaExec) { + group = 'Application' + description = "Starts the ${appName} integration test app, useful when debugging." + + mainClass = 'org.apache.tapestry5.test.JettyRunner' + args '-d', "src/test/${appName}", '-p', '8080' + classpath = sourceSets.test.runtimeClasspath } - // TAP5-2722 - systemProperty 'user.language', 'en' -} - -task runTestApp1(type:JavaExec) { - description 'Start app1 integration test app, useful when debugging failing integration tests' - main = 'org.apache.tapestry5.test.JettyRunner' - args "-d", "src/test/app1", "-p", "8080" - classpath += project.sourceSets.test.runtimeClasspath -} -task runTestApp2(type:JavaExec) { - description 'Start app2 integration test app, useful when debugging failing integration tests' - main = 'org.apache.tapestry5.test.JettyRunner' - args "-d", "src/test/app2", "-p", "8080" - classpath += project.sourceSets.test.runtimeClasspath -} -task runTestApp3(type:JavaExec) { - description 'Start app3 integration test app, useful when debugging failing integration tests' - main = 'org.apache.tapestry5.test.JettyRunner' - args "-d", "src/test/app3", "-p", "8080" - classpath += project.sourceSets.test.runtimeClasspath -} -task runTestApp4(type:JavaExec) { - description 'Start app4 integration test app, useful when debugging failing integration tests' - main = 'org.apache.tapestry5.test.JettyRunner' - args "-d", "src/test/app4", "-p", "8080" - classpath += project.sourceSets.test.runtimeClasspath -} -task runTestApp5(type:JavaExec) { - description 'Start app5 integration test app, useful when debugging failing integration tests' - main = 'org.apache.tapestry5.test.JettyRunner' - args "-d", "src/test/app5", "-p", "8080" - classpath += project.sourceSets.test.runtimeClasspath -} -task runTestApp7(type:JavaExec) { - description 'Start app7 integration test app, useful when debugging failing integration tests' - main = 'org.apache.tapestry5.test.JettyRunner' - args "-d", "src/test/app7", "-p", "8080" - classpath += project.sourceSets.test.runtimeClasspath -} -task runTestAppfolder(type:JavaExec) { - description 'Start appFolder integration test app, useful when debugging failing integration tests' - main = 'org.apache.tapestry5.test.JettyRunner' - args "-d", "src/test/appfolder", "-p", "8080" - classpath += project.sourceSets.test.runtimeClasspath } // Default is jQuery and Require.js enabled, so here are the tests for the // other combinations -task testWithJqueryAndRequireJsDisabled(type:Test) { - systemProperties."tapestry.javascript-infrastructure-provider" = "jquery" - systemProperties."tapestry.require-js-enabled" = "false" +tasks.register('testWithJqueryAndRequireJsDisabled', Test) { + group = 'Verification' + description = 'Runs tests with jQuery and Require.js disabled' + + systemProperty 'tapestry.javascript-infrastructure-provider', 'jquery' + systemProperty 'tapestry.require-js-enabled', 'false' } -task testWithPrototypeAndRequireJsEnabled(type:Test) { - systemProperties."tapestry.javascript-infrastructure-provider" = "prototype" - systemProperties."tapestry.require-js-enabled" = "true" -} +tasks.register('testWithPrototypeAndRequireJsEnabled', Test) { + group = 'Verification' + description = 'Runs tests with Prototype and Require.js enabled' -task testWithPrototypeAndRequireJsDisabled(type:Test) { - systemProperties."tapestry.javascript-infrastructure-provider" = "prototype" - systemProperties."tapestry.require-js-enabled" = "false" -} \ No newline at end of file + systemProperty 'tapestry.javascript-infrastructure-provider', 'prototype' + systemProperty 'tapestry.require-js-enabled', 'true' +} + +tasks.register('testWithPrototypeAndRequireJsDisabled', Test) { + group = 'Verification' + description = 'Runs tests with Prototype and Require.js disabled' + + systemProperty 'tapestry.javascript-infrastructure-provider', 'prototype' + systemProperty 'tapestry.require-js-enabled', 'false' +} diff --git a/tapestry-func/build.gradle b/tapestry-func/build.gradle index fa7b059ea..d52fbe364 100644 --- a/tapestry-func/build.gradle +++ b/tapestry-func/build.gradle @@ -1,7 +1,9 @@ -description = "Light-weight functional programming for Flows of values" +plugins { + id 'tapestry.junit5-convention' +} + +description = 'Light-weight functional programming for Flows of values' dependencies { - testImplementation "org.testng:testng:${versions.testng}" - testImplementation "commons-lang:commons-lang:2.6" - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" -} \ No newline at end of file + testImplementation libs.commons.lang3 +} diff --git a/tapestry-hibernate-core/build.gradle b/tapestry-hibernate-core/build.gradle index 3e541327a..f89144f41 100644 --- a/tapestry-hibernate-core/build.gradle +++ b/tapestry-hibernate-core/build.gradle @@ -1,21 +1,26 @@ -description = "Basic Hibernate services for Tapestry, useable outside of a Tapestry web application" +plugins { + id 'tapestry.testng-convention' +} + +description = 'Basic Hibernate services for Tapestry, useable outside of a Tapestry web application' +def moduleLibs = [ + jaxbRuntime: 'org.glassfish.jaxb:jaxb-runtime:2.3.2', +] dependencies { implementation project(':tapestry-ioc') - api group: 'org.hibernate', name: 'hibernate-core', version: versions.hibernate - - implementation 'org.glassfish.jaxb:jaxb-runtime:2.3.2' + api libs.hibernate.core + + implementation moduleLibs.jaxbRuntime testImplementation project(':tapestry-test') - testImplementation "org.easymock:easymock:${versions.easymock}" - testImplementation "org.testng:testng:${versions.testng}", { transitive = false } - testRuntimeOnly "org.hsqldb:hsqldb:${versions.hsqldb}" + testRuntimeOnly("${libs.hsqldb.get().module.group}:${libs.hsqldb.get().module.name}:${libs.hsqldb.get().version}:jdk8") } jar { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.hibernate.modules.HibernateCoreModule' } -} \ No newline at end of file +} diff --git a/tapestry-hibernate/build.gradle b/tapestry-hibernate/build.gradle index f13cdcde9..de74ab1cd 100644 --- a/tapestry-hibernate/build.gradle +++ b/tapestry-hibernate/build.gradle @@ -1,24 +1,33 @@ -description = "Provides support for simple CRUD applications built on top of Tapestry and Hibernate" +plugins { + id 'tapestry.testng-convention' +} + +description = 'Provides support for simple CRUD applications built on top of Tapestry and Hibernate' + +def moduleLibs = [ + jbossLogging: 'org.jboss.logging:jboss-logging:3.3.0.Final', +] dependencies { - api project(':tapestry-core') - api project(':tapestry-hibernate-core') - implementation "org.jboss.logging:jboss-logging:3.3.0.Final" + api project(':tapestry-core') + api project(':tapestry-hibernate-core') - testImplementation project(':tapestry-test') - - testRuntimeOnly "org.hsqldb:hsqldb:${versions.hsqldb}" + implementation moduleLibs.jbossLogging + + testImplementation project(':tapestry-test') + testRuntimeOnly("${libs.hsqldb.get().module.group}:${libs.hsqldb.get().module.name}:${libs.hsqldb.get().version}:jdk8") } -jar { +tasks.register('runTestApp0', JavaExec) { + description = 'Start tapestry-hibernate integration test app, useful when debugging failing integration tests' + + mainClass = 'org.apache.tapestry5.test.JettyRunner' + args '-d', 'src/test/webapp', '-p', '8080' + classpath += project.sourceSets.test.runtimeClasspath +} + +tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.hibernate.web.modules.HibernateModule' } } - -task runTestApp0(type:JavaExec) { - description 'Start tapestry-hibernate integration test app, useful when debugging failing integration tests' - main = 'org.apache.tapestry5.test.JettyRunner' - args "-d", "src/test/webapp", "-p", "8080" - classpath += project.sourceSets.test.runtimeClasspath -} diff --git a/tapestry-http/build.gradle b/tapestry-http/build.gradle index be6b4cede..f6cbd76da 100644 --- a/tapestry-http/build.gradle +++ b/tapestry-http/build.gradle @@ -1,32 +1,36 @@ -import org.gradle.plugins.ide.idea.model.* +plugins { + id 'tapestry.testng-convention' +} + import org.apache.tools.ant.filters.ReplaceTokens -import t5build.* -description = "Tapestry classes that handle HTTP requests" +description = 'Tapestry classes that handle HTTP requests' dependencies { implementation project(':tapestry-ioc') implementation project(':tapestry-json') implementation project(':beanmodel') - provided project(":tapestry-test") - provided project(":tapestry-test-constants") - - provided "javax.servlet:javax.servlet-api:${versions.servletapi}" + provided libs.javax.servlet.api - implementation "commons-codec:commons-codec:1.10" - implementation "commons-io:commons-io:${versions.commonsIo}" + implementation libs.commons.codec + implementation libs.commons.io - testRuntimeOnly "org.hsqldb:hsqldb:${versions.hsqldb}" + testImplementation project(':tapestry-test') + testImplementation project(':tapestry-test-constants') - testRuntimeOnly 'com.google.inject:guice:3.0' + testRuntimeOnly("${libs.hsqldb.get().module.group}:${libs.hsqldb.get().module.name}:${libs.hsqldb.get().version}:jdk8") + testRuntimeOnly libs.guice + testRuntimeOnly libs.slf4j.simple } // Not sure why this is necessary: -compileTestGroovy.dependsOn compileTestJava +tasks.named('compileTestGroovy') { + dependsOn compileTestJava +} -jar { - from("src/main/filtered-resources") { +tasks.named('jar', Jar) { + from('src/main/filtered-resources') { filter(ReplaceTokens, tokens: [version: project.parent.version]) } -} \ No newline at end of file +} diff --git a/tapestry-internal-test/build.gradle b/tapestry-internal-test/build.gradle index 9caa72c9b..4213b6d2d 100644 --- a/tapestry-internal-test/build.gradle +++ b/tapestry-internal-test/build.gradle @@ -1,5 +1,5 @@ -description = "Internal utilties used to assist with testing; not intended for outside use" +description = 'Internal utilties used to assist with testing; not intended for outside use' dependencies { - implementation project(":tapestry-core") -} \ No newline at end of file + implementation project(':tapestry-core') +} diff --git a/tapestry-ioc-jcache/build.gradle b/tapestry-ioc-jcache/build.gradle index 878cbab07..6d10137f7 100644 --- a/tapestry-ioc-jcache/build.gradle +++ b/tapestry-ioc-jcache/build.gradle @@ -1,35 +1,41 @@ -import org.gradle.plugins.ide.idea.model.* -import t5build.* - -description = "JCache (JSR 107) integration for Tapestry-IoC" +plugins { + id 'tapestry.junit4-legacy-convention' +} -//apply plugin: JavaPlugin +description = 'JCache (JSR 107) integration for Tapestry-IoC' -project.ext.libraryVersions = [ - jcache: '1.0.0', +def moduleLibs = [ + javaxCacheApi: 'javax.cache:cache-api:1.0.0', + javaxCacheTests: 'javax.cache:cache-tests:1.0.0', + javaxCacheDomain: 'javax.cache:test-domain:1.0.0', + cacheAnnotations: 'org.jsr107.ri:cache-annotations-ri-common:1.0.0', + infinispanJcache: 'org.infinispan:infinispan-jcache:7.0.0.Alpha4', ] dependencies { - /*compile "org.apache.tapestry:tapestry-ioc:${tapestryVersion()}"*/ - provided project(":tapestry-ioc") - implementation "javax.cache:cache-api:${libraryVersions.jcache}" - implementation "org.jsr107.ri:cache-annotations-ri-common:${libraryVersions.jcache}" - testImplementation "javax.cache:cache-tests:${libraryVersions.jcache}" - testImplementation "javax.cache:test-domain:${libraryVersions.jcache}" - testRuntimeOnly "org.infinispan:infinispan-jcache:7.0.0.Alpha4" /* Just to be able to run the tests */ + provided project(":tapestry-ioc") + + implementation moduleLibs.javaxCacheApi + implementation moduleLibs.cacheAnnotations + + testImplementation(moduleLibs.javaxCacheTests) + testImplementation moduleLibs.javaxCacheDomain + testRuntimeOnly moduleLibs.infinispanJcache /* Just to be able to run the tests */ } -jar { - manifest { - attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.jcache.module.JCacheModule' - } +tasks.named('jar', Jar) { + manifest { + attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.jcache.module.JCacheModule' + } } test { - useJUnit() - - // those tests do not work with JDK 6 (java.lang.UnsupportedClassVersionError) - exclude '**/InterceptionUsingDefaultCacheNameTest.class', - '**/InterceptionCacheNameOnEachMethodTest.class', - '**/InterceptionUsingCacheConfigTest.class' + if (JavaVersion.current().isJava9Compatible()) { + jvmArgs '--add-opens', 'java.base/java.util=ALL-UNNAMED' + jvmArgs '--add-opens', 'java.base/java.util.concurrent=ALL-UNNAMED' + jvmArgs '--add-opens', 'java.base/java.io=ALL-UNNAMED' + jvmArgs '--add-opens', 'java.base/java.lang=ALL-UNNAMED' + jvmArgs '--add-opens', 'java.base/java.lang.invoke=ALL-UNNAMED' + jvmArgs '--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED' + } } diff --git a/tapestry-ioc-junit/build.gradle b/tapestry-ioc-junit/build.gradle index 39a81a2ca..117e20ba3 100644 --- a/tapestry-ioc-junit/build.gradle +++ b/tapestry-ioc-junit/build.gradle @@ -1,10 +1,13 @@ -description = "Utilities for junit testing a tapestry-ioc application" +plugins { + id 'tapestry.junit5-convention' +} + +description = 'Utilities for junit testing a tapestry-ioc application' dependencies { implementation project(':tapestry-ioc') - implementation 'junit:junit:4.11' -} -test { - useJUnit() + // We also need these in implementation + implementation platform(libs.junit.bom) + implementation libs.junit.jupiter.api } diff --git a/tapestry-ioc/build.gradle b/tapestry-ioc/build.gradle index df3f1d9ac..75879fb7b 100644 --- a/tapestry-ioc/build.gradle +++ b/tapestry-ioc/build.gradle @@ -1,35 +1,28 @@ -description = "A code-centric, high-performance, simple Inversion of Control container" +plugins { + id 'tapestry.junit5-spock-convention' +} +description = 'A code-centric, high-performance, simple Inversion of Control container' dependencies { api project(':tapestry-func') - api project(':tapestry5-annotations') - api project(":plastic") - api project(":beanmodel") + api project(':commons') + implementation project(":beanmodel") provided project(':tapestry-test') // For now, keep these compile dependencies synchronized with the binaries dependencies // of the top-level build: - api "javax.inject:javax.inject:1" - api "javax.annotation:javax.annotation-api:1.3.2" + api libs.javax.inject + api libs.jakarta.annotation.api - api "org.slf4j:slf4j-api:${versions.slf4j}" + testImplementation libs.commons.lang3 + testImplementation libs.hibernate.core + testRuntimeOnly("${libs.hsqldb.get().module.group}:${libs.hsqldb.get().module.name}:${libs.hsqldb.get().version}:jdk8") - testImplementation "commons-lang:commons-lang:2.6" - testImplementation "org.apache.commons:commons-lang3:3.4" - - testImplementation "org.apache.commons:commons-lang3:3.4" - testImplementation "org.hibernate:hibernate-core:5.2.10.Final" - testRuntimeOnly "org.hsqldb:hsqldb:${versions.hsqldb}" - - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" - - provided "org.testng:testng:${versions.testng}", { transitive = false } } -test { - useJUnitPlatform() +tasks.named('test', Test) { // Override the master build.gradle - systemProperties.remove("tapestry.service-reloading-enabled") -} \ No newline at end of file + systemProperties.remove('tapestry.service-reloading-enabled') +} diff --git a/tapestry-javadoc/build.gradle b/tapestry-javadoc/build.gradle index d72b91a73..59bd8a2b7 100644 --- a/tapestry-javadoc/build.gradle +++ b/tapestry-javadoc/build.gradle @@ -1,32 +1,35 @@ -description = "JavaDoc Plugin for Tapestry that generates component reference documentation for component classes" +plugins { + id 'tapestry.junit5-convention' +} + +description = 'JavaDoc Plugin for Tapestry that generates component reference documentation for component classes' dependencies { - implementation project(':tapestry-core') - implementation "commons-lang:commons-lang:2.6" - - if (JavaVersion.current() <= JavaVersion.VERSION_1_8) { - implementation files(getTools()) - } - -} + implementation project(':tapestry-core') -/** Returns the tools.jar/classes.jar of the Java runtime. */ -File getTools() { + implementation libs.commons.lang3 + implementation libs.commons.text - def dir = isMacOSX_1_6() ? "classes" : "lib" - - def jar = isMacOSX_1_6() ? "classes" : "tools.jar" - - def jreRelpath = "../${dir}/${jar}" - def jdkRelpath = "$dir/${jar}" - - def javaHome = System.properties['java.home'] + testImplementation platform(libs.spock.bom) + testImplementation libs.spock.core +} - return new File(javaHome, jdkRelpath).exists() ? new File(javaHome, jdkRelpath) : new File(javaHome, jreRelpath) +java { + toolchain { + languageVersion = JavaLanguageVersion.of(11) + } } -boolean isMacOSX_1_6() { - System.properties['os.name'].toLowerCase().contains('mac os') && - System.properties['java.version'].startsWith("1.6.") +tasks.withType(JavaCompile).configureEach { + // Override Java 8 compatibility inherited from root + sourceCompatibility = '11' + targetCompatibility = '11' + + // Only apply --add-modules if target is not 1.8 + if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_11)) { + options.compilerArgs += [ + '--add-modules', + 'jdk.compiler' + ] + } } - \ No newline at end of file diff --git a/tapestry-jmx/build.gradle b/tapestry-jmx/build.gradle index ef371e800..00694090c 100644 --- a/tapestry-jmx/build.gradle +++ b/tapestry-jmx/build.gradle @@ -1,18 +1,17 @@ -description = "Allows easy exposure of Tapestry Services as JMX MBeans" +plugins { + id 'tapestry.testng-convention' +} -dependencies { - implementation project(':tapestry-core') +description = 'Allows easy exposure of Tapestry Services as JMX MBeans' - testImplementation project(':tapestry-test') - } +dependencies { + implementation project(':tapestry-core') -test { - systemProperties "tapestry.service-reloading-enabled": "false" + testImplementation project(':tapestry-test') } - jar { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.jmx.modules.JmxModule' } -} \ No newline at end of file +} diff --git a/tapestry-jpa/build.gradle b/tapestry-jpa/build.gradle index e72805b6a..58c723e7b 100644 --- a/tapestry-jpa/build.gradle +++ b/tapestry-jpa/build.gradle @@ -1,40 +1,41 @@ -description = "Provides support for simple CRUD applications built on top of Tapestry and JPA" +plugins { + id 'tapestry.testng-convention' +} + +description = 'Provides support for simple CRUD applications built on top of Tapestry and JPA' + +def moduleLibs = [ + jpaSpecs: 'org.apache.geronimo.specs:geronimo-jpa_2.0_spec:1.1', + javaxCdiApi: 'javax.enterprise:cdi-api:1.2', + eclipselink: 'org.eclipse.persistence:eclipselink:2.7.7', + dbcp: 'org.apache.tomcat:dbcp:6.0.32', + h2: 'com.h2database:h2:1.3.175' +] dependencies { - implementation project(':tapestry-core') - implementation "org.apache.geronimo.specs:geronimo-jpa_2.0_spec:1.1" - implementation 'javax.enterprise:cdi-api:1.2' + implementation project(':tapestry-core') + implementation moduleLibs.jpaSpecs + implementation moduleLibs.javaxCdiApi - testImplementation project(':tapestry-test') - testImplementation 'org.eclipse.persistence:eclipselink:2.7.7' + testImplementation project(':tapestry-test') + testImplementation moduleLibs.eclipselink - testRuntimeOnly "com.h2database:h2:1.2.145" - testRuntimeOnly "org.apache.tomcat:dbcp:6.0.32" - testRuntimeOnly 'com.h2database:h2:1.3.175' + testRuntimeOnly moduleLibs.dbcp + testRuntimeOnly moduleLibs.h2 } -repositories { - maven { - name "EclipseLink" - url "https://download.eclipse.org/rt/eclipselink/maven.repo/" +(1..6).each { + tasks.register("runTestApp${it}", JavaExec) { + description = "Start app${it} integration test app, useful when debugging failing integration tests" + mainClass = 'org.apache.tapestry5.test.JettyRunner' + args '-d', "src/test/app${it}", '-p', '8080' + classpath = project.sourceSets.test.runtimeClasspath } } -test { - systemProperties "tapestry.service-reloading-enabled": "false" -} - - -jar { +tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.jpa.modules.JpaModule' } } - -task runTestApp6(type:JavaExec) { - description 'Start app6 integration test app, useful when debugging failing integration tests' - main = 'org.apache.tapestry5.test.JettyRunner' - args "-d", "src/test/app6", "-p", "8080" - classpath += project.sourceSets.test.runtimeClasspath -} diff --git a/tapestry-json/build.gradle b/tapestry-json/build.gradle index 055ed9a73..9d71e30d7 100644 --- a/tapestry-json/build.gradle +++ b/tapestry-json/build.gradle @@ -1,16 +1,18 @@ -description = "Repackaged, improved (and tested) version of code originally from https://github.com/tdunning/open-json" +plugins { + id 'tapestry.junit5-convention' +} + +description = 'Repackaged, improved (and tested) version of code originally from https://github.com/tdunning/open-json' dependencies { - provided project(':tapestry-ioc') - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" -} + implementation project(':tapestry5-annotations') + implementation project(':commons') -test { - useJUnit() + testImplementation project(":tapestry-func") } -jar { +tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.json.modules.JSONModule' } -} \ No newline at end of file +} diff --git a/tapestry-kaptcha/build.gradle b/tapestry-kaptcha/build.gradle index 4b79ed964..8ccbd8a4a 100644 --- a/tapestry-kaptcha/build.gradle +++ b/tapestry-kaptcha/build.gradle @@ -1,17 +1,25 @@ -description = "Kaptcha user verification support" +plugins { + id 'tapestry.testng-convention' +} + +description = 'Kaptcha user verification support' + +def moduleLibs= [ + kaptcha: 'com.github.axet:kaptcha:0.0.8', +] dependencies { implementation project(':tapestry-core') - implementation "com.github.axet:kaptcha:0.0.8" + implementation moduleLibs.kaptcha - provided "javax.servlet:javax.servlet-api:${versions.servletapi}" + provided libs.javax.servlet.api testImplementation project(':tapestry-test') } -jar { +tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.kaptcha.modules.KaptchaModule' } -} \ No newline at end of file +} diff --git a/tapestry-latest-java-tests/build.gradle b/tapestry-latest-java-tests/build.gradle index 4371b82ff..6954db351 100644 --- a/tapestry-latest-java-tests/build.gradle +++ b/tapestry-latest-java-tests/build.gradle @@ -1,26 +1,20 @@ -description = "Test suite for making sure Tapestry runs on latest Java" +plugins { + id 'tapestry.junit5-spock-convention' +} -sourceCompatibility = "17" -targetCompatibility = "17" +description = 'Test suite for making sure Tapestry runs on latest Java' -tasks.withType(JavaCompile).each { - it.options.compilerArgs.add("--enable-preview") -} +sourceCompatibility = '17' +targetCompatibility = '17' -test { - dependsOn 'testNG' - useJUnitPlatform() - jvmArgs(["--enable-preview"]) +tasks.withType(JavaCompile).configureEach { + options.compilerArgs += '--enable-preview' } -tasks.register('testNG', Test) { - useTestNG() - jvmArgs(["--enable-preview"]) +tasks.withType(Test).configureEach { + jvmArgs += '--enable-preview' } dependencies { testImplementation project(':tapestry-ioc') - testImplementation "org.slf4j:slf4j-api:${versions.slf4j}" - testImplementation "org.testng:testng:${versions.testng}" - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" } diff --git a/tapestry-mongodb/build.gradle b/tapestry-mongodb/build.gradle index 6428ece0d..bd6e72126 100644 --- a/tapestry-mongodb/build.gradle +++ b/tapestry-mongodb/build.gradle @@ -1,18 +1,25 @@ -description = "Basic MongoDB services for Tapestry, useable outside of a Tapestry web application" +plugins { + id 'tapestry.junit5-spock-convention' +} + +import groovy.transform.AutoExternalize + +description = 'Basic MongoDB services for Tapestry, useable outside of a Tapestry web application' + +def moduleLibs = [ + mongoJavaDriver: 'org.mongodb:mongo-java-driver:2.10.1', + jongo: 'org.jongo:jongo:0.3', + embedMongo: 'de.flapdoodle.embed:de.flapdoodle.embed.mongo:1.28', +] dependencies { implementation project(':tapestry-ioc') - testImplementation project(':tapestry-test') - - implementation group: 'org.mongodb', name: 'mongo-java-driver', version: '2.10.1' - testImplementation group: 'org.jongo', name: 'jongo', version: '0.3' - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" - testImplementation "de.flapdoodle.embed:de.flapdoodle.embed.mongo:1.28" -} + implementation moduleLibs.mongoJavaDriver -test { - useJUnit() + testImplementation project(':tapestry-test') + testImplementation moduleLibs.jongo + testImplementation moduleLibs.embedMongo } jar { diff --git a/tapestry-openapi-viewer/build.gradle b/tapestry-openapi-viewer/build.gradle index b6a62e6ff..5662fb5ba 100644 --- a/tapestry-openapi-viewer/build.gradle +++ b/tapestry-openapi-viewer/build.gradle @@ -1,11 +1,12 @@ -description = "Embedded OpenAPI (Swagger) viewer for Tapestry, based on Swagger UI" +description = 'Embedded OpenAPI (Swagger) viewer for Tapestry, based on Swagger UI' dependencies { implementation project(':tapestry-core') - testImplementation "javax.servlet:javax.servlet-api:${versions.servletapi}" + + testImplementation libs.javax.servlet.api } -jar { +tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.openapiviewer.modules.TapestryOpenApiViewerModule' } diff --git a/tapestry-rest-jackson/build.gradle b/tapestry-rest-jackson/build.gradle index aa806f3a4..85e76208f 100644 --- a/tapestry-rest-jackson/build.gradle +++ b/tapestry-rest-jackson/build.gradle @@ -1,13 +1,19 @@ -description = "Support for using Jackson Databind with the Tapestry REST support" +def moduleLibs = [ + jsonschemaGenerator: 'com.github.victools:jsonschema-generator:4.20.0', +] + +description = 'Support for using Jackson Databind with the Tapestry REST support' dependencies { implementation project(':tapestry-core') - implementation "com.fasterxml.jackson.core:jackson-databind:${versions.jackson}" - implementation "com.github.victools:jsonschema-generator:${versions.jsonschemaGenerator}" - provided "javax.servlet:javax.servlet-api:${versions.servletapi}" + + implementation libs.jackson.databind + implementation moduleLibs.jsonschemaGenerator + + provided libs.javax.servlet.api } -jar { +tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.rest.jackson.modules.RestJacksonModule' } diff --git a/tapestry-runner/build.gradle b/tapestry-runner/build.gradle index 88acdb405..1391e5b0c 100644 --- a/tapestry-runner/build.gradle +++ b/tapestry-runner/build.gradle @@ -1,17 +1,22 @@ -description = "Utilities for running a Tapestry application in Jetty or Tomcat as part of test suite." +description = 'Utilities for running a Tapestry application in Jetty or Tomcat as part of test suite.' + +def moduleVersions = [ + jetty: '8.1.19.v20160209', + tomcat: '7.0.70', +] dependencies { + api project(':tapestry-test-constants') - api project(":tapestry-test-constants") - implementation "org.eclipse.jetty:jetty-server:${versions.jetty}" - implementation "org.eclipse.jetty:jetty-jndi:${versions.jetty}" - implementation "org.eclipse.jetty:jetty-plus:${versions.jetty}" - implementation "org.eclipse.jetty:jetty-webapp:${versions.jetty}" + implementation "org.eclipse.jetty:jetty-server:${moduleVersions.jetty}" + implementation "org.eclipse.jetty:jetty-jndi:${moduleVersions.jetty}" + implementation "org.eclipse.jetty:jetty-plus:${moduleVersions.jetty}" + implementation "org.eclipse.jetty:jetty-webapp:${moduleVersions.jetty}" - implementation "org.apache.tomcat:tomcat-catalina:${versions.tomcat}" - implementation "org.apache.tomcat:tomcat-coyote:${versions.tomcat}" - implementation "org.apache.tomcat:tomcat-jasper:${versions.tomcat}" + implementation "org.apache.tomcat:tomcat-catalina:${moduleVersions.tomcat}" + implementation "org.apache.tomcat:tomcat-coyote:${moduleVersions.tomcat}" + implementation "org.apache.tomcat:tomcat-jasper:${moduleVersions.tomcat}" - implementation "org.apache.tomcat:tomcat-dbcp:${versions.tomcat}" - implementation "commons-cli:commons-cli:1.2" + implementation "org.apache.tomcat:tomcat-dbcp:${moduleVersions.tomcat}" + implementation libs.commons.cli } diff --git a/tapestry-spock/build.gradle b/tapestry-spock/build.gradle index 894614390..50a9a60c8 100644 --- a/tapestry-spock/build.gradle +++ b/tapestry-spock/build.gradle @@ -1,14 +1,16 @@ -description = "Provides support Tapestry injections in Spock specifications" +plugins { + id 'tapestry.junit5-convention' + id 'groovy' +} + +description = 'Provides support Tapestry injections in Spock specifications' dependencies { - implementation project(':commons') - implementation project(':tapestry-ioc') - implementation "org.spockframework:spock-core:${versions.spock}" - - testImplementation "javax.inject:javax.inject:1" - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" -} + provided project(':commons') + provided project(':tapestry-ioc') + + api platform(libs.spock.bom) + api libs.spock.core -test { - useJUnitPlatform() + testImplementation libs.javax.inject } diff --git a/tapestry-spring/build.gradle b/tapestry-spring/build.gradle index 1b4bb0c34..fd0346f6a 100644 --- a/tapestry-spring/build.gradle +++ b/tapestry-spring/build.gradle @@ -1,30 +1,34 @@ -description = "Integration of Tapestry with the Spring Inversion Of Control Container" +plugins { + id 'tapestry.testng-convention' +} + +description = 'Integration of Tapestry with the Spring Inversion Of Control Container' +def moduleLibs = [ + springWeb: 'org.springframework:spring-web:3.2.9.RELEASE', +] dependencies { - implementation project(':tapestry-core') - implementation "org.springframework:spring-web:3.2.9.RELEASE" + implementation project(':tapestry-core') + + implementation moduleLibs.springWeb - provided "javax.servlet:javax.servlet-api:${versions.servletapi}" + provided libs.javax.servlet.api - testImplementation project(':tapestry-test') + testImplementation project(':tapestry-test') } -jar { - manifest { - attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.spring.modules.SpringModule' +['', '1'].each { suffix -> + tasks.register("runTestApp${suffix}", JavaExec) { + group = 'Application' + description = "Start tapestry-spring integration test app${suffix}, useful when debugging failing integration tests" + mainClass = 'org.apache.tapestry5.test.JettyRunner' + args '-d', "src/test/webapp${suffix}", '-p', '8080' + classpath += project.sourceSets.test.runtimeClasspath } } -task runTestApp(type:JavaExec) { - description 'Start tapestry-spring integration test app, useful when debugging failing integration tests' - main = 'org.apache.tapestry5.test.JettyRunner' - args "-d", "src/test/webapp", "-p", "8080" - classpath += project.sourceSets.test.runtimeClasspath +tasks.named('jar', Jar) { + manifest { + attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.spring.modules.SpringModule' + } } - -task runTestApp1(type:JavaExec) { - description 'Start tapestry-spring integration test app 1, useful when debugging failing integration tests' - main = 'org.apache.tapestry5.test.JettyRunner' - args "-d", "src/test/webapp1", "-p", "8080" - classpath += project.sourceSets.test.runtimeClasspath -} \ No newline at end of file diff --git a/tapestry-test-data/build.gradle b/tapestry-test-data/build.gradle index 63229bc4f..ea9530ee9 100644 --- a/tapestry-test-data/build.gradle +++ b/tapestry-test-data/build.gradle @@ -1,5 +1,5 @@ -description = "Utilities for generating random data used when populating entities" +description = 'Utilities for generating random data used when populating entities' dependencies { - implementation "org.slf4j:slf4j-api:${versions.slf4j}" + implementation libs.slf4j.api } diff --git a/tapestry-test/build.gradle b/tapestry-test/build.gradle index faf10b63e..70b34c377 100644 --- a/tapestry-test/build.gradle +++ b/tapestry-test/build.gradle @@ -1,20 +1,27 @@ -description = "[Deprecated] Utilities for integration testing of Tapestry applications using Selenium" +plugins { + id 'tapestry.testng-convention' +} + +description = '[Deprecated] Utilities for integration testing of Tapestry applications using Selenium' dependencies { - api project(":tapestry-test-data") - api project(":tapestry-runner") + api project(':tapestry-test-data') + api project(':tapestry-runner') + + implementation libs.webdrivermanager - implementation ("io.github.bonigarcia:webdrivermanager:${versions.webdriverManager}") + api libs.selenium.java - api "org.seleniumhq.selenium:selenium-leg-rc:${versions.selenium}", { - exclude group: "org.seleniumhq.selenium", module: "jetty-repacked" - exclude group: "org.testng", module: "testng" - exclude group: "javax.servlet", module: "javax.servlet-api" - exclude group: "org.seleniumhq.selenium", module: "selenium-firefox-driver" - } - api "org.seleniumhq.selenium:selenium-java:${versions.seleniumServer}" + api(libs.selenium.legrc) { + exclude group: 'org.seleniumhq.selenium', module: 'jetty-repacked' + exclude group: 'org.testng', module: 'testng' + exclude group: 'junit', module: 'junit' + exclude group: 'javax.servlet', module: 'javax.servlet-api' + exclude group: 'org.seleniumhq.selenium', module: 'selenium-firefox-driver' + } - api "org.testng:testng:${versions.testng}" - api "org.easymock:easymock:${versions.easymock}" + // we need to add them to api + api libs.testng + api libs.easymock } diff --git a/tapestry-upload/build.gradle b/tapestry-upload/build.gradle index 99d15479c..048f8e0a2 100644 --- a/tapestry-upload/build.gradle +++ b/tapestry-upload/build.gradle @@ -1,15 +1,26 @@ -description = "File Upload component, with supporting services" +plugins { + id 'tapestry.testng-convention' +} + +description = 'File Upload component, with supporting services' + +def moduleLibs = [ + commonsFileupload: 'commons-fileupload:commons-fileupload:1.5', +] dependencies { - implementation project(':tapestry-core') - api "commons-fileupload:commons-fileupload:1.5" - implementation "commons-io:commons-io:${versions.commonsIo}" - provided "javax.servlet:javax.servlet-api:${versions.servletapi}" + implementation project(':tapestry-core') + + implementation libs.commons.io + + api moduleLibs.commonsFileupload + + provided libs.javax.servlet.api - testImplementation project(':tapestry-test') + testImplementation project(':tapestry-test') } -jar { +tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.upload.modules.UploadModule' } diff --git a/tapestry-version-migrator/build.gradle b/tapestry-version-migrator/build.gradle index 04a897d10..4a19631fa 100644 --- a/tapestry-version-migrator/build.gradle +++ b/tapestry-version-migrator/build.gradle @@ -1,16 +1,18 @@ -description = "Tool to help migrate source code using Tapestry from one version to another. Initially built for 5.7.0" - -dependencies { - testImplementation group: 'org.testng', name: 'testng', version: '7.3.0' +plugins { + id 'tapestry.testng-convention' } -test { - useTestNG() { - useDefaultListeners = true // Tells TestNG to execute its default reporting structure +description = 'Tool to help migrate source code using Tapestry from one version to another. Initially built for 5.7.0' + +tasks.withType(Test).configureEach { + if (options instanceof TestNGOptions) { + options { + useDefaultListeners = true + } } } -jar { +tasks.named('jar', Jar) { manifest { attributes 'Main-Class': 'org.apache.tapestry5.versionmigrator.Main' } diff --git a/tapestry-webresources/build.gradle b/tapestry-webresources/build.gradle index 73a69bdf2..943d36fdb 100644 --- a/tapestry-webresources/build.gradle +++ b/tapestry-webresources/build.gradle @@ -1,48 +1,52 @@ -description = "Integration with WRO4J to perform runtime CoffeeScript compilation, JavaScript minimization, and more." +plugins { + id 'tapestry.junit5-convention' + id 'tapestry.testng-convention' +} + +description = 'Integration with WRO4J to perform runtime CoffeeScript compilation, JavaScript minimization, and more.' -//configurations { -// all { -// exclude group: "org.codehaus.groovy", module: "groovy-all" // avoid multiple Groovy compilers on classpath -// } -//} +def moduleLibs = [ + closureCompiler: 'com.google.javascript:closure-compiler-unshaded:v20220502', + less4j: 'com.github.sommeri:less4j:1.12.0', + autoValueAnnotations: 'com.google.auto.value:auto-value-annotations:1.9', + rhino: 'org.mozilla:rhino:1.7.7.2', +] dependencies { - api project(":tapestry-core") - testImplementation project(":tapestry-test") - api "com.google.javascript:closure-compiler-unshaded:v20220502" - implementation "com.github.sommeri:less4j:1.12.0" - - compileOnly "com.google.auto.value:auto-value-annotations:1.9" - - implementation "org.mozilla:rhino:1.7.7.2" - - testImplementation project(":tapestry-runner") - testImplementation "org.gebish:geb-spock:${versions.geb}", { - exclude group: "org.codehaus.groovy", module: "groovy-all" // avoid multiple Groovy compilers on classpath - } - testImplementation "org.spockframework:spock-tapestry:${versions.spock}", { - exclude group: "org.apache.tapestry" - } - testImplementation "org.junit.jupiter:junit-jupiter:${versions.junitJupiter}" - testImplementation "org.seleniumhq.selenium:selenium-leg-rc:${versions.selenium}", { - exclude group: "org.seleniumhq.selenium", module: "jetty-repacked" - exclude group: "org.testng", module: "testng" - exclude group: "javax.servlet", module: "javax.servlet-api" - exclude group: "org.seleniumhq.selenium", module: "selenium-firefox-driver" + api project(':tapestry-core') + + api moduleLibs.closureCompiler + + implementation moduleLibs.less4j + implementation moduleLibs.rhino + + compileOnly moduleLibs.autoValueAnnotations + + testImplementation project(':tapestry-test') + testImplementation project(':tapestry-runner') + + testImplementation(libs.geb.spock) { + exclude group: 'org.codehaus.groovy', module: 'groovy-all' // avoid multiple Groovy compilers on classpath } - testImplementation "org.seleniumhq.selenium:selenium-java:${versions.seleniumServer}" - testImplementation ("io.github.bonigarcia:webdrivermanager:${versions.webdriverManager}") -} -jar.manifest { - attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.webresources.modules.WebResourcesModule' + testImplementation project(":tapestry-spock") + testImplementation libs.selenium.java + testImplementation libs.webdrivermanager } test { - useJUnitPlatform() + systemProperties( + 'geb.build.reportsDir': "$reporting.baseDir/geb", + 'tapestry.compiled-asset-cache-dir': "$buildDir/compiled-asset-cache", + 'tapestry.production-mode': 'false', + 'tapestry.compress-whitespace': 'false', + 'tapestry.combine-scripts': 'false' + ) +} - systemProperties("geb.build.reportsDir": "$reporting.baseDir/geb", - "tapestry.compiled-asset-cache-dir": "$buildDir/compiled-asset-cache", - "tapestry.production-mode": "false") +tasks.named('jar', Jar) { + manifest { + attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.webresources.modules.WebResourcesModule' + } } diff --git a/tapestry5-annotations/build.gradle b/tapestry5-annotations/build.gradle index 4f411a174..bc3d98c9e 100644 --- a/tapestry5-annotations/build.gradle +++ b/tapestry5-annotations/build.gradle @@ -1 +1 @@ -description = "Annotations used with Tapestry, Tapestry-IoC and BeanModel applications" \ No newline at end of file +description = 'Annotations used with Tapestry, Tapestry-IoC and BeanModel applications'
