hibernate-orm/gradle/java-module.gradle

552 lines
18 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.1'
}
}
import de.thetaphi.forbiddenapis.gradle.CheckForbiddenApis
import org.apache.tools.ant.filters.ReplaceTokens
apply from: rootProject.file( 'gradle/libraries.gradle' )
apply from: rootProject.file( 'gradle/databases.gradle' )
apply plugin: 'java-library'
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"
forbiddenAPITargetJDKCompatibility = '11'
}
if ( !project.description ) {
project.description = "The Hibernate ORM $project.name module"
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Configurations and Dependencies
configurations.all {
resolutionStrategy {
dependencySubstitution {
// will handle dependencies pulled in transitively
substitute module( 'javax.persistence:javax.persistence-api' ) with module( libraries.jakarta_jpa )
substitute module( 'javax.transaction:jta' ) with module( libraries.jakarta_jta )
substitute module( 'org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec' ) with module( libraries.jakarta_jta )
substitute module( 'javax.validation:validation-api' ) with module( libraries.jakarta_validation )
substitute module( 'javax.interceptor:javax.interceptor-api' ) with module( libraries.jakarta_interceptor )
substitute module( 'javax.activation:javax.activation-api' ) with module( libraries.jakarta_activation )
substitute module( 'javax.enterprise:cdi-api' ) with module( libraries.jakarta_cdi )
substitute module( 'org.jboss.weld.se:weld-se-shaded' ) with module( libraries.jakarta_weld )
substitute module( 'javax.xml.bind:jaxb-api' ) with module( libraries.jakarta_jaxb_api )
substitute module( 'org.glassfish.jaxb:jaxb-runtime' ) with module( libraries.jakarta_jaxb_runtime )
substitute module( 'org.jboss.narayana.jta:narayana-jta' ) with module( libraries.jboss_jta_jakarta )
substitute module( 'org.jboss:jboss-transaction-spi' ) with module( libraries.jboss_tx_spi_jakarta )
substitute module( 'org.hibernate.validator:hibernate-validator' ) with module( libraries.jakarta_validator )
substitute module( 'org.glassfish:javax.el' ) with module( libraries.jakarta_el )
}
}
exclude group: 'xml-apis', module: 'xml-apis'
}
dependencies {
implementation libraries.logging
compileOnly libraries.logging_annotations
// 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 libraries.junit5_api
testImplementation libraries.junit5_jupiter
testImplementation libraries.junit5_params
testImplementation libraries.junit
testImplementation libraries.junit5_vintage
testImplementation libraries.byteman
testImplementation libraries.byteman_install
testImplementation libraries.byteman_bmunit
testRuntimeOnly libraries.log4j2
testRuntimeOnly libraries.byteBuddy
//Databases
testRuntimeOnly libraries.h2
testRuntimeOnly libraries.derby
testRuntimeOnly libraries.hsqldb
testRuntimeOnly libraries.postgresql
testRuntimeOnly libraries.mysql
testRuntimeOnly libraries.mariadb
testRuntimeOnly libraries.mssql
testRuntimeOnly libraries.informix
testRuntimeOnly libraries.cockroachdb
testRuntimeOnly libraries.oracle
testRuntimeOnly libraries.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 libraries.db2
}
else if ( db.startsWith( 'hana' ) ) {
testRuntimeOnly libraries.hana
}
annotationProcessor libraries.logging_processor
annotationProcessor libraries.logging
annotationProcessor libraries.logging_annotations
constraints {
implementation('org.apache.logging.log4j:log4j-core') {
version {
strictly('[2.17, 3[')
prefer('2.17.0')
}
because('CVE-2021-44228, CVE-2021-45046, CVE-2021-45105: Log4j vulnerable to remote code execution and other critical security vulnerabilities')
}
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Compilation
tasks.withType( JavaCompile ) {
options.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
tasks.withType( JavaCompile ).configureEach {
options.forkOptions.jvmArgs.addAll( getProperty( 'toolchain.compiler.jvmargs' ).toString().split( ' ' ) )
}
tasks.withType( Javadoc ).configureEach {
options.setJFlags( getProperty( 'toolchain.javadoc.jvmargs' ).toString().split( ' ' ).toList().findAll( { !it.isEmpty() } ) )
}
// Display version of Java tools
tasks.withType( JavaCompile ).configureEach {
doFirst {
logger.lifecycle "Compiling with '${javaCompiler.get().metadata.installationPath}'"
}
}
tasks.withType( Javadoc ).configureEach {
doFirst {
logger.lifecycle "Generating javadoc with '${javadocTool.get().metadata.installationPath}'"
}
}
}
task compile(dependsOn: [compileJava, processResources, compileTestJava, processTestResources] )
convention.findPlugin( JavaPluginConvention.class ).sourceSets.each { sourceSet ->
JavaCompile javaCompileTask = project.tasks.findByName( sourceSet.compileJavaTaskName ) as JavaCompile
// NOTE : this aptDir stuff is needed until we can have IntelliJ run annotation processors for us
// which cannot happen until we can fold hibernate-testing back into hibernate-core/src/test
// which cannot happen until... ugh
javaCompileTask.options.compilerArgs += [
"-nowarn",
"-encoding", "UTF-8"
]
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 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( ' ' ) )
// 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'
}
// todo (6.0) : temporarily include just the new tests so we can publish SNAPSHOTS for others to use
test.include 'org/hibernate/orm/test/**'
}
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 )
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 {
if ( gradle.ext.javaVersions.test.release.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"
}
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Artifacts (jar, sources, javadoc)
ext {
java9ModuleNameBase = project.name.startsWith( 'hibernate-' ) ? name.drop( 'hibernate-'.length() ): name
java9ModuleName = "org.hibernate.orm.$project.java9ModuleNameBase"
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 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 )
}
copyResourcesToIntelliJOutFolder.mustRunAfter processTestResources
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Report configs
checkstyle {
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
checkstyleMain.source = 'src/main/java'
// 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' )
}
// because cfg package is a mess mainly from annotation stuff
checkstyleMain.exclude '**/org/hibernate/cfg/**'
checkstyleMain.exclude '**/org/hibernate/cfg/*'
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
project.tasks.withType( CheckForbiddenApis ).each { task ->
task.outputs.dirs project.sourceSets.main.output.classesDirs
task.classesDirs = project.sourceSets.main.output.classesDirs
task.classpath = project.sourceSets.main.compileClasspath + project.sourceSets.main.runtimeClasspath
task.targetCompatibility = project.forbiddenAPITargetJDKCompatibility
// This slows down the checks a little, but is necessary to avoid the gradle deamon holding on
// to class definitions loaded previously - even possibly in a previous build.
task.disableClassloadingCache = true
tasks.forbiddenApis.finalizedBy task
}
project.tasks.check.finalizedBy tasks.forbiddenApis