570 lines
17 KiB
Groovy
570 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 buildscriptLibs.forbiddenapis
|
|
}
|
|
}
|
|
|
|
import de.thetaphi.forbiddenapis.gradle.CheckForbiddenApis
|
|
import org.apache.tools.ant.filters.ReplaceTokens
|
|
|
|
apply plugin: 'java-library'
|
|
|
|
apply from: rootProject.file( 'gradle/module.gradle' )
|
|
apply from: rootProject.file( 'gradle/databases.gradle' )
|
|
apply from: rootProject.file( 'gradle/javadoc.gradle' )
|
|
|
|
apply plugin: 'biz.aQute.bnd.builder'
|
|
apply plugin: 'org.hibernate.orm.database-service'
|
|
apply plugin: 'org.hibernate.orm.build.java-module'
|
|
|
|
apply plugin: 'org.checkerframework'
|
|
apply plugin: 'de.thetaphi.forbiddenapis'
|
|
apply plugin: 'com.diffplug.spotless'
|
|
|
|
apply plugin: "jacoco"
|
|
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"
|
|
}
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Reproducible Builds
|
|
|
|
// https://docs.gradle.org/current/userguide/working_with_files.html#sec:reproducible_archives
|
|
// Configure archive tasks to produce reproducible archives:
|
|
tasks.withType(AbstractArchiveTask).configureEach {
|
|
preserveFileTimestamps = false
|
|
reproducibleFileOrder = true
|
|
}
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Configurations and Dependencies
|
|
|
|
configurations.configureEach {
|
|
resolutionStrategy.eachDependency { details ->
|
|
//Force the "byte buddy agent" version to match the Byte Buddy version
|
|
// we use, as Mockito might pull in a mismatched version transitively
|
|
if (details.requested.group == "net.bytebuddy" && details.requested.name == 'byte-buddy-agent') {
|
|
details.useVersion libs.versions.byteBuddy.get()
|
|
}
|
|
}
|
|
}
|
|
|
|
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.derbyTools
|
|
testRuntimeOnly dbLibs.hsqldb
|
|
testRuntimeOnly dbLibs.postgresql
|
|
testRuntimeOnly dbLibs.mssql
|
|
testRuntimeOnly dbLibs.informix
|
|
testRuntimeOnly dbLibs.cockroachdb
|
|
testRuntimeOnly dbLibs.sybase
|
|
testRuntimeOnly rootProject.fileTree(dir: 'drivers', include: '*.jar')
|
|
|
|
// 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
|
|
}
|
|
else if ( db.startsWith( 'firebird' ) ) {
|
|
testRuntimeOnly dbLibs.firebird
|
|
}
|
|
else if ( db.startsWith( 'oracle' ) ) {
|
|
testRuntimeOnly dbLibs.oracle
|
|
testRuntimeOnly dbLibs.oracleXml
|
|
testRuntimeOnly dbLibs.oracleXmlParser
|
|
}
|
|
else if ( db.startsWith( 'altibase' ) ) {
|
|
testRuntimeOnly dbLibs.altibase
|
|
}
|
|
else if ( db.startsWith( 'informix' ) ) {
|
|
testRuntimeOnly dbLibs.informix
|
|
}
|
|
|
|
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
|
|
options.fork = true
|
|
options.forkOptions.memoryMaximumSize = '768m'
|
|
|
|
options.compilerArgs += [
|
|
// disable adding @Generated annotation in the logger impls to make
|
|
// the logging annotation processor create the same sources each time.
|
|
"-Aorg.jboss.logging.tools.addGeneratedAnnotation=false"
|
|
// "-nowarn",
|
|
// "-encoding", "UTF-8"
|
|
]
|
|
}
|
|
|
|
tasks.compileJava.dependsOn spotlessApply
|
|
|
|
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
|
|
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['hibernate.highlight_sql'] = false
|
|
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 {
|
|
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 )
|
|
inputs.file( rootProject.file( "gradle/databases.gradle" ) )
|
|
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'
|
|
}
|
|
|
|
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"
|
|
exceptionFormat = 'full'
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// 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
|
|
|
|
tasks.named( "javadoc", Javadoc ) {
|
|
configure( options ) {
|
|
windowTitle = "Hibernate Javadocs ($project.name)"
|
|
docTitle = "Hibernate Javadocs ($project.name : $project.version)"
|
|
}
|
|
}
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// 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
|
|
|
|
task enforceRules {
|
|
doLast {
|
|
def illegalImport = ~/^import (sun|java.awt|org.slf4j)/
|
|
def missingNewline = ~/^\s*}\s*(else|catch|finally)/
|
|
def lowerEll = ~/\b\d+l\b/
|
|
def equals = ~/boolean +equals\((@?\w+ )*Object \w+\)/
|
|
def hashCode = ~/int +hashCode\(\)/
|
|
def errors = 0
|
|
def tree = fileTree("src/main/java/")
|
|
tree.include "**/*.java"
|
|
tree.each { file ->
|
|
def lineNum = 0
|
|
def shortName = file.path.substring(rootDir.path.length())
|
|
def equalsMinusHashcode = 0
|
|
file.eachLine { line ->
|
|
lineNum++
|
|
if (line =~ illegalImport) {
|
|
errors++
|
|
logger.error("Illegal import in ${shortName}\n${lineNum}: ${line}")
|
|
}
|
|
if (line =~ missingNewline) {
|
|
errors++
|
|
logger.error("Missing newline in ${shortName}\n${lineNum}: ${line}")
|
|
}
|
|
if (line =~ lowerEll) {
|
|
errors++
|
|
logger.error("Lowercase long literal in ${shortName}\n${lineNum}: ${line}")
|
|
}
|
|
if (!line.startsWith("//")) { //ignore commented-out code
|
|
if (line =~ equals) {
|
|
equalsMinusHashcode ++
|
|
}
|
|
if (line =~ hashCode) {
|
|
equalsMinusHashcode --
|
|
}
|
|
}
|
|
}
|
|
if (equalsMinusHashcode>0) {
|
|
errors++
|
|
logger.error("Equals with missing hash code in ${shortName}")
|
|
}
|
|
if (equalsMinusHashcode<0) {
|
|
errors++
|
|
logger.error("Hash code with missing equals in ${shortName}")
|
|
}
|
|
}
|
|
if ( errors>0 ) {
|
|
throw new GradleException("Code rules were violated ($errors problems)")
|
|
}
|
|
}
|
|
}
|
|
|
|
spotless {
|
|
//Don't fail during the check: rather than enforcing guidelines, we use this plugin to fix mistakes automatically.
|
|
enforceCheck false
|
|
java {
|
|
targetExclude( "**/target/**/*.java" )
|
|
licenseHeaderFile rootProject.file( 'spotless.license.java' )
|
|
removeUnusedImports()
|
|
indentWithTabs( 4 )
|
|
trimTrailingWhitespace()
|
|
endWithNewline()
|
|
}
|
|
}
|
|
|
|
tasks.spotlessApply.dependsOn enforceRules
|
|
|
|
|
|
class CompilerStubsArgumentProvider implements CommandLineArgumentProvider {
|
|
|
|
@InputDirectory
|
|
@PathSensitive(PathSensitivity.NONE)
|
|
File stubsDir
|
|
|
|
@Override
|
|
Iterable<String> asArguments() {
|
|
{ return ["-Astubs=${stubsDir}"]}
|
|
}
|
|
}
|
|
|
|
tasks.withType(JavaCompile).configureEach { task ->
|
|
// stubs argument needs to be passed as an absolute path, JavaCompile uses the Worker API which changes the current
|
|
// working directory and prevents from using a relative path to locate a project file.
|
|
// Using a CommandLineArgumentProvider allows build cache hits when the build cache is relocated.
|
|
task.options.compilerArgumentProviders.add(new CompilerStubsArgumentProvider(stubsDir: new File(project.rootDir, "checkerstubs")))
|
|
|
|
if (System.getProperty('APT_DEBUG', 'false') == 'true') {
|
|
task.options.forkOptions.jvmArgs += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9099']
|
|
}
|
|
}
|
|
|
|
checkerFramework {
|
|
excludeTests = true
|
|
checkers = [
|
|
'org.checkerframework.checker.nullness.NullnessChecker'
|
|
]
|
|
extraJavacArgs = [
|
|
'-AsuppressWarnings=initialization',
|
|
// stubs is passed directly through options.compilerArgumentProviders
|
|
'-AonlyDefs=^org\\.hibernate\\.(jdbc|exception|integrator|processor|service|spi|pretty|property\\.access|stat|engine\\.(config|jndi|profile|spi|transaction)|(action|context|bytecode)\\.spi)\\.'
|
|
]
|
|
}
|
|
|
|
tasks.forbiddenApisMain {
|
|
// unfortunately we currently have many uses of default Locale implicitly (~370)
|
|
// which need to be fixed before we can enable the "unsafe" check
|
|
//bundledSignatures += ["jdk-system-out", "jdk-non-portable", "jdk-unsafe-${jdkVersions.baseline}"]
|
|
bundledSignatures += ["jdk-system-out", "jdk-non-portable"]
|
|
|
|
suppressAnnotations += [
|
|
"org.hibernate.internal.build.AllowSysOut",
|
|
"org.hibernate.internal.build.AllowPrintStacktrace",
|
|
"org.hibernate.internal.build.AllowNonPortable"
|
|
]
|
|
}
|
|
|
|
tasks.forbiddenApisTest {
|
|
enabled = false
|
|
}
|
|
|