553 lines
17 KiB
Groovy
553 lines
17 KiB
Groovy
/*
|
|
* Hibernate, Relational Persistence for Idiomatic Java
|
|
*
|
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
|
*/
|
|
|
|
/**
|
|
* Support for modules that contain Java code
|
|
*/
|
|
|
|
buildscript {
|
|
repositories {
|
|
mavenCentral()
|
|
}
|
|
dependencies {
|
|
classpath 'de.thetaphi:forbiddenapis:3.2'
|
|
}
|
|
}
|
|
|
|
import de.thetaphi.forbiddenapis.gradle.CheckForbiddenApis
|
|
import org.apache.tools.ant.filters.ReplaceTokens
|
|
|
|
apply from: rootProject.file( 'gradle/module.gradle' )
|
|
apply from: rootProject.file( 'gradle/libraries.gradle' )
|
|
apply from: rootProject.file( 'gradle/databases.gradle' )
|
|
|
|
apply plugin: 'org.hibernate.orm.database-service'
|
|
|
|
apply plugin: 'java-library'
|
|
apply plugin: 'biz.aQute.bnd.builder'
|
|
apply plugin: 'org.hibernate.orm.database-service'
|
|
|
|
apply plugin: 'checkstyle'
|
|
apply plugin: 'build-dashboard'
|
|
apply plugin: 'project-report'
|
|
|
|
|
|
// Attempt to leverage JetBrain's Gradle extension to automatically define
|
|
// `copyResourcesToIntelliJOutFolder` as a "build trigger" on import.
|
|
//
|
|
// However, see https://github.com/JetBrains/gradle-idea-ext-plugin/issues/8
|
|
|
|
apply plugin: 'org.jetbrains.gradle.plugin.idea-ext'
|
|
|
|
ext {
|
|
java9ModuleNameBase = project.name.startsWith( 'hibernate-' ) ? name.drop( 'hibernate-'.length() ): name
|
|
java9ModuleName = "org.hibernate.orm.$project.java9ModuleNameBase".replace('-','.')
|
|
forbiddenAPITargetJDKCompatibility = '11'
|
|
}
|
|
|
|
if ( !project.description ) {
|
|
project.description = "The Hibernate ORM $project.name module"
|
|
}
|
|
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Configurations and Dependencies
|
|
|
|
|
|
dependencies {
|
|
implementation libs.logging
|
|
|
|
compileOnly libs.loggingAnnotations
|
|
// Used for compiling some Oracle specific JdbcTypes
|
|
compileOnly dbLibs.oracle
|
|
|
|
// JUnit dependencies made up of:
|
|
// * JUnit 5
|
|
// * the Jupiter engine which runs JUnit 5 based tests
|
|
// * the "vintage" engine - which runs JUnit 3 and 4 based tests
|
|
testImplementation testLibs.junit5Api
|
|
testImplementation testLibs.junit5Engine
|
|
testImplementation testLibs.junit5Params
|
|
testImplementation testLibs.junit4
|
|
testImplementation testLibs.junit4Engine
|
|
testImplementation testLibs.assertjCore
|
|
|
|
testImplementation testLibs.byteman
|
|
|
|
testRuntimeOnly testLibs.log4j2
|
|
testRuntimeOnly libs.byteBuddy
|
|
|
|
//Databases
|
|
testRuntimeOnly dbLibs.h2
|
|
testRuntimeOnly dbLibs.derby
|
|
testRuntimeOnly dbLibs.hsqldb
|
|
testRuntimeOnly dbLibs.postgresql
|
|
testRuntimeOnly dbLibs.mssql
|
|
testRuntimeOnly dbLibs.informix
|
|
testRuntimeOnly dbLibs.cockroachdb
|
|
testRuntimeOnly dbLibs.oracle
|
|
testRuntimeOnly dbLibs.oracleXml
|
|
testRuntimeOnly dbLibs.oracleXmlParser
|
|
testRuntimeOnly dbLibs.sybase
|
|
|
|
// Since both the DB2 driver and HANA have a package "net.jpountz" we have to add dependencies conditionally
|
|
// This is due to the "no split-packages" requirement of Java 9+
|
|
|
|
if ( db.startsWith( 'db2' ) ) {
|
|
testRuntimeOnly dbLibs.db2
|
|
}
|
|
else if ( db.startsWith( 'hana' ) ) {
|
|
testRuntimeOnly dbLibs.hana
|
|
}
|
|
else if ( db.startsWith( 'mysql' ) || db.startsWith( 'tidb' ) ) {
|
|
testRuntimeOnly dbLibs.mysql
|
|
}
|
|
else if ( db.startsWith( 'mariadb' ) ) {
|
|
testRuntimeOnly dbLibs.mariadb
|
|
}
|
|
|
|
annotationProcessor libs.loggingProcessor
|
|
annotationProcessor libs.logging
|
|
annotationProcessor libs.loggingAnnotations
|
|
|
|
|
|
constraints {
|
|
implementation('org.apache.logging.log4j:log4j-core') {
|
|
version {
|
|
strictly('[2.17.1, 3[')
|
|
prefer('2.17.1')
|
|
}
|
|
because('CVE-2021-44228, CVE-2021-45046, CVE-2021-45105, CVE-2021-44832: Log4j vulnerable to remote code execution and other critical security vulnerabilities')
|
|
}
|
|
}
|
|
}
|
|
|
|
configurations {
|
|
javadocSources {
|
|
canBeConsumed = true
|
|
canBeResolved = false
|
|
visible = false
|
|
description = 'Configuration for accessing the sources that should be included in the javadoc for the project'
|
|
}
|
|
}
|
|
|
|
artifacts {
|
|
sourceSets.main.allJava.srcDirs.each { srcDir ->
|
|
javadocSources srcDir
|
|
}
|
|
}
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Compilation
|
|
|
|
tasks.withType( JavaCompile ) {
|
|
options.encoding = 'UTF-8'
|
|
options.warnings false
|
|
// javaCompileTask.options.compilerArgs += [
|
|
// "-nowarn",
|
|
// "-encoding", "UTF-8"
|
|
// ]
|
|
}
|
|
|
|
if ( !gradle.ext.javaToolchainEnabled ) {
|
|
tasks.compileJava.configure {
|
|
sourceCompatibility = JavaVersion.toVersion( gradle.ext.javaVersions.main.release )
|
|
targetCompatibility = JavaVersion.toVersion( gradle.ext.javaVersions.main.release )
|
|
}
|
|
tasks.compileTestJava.configure {
|
|
sourceCompatibility = JavaVersion.toVersion( gradle.ext.javaVersions.test.release )
|
|
targetCompatibility = JavaVersion.toVersion( gradle.ext.javaVersions.test.release )
|
|
}
|
|
}
|
|
else {
|
|
// Configure generated bytecode
|
|
// "sourceCompatibility" is not supported with toolchains. We have to work around that limitation.
|
|
tasks.compileJava.configure {
|
|
options.release = gradle.ext.javaVersions.main.release.asInt()
|
|
// Needs add-opens because of https://github.com/gradle/gradle/issues/15538
|
|
options.forkOptions.jvmArgs.addAll( ["--add-opens", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"] )
|
|
}
|
|
tasks.compileTestJava.configure {
|
|
options.release = gradle.ext.javaVersions.test.release.asInt()
|
|
// Needs add-opens because of https://github.com/gradle/gradle/issues/15538
|
|
options.forkOptions.jvmArgs.addAll( ["--add-opens", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"] )
|
|
}
|
|
|
|
// Configure version of Java tools
|
|
java {
|
|
toolchain {
|
|
languageVersion = gradle.ext.javaVersions.main.compiler
|
|
}
|
|
}
|
|
tasks.compileTestJava {
|
|
javaCompiler = javaToolchains.compilerFor {
|
|
languageVersion = gradle.ext.javaVersions.test.compiler
|
|
}
|
|
}
|
|
|
|
// Configure JVM Options
|
|
// Display version of Java tools
|
|
tasks.withType( JavaCompile ).configureEach {
|
|
options.forkOptions.jvmArgs.addAll( getProperty( 'toolchain.compiler.jvmargs' ).toString().split( ' ' ) )
|
|
doFirst {
|
|
logger.lifecycle "Compiling with '${javaCompiler.get().metadata.installationPath}'"
|
|
}
|
|
}
|
|
tasks.withType( Javadoc ).configureEach {
|
|
options.setJFlags( getProperty( 'toolchain.javadoc.jvmargs' ).toString().split( ' ' ).toList().findAll( { !it.isEmpty() } ) )
|
|
doFirst {
|
|
logger.lifecycle "Generating javadoc with '${javadocTool.get().metadata.installationPath}'"
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
task compile(dependsOn: [compileJava, processResources, compileTestJava, processTestResources] )
|
|
|
|
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Attach tools JAR to the classpath for byteman tests
|
|
|
|
final File toolsJar = file("${System.getProperty('java.home')}/../lib/tools.jar")
|
|
if ( toolsJar.exists() ) {
|
|
dependencies{
|
|
testImplementation files( toolsJar )
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Testing
|
|
|
|
if ( gradle.ext.javaToolchainEnabled ) {
|
|
tasks.test {
|
|
// Configure version of Java tools
|
|
javaLauncher = javaToolchains.launcherFor {
|
|
languageVersion = gradle.ext.javaVersions.test.launcher
|
|
}
|
|
|
|
// Configure JVM Options
|
|
jvmArgs( getProperty( 'toolchain.launcher.jvmargs' ).toString().split( ' ' ) )
|
|
if ( project.hasProperty( 'test.jdk.launcher.args' ) ) {
|
|
jvmArgs( project.getProperty( 'test.jdk.launcher.args' ).toString().split( ' ' ) )
|
|
}
|
|
|
|
// Display version of Java tools
|
|
doFirst {
|
|
logger.lifecycle "Testing with '${javaLauncher.get().metadata.installationPath}'"
|
|
}
|
|
}
|
|
}
|
|
class HeapDumpPathProvider implements CommandLineArgumentProvider {
|
|
@OutputDirectory
|
|
Provider<Directory> path
|
|
|
|
@Override
|
|
Iterable<String> asArguments() {
|
|
["-XX:HeapDumpPath=${path.get().asFile.absolutePath}"]
|
|
}
|
|
}
|
|
|
|
tasks.withType( Test.class ).each { test ->
|
|
test.useJUnitPlatform()
|
|
|
|
test.usesService( project.gradle.sharedServices.registrations.getByName( 'databaseService' ).service )
|
|
|
|
// Byteman needs this property to be set, https://developer.jboss.org/thread/274997
|
|
test.jvmArgs += ["-Djdk.attach.allowAttachSelf=true"]
|
|
|
|
test.jvmArgumentProviders.add(
|
|
new HeapDumpPathProvider( path: project.layout.buildDirectory.dir("OOM-dump") )
|
|
)
|
|
|
|
test.jvmArgs += [
|
|
'-XX:+HeapDumpOnOutOfMemoryError',
|
|
'-XX:MetaspaceSize=256M'
|
|
]
|
|
|
|
test.maxHeapSize = '3G'
|
|
|
|
test.systemProperties['hibernate.test.validatefailureexpected'] = true
|
|
test.systemProperties += System.properties.findAll { it.key.startsWith( "hibernate." ) }
|
|
|
|
test.enableAssertions = true
|
|
|
|
if ( project.name != 'hibernate-testing' ) {
|
|
test.dependsOn ':hibernate-testing:test'
|
|
}
|
|
|
|
// Allow to exclude specific tests
|
|
if ( project.hasProperty( 'excludeTests' ) ) {
|
|
test.filter {
|
|
excludeTestsMatching project.property('excludeTests').toString()
|
|
}
|
|
}
|
|
}
|
|
|
|
sourceSets {
|
|
test {
|
|
resources {
|
|
// add `src/test/java` as a test-resources dir
|
|
configure( srcDir('src/test/java') ) {
|
|
filter {
|
|
include '**/*.properties'
|
|
include '**/*.xml'
|
|
}
|
|
}
|
|
configure( srcDir('src/test/resources') ) {
|
|
filter {
|
|
include '*.properties'
|
|
include '*.xml'
|
|
include '**/*.properties'
|
|
include '**/*.xml'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
processTestResources {
|
|
duplicatesStrategy DuplicatesStrategy.INCLUDE
|
|
inputs.property( "db", db )
|
|
inputs.property( "dbHost", dbHost )
|
|
doLast {
|
|
copy {
|
|
from( sourceSets.test.java.srcDirs ) {
|
|
include '**/*.properties'
|
|
include '**/*.xml'
|
|
}
|
|
into sourceSets.test.java.classesDirectory
|
|
}
|
|
copy {
|
|
from file( 'src/test/resources' )
|
|
into file( "${buildDir}/resources/test" )
|
|
exclude 'src/test/resources/hibernate.properties'
|
|
}
|
|
copy {
|
|
from file( 'src/test/resources/hibernate.properties' )
|
|
into file( "${buildDir}/resources/test" )
|
|
filter( ReplaceTokens, tokens: dbBundle[db] )
|
|
}
|
|
}
|
|
}
|
|
|
|
// Keep system properties in sync with gradle.properties!
|
|
test {
|
|
systemProperty 'user.language', 'en'
|
|
systemProperty 'user.country', 'US'
|
|
systemProperty 'user.timezone', 'UTC'
|
|
systemProperty 'file.encoding', 'UTF-8'
|
|
// Needed for AdoptOpenJDK on alpine? The problem is similar to this: https://github.com/mockito/mockito/issues/978
|
|
jvmArgs '-XX:+StartAttachListener'
|
|
}
|
|
|
|
// Enable the experimental features of ByteBuddy with JDK 19+
|
|
test {
|
|
// We need to test the *launcher* version,
|
|
// because some tests will use Mockito (and thus Bytebuddy) to mock/spy
|
|
// classes that are part of the JDK,
|
|
// and those classes always have bytecode matching the version of the launcher.
|
|
// So for example, when using a JDK19 launcher and compiling tests with --release 17,
|
|
// Bytebuddy will still encounter classes with Java 19 bytecode.
|
|
if ( gradle.ext.javaVersions.test.launcher.asInt() >= 19 ) {
|
|
logger.warn( "The version of Java bytecode that will be tested is not supported by Bytebuddy by default. " +
|
|
" Setting 'net.bytebuddy.experimental=true'." )
|
|
systemProperty 'net.bytebuddy.experimental', true
|
|
}
|
|
}
|
|
|
|
test {
|
|
if ( project.findProperty( 'log-test-progress' )?.toString()?.toBoolean() ) {
|
|
// Log a statement for each test.
|
|
// Used in the Travis build so that Travis doesn't end up panicking because there's no output for a long time.
|
|
testLogging {
|
|
events "passed", "skipped", "failed"
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Jar
|
|
|
|
jar {
|
|
manifest {
|
|
attributes(
|
|
// Basic JAR manifest attributes
|
|
'Specification-Title': project.name,
|
|
'Specification-Version': project.version,
|
|
'Specification-Vendor': 'Hibernate.org',
|
|
'Implementation-Title': project.name,
|
|
'Implementation-Version': project.version,
|
|
'Implementation-Vendor': 'Hibernate.org',
|
|
'Implementation-Vendor-Id': 'org.hibernate',
|
|
'Implementation-Url': 'https://hibernate.org/orm',
|
|
|
|
// Java 9 module name
|
|
'Automatic-Module-Name': project.java9ModuleName,
|
|
|
|
// Hibernate-specific JAR manifest attributes
|
|
'Hibernate-VersionFamily': project.ormVersion.family,
|
|
'Hibernate-JpaVersion': project.jpaVersion.name,
|
|
|
|
// BND Plugin instructions (for OSGi):
|
|
'-reproducible': true,
|
|
'-noextraheaders': true,
|
|
'Bundle-Name': project.name,
|
|
'Bundle-SymbolicName': project.java9ModuleName,
|
|
'Bundle-Vendor': 'Hibernate.org',
|
|
'Bundle-DocURL': "https://www.hibernate.org/orm/${project.ormVersion.family}",
|
|
// This is overridden in some sub-projects
|
|
'Import-Package': [
|
|
// Temporarily support JTA 1.1 -- Karaf and other frameworks still
|
|
// use it. Without this, the plugin generates [1.2,2).
|
|
'javax.transaction;version="[1.1,2)"',
|
|
// Also import every package referenced in the code
|
|
// (note that '*' is resolved at build time to a list of packages)
|
|
'*'
|
|
].join( ',' ),
|
|
'-exportcontents': "*;version=${project.version}"
|
|
)
|
|
}
|
|
}
|
|
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// sources
|
|
|
|
task sourcesJar(type: Jar) {
|
|
from project.sourceSets.main.allSource
|
|
manifest {
|
|
attributes(
|
|
// Basic JAR manifest attributes
|
|
'Specification-Title': project.name,
|
|
'Specification-Version': project.version,
|
|
'Specification-Vendor': 'Hibernate.org',
|
|
'Implementation-Title': project.name,
|
|
'Implementation-Version': project.version,
|
|
'Implementation-Vendor': 'Hibernate.org',
|
|
'Implementation-Vendor-Id': 'org.hibernate',
|
|
'Implementation-Url': 'https://hibernate.org/orm',
|
|
|
|
// Hibernate-specific JAR manifest attributes
|
|
'Hibernate-VersionFamily': project.ormVersion.family,
|
|
'Hibernate-JpaVersion': project.jpaVersion.name
|
|
)
|
|
}
|
|
archiveClassifier.set( 'sources' )
|
|
}
|
|
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Javadoc
|
|
|
|
apply from: rootProject.file( 'gradle/javadoc.gradle' )
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// IDE
|
|
|
|
|
|
/*
|
|
The latest versions of IntelliJ copy the test resources into out/test/resources and
|
|
use those for its test classpath. Unfortunately, this occurs before the placeholder
|
|
in the test config file are substituted with the testing values.
|
|
|
|
This behaviour prevents the execution of the hibernate tests from inside the IDE.
|
|
|
|
A solution is to enable the 'After Build' Execution of the copyResourcesToIntelliJOutFolder task
|
|
from the 'Gradle project' IntelliJ tool window ( The task can be found under hibernate-orm > Task > other)
|
|
*/
|
|
task copyResourcesToIntelliJOutFolder(type: Task, dependsOn: project.tasks.processTestResources) {
|
|
doLast {
|
|
copy {
|
|
from "$buildDir/resources/test"
|
|
into 'out/test/resources'
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Use this task to set the current DB in a given module.
|
|
|
|
> gradlew sDB -Pdb=mysql
|
|
|
|
Afterward, you can run any test from the IDE against that particular DB.
|
|
*/
|
|
task setDataBase dependsOn( processTestResources, copyResourcesToIntelliJOutFolder ) {
|
|
println( "Setting current database to ${db}" )
|
|
}
|
|
|
|
tasks.copyResourcesToIntelliJOutFolder.mustRunAfter processTestResources
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Report configs
|
|
|
|
checkstyle {
|
|
it.sourceSets = [ project.sourceSets.main ]
|
|
configFile = rootProject.file( 'shared/config/checkstyle/checkstyle.xml' )
|
|
showViolations = false
|
|
}
|
|
|
|
// exclude generated java sources - by explicitly setting the base source dir
|
|
tasks.checkstyleMain.source = 'src/main/java'
|
|
// because cfg package is a mess mainly from annotation stuff
|
|
tasks.checkstyleMain.exclude '**/org/hibernate/cfg/**'
|
|
tasks.checkstyleMain.exclude '**/org/hibernate/cfg/*'
|
|
|
|
// define a second checkstyle task for checking non-fatal violations
|
|
task nonFatalCheckstyle(type:Checkstyle) {
|
|
source = project.sourceSets.main.java
|
|
classpath = project.configurations.checkstyle
|
|
showViolations = false
|
|
configFile = rootProject.file( 'shared/config/checkstyle/checkstyle-non-fatal.xml' )
|
|
}
|
|
|
|
|
|
task forbiddenApisSystemOut(type: CheckForbiddenApis, dependsOn: compileJava) {
|
|
bundledSignatures += 'jdk-system-out'
|
|
suppressAnnotations += ['org.hibernate.internal.build.AllowSysOut', 'org.hibernate.internal.build.AllowPrintStacktrace']
|
|
}
|
|
|
|
task forbiddenApisUnsafe(type: CheckForbiddenApis, dependsOn: compileJava) {
|
|
bundledSignatures += "jdk-unsafe-${gradle.ext.baselineJavaVersion}".toString()
|
|
|
|
// unfortunately we currently have many uses of default Locale implicitly (~370) which need to be fixed
|
|
// before we can fully enabled this check
|
|
//
|
|
// No idea how findbugs was missing these b4
|
|
ignoreFailures = true
|
|
}
|
|
|
|
task forbiddenApisNonPortable(type: CheckForbiddenApis, dependsOn: compileJava) {
|
|
bundledSignatures += 'jdk-non-portable'
|
|
}
|
|
|
|
task forbiddenApis {
|
|
description 'Grouping task for all defined forbidden-apis tasks'
|
|
}
|
|
|
|
project.tasks.withType( CheckForbiddenApis ) {
|
|
outputs.upToDateWhen { true }
|
|
|
|
classesDirs = project.sourceSets.main.output
|
|
classpath = configurations.runtimeClasspath + configurations.compileClasspath
|
|
targetCompatibility = project.forbiddenAPITargetJDKCompatibility
|
|
|
|
// This slows down the checks a little, but is necessary to avoid the gradle daemon holding on
|
|
// to class definitions loaded previously - even possibly in a previous build.
|
|
disableClassloadingCache = true
|
|
|
|
tasks.forbiddenApis.finalizedBy it
|
|
}
|
|
|
|
project.tasks.check.finalizedBy tasks.forbiddenApis
|