import org.gradle.internal.os.OperatingSystem import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform import org.jabref.build.xjc.XjcPlugin import org.jabref.build.xjc.XjcTask plugins { id 'application' id 'com.github.andygoossens.modernizer' version '1.9.3' id 'me.champeau.jmh' version '0.7.2' // This is https://github.com/java9-modularity/gradle-modules-plugin/pull/282 id 'com.github.koppor.gradle-modules-plugin' version 'v1.8.15-cmd-1' id 'org.openjfx.javafxplugin' version '0.1.0' id 'org.beryx.jlink' version '3.0.1' // nicer test outputs during running and completion // Homepage: https://github.com/radarsh/gradle-test-logger-plugin id 'com.adarshr.test-logger' version '4.0.0' id 'jacoco' id 'checkstyle' id 'project-report' id 'idea' id 'org.openrewrite.rewrite' version '6.20.0' } // Enable following for debugging // gradle.startParameter.showStacktrace = org.gradle.api.logging.configuration.ShowStacktrace. apply plugin: XjcPlugin apply from: 'eclipse.gradle' group = "org.jabref" version = project.findProperty('projVersion') ?: '100.0.0' java { sourceCompatibility = JavaVersion.VERSION_21 targetCompatibility = JavaVersion.VERSION_21 // Workaround needed for Eclipse, probably because of https://github.com/gradle/gradle/issues/16922 // Should be removed as soon as Gradle 7.0.1 is released ( https://github.com/gradle/gradle/issues/16922#issuecomment-828217060 ) modularity.inferModulePath.set(false) toolchain { // If this is updated, also update // - .gitpod.Dockerfile // - .devcontainer/devcontainer.json#L34 and // - .github/workflows/deployment-jdk-ea.yml#L53 languageVersion = JavaLanguageVersion.of(21) // See https://docs.gradle.org/current/javadoc/org/gradle/jvm/toolchain/JvmVendorSpec.html for a full list // vendor = JvmVendorSpec.AMAZON } } application { mainClass.set('org.jabref.Launcher') mainModule.set('org.jabref') applicationDefaultJvmArgs = [ // On a change here, also adapt // 1. "run > moduleOptions" // 2. "deployment.yml" (macOS part) // 3. "deployment-arm64.yml" // Note that the arguments are cleared for the "run" task to avoid messages like "WARNING: Unknown module: org.jabref.merged.module specified to --add-exports" // Fix for https://github.com/JabRef/jabref/issues/11188 '--add-exports=javafx.base/com.sun.javafx.event=org.jabref.merged.module', '--add-exports=javafx.controls/com.sun.javafx.scene.control=org.jabref.merged.module', // Fix for https://github.com/JabRef/jabref/issues/11198 '--add-opens=javafx.graphics/javafx.scene=org.jabref.merged.module', '--add-opens=javafx.controls/javafx.scene.control=org.jabref.merged.module', '--add-opens=javafx.controls/com.sun.javafx.scene.control=org.jabref.merged.module', // fix for https://github.com/JabRef/jabref/issues/11426 '--add-opens=javafx.controls/javafx.scene.control.skin=org.jabref.merged.module', // Fix for https://github.com/JabRef/jabref/issues/11225 on linux '--add-opens=javafx.controls/javafx.scene.control=org.jabref', '--add-exports=javafx.base/com.sun.javafx.event=org.jabref', '--add-exports=javafx.controls/com.sun.javafx.scene.control=org.jabref', '--add-opens=javafx.graphics/javafx.scene=org.jabref', '--add-opens=javafx.controls/javafx.scene.control=org.jabref', '--add-opens=javafx.controls/com.sun.javafx.scene.control=org.jabref', '--add-opens=javafx.base/javafx.collections=org.jabref', '--add-opens=javafx.base/javafx.collections.transformation=org.jabref' ] } // Workaround for https://github.com/openjfx/javafx-gradle-plugin/issues/89 // See also https://github.com/java9-modularity/gradle-modules-plugin/issues/165 modularity.disableEffectiveArgumentsAdjustment() sourceSets { main { java { // src-gen reasoning: https://stackoverflow.com/a/64612308/873282 srcDirs = ["src/main/java", "src-gen/main/java"] } resources { srcDirs = ["src/main/java", "src/main/resources"] } } test { java { srcDirs = ["src/test/java"] } resources { srcDirs = ["src/test/resources"] } } } repositories { mavenCentral() maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' } maven { url 'https://jitpack.io' } maven { url 'https://oss.sonatype.org/content/groups/public' } // Required for one.jpro.jproutils:tree-showing maven { url 'https://sandec.jfrog.io/artifactory/repo' } } configurations { antlr4 } dependencyLocking { lockAllConfigurations() } javafx { version = "22.0.2" modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.web', 'javafx.swing' ] } jacoco { toolVersion = "0.8.10" } dependencies { // Include all jar-files in the 'lib' folder as dependencies implementation fileTree(dir: 'lib', includes: ['*.jar']) def pdfbox = "3.0.3" implementation ("org.apache.pdfbox:pdfbox:$pdfbox") { exclude group: 'commons-logging' } implementation ("org.apache.pdfbox:fontbox:$pdfbox") { exclude group: 'commons-logging' } implementation ("org.apache.pdfbox:xmpbox:$pdfbox") { exclude group: 'org.junit.jupiter' exclude group: 'commons-logging' } def luceneVersion = "9.11.1" implementation "org.apache.lucene:lucene-core:$luceneVersion" implementation "org.apache.lucene:lucene-queryparser:$luceneVersion" implementation "org.apache.lucene:lucene-queries:$luceneVersion" implementation "org.apache.lucene:lucene-analysis-common:$luceneVersion" implementation "org.apache.lucene:lucene-highlighter:$luceneVersion" implementation group: 'org.apache.commons', name: 'commons-csv', version: '1.11.0' implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.17.0' implementation group: 'org.apache.commons', name: 'commons-text', version: '1.12.0' implementation 'commons-logging:commons-logging:1.3.4' implementation 'com.h2database:h2-mvstore:2.3.232' // required for reading write-protected PDFs - see https://github.com/JabRef/jabref/pull/942#issuecomment-209252635 implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1' implementation 'commons-cli:commons-cli:1.9.0' // region: LibreOffice implementation 'org.libreoffice:unoloader:24.2.3' implementation 'org.libreoffice:libreoffice:24.2.3' // Required for ID generation implementation 'io.github.thibaultmeyer:cuid:2.0.3' // endregion implementation 'io.github.java-diff-utils:java-diff-utils:4.12' implementation 'info.debatty:java-string-similarity:2.0.0' implementation 'com.github.javakeyring:java-keyring:1.0.4' antlr4 'org.antlr:antlr4:4.13.2' implementation 'org.antlr:antlr4-runtime:4.13.2' implementation group: 'org.eclipse.jgit', name: 'org.eclipse.jgit', version: '6.10.0.202406032230-r' implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.17.2' implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.17.2' implementation 'com.fasterxml:aalto-xml:1.3.3' implementation group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '2.7.9' implementation 'org.postgresql:postgresql:42.7.4' // Support unix socket connection types implementation 'com.kohlschutter.junixsocket:junixsocket-core:2.10.0' implementation 'com.kohlschutter.junixsocket:junixsocket-mysql:2.10.0' implementation ('com.oracle.ojdbc:ojdbc10:19.3.0.0') { // causing module issues exclude module: 'oraclepki' } implementation ('com.google.guava:guava:33.1.0-jre') { // TODO: Remove this as soon as https://github.com/google/guava/issues/2960 is fixed exclude module: "jsr305" } implementation 'jakarta.annotation:jakarta.annotation-api:2.1.1' implementation 'jakarta.inject:jakarta.inject-api:2.0.1' implementation('org.jabref:afterburner.fx:2.0.0') { exclude group: 'org.openjfx' } implementation 'org.kordamp.ikonli:ikonli-javafx:12.3.1' implementation 'org.kordamp.ikonli:ikonli-materialdesign2-pack:12.3.1' implementation 'com.github.sialcasa.mvvmFX:mvvmfx-validation:f195849ca9' //jitpack implementation 'de.saxsys:mvvmfx:1.8.0' implementation('org.jabref:easybind:2.2.1-SNAPSHOT') { exclude group: 'org.openjfx' } implementation 'org.fxmisc.flowless:flowless:0.7.3' implementation 'org.fxmisc.richtext:richtextfx:0.11.3' implementation (group: 'com.dlsc.gemsfx', name: 'gemsfx', version: '2.43.0') { exclude module: 'javax.inject' // Split package, use only jakarta.inject exclude module: 'commons-lang3' exclude group: 'org.apache.commons.validator' exclude group: 'org.apache.commons.commons-logging' exclude module: 'kotlin-stdlib-jdk8' exclude group: 'com.squareup.retrofit2' exclude group: 'org.openjfx' exclude group: 'org.apache.logging.log4j' exclude group: 'tech.units' } // Required by gemsfx implementation 'tech.units:indriya:2.2' implementation ('com.squareup.retrofit2:retrofit:2.11.0') { exclude group: 'com.squareup.okhttp3' } implementation 'org.controlsfx:controlsfx:11.2.1' implementation 'org.jsoup:jsoup:1.18.1' implementation 'com.konghq:unirest-java-core:4.4.4' implementation 'com.konghq:unirest-modules-gson:4.4.4' implementation 'org.apache.httpcomponents.client5:httpclient5:5.3.1' implementation 'org.slf4j:slf4j-api:2.0.16' implementation 'org.tinylog:tinylog-api:2.7.0' implementation 'org.tinylog:slf4j-tinylog:2.7.0' implementation 'org.tinylog:tinylog-impl:2.7.0' // route all requests to java.util.logging to SLF4J (which in turn routes to tinylog) implementation 'org.slf4j:jul-to-slf4j:2.0.13' // route all requests to log4j to SLF4J implementation 'org.apache.logging.log4j:log4j-to-slf4j:2.23.1' implementation('de.undercouch:citeproc-java:3.1.0') { exclude group: 'org.antlr' } // jakarta.activation is already dependency of glassfish implementation group: 'jakarta.xml.bind', name: 'jakarta.xml.bind-api', version: '4.0.2' implementation group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '4.0.3' implementation ('com.github.tomtung:latex2unicode_2.13:0.3.2') { exclude module: 'fastparse_2.13' } implementation "de.rototor.snuggletex:snuggletex:1.3.0" implementation ("de.rototor.snuggletex:snuggletex-jeuclid:1.3.0") { exclude group: "org.apache.xmlgraphics" } implementation 'com.vladsch.flexmark:flexmark:0.64.8' implementation 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8' implementation group: 'net.harawata', name: 'appdirs', version: '1.2.2' implementation group: 'org.jooq', name: 'jool', version: '0.9.15' // JAX-RS implemented by Jersey // API implementation 'jakarta.ws.rs:jakarta.ws.rs-api:4.0.0' // Implementation of the API implementation 'org.glassfish.jersey.core:jersey-server:3.1.8' // injection framework implementation 'org.glassfish.jersey.inject:jersey-hk2:3.1.8' implementation 'org.glassfish.hk2:hk2-api:3.1.1' // testImplementation 'org.glassfish.hk2:hk2-testing:3.0.4' // implementation 'org.glassfish.hk2:hk2-testing-jersey:3.0.4' // testImplementation 'org.glassfish.hk2:hk2-junitrunner:3.0.4' // HTTP server // implementation 'org.glassfish.jersey.containers:jersey-container-netty-http:3.1.1' implementation 'org.glassfish.jersey.containers:jersey-container-grizzly2-http:3.1.8' testImplementation 'org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-grizzly2:3.1.8' // Allow objects "magically" to be mapped to JSON using GSON // implementation 'org.glassfish.jersey.media:jersey-media-json-gson:3.1.1' // Because of GraalVM quirks, we need to ship that. See https://github.com/jspecify/jspecify/issues/389#issuecomment-1661130973 for details implementation 'org.jspecify:jspecify:1.0.0' // parse plist files implementation 'com.googlecode.plist:dd-plist:1.28' // Parse lnk files implementation 'com.github.vatbub:mslinks:1.0.6.2' // YAML formatting implementation 'org.yaml:snakeyaml:2.2' // AI implementation 'dev.langchain4j:langchain4j:0.33.0' // Even though we use jvm-openai for LLM connection, we still need this package for tokenization. implementation('dev.langchain4j:langchain4j-open-ai:0.33.0') { exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8' } implementation('dev.langchain4j:langchain4j-mistral-ai:0.33.0') implementation('dev.langchain4j:langchain4j-hugging-face:0.33.0') implementation 'ai.djl:api:0.29.0' implementation 'ai.djl.pytorch:pytorch-model-zoo:0.29.0' implementation 'ai.djl.huggingface:tokenizers:0.29.0' implementation 'io.github.stefanbratanov:jvm-openai:0.10.0' // openai depends on okhttp, which needs kotlin - see https://github.com/square/okhttp/issues/5299 for details implementation ('com.squareup.okhttp3:okhttp:4.12.0') { exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8' } // GemxFX also (transitively) depends on kotlin implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.0.20' implementation 'commons-io:commons-io:2.16.1' // Even if "compileOnly" is used, IntelliJ always adds to module-info.java. To avoid issues during committing, we use "implementation" instead of "compileOnly" implementation 'io.github.adr:e-adr:2.0.0-SNAPSHOT' testImplementation 'io.github.classgraph:classgraph:4.8.175' testImplementation 'org.junit.jupiter:junit-jupiter:5.11.0' testImplementation 'org.junit.platform:junit-platform-launcher:1.10.3' testImplementation 'org.mockito:mockito-core:5.13.0' testImplementation 'org.xmlunit:xmlunit-core:2.10.0' testImplementation 'org.xmlunit:xmlunit-matchers:2.10.0' testRuntimeOnly 'com.tngtech.archunit:archunit-junit5-engine:1.3.0' testImplementation 'com.tngtech.archunit:archunit-junit5-api:1.3.0' testImplementation "org.testfx:testfx-core:4.0.16-alpha" testImplementation "org.testfx:testfx-junit5:4.0.16-alpha" testImplementation "org.hamcrest:hamcrest-library:3.0" checkstyle 'com.puppycrawl.tools:checkstyle:10.18.0' // xjc needs the runtime as well for the ant task, otherwise it fails xjc group: 'org.glassfish.jaxb', name: 'jaxb-xjc', version: '3.0.2' xjc group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '3.0.2' rewrite(platform("org.openrewrite.recipe:rewrite-recipe-bom:2.17.0")) rewrite("org.openrewrite.recipe:rewrite-static-analysis") rewrite("org.openrewrite.recipe:rewrite-logging-frameworks") rewrite("org.openrewrite.recipe:rewrite-testing-frameworks") rewrite("org.openrewrite.recipe:rewrite-migrate-java") configurations.checkstyle { resolutionStrategy.capabilitiesResolution.withCapability("com.google.collections:google-collections") { select("com.google.guava:guava:0") } } configurations .matching(c -> c.name.contains("downloadSources")) .configureEach { attributes { attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME)) attribute(OperatingSystemFamily.OPERATING_SYSTEM_ATTRIBUTE, objects.named(OperatingSystemFamily, DefaultNativePlatform.getCurrentOperatingSystem().getName())) attribute(MachineArchitecture.ARCHITECTURE_ATTRIBUTE, objects.named(MachineArchitecture, DefaultNativePlatform.getCurrentArchitecture().getName())) } } } clean { delete "src/main/generated" delete "src-gen" } processResources { filteringCharset = 'UTF-8' filesMatching("build.properties") { expand(version: project.findProperty('projVersionInfo') ?: '100.0.0', "year": String.valueOf(Calendar.getInstance().get(Calendar.YEAR)), "maintainers": new File('MAINTAINERS').readLines().findAll { !it.startsWith("#") }.join(", "), "azureInstrumentationKey": System.getenv('AzureInstrumentationKey') ? System.getenv('AzureInstrumentationKey') : '', "springerNatureAPIKey": System.getenv('SpringerNatureAPIKey') ? System.getenv('SpringerNatureAPIKey') : '', "astrophysicsDataSystemAPIKey": System.getenv('AstrophysicsDataSystemAPIKey') ? System.getenv('AstrophysicsDataSystemAPIKey') : '', "ieeeAPIKey": System.getenv('IEEEAPIKey') ? System.getenv('IEEEAPIKey') : '', "scienceDirectApiKey": System.getenv('SCIENCEDIRECTAPIKEY') ? System.getenv('SCIENCEDIRECTAPIKEY') : '', "biodiversityHeritageApiKey": System.getenv('BiodiversityHeritageApiKey') ? System.getenv('BiodiversityHeritageApiKey') : '', "semanticScholarApiKey": System.getenv('SemanticScholarApiKey') ? System.getenv("SemanticScholarApiKey") : '' ) filteringCharset = 'UTF-8' } filesMatching(["resources/resource/ods/meta.xml", "resources/resource/openoffice/meta.xml"]) { expand version: project.version } } tasks.register('generateSource') { dependsOn("generateBstGrammarSource", "generateSearchGrammarSource", "generateCitaviSource") group = 'JabRef' description 'Generates all necessary (Java) source files.' } tasks.register("generateBstGrammarSource", JavaExec) { group = "JabRef" description = 'Generates BstLexer.java and BstParser.java from the Bst.g grammar file using antlr4.' classpath = configurations.antlr4 mainClass = "org.antlr.v4.Tool" javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) inputs.dir('src/main/antlr4/org/jabref/bst/') outputs.dir("src-gen/main/java/org/jabref/logic/bst/") args = ["-o", "src-gen/main/java/org/jabref/logic/bst/", "-visitor", "-no-listener", "-package", "org.jabref.logic.bst", "$projectDir/src/main/antlr4/org/jabref/bst/Bst.g4"] } tasks.register("generateSearchGrammarSource", JavaExec) { group = 'JabRef' description = "Generates java files for Search.g antlr4." classpath = configurations.antlr4 mainClass = "org.antlr.v4.Tool" javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) inputs.dir("src/main/antlr4/org/jabref/search/") outputs.dir("src-gen/main/java/org/jabref/search/") args = ["-o","src-gen/main/java/org/jabref/search" , "-visitor", "-no-listener", "-package", "org.jabref.search", "$projectDir/src/main/antlr4/org/jabref/search/Search.g4"] } tasks.register("generateJournalListMV", JavaExec) { group = "JabRef" description = "Converts the comma-separated journal abbreviation file to a H2 MVStore" classpath = sourceSets.main.runtimeClasspath mainClass = "org.jabref.cli.JournalListMvGenerator" javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) onlyIf { !file("build/resources/main/journals/journal-list.mv").exists() } } jar.dependsOn("generateJournalListMV") compileTestJava.dependsOn("generateJournalListMV") tasks.register('generateCitaviSource', XjcTask) { group = 'JabRef' description = "Generates java files for the citavi importer." schemaFile = "src/main/resources/xjc/citavi/citavi.xsd" outputDirectory = "src-gen/main/java/" javaPackage = "org.jabref.logic.importer.fileformat.citavi" } tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' // hint by https://docs.gradle.org/current/userguide/performance.html#run_the_compiler_as_a_separate_process options.fork = true } compileJava { options.compilerArgs << "-Xlint:none" dependsOn "generateSource" options.generatedSourceOutputDirectory.set(file("src-gen/main/java")) moduleOptions { addExports = [ // TODO: Remove access to internal api 'javafx.controls/com.sun.javafx.scene.control' : 'org.jabref', 'org.controlsfx.controls/impl.org.controlsfx.skin' : 'org.jabref' ] } } // Configures "application > run" task run { doFirst { // Clear the default JVM arguments, to avoid messages like "WARNING: Unknown module: org.jabref.merged.module specified to --add-exports" application.applicationDefaultJvmArgs = [] } moduleOptions { // On a change here, also adapt "application > applicationDefaultJvmArgs" addExports = [ // TODO: Remove access to internal api 'javafx.base/com.sun.javafx.event' : 'org.jabref.merged.module', 'javafx.controls/com.sun.javafx.scene.control' : 'org.jabref', // We need to restate the ControlsFX exports, because we get following error otherwise: // java.lang.IllegalAccessError: // class org.controlsfx.control.textfield.AutoCompletionBinding (in module org.controlsfx.controls) // cannot access class com.sun.javafx.event.EventHandlerManager (in module javafx.base) because // module javafx.base does not export com.sun.javafx.event to module org.controlsfx.controls // Taken from here: https://github.com/controlsfx/controlsfx/blob/9.0.0/build.gradle#L1 'javafx.graphics/com.sun.javafx.scene' : 'org.controlsfx.controls', 'javafx.graphics/com.sun.javafx.scene.traversal' : 'org.controlsfx.controls', 'javafx.graphics/com.sun.javafx.css' : 'org.controlsfx.controls', 'javafx.controls/com.sun.javafx.scene.control' : 'org.controlsfx.controls', 'javafx.controls/com.sun.javafx.scene.control.behavior' : 'org.controlsfx.controls', 'javafx.controls/com.sun.javafx.scene.control.inputmap' : 'org.controlsfx.controls', 'javafx.base/com.sun.javafx.event' : 'org.controlsfx.controls', 'javafx.base/com.sun.javafx.collections' : 'org.controlsfx.controls', 'javafx.base/com.sun.javafx.runtime': 'org.controlsfx.controls', 'javafx.web/com.sun.webkit' : 'org.controlsfx.controls', ] addOpens = [ 'javafx.controls/javafx.scene.control' : 'org.jabref', 'javafx.controls/com.sun.javafx.scene.control' : 'org.jabref', 'org.controlsfx.controls/impl.org.controlsfx.skin' : 'org.jabref', 'org.controlsfx.controls/org.controlsfx.control.textfield' : 'org.jabref', 'javafx.controls/javafx.scene.control.skin' : 'org.controlsfx.controls', 'javafx.graphics/javafx.scene' : 'org.controlsfx.controls', 'javafx.base/javafx.collections' : 'org.jabref', 'javafx.base/javafx.collections.transformation' : 'org.jabref' ] addModules = [ 'jdk.incubator.vector' ] createCommandLineArgumentFile = true } if (project.hasProperty('component')){ if (component == 'httpserver'){ main = 'org.jabref.http.server.Server' } } } javadoc { options { encoding = 'UTF-8' version = false author = false addMultilineStringsOption("-add-exports").setValue([ 'javafx.controls/com.sun.javafx.scene.control=org.jabref' ]) } } test { useJUnitPlatform { excludeTags 'DatabaseTest', 'FetcherTest', 'GUITest' } moduleOptions { // TODO: Remove this as soon as ArchUnit is modularized runOnClasspath = true } } testlogger { // See https://github.com/radarsh/gradle-test-logger-plugin#configuration for configuration options theme 'standard' showPassed false showSkipped false showCauses false showStackTraces false } tasks.withType(Test).configureEach { reports.html.outputLocation.set(file("${reporting.baseDir}/${name}")) // Enable parallel tests (on desktop). // See https://docs.gradle.org/8.1/userguide/performance.html#execute_tests_in_parallel for details. if (!providers.environmentVariable("CI").isPresent()) { maxParallelForks = Math.max(Runtime.runtime.availableProcessors() - 1, 1) } } tasks.register('databaseTest', Test) { useJUnitPlatform { includeTags 'DatabaseTest' } testLogging { // set options for log level LIFECYCLE events = ["FAILED"] exceptionFormat "full" } maxParallelForks = 1 } tasks.register('fetcherTest', Test) { useJUnitPlatform { includeTags 'FetcherTest' } maxParallelForks = 1 } tasks.register('guiTest', Test) { useJUnitPlatform { includeTags 'GUITest' } testLogging { // set options for log level LIFECYCLE events = ["FAILED"] exceptionFormat "full" } maxParallelForks = 1 } // Test result tasks tasks.register('copyTestResources', Copy) { from "${projectDir}/src/test/resources" into "${buildDir}/classes/test" } processTestResources.dependsOn copyTestResources tasks.register('jacocoPrepare') { doFirst { // Ignore failures of tests tasks.withType(Test).tap { configureEach { ignoreFailures = true } } } } test.mustRunAfter jacocoPrepare databaseTest.mustRunAfter jacocoPrepare fetcherTest.mustRunAfter jacocoPrepare jacocoTestReport { dependsOn jacocoPrepare, test, fetcherTest, databaseTest executionData files( layout.buildDirectory.file('jacoco/test.exec').get().asFile, layout.buildDirectory.file('jacoco/fetcherTest.exec').get().asFile, layout.buildDirectory.file('jacoco/databaseTest.exec').get().asFile) reports { csv.required = true html.required = true // coveralls plugin depends on xml format report xml.required = true } } // Code quality tasks checkstyle { // will only run when called explicitly from the command line sourceSets = [] } rewrite { activeRecipe( 'org.jabref.config.rewrite.cleanup' ) exclusion ( "build.gradle", "buildSrc/build.gradle", "eclipse.gradle", "settings.gradle", "src-gen/**", "src/main/resources/**", "src/test/resources/**", "**/module-info.java", "**/*.py", "**/*.xml", "**/*.yml" ) plainTextMask("**/*.md") failOnDryRunResults = true } modernizer { failOnViolations = false includeTestClasses = true exclusions = [ 'java/util/Optional.get:()Ljava/lang/Object;' ] } // Release tasks tasks.register('deleteInstallerTemp', Delete) { delete "$buildDir/installer" } jpackage.dependsOn deleteInstallerTemp jlinkZip.dependsOn jpackage jlink { // https://github.com/beryx/badass-jlink-plugin/issues/61#issuecomment-504640018 addExtraDependencies("javafx") addOptions('--strip-debug', '--compress', 'zip-6', '--no-header-files', '--no-man-pages') launcher { name = 'JabRef' } addOptions("--bind-services") // TODO: Remove the following as soon as the dependencies are fixed (upstream) // forceMerge is usually needed when some non-modular artifacts in the dependency graph use code that was previously part of the JDK // but it was removed in the newer releases. // The pom.xml associated with such a non-modular artifact does not mention that the artifact depends on the removed code // (because the artifact was published when this code was still available in the JDK). forceMerge "controlsfx", "bcprov", "jaxb", "istack", "stax" // TODO: Remove the following correction to the merged module // The module descriptor automatically generated by the plugin for the merged module contained some invalid entries. // This is based on ./gradlew suggestMergedModuleInfo, sort, strip ";"", comment non-used modules, and include the suggested directives here. // However, we need to fine-tune this manually (non-alphabetic order) mergedModule { requires 'javafx.base' requires 'javafx.controls' requires 'javafx.fxml' requires 'javafx.graphics' requires 'javafx.media' requires 'javafx.swing' requires 'java.compiler' requires 'java.datatransfer' requires 'java.desktop' requires 'java.logging' requires 'java.management' requires 'java.naming' requires 'java.net.http' requires 'java.scripting' requires 'java.security.jgss' requires 'java.security.sasl' requires 'java.sql' requires 'java.sql.rowset' requires 'java.transaction.xa' requires 'java.rmi' requires 'java.xml' requires 'jdk.jsobject' requires 'jdk.unsupported' requires 'jdk.unsupported.desktop' requires 'jdk.security.jgss' requires 'jdk.xml.dom' requires 'com.google.gson' requires 'org.jsoup' requires 'org.slf4j' requires 'jakarta.xml.bind' requires 'org.apache.commons.lang3' requires 'org.apache.commons.text' requires 'org.apache.commons.logging'; uses 'org.mariadb.jdbc.credential.CredentialPlugin' uses 'org.mariadb.jdbc.authentication.AuthenticationPlugin' uses 'org.mariadb.jdbc.tls.TlsSocketPlugin' uses 'org.mariadb.jdbc.LocalInfileInterceptor' uses 'org.eclipse.jgit.transport.SshSessionFactory' uses 'org.eclipse.jgit.lib.GpgSigner' uses 'kong.unirest.core.json.JsonEngine'; provides 'org.mariadb.jdbc.tls.TlsSocketPlugin' with 'org.mariadb.jdbc.internal.protocol.tls.DefaultTlsSocketPlugin' provides 'java.sql.Driver' with 'org.postgresql.Driver' provides 'org.mariadb.jdbc.authentication.AuthenticationPlugin' with 'org.mariadb.jdbc.internal.com.send.authentication.CachingSha2PasswordPlugin', 'org.mariadb.jdbc.internal.com.send.authentication.ClearPasswordPlugin', 'org.mariadb.jdbc.internal.com.send.authentication.Ed25519PasswordPlugin', 'org.mariadb.jdbc.internal.com.send.authentication.NativePasswordPlugin', 'org.mariadb.jdbc.internal.com.send.authentication.OldPasswordPlugin', 'org.mariadb.jdbc.internal.com.send.authentication.SendGssApiAuthPacket', 'org.mariadb.jdbc.internal.com.send.authentication.SendPamAuthPacket', 'org.mariadb.jdbc.internal.com.send.authentication.Sha256PasswordPlugin' provides 'org.mariadb.jdbc.credential.CredentialPlugin' with 'org.mariadb.jdbc.credential.aws.AwsIamCredentialPlugin', 'org.mariadb.jdbc.credential.env.EnvCredentialPlugin', 'org.mariadb.jdbc.credential.system.PropertiesCredentialPlugin' provides 'java.security.Provider' with 'org.bouncycastle.jce.provider.BouncyCastleProvider', 'org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider' provides 'kong.unirest.core.json.JsonEngine' with 'kong.unirest.modules.gson.GsonEngine'; } jpackage { outputDir = "distribution" if (OperatingSystem.current().isWindows()) { // This requires WiX to be installed: https://github.com/wixtoolset/wix3/releases installerType = "msi" imageOptions = [ '--icon', "${projectDir}/src/main/resources/icons/jabref.ico", ] installerOptions = [ '--vendor', 'JabRef', '--app-version', "${project.version}", '--verbose', '--win-upgrade-uuid', 'd636b4ee-6f10-451e-bf57-c89656780e36', '--win-dir-chooser', '--win-shortcut', '--win-menu', '--win-menu-group', "JabRef", '--temp', "$buildDir/installer", '--resource-dir', "${projectDir}/buildres/windows", '--license-file', "${projectDir}/buildres/LICENSE_with_Privacy.md", '--file-associations', "${projectDir}/buildres/windows/bibtexAssociations.properties" ] } if (OperatingSystem.current().isLinux()) { imageOptions = [ '--icon', "${projectDir}/src/main/resources/icons/JabRef-icon-64.png", '--app-version', "${project.version}", ] installerOptions = [ '--verbose', '--vendor', 'JabRef', '--app-version', "${project.version}", // '--temp', "$buildDir/installer", '--resource-dir', "${projectDir}/buildres/linux", '--linux-menu-group', 'Office;', '--linux-rpm-license-type', 'MIT', // '--license-file', "${projectDir}/LICENSE.md", '--description', 'JabRef is an open source bibliography reference manager. The native file format used by JabRef is BibTeX, the standard LaTeX bibliography format.', '--linux-shortcut', '--file-associations', "${projectDir}/buildres/linux/bibtexAssociations.properties" ] } if (OperatingSystem.current().isMacOsX()) { imageOptions = [ '--icon', "${projectDir}/src/main/resources/icons/jabref.icns", '--resource-dir', "${projectDir}/buildres/mac" ] // Notarized mac images and packages are built on the pipeline only skipInstaller = true installerOptions = [ '--verbose', '--vendor', 'JabRef', '--mac-package-identifier', "JabRef", '--mac-package-name', "JabRef", '--app-version', "${project.version}", '--file-associations', "${projectDir}/buildres/mac/bibtexAssociations.properties", '--resource-dir', "${projectDir}/buildres/mac" ] } } } if (OperatingSystem.current().isWindows()) { tasks.jpackageImage.doLast { copy { from("${projectDir}/buildres/windows") { include "jabref-firefox.json", "jabref-chrome.json", "JabRefHost.bat", "JabRefHost.ps1" } into "$buildDir/distribution/JabRef" } } } if (OperatingSystem.current().isLinux()) { tasks.jpackageImage.doLast { copy { from("${projectDir}/buildres/linux") { include "native-messaging-host/**", "jabrefHost.py" } into "$buildDir/distribution/JabRef/lib" } } } if (OperatingSystem.current().isMacOsX()) { tasks.jpackageImage.doLast { copy { from("${projectDir}/buildres/mac") { include "native-messaging-host/**", "jabrefHost.py" } into "$buildDir/distribution/JabRef.app/Contents/Resources" } } } jmh { warmupIterations = 5 iterations = 10 fork = 2 }