diff --git a/.github/actions/run-gradle/action.yml b/.github/actions/run-gradle/action.yml index 3d64732fac..f12eb25187 100644 --- a/.github/actions/run-gradle/action.yml +++ b/.github/actions/run-gradle/action.yml @@ -8,7 +8,7 @@ inputs: required: true description: The JDK version early-access: - default: '23' + default: '24' required: false description: The early access release graal: @@ -79,7 +79,7 @@ runs: distribution: temurin - name: Setup Gradle id: setup-gradle - uses: gradle/actions/setup-gradle@d9336dac04dea2507a617466bc058a3def92b18b # v3.4.0 + uses: gradle/actions/setup-gradle@31ae3562f68c96d481c31bc1a8a55cc1be162f83 # v3.4.1 env: JAVA_HOME: ${{ steps.setup-gradle-jdk.outputs.path }} ORG_GRADLE_PROJECT_org.gradle.java.installations.auto-download: 'false' diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index ea46e1b879..fc1b27d585 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -16,7 +16,7 @@ jobs: github.com:443 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: actionlint - uses: reviewdog/action-actionlint@fd627997c9688c2f39e13917aed23873c031b834 # v1.48.0 + uses: reviewdog/action-actionlint@52819f5f70db72e17c2fadecd44a791ae4459276 # v1.49.0 env: SHELLCHECK_OPTS: -e SC2001 -e SC2035 -e SC2046 -e SC2061 -e SC2086 -e SC2156 with: diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index cbfc71e225..f8049f2539 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ 11, 21, 23, GraalVM ] + java: [ 11, 21, 24, GraalVM ] env: JAVA_VERSION: ${{ matrix.java }} steps: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 242bd6f0a4..23f9033072 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,7 +39,7 @@ env: schemastore.org:443 www.graalvm.org:443 PUBLISH_JDK: 11 - EA_JDK: 23 + EA_JDK: 24 jobs: compile: @@ -48,7 +48,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ 11, 22, 23, GraalVM ] + java: [ 11, 22, 24, GraalVM ] env: JAVA_VERSION: ${{ matrix.java }} steps: diff --git a/.github/workflows/dependency-submission-pr-retreive.yml b/.github/workflows/dependency-submission-pr-retreive.yml index 2e021421f7..b0b02d8e50 100644 --- a/.github/workflows/dependency-submission-pr-retreive.yml +++ b/.github/workflows/dependency-submission-pr-retreive.yml @@ -35,6 +35,6 @@ jobs: repo1.maven.org:443 services.gradle.org:443 - name: Retrieve and submit dependency graph - uses: gradle/actions/dependency-submission@d9336dac04dea2507a617466bc058a3def92b18b # v3.4.0 + uses: gradle/actions/dependency-submission@31ae3562f68c96d481c31bc1a8a55cc1be162f83 # v3.4.1 with: dependency-graph: download-and-submit diff --git a/.github/workflows/dependency-submission-pr-submit.yml b/.github/workflows/dependency-submission-pr-submit.yml index ed572aae6c..f73c9e7f8d 100644 --- a/.github/workflows/dependency-submission-pr-submit.yml +++ b/.github/workflows/dependency-submission-pr-submit.yml @@ -38,7 +38,7 @@ jobs: java-version: ${{ env.JAVA_VERSION }} distribution: temurin - name: Submit Dependency Graph - uses: gradle/actions/dependency-submission@d9336dac04dea2507a617466bc058a3def92b18b # v3.4.0 + uses: gradle/actions/dependency-submission@31ae3562f68c96d481c31bc1a8a55cc1be162f83 # v3.4.1 with: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} dependency-graph: generate-and-upload diff --git a/.github/workflows/dependency-submission.yml b/.github/workflows/dependency-submission.yml index 5256d8ae34..7f2299fa7a 100644 --- a/.github/workflows/dependency-submission.yml +++ b/.github/workflows/dependency-submission.yml @@ -38,6 +38,6 @@ jobs: java-version: ${{ env.JAVA_VERSION }} distribution: temurin - name: Submit Dependency Graph - uses: gradle/actions/dependency-submission@d9336dac04dea2507a617466bc058a3def92b18b # v3.4.0 + uses: gradle/actions/dependency-submission@31ae3562f68c96d481c31bc1a8a55cc1be162f83 # v3.4.1 with: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index b915ca3d42..18d6e2514c 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -39,7 +39,7 @@ jobs: java-version: ${{ env.JAVA_VERSION }} distribution: temurin - name: Setup Gradle - uses: gradle/actions/setup-gradle@d9336dac04dea2507a617466bc058a3def92b18b # v3.4.0 + uses: gradle/actions/setup-gradle@31ae3562f68c96d481c31bc1a8a55cc1be162f83 # v3.4.1 with: add-job-summary: never cache-read-only: false diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index aea993e18a..b2db44c243 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -18,4 +18,4 @@ jobs: github.com:443 services.gradle.org:443 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - uses: gradle/actions/wrapper-validation@d9336dac04dea2507a617466bc058a3def92b18b # v3.4.0 + - uses: gradle/actions/wrapper-validation@31ae3562f68c96d481c31bc1a8a55cc1be162f83 # v3.4.1 diff --git a/build.gradle.kts b/build.gradle.kts index 947b1b5512..119004d448 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("root-caffeine-conventions") + id("root.caffeine") } allprojects { diff --git a/caffeine/build.gradle.kts b/caffeine/build.gradle.kts index de5bf107a6..1e032ec78e 100644 --- a/caffeine/build.gradle.kts +++ b/caffeine/build.gradle.kts @@ -7,8 +7,8 @@ import org.gradle.plugins.ide.eclipse.model.Classpath as EclipseClasspath import org.gradle.plugins.ide.eclipse.model.Library plugins { - id("java-library-caffeine-conventions") - id("jmh-caffeine-conventions") + id("jmh.caffeine") + id("java-library.caffeine") } sourceSets { diff --git a/examples/indexable/README.md b/examples/indexable/README.md index f5815d2f21..07a41235ae 100644 --- a/examples/indexable/README.md +++ b/examples/indexable/README.md @@ -18,7 +18,7 @@ CREATE TABLE user_info ( username varchar(255) NOT NULL, password_hash varchar(255) NOT NULL, created_on timestamp with time zone DEFAULT CURRENT_TIMESTAMP, - modified_on timestamp with time zone DEFAULT CURRENT_TIMESTAMP, + modified_on timestamp with time zone DEFAULT CURRENT_TIMESTAMP ); CREATE UNIQUE INDEX user_info_email_idx ON user_info (email); CREATE UNIQUE INDEX user_info_username_idx ON user_info (username); @@ -50,8 +50,8 @@ constraints. The value can then be queried using the typed key. ```java var cache = new IndexedCache.Builder() .primaryKey(user -> new UserById(user.id())) - .addSecondaryKey(user -> new UserByLogin(user.login())) .addSecondaryKey(user -> new UserByEmail(user.email())) + .addSecondaryKey(user -> new UserByLogin(user.username())) .expireAfterWrite(Duration.ofMinutes(5)) .maximumSize(10_000) .build(this::findUser); @@ -63,7 +63,7 @@ assertThat(userByEmail).isSameInstanceAs(userByLogin); ### How it works The sample [IndexedCache][] combines a key-value cache with an associated mapping from the -individual keys to the entry's complete set. Consistency is maintained by acquiring the write lock +individual keys to the entry's complete set. Consistency is maintained by acquiring the entry's lock through the cache using the primary key before updating the index. This prevents race conditions when the entry is concurrently updated and evicted, which could otherwise lead to missing or non-resident key associations in the index. On eviction, a listener discards the keys while holding diff --git a/examples/indexable/src/main/java/com/github/benmanes/caffeine/examples/indexable/IndexedCache.java b/examples/indexable/src/main/java/com/github/benmanes/caffeine/examples/indexable/IndexedCache.java index 67606bbacd..fe4b57086f 100644 --- a/examples/indexable/src/main/java/com/github/benmanes/caffeine/examples/indexable/IndexedCache.java +++ b/examples/indexable/src/main/java/com/github/benmanes/caffeine/examples/indexable/IndexedCache.java @@ -15,11 +15,13 @@ */ package com.github.benmanes.caffeine.examples.indexable; -import static com.google.common.collect.ImmutableSet.toImmutableSet; +import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; import java.time.Duration; -import java.util.Set; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.SequencedSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.Lock; @@ -28,7 +30,6 @@ import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Ticker; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.google.common.util.concurrent.Striped; @@ -42,29 +43,27 @@ * @author ben.manes@gmail.com (Ben Manes) */ public final class IndexedCache { - final ConcurrentMap> indexes; + final ConcurrentMap> indexes; + final SequencedSet> indexers; final Function mappingFunction; - final Function> indexer; final Striped locks; final Cache store; - private IndexedCache(Caffeine cacheBuilder, Function mappingFunction, - Function primary, Set> secondaries) { - this.locks = Striped.lock(1_000); - this.mappingFunction = mappingFunction; + private IndexedCache(Caffeine cacheBuilder, + Function mappingFunction, SequencedSet> indexers) { this.indexes = new ConcurrentHashMap<>(); + this.mappingFunction = mappingFunction; + this.locks = Striped.lock(1_024); + this.indexers = indexers; this.store = cacheBuilder - .evictionListener((key, value, cause) -> - indexes.keySet().removeAll(indexes.get(key).allKeys())) + .evictionListener((key, value, cause) -> indexes.keySet().removeAll(indexes.get(key))) .build(); - this.indexer = value -> new Index<>(primary.apply(value), - secondaries.stream().map(indexer -> indexer.apply(value)).collect(toImmutableSet())); } /** Returns the value associated with the key or {@code null} if not found. */ public V getIfPresent(K key) { var index = indexes.get(key); - return (index == null) ? null : store.getIfPresent(index.primaryKey()); + return (index == null) ? null : store.getIfPresent(index.getFirst()); } /** @@ -103,13 +102,12 @@ public V get(K key) { /** Associates the {@code value} with its keys, replacing the old value and keys if present. */ public V put(V value) { requireNonNull(value); - var index = indexer.apply(value); - return store.asMap().compute(index.primaryKey(), (key, oldValue) -> { + var index = buildIndex(value); + return store.asMap().compute(index.getFirst(), (key, oldValue) -> { if (oldValue != null) { - indexes.keySet().removeAll(Sets.difference( - indexes.get(index.primaryKey()).allKeys(), index.allKeys())); + indexes.keySet().removeAll(Sets.difference(indexes.get(index.getFirst()), index)); } - for (var indexKey : index.allKeys()) { + for (var indexKey : index) { indexes.put(indexKey, index); } return value; @@ -123,28 +121,36 @@ public void invalidate(K key) { return; } - store.asMap().computeIfPresent(index.primaryKey(), (k, v) -> { - indexes.keySet().removeAll(index.allKeys()); + store.asMap().computeIfPresent(index.getFirst(), (k, v) -> { + indexes.keySet().removeAll(indexes.get(key)); return null; }); } - private record Index(K primaryKey, Set secondaryKeys) { - public Set allKeys() { - return Sets.union(Set.of(primaryKey), secondaryKeys); + /** Returns a sequence of keys where the first item is the primary key. */ + private SequencedSet buildIndex(V value) { + var index = LinkedHashSet.newLinkedHashSet(indexers.size()); + for (var indexer : indexers) { + var key = indexer.apply(value); + if (key == null) { + checkState(!index.isEmpty(), "The primary key may not be null"); + } else { + index.add(key); + } } + return Collections.unmodifiableSequencedSet(index); } /** This builder could be extended to support most cache options, but not weak keys. */ public static final class Builder { + final SequencedSet> indexers; final Caffeine cacheBuilder; - final ImmutableSet.Builder> secondaries; - Function primary; + boolean hasPrimary; public Builder() { + indexers = new LinkedHashSet<>(); cacheBuilder = Caffeine.newBuilder(); - secondaries = ImmutableSet.builder(); } /** See {@link Caffeine#expireAfterWrite(Duration)}. */ @@ -159,22 +165,25 @@ public Builder ticker(Ticker ticker) { return this; } - /** Adds the functions to extract the primary key. */ + /** Adds the function to extract the unique, stable, non-null primary key. */ public Builder primaryKey(Function primary) { - this.primary = requireNonNull(primary); + checkState(!hasPrimary, "The primary indexing function was already defined"); + indexers.addFirst(requireNonNull(primary)); + hasPrimary = true; return this; } - /** Adds the functions to extract a secondary key. */ + /** Adds a function to extract a unique secondary key or null if absent. */ public Builder addSecondaryKey(Function secondary) { - secondaries.add(requireNonNull(secondary)); + indexers.addLast(requireNonNull(secondary)); return this; } public IndexedCache build(Function mappingFunction) { - requireNonNull(primary); - requireNonNull(mappingFunction); - return new IndexedCache(cacheBuilder, mappingFunction, primary, secondaries.build()); + checkState(hasPrimary, "The primary indexing function is required"); + requireNonNull(mappingFunction, "The mapping function to load the value is required"); + return new IndexedCache(cacheBuilder, mappingFunction, + Collections.unmodifiableSequencedSet(indexers)); } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 44fb3b5b94..238d1b7b17 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ coveralls = "2.12.2" dependency-check = "9.2.0" eclipse-collections = "12.0.0.M3" ehcache3 = "3.10.8" -errorprone-core = "2.28.0" +errorprone = "2.28.0" errorprone-plugin = "4.0.0" errorprone-support = "0.16.1" expiring-map = "0.5.11" @@ -54,7 +54,7 @@ jcommander = "1.82" jctools = "4.0.5" jfreechart = "1.5.4" jgit = "6.10.0.202406032230-r" -jmh-core = "1.37" +jmh = "1.37" jmh-plugin = "0.7.2" jmh-report = "0.9.6" joor = "0.9.15" @@ -68,7 +68,7 @@ kotlin = "2.0.0" lincheck = "2.32" mockito = "5.12.0" nexus-publish = "2.0.0" -nullaway-core = "0.11.0" +nullaway = "0.11.0" nullaway-plugin = "2.0.0" okhttp-bom = "4.12.0" okio-bom = "3.9.0" @@ -84,9 +84,9 @@ slf4j = "2.0.13" slf4j-test = "3.0.1" snakeyaml = "2.2" sonarqube = "5.0.0.4638" +spotbugs = "4.8.5" spotbugs-contrib = "7.6.4" -spotbugs-core = "4.8.5" -spotbugs-plugin = "6.0.16" +spotbugs-plugin = "6.0.17" stream = "2.9.8" tcache = "2.0.1" testng = "7.10.2" @@ -104,13 +104,12 @@ auto-value-annotations = { module = "com.google.auto.value:auto-value-annotation auto-value-processor = { module = "com.google.auto.value:auto-value", version.ref = "auto-value" } awaitility = { module = "org.awaitility:awaitility", version.ref = "awaitility" } bcel = { module = "org.apache.bcel:bcel", version.ref = "bcel" } -bnd = { module = "biz.aQute.bnd:biz.aQute.bnd.gradle", version.ref = "bnd" } bouncycastle-jdk18on = { module = "org.bouncycastle:bcprov-jdk18on", version.ref = "bouncycastle-jdk18on" } cache2k = { module = "org.cache2k:cache2k-core", version.ref = "cache2k" } caffeine = { module = "com.github.ben-manes.caffeine:caffeine", version.ref = "caffeine" } checker-annotations = { module = "org.checkerframework:checker-qual", version.ref = "checker-framework" } checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" } -coherence-core = { module = "com.oracle.coherence.ce:coherence", version.ref = "coherence" } +coherence = { module = "com.oracle.coherence.ce:coherence", version.ref = "coherence" } commons-collections4 = { module = "org.apache.commons:commons-collections4", version.ref = "commons-collections4" } commons-compress = { module = "org.apache.commons:commons-compress", version.ref = "commons-compress" } commons-io = { module = "commons-io:commons-io", version.ref = "commons-io" } @@ -119,15 +118,12 @@ commons-math3 = { module = "org.apache.commons:commons-math3", version.ref = "co commons-text = { module = "org.apache.commons:commons-text", version.ref = "commons-text" } concurrentlinkedhashmap = { module = "com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru", version.ref = "concurrentlinkedhashmap" } config = { module = "com.typesafe:config", version.ref = "config" } -coveralls = { module = "gradle.plugin.org.kt3k.gradle.plugin:coveralls-gradle-plugin", version.ref = "coveralls" } -dependency-check = { module = "org.owasp:dependency-check-gradle", version.ref = "dependency-check" } dependency-versions = { module = "com.github.ben-manes:gradle-versions-plugin", version.ref = "versions" } eclipse-collections-testutils = { module = "org.eclipse.collections:eclipse-collections-testutils", version.ref = "eclipse-collections" } ehcache3 = { module = "org.ehcache:ehcache", version.ref = "ehcache3" } -errorprone-annotations = { module = "com.google.errorprone:error_prone_annotations", version.ref = "errorprone-core" } -errorprone-core = { module = "com.google.errorprone:error_prone_core", version.ref = "errorprone-core" } +errorprone = { module = "com.google.errorprone:error_prone_core", version.ref = "errorprone" } +errorprone-annotations = { module = "com.google.errorprone:error_prone_annotations", version.ref = "errorprone" } errorprone-mockito = { module = "org.mockito:mockito-errorprone", version.ref = "mockito" } -errorprone-plugin = { module = "net.ltgt.gradle:gradle-errorprone-plugin", version.ref = "errorprone-plugin" } errorprone-support = { module = "tech.picnic.error-prone-support:error-prone-contrib", version.ref = "errorprone-support" } errorprone-support-refaster = { module = "tech.picnic.error-prone-support:refaster-runner", version.ref = "errorprone-support" } expiring-map = { module = "net.jodah:expiringmap", version.ref = "expiring-map" } @@ -137,7 +133,6 @@ felix-framework = { module = "org.apache.felix:org.apache.felix.framework", vers felix-scr = { module = "org.apache.felix:org.apache.felix.scr", version.ref = "felix-scr" } findsecbugs = { module = "com.h3xstream.findsecbugs:findsecbugs-plugin", version.ref = "findsecbugs" } flip-tables = { module = "com.jakewharton.fliptables:fliptables", version.ref = "flip-tables" } -forbidden-apis = { module = "de.thetaphi:forbiddenapis", version.ref = "forbidden-apis" } google-java-format = { module = "com.google.googlejavaformat:google-java-format", version.ref = "google-java-format" } guava = { module = "com.google.guava:guava", version.ref = "guava" } guava-testlib = { module = "com.google.guava:guava-testlib", version.ref = "guava" } @@ -146,7 +141,6 @@ h2 = { module = "com.h2database:h2", version.ref = "h2" } hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" } hazelcast = { module = "com.hazelcast:hazelcast", version.ref = "hazelcast" } httpclient = { module = "org.apache.httpcomponents:httpclient", version.ref = "httpclient" } -idea = { module = "gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext", version.ref = "idea" } jackrabbit = { module = "org.apache.jackrabbit:oak-core", version.ref = "jackrabbit" } jackson-bom = { module = "com.fasterxml.jackson:jackson-bom", version.ref = "jackson" } jacoco = { module = "org.jacoco:jacoco", version.ref = "jacoco" } @@ -164,9 +158,7 @@ jcommander = { module = "com.beust:jcommander", version.ref = "jcommander" } jctools = { module = "org.jctools:jctools-core", version.ref = "jctools" } jfreechart = { module = "org.jfree:jfreechart", version.ref = "jfreechart" } jgit = { module = "org.eclipse.jgit:org.eclipse.jgit", version.ref = "jgit" } -jmh-core = { module = "org.openjdk.jmh:jmh-core", version.ref = "jmh-core" } -jmh-plugin = { module = "me.champeau.jmh:jmh-gradle-plugin", version.ref = "jmh-plugin" } -jmh-report = { module = "gradle.plugin.io.morethan.jmhreport:gradle-jmh-report", version.ref = "jmh-report" } +jmh = { module = "org.openjdk.jmh:jmh-core", version.ref = "jmh" } joor = { module = "org.jooq:joor", version.ref = "joor" } json-bind = { module = "javax.json.bind:javax.json.bind-api", version.ref = "json-bind" } jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } @@ -176,13 +168,10 @@ junit5-bom = { module = "org.junit:junit-bom", version.ref = "junit5" } junit5-launcher = { module = "org.junit.platform:junit-platform-launcher" } junit5-testng = { module = "org.junit.support:testng-engine", version.ref = "junit-testng" } junit5-vintage = { module = "org.junit.vintage:junit-vintage-engine", version.ref = "junit5" } -jvm-dependency-conflict-resolution = { module = "org.gradlex:jvm-dependency-conflict-resolution", version.ref = "jvm-dependency-conflict-resolution" } kotlin-bom = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "kotlin" } lincheck = { module = "org.jetbrains.kotlinx:lincheck-jvm", version.ref = "lincheck" } mockito = { module = "org.mockito:mockito-core", version.ref = "mockito" } -nexus-publish = { module = "io.github.gradle-nexus:publish-plugin", version.ref = "nexus-publish" } -nullaway-core = { module = "com.uber.nullaway:nullaway", version.ref = "nullaway-core" } -nullaway-plugin = { module = "net.ltgt.gradle:gradle-nullaway-plugin", version.ref = "nullaway-plugin" } +nullaway = { module = "com.uber.nullaway:nullaway", version.ref = "nullaway" } okhttp-bom = { module = "com.squareup.okhttp3:okhttp-bom", version.ref = "okhttp-bom" } okio-bom = { module = "com.squareup.okio:okio-bom", version.ref = "okio-bom" } osgi-annotations = { module = "org.osgi:org.osgi.service.component.annotations", version.ref = "osgi-annotations" } @@ -203,10 +192,8 @@ slf4j-jul-bridge = { module = "org.slf4j:jul-to-slf4j", version.ref = "slf4j" } slf4j-nop = { module = "org.slf4j:slf4j-nop", version.ref = "slf4j" } slf4j-test = { module = "com.github.valfirst:slf4j-test", version.ref = "slf4j-test" } snakeyaml = { module = "org.yaml:snakeyaml", version.ref = "snakeyaml" } -sonarqube = { module = "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin", version.ref = "sonarqube" } +spotbugs = { module = "com.github.spotbugs:spotbugs", version.ref = "spotbugs" } spotbugs-contrib = { module = "com.mebigfatguy.sb-contrib:sb-contrib", version.ref = "spotbugs-contrib" } -spotbugs-core = { module = "com.github.spotbugs:spotbugs", version.ref = "spotbugs-core" } -spotbugs-plugin = { module = "com.github.spotbugs.snom:spotbugs-gradle-plugin", version.ref = "spotbugs-plugin" } stream = { module = "com.clearspring.analytics:stream", version.ref = "stream" } tcache = { module = "com.trivago:triava", version.ref = "tcache" } testng = { module = "org.testng:testng", version.ref = "testng" } @@ -218,11 +205,10 @@ zero-allocation-hashing = { module = "net.openhft:zero-allocation-hashing", vers zstd = { module = "com.github.luben:zstd-jni", version.ref = "zstd" } [bundles] -coherence = ["coherence-core", "json-bind"] +coherence = ["coherence", "json-bind"] constraints = ["bcel", "bouncycastle-jdk18on", "commons-compress", "commons-text", "h2", "httpclient", "guava", "jcommander", "jgit", "jsoup", "protobuf", "snakeyaml" ] errorprone-support = [ "errorprone-support", "errorprone-support-refaster" ] -jmh = ["jmh-core", "jmh-plugin", "jmh-report"] junit = ["junit4", "junit5"] junit-engines = ["junit5-vintage", "junit5-testng"] osgi-test-compile = ["pax-exam-junit4"] @@ -234,4 +220,17 @@ slf4j-nop = ["slf4j-jdk-platform-logging", "slf4j-nop"] slf4j-test = ["slf4j-jdk-platform-logging", "slf4j-jul-bridge", "slf4j-test"] [plugins] +bnd = { id = "biz.aQute.bnd", version.ref = "bnd" } +coveralls = { id = "com.github.kt3k.coveralls", version.ref = "coveralls" } +dependency-check = { id = "org.owasp.dependencycheck", version.ref = "dependency-check" } +errorprone = { id = "net.ltgt.errorprone", version.ref = "errorprone-plugin" } +forbidden-apis = { id = "de.thetaphi.forbiddenapis", version.ref = "forbidden-apis" } +idea = { id = "org.jetbrains.gradle.plugin.idea-ext", version.ref = "idea" } +jmh = { id = "me.champeau.jmh", version.ref = "jmh-plugin" } +jmh-report = { id = "io.morethan.jmhreport", version.ref = "jmh-report" } +jvm-dependency-conflict-resolution = { id = "org.gradlex.jvm-dependency-conflict-resolution", version.ref = "jvm-dependency-conflict-resolution" } +nexus-publish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexus-publish" } +nullaway = { id = "net.ltgt.nullaway", version.ref = "nullaway-plugin" } +sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" } +spotbugs = { id = "com.github.spotbugs", version.ref = "spotbugs-plugin" } versions = { id = "com.github.ben-manes.versions", version.ref = "versions" } diff --git a/gradle/plugins/build.gradle.kts b/gradle/plugins/build.gradle.kts index e5cca2cef2..152739bd86 100644 --- a/gradle/plugins/build.gradle.kts +++ b/gradle/plugins/build.gradle.kts @@ -19,21 +19,24 @@ plugins { java.toolchain.languageVersion = JavaLanguageVersion.of(17) dependencies { - implementation(libs.bnd) - implementation(libs.idea) + implementation(libs.jmh) implementation(libs.guava) - implementation(libs.sonarqube) - implementation(libs.bundles.jmh) implementation(libs.bundles.pmd) - implementation(libs.nexus.publish) - implementation(libs.forbidden.apis) - implementation(libs.nullaway.plugin) - implementation(libs.spotbugs.plugin) - implementation(libs.dependency.check) - implementation(libs.errorprone.plugin) - implementation(libs.dependency.versions) - implementation(libs.jvm.dependency.conflict.resolution) - implementation(libs.coveralls) { + + implementation(plugin(libs.plugins.bnd)) + implementation(plugin(libs.plugins.idea)) + implementation(plugin(libs.plugins.nullaway)) + implementation(plugin(libs.plugins.spotbugs)) + implementation(plugin(libs.plugins.versions)) + implementation(plugin(libs.plugins.sonarqube)) + implementation(plugin(libs.plugins.jmh.report)) + implementation(plugin(libs.plugins.errorprone)) + implementation(plugin(libs.plugins.nexus.publish)) + implementation(plugin(libs.plugins.forbidden.apis)) + implementation(plugin(libs.plugins.jmh.asProvider())) + implementation(plugin(libs.plugins.dependency.check)) + implementation(plugin(libs.plugins.jvm.dependency.conflict.resolution)) + implementation(plugin(libs.plugins.coveralls)) { exclude(group = "net.sourceforge.nekohtml", module = "nekohtml") } @@ -71,6 +74,11 @@ tasks.withType { } } +fun plugin(plugin: Provider): Provider { + // https://docs.gradle.org/current/userguide/plugins.html#sec:plugin_markers + return plugin.map { "${it.pluginId}:${it.pluginId}.gradle.plugin:${it.version}" } +} + fun setProjectEncoding() { val prefs = file(".settings/org.eclipse.core.resources.prefs") if (!prefs.exists()) { diff --git a/gradle/plugins/src/main/kotlin/analyze/jmh-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/analyze/jmh.caffeine.gradle.kts similarity index 98% rename from gradle/plugins/src/main/kotlin/analyze/jmh-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/analyze/jmh.caffeine.gradle.kts index 7a094ae9b3..3c9d3aa522 100644 --- a/gradle/plugins/src/main/kotlin/analyze/jmh-caffeine-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/analyze/jmh.caffeine.gradle.kts @@ -23,7 +23,7 @@ dependencies { } jmh { - jmhVersion = libs.versions.jmh.core + jmhVersion = libs.versions.jmh.asProvider() benchmarkMode.add("thrpt") warmupIterations = 3 diff --git a/gradle/plugins/src/main/kotlin/analyze/object-layout-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/analyze/object-layout.caffeine.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/analyze/object-layout-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/analyze/object-layout.caffeine.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/lifecycle/auto-value-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/lifecycle/auto-value.caffeine.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/lifecycle/auto-value-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/lifecycle/auto-value.caffeine.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/lifecycle/base-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/lifecycle/base.caffeine.gradle.kts similarity index 92% rename from gradle/plugins/src/main/kotlin/lifecycle/base-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/lifecycle/base.caffeine.gradle.kts index e954e3ecb3..c866664c8f 100644 --- a/gradle/plugins/src/main/kotlin/lifecycle/base-caffeine-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/lifecycle/base.caffeine.gradle.kts @@ -1,7 +1,7 @@ plugins { idea `jvm-ecosystem` - id("eclipse-caffeine-conventions") + id("eclipse.caffeine") id("org.gradlex.jvm-dependency-conflict-resolution") } diff --git a/gradle/plugins/src/main/kotlin/lifecycle/eclipse-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/lifecycle/eclipse.caffeine.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/lifecycle/eclipse-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/lifecycle/eclipse.caffeine.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/lifecycle/intellij-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/lifecycle/intellij.caffeine.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/lifecycle/intellij-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/lifecycle/intellij.caffeine.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/lifecycle/java-library-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/lifecycle/java-library.caffeine.gradle.kts similarity index 87% rename from gradle/plugins/src/main/kotlin/lifecycle/java-library-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/lifecycle/java-library.caffeine.gradle.kts index b4e51e8b88..296a126110 100644 --- a/gradle/plugins/src/main/kotlin/lifecycle/java-library-caffeine-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/lifecycle/java-library.caffeine.gradle.kts @@ -1,16 +1,16 @@ plugins { `java-library` + id("pmd.caffeine") + id("base.caffeine") + id("jacoco.caffeine") + id("publish.caffeine") + id("testing.caffeine") + id("spotbugs.caffeine") + id("checkstyle.caffeine") + id("errorprone.caffeine") id("biz.aQute.bnd.builder") - id("pmd-caffeine-conventions") - id("base-caffeine-conventions") - id("jacoco-caffeine-conventions") - id("publish-caffeine-conventions") - id("testing-caffeine-conventions") - id("spotbugs-caffeine-conventions") - id("checkstyle-caffeine-conventions") - id("errorprone-caffeine-conventions") - id("object-layout-caffeine-conventions") - id("forbidden-apis-caffeine-conventions") + id("object-layout.caffeine") + id("forbidden-apis.caffeine") } dependencies { diff --git a/gradle/plugins/src/main/kotlin/lifecycle/publish-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/lifecycle/publish.caffeine.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/lifecycle/publish-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/lifecycle/publish.caffeine.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/lifecycle/root-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/lifecycle/root-caffeine-conventions.gradle.kts deleted file mode 100644 index 647f0b03a1..0000000000 --- a/gradle/plugins/src/main/kotlin/lifecycle/root-caffeine-conventions.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -plugins { - id("base-caffeine-conventions") - id("coverage-caffeine-conventions") - id("intellij-caffeine-conventions") - id("sonarqube-caffeine-conventions") - id("io.github.gradle-nexus.publish-plugin") - id("dependency-check-caffeine-conventions") - id("dependency-versions-caffeine-conventions") -} - -nexusPublishing { - repositories { - sonatype() - } -} diff --git a/gradle/plugins/src/main/kotlin/lifecycle/root.caffeine.gradle.kts b/gradle/plugins/src/main/kotlin/lifecycle/root.caffeine.gradle.kts new file mode 100644 index 0000000000..7d8c6d2ff3 --- /dev/null +++ b/gradle/plugins/src/main/kotlin/lifecycle/root.caffeine.gradle.kts @@ -0,0 +1,15 @@ +plugins { + id("base.caffeine") + id("coverage.caffeine") + id("intellij.caffeine") + id("versions.caffeine") + id("sonarqube.caffeine") + id("dependency-check.caffeine") + id("io.github.gradle-nexus.publish-plugin") +} + +nexusPublishing { + repositories { + sonatype() + } +} diff --git a/gradle/plugins/src/main/kotlin/lifecycle/testing-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/lifecycle/testing.caffeine.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/lifecycle/testing-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/lifecycle/testing.caffeine.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/lifecycle/dependency-versions-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/lifecycle/versions.caffeine.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/lifecycle/dependency-versions-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/lifecycle/versions.caffeine.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/quality/checkstyle-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/quality/checkstyle.caffeine.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/quality/checkstyle-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/quality/checkstyle.caffeine.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/quality/coverage-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/quality/coverage.caffeine.gradle.kts similarity index 98% rename from gradle/plugins/src/main/kotlin/quality/coverage-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/quality/coverage.caffeine.gradle.kts index cec5729e0b..809e0bfc02 100644 --- a/gradle/plugins/src/main/kotlin/quality/coverage-caffeine-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/quality/coverage.caffeine.gradle.kts @@ -2,8 +2,8 @@ import org.gradle.api.plugins.JavaPluginExtension plugins { jacoco + id("jacoco.caffeine") id("com.github.kt3k.coveralls") - id("jacoco-caffeine-conventions") } dependencies { diff --git a/gradle/plugins/src/main/kotlin/quality/dependency-check-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/quality/dependency-check.caffeine.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/quality/dependency-check-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/quality/dependency-check.caffeine.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/quality/errorprone-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/quality/errorprone.caffeine.gradle.kts similarity index 98% rename from gradle/plugins/src/main/kotlin/quality/errorprone-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/quality/errorprone.caffeine.gradle.kts index 2a13d26689..4470462fc6 100644 --- a/gradle/plugins/src/main/kotlin/quality/errorprone-caffeine-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/quality/errorprone.caffeine.gradle.kts @@ -5,17 +5,17 @@ import net.ltgt.gradle.errorprone.errorprone import net.ltgt.gradle.nullaway.nullaway plugins { - id("net.ltgt.errorprone") id("net.ltgt.nullaway") + id("net.ltgt.errorprone") } dependencies { - errorprone(libs.errorprone.core) { + errorprone(libs.errorprone) { exclude(group = "com.github.ben-manes.caffeine") } errorprone(layout.buildDirectory.files("errorprone/caffeine-${libs.versions.caffeine.get()}.jar")) - errorprone(libs.nullaway.core) + errorprone(libs.nullaway) errorprone(libs.errorprone.mockito) errorprone(libs.bundles.errorprone.support) } diff --git a/gradle/plugins/src/main/kotlin/quality/forbidden-apis-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/quality/forbidden-apis.caffeine.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/quality/forbidden-apis-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/quality/forbidden-apis.caffeine.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/quality/jacoco-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/quality/jacoco.caffeine.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/quality/jacoco-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/quality/jacoco.caffeine.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/quality/pmd-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/quality/pmd.caffeine.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/quality/pmd-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/quality/pmd.caffeine.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/quality/sonarqube-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/quality/sonarqube.caffeine.gradle.kts similarity index 94% rename from gradle/plugins/src/main/kotlin/quality/sonarqube-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/quality/sonarqube.caffeine.gradle.kts index 44a83e7234..cf730cc6d1 100644 --- a/gradle/plugins/src/main/kotlin/quality/sonarqube-caffeine-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/quality/sonarqube.caffeine.gradle.kts @@ -1,6 +1,6 @@ plugins { id("org.sonarqube") - id("coverage-caffeine-conventions") + id("coverage.caffeine") } sonarqube { diff --git a/gradle/plugins/src/main/kotlin/quality/spotbugs-caffeine-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/quality/spotbugs.caffeine.gradle.kts similarity index 89% rename from gradle/plugins/src/main/kotlin/quality/spotbugs-caffeine-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/quality/spotbugs.caffeine.gradle.kts index f0cfc9fcc9..3d5ed57cb8 100644 --- a/gradle/plugins/src/main/kotlin/quality/spotbugs-caffeine-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/quality/spotbugs.caffeine.gradle.kts @@ -7,7 +7,7 @@ plugins { } dependencies { - spotbugs(libs.spotbugs.core) + spotbugs(libs.spotbugs) spotbugsPlugins(libs.findsecbugs) spotbugsPlugins(libs.spotbugs.contrib) } @@ -16,7 +16,7 @@ spotbugs { effort = MAX reportLevel = LOW useJavaToolchains = true - toolVersion = libs.versions.spotbugs.core + toolVersion = libs.versions.spotbugs.asProvider() excludeFilter = rootProject.layout.projectDirectory.file("gradle/config/spotbugs/exclude.xml") } diff --git a/guava/build.gradle.kts b/guava/build.gradle.kts index a11bae1075..3fdc654bb5 100644 --- a/guava/build.gradle.kts +++ b/guava/build.gradle.kts @@ -2,7 +2,7 @@ import de.thetaphi.forbiddenapis.gradle.CheckForbiddenApis plugins { - id("java-library-caffeine-conventions") + id("java-library.caffeine") } dependencies { diff --git a/jcache/build.gradle.kts b/jcache/build.gradle.kts index b8c5757de3..f96d674c99 100644 --- a/jcache/build.gradle.kts +++ b/jcache/build.gradle.kts @@ -4,7 +4,7 @@ import org.gradle.plugins.ide.eclipse.model.Classpath import org.gradle.plugins.ide.eclipse.model.Library plugins { - id("java-library-caffeine-conventions") + id("java-library.caffeine") } sourceSets { diff --git a/simulator/build.gradle.kts b/simulator/build.gradle.kts index b5ed6dab5b..fb5b991001 100644 --- a/simulator/build.gradle.kts +++ b/simulator/build.gradle.kts @@ -6,8 +6,8 @@ import net.ltgt.gradle.nullaway.nullaway plugins { id("application") - id("auto-value-caffeine-conventions") - id("java-library-caffeine-conventions") + id("auto-value.caffeine") + id("java-library.caffeine") } dependencies {