From 84ce5aff8abd44d119286251f105f509547c7eb3 Mon Sep 17 00:00:00 2001 From: Aurelien Date: Wed, 25 Feb 2026 14:51:17 +0100 Subject: [PATCH 1/2] - Upgrade slf4j-api from 1.7.36 to 2.0.17 (required by logback 1.5.26) and add slf4j exclusions on Terracotta dependencies (statistics, offheap-store, sizeof, terracotta-utilities-tools) that declare the conflicting 1.7 range - Fix Java deprecation/removal warnings treated as errors by -Werror - Add missing javax.xml.bind:jaxb-api to xjcToolJakarta configuration to fix ClassNotFoundException during Jakarta XJC code generation - Add javadocAdd/jakartaJavadocAdd classpath configurations in ehcache/build.gradle (spotbugs-annotations, jaxb-api) and clustered/ehcache-clustered/build.gradle (ehcache-common-api, ehcache-common) required for javadocJar tasks in the assemble chain - Backport of TDB-19854 (master/3.12): upgrade SpotBugs to 4.9.8, AssertJ to 3.27.7, Mockito to 5.12.0, ByteBuddy to 1.18.3; rewrite demos to use embedded Jetty 12 instead of Gretty; refactor SPI tests to use JUnit 4 rules; update Mockito 5 API usage (MockitoAnnotations, ArgumentMatchers); fix SpotBugs annotation usages - Address compilation errors and test failures introduced by upgrading slf4j from 1.7.x to 2.0.17 - PR build with java 17 - Fix async assertion (implemented manually since awaitility is not present) --- azure-pipelines.yml | 63 ++++++----------- .../conventions/CheckstyleConvention.java | 18 +++++ .../build/conventions/JavaConvention.java | 17 ++++- .../build/conventions/SpotbugsConvention.java | 10 ++- clustered/ehcache-client/build.gradle | 8 ++- .../service/DefaultClusteringService.java | 1 + .../store/CommonServerStoreProxy.java | 1 + .../DefaultClusteringServiceDestroyTest.java | 6 +- .../StateRepositoryWhitelistingTest.java | 4 +- .../internal/store/ClusteredStoreTest.java | 4 +- clustered/ehcache-clustered/build.gradle | 10 +++ .../common/internal/store/ValueWrapper.java | 1 - clustered/ehcache-common/build.gradle | 4 +- .../Store/WhitelistedUnmarshallingTest.java | 18 ++--- .../internal/messages/ChainCodecTest.java | 10 +-- .../internal/messages/ResponseCodecTest.java | 2 +- clustered/integration-test/build.gradle | 24 ++++++- .../ClusteringManagementServiceTest.java | 10 +-- ...dCacheOpsReplicationMultiThreadedTest.java | 11 ++- clustered/osgi-test/build.gradle | 15 +++- clustered/server/ehcache-entity/build.gradle | 12 +++- clustered/server/ehcache-service/build.gradle | 13 +++- .../offheap/OffHeapChainStorageEngine.java | 4 +- .../server/offheap/ChainMapExtensionTest.java | 2 +- .../server/offheap/ChainMapTest.java | 2 +- config/checkstyle.xml | 15 +++- .../internal/store/SPIStoreTester.java | 31 +++++++++ .../internal/store/StoreContainsKeyTest.java | 9 +-- .../ehcache/internal/store/StoreGetTest.java | 9 +-- .../internal/store/StorePutIfAbsentTest.java | 18 ++--- .../ehcache/internal/store/StorePutTest.java | 18 +---- .../internal/store/StoreRemoveKeyTest.java | 9 +-- .../store/StoreRemoveKeyValueTest.java | 18 +---- .../store/StoreReplaceKeyValueTest.java | 18 +---- demos/00-NoCache/build.gradle | 7 ++ .../ehcache/demos/peeper/PeeperServer.java | 26 +++++++ .../ehcache/demos/peeper/PeeperServlet.java | 10 +-- .../peeper/PeeperServletContextListener.java | 6 +- demos/01-CacheAside/build.gradle | 7 ++ .../config/checkstyle-suppressions.xml | 3 +- .../ehcache/demos/peeper/PeeperServer.java | 26 +++++++ .../ehcache/demos/peeper/PeeperServlet.java | 10 +-- .../peeper/PeeperServletContextListener.java | 6 +- demos/build.gradle | 69 ++++++------------- demos/config/checkstyle-suppressions.xml | 9 +++ .../demos/server/EmbeddedPeeperServer.java | 55 +++++++++++++++ docs/src/docs/asciidoc/user/examples.adoc | 6 +- ehcache-107/build.gradle | 4 +- .../ParsesConfigurationExtensionTest.java | 4 +- ehcache-core/build.gradle | 4 +- .../org/ehcache/core/util/ClassLoading.java | 9 ++- .../org/ehcache/core/EhcacheManagerTest.java | 25 ++++--- .../org/ehcache/core/PrefixLoggerTest.java | 12 ++-- ehcache-impl/build.gradle | 16 +++-- .../builders/UserManagedCacheBuilder.java | 2 +- .../commonslang/reflect/MemberUtils.java | 1 + .../internal/store/tiering/TieredStore.java | 4 +- .../ehcache/impl/persistence/FileUtils.java | 1 - .../serialization/PlainJavaSerializer.java | 2 +- .../CacheConfigurationBuilderTest.java | 16 +++-- .../ehcache/docs/ConfigurationDerivation.java | 2 +- .../store/tiering/TieredStoreTest.java | 9 +-- .../impl/serialization/AddedFieldTest.java | 4 +- .../serialization/AddedSuperClassTest.java | 4 +- .../CompactJavaSerializerClassLoaderTest.java | 4 +- ...mpactJavaSerializerClassUnloadingTest.java | 2 +- .../impl/serialization/GetFieldTest.java | 2 +- .../impl/serialization/JavaSerializer.java | 1 + .../impl/serialization/PutFieldTest.java | 4 +- .../serialization/ReadObjectNoDataTest.java | 2 +- .../SerializeAfterEvolutionTest.java | 4 +- .../concurrent/ConcurrentHashMap.java | 1 - ehcache-management/build.gradle | 9 ++- .../DefaultManagementRegistryServiceTest.java | 8 +-- ehcache-transactions/build.gradle | 4 +- .../xa/internal/SoftLockSerializer.java | 1 + .../LookupTransactionManagerProvider.java | 4 +- .../LookupTransactionManagerProvider.java | 4 +- .../transactions/xa/utils/JavaSerializer.java | 1 + ehcache-xml/build.gradle | 1 + .../java/org/ehcache/xml/ParsingUtil.java | 7 +- .../org/ehcache/xml/ConfigurationParser.java | 6 +- .../xml/CoreCacheConfigurationParser.java | 8 +-- .../org/ehcache/xml/XmlConfiguration.java | 8 +-- .../org/ehcache/xml/ConfigurationParser.java | 6 +- .../xml/CoreCacheConfigurationParser.java | 8 +-- .../org/ehcache/xml/XmlConfiguration.java | 8 +-- .../xml/IntegrationConfigurationTest.java | 4 +- ehcache/build.gradle | 20 +++++- gradle.properties | 8 ++- integration-test/build.gradle | 4 +- .../integration/OverSizeMappingTest.java | 2 +- osgi-test/build.gradle | 7 ++ .../java/org/ehcache/osgi/OsgiTestUtils.java | 8 +++ settings.gradle | 1 - 95 files changed, 574 insertions(+), 357 deletions(-) create mode 100644 demos/00-NoCache/build.gradle create mode 100644 demos/00-NoCache/src/main/java/org/ehcache/demos/peeper/PeeperServer.java create mode 100644 demos/01-CacheAside/build.gradle create mode 100644 demos/01-CacheAside/src/main/java/org/ehcache/demos/peeper/PeeperServer.java create mode 100644 demos/config/checkstyle-suppressions.xml create mode 100644 demos/src/main/java/org/ehcache/demos/server/EmbeddedPeeperServer.java diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 50375a8b65..f2005e0b74 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -25,44 +25,25 @@ resources: name: terracotta/terracotta jobs: -- template: build-templates/gradle-common.yml@templates - parameters: - jdkVersion: '1.8' - jobName: 'LinuxJava8' - gradleTasks: 'check -x dependencyCheckAggregate' - -- template: build-templates/gradle-common.yml@templates - parameters: - jdkVersion: '1.8' - options: '-PtestVM=java11Home' - jobName: 'LinuxJava11' - gradleTasks: 'check -x dependencyCheckAggregate' - -- template: build-templates/gradle-common.yml@templates - parameters: - jdkVersion: '1.8' - options: '-PtestVM=java17Home' - jobName: 'LinuxJava17' - gradleTasks: 'check -x dependencyCheckAggregate' - -- template: build-templates/gradle-common.yml@templates - parameters: - jdkVersion: '1.8' - options: '-PtestVM=java21Home' - jobName: 'LinuxJava21' - gradleTasks: 'check -x dependencyCheckAggregate' - -- template: build-templates/gradle-common.yml@templates - parameters: - vmImage: 'windows-latest' - jdkVersion: '1.8' - jobName: 'WindowsJava8' - gradleTasks: 'check -x dependencyCheckAggregate' - -- template: build-templates/gradle-common.yml@templates - parameters: - vmImage: 'windows-latest' - jdkVersion: '1.8' - options: '-PtestVM=java21Home' - jobName: 'WindowsJava21' - gradleTasks: 'check -x dependencyCheckAggregate' + - template: build-templates/gradle-common.yml@templates + parameters: + jdkVersion: '17' + options: '-PtestVM=java17Home' + jobName: 'LinuxJava17' + gradleTasks: 'check -x dependencyCheckAggregate' + + - template: build-templates/gradle-common.yml@templates + parameters: + jdkVersion: '17' + options: '-PtestVM=java21Home' + jobName: 'LinuxJava21' + gradleTasks: 'check -x dependencyCheckAggregate' + + + - template: build-templates/gradle-common.yml@templates + parameters: + vmImage: 'windows-latest' + jdkVersion: '17' + options: '-PtestVM=java21Home' + jobName: 'WindowsJava21' + gradleTasks: 'check -x dependencyCheckAggregate' diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/CheckstyleConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/CheckstyleConvention.java index 0973fc1237..e4e5f0c88d 100644 --- a/build-logic/src/main/java/org/ehcache/build/conventions/CheckstyleConvention.java +++ b/build-logic/src/main/java/org/ehcache/build/conventions/CheckstyleConvention.java @@ -13,10 +13,28 @@ public void apply(Project project) { project.getPlugins().apply(CheckstylePlugin.class); project.getExtensions().configure(CheckstyleExtension.class, checkstyle -> { + checkstyle.setToolVersion("10.18.1"); checkstyle.setConfigFile(project.getRootProject().file("config/checkstyle.xml")); Map properties = checkstyle.getConfigProperties(); properties.put("projectDir", project.getProjectDir()); properties.put("rootDir", project.getRootDir()); }); + + project.getConfigurations().named("checkstyle", config -> { + config.getResolutionStrategy().dependencySubstitution(subs -> { + subs.substitute(subs.module("org.codehaus.plexus:plexus-utils:3.1.1")) + .using(subs.module("org.codehaus.plexus:plexus-utils:3.3.0")) + .because("Checkstyle 10.18.1 pulls mismatched plexus-utils versions"); + subs.substitute(subs.module("org.apache.commons:commons-lang3:3.7")) + .using(subs.module("org.apache.commons:commons-lang3:3.8.1")) + .because("Checkstyle transitives mix commons-lang3 versions"); + subs.substitute(subs.module("org.apache.httpcomponents:httpcore:4.4.13")) + .using(subs.module("org.apache.httpcomponents:httpcore:4.4.14")) + .because("Align httpcore to latest bugfix release"); + subs.substitute(subs.module("commons-codec:commons-codec:1.11")) + .using(subs.module("commons-codec:commons-codec:1.15")) + .because("Checkstyle transitive dependencies depend on different commons-codec versions"); + }); + }); } } diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/JavaConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/JavaConvention.java index f26ae8e8d4..e954d691d7 100644 --- a/build-logic/src/main/java/org/ehcache/build/conventions/JavaConvention.java +++ b/build-logic/src/main/java/org/ehcache/build/conventions/JavaConvention.java @@ -1,7 +1,9 @@ package org.ehcache.build.conventions; +import java.util.Map; import org.gradle.api.Plugin; import org.gradle.api.Project; +import org.gradle.api.artifacts.ModuleDependency; import org.gradle.api.artifacts.dsl.DependencyHandler; import org.gradle.api.plugins.JavaPlugin; @@ -20,9 +22,14 @@ public void apply(Project project) { dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "junit:junit:" + project.property("junitVersion")); dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.assertj:assertj-core:" + project.property("assertjVersion")); + dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "net.bytebuddy:byte-buddy:" + project.property("byteBuddyVersion")); + dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "net.bytebuddy:byte-buddy-agent:" + project.property("byteBuddyVersion")); dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.hamcrest:hamcrest:" + project.property("hamcrestVersion")); dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.mockito:mockito-core:" + project.property("mockitoVersion")); - dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.terracotta:terracotta-utilities-test-tools:" + project.property("terracottaUtilitiesVersion")); + ModuleDependency md = (ModuleDependency)dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.terracotta:terracotta-utilities-test-tools:" + project.property("terracottaUtilitiesVersion")); + if (md != null) { + md.exclude(Map.of("group", "org.slf4j")); + } project.getConfigurations().all(config -> { config.getResolutionStrategy().dependencySubstitution(subs -> { @@ -30,6 +37,14 @@ public void apply(Project project) { subs.substitute(subs.module("org.hamcrest:hamcrest-library:1.3")).with(subs.module("org.hamcrest:hamcrest-library:" + project.property("hamcrestVersion"))); subs.substitute(subs.module("junit:junit:4.12")).using(subs.module("junit:junit:4.13.1")); }); + config.getResolutionStrategy().eachDependency(details -> { + String group = details.getRequested().getGroup(); + String name = details.getRequested().getName(); + if ("net.bytebuddy".equals(group) && ("byte-buddy".equals(name) || "byte-buddy-agent".equals(name))) { + details.useVersion(project.property("byteBuddyVersion").toString()); + details.because("Align Byte Buddy family versions across AssertJ and Mockito"); + } + }); }); } } diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/SpotbugsConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/SpotbugsConvention.java index 9815385453..c48c6093b3 100644 --- a/build-logic/src/main/java/org/ehcache/build/conventions/SpotbugsConvention.java +++ b/build-logic/src/main/java/org/ehcache/build/conventions/SpotbugsConvention.java @@ -17,8 +17,8 @@ public void apply(Project project) { SpotBugsExtension spotbugs = project.getExtensions().getByType(SpotBugsExtension.class); spotbugs.getIgnoreFailures().set(false); - // Later versions of Spotbugs have stupid heuristics for EI_EXPOSE_REP* - spotbugs.getToolVersion().set("4.2.3"); + spotbugs.getToolVersion().set("4.9.8"); + spotbugs.getOmitVisitors().addAll("FindReturnRef", "ConstructorThrow"); project.getPlugins().withType(JavaBasePlugin.class).configureEach(plugin -> { @@ -46,6 +46,12 @@ public void apply(Project project) { subs.substitute(subs.module("org.apache.commons:commons-lang3:3.11")) .using(subs.module("org.apache.commons:commons-lang3:3.12.0")) .because("Spotbugs has dependency divergences"); + subs.substitute(subs.module("org.apache.commons:commons-lang3:3.18.0")) + .using(subs.module("org.apache.commons:commons-lang3:3.19.0")) + .because("Spotbugs 4.9.8 has dependency divergences"); + subs.substitute(subs.module("org.apache.logging.log4j:log4j-core:2.25.2")) + .using(subs.module("org.apache.logging.log4j:log4j-core:2.25.3")) + .because("Security vulnerability fix"); }); }); diff --git a/clustered/ehcache-client/build.gradle b/clustered/ehcache-client/build.gradle index 77dbac4ca6..3dc28ca4a6 100644 --- a/clustered/ehcache-client/build.gradle +++ b/clustered/ehcache-client/build.gradle @@ -37,7 +37,9 @@ dependencies { implementation "org.terracotta:lease-api:$terracottaPlatformVersion" implementation "org.terracotta.dynamic-config.entities:dynamic-config-topology-entity-client:$terracottaPlatformVersion" implementation "org.terracotta:connection-api:$terracottaApisVersion" - implementation "org.terracotta:terracotta-utilities-tools:$terracottaUtilitiesVersion" + implementation ("org.terracotta:terracotta-utilities-tools:$terracottaUtilitiesVersion") { + exclude group: 'org.slf4j' + } compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' @@ -60,5 +62,7 @@ dependencies { exclude group:'org.slf4j', module:'slf4j-api' } testImplementation testFixtures(project(':ehcache-xml')) - testImplementation ("org.terracotta:statistics:$parent.statisticVersion") + testImplementation ("org.terracotta:statistics:$parent.statisticVersion") { + exclude group: 'org.slf4j', module: 'slf4j-api' + } } diff --git a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java index eaf162c771..bd18840dd5 100644 --- a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java +++ b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java @@ -377,6 +377,7 @@ public ConnectionState getConnectionState() { return connectionState; } + @SuppressWarnings("removal") private static ExecutorService createAsyncWorker() { SecurityManager s = System.getSecurityManager(); ThreadGroup initialGroup = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); diff --git a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java index 2d608c9028..68e5a0453b 100644 --- a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java +++ b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java @@ -232,6 +232,7 @@ public Map.Entry next() { } @Override + @SuppressWarnings("deprecation") protected void finalize() throws Throwable { if (!lastBatch) { entity.invokeAndWaitForReceive(new ServerStoreOpMessage.IteratorCloseMessage(iteratorId), false); diff --git a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java index b9c346e6ea..67bd01bda3 100644 --- a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java +++ b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java @@ -55,6 +55,8 @@ import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; +import org.mockito.quality.Strictness; + /** * DefaultClusteringServiceDestroyTest */ @@ -194,7 +196,7 @@ public void testDestroyOnPartialDestroyState() throws Exception { private void mockLockForWriteLockSuccess() throws org.terracotta.exception.EntityNotProvidedException, org.terracotta.exception.EntityNotFoundException, org.terracotta.exception.EntityVersionMismatchException { when(connection.getEntityRef(same(VoltronReadWriteLockClient.class), eq(1L), any())).thenReturn(lockEntityRef); - VoltronReadWriteLockClient lockClient = mock(VoltronReadWriteLockClient.class, withSettings().lenient()); + VoltronReadWriteLockClient lockClient = mock(VoltronReadWriteLockClient.class, withSettings().strictness(Strictness.LENIENT)); when(lockEntityRef.fetchEntity(null)).thenReturn(lockClient); when(lockClient.tryLock(LockMessaging.HoldType.WRITE)).thenReturn(true); @@ -203,7 +205,7 @@ private void mockLockForWriteLockSuccess() throws org.terracotta.exception.Entit private void mockLockForReadLockSuccess() throws org.terracotta.exception.EntityNotProvidedException, org.terracotta.exception.EntityNotFoundException, org.terracotta.exception.EntityVersionMismatchException { when(connection.getEntityRef(same(VoltronReadWriteLockClient.class), eq(1L), any())).thenReturn(lockEntityRef); - VoltronReadWriteLockClient lockClient = mock(VoltronReadWriteLockClient.class, withSettings().lenient()); + VoltronReadWriteLockClient lockClient = mock(VoltronReadWriteLockClient.class, withSettings().strictness(Strictness.LENIENT)); when(lockEntityRef.fetchEntity(null)).thenReturn(lockClient); when(lockClient.tryLock(LockMessaging.HoldType.READ)).thenReturn(true); diff --git a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java index 48274dab70..b291b4892b 100644 --- a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java +++ b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java @@ -166,9 +166,9 @@ public void testWhitelistingForPrimitiveClass() throws Exception { StateHolder testMap = stateRepository.getPersistentStateHolder("testMap", Integer.class, Integer.class, Arrays.asList(Child.class)::contains, null); - testMap.putIfAbsent(new Integer(10), new Integer(20)); + testMap.putIfAbsent(Integer.valueOf(10), Integer.valueOf(20)); - assertThat(testMap.get(new Integer(10)), is(new Integer(20))); + assertThat(testMap.get(Integer.valueOf(10)), is(Integer.valueOf(20))); assertThat(testMap.entrySet(), hasSize(1)); } diff --git a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java index 750e53c0b5..894ef50bf5 100644 --- a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java +++ b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java @@ -231,7 +231,7 @@ public void testGetThrowsOnlySAE() throws Exception { @SuppressWarnings("unchecked") public void testGetTimeout() throws Exception { ServerStoreProxy proxy = mock(ServerStoreProxy.class); - long longKey = HashUtils.intHashToLong(new Long(1L).hashCode()); + long longKey = HashUtils.intHashToLong(Long.valueOf(1L).hashCode()); when(proxy.get(longKey)).thenThrow(TimeoutException.class); ClusteredStore store = new ClusteredStore<>(config,null, null, proxy, null, null, new DefaultStatisticsService()); assertThat(store.get(1L), nullValue()); @@ -630,7 +630,7 @@ public void testSingleChainSingleValue() throws StoreAccessException { @Test public void testSingleChainMultipleValues() throws StoreAccessException { - assertThat(Long.hashCode(1L), is(Long.hashCode(~1L))); + assertThat(Long.valueOf(1L).hashCode(), is(Long.valueOf(~1L).hashCode())); store.put(1L, "foo"); store.put(~1L, "bar"); diff --git a/clustered/ehcache-clustered/build.gradle b/clustered/ehcache-clustered/build.gradle index c1c77ab825..565a48ea7c 100644 --- a/clustered/ehcache-clustered/build.gradle +++ b/clustered/ehcache-clustered/build.gradle @@ -100,8 +100,18 @@ task copyDocs(type: Sync) { into docsFolder } +configurations { + javadocAdd +} + +dependencies { + javadocAdd project(':clustered:ehcache-common-api') + javadocAdd project(':clustered:ehcache-common') +} + javadoc { exclude '**/core/**', '**/impl/**', '**/xml/**', '**/jsr107/**', '**/transactions/**', '**/management/**', '**/tck/**' + classpath += configurations.javadocAdd } tasks.named('jar') { diff --git a/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java index e74444ef2e..1d87fcefd9 100644 --- a/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java +++ b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java @@ -25,7 +25,6 @@ /** * ValueWrapper */ -@SuppressFBWarnings("EI_EXPOSE_REP") public class ValueWrapper implements Serializable { private static final long serialVersionUID = -4794738044295644587L; diff --git a/clustered/ehcache-common/build.gradle b/clustered/ehcache-common/build.gradle index 61a144319d..ca15511653 100644 --- a/clustered/ehcache-common/build.gradle +++ b/clustered/ehcache-common/build.gradle @@ -32,7 +32,9 @@ dependencies { implementation "org.terracotta:entity-common-api:$terracottaApisVersion" implementation "org.terracotta:runnel:$terracottaPlatformVersion" - implementation "org.terracotta:terracotta-utilities-tools:$terracottaUtilitiesVersion" + implementation ("org.terracotta:terracotta-utilities-tools:$terracottaUtilitiesVersion") { + exclude group: 'org.slf4j' + } testImplementation project(':clustered:test-utils') } diff --git a/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java index 362300fb18..56935efde4 100644 --- a/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java +++ b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java @@ -62,48 +62,48 @@ private void unmarshallingStateRepoMessagesCheck(T t) { @Test public void unmarshallingIntegerTest() throws Exception { - unmarshallingStateRepoMessagesCheck(new Integer(10)); + unmarshallingStateRepoMessagesCheck(Integer.valueOf(10)); } @Test public void unmarshallingLongTest() throws Exception { - unmarshallingStateRepoMessagesCheck(new Long(10)); + unmarshallingStateRepoMessagesCheck(Long.valueOf(10L)); } @Test public void unmarshallingFloatTest() throws Exception { - unmarshallingStateRepoMessagesCheck(new Float(10.0)); + unmarshallingStateRepoMessagesCheck(Float.valueOf(10.0f)); } @Test public void unmarshallingDoubleTest() throws Exception { - unmarshallingStateRepoMessagesCheck(new Double(10.0)); + unmarshallingStateRepoMessagesCheck(Double.valueOf(10.0)); } @Test public void unmarshallingByteTest() throws Exception { byte b = 101; - unmarshallingStateRepoMessagesCheck(new Byte(b)); + unmarshallingStateRepoMessagesCheck(Byte.valueOf(b)); } @Test public void unmarshallingCharacterTest() throws Exception { - unmarshallingStateRepoMessagesCheck(new Character('b')); + unmarshallingStateRepoMessagesCheck(Character.valueOf('b')); } @Test public void unmarshallingStringTest() throws Exception { - unmarshallingStateRepoMessagesCheck(new String("John")); + unmarshallingStateRepoMessagesCheck("John"); } @Test public void unmarshallingBooleanTest() throws Exception { - unmarshallingStateRepoMessagesCheck(new Boolean(true)); + unmarshallingStateRepoMessagesCheck(Boolean.TRUE); } @Test public void unmarshallingShortTest() throws Exception { - unmarshallingStateRepoMessagesCheck(new Short((short) 1)); + unmarshallingStateRepoMessagesCheck(Short.valueOf((short) 1)); } @Test diff --git a/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java index f22474cb4a..3b7a601309 100644 --- a/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java +++ b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java @@ -115,7 +115,7 @@ public void testChainEntryWithSingleElement() { StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); ChainCodec.encodeChainEntry(encoder, entry); - Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder(encoder.encode().flip())); assertThat(decoded.getKey(), is(42L)); @@ -132,7 +132,7 @@ public void testChainEntryWithSingleSequencedElement() { StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); ChainCodec.encodeChainEntry(encoder, entry); - Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder(encoder.encode().flip())); assertThat(decoded.getKey(), is(43L)); assertThat(decoded.getValue().isEmpty(), is(false)); @@ -150,7 +150,7 @@ public void testChainEntryWithMultipleElements() { StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); ChainCodec.encodeChainEntry(encoder, entry); - Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder(encoder.encode().flip())); assertThat(decoded.getKey(), is(44L)); assertThat(decoded.getValue().isEmpty(), is(false)); @@ -164,7 +164,7 @@ public void testChainEntryWithMultipleSequencedElements() { StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); ChainCodec.encodeChainEntry(encoder, entry); - Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder(encoder.encode().flip())); assertThat(decoded.getKey(), is(45L)); assertThat(decoded.getValue().isEmpty(), is(false)); @@ -180,7 +180,7 @@ public void testEmptyChainEntry() { StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); ChainCodec.encodeChainEntry(encoder, entry); - Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder(encoder.encode().flip())); assertThat(decoded.getKey(), is(46L)); assertThat(decoded.getValue().isEmpty(), is(true)); diff --git a/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java index abc8c55e68..46105f8b2c 100644 --- a/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java +++ b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java @@ -76,7 +76,7 @@ public void testGetResponseCodec() { @Test public void testMapValueCodec() throws Exception { - Object subject = new Integer(10); + Object subject = Integer.valueOf(10); EhcacheEntityResponse mapValue = mapValue(subject); EhcacheEntityResponse.MapValue decoded = (EhcacheEntityResponse.MapValue) RESPONSE_CODEC.decode(RESPONSE_CODEC.encode(mapValue)); diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index ccf2f904c9..a17d5c5f6a 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -40,11 +40,18 @@ dependencies { } testImplementation project(':ehcache-management') - testImplementation "org.terracotta.management:nms-entity-client:$terracottaPlatformVersion" - testImplementation "org.terracotta.management:nms-agent-entity-client:$terracottaPlatformVersion" - testImplementation "org.terracotta:terracotta-utilities-port-chooser:$terracottaUtilitiesVersion" + testImplementation ("org.terracotta.management:nms-entity-client:$terracottaPlatformVersion") { + exclude group: 'org.slf4j' + } + testImplementation ("org.terracotta.management:nms-agent-entity-client:$terracottaPlatformVersion") { + exclude group: 'org.slf4j' + } + testImplementation ("org.terracotta:terracotta-utilities-port-chooser:$terracottaUtilitiesVersion") { + exclude group: 'org.slf4j' + } testImplementation("org.terracotta:galvan-platform-support:$terracottaPlatformVersion") { exclude group: 'org.terracotta', module: 'terracotta-utilities-port-chooser' + exclude group: 'org.slf4j' } testImplementation "javax.cache:cache-api:$jcacheVersion" } @@ -79,5 +86,16 @@ configurations.all { .because('CVE-2020-15250') .with(module('junit:junit:4.13.1')) } + eachDependency { details -> + if (details.requested.group == 'ch.qos.logback' && + (details.requested.name == 'logback-classic' || details.requested.name == 'logback-core')) { + def enforcedLogbackVersion = project.property('logbackVersion').toString() + if (!details.requested.version || details.requested.version < enforcedLogbackVersion) { + details.useVersion enforcedLogbackVersion + details.because 'Force logback >= ' + enforcedLogbackVersion + } + } + } } } + diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java index dee9b2e18d..7f274206da 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java @@ -173,7 +173,7 @@ public void test_C_client_capabilities_exposed() throws Exception { allDescriptors.addAll(OFFHEAP_DESCRIPTORS); allDescriptors.addAll(CLUSTERED_DESCRIPTORS); - assertThat(descriptors).hasSameElementsAs(allDescriptors); + assertThat(allDescriptors).hasSameElementsAs(descriptors); } @Test @@ -203,9 +203,9 @@ public void test_D_server_capabilities_exposed() throws Exception { // stats - assertThat(tierCapabilities[3].getDescriptors()).hasSameElementsAs(SERVER_STORE_DESCRIPTORS); - assertThat(managerCapabilities[2].getDescriptors()).hasSameElementsAs(POOL_DESCRIPTORS); - assertThat(tierCapabilities[1].getDescriptors()).hasSameElementsAs(POOL_DESCRIPTORS); + assertThat(new ArrayList(tierCapabilities[3].getDescriptors())).hasSameElementsAs(SERVER_STORE_DESCRIPTORS); + assertThat(new ArrayList(managerCapabilities[2].getDescriptors())).hasSameElementsAs(POOL_DESCRIPTORS); + assertThat(new ArrayList(tierCapabilities[1].getDescriptors())).hasSameElementsAs(POOL_DESCRIPTORS); // ClusterTierManagerSettings @@ -271,7 +271,7 @@ public void test_D_server_capabilities_exposed() throws Exception { assertThat(managerCapabilities[0].getDescriptors()).hasSize(3); // time + 2 resources - assertThat(managerCapabilities[1].getDescriptors()).hasSameElementsAs(OFFHEAP_RES_DESCRIPTORS); + assertThat(new ArrayList(managerCapabilities[1].getDescriptors())).hasSameElementsAs(OFFHEAP_RES_DESCRIPTORS); } @Test diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index fc33ca4cf7..d15f71a8af 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -269,7 +269,16 @@ public void testClear() throws Exception { clearFuture.get(); - universalSet.forEach(x -> assertThat(cache2.get(x), nullValue())); + long deadline = System.currentTimeMillis() + 30_000; + for (Long x : universalSet) { + while (cache2.get(x) != null) { + if (System.currentTimeMillis() > deadline) { + assertThat("Key " + x + " still present in cache2 after 30s wait", cache2.get(x), nullValue()); + break; + } + Thread.sleep(100); + } + } } diff --git a/clustered/osgi-test/build.gradle b/clustered/osgi-test/build.gradle index a87b016500..7cb2222dd3 100644 --- a/clustered/osgi-test/build.gradle +++ b/clustered/osgi-test/build.gradle @@ -36,8 +36,14 @@ dependencies { osgiModule project(':clustered:ehcache-clustered') osgiModule "javax.cache:cache-api:$parent.jcacheVersion" osgiModule "org.slf4j:slf4j-simple:$parent.slf4jVersion" - osgiModule "org.terracotta:terracotta-utilities-test-tools:$terracottaUtilitiesVersion" - osgiModule "org.terracotta:terracotta-utilities-port-chooser:$terracottaUtilitiesVersion" + // SLF4J 2.x requires osgi.serviceloader.processor; Apache Aries SPIFly provides it + osgiModule 'org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle:1.3.7' + osgiModule ("org.terracotta:terracotta-utilities-test-tools:$terracottaUtilitiesVersion") { + exclude group: 'org.slf4j' + } + osgiModule ("org.terracotta:terracotta-utilities-port-chooser:$terracottaUtilitiesVersion") { + exclude group: 'org.slf4j' + } osgiModule 'org.apache.felix:org.apache.felix.scr:2.2.0' osgiModule 'com.sun.activation:javax.activation:1.2.0' osgiModule 'org.osgi:org.osgi.util.promise:1.2.0' @@ -59,6 +65,11 @@ configurations.all { .using(module('org.ops4j.pax.url:pax-url-classpath:2.6.11')) substitute(module('org.ops4j.pax.url:pax-url-link:2.6.8')) .using(module('org.ops4j.pax.url:pax-url-link:2.6.11')) + substitute(module('org.ops4j.pax.url:pax-url-aether:2.6.8')) + .using(module('org.ops4j.pax.url:pax-url-aether:3.0.2')) + substitute(module('org.apache.commons:commons-lang3:3.12.0')) + .using(module('org.apache.commons:commons-lang3:3.18.0')) + .because('CVE-2025-48924') substitute(module('org.osgi:org.osgi.util.function:1.1.0')) .using(module('org.osgi:org.osgi.util.function:1.2.0')) .because('Dependency divergence in org.osgi:org.osgi.util.promise:1.2.0') diff --git a/clustered/server/ehcache-entity/build.gradle b/clustered/server/ehcache-entity/build.gradle index 3834655e2d..52349a5e6c 100644 --- a/clustered/server/ehcache-entity/build.gradle +++ b/clustered/server/ehcache-entity/build.gradle @@ -28,12 +28,18 @@ publishing.publications.withType(MavenPublication) { dependencies { service project(':clustered:server:ehcache-service-api') - service "org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion" - service "org.terracotta.management:management-registry:$terracottaPlatformVersion" + service ("org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion") { + exclude group: 'org.slf4j' + } + service ("org.terracotta.management:management-registry:$terracottaPlatformVersion") { + exclude group: 'org.slf4j' + } api project(':clustered:ehcache-common') implementation "org.terracotta:runnel:$terracottaPlatformVersion" - implementation "org.terracotta:offheap-store:$offheapVersion" + implementation ("org.terracotta:offheap-store:$offheapVersion") { + exclude group:'org.slf4j' + } implementation "org.terracotta:client-message-tracker:$terracottaPlatformVersion" testImplementation project(':clustered:server:ehcache-service') diff --git a/clustered/server/ehcache-service/build.gradle b/clustered/server/ehcache-service/build.gradle index a2e1031993..1710c728b2 100644 --- a/clustered/server/ehcache-service/build.gradle +++ b/clustered/server/ehcache-service/build.gradle @@ -29,12 +29,19 @@ publishing.publications.withType(MavenPublication) { dependencies { service project(':clustered:server:ehcache-service-api') service "org.terracotta:offheap-resource:$terracottaPlatformVersion" - service "org.terracotta:statistics:$statisticVersion" + service ("org.terracotta:statistics:$statisticVersion") { + exclude group: 'org.slf4j', module: 'slf4j-api' + } implementation project(':clustered:ehcache-common') - implementation "org.terracotta:offheap-store:$offheapVersion" + implementation ("org.terracotta:offheap-store:$offheapVersion") { + exclude group:'org.slf4j' + } testImplementation project(':clustered:test-utils') - testImplementation "org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion" + testImplementation ("org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion") { + exclude group: 'org.slf4j' + } testImplementation "org.terracotta:passthrough-server:$terracottaPassthroughTestingVersion" + testImplementation 'javax.xml.bind:jaxb-api:[2.2,3)' } diff --git a/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java index 527978652f..6a29355de4 100644 --- a/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java +++ b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java @@ -215,7 +215,7 @@ public ByteBuffer readBinaryValue(long chain) { detachedContiguousBuffer.reset(); element = storage.readLong(element + ELEMENT_HEADER_NEXT_OFFSET); } while (element != chain); - return (ByteBuffer)detachedContiguousBuffer.flip(); + return detachedContiguousBuffer.flip(); } @Override @@ -700,7 +700,7 @@ private void append(long head, long tail) { } private Element element(ByteBuffer attachedBuffer, final long sequence) { - final ByteBuffer detachedBuffer = (ByteBuffer) ByteBuffer.allocate(attachedBuffer.remaining()).put(attachedBuffer).flip(); + final ByteBuffer detachedBuffer = ByteBuffer.allocate(attachedBuffer.remaining()).put(attachedBuffer).flip(); return new SequencedElement() { diff --git a/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java index fe0ceba783..65a615fba9 100644 --- a/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java +++ b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java @@ -144,7 +144,7 @@ private static ByteBuffer buffer(int i) { while (buffer.hasRemaining()) { buffer.put((byte) i); } - return (ByteBuffer) buffer.flip(); + return buffer.flip(); } private static Matcher element(int i) { diff --git a/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java index 32c87c4ccf..c57977037b 100644 --- a/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java +++ b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java @@ -504,7 +504,7 @@ private static ByteBuffer buffer(int i) { while (buffer.hasRemaining()) { buffer.put((byte) i); } - return (ByteBuffer) buffer.flip(); + return buffer.flip(); } private static Matcher element(final int i) { diff --git a/config/checkstyle.xml b/config/checkstyle.xml index 6a9374d111..c73e1aa2da 100644 --- a/config/checkstyle.xml +++ b/config/checkstyle.xml @@ -1,7 +1,7 @@ + "-//Puppy Crawl//DTD Check Configuration 1.3//EN" + "http://www.puppycrawl.com/dtds/configuration_1_3.dtd"> @@ -22,6 +22,15 @@ + + + + + + + + + @@ -29,7 +38,7 @@ - + diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/SPIStoreTester.java b/core-spi-test/src/main/java/org/ehcache/internal/store/SPIStoreTester.java index 1f7697e5b2..4cc5063f96 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/SPIStoreTester.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/SPIStoreTester.java @@ -18,6 +18,8 @@ package org.ehcache.internal.store; import org.ehcache.core.spi.store.Store; +import org.ehcache.spi.resilience.StoreAccessException; +import org.ehcache.spi.test.LegalSPITesterException; import org.ehcache.spi.test.SPITester; /** @@ -30,10 +32,39 @@ public class SPIStoreTester extends SPITester { + protected static final String SPI_WARNING = "Warning, an exception is thrown due to the SPI test"; + protected final StoreFactory factory; public SPIStoreTester(final StoreFactory factory) { this.factory = factory; } + @FunctionalInterface + protected interface StoreRunnable { + void run() throws StoreAccessException; + } + + protected T expectException(Class expected, StoreRunnable action) + throws LegalSPITesterException { + try { + action.run(); + } catch (Throwable throwable) { + if (expected.isInstance(throwable)) { + return expected.cast(throwable); + } + if (throwable instanceof StoreAccessException) { + throw new LegalSPITesterException(SPI_WARNING, throwable); + } + if (throwable instanceof RuntimeException) { + throw (RuntimeException) throwable; + } + if (throwable instanceof Error) { + throw (Error) throwable; + } + throw new AssertionError("Unexpected checked exception", throwable); + } + throw new AssertionError("Expected " + expected.getSimpleName() + " to be thrown"); + } + } diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreContainsKeyTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreContainsKeyTest.java index a8ffcd0881..a11ed0557a 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreContainsKeyTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreContainsKeyTest.java @@ -73,14 +73,7 @@ public void nullKeyThrowsException() K key = null; - try { - kvStore.containsKey(key); - throw new AssertionError("Expected NullPointerException because the key is null"); - } catch (NullPointerException e) { - // expected - } catch (StoreAccessException e) { - throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); - } + expectException(NullPointerException.class, () -> kvStore.containsKey(key)); } @SPITest diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreGetTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreGetTest.java index a2401b2994..51036b5a3a 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreGetTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreGetTest.java @@ -115,14 +115,7 @@ public void nullKeyThrowsException() K key = null; - try { - kvStore.get(key); - throw new AssertionError("Expected NullPointerException because the key is null"); - } catch (NullPointerException e) { - // expected - } catch (StoreAccessException e) { - throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); - } + expectException(NullPointerException.class, () -> kvStore.get(key)); } @SPITest diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutIfAbsentTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutIfAbsentTest.java index 0a47012335..cfabea7622 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutIfAbsentTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutIfAbsentTest.java @@ -97,34 +97,24 @@ public void doesntMapKeyToValueWhenMappingExists() @SPITest public void nullKeyThrowsException() - throws StoreAccessException, IllegalAccessException, InstantiationException { + throws IllegalAccessException, InstantiationException, LegalSPITesterException { kvStore = factory.newStore(); K key = null; V value = factory.createValue(1); - try { - kvStore.putIfAbsent(key, value, b -> {}); - throw new AssertionError("Expected NullPointerException because the key is null"); - } catch (NullPointerException e) { - // expected - } + expectException(NullPointerException.class, () -> kvStore.putIfAbsent(key, value, b -> {})); } @SPITest public void nullValueThrowsException() - throws StoreAccessException, IllegalAccessException, InstantiationException { + throws IllegalAccessException, InstantiationException, LegalSPITesterException { kvStore = factory.newStore(); K key = factory.createKey(1); V value = null; - try { - kvStore.putIfAbsent(key, value, b -> {}); - throw new AssertionError("Expected NullPointerException because the value is null"); - } catch (NullPointerException e) { - // expected - } + expectException(NullPointerException.class, () -> kvStore.putIfAbsent(key, value, b -> {})); } @SPITest diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutTest.java index 772eb6349f..b77da2b1fd 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutTest.java @@ -64,14 +64,7 @@ public void nullKeyThrowsException() K key = null; V value = factory.createValue(1); - try { - kvStore.put(key, value); - throw new AssertionError("Expected NullPointerException because the key is null"); - } catch (NullPointerException e) { - // expected - } catch (StoreAccessException e) { - throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); - } + expectException(NullPointerException.class, () -> kvStore.put(key, value)); } @SPITest @@ -82,14 +75,7 @@ public void nullValueThrowsException() K key = factory.createKey(1); V value = null; - try { - kvStore.put(key, value); - throw new AssertionError("Expected NullPointerException because the value is null"); - } catch (NullPointerException e) { - // expected - } catch (StoreAccessException e) { - throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); - } + expectException(NullPointerException.class, () -> kvStore.put(key, value)); } @SPITest diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyTest.java index 942de9385b..cb50228a4a 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyTest.java @@ -89,14 +89,7 @@ public void nullKeyThrowsException() throws IllegalAccessException, InstantiationException, LegalSPITesterException { kvStore = factory.newStore(); - try { - kvStore.remove(null); - throw new AssertionError("Expected NullPointerException because the key is null"); - } catch (NullPointerException e) { - // expected - } catch (StoreAccessException e) { - throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); - } + expectException(NullPointerException.class, () -> kvStore.remove(null)); } @SPITest diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyValueTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyValueTest.java index 5958a439c3..158563b266 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyValueTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyValueTest.java @@ -164,14 +164,7 @@ public void nullKeyThrowsException() K key = null; V value = factory.createValue(1); - try { - kvStore.remove(key, value); - throw new AssertionError("Expected NullPointerException because the key is null"); - } catch (NullPointerException e) { - // expected - } catch (StoreAccessException e) { - throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); - } + expectException(NullPointerException.class, () -> kvStore.remove(key, value)); } @SPITest @@ -182,14 +175,7 @@ public void nullValueThrowsException() K key = factory.createKey(1); V value = null; - try { - kvStore.remove(key, value); - throw new AssertionError("Expected NullPointerException because the value is null"); - } catch (NullPointerException e) { - // expected - } catch (StoreAccessException e) { - throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); - } + expectException(NullPointerException.class, () -> kvStore.remove(key, value)); } @SPITest diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreReplaceKeyValueTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreReplaceKeyValueTest.java index df62e0b0a7..d47801084a 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreReplaceKeyValueTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreReplaceKeyValueTest.java @@ -117,14 +117,7 @@ public void nullKeyThrowsException() K key = null; V value = factory.createValue(1); - try { - kvStore.replace(key, value); - throw new AssertionError("Expected NullPointerException because the key is null"); - } catch (NullPointerException e) { - // expected - } catch (StoreAccessException e) { - throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); - } + expectException(NullPointerException.class, () -> kvStore.replace(key, value)); } @SPITest @@ -134,14 +127,7 @@ public void nullValueThrowsException() K key = factory.createKey(1); - try { - kvStore.replace(key, null); - throw new AssertionError("Expected NullPointerException because the value is null"); - } catch (NullPointerException e) { - // expected - } catch (StoreAccessException e) { - throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); - } + expectException(NullPointerException.class, () -> kvStore.replace(key, null)); } @SPITest diff --git a/demos/00-NoCache/build.gradle b/demos/00-NoCache/build.gradle new file mode 100644 index 0000000000..60a75d213e --- /dev/null +++ b/demos/00-NoCache/build.gradle @@ -0,0 +1,7 @@ +plugins { + id 'application' +} + +application { + mainClass = 'org.ehcache.demos.peeper.PeeperServer' +} diff --git a/demos/00-NoCache/src/main/java/org/ehcache/demos/peeper/PeeperServer.java b/demos/00-NoCache/src/main/java/org/ehcache/demos/peeper/PeeperServer.java new file mode 100644 index 0000000000..7c4317b4cb --- /dev/null +++ b/demos/00-NoCache/src/main/java/org/ehcache/demos/peeper/PeeperServer.java @@ -0,0 +1,26 @@ +/* + * Copyright Terracotta, Inc. + * Copyright IBM Corp. 2024, 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.demos.peeper; + +import org.ehcache.demos.server.EmbeddedPeeperServer; + +public class PeeperServer { + + public static void main(String[] args) throws Exception { + EmbeddedPeeperServer.run(PeeperServletContextListener::new, PeeperServlet::new); + } +} diff --git a/demos/00-NoCache/src/main/java/org/ehcache/demos/peeper/PeeperServlet.java b/demos/00-NoCache/src/main/java/org/ehcache/demos/peeper/PeeperServlet.java index 9fb8ca1436..524adeaddc 100755 --- a/demos/00-NoCache/src/main/java/org/ehcache/demos/peeper/PeeperServlet.java +++ b/demos/00-NoCache/src/main/java/org/ehcache/demos/peeper/PeeperServlet.java @@ -16,11 +16,11 @@ */ package org.ehcache.demos.peeper; -import javax.servlet.ServletException; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.List; diff --git a/demos/00-NoCache/src/main/java/org/ehcache/demos/peeper/PeeperServletContextListener.java b/demos/00-NoCache/src/main/java/org/ehcache/demos/peeper/PeeperServletContextListener.java index efb905a8a4..a3efb3d2a3 100755 --- a/demos/00-NoCache/src/main/java/org/ehcache/demos/peeper/PeeperServletContextListener.java +++ b/demos/00-NoCache/src/main/java/org/ehcache/demos/peeper/PeeperServletContextListener.java @@ -16,9 +16,9 @@ */ package org.ehcache.demos.peeper; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.annotation.WebListener; +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; +import jakarta.servlet.annotation.WebListener; /** * @author Ludovic Orban diff --git a/demos/01-CacheAside/build.gradle b/demos/01-CacheAside/build.gradle new file mode 100644 index 0000000000..60a75d213e --- /dev/null +++ b/demos/01-CacheAside/build.gradle @@ -0,0 +1,7 @@ +plugins { + id 'application' +} + +application { + mainClass = 'org.ehcache.demos.peeper.PeeperServer' +} diff --git a/demos/01-CacheAside/config/checkstyle-suppressions.xml b/demos/01-CacheAside/config/checkstyle-suppressions.xml index be989c924a..a6867b21a7 100644 --- a/demos/01-CacheAside/config/checkstyle-suppressions.xml +++ b/demos/01-CacheAside/config/checkstyle-suppressions.xml @@ -1,9 +1,8 @@ - - \ No newline at end of file + diff --git a/demos/01-CacheAside/src/main/java/org/ehcache/demos/peeper/PeeperServer.java b/demos/01-CacheAside/src/main/java/org/ehcache/demos/peeper/PeeperServer.java new file mode 100644 index 0000000000..7c4317b4cb --- /dev/null +++ b/demos/01-CacheAside/src/main/java/org/ehcache/demos/peeper/PeeperServer.java @@ -0,0 +1,26 @@ +/* + * Copyright Terracotta, Inc. + * Copyright IBM Corp. 2024, 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.demos.peeper; + +import org.ehcache.demos.server.EmbeddedPeeperServer; + +public class PeeperServer { + + public static void main(String[] args) throws Exception { + EmbeddedPeeperServer.run(PeeperServletContextListener::new, PeeperServlet::new); + } +} diff --git a/demos/01-CacheAside/src/main/java/org/ehcache/demos/peeper/PeeperServlet.java b/demos/01-CacheAside/src/main/java/org/ehcache/demos/peeper/PeeperServlet.java index 4a0e115e18..4348afad68 100755 --- a/demos/01-CacheAside/src/main/java/org/ehcache/demos/peeper/PeeperServlet.java +++ b/demos/01-CacheAside/src/main/java/org/ehcache/demos/peeper/PeeperServlet.java @@ -16,11 +16,11 @@ */ package org.ehcache.demos.peeper; -import javax.servlet.ServletException; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.List; diff --git a/demos/01-CacheAside/src/main/java/org/ehcache/demos/peeper/PeeperServletContextListener.java b/demos/01-CacheAside/src/main/java/org/ehcache/demos/peeper/PeeperServletContextListener.java index efb905a8a4..a3efb3d2a3 100755 --- a/demos/01-CacheAside/src/main/java/org/ehcache/demos/peeper/PeeperServletContextListener.java +++ b/demos/01-CacheAside/src/main/java/org/ehcache/demos/peeper/PeeperServletContextListener.java @@ -16,9 +16,9 @@ */ package org.ehcache.demos.peeper; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.annotation.WebListener; +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; +import jakarta.servlet.annotation.WebListener; /** * @author Ludovic Orban diff --git a/demos/build.gradle b/demos/build.gradle index 6b4e163021..2c4c8d8d8c 100644 --- a/demos/build.gradle +++ b/demos/build.gradle @@ -1,60 +1,31 @@ plugins { + id 'org.ehcache.build.conventions.java-library' id 'org.ehcache.build.conventions.war' apply false - id 'org.gretty' apply false } -subprojects { - apply plugin: 'org.ehcache.build.conventions.war' - apply plugin: 'org.gretty' - - gretty { - httpPort = 8080 - contextPath = '/' - servletContainer = 'jetty9' - } +def jettyVersion = '12.1.5' - dependencies { - implementation project(':ehcache-impl') - implementation 'javax.servlet:javax.servlet-api:3.1.0' - runtimeOnly 'ch.qos.logback:logback-classic:1.2.11' - runtimeOnly 'com.h2database:h2:1.4.196' - } +dependencies { + api platform("org.eclipse.jetty:jetty-bom:${jettyVersion}") + api 'jakarta.servlet:jakarta.servlet-api:6.0.0' + api 'org.eclipse.jetty:jetty-server' + api "org.eclipse.jetty.ee10:jetty-ee10-servlet:${jettyVersion}" +} - configurations.all { - resolutionStrategy { - dependencySubstitution { - substitute(module('org.slf4j:slf4j-api')) - .because('org.gretty:gretty-runner-jetty declares a very old version of slf4j') - .with(module('org.slf4j:slf4j-api:' + project.property('slf4jVersion'))) - } - } +configurations.configureEach { + resolutionStrategy { + force "org.slf4j:slf4j-api:${project.property('slf4jVersion')}" } +} - /* - * This substitution is solely to permit the 'dependencies' task to complete normally -- - * the Jetty 8 environment provided by gretty is not used in this module. - */ - configurations.named('grettyRunnerJetty8') { - resolutionStrategy { - dependencySubstitution { - substitute(module('org.eclipse.jetty.orbit:javax.servlet.jsp:2.1.0.v201105211820')) - .because('gretty plug-in pulls in older version for Jetty8') - .with(module('org.eclipse.jetty.orbit:javax.servlet.jsp:2.2.0.v201112011158')) - } - } - } +subprojects { + apply plugin: 'org.ehcache.build.conventions.war' - /* - * This substitution is solely to permit the 'dependencies' task to complete normally -- - * the Jetty 9.3 environment provided by gretty is not used in this module. - */ - configurations.named('grettyRunnerJetty93') { - resolutionStrategy { - dependencySubstitution { - substitute(module('org.eclipse.jetty.toolchain:jetty-schemas:3.1.M0')) - .because('gretty plug-in pulls in older version for Jetty9.3') - .with(module('org.eclipse.jetty.toolchain:jetty-schemas:3.1')) - } - } + dependencies { + implementation project(':demos') + implementation project(':ehcache-impl') + implementation 'jakarta.servlet:jakarta.servlet-api:6.0.0' + runtimeOnly "ch.qos.logback:logback-classic:${project.property('logbackVersion')}" + runtimeOnly 'com.h2database:h2:2.4.240' } } diff --git a/demos/config/checkstyle-suppressions.xml b/demos/config/checkstyle-suppressions.xml new file mode 100644 index 0000000000..cb41d0baf7 --- /dev/null +++ b/demos/config/checkstyle-suppressions.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/demos/src/main/java/org/ehcache/demos/server/EmbeddedPeeperServer.java b/demos/src/main/java/org/ehcache/demos/server/EmbeddedPeeperServer.java new file mode 100644 index 0000000000..d16ff81c3b --- /dev/null +++ b/demos/src/main/java/org/ehcache/demos/server/EmbeddedPeeperServer.java @@ -0,0 +1,55 @@ +/* + * Copyright Terracotta, Inc. + * Copyright IBM Corp. 2024, 2026 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.demos.server; + +import jakarta.servlet.ServletContextListener; +import jakarta.servlet.http.HttpServlet; +import java.util.Objects; +import java.util.function.Supplier; +import org.eclipse.jetty.ee10.servlet.ServletContextHandler; +import org.eclipse.jetty.ee10.servlet.ServletHolder; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; + +public final class EmbeddedPeeperServer { + + private EmbeddedPeeperServer() { + } + + public static void run(Supplier listenerSupplier, + Supplier servletSupplier) throws Exception { + Objects.requireNonNull(listenerSupplier, "listenerSupplier"); + Objects.requireNonNull(servletSupplier, "servletSupplier"); + + Server server = new Server(); + + ServerConnector connector = new ServerConnector(server); + connector.setPort(8080); + connector.setHost(System.getenv().getOrDefault("HOST", "0.0.0.0")); + server.addConnector(connector); + + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath("/"); + context.addEventListener(listenerSupplier.get()); + context.addServlet(new ServletHolder(servletSupplier.get()), "/*"); + + server.setHandler(context); + + server.start(); + server.join(); + } +} diff --git a/docs/src/docs/asciidoc/user/examples.adoc b/docs/src/docs/asciidoc/user/examples.adoc index 81bf6d26e1..6de5184a11 100644 --- a/docs/src/docs/asciidoc/user/examples.adoc +++ b/docs/src/docs/asciidoc/user/examples.adoc @@ -39,8 +39,7 @@ from the database to display the Peeper web page. To run this implementation: [source,bash] ---- -cd ehcache3/demos/00-NoCache -../../gradlew appStart +./gradlew :demos:00-NoCache:run ---- This builds the necessary components, starts a http://eclipse.org/jetty/[Jetty] web service, @@ -73,8 +72,7 @@ the cache is cleared. To run this implementation: [source,bash] ---- -cd ehcache3/demos/01-CacheAside -../../gradlew appStart +./gradlew :demos:01-CacheAside:run ---- This builds the necessary components, starts a http://eclipse.org/jetty/[Jetty] web service, diff --git a/ehcache-107/build.gradle b/ehcache-107/build.gradle index b929aba6ff..acb2572b40 100644 --- a/ehcache-107/build.gradle +++ b/ehcache-107/build.gradle @@ -66,7 +66,9 @@ dependencies { commonApi "javax.cache:cache-api:$parent.jcacheVersion" commonImplementation project(':ehcache-impl') - commonImplementation "org.terracotta:statistics:$statisticVersion" + commonImplementation ("org.terracotta:statistics:$statisticVersion") { + exclude group: 'org.slf4j', module: 'slf4j-api' + } implementation project(':ehcache-xml') jakartaImplementation(project(':ehcache-xml')) { diff --git a/ehcache-107/src/test/java/org/ehcache/ParsesConfigurationExtensionTest.java b/ehcache-107/src/test/java/org/ehcache/ParsesConfigurationExtensionTest.java index 8284d9a797..2e94eb5dc7 100644 --- a/ehcache-107/src/test/java/org/ehcache/ParsesConfigurationExtensionTest.java +++ b/ehcache-107/src/test/java/org/ehcache/ParsesConfigurationExtensionTest.java @@ -53,7 +53,7 @@ public class ParsesConfigurationExtensionTest { @Test - public void testConfigParse() throws ClassNotFoundException, SAXException, InstantiationException, IllegalAccessException, IOException { + public void testConfigParse() throws SAXException, ReflectiveOperationException, IOException { final XmlConfiguration configuration = new XmlConfiguration(this.getClass().getResource("/ehcache-107.xml")); final DefaultJsr107Service jsr107Service = new DefaultJsr107Service(ServiceUtils.findSingletonAmongst(Jsr107Configuration.class, configuration.getServiceCreationConfigurations())); @@ -66,7 +66,7 @@ public void testConfigParse() throws ClassNotFoundException, SAXException, Insta @SuppressWarnings("rawtypes") @Test - public void testXmlExample() throws ClassNotFoundException, SAXException, InstantiationException, IOException, IllegalAccessException { + public void testXmlExample() throws SAXException, ReflectiveOperationException, IOException { XmlConfiguration config = new XmlConfiguration(ParsesConfigurationExtensionTest.class.getResource("/ehcache-example.xml")); final DefaultJsr107Service jsr107Service = new DefaultJsr107Service(ServiceUtils.findSingletonAmongst(Jsr107Configuration.class, config.getServiceCreationConfigurations())); diff --git a/ehcache-core/build.gradle b/ehcache-core/build.gradle index e01e68e42b..aa3043b776 100644 --- a/ehcache-core/build.gradle +++ b/ehcache-core/build.gradle @@ -29,7 +29,9 @@ publishing.publications.withType(MavenPublication) { dependencies { api project(':ehcache-api') - implementation "org.terracotta:statistics:$parent.statisticVersion" + implementation ("org.terracotta:statistics:$parent.statisticVersion") { + exclude group: 'org.slf4j', module: 'slf4j-api' + } compileOnly 'org.osgi:osgi.core:6.0.0' compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':spi-tester') diff --git a/ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java b/ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java index b8fb8a22e4..d33f3b507a 100644 --- a/ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java +++ b/ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java @@ -30,7 +30,6 @@ import java.util.ServiceLoader; import java.util.function.Supplier; -import static java.security.AccessController.doPrivileged; import static java.util.Collections.enumeration; import static java.util.Collections.list; import static java.util.stream.Collectors.toList; @@ -57,14 +56,14 @@ public static Iterable servicesOfType(Class serviceType) { } } - @SuppressWarnings("unchecked") + @SuppressWarnings("removal") public static ClassLoader delegationChain(Supplier loader, ClassLoader ... loaders) { - return doPrivileged((PrivilegedAction) () -> new ChainedClassLoader(concat(of(loader), of(loaders).map(l -> () -> l)).collect(toList()))); + return java.security.AccessController.doPrivileged((PrivilegedAction) () -> new ChainedClassLoader(concat(of(loader), of(loaders).map(l -> () -> l)).collect(toList()))); } - @SuppressWarnings("unchecked") + @SuppressWarnings("removal") public static ClassLoader delegationChain(ClassLoader ... loaders) { - return doPrivileged((PrivilegedAction) () -> new ChainedClassLoader(of(loaders).>map(l -> () -> l).collect(toList()))); + return java.security.AccessController.doPrivileged((PrivilegedAction) () -> new ChainedClassLoader(of(loaders).>map(l -> () -> l).collect(toList()))); } private static class ChainedClassLoader extends ClassLoader { diff --git a/ehcache-core/src/test/java/org/ehcache/core/EhcacheManagerTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheManagerTest.java index 03d6f93a9b..b93a22b331 100644 --- a/ehcache-core/src/test/java/org/ehcache/core/EhcacheManagerTest.java +++ b/ehcache-core/src/test/java/org/ehcache/core/EhcacheManagerTest.java @@ -117,7 +117,7 @@ public void testCanDestroyAndClose() throws Exception { Store store = mock(Store.class); CacheEventDispatcherFactory cacheEventNotificationListenerServiceProvider = mock(CacheEventDispatcherFactory.class); - when(storeProvider.createStore(any(Store.Configuration.class), ArgumentMatchers.any())).thenReturn(store); + when(storeProvider.createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(store); when(store.getConfigurationChangeListeners()).thenReturn(new ArrayList<>()); when(cacheEventNotificationListenerServiceProvider.createCacheEventDispatcher(store)).thenReturn(mock(CacheEventDispatcher.class)); @@ -200,7 +200,7 @@ public void testNoClassLoaderSpecified() { final Collection services = getServices(storeProvider, cenlProvider); when(storeProvider - .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); + .createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(mock); EhcacheManager cacheManager = new EhcacheManager(config, services); cacheManager.init(); assertSame(ClassLoading.getDefaultClassLoader(), cacheManager.getClassLoader()); @@ -240,7 +240,7 @@ public ClassLoader getClassLoader() { final Collection services = getServices(storeProvider, cenlProvider); when(storeProvider - .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); + .createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(mock); EhcacheManager cacheManager = new EhcacheManager(config, services); cacheManager.init(); assertSame(cl1, cacheManager.getClassLoader()); @@ -274,7 +274,7 @@ public void testThrowsWhenAddingExistingCache() { final Collection services = getServices(storeProvider, cenlProvider); when(storeProvider - .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); + .createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(mock); Map> caches = newCacheMap(); caches.put("bar", cacheConfiguration); @@ -303,7 +303,7 @@ public void testThrowsWhenNotInitialized() { final Collection services = getServices(storeProvider, cenlProvider); when(storeProvider - .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); + .createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(mock); final CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Integer.class, String.class); Map> caches = newCacheMap(); @@ -341,7 +341,7 @@ public void testThrowsWhenRetrievingCacheWithWrongTypes() { final Collection services = getServices(storeProvider, cenlProvider); when(storeProvider - .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); + .createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(mock); final CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Integer.class, String.class); Map> caches = newCacheMap(); @@ -406,7 +406,7 @@ public void testLifeCyclesCacheLoaders() throws Exception { when(cenlProvider.createCacheEventDispatcher(mock)).thenReturn(cenlServiceMock); Collection services = getServices(cacheLoaderWriterProvider, decoratorLoaderWriterProvider, storeProvider, cenlProvider); when(storeProvider - .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); + .createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(mock); EhcacheManager manager = new EhcacheManager(cfg, services); manager.init(); @@ -494,8 +494,7 @@ InternalCache createNewEhcache(final String alias, final CacheConfi final InternalCache ehcache = super.createNewEhcache(alias, config, keyType, valueType); caches.add(alias); if(caches.size() == 1) { - when(storeProvider.createStore( - ArgumentMatchers.>any(), ArgumentMatchers.>any())) + when(storeProvider.createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))) .thenThrow(thrown); } return ehcache; @@ -669,7 +668,7 @@ public void testChangesToManagerAreReflectedInConfig() { Store store = mock(Store.class); CacheEventDispatcherFactory cacheEventNotificationListenerServiceProvider = mock(CacheEventDispatcherFactory.class); - when(storeProvider.createStore(any(Store.Configuration.class), ArgumentMatchers.any())).thenReturn(store); + when(storeProvider.createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(store); when(store.getConfigurationChangeListeners()).thenReturn(new ArrayList<>()); when(cacheEventNotificationListenerServiceProvider.createCacheEventDispatcher(store)).thenReturn(mock(CacheEventDispatcher.class)); @@ -716,7 +715,7 @@ public void testCachesAddedAtRuntimeGetReInited() { Store store = mock(Store.class); CacheEventDispatcherFactory cacheEventNotificationListenerServiceProvider = mock(CacheEventDispatcherFactory.class); - when(storeProvider.createStore(any(Store.Configuration.class), ArgumentMatchers.any())).thenReturn(store); + when(storeProvider.createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(store); when(store.getConfigurationChangeListeners()).thenReturn(new ArrayList<>()); when(cacheEventNotificationListenerServiceProvider.createCacheEventDispatcher(store)).thenReturn(mock(CacheEventDispatcher.class)); @@ -754,7 +753,7 @@ public void testCachesAddedAtRuntimeGetReInited() { public void testCloseWhenRuntimeCacheCreationFails() throws Exception { Store.Provider storeProvider = mock(Store.Provider.class); when(storeProvider.rank(any(Set.class), any(Collection.class))).thenReturn(1); - doThrow(new Error("Test EhcacheManager close.")).when(storeProvider).createStore(any(Store.Configuration.class), ArgumentMatchers.any()); + doThrow(new Error("Test EhcacheManager close.")).when(storeProvider).createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class)); Map> caches = newCacheMap(); DefaultConfiguration config = new DefaultConfiguration(caches, null); @@ -788,7 +787,7 @@ public void testCloseWhenRuntimeCacheCreationFails() throws Exception { public void testCloseWhenCacheCreationFailsDuringInitialization() throws Exception { Store.Provider storeProvider = mock(Store.Provider.class); when(storeProvider.rank(any(Set.class), any(Collection.class))).thenReturn(1); - doThrow(new Error("Test EhcacheManager close.")).when(storeProvider).createStore(any(Store.Configuration.class), ArgumentMatchers.any()); + doThrow(new Error("Test EhcacheManager close.")).when(storeProvider).createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class)); CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Long.class, String.class); Map> caches = newCacheMap(); diff --git a/ehcache-core/src/test/java/org/ehcache/core/PrefixLoggerTest.java b/ehcache-core/src/test/java/org/ehcache/core/PrefixLoggerTest.java index 2ee8abd459..e3bf02c659 100644 --- a/ehcache-core/src/test/java/org/ehcache/core/PrefixLoggerTest.java +++ b/ehcache-core/src/test/java/org/ehcache/core/PrefixLoggerTest.java @@ -20,9 +20,11 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.Marker; +import org.slf4j.spi.LoggingEventBuilder; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.Arrays; import static org.mockito.Mockito.*; @@ -88,7 +90,9 @@ public void testAllMethodsDelegationWithEnrichment() throws InvocationTargetExce PrefixLogger prefixLogger = new PrefixLogger(mockLogger, prefix); for (Method prefixLogMethod : Logger.class.getDeclaredMethods()) { - + if ((prefixLogMethod.getModifiers() & Modifier.PUBLIC) != 0 && + !prefixLogMethod.getReturnType().equals(LoggingEventBuilder.class) && + !prefixLogMethod.getReturnType().equals(boolean.class)) { Class[] parameterTypes = prefixLogMethod.getParameterTypes(); Object[] parameters = new Object[parameterTypes.length]; for (int j = 0; j < parameterTypes.length; j++) { @@ -101,9 +105,9 @@ public void testAllMethodsDelegationWithEnrichment() throws InvocationTargetExce } } - prefixLogMethod.invoke(prefixLogger, parameters); - prefixLogMethod.invoke(verify(mockLogger, times(1)), enrichStringParamValues(parameters, isMsgParameter(prefixLogMethod))); - + prefixLogMethod.invoke(prefixLogger, parameters); + prefixLogMethod.invoke(verify(mockLogger, times(1)), enrichStringParamValues(parameters, isMsgParameter(prefixLogMethod))); + } } } diff --git a/ehcache-impl/build.gradle b/ehcache-impl/build.gradle index 4d50e71ef7..a1a37ae4ea 100644 --- a/ehcache-impl/build.gradle +++ b/ehcache-impl/build.gradle @@ -51,15 +51,23 @@ task slowTest(type: Test) { dependencies { api project(':ehcache-core') - implementation group: 'org.terracotta', name: 'offheap-store', version: parent.offheapVersion - implementation group: 'org.ehcache', name: 'sizeof', version: parent.sizeofVersion - implementation group: 'org.terracotta', name: 'terracotta-utilities-tools', version: parent.terracottaUtilitiesVersion + implementation (group: 'org.terracotta', name: 'offheap-store', version: parent.offheapVersion) { + exclude group:'org.slf4j' + } + implementation (group: 'org.ehcache', name: 'sizeof', version: parent.sizeofVersion) { + exclude group: 'org.slf4j' + } + implementation (group: 'org.terracotta', name: 'terracotta-utilities-tools', version: parent.terracottaUtilitiesVersion) { + exclude group: 'org.slf4j' + } compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation testFixtures(project(':ehcache-core')) testImplementation project(':core-spi-test') testImplementation 'org.ow2.asm:asm:6.2' testImplementation 'org.ow2.asm:asm-commons:6.2' - testImplementation ("org.terracotta:statistics:$parent.statisticVersion") + testImplementation ("org.terracotta:statistics:$parent.statisticVersion") { + exclude group: 'org.slf4j', module: 'slf4j-api' + } } jar { diff --git a/ehcache-impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java index ce20ee2ced..5ceb07101b 100644 --- a/ehcache-impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java +++ b/ehcache-impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java @@ -121,7 +121,7 @@ public class UserManagedCacheBuilder> imp private boolean useValueSerializingCopier; private Serializer keySerializer; private Serializer valueSerializer; - private int dispatcherConcurrency = 4; + private volatile int dispatcherConcurrency = 4; private List> eventListenerConfigurations = new ArrayList<>(); private ExecutorService unOrderedExecutor; private ExecutorService orderedExecutor; diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MemberUtils.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MemberUtils.java index 0849b9d234..f2d2e1b4d5 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MemberUtils.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MemberUtils.java @@ -58,6 +58,7 @@ abstract class MemberUtils { * @param o the AccessibleObject to set as accessible * @return a boolean indicating whether the accessibility of the object was set to true. */ + @SuppressWarnings("deprecation") static boolean setAccessibleWorkaround(final AccessibleObject o) { if (o == null || o.isAccessible()) { return false; diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java index 5f503ca55d..ddc472fa38 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java @@ -16,6 +16,7 @@ */ package org.ehcache.impl.internal.store.tiering; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.ehcache.Cache; import org.ehcache.config.ResourcePools; import org.ehcache.config.ResourceType; @@ -221,8 +222,9 @@ private void swapCachingTiers() { } } + @SuppressFBWarnings("NN_NAKED_NOTIFY") private void swapBackCachingTiers() { - if(!cachingTierRef.compareAndSet(noopCachingTier, realCachingTier)) { + if (!cachingTierRef.compareAndSet(noopCachingTier, realCachingTier)) { throw new AssertionError("Something bad happened"); } synchronized (noopCachingTier) { diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java b/ehcache-impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java index ca831aeff3..d90c7e4851 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java @@ -110,7 +110,6 @@ static boolean tryRecursiveDelete(File file) { } } - @SuppressFBWarnings("DM_GC") private static void gc() { System.gc(); System.runFinalization(); diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java index 54d60a9e3a..51176dcdec 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java @@ -107,7 +107,7 @@ protected Class resolveProxyClass(String[] interfaces) throws ClassNotFoundEx interfaceClasses[i] = Class.forName(interfaces[i], false, classLoader); } - return Proxy.getProxyClass(classLoader, interfaceClasses); + return Proxy.newProxyInstance(classLoader, interfaceClasses, (proxy, method, args) -> null).getClass(); } private static final Map> primitiveClasses = new HashMap<>(); diff --git a/ehcache-impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java b/ehcache-impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java index 3402a4a863..607d997e06 100644 --- a/ehcache-impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java @@ -391,8 +391,10 @@ public void testIncompatibleServiceRemovesExistingConfiguration() { CacheConfigurationBuilder newBuilder = oldBuilder.withService(newConfig); - assertThat(oldBuilder.build().getServiceConfigurations(), both(hasItem(sameInstance(oldConfig))).and(not(hasItem(sameInstance(newConfig))))); - assertThat(newBuilder.build().getServiceConfigurations(), both(hasItem(sameInstance(newConfig))).and(not(hasItem(sameInstance(oldConfig))))); + assertThat(oldBuilder.build().getServiceConfigurations(), hasItem(sameInstance(oldConfig))); + assertThat(oldBuilder.build().getServiceConfigurations(), not(hasItem(sameInstance(newConfig)))); + assertThat(newBuilder.build().getServiceConfigurations(), hasItem(sameInstance(newConfig))); + assertThat(newBuilder.build().getServiceConfigurations(), not(hasItem(sameInstance(oldConfig)))); } @Test @@ -400,12 +402,14 @@ public void testCompatibleServiceJoinsExistingConfiguration() { ServiceConfiguration oldConfig = new CompatibleServiceConfig(); ServiceConfiguration newConfig = new CompatibleServiceConfig(); - CacheConfigurationBuilder oldBuilder = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(oldConfig); + CacheConfigurationBuilder oldBuilder = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(oldConfig); - CacheConfigurationBuilder newBuilder = oldBuilder.withService(newConfig); + CacheConfigurationBuilder newBuilder = oldBuilder.withService(newConfig); - assertThat(oldBuilder.build().getServiceConfigurations(), both(hasItem(sameInstance(oldConfig))).and(not(hasItem(sameInstance(newConfig))))); - assertThat(newBuilder.build().getServiceConfigurations(), both(hasItem(sameInstance(oldConfig))).and(hasItem(sameInstance(newConfig)))); + assertThat(oldBuilder.build().getServiceConfigurations(), hasItem(sameInstance(oldConfig))); + assertThat(oldBuilder.build().getServiceConfigurations(), not(hasItem(sameInstance(newConfig)))); + assertThat(newBuilder.build().getServiceConfigurations(), hasItem(sameInstance(oldConfig))); + assertThat(newBuilder.build().getServiceConfigurations(), hasItem(sameInstance(newConfig))); } @Test diff --git a/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java b/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java index 6b38682668..bcfaaff5d7 100644 --- a/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java +++ b/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java @@ -207,7 +207,7 @@ public OptimizedDateSerializer(ClassLoader classLoader) {} @Override public ByteBuffer serialize(Date object) throws SerializerException { ByteBuffer buffer = ByteBuffer.allocate(8); - return (ByteBuffer) buffer.putLong(object.getTime()).flip(); + return buffer.putLong(object.getTime()).flip(); } @Override diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java index 9dcad09ee4..9afa8d8a14 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java @@ -34,6 +34,7 @@ import org.ehcache.impl.internal.store.heap.OnHeapStore; import org.ehcache.impl.internal.store.offheap.OffHeapStore; import org.ehcache.spi.service.Service; +import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.spi.service.ServiceProvider; import org.hamcrest.Matchers; import org.junit.Test; @@ -867,15 +868,15 @@ public void testReleaseStoreFlushes() throws Exception { OnHeapStore.Provider onHeapStoreProvider = mock(OnHeapStore.Provider.class); Set> cachingResources = Collections.>singleton( ResourceType.Core.HEAP); when(onHeapStoreProvider.rankCachingTier(eq(cachingResources), any(Collection.class))).thenReturn(1); - when(onHeapStoreProvider.createCachingTier(eq(cachingResources), any(Store.Configuration.class), - ArgumentMatchers.any())) + when(onHeapStoreProvider.createCachingTier(any(Set.class), any(Store.Configuration.class), + any(ServiceConfiguration[].class))) .thenReturn(stringCachingTier); OffHeapStore.Provider offHeapStoreProvider = mock(OffHeapStore.Provider.class); Set> authorityResources = Collections.>singleton( ResourceType.Core.OFFHEAP); when(offHeapStoreProvider.rankAuthority(eq(authorityResources), any(Collection.class))).thenReturn(1); - when(offHeapStoreProvider.createAuthoritativeTier(eq(authorityResources), - any(Store.Configuration.class), ArgumentMatchers.any())) + when(offHeapStoreProvider.createAuthoritativeTier(any(Set.class), + any(Store.Configuration.class), any(ServiceConfiguration[].class))) .thenReturn(stringAuthoritativeTier); Store.Configuration configuration = mock(Store.Configuration.class); diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java index 31612486f1..488513668e 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java @@ -47,7 +47,7 @@ public void addingSerializableField() throws Exception { serializer.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(A_write.class, IncompatibleSerializable_write.class, Serializable_write.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(A_write.class)).newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(A_write.class)).getDeclaredConstructor().newInstance(); ByteBuffer encodedA = serializer.serialize(a); pushTccl(createClassNameRewritingLoader(A_read.class, IncompatibleSerializable_read.class)); @@ -65,7 +65,7 @@ public void addingExternalizableField() throws Exception { serializer.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(B_write.class, Externalizable_write.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(B_write.class)).newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(B_write.class)).getDeclaredConstructor().newInstance(); ByteBuffer encodedA = serializer.serialize(a); pushTccl(createClassNameRewritingLoader(B_read.class)); diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedSuperClassTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedSuperClassTest.java index 6e897bab53..ca4d245ddb 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedSuperClassTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedSuperClassTest.java @@ -41,7 +41,7 @@ public void testAddedSuperClass() throws Exception { serializer.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(A_2.class, AddedSuperClass_Hidden.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(A_2.class)).newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(A_2.class)).getDeclaredConstructor().newInstance(); ByteBuffer encodedA = serializer.serialize(a); pushTccl(createClassNameRewritingLoader(A_1.class)); @@ -58,7 +58,7 @@ public void testAddedSuperClassNotHidden() throws Exception { serializer.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(A_2.class, AddedSuperClass_Hidden.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(A_2.class)).newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(A_2.class)).getDeclaredConstructor().newInstance(); ByteBuffer encodedA = serializer.serialize(a); pushTccl(createClassNameRewritingLoader(A_1.class, AddedSuperClass_Hidden.class)); diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassLoaderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassLoaderTest.java index a7d9bb25bd..c01a28e532 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassLoaderTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassLoaderTest.java @@ -42,7 +42,7 @@ public void testThreadContextLoader() throws Exception { serializer.init(new TransientStateRepository()); ClassLoader loader = newLoader(); - ByteBuffer encoded = serializer.serialize((Serializable) loader.loadClass(Foo.class.getName()).newInstance()); + ByteBuffer encoded = serializer.serialize((Serializable) loader.loadClass(Foo.class.getName()).getDeclaredConstructor().newInstance()); pushTccl(loader); try { @@ -58,7 +58,7 @@ public void testExplicitLoader() throws Exception { StatefulSerializer serializer = new CompactJavaSerializer<>(loader); serializer.init(new TransientStateRepository()); - ByteBuffer encoded = serializer.serialize((Serializable) loader.loadClass(Foo.class.getName()).newInstance()); + ByteBuffer encoded = serializer.serialize((Serializable) loader.loadClass(Foo.class.getName()).getDeclaredConstructor().newInstance()); // setting TCCL doesn't matter here, but set it to make sure it doesn't get used pushTccl(newLoader()); diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassUnloadingTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassUnloadingTest.java index b115b68eb7..15aab1730d 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassUnloadingTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassUnloadingTest.java @@ -49,7 +49,7 @@ public void createSpecialObject() throws Exception { Class special = (Class) duplicate.loadClass(SpecialClass.class.getName()); classRef = new WeakReference<>(special); - specialObject = special.newInstance(); + specialObject = special.getDeclaredConstructor().newInstance(); } @Test diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/GetFieldTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/GetFieldTest.java index ccb69e6f9f..151ee159ce 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/GetFieldTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/GetFieldTest.java @@ -44,7 +44,7 @@ public void testGetField() throws Exception { s.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(Foo_A.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(Foo_A.class)).newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(Foo_A.class)).getDeclaredConstructor().newInstance(); ByteBuffer encodedA = s.serialize(a); pushTccl(createClassNameRewritingLoader(Foo_B.class)); diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java index ec1774fe36..b68c09215a 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java @@ -108,6 +108,7 @@ protected Class resolveClass(ObjectStreamClass desc) throws IOException, Clas } @Override + @SuppressWarnings("deprecation") protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException { Class[] interfaceClasses = new Class[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/PutFieldTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/PutFieldTest.java index bc2da6c360..5122085349 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/PutFieldTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/PutFieldTest.java @@ -45,7 +45,7 @@ public void testWithAllPrimitivesAndString() throws Exception { s.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(Foo_A.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(Foo_A.class)).newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(Foo_A.class)).getDeclaredConstructor().newInstance(); ByteBuffer encodedA = s.serialize(a); pushTccl(Foo.class.getClassLoader()); @@ -72,7 +72,7 @@ public void testWithTwoStrings() throws Exception { s.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(Bar_A.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(Bar_A.class)).newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(Bar_A.class)).getDeclaredConstructor().newInstance(); ByteBuffer encodedA = s.serialize(a); pushTccl(Bar.class.getClassLoader()); diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/ReadObjectNoDataTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/ReadObjectNoDataTest.java index 7c9bc2ca01..5a30f20906 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/ReadObjectNoDataTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/ReadObjectNoDataTest.java @@ -44,7 +44,7 @@ public void test() throws Exception { ClassLoader loaderW = createClassNameRewritingLoader(C_W.class, B_W.class); - ByteBuffer b = s.serialize((Serializable) loaderW.loadClass(newClassName(C_W.class)).newInstance()); + ByteBuffer b = s.serialize((Serializable) loaderW.loadClass(newClassName(C_W.class)).getDeclaredConstructor().newInstance()); pushTccl(createClassNameRewritingLoader(C_R.class, B_R.class, A_R.class)); try { diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java index 80246ae1a7..795c8ed217 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java @@ -41,7 +41,7 @@ public void test() throws Exception { s.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(A_old.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(A_old.class)).newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(A_old.class)).getDeclaredConstructor().newInstance(); ByteBuffer encodedA = s.serialize(a); ClassLoader loaderB = createClassNameRewritingLoader(A_new.class); @@ -50,7 +50,7 @@ public void test() throws Exception { Serializable outA = s.read(encodedA); assertThat((Integer) outA.getClass().getField("integer").get(outA), is(42)); - Serializable b = (Serializable) loaderB.loadClass(newClassName(A_new.class)).newInstance(); + Serializable b = (Serializable) loaderB.loadClass(newClassName(A_new.class)).getDeclaredConstructor().newInstance(); Serializable outB = s.read(s.serialize(b)); assertThat((Integer) outB.getClass().getField("integer").get(outB), is(42)); } finally { diff --git a/ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java b/ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java index 97ad217521..f1a16121e2 100644 --- a/ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java +++ b/ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java @@ -2583,7 +2583,6 @@ else if (f instanceof TreeBin) { * A padded cell for distributing counts. Adapted from LongAdder * and Striped64. See their internal docs for explanation. */ - @sun.misc.Contended static final class CounterCell { volatile long value; CounterCell(long x) { value = x; } diff --git a/ehcache-management/build.gradle b/ehcache-management/build.gradle index 055ec39134..7dcc0fb3df 100644 --- a/ehcache-management/build.gradle +++ b/ehcache-management/build.gradle @@ -29,7 +29,9 @@ publishing.publications.withType(MavenPublication) { dependencies { api project(':ehcache-core') implementation project(':ehcache-impl') - implementation "org.terracotta:statistics:$statisticVersion" + implementation ("org.terracotta:statistics:$statisticVersion") { + exclude group: 'org.slf4j' + } // optional: if we want xml config compileOnlyApi project(':ehcache-xml:ehcache-xml-spi') @@ -40,9 +42,12 @@ dependencies { compileOnlyApi ("org.terracotta.management:nms-agent-entity-client:$terracottaPlatformVersion") { // This is to avoid stats lib being directly used. exclude group:'org.terracotta', module:'statistics' + exclude group: 'org.slf4j' } - testImplementation "org.terracotta.management:management-registry:$terracottaPlatformVersion" + testImplementation ("org.terracotta.management:management-registry:$terracottaPlatformVersion") { + exclude group: 'org.slf4j' + } testImplementation project(':ehcache-xml') testImplementation "org.terracotta.common:common-json-support:$terracottaPlatformVersion" testImplementation testFixtures(project(':ehcache-xml')) diff --git a/ehcache-management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java b/ehcache-management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java index 2b4f6ebd95..6f4b5b774f 100644 --- a/ehcache-management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java +++ b/ehcache-management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java @@ -120,7 +120,7 @@ public void descriptorOnHeapTest() { allDescriptors.addAll(ONHEAP_DESCRIPTORS); allDescriptors.addAll(CACHE_DESCRIPTORS); - assertThat(descriptors).hasSameElementsAs(allDescriptors); + assertThat(allDescriptors).hasSameElementsAs(descriptors); } } @@ -150,7 +150,7 @@ public void descriptorOnHeapTest_withoutStats() { allDescriptors.addAll(ONHEAP_NO_STATS_DESCRIPTORS); allDescriptors.addAll(CACHE_DESCRIPTORS); - assertThat(descriptors).hasSameElementsAs(allDescriptors); + assertThat(allDescriptors).hasSameElementsAs(descriptors); } } @@ -181,7 +181,7 @@ public void descriptorOffHeapTest() { allDescriptors.addAll(OFFHEAP_DESCRIPTORS); allDescriptors.addAll(CACHE_DESCRIPTORS); - assertThat(descriptors).hasSameElementsAs(allDescriptors); + assertThat(allDescriptors).hasSameElementsAs(descriptors); } } @@ -215,7 +215,7 @@ public void descriptorDiskStoreTest() throws Exception { allDescriptors.addAll(DISK_DESCRIPTORS); allDescriptors.addAll(CACHE_DESCRIPTORS); - assertThat(descriptors).hasSameElementsAs(allDescriptors); + assertThat(allDescriptors).hasSameElementsAs(descriptors); } } diff --git a/ehcache-transactions/build.gradle b/ehcache-transactions/build.gradle index 152c25f0a8..0944478484 100644 --- a/ehcache-transactions/build.gradle +++ b/ehcache-transactions/build.gradle @@ -119,7 +119,9 @@ dependencies { jakartaTestRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" jakartaTestImplementation "junit:junit:$junitVersion" jakartaTestImplementation "org.hamcrest:hamcrest-library:$hamcrestVersion" - jakartaTestImplementation "org.terracotta:terracotta-utilities-test-tools:$terracottaUtilitiesVersion" + jakartaTestImplementation ("org.terracotta:terracotta-utilities-test-tools:$terracottaUtilitiesVersion") { + exclude group: 'org.slf4j' + } } configurations { diff --git a/ehcache-transactions/src/common/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java b/ehcache-transactions/src/common/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java index 44b9cbac75..2da9e8c9f0 100644 --- a/ehcache-transactions/src/common/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java +++ b/ehcache-transactions/src/common/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java @@ -111,6 +111,7 @@ protected Class resolveClass(ObjectStreamClass desc) throws ClassNotFoundExce } @Override + @SuppressWarnings("deprecation") protected Class resolveProxyClass(String[] interfaces) throws ClassNotFoundException { Class[] interfaceClasses = new Class[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { diff --git a/ehcache-transactions/src/jakarta/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java b/ehcache-transactions/src/jakarta/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java index 97f78f02f9..290bca898e 100644 --- a/ehcache-transactions/src/jakarta/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java +++ b/ehcache-transactions/src/jakarta/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java @@ -55,8 +55,8 @@ public LookupTransactionManagerProvider(LookupTransactionManagerProviderConfigur throw new NullPointerException("LookupTransactionManagerProviderConfiguration cannot be null"); } try { - lookup = config.getTransactionManagerLookup().newInstance(); - } catch (InstantiationException | IllegalAccessException e) { + lookup = config.getTransactionManagerLookup().getDeclaredConstructor().newInstance(); + } catch (ReflectiveOperationException e) { throw new IllegalArgumentException("Could not instantiate lookup class", e); } } diff --git a/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java index b8ea5a2764..4f86374ad3 100644 --- a/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java +++ b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java @@ -56,8 +56,8 @@ public LookupTransactionManagerProvider(LookupTransactionManagerProviderConfigur throw new NullPointerException("LookupTransactionManagerProviderConfiguration cannot be null"); } try { - lookup = config.getTransactionManagerLookup().newInstance(); - } catch (InstantiationException | IllegalAccessException e) { + lookup = config.getTransactionManagerLookup().getDeclaredConstructor().newInstance(); + } catch (ReflectiveOperationException e) { throw new IllegalArgumentException("Could not instantiate lookup class", e); } } diff --git a/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java index dab8615e97..c335c6cd0c 100644 --- a/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java +++ b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java @@ -108,6 +108,7 @@ protected Class resolveClass(ObjectStreamClass desc) throws IOException, Clas } @Override + @SuppressWarnings("deprecation") protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException { Class[] interfaceClasses = new Class[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { diff --git a/ehcache-xml/build.gradle b/ehcache-xml/build.gradle index c9dcd8e286..64ac2910a8 100644 --- a/ehcache-xml/build.gradle +++ b/ehcache-xml/build.gradle @@ -115,6 +115,7 @@ dependencies { xjcToolJakarta 'com.sun.xml.bind:jaxb-xjc:3.0.0-M4' xjcToolJakarta 'com.sun.xml.bind:jaxb-impl:3.0.0-M4' + xjcToolJakarta 'javax.xml.bind:jaxb-api:[2.2,3)' lowerBoundTestRuntimeClasspath 'com.sun.activation:javax.activation:1.2.0' } diff --git a/ehcache-xml/ehcache-xml-spi/src/main/java/org/ehcache/xml/ParsingUtil.java b/ehcache-xml/ehcache-xml-spi/src/main/java/org/ehcache/xml/ParsingUtil.java index 073f74d274..6f0315b7db 100644 --- a/ehcache-xml/ehcache-xml-spi/src/main/java/org/ehcache/xml/ParsingUtil.java +++ b/ehcache-xml/ehcache-xml-spi/src/main/java/org/ehcache/xml/ParsingUtil.java @@ -20,12 +20,9 @@ import org.ehcache.javadoc.PublicApi; import java.math.BigInteger; -import java.security.PrivilegedAction; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static java.security.AccessController.doPrivileged; - @PublicApi public class ParsingUtil { @@ -36,7 +33,7 @@ public static String parsePropertyOrString(String s) { Matcher matcher = PADDED_SYSPROP.matcher(s); if (matcher.matches()) { String property = matcher.group("property"); - String value = doPrivileged((PrivilegedAction) () -> System.getProperty(property)); + String value = System.getProperty(property); if (value == null) { throw new IllegalStateException(String.format("Replacement for ${%s} not found!", property)); } else { @@ -74,7 +71,7 @@ public static String parseStringWithProperties(String s) { StringBuffer sb = new StringBuffer(); while (matcher.find()) { final String property = matcher.group("property"); - final String value = doPrivileged((PrivilegedAction) () -> System.getProperty(property)); + final String value = System.getProperty(property); if (value == null) { throw new IllegalStateException(String.format("Replacement for ${%s} not found!", property)); } diff --git a/ehcache-xml/src/jakarta/java/org/ehcache/xml/ConfigurationParser.java b/ehcache-xml/src/jakarta/java/org/ehcache/xml/ConfigurationParser.java index 3b19d87feb..afcbc410c9 100644 --- a/ehcache-xml/src/jakarta/java/org/ehcache/xml/ConfigurationParser.java +++ b/ehcache-xml/src/jakarta/java/org/ehcache/xml/ConfigurationParser.java @@ -150,7 +150,7 @@ private static Stream stream(Iterable iterable) { CacheConfigurationBuilder parseServiceConfigurations(Document document, CacheConfigurationBuilder cacheBuilder, ClassLoader cacheClassLoader, CacheTemplate cacheDefinition) - throws ClassNotFoundException, IllegalAccessException, InstantiationException { + throws ReflectiveOperationException { cacheBuilder = CORE_CACHE_CONFIGURATION_PARSER.parse(cacheDefinition, cacheClassLoader, cacheBuilder); return serviceConfigurationParser.parse(document, cacheDefinition, cacheClassLoader, cacheBuilder); } @@ -194,7 +194,7 @@ private Map getTemplates(Document document, C private XmlConfiguration.Template parseTemplate(Document document, CacheTemplate template) { return new XmlConfiguration.Template() { @Override - public CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resources) throws ClassNotFoundException, InstantiationException, IllegalAccessException { + public CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resources) throws ReflectiveOperationException { checkTemplateTypeConsistency("key", classLoader, keyType, template); checkTemplateTypeConsistency("value", classLoader, valueType, template); @@ -228,7 +228,7 @@ public Document uriToDocument(URI uri) throws IOException, SAXException { return documentBuilder.parse(uri.toString()); } - public XmlConfigurationWrapper documentToConfig(Document document, ClassLoader classLoader, Map cacheClassLoaders) throws JAXBException, ClassNotFoundException, InstantiationException, IllegalAccessException { + public XmlConfigurationWrapper documentToConfig(Document document, ClassLoader classLoader, Map cacheClassLoaders) throws JAXBException, ReflectiveOperationException { Document annotatedDocument = stampExternalConfigurations(copyAndValidate(document)); Element root = annotatedDocument.getDocumentElement(); diff --git a/ehcache-xml/src/jakarta/java/org/ehcache/xml/CoreCacheConfigurationParser.java b/ehcache-xml/src/jakarta/java/org/ehcache/xml/CoreCacheConfigurationParser.java index 02666ca854..1c1126fd40 100644 --- a/ehcache-xml/src/jakarta/java/org/ehcache/xml/CoreCacheConfigurationParser.java +++ b/ehcache-xml/src/jakarta/java/org/ehcache/xml/CoreCacheConfigurationParser.java @@ -44,7 +44,7 @@ public class CoreCacheConfigurationParser { public CacheConfigurationBuilder parse(CacheTemplate cacheDefinition, ClassLoader cacheClassLoader, - CacheConfigurationBuilder cacheBuilder) throws ClassNotFoundException, IllegalAccessException, InstantiationException { + CacheConfigurationBuilder cacheBuilder) throws ReflectiveOperationException { final Expiry parsedExpiry = cacheDefinition.expiry(); if (parsedExpiry != null) { cacheBuilder = cacheBuilder.withExpiry(getExpiry(cacheClassLoader, parsedExpiry)); @@ -59,7 +59,7 @@ public CacheConfigurationBuilder parse(CacheTemplate cacheDefinitio @SuppressWarnings({"unchecked", "deprecation"}) private static ExpiryPolicy getExpiry(ClassLoader cacheClassLoader, Expiry parsedExpiry) - throws ClassNotFoundException, InstantiationException, IllegalAccessException { + throws ReflectiveOperationException { if (parsedExpiry.isUserDef()) { try { return getInstanceOfName(parsedExpiry.type(), cacheClassLoader, ExpiryPolicy.class); @@ -75,12 +75,12 @@ public CacheConfigurationBuilder parse(CacheTemplate cacheDefinitio } } - static T getInstanceOfName(String name, ClassLoader classLoader, Class type) throws ClassNotFoundException, InstantiationException, IllegalAccessException { + static T getInstanceOfName(String name, ClassLoader classLoader, Class type) throws ReflectiveOperationException { if (name == null) { return null; } Class klazz = getClassForName(name, classLoader); - return klazz.asSubclass(type).newInstance(); + return klazz.asSubclass(type).getDeclaredConstructor().newInstance(); } public CacheType unparse(CacheConfiguration cacheConfiguration, CacheType cacheType) { diff --git a/ehcache-xml/src/jakarta/java/org/ehcache/xml/XmlConfiguration.java b/ehcache-xml/src/jakarta/java/org/ehcache/xml/XmlConfiguration.java index 7db144bfb0..24db84de13 100644 --- a/ehcache-xml/src/jakarta/java/org/ehcache/xml/XmlConfiguration.java +++ b/ehcache-xml/src/jakarta/java/org/ehcache/xml/XmlConfiguration.java @@ -272,7 +272,7 @@ public URL getURL() { public CacheConfigurationBuilder newCacheConfigurationBuilderFromTemplate(final String name, final Class keyType, final Class valueType) - throws InstantiationException, IllegalAccessException, ClassNotFoundException { + throws ReflectiveOperationException { Template template = templates.get(name); if (template == null) { return null; @@ -307,7 +307,7 @@ public CacheConfigurationBuilder newCacheConfigurationBuilderFromTe final Class keyType, final Class valueType, final ResourcePools resourcePools) - throws InstantiationException, IllegalAccessException, ClassNotFoundException { + throws ReflectiveOperationException { Template template = templates.get(name); if (template == null) { return null; @@ -342,7 +342,7 @@ public CacheConfigurationBuilder newCacheConfigurationBuilderFromTe final Class keyType, final Class valueType, final Builder resourcePoolsBuilder) - throws InstantiationException, IllegalAccessException, ClassNotFoundException { + throws ReflectiveOperationException { return newCacheConfigurationBuilderFromTemplate(name, keyType, valueType, resourcePoolsBuilder.build()); } @@ -372,7 +372,7 @@ public FluentConfigurationBuilder derive() { } public interface Template { - CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resourcePools) throws ClassNotFoundException, InstantiationException, IllegalAccessException; + CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resourcePools) throws ReflectiveOperationException; } public static Class getClassForName(String name, ClassLoader classLoader) throws ClassNotFoundException { diff --git a/ehcache-xml/src/main/java/org/ehcache/xml/ConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/ConfigurationParser.java index 275b7d35cc..0f525243d1 100644 --- a/ehcache-xml/src/main/java/org/ehcache/xml/ConfigurationParser.java +++ b/ehcache-xml/src/main/java/org/ehcache/xml/ConfigurationParser.java @@ -149,7 +149,7 @@ private static Stream stream(Iterable iterable) { CacheConfigurationBuilder parseServiceConfigurations(Document document, CacheConfigurationBuilder cacheBuilder, ClassLoader cacheClassLoader, CacheTemplate cacheDefinition) - throws ClassNotFoundException, IllegalAccessException, InstantiationException { + throws ReflectiveOperationException { cacheBuilder = CORE_CACHE_CONFIGURATION_PARSER.parse(cacheDefinition, cacheClassLoader, cacheBuilder); return serviceConfigurationParser.parse(document, cacheDefinition, cacheClassLoader, cacheBuilder); } @@ -193,7 +193,7 @@ private Map getTemplates(Document document, C private XmlConfiguration.Template parseTemplate(Document document, CacheTemplate template) { return new XmlConfiguration.Template() { @Override - public CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resources) throws ClassNotFoundException, InstantiationException, IllegalAccessException { + public CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resources) throws ReflectiveOperationException { checkTemplateTypeConsistency("key", classLoader, keyType, template); checkTemplateTypeConsistency("value", classLoader, valueType, template); @@ -227,7 +227,7 @@ public Document uriToDocument(URI uri) throws IOException, SAXException { return documentBuilder.parse(uri.toString()); } - public XmlConfigurationWrapper documentToConfig(Document document, ClassLoader classLoader, Map cacheClassLoaders) throws JAXBException, ClassNotFoundException, InstantiationException, IllegalAccessException { + public XmlConfigurationWrapper documentToConfig(Document document, ClassLoader classLoader, Map cacheClassLoaders) throws JAXBException, ReflectiveOperationException { Document annotatedDocument = stampExternalConfigurations(copyAndValidate(document)); Element root = annotatedDocument.getDocumentElement(); diff --git a/ehcache-xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java index 02666ca854..1c1126fd40 100644 --- a/ehcache-xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java +++ b/ehcache-xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java @@ -44,7 +44,7 @@ public class CoreCacheConfigurationParser { public CacheConfigurationBuilder parse(CacheTemplate cacheDefinition, ClassLoader cacheClassLoader, - CacheConfigurationBuilder cacheBuilder) throws ClassNotFoundException, IllegalAccessException, InstantiationException { + CacheConfigurationBuilder cacheBuilder) throws ReflectiveOperationException { final Expiry parsedExpiry = cacheDefinition.expiry(); if (parsedExpiry != null) { cacheBuilder = cacheBuilder.withExpiry(getExpiry(cacheClassLoader, parsedExpiry)); @@ -59,7 +59,7 @@ public CacheConfigurationBuilder parse(CacheTemplate cacheDefinitio @SuppressWarnings({"unchecked", "deprecation"}) private static ExpiryPolicy getExpiry(ClassLoader cacheClassLoader, Expiry parsedExpiry) - throws ClassNotFoundException, InstantiationException, IllegalAccessException { + throws ReflectiveOperationException { if (parsedExpiry.isUserDef()) { try { return getInstanceOfName(parsedExpiry.type(), cacheClassLoader, ExpiryPolicy.class); @@ -75,12 +75,12 @@ public CacheConfigurationBuilder parse(CacheTemplate cacheDefinitio } } - static T getInstanceOfName(String name, ClassLoader classLoader, Class type) throws ClassNotFoundException, InstantiationException, IllegalAccessException { + static T getInstanceOfName(String name, ClassLoader classLoader, Class type) throws ReflectiveOperationException { if (name == null) { return null; } Class klazz = getClassForName(name, classLoader); - return klazz.asSubclass(type).newInstance(); + return klazz.asSubclass(type).getDeclaredConstructor().newInstance(); } public CacheType unparse(CacheConfiguration cacheConfiguration, CacheType cacheType) { diff --git a/ehcache-xml/src/main/java/org/ehcache/xml/XmlConfiguration.java b/ehcache-xml/src/main/java/org/ehcache/xml/XmlConfiguration.java index 3363470e2a..b2c3f2433e 100644 --- a/ehcache-xml/src/main/java/org/ehcache/xml/XmlConfiguration.java +++ b/ehcache-xml/src/main/java/org/ehcache/xml/XmlConfiguration.java @@ -271,7 +271,7 @@ public URL getURL() { public CacheConfigurationBuilder newCacheConfigurationBuilderFromTemplate(final String name, final Class keyType, final Class valueType) - throws InstantiationException, IllegalAccessException, ClassNotFoundException { + throws ReflectiveOperationException { Template template = templates.get(name); if (template == null) { return null; @@ -305,7 +305,7 @@ public CacheConfigurationBuilder newCacheConfigurationBuilderFromTe final Class keyType, final Class valueType, final ResourcePools resourcePools) - throws InstantiationException, IllegalAccessException, ClassNotFoundException { + throws ReflectiveOperationException { Template template = templates.get(name); if (template == null) { return null; @@ -339,7 +339,7 @@ public CacheConfigurationBuilder newCacheConfigurationBuilderFromTe final Class keyType, final Class valueType, final Builder resourcePoolsBuilder) - throws InstantiationException, IllegalAccessException, ClassNotFoundException { + throws ReflectiveOperationException { return newCacheConfigurationBuilderFromTemplate(name, keyType, valueType, resourcePoolsBuilder.build()); } @@ -369,7 +369,7 @@ public FluentConfigurationBuilder derive() { } public interface Template { - CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resourcePools) throws ClassNotFoundException, InstantiationException, IllegalAccessException; + CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resourcePools) throws ReflectiveOperationException; } public static Class getClassForName(String name, ClassLoader classLoader) throws ClassNotFoundException { diff --git a/ehcache-xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java index e33f0eb713..3266ac2161 100644 --- a/ehcache-xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java +++ b/ehcache-xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java @@ -125,7 +125,7 @@ public void testLoaderWriter() throws ClassNotFoundException, SAXException, Inst final Cache cache = cacheManager.getCache("bar", Number.class, String.class); assertThat(cache, notNullValue()); assertThat(cache.get(1), notNullValue()); - final Number key = new Long(42); + final Number key = 42L; cache.put(key, "Bye y'all!"); assertThat(TestCacheLoaderWriter.lastWrittenKey, is(key)); @@ -133,7 +133,7 @@ public void testLoaderWriter() throws ClassNotFoundException, SAXException, Inst final Cache templateCache = cacheManager.getCache("template1", Number.class, String.class); assertThat(templateCache, notNullValue()); assertThat(templateCache.get(1), notNullValue()); - final Number key1 = new Long(100); + final Number key1 = 100L; templateCache.put(key1, "Bye y'all!"); assertThat(TestCacheLoaderWriter.lastWrittenKey, is(key1)); } diff --git a/ehcache/build.gradle b/ehcache/build.gradle index 98cc84e224..145f067156 100644 --- a/ehcache/build.gradle +++ b/ehcache/build.gradle @@ -69,6 +69,8 @@ configurations { jakartaContents { exclude group:'jakarta.xml.bind' } + javadocAdd + jakartaJavadocAdd } dependencies { @@ -94,6 +96,12 @@ dependencies { } } jakartaRuntimeOnly 'org.glassfish.jaxb:jaxb-runtime:[3,3.1)' + + javadocAdd 'com.github.spotbugs:spotbugs-annotations:4.9.8' + javadocAdd 'javax.xml.bind:jaxb-api:[2.2,3)' + + jakartaJavadocAdd 'com.github.spotbugs:spotbugs-annotations:4.9.8' + jakartaJavadocAdd 'jakarta.xml.bind:jakarta.xml.bind-api:[3,4)' } tasks.named('jakartaJar') { @@ -103,7 +111,7 @@ tasks.named('jakartaJar') { instruction Constants.BUNDLE_DESCRIPTION, 'Ehcache is an open-source caching library, compliant with the JSR-107 standard.' instruction Constants.BUNDLE_ACTIVATOR, 'org.ehcache.core.osgi.EhcacheActivator' instruction Constants.EXPORT_PACKAGE, '!org.ehcache.jsr107.tck, !org.ehcache.*.internal.*, org.ehcache.*' - instruction Constants.IMPORT_PACKAGE, 'javax.cache.*;resolution:=optional, jdk.internal.misc;resolution:=optional, !javax.annotation, !sun.misc, jakarta.xml.bind*;version="[3,4)", *' + instruction Constants.IMPORT_PACKAGE, 'javax.annotation.*;resolution:=optional, javax.cache.*;resolution:=optional, jdk.internal.misc;resolution:=optional, !javax.annotation, !sun.misc, jakarta.xml.bind*;version="[3,4)", *' } } @@ -114,6 +122,14 @@ tasks.named('jar') { instruction Constants.BUNDLE_DESCRIPTION, 'Ehcache is an open-source caching library, compliant with the JSR-107 standard.' instruction Constants.BUNDLE_ACTIVATOR, 'org.ehcache.core.osgi.EhcacheActivator' instruction Constants.EXPORT_PACKAGE, '!org.ehcache.jsr107.tck, !org.ehcache.*.internal.*, org.ehcache.*' - instruction Constants.IMPORT_PACKAGE, 'javax.cache.*;resolution:=optional, jdk.internal.misc;resolution:=optional, !javax.annotation, !sun.misc, javax.xml.bind*;version="[2.2,3)", *' + instruction Constants.IMPORT_PACKAGE, 'javax.annotation.*;resolution:=optional, javax.cache.*;resolution:=optional, jdk.internal.misc;resolution:=optional, !javax.annotation, !sun.misc, javax.xml.bind*;version="[2.2,3)", *' } } + +tasks.named('javadoc') { + classpath += configurations.javadocAdd +} + +tasks.named('jakartaJavadoc') { + classpath += configurations.jakartaJavadocAdd +} diff --git a/gradle.properties b/gradle.properties index 49162e7fe7..a973c451c7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ ehcacheVersion = 3.11-SNAPSHOT offheapVersion = 2.5.6 statisticVersion = 2.1.3 jcacheVersion = 1.1.0 -slf4jVersion = 1.7.36 +slf4jVersion = 2.0.17 sizeofVersion = 0.4.4 # Terracotta clustered @@ -17,10 +17,12 @@ terracottaUtilitiesVersion = 0.0.19 # Test lib versions junitVersion = 4.13.1 -assertjVersion = 3.22.0 +assertjVersion = 3.27.7 +byteBuddyVersion = 1.18.3 hamcrestVersion = 2.2 -mockitoVersion = 4.3.1 +mockitoVersion = 5.12.0 jcacheTckVersion = 1.1.0 +logbackVersion = 1.5.26 sonatypeUser = OVERRIDE_ME sonatypePwd = OVERRIDE_ME diff --git a/integration-test/build.gradle b/integration-test/build.gradle index 7f1aae39e9..8f50fac865 100644 --- a/integration-test/build.gradle +++ b/integration-test/build.gradle @@ -31,5 +31,7 @@ dependencies { testImplementation (group: 'org.codehaus.btm', name: 'btm', version: '2.1.4') { exclude group:'org.slf4j', module:'slf4j-api' } - testImplementation "org.terracotta:statistics:$parent.statisticVersion" + testImplementation ("org.terracotta:statistics:$parent.statisticVersion") { + exclude group: 'org.slf4j', module: 'slf4j-api' + } } diff --git a/integration-test/src/test/java/org/ehcache/integration/OverSizeMappingTest.java b/integration-test/src/test/java/org/ehcache/integration/OverSizeMappingTest.java index e23b6f9f8e..29d7d37877 100644 --- a/integration-test/src/test/java/org/ehcache/integration/OverSizeMappingTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/OverSizeMappingTest.java @@ -124,7 +124,7 @@ private static class ObjectSizeGreaterThanN implements Serializable { private ObjectSizeGreaterThanN(int n) { arr = new Integer[n]; for (int i = 0; i < arr.length; i++) { - arr[i] = new Integer(i); + arr[i] = i; } } diff --git a/osgi-test/build.gradle b/osgi-test/build.gradle index 07d4ec52c2..68c6286d99 100644 --- a/osgi-test/build.gradle +++ b/osgi-test/build.gradle @@ -57,6 +57,8 @@ dependencies { osgiModule project(':ehcache') osgiModule "org.slf4j:slf4j-simple:$parent.slf4jVersion" + // SLF4J 2.x requires osgi.serviceloader.processor; Apache Aries SPIFly provides it + osgiModule 'org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle:1.3.7' osgiModule 'org.apache.felix:org.apache.felix.scr:2.2.0' osgiModule 'com.sun.activation:javax.activation:1.2.0' @@ -77,6 +79,11 @@ configurations.all { .using(module('org.ops4j.pax.url:pax-url-classpath:2.6.11')) substitute(module('org.ops4j.pax.url:pax-url-link:2.6.8')) .using(module('org.ops4j.pax.url:pax-url-link:2.6.11')) + substitute(module('org.ops4j.pax.url:pax-url-aether:2.6.8')) + .using(module('org.ops4j.pax.url:pax-url-aether:3.0.2')) + substitute(module('org.apache.commons:commons-lang3:3.12.0')) + .using(module('org.apache.commons:commons-lang3:3.18.0')) + .because('CVE-2025-48924') substitute(module('org.osgi:org.osgi.util.function:1.1.0')) .using(module('org.osgi:org.osgi.util.function:1.2.0')) .because('Dependency divergence in org.osgi:org.osgi.util.promise:1.2.0') diff --git a/osgi-test/src/main/java/org/ehcache/osgi/OsgiTestUtils.java b/osgi-test/src/main/java/org/ehcache/osgi/OsgiTestUtils.java index ed4558f20f..e9599d4e9d 100644 --- a/osgi-test/src/main/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/osgi-test/src/main/java/org/ehcache/osgi/OsgiTestUtils.java @@ -49,6 +49,14 @@ public static Option baseConfiguration(String ... path) { return composite( gradleBundle("org.slf4j:slf4j-api"), gradleBundle("org.slf4j:slf4j-simple").noStart(), + // ASM bundles required by SPI Fly + gradleBundle("org.ow2.asm:asm"), + gradleBundle("org.ow2.asm:asm-tree"), + gradleBundle("org.ow2.asm:asm-analysis"), + gradleBundle("org.ow2.asm:asm-commons"), + gradleBundle("org.ow2.asm:asm-util"), + // SPI Fly for SLF4J 2.x ServiceLoader support + gradleBundle("org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle"), gradleBundle("org.apache.felix:org.apache.felix.scr"), gradleBundle("org.osgi:org.osgi.util.promise"), gradleBundle("org.osgi:org.osgi.util.function"), diff --git a/settings.gradle b/settings.gradle index 25b631c790..fbb97e9815 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,7 +18,6 @@ pluginManagement { plugins { id 'org.owasp.dependencycheck' version '7.1.0.1' - id 'org.gretty' version '3.0.6' id 'org.asciidoctor.jvm.base' version '3.3.2' id 'org.unbroken-dome.xjc' version '2.0.0' id 'com.jfrog.artifactory' version '5.2.5' From 8c357f54d1aeff2a1f99f7abed99525503a90221 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 9 Mar 2026 16:11:25 -0400 Subject: [PATCH 2/2] chris review/rethinking --- azure-pipelines.yml | 63 ++++++++++++------ .../build/conventions/BndConvention.java | 2 +- .../conventions/CheckstyleConvention.java | 18 ----- .../build/conventions/JavaBaseConvention.java | 4 +- .../build/conventions/JavaConvention.java | 21 +----- .../build/conventions/SpotbugsConvention.java | 10 +-- clustered/ehcache-client/build.gradle | 8 +-- .../service/DefaultClusteringService.java | 1 - .../store/CommonServerStoreProxy.java | 1 - .../DefaultClusteringServiceDestroyTest.java | 6 +- .../StateRepositoryWhitelistingTest.java | 4 +- .../internal/store/ClusteredStoreTest.java | 4 +- clustered/ehcache-clustered/build.gradle | 10 --- .../common/internal/store/ValueWrapper.java | 1 + clustered/ehcache-common/build.gradle | 4 +- .../Store/WhitelistedUnmarshallingTest.java | 18 ++--- .../internal/messages/ChainCodecTest.java | 10 +-- .../internal/messages/ResponseCodecTest.java | 2 +- clustered/integration-test/build.gradle | 26 ++------ .../ClusteringManagementServiceTest.java | 10 +-- ...dCacheOpsReplicationMultiThreadedTest.java | 11 +-- clustered/osgi-test/build.gradle | 17 +---- clustered/server/ehcache-entity/build.gradle | 12 +--- clustered/server/ehcache-service/build.gradle | 13 +--- .../offheap/OffHeapChainStorageEngine.java | 4 +- .../server/offheap/ChainMapExtensionTest.java | 2 +- .../server/offheap/ChainMapTest.java | 2 +- config/checkstyle.xml | 15 +---- .../internal/store/SPIStoreTester.java | 31 --------- .../internal/store/StoreContainsKeyTest.java | 9 ++- .../ehcache/internal/store/StoreGetTest.java | 9 ++- .../internal/store/StorePutIfAbsentTest.java | 18 +++-- .../ehcache/internal/store/StorePutTest.java | 18 ++++- .../internal/store/StoreRemoveKeyTest.java | 9 ++- .../store/StoreRemoveKeyValueTest.java | 18 ++++- .../store/StoreReplaceKeyValueTest.java | 18 ++++- .../config/checkstyle-suppressions.xml | 3 +- demos/build.gradle | 35 +++++++--- .../demos/server/EmbeddedPeeperServer.java | 2 +- docs/src/docs/asciidoc/user/examples.adoc | 6 +- ehcache-107/build.gradle | 10 ++- .../ParsesConfigurationExtensionTest.java | 4 +- ehcache-core/build.gradle | 4 +- .../org/ehcache/core/util/ClassLoading.java | 9 +-- .../org/ehcache/core/EhcacheManagerTest.java | 25 +++---- .../org/ehcache/core/PrefixLoggerTest.java | 12 ++-- ehcache-impl/build.gradle | 20 ++---- .../builders/UserManagedCacheBuilder.java | 2 +- .../commonslang/reflect/MemberUtils.java | 1 - .../internal/store/tiering/TieredStore.java | 4 +- .../ehcache/impl/persistence/FileUtils.java | 1 + .../serialization/PlainJavaSerializer.java | 2 +- .../CacheConfigurationBuilderTest.java | 16 ++--- .../ehcache/docs/ConfigurationDerivation.java | 2 +- .../store/tiering/TieredStoreTest.java | 9 ++- .../impl/serialization/AddedFieldTest.java | 4 +- .../serialization/AddedSuperClassTest.java | 4 +- .../CompactJavaSerializerClassLoaderTest.java | 4 +- ...mpactJavaSerializerClassUnloadingTest.java | 2 +- .../impl/serialization/GetFieldTest.java | 2 +- .../impl/serialization/JavaSerializer.java | 1 - .../impl/serialization/PutFieldTest.java | 4 +- .../serialization/ReadObjectNoDataTest.java | 2 +- .../SerializeAfterEvolutionTest.java | 4 +- .../concurrent/ConcurrentHashMap.java | 1 + ehcache-management/build.gradle | 9 +-- .../DefaultManagementRegistryServiceTest.java | 8 +-- ehcache-transactions/build.gradle | 4 +- .../xa/internal/SoftLockSerializer.java | 1 - .../LookupTransactionManagerProvider.java | 4 +- .../LookupTransactionManagerProvider.java | 4 +- .../transactions/xa/utils/JavaSerializer.java | 1 - .../java/org/ehcache/xml/ParsingUtil.java | 7 +- .../org/ehcache/xml/ConfigurationParser.java | 6 +- .../xml/CoreCacheConfigurationParser.java | 8 +-- .../org/ehcache/xml/XmlConfiguration.java | 8 +-- .../org/ehcache/xml/ConfigurationParser.java | 6 +- .../xml/CoreCacheConfigurationParser.java | 8 +-- .../org/ehcache/xml/XmlConfiguration.java | 8 +-- .../xml/IntegrationConfigurationTest.java | 4 +- ehcache/build.gradle | 20 +----- gradle.properties | 8 +-- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 61608 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 18 +++-- gradlew.bat | 15 +++-- integration-test/build.gradle | 4 +- .../integration/OverSizeMappingTest.java | 2 +- osgi-test/build.gradle | 11 +-- .../java/org/ehcache/osgi/OsgiTestUtils.java | 8 --- 90 files changed, 359 insertions(+), 440 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f2005e0b74..50375a8b65 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -25,25 +25,44 @@ resources: name: terracotta/terracotta jobs: - - template: build-templates/gradle-common.yml@templates - parameters: - jdkVersion: '17' - options: '-PtestVM=java17Home' - jobName: 'LinuxJava17' - gradleTasks: 'check -x dependencyCheckAggregate' - - - template: build-templates/gradle-common.yml@templates - parameters: - jdkVersion: '17' - options: '-PtestVM=java21Home' - jobName: 'LinuxJava21' - gradleTasks: 'check -x dependencyCheckAggregate' - - - - template: build-templates/gradle-common.yml@templates - parameters: - vmImage: 'windows-latest' - jdkVersion: '17' - options: '-PtestVM=java21Home' - jobName: 'WindowsJava21' - gradleTasks: 'check -x dependencyCheckAggregate' +- template: build-templates/gradle-common.yml@templates + parameters: + jdkVersion: '1.8' + jobName: 'LinuxJava8' + gradleTasks: 'check -x dependencyCheckAggregate' + +- template: build-templates/gradle-common.yml@templates + parameters: + jdkVersion: '1.8' + options: '-PtestVM=java11Home' + jobName: 'LinuxJava11' + gradleTasks: 'check -x dependencyCheckAggregate' + +- template: build-templates/gradle-common.yml@templates + parameters: + jdkVersion: '1.8' + options: '-PtestVM=java17Home' + jobName: 'LinuxJava17' + gradleTasks: 'check -x dependencyCheckAggregate' + +- template: build-templates/gradle-common.yml@templates + parameters: + jdkVersion: '1.8' + options: '-PtestVM=java21Home' + jobName: 'LinuxJava21' + gradleTasks: 'check -x dependencyCheckAggregate' + +- template: build-templates/gradle-common.yml@templates + parameters: + vmImage: 'windows-latest' + jdkVersion: '1.8' + jobName: 'WindowsJava8' + gradleTasks: 'check -x dependencyCheckAggregate' + +- template: build-templates/gradle-common.yml@templates + parameters: + vmImage: 'windows-latest' + jdkVersion: '1.8' + options: '-PtestVM=java21Home' + jobName: 'WindowsJava21' + gradleTasks: 'check -x dependencyCheckAggregate' diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/BndConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/BndConvention.java index 3e03adfb6f..8e4b72fd49 100644 --- a/build-logic/src/main/java/org/ehcache/build/conventions/BndConvention.java +++ b/build-logic/src/main/java/org/ehcache/build/conventions/BndConvention.java @@ -11,6 +11,7 @@ import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.ExternalDependency; import org.gradle.api.artifacts.ProjectDependency; +import org.gradle.api.artifacts.ResolutionStrategy; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.provider.MapProperty; import org.gradle.api.publish.PublishingExtension; @@ -46,7 +47,6 @@ public void apply(Project project) { if (baseline instanceof ProjectDependency) { throw new GradleException("Baseline should not be a project dependency"); } else if (baseline instanceof ExternalDependency) { - ((ExternalDependency) baseline).setForce(true); ((ExternalDependency) baseline).setTransitive(false); } else { throw new IllegalArgumentException("Unexpected dependency type: " + baseline); diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/CheckstyleConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/CheckstyleConvention.java index e4e5f0c88d..0973fc1237 100644 --- a/build-logic/src/main/java/org/ehcache/build/conventions/CheckstyleConvention.java +++ b/build-logic/src/main/java/org/ehcache/build/conventions/CheckstyleConvention.java @@ -13,28 +13,10 @@ public void apply(Project project) { project.getPlugins().apply(CheckstylePlugin.class); project.getExtensions().configure(CheckstyleExtension.class, checkstyle -> { - checkstyle.setToolVersion("10.18.1"); checkstyle.setConfigFile(project.getRootProject().file("config/checkstyle.xml")); Map properties = checkstyle.getConfigProperties(); properties.put("projectDir", project.getProjectDir()); properties.put("rootDir", project.getRootDir()); }); - - project.getConfigurations().named("checkstyle", config -> { - config.getResolutionStrategy().dependencySubstitution(subs -> { - subs.substitute(subs.module("org.codehaus.plexus:plexus-utils:3.1.1")) - .using(subs.module("org.codehaus.plexus:plexus-utils:3.3.0")) - .because("Checkstyle 10.18.1 pulls mismatched plexus-utils versions"); - subs.substitute(subs.module("org.apache.commons:commons-lang3:3.7")) - .using(subs.module("org.apache.commons:commons-lang3:3.8.1")) - .because("Checkstyle transitives mix commons-lang3 versions"); - subs.substitute(subs.module("org.apache.httpcomponents:httpcore:4.4.13")) - .using(subs.module("org.apache.httpcomponents:httpcore:4.4.14")) - .because("Align httpcore to latest bugfix release"); - subs.substitute(subs.module("commons-codec:commons-codec:1.11")) - .using(subs.module("commons-codec:commons-codec:1.15")) - .because("Checkstyle transitive dependencies depend on different commons-codec versions"); - }); - }); } } diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/JavaBaseConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/JavaBaseConvention.java index 64dd065fa5..039d3d3c94 100644 --- a/build-logic/src/main/java/org/ehcache/build/conventions/JavaBaseConvention.java +++ b/build-logic/src/main/java/org/ehcache/build/conventions/JavaBaseConvention.java @@ -13,6 +13,7 @@ import org.gradle.external.javadoc.CoreJavadocOptions; import org.gradle.internal.jvm.JavaInfo; import org.gradle.internal.jvm.Jvm; +import org.gradle.jvm.toolchain.JavaLanguageVersion; import org.gradle.process.internal.ExecException; import java.io.ByteArrayOutputStream; @@ -40,8 +41,7 @@ public void apply(Project project) { project.getExtensions().getExtraProperties().set("testJava", testJava); project.getExtensions().configure(JavaPluginExtension.class, java -> { - java.setSourceCompatibility(JavaVersion.VERSION_1_8); - java.setTargetCompatibility(JavaVersion.VERSION_1_8); + java.toolchain(spec -> spec.getLanguageVersion().convention(JavaLanguageVersion.of(8))); }); project.getTasks().withType(Jar.class).configureEach(jar -> { diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/JavaConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/JavaConvention.java index e954d691d7..122f00865f 100644 --- a/build-logic/src/main/java/org/ehcache/build/conventions/JavaConvention.java +++ b/build-logic/src/main/java/org/ehcache/build/conventions/JavaConvention.java @@ -1,9 +1,7 @@ package org.ehcache.build.conventions; -import java.util.Map; import org.gradle.api.Plugin; import org.gradle.api.Project; -import org.gradle.api.artifacts.ModuleDependency; import org.gradle.api.artifacts.dsl.DependencyHandler; import org.gradle.api.plugins.JavaPlugin; @@ -22,29 +20,16 @@ public void apply(Project project) { dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "junit:junit:" + project.property("junitVersion")); dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.assertj:assertj-core:" + project.property("assertjVersion")); - dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "net.bytebuddy:byte-buddy:" + project.property("byteBuddyVersion")); - dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "net.bytebuddy:byte-buddy-agent:" + project.property("byteBuddyVersion")); dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.hamcrest:hamcrest:" + project.property("hamcrestVersion")); dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.mockito:mockito-core:" + project.property("mockitoVersion")); - ModuleDependency md = (ModuleDependency)dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.terracotta:terracotta-utilities-test-tools:" + project.property("terracottaUtilitiesVersion")); - if (md != null) { - md.exclude(Map.of("group", "org.slf4j")); - } + dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.terracotta:terracotta-utilities-test-tools:" + project.property("terracottaUtilitiesVersion")); project.getConfigurations().all(config -> { config.getResolutionStrategy().dependencySubstitution(subs -> { - subs.substitute(subs.module("org.hamcrest:hamcrest-core:1.3")).with(subs.module("org.hamcrest:hamcrest-core:" + project.property("hamcrestVersion"))); - subs.substitute(subs.module("org.hamcrest:hamcrest-library:1.3")).with(subs.module("org.hamcrest:hamcrest-library:" + project.property("hamcrestVersion"))); + subs.substitute(subs.module("org.hamcrest:hamcrest-core:1.3")).using(subs.module("org.hamcrest:hamcrest-core:" + project.property("hamcrestVersion"))); + subs.substitute(subs.module("org.hamcrest:hamcrest-library:1.3")).using(subs.module("org.hamcrest:hamcrest-library:" + project.property("hamcrestVersion"))); subs.substitute(subs.module("junit:junit:4.12")).using(subs.module("junit:junit:4.13.1")); }); - config.getResolutionStrategy().eachDependency(details -> { - String group = details.getRequested().getGroup(); - String name = details.getRequested().getName(); - if ("net.bytebuddy".equals(group) && ("byte-buddy".equals(name) || "byte-buddy-agent".equals(name))) { - details.useVersion(project.property("byteBuddyVersion").toString()); - details.because("Align Byte Buddy family versions across AssertJ and Mockito"); - } - }); }); } } diff --git a/build-logic/src/main/java/org/ehcache/build/conventions/SpotbugsConvention.java b/build-logic/src/main/java/org/ehcache/build/conventions/SpotbugsConvention.java index c48c6093b3..9815385453 100644 --- a/build-logic/src/main/java/org/ehcache/build/conventions/SpotbugsConvention.java +++ b/build-logic/src/main/java/org/ehcache/build/conventions/SpotbugsConvention.java @@ -17,8 +17,8 @@ public void apply(Project project) { SpotBugsExtension spotbugs = project.getExtensions().getByType(SpotBugsExtension.class); spotbugs.getIgnoreFailures().set(false); - spotbugs.getToolVersion().set("4.9.8"); - spotbugs.getOmitVisitors().addAll("FindReturnRef", "ConstructorThrow"); + // Later versions of Spotbugs have stupid heuristics for EI_EXPOSE_REP* + spotbugs.getToolVersion().set("4.2.3"); project.getPlugins().withType(JavaBasePlugin.class).configureEach(plugin -> { @@ -46,12 +46,6 @@ public void apply(Project project) { subs.substitute(subs.module("org.apache.commons:commons-lang3:3.11")) .using(subs.module("org.apache.commons:commons-lang3:3.12.0")) .because("Spotbugs has dependency divergences"); - subs.substitute(subs.module("org.apache.commons:commons-lang3:3.18.0")) - .using(subs.module("org.apache.commons:commons-lang3:3.19.0")) - .because("Spotbugs 4.9.8 has dependency divergences"); - subs.substitute(subs.module("org.apache.logging.log4j:log4j-core:2.25.2")) - .using(subs.module("org.apache.logging.log4j:log4j-core:2.25.3")) - .because("Security vulnerability fix"); }); }); diff --git a/clustered/ehcache-client/build.gradle b/clustered/ehcache-client/build.gradle index 3dc28ca4a6..77dbac4ca6 100644 --- a/clustered/ehcache-client/build.gradle +++ b/clustered/ehcache-client/build.gradle @@ -37,9 +37,7 @@ dependencies { implementation "org.terracotta:lease-api:$terracottaPlatformVersion" implementation "org.terracotta.dynamic-config.entities:dynamic-config-topology-entity-client:$terracottaPlatformVersion" implementation "org.terracotta:connection-api:$terracottaApisVersion" - implementation ("org.terracotta:terracotta-utilities-tools:$terracottaUtilitiesVersion") { - exclude group: 'org.slf4j' - } + implementation "org.terracotta:terracotta-utilities-tools:$terracottaUtilitiesVersion" compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' @@ -62,7 +60,5 @@ dependencies { exclude group:'org.slf4j', module:'slf4j-api' } testImplementation testFixtures(project(':ehcache-xml')) - testImplementation ("org.terracotta:statistics:$parent.statisticVersion") { - exclude group: 'org.slf4j', module: 'slf4j-api' - } + testImplementation ("org.terracotta:statistics:$parent.statisticVersion") } diff --git a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java index bd18840dd5..eaf162c771 100644 --- a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java +++ b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java @@ -377,7 +377,6 @@ public ConnectionState getConnectionState() { return connectionState; } - @SuppressWarnings("removal") private static ExecutorService createAsyncWorker() { SecurityManager s = System.getSecurityManager(); ThreadGroup initialGroup = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); diff --git a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java index 68e5a0453b..2d608c9028 100644 --- a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java +++ b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/CommonServerStoreProxy.java @@ -232,7 +232,6 @@ public Map.Entry next() { } @Override - @SuppressWarnings("deprecation") protected void finalize() throws Throwable { if (!lastBatch) { entity.invokeAndWaitForReceive(new ServerStoreOpMessage.IteratorCloseMessage(iteratorId), false); diff --git a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java index 67bd01bda3..b9c346e6ea 100644 --- a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java +++ b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/DefaultClusteringServiceDestroyTest.java @@ -55,8 +55,6 @@ import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; -import org.mockito.quality.Strictness; - /** * DefaultClusteringServiceDestroyTest */ @@ -196,7 +194,7 @@ public void testDestroyOnPartialDestroyState() throws Exception { private void mockLockForWriteLockSuccess() throws org.terracotta.exception.EntityNotProvidedException, org.terracotta.exception.EntityNotFoundException, org.terracotta.exception.EntityVersionMismatchException { when(connection.getEntityRef(same(VoltronReadWriteLockClient.class), eq(1L), any())).thenReturn(lockEntityRef); - VoltronReadWriteLockClient lockClient = mock(VoltronReadWriteLockClient.class, withSettings().strictness(Strictness.LENIENT)); + VoltronReadWriteLockClient lockClient = mock(VoltronReadWriteLockClient.class, withSettings().lenient()); when(lockEntityRef.fetchEntity(null)).thenReturn(lockClient); when(lockClient.tryLock(LockMessaging.HoldType.WRITE)).thenReturn(true); @@ -205,7 +203,7 @@ private void mockLockForWriteLockSuccess() throws org.terracotta.exception.Entit private void mockLockForReadLockSuccess() throws org.terracotta.exception.EntityNotProvidedException, org.terracotta.exception.EntityNotFoundException, org.terracotta.exception.EntityVersionMismatchException { when(connection.getEntityRef(same(VoltronReadWriteLockClient.class), eq(1L), any())).thenReturn(lockEntityRef); - VoltronReadWriteLockClient lockClient = mock(VoltronReadWriteLockClient.class, withSettings().strictness(Strictness.LENIENT)); + VoltronReadWriteLockClient lockClient = mock(VoltronReadWriteLockClient.class, withSettings().lenient()); when(lockEntityRef.fetchEntity(null)).thenReturn(lockClient); when(lockClient.tryLock(LockMessaging.HoldType.READ)).thenReturn(true); diff --git a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java index b291b4892b..48274dab70 100644 --- a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java +++ b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/StateRepositoryWhitelistingTest.java @@ -166,9 +166,9 @@ public void testWhitelistingForPrimitiveClass() throws Exception { StateHolder testMap = stateRepository.getPersistentStateHolder("testMap", Integer.class, Integer.class, Arrays.asList(Child.class)::contains, null); - testMap.putIfAbsent(Integer.valueOf(10), Integer.valueOf(20)); + testMap.putIfAbsent(new Integer(10), new Integer(20)); - assertThat(testMap.get(Integer.valueOf(10)), is(Integer.valueOf(20))); + assertThat(testMap.get(new Integer(10)), is(new Integer(20))); assertThat(testMap.entrySet(), hasSize(1)); } diff --git a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java index 894ef50bf5..750e53c0b5 100644 --- a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java +++ b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java @@ -231,7 +231,7 @@ public void testGetThrowsOnlySAE() throws Exception { @SuppressWarnings("unchecked") public void testGetTimeout() throws Exception { ServerStoreProxy proxy = mock(ServerStoreProxy.class); - long longKey = HashUtils.intHashToLong(Long.valueOf(1L).hashCode()); + long longKey = HashUtils.intHashToLong(new Long(1L).hashCode()); when(proxy.get(longKey)).thenThrow(TimeoutException.class); ClusteredStore store = new ClusteredStore<>(config,null, null, proxy, null, null, new DefaultStatisticsService()); assertThat(store.get(1L), nullValue()); @@ -630,7 +630,7 @@ public void testSingleChainSingleValue() throws StoreAccessException { @Test public void testSingleChainMultipleValues() throws StoreAccessException { - assertThat(Long.valueOf(1L).hashCode(), is(Long.valueOf(~1L).hashCode())); + assertThat(Long.hashCode(1L), is(Long.hashCode(~1L))); store.put(1L, "foo"); store.put(~1L, "bar"); diff --git a/clustered/ehcache-clustered/build.gradle b/clustered/ehcache-clustered/build.gradle index 565a48ea7c..c1c77ab825 100644 --- a/clustered/ehcache-clustered/build.gradle +++ b/clustered/ehcache-clustered/build.gradle @@ -100,18 +100,8 @@ task copyDocs(type: Sync) { into docsFolder } -configurations { - javadocAdd -} - -dependencies { - javadocAdd project(':clustered:ehcache-common-api') - javadocAdd project(':clustered:ehcache-common') -} - javadoc { exclude '**/core/**', '**/impl/**', '**/xml/**', '**/jsr107/**', '**/transactions/**', '**/management/**', '**/tck/**' - classpath += configurations.javadocAdd } tasks.named('jar') { diff --git a/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java index 1d87fcefd9..e74444ef2e 100644 --- a/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java +++ b/clustered/ehcache-common-api/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java @@ -25,6 +25,7 @@ /** * ValueWrapper */ +@SuppressFBWarnings("EI_EXPOSE_REP") public class ValueWrapper implements Serializable { private static final long serialVersionUID = -4794738044295644587L; diff --git a/clustered/ehcache-common/build.gradle b/clustered/ehcache-common/build.gradle index ca15511653..61a144319d 100644 --- a/clustered/ehcache-common/build.gradle +++ b/clustered/ehcache-common/build.gradle @@ -32,9 +32,7 @@ dependencies { implementation "org.terracotta:entity-common-api:$terracottaApisVersion" implementation "org.terracotta:runnel:$terracottaPlatformVersion" - implementation ("org.terracotta:terracotta-utilities-tools:$terracottaUtilitiesVersion") { - exclude group: 'org.slf4j' - } + implementation "org.terracotta:terracotta-utilities-tools:$terracottaUtilitiesVersion" testImplementation project(':clustered:test-utils') } diff --git a/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java index 56935efde4..362300fb18 100644 --- a/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java +++ b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/Store/WhitelistedUnmarshallingTest.java @@ -62,48 +62,48 @@ private void unmarshallingStateRepoMessagesCheck(T t) { @Test public void unmarshallingIntegerTest() throws Exception { - unmarshallingStateRepoMessagesCheck(Integer.valueOf(10)); + unmarshallingStateRepoMessagesCheck(new Integer(10)); } @Test public void unmarshallingLongTest() throws Exception { - unmarshallingStateRepoMessagesCheck(Long.valueOf(10L)); + unmarshallingStateRepoMessagesCheck(new Long(10)); } @Test public void unmarshallingFloatTest() throws Exception { - unmarshallingStateRepoMessagesCheck(Float.valueOf(10.0f)); + unmarshallingStateRepoMessagesCheck(new Float(10.0)); } @Test public void unmarshallingDoubleTest() throws Exception { - unmarshallingStateRepoMessagesCheck(Double.valueOf(10.0)); + unmarshallingStateRepoMessagesCheck(new Double(10.0)); } @Test public void unmarshallingByteTest() throws Exception { byte b = 101; - unmarshallingStateRepoMessagesCheck(Byte.valueOf(b)); + unmarshallingStateRepoMessagesCheck(new Byte(b)); } @Test public void unmarshallingCharacterTest() throws Exception { - unmarshallingStateRepoMessagesCheck(Character.valueOf('b')); + unmarshallingStateRepoMessagesCheck(new Character('b')); } @Test public void unmarshallingStringTest() throws Exception { - unmarshallingStateRepoMessagesCheck("John"); + unmarshallingStateRepoMessagesCheck(new String("John")); } @Test public void unmarshallingBooleanTest() throws Exception { - unmarshallingStateRepoMessagesCheck(Boolean.TRUE); + unmarshallingStateRepoMessagesCheck(new Boolean(true)); } @Test public void unmarshallingShortTest() throws Exception { - unmarshallingStateRepoMessagesCheck(Short.valueOf((short) 1)); + unmarshallingStateRepoMessagesCheck(new Short((short) 1)); } @Test diff --git a/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java index 3b7a601309..f22474cb4a 100644 --- a/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java +++ b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ChainCodecTest.java @@ -115,7 +115,7 @@ public void testChainEntryWithSingleElement() { StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); ChainCodec.encodeChainEntry(encoder, entry); - Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder(encoder.encode().flip())); + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); assertThat(decoded.getKey(), is(42L)); @@ -132,7 +132,7 @@ public void testChainEntryWithSingleSequencedElement() { StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); ChainCodec.encodeChainEntry(encoder, entry); - Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder(encoder.encode().flip())); + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); assertThat(decoded.getKey(), is(43L)); assertThat(decoded.getValue().isEmpty(), is(false)); @@ -150,7 +150,7 @@ public void testChainEntryWithMultipleElements() { StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); ChainCodec.encodeChainEntry(encoder, entry); - Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder(encoder.encode().flip())); + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); assertThat(decoded.getKey(), is(44L)); assertThat(decoded.getValue().isEmpty(), is(false)); @@ -164,7 +164,7 @@ public void testChainEntryWithMultipleSequencedElements() { StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); ChainCodec.encodeChainEntry(encoder, entry); - Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder(encoder.encode().flip())); + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); assertThat(decoded.getKey(), is(45L)); assertThat(decoded.getValue().isEmpty(), is(false)); @@ -180,7 +180,7 @@ public void testEmptyChainEntry() { StructEncoder encoder = ChainCodec.CHAIN_ENTRY_STRUCT.encoder(); ChainCodec.encodeChainEntry(encoder, entry); - Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder(encoder.encode().flip())); + Map.Entry decoded = ChainCodec.decodeChainEntry(ChainCodec.CHAIN_ENTRY_STRUCT.decoder((ByteBuffer) encoder.encode().flip())); assertThat(decoded.getKey(), is(46L)); assertThat(decoded.getValue().isEmpty(), is(true)); diff --git a/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java index 46105f8b2c..abc8c55e68 100644 --- a/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java +++ b/clustered/ehcache-common/src/test/java/org/ehcache/clustered/common/internal/messages/ResponseCodecTest.java @@ -76,7 +76,7 @@ public void testGetResponseCodec() { @Test public void testMapValueCodec() throws Exception { - Object subject = Integer.valueOf(10); + Object subject = new Integer(10); EhcacheEntityResponse mapValue = mapValue(subject); EhcacheEntityResponse.MapValue decoded = (EhcacheEntityResponse.MapValue) RESPONSE_CODEC.decode(RESPONSE_CODEC.encode(mapValue)); diff --git a/clustered/integration-test/build.gradle b/clustered/integration-test/build.gradle index a17d5c5f6a..3c753ecfcc 100644 --- a/clustered/integration-test/build.gradle +++ b/clustered/integration-test/build.gradle @@ -40,18 +40,11 @@ dependencies { } testImplementation project(':ehcache-management') - testImplementation ("org.terracotta.management:nms-entity-client:$terracottaPlatformVersion") { - exclude group: 'org.slf4j' - } - testImplementation ("org.terracotta.management:nms-agent-entity-client:$terracottaPlatformVersion") { - exclude group: 'org.slf4j' - } - testImplementation ("org.terracotta:terracotta-utilities-port-chooser:$terracottaUtilitiesVersion") { - exclude group: 'org.slf4j' - } + testImplementation "org.terracotta.management:nms-entity-client:$terracottaPlatformVersion" + testImplementation "org.terracotta.management:nms-agent-entity-client:$terracottaPlatformVersion" + testImplementation "org.terracotta:terracotta-utilities-port-chooser:$terracottaUtilitiesVersion" testImplementation("org.terracotta:galvan-platform-support:$terracottaPlatformVersion") { exclude group: 'org.terracotta', module: 'terracotta-utilities-port-chooser' - exclude group: 'org.slf4j' } testImplementation "javax.cache:cache-api:$jcacheVersion" } @@ -84,18 +77,7 @@ configurations.all { dependencySubstitution { substitute(module('junit:junit:4.12')) .because('CVE-2020-15250') - .with(module('junit:junit:4.13.1')) - } - eachDependency { details -> - if (details.requested.group == 'ch.qos.logback' && - (details.requested.name == 'logback-classic' || details.requested.name == 'logback-core')) { - def enforcedLogbackVersion = project.property('logbackVersion').toString() - if (!details.requested.version || details.requested.version < enforcedLogbackVersion) { - details.useVersion enforcedLogbackVersion - details.because 'Force logback >= ' + enforcedLogbackVersion - } - } + .using(module('junit:junit:4.13.1')) } } } - diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java index 7f274206da..dee9b2e18d 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java @@ -173,7 +173,7 @@ public void test_C_client_capabilities_exposed() throws Exception { allDescriptors.addAll(OFFHEAP_DESCRIPTORS); allDescriptors.addAll(CLUSTERED_DESCRIPTORS); - assertThat(allDescriptors).hasSameElementsAs(descriptors); + assertThat(descriptors).hasSameElementsAs(allDescriptors); } @Test @@ -203,9 +203,9 @@ public void test_D_server_capabilities_exposed() throws Exception { // stats - assertThat(new ArrayList(tierCapabilities[3].getDescriptors())).hasSameElementsAs(SERVER_STORE_DESCRIPTORS); - assertThat(new ArrayList(managerCapabilities[2].getDescriptors())).hasSameElementsAs(POOL_DESCRIPTORS); - assertThat(new ArrayList(tierCapabilities[1].getDescriptors())).hasSameElementsAs(POOL_DESCRIPTORS); + assertThat(tierCapabilities[3].getDescriptors()).hasSameElementsAs(SERVER_STORE_DESCRIPTORS); + assertThat(managerCapabilities[2].getDescriptors()).hasSameElementsAs(POOL_DESCRIPTORS); + assertThat(tierCapabilities[1].getDescriptors()).hasSameElementsAs(POOL_DESCRIPTORS); // ClusterTierManagerSettings @@ -271,7 +271,7 @@ public void test_D_server_capabilities_exposed() throws Exception { assertThat(managerCapabilities[0].getDescriptors()).hasSize(3); // time + 2 resources - assertThat(new ArrayList(managerCapabilities[1].getDescriptors())).hasSameElementsAs(OFFHEAP_RES_DESCRIPTORS); + assertThat(managerCapabilities[1].getDescriptors()).hasSameElementsAs(OFFHEAP_RES_DESCRIPTORS); } @Test diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java index d15f71a8af..fc33ca4cf7 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/replication/BasicClusteredCacheOpsReplicationMultiThreadedTest.java @@ -269,16 +269,7 @@ public void testClear() throws Exception { clearFuture.get(); - long deadline = System.currentTimeMillis() + 30_000; - for (Long x : universalSet) { - while (cache2.get(x) != null) { - if (System.currentTimeMillis() > deadline) { - assertThat("Key " + x + " still present in cache2 after 30s wait", cache2.get(x), nullValue()); - break; - } - Thread.sleep(100); - } - } + universalSet.forEach(x -> assertThat(cache2.get(x), nullValue())); } diff --git a/clustered/osgi-test/build.gradle b/clustered/osgi-test/build.gradle index 7cb2222dd3..09db23b537 100644 --- a/clustered/osgi-test/build.gradle +++ b/clustered/osgi-test/build.gradle @@ -36,14 +36,8 @@ dependencies { osgiModule project(':clustered:ehcache-clustered') osgiModule "javax.cache:cache-api:$parent.jcacheVersion" osgiModule "org.slf4j:slf4j-simple:$parent.slf4jVersion" - // SLF4J 2.x requires osgi.serviceloader.processor; Apache Aries SPIFly provides it - osgiModule 'org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle:1.3.7' - osgiModule ("org.terracotta:terracotta-utilities-test-tools:$terracottaUtilitiesVersion") { - exclude group: 'org.slf4j' - } - osgiModule ("org.terracotta:terracotta-utilities-port-chooser:$terracottaUtilitiesVersion") { - exclude group: 'org.slf4j' - } + osgiModule "org.terracotta:terracotta-utilities-test-tools:$terracottaUtilitiesVersion" + osgiModule "org.terracotta:terracotta-utilities-port-chooser:$terracottaUtilitiesVersion" osgiModule 'org.apache.felix:org.apache.felix.scr:2.2.0' osgiModule 'com.sun.activation:javax.activation:1.2.0' osgiModule 'org.osgi:org.osgi.util.promise:1.2.0' @@ -65,11 +59,6 @@ configurations.all { .using(module('org.ops4j.pax.url:pax-url-classpath:2.6.11')) substitute(module('org.ops4j.pax.url:pax-url-link:2.6.8')) .using(module('org.ops4j.pax.url:pax-url-link:2.6.11')) - substitute(module('org.ops4j.pax.url:pax-url-aether:2.6.8')) - .using(module('org.ops4j.pax.url:pax-url-aether:3.0.2')) - substitute(module('org.apache.commons:commons-lang3:3.12.0')) - .using(module('org.apache.commons:commons-lang3:3.18.0')) - .because('CVE-2025-48924') substitute(module('org.osgi:org.osgi.util.function:1.1.0')) .using(module('org.osgi:org.osgi.util.function:1.2.0')) .because('Dependency divergence in org.osgi:org.osgi.util.promise:1.2.0') @@ -110,7 +99,7 @@ test { configurations { lowerBoundOsgiModule { resolutionStrategy.dependencySubstitution { - substitute module('org.glassfish.jaxb:jaxb-runtime') with module('com.sun.xml.bind:jaxb-osgi:2.2.8-b01') + substitute module('org.glassfish.jaxb:jaxb-runtime') using module('com.sun.xml.bind:jaxb-osgi:2.2.8-b01') } } } diff --git a/clustered/server/ehcache-entity/build.gradle b/clustered/server/ehcache-entity/build.gradle index 52349a5e6c..3834655e2d 100644 --- a/clustered/server/ehcache-entity/build.gradle +++ b/clustered/server/ehcache-entity/build.gradle @@ -28,18 +28,12 @@ publishing.publications.withType(MavenPublication) { dependencies { service project(':clustered:server:ehcache-service-api') - service ("org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion") { - exclude group: 'org.slf4j' - } - service ("org.terracotta.management:management-registry:$terracottaPlatformVersion") { - exclude group: 'org.slf4j' - } + service "org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion" + service "org.terracotta.management:management-registry:$terracottaPlatformVersion" api project(':clustered:ehcache-common') implementation "org.terracotta:runnel:$terracottaPlatformVersion" - implementation ("org.terracotta:offheap-store:$offheapVersion") { - exclude group:'org.slf4j' - } + implementation "org.terracotta:offheap-store:$offheapVersion" implementation "org.terracotta:client-message-tracker:$terracottaPlatformVersion" testImplementation project(':clustered:server:ehcache-service') diff --git a/clustered/server/ehcache-service/build.gradle b/clustered/server/ehcache-service/build.gradle index 1710c728b2..a2e1031993 100644 --- a/clustered/server/ehcache-service/build.gradle +++ b/clustered/server/ehcache-service/build.gradle @@ -29,19 +29,12 @@ publishing.publications.withType(MavenPublication) { dependencies { service project(':clustered:server:ehcache-service-api') service "org.terracotta:offheap-resource:$terracottaPlatformVersion" - service ("org.terracotta:statistics:$statisticVersion") { - exclude group: 'org.slf4j', module: 'slf4j-api' - } + service "org.terracotta:statistics:$statisticVersion" implementation project(':clustered:ehcache-common') - implementation ("org.terracotta:offheap-store:$offheapVersion") { - exclude group:'org.slf4j' - } + implementation "org.terracotta:offheap-store:$offheapVersion" testImplementation project(':clustered:test-utils') - testImplementation ("org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion") { - exclude group: 'org.slf4j' - } + testImplementation "org.terracotta.management:monitoring-service-api:$terracottaPlatformVersion" testImplementation "org.terracotta:passthrough-server:$terracottaPassthroughTestingVersion" - testImplementation 'javax.xml.bind:jaxb-api:[2.2,3)' } diff --git a/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java index 6a29355de4..527978652f 100644 --- a/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java +++ b/clustered/server/ehcache-service/src/main/java/org/ehcache/clustered/server/offheap/OffHeapChainStorageEngine.java @@ -215,7 +215,7 @@ public ByteBuffer readBinaryValue(long chain) { detachedContiguousBuffer.reset(); element = storage.readLong(element + ELEMENT_HEADER_NEXT_OFFSET); } while (element != chain); - return detachedContiguousBuffer.flip(); + return (ByteBuffer)detachedContiguousBuffer.flip(); } @Override @@ -700,7 +700,7 @@ private void append(long head, long tail) { } private Element element(ByteBuffer attachedBuffer, final long sequence) { - final ByteBuffer detachedBuffer = ByteBuffer.allocate(attachedBuffer.remaining()).put(attachedBuffer).flip(); + final ByteBuffer detachedBuffer = (ByteBuffer) ByteBuffer.allocate(attachedBuffer.remaining()).put(attachedBuffer).flip(); return new SequencedElement() { diff --git a/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java index 65a615fba9..fe0ceba783 100644 --- a/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java +++ b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapExtensionTest.java @@ -144,7 +144,7 @@ private static ByteBuffer buffer(int i) { while (buffer.hasRemaining()) { buffer.put((byte) i); } - return buffer.flip(); + return (ByteBuffer) buffer.flip(); } private static Matcher element(int i) { diff --git a/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java index c57977037b..32c87c4ccf 100644 --- a/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java +++ b/clustered/server/ehcache-service/src/test/java/org/ehcache/clustered/server/offheap/ChainMapTest.java @@ -504,7 +504,7 @@ private static ByteBuffer buffer(int i) { while (buffer.hasRemaining()) { buffer.put((byte) i); } - return buffer.flip(); + return (ByteBuffer) buffer.flip(); } private static Matcher element(final int i) { diff --git a/config/checkstyle.xml b/config/checkstyle.xml index c73e1aa2da..6a9374d111 100644 --- a/config/checkstyle.xml +++ b/config/checkstyle.xml @@ -1,7 +1,7 @@ + "-//Puppy Crawl//DTD Check Configuration 1.3//EN" + "http://www.puppycrawl.com/dtds/configuration_1_3.dtd"> @@ -22,15 +22,6 @@ - - - - - - - - - @@ -38,7 +29,7 @@ - + diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/SPIStoreTester.java b/core-spi-test/src/main/java/org/ehcache/internal/store/SPIStoreTester.java index 4cc5063f96..1f7697e5b2 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/SPIStoreTester.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/SPIStoreTester.java @@ -18,8 +18,6 @@ package org.ehcache.internal.store; import org.ehcache.core.spi.store.Store; -import org.ehcache.spi.resilience.StoreAccessException; -import org.ehcache.spi.test.LegalSPITesterException; import org.ehcache.spi.test.SPITester; /** @@ -32,39 +30,10 @@ public class SPIStoreTester extends SPITester { - protected static final String SPI_WARNING = "Warning, an exception is thrown due to the SPI test"; - protected final StoreFactory factory; public SPIStoreTester(final StoreFactory factory) { this.factory = factory; } - @FunctionalInterface - protected interface StoreRunnable { - void run() throws StoreAccessException; - } - - protected T expectException(Class expected, StoreRunnable action) - throws LegalSPITesterException { - try { - action.run(); - } catch (Throwable throwable) { - if (expected.isInstance(throwable)) { - return expected.cast(throwable); - } - if (throwable instanceof StoreAccessException) { - throw new LegalSPITesterException(SPI_WARNING, throwable); - } - if (throwable instanceof RuntimeException) { - throw (RuntimeException) throwable; - } - if (throwable instanceof Error) { - throw (Error) throwable; - } - throw new AssertionError("Unexpected checked exception", throwable); - } - throw new AssertionError("Expected " + expected.getSimpleName() + " to be thrown"); - } - } diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreContainsKeyTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreContainsKeyTest.java index a11ed0557a..a8ffcd0881 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreContainsKeyTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreContainsKeyTest.java @@ -73,7 +73,14 @@ public void nullKeyThrowsException() K key = null; - expectException(NullPointerException.class, () -> kvStore.containsKey(key)); + try { + kvStore.containsKey(key); + throw new AssertionError("Expected NullPointerException because the key is null"); + } catch (NullPointerException e) { + // expected + } catch (StoreAccessException e) { + throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); + } } @SPITest diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreGetTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreGetTest.java index 51036b5a3a..a2401b2994 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreGetTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreGetTest.java @@ -115,7 +115,14 @@ public void nullKeyThrowsException() K key = null; - expectException(NullPointerException.class, () -> kvStore.get(key)); + try { + kvStore.get(key); + throw new AssertionError("Expected NullPointerException because the key is null"); + } catch (NullPointerException e) { + // expected + } catch (StoreAccessException e) { + throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); + } } @SPITest diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutIfAbsentTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutIfAbsentTest.java index cfabea7622..0a47012335 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutIfAbsentTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutIfAbsentTest.java @@ -97,24 +97,34 @@ public void doesntMapKeyToValueWhenMappingExists() @SPITest public void nullKeyThrowsException() - throws IllegalAccessException, InstantiationException, LegalSPITesterException { + throws StoreAccessException, IllegalAccessException, InstantiationException { kvStore = factory.newStore(); K key = null; V value = factory.createValue(1); - expectException(NullPointerException.class, () -> kvStore.putIfAbsent(key, value, b -> {})); + try { + kvStore.putIfAbsent(key, value, b -> {}); + throw new AssertionError("Expected NullPointerException because the key is null"); + } catch (NullPointerException e) { + // expected + } } @SPITest public void nullValueThrowsException() - throws IllegalAccessException, InstantiationException, LegalSPITesterException { + throws StoreAccessException, IllegalAccessException, InstantiationException { kvStore = factory.newStore(); K key = factory.createKey(1); V value = null; - expectException(NullPointerException.class, () -> kvStore.putIfAbsent(key, value, b -> {})); + try { + kvStore.putIfAbsent(key, value, b -> {}); + throw new AssertionError("Expected NullPointerException because the value is null"); + } catch (NullPointerException e) { + // expected + } } @SPITest diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutTest.java index b77da2b1fd..772eb6349f 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StorePutTest.java @@ -64,7 +64,14 @@ public void nullKeyThrowsException() K key = null; V value = factory.createValue(1); - expectException(NullPointerException.class, () -> kvStore.put(key, value)); + try { + kvStore.put(key, value); + throw new AssertionError("Expected NullPointerException because the key is null"); + } catch (NullPointerException e) { + // expected + } catch (StoreAccessException e) { + throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); + } } @SPITest @@ -75,7 +82,14 @@ public void nullValueThrowsException() K key = factory.createKey(1); V value = null; - expectException(NullPointerException.class, () -> kvStore.put(key, value)); + try { + kvStore.put(key, value); + throw new AssertionError("Expected NullPointerException because the value is null"); + } catch (NullPointerException e) { + // expected + } catch (StoreAccessException e) { + throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); + } } @SPITest diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyTest.java index cb50228a4a..942de9385b 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyTest.java @@ -89,7 +89,14 @@ public void nullKeyThrowsException() throws IllegalAccessException, InstantiationException, LegalSPITesterException { kvStore = factory.newStore(); - expectException(NullPointerException.class, () -> kvStore.remove(null)); + try { + kvStore.remove(null); + throw new AssertionError("Expected NullPointerException because the key is null"); + } catch (NullPointerException e) { + // expected + } catch (StoreAccessException e) { + throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); + } } @SPITest diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyValueTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyValueTest.java index 158563b266..5958a439c3 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyValueTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreRemoveKeyValueTest.java @@ -164,7 +164,14 @@ public void nullKeyThrowsException() K key = null; V value = factory.createValue(1); - expectException(NullPointerException.class, () -> kvStore.remove(key, value)); + try { + kvStore.remove(key, value); + throw new AssertionError("Expected NullPointerException because the key is null"); + } catch (NullPointerException e) { + // expected + } catch (StoreAccessException e) { + throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); + } } @SPITest @@ -175,7 +182,14 @@ public void nullValueThrowsException() K key = factory.createKey(1); V value = null; - expectException(NullPointerException.class, () -> kvStore.remove(key, value)); + try { + kvStore.remove(key, value); + throw new AssertionError("Expected NullPointerException because the value is null"); + } catch (NullPointerException e) { + // expected + } catch (StoreAccessException e) { + throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); + } } @SPITest diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreReplaceKeyValueTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreReplaceKeyValueTest.java index d47801084a..df62e0b0a7 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreReplaceKeyValueTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreReplaceKeyValueTest.java @@ -117,7 +117,14 @@ public void nullKeyThrowsException() K key = null; V value = factory.createValue(1); - expectException(NullPointerException.class, () -> kvStore.replace(key, value)); + try { + kvStore.replace(key, value); + throw new AssertionError("Expected NullPointerException because the key is null"); + } catch (NullPointerException e) { + // expected + } catch (StoreAccessException e) { + throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); + } } @SPITest @@ -127,7 +134,14 @@ public void nullValueThrowsException() K key = factory.createKey(1); - expectException(NullPointerException.class, () -> kvStore.replace(key, null)); + try { + kvStore.replace(key, null); + throw new AssertionError("Expected NullPointerException because the value is null"); + } catch (NullPointerException e) { + // expected + } catch (StoreAccessException e) { + throw new LegalSPITesterException("Warning, an exception is thrown due to the SPI test"); + } } @SPITest diff --git a/demos/01-CacheAside/config/checkstyle-suppressions.xml b/demos/01-CacheAside/config/checkstyle-suppressions.xml index a6867b21a7..be989c924a 100644 --- a/demos/01-CacheAside/config/checkstyle-suppressions.xml +++ b/demos/01-CacheAside/config/checkstyle-suppressions.xml @@ -1,8 +1,9 @@ + - + \ No newline at end of file diff --git a/demos/build.gradle b/demos/build.gradle index 2c4c8d8d8c..e3b0a1dd95 100644 --- a/demos/build.gradle +++ b/demos/build.gradle @@ -1,6 +1,25 @@ plugins { id 'org.ehcache.build.conventions.java-library' - id 'org.ehcache.build.conventions.war' apply false +} + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +allprojects { + java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } + } + + configurations.configureEach { + resolutionStrategy { + force "org.slf4j:slf4j-api:2.0.17" + } + } } def jettyVersion = '12.1.5' @@ -12,20 +31,20 @@ dependencies { api "org.eclipse.jetty.ee10:jetty-ee10-servlet:${jettyVersion}" } -configurations.configureEach { - resolutionStrategy { - force "org.slf4j:slf4j-api:${project.property('slf4jVersion')}" - } -} - subprojects { apply plugin: 'org.ehcache.build.conventions.war' + java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } + } + dependencies { implementation project(':demos') implementation project(':ehcache-impl') implementation 'jakarta.servlet:jakarta.servlet-api:6.0.0' - runtimeOnly "ch.qos.logback:logback-classic:${project.property('logbackVersion')}" + runtimeOnly "ch.qos.logback:logback-classic:1.5.26" runtimeOnly 'com.h2database:h2:2.4.240' } } diff --git a/demos/src/main/java/org/ehcache/demos/server/EmbeddedPeeperServer.java b/demos/src/main/java/org/ehcache/demos/server/EmbeddedPeeperServer.java index d16ff81c3b..b0039d1480 100644 --- a/demos/src/main/java/org/ehcache/demos/server/EmbeddedPeeperServer.java +++ b/demos/src/main/java/org/ehcache/demos/server/EmbeddedPeeperServer.java @@ -1,6 +1,6 @@ /* * Copyright Terracotta, Inc. - * Copyright IBM Corp. 2024, 2026 + * Copyright IBM Corp. 2024, 2025 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/docs/src/docs/asciidoc/user/examples.adoc b/docs/src/docs/asciidoc/user/examples.adoc index 6de5184a11..81bf6d26e1 100644 --- a/docs/src/docs/asciidoc/user/examples.adoc +++ b/docs/src/docs/asciidoc/user/examples.adoc @@ -39,7 +39,8 @@ from the database to display the Peeper web page. To run this implementation: [source,bash] ---- -./gradlew :demos:00-NoCache:run +cd ehcache3/demos/00-NoCache +../../gradlew appStart ---- This builds the necessary components, starts a http://eclipse.org/jetty/[Jetty] web service, @@ -72,7 +73,8 @@ the cache is cleared. To run this implementation: [source,bash] ---- -./gradlew :demos:01-CacheAside:run +cd ehcache3/demos/01-CacheAside +../../gradlew appStart ---- This builds the necessary components, starts a http://eclipse.org/jetty/[Jetty] web service, diff --git a/ehcache-107/build.gradle b/ehcache-107/build.gradle index acb2572b40..5256668fbb 100644 --- a/ehcache-107/build.gradle +++ b/ehcache-107/build.gradle @@ -46,7 +46,7 @@ configurations { dependencySubstitution { substitute(module('junit:junit:4.11')) .because('CVE-2020-15250') - .with(module('junit:junit:4.13.1')) + .using(module('junit:junit:4.13.1')) } } } @@ -66,9 +66,7 @@ dependencies { commonApi "javax.cache:cache-api:$parent.jcacheVersion" commonImplementation project(':ehcache-impl') - commonImplementation ("org.terracotta:statistics:$statisticVersion") { - exclude group: 'org.slf4j', module: 'slf4j-api' - } + commonImplementation "org.terracotta:statistics:$statisticVersion" implementation project(':ehcache-xml') jakartaImplementation(project(':ehcache-xml')) { @@ -101,14 +99,14 @@ task unpackTckTests(type: Sync) { from { configurations.tckTestClasses.collect {zipTree(it)} } - into sourceSets.tckTest.java.outputDir + into sourceSets.tckTest.java.classesDirectory } task tckTest(type: Test, dependsOn: unpackTckTests) { testClassesDirs = sourceSets.tckTest.output.classesDirs classpath += sourceSets.tckTest.runtimeClasspath - binResultsDir file("$buildDir/tck-tests-results/binary/$name") + binaryResultsDirectory = file("$buildDir/tck-tests-results/binary/$name") reports.junitXml.destination = file("$buildDir/tck-tests-results") reports.html.destination = file("$buildDir/reports/tck-tests") diff --git a/ehcache-107/src/test/java/org/ehcache/ParsesConfigurationExtensionTest.java b/ehcache-107/src/test/java/org/ehcache/ParsesConfigurationExtensionTest.java index 2e94eb5dc7..8284d9a797 100644 --- a/ehcache-107/src/test/java/org/ehcache/ParsesConfigurationExtensionTest.java +++ b/ehcache-107/src/test/java/org/ehcache/ParsesConfigurationExtensionTest.java @@ -53,7 +53,7 @@ public class ParsesConfigurationExtensionTest { @Test - public void testConfigParse() throws SAXException, ReflectiveOperationException, IOException { + public void testConfigParse() throws ClassNotFoundException, SAXException, InstantiationException, IllegalAccessException, IOException { final XmlConfiguration configuration = new XmlConfiguration(this.getClass().getResource("/ehcache-107.xml")); final DefaultJsr107Service jsr107Service = new DefaultJsr107Service(ServiceUtils.findSingletonAmongst(Jsr107Configuration.class, configuration.getServiceCreationConfigurations())); @@ -66,7 +66,7 @@ public void testConfigParse() throws SAXException, ReflectiveOperationException, @SuppressWarnings("rawtypes") @Test - public void testXmlExample() throws SAXException, ReflectiveOperationException, IOException { + public void testXmlExample() throws ClassNotFoundException, SAXException, InstantiationException, IOException, IllegalAccessException { XmlConfiguration config = new XmlConfiguration(ParsesConfigurationExtensionTest.class.getResource("/ehcache-example.xml")); final DefaultJsr107Service jsr107Service = new DefaultJsr107Service(ServiceUtils.findSingletonAmongst(Jsr107Configuration.class, config.getServiceCreationConfigurations())); diff --git a/ehcache-core/build.gradle b/ehcache-core/build.gradle index aa3043b776..e01e68e42b 100644 --- a/ehcache-core/build.gradle +++ b/ehcache-core/build.gradle @@ -29,9 +29,7 @@ publishing.publications.withType(MavenPublication) { dependencies { api project(':ehcache-api') - implementation ("org.terracotta:statistics:$parent.statisticVersion") { - exclude group: 'org.slf4j', module: 'slf4j-api' - } + implementation "org.terracotta:statistics:$parent.statisticVersion" compileOnly 'org.osgi:osgi.core:6.0.0' compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation project(':spi-tester') diff --git a/ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java b/ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java index d33f3b507a..b8fb8a22e4 100644 --- a/ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java +++ b/ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java @@ -30,6 +30,7 @@ import java.util.ServiceLoader; import java.util.function.Supplier; +import static java.security.AccessController.doPrivileged; import static java.util.Collections.enumeration; import static java.util.Collections.list; import static java.util.stream.Collectors.toList; @@ -56,14 +57,14 @@ public static Iterable servicesOfType(Class serviceType) { } } - @SuppressWarnings("removal") + @SuppressWarnings("unchecked") public static ClassLoader delegationChain(Supplier loader, ClassLoader ... loaders) { - return java.security.AccessController.doPrivileged((PrivilegedAction) () -> new ChainedClassLoader(concat(of(loader), of(loaders).map(l -> () -> l)).collect(toList()))); + return doPrivileged((PrivilegedAction) () -> new ChainedClassLoader(concat(of(loader), of(loaders).map(l -> () -> l)).collect(toList()))); } - @SuppressWarnings("removal") + @SuppressWarnings("unchecked") public static ClassLoader delegationChain(ClassLoader ... loaders) { - return java.security.AccessController.doPrivileged((PrivilegedAction) () -> new ChainedClassLoader(of(loaders).>map(l -> () -> l).collect(toList()))); + return doPrivileged((PrivilegedAction) () -> new ChainedClassLoader(of(loaders).>map(l -> () -> l).collect(toList()))); } private static class ChainedClassLoader extends ClassLoader { diff --git a/ehcache-core/src/test/java/org/ehcache/core/EhcacheManagerTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheManagerTest.java index b93a22b331..03d6f93a9b 100644 --- a/ehcache-core/src/test/java/org/ehcache/core/EhcacheManagerTest.java +++ b/ehcache-core/src/test/java/org/ehcache/core/EhcacheManagerTest.java @@ -117,7 +117,7 @@ public void testCanDestroyAndClose() throws Exception { Store store = mock(Store.class); CacheEventDispatcherFactory cacheEventNotificationListenerServiceProvider = mock(CacheEventDispatcherFactory.class); - when(storeProvider.createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(store); + when(storeProvider.createStore(any(Store.Configuration.class), ArgumentMatchers.any())).thenReturn(store); when(store.getConfigurationChangeListeners()).thenReturn(new ArrayList<>()); when(cacheEventNotificationListenerServiceProvider.createCacheEventDispatcher(store)).thenReturn(mock(CacheEventDispatcher.class)); @@ -200,7 +200,7 @@ public void testNoClassLoaderSpecified() { final Collection services = getServices(storeProvider, cenlProvider); when(storeProvider - .createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(mock); + .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); EhcacheManager cacheManager = new EhcacheManager(config, services); cacheManager.init(); assertSame(ClassLoading.getDefaultClassLoader(), cacheManager.getClassLoader()); @@ -240,7 +240,7 @@ public ClassLoader getClassLoader() { final Collection services = getServices(storeProvider, cenlProvider); when(storeProvider - .createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(mock); + .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); EhcacheManager cacheManager = new EhcacheManager(config, services); cacheManager.init(); assertSame(cl1, cacheManager.getClassLoader()); @@ -274,7 +274,7 @@ public void testThrowsWhenAddingExistingCache() { final Collection services = getServices(storeProvider, cenlProvider); when(storeProvider - .createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(mock); + .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); Map> caches = newCacheMap(); caches.put("bar", cacheConfiguration); @@ -303,7 +303,7 @@ public void testThrowsWhenNotInitialized() { final Collection services = getServices(storeProvider, cenlProvider); when(storeProvider - .createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(mock); + .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); final CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Integer.class, String.class); Map> caches = newCacheMap(); @@ -341,7 +341,7 @@ public void testThrowsWhenRetrievingCacheWithWrongTypes() { final Collection services = getServices(storeProvider, cenlProvider); when(storeProvider - .createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(mock); + .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); final CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Integer.class, String.class); Map> caches = newCacheMap(); @@ -406,7 +406,7 @@ public void testLifeCyclesCacheLoaders() throws Exception { when(cenlProvider.createCacheEventDispatcher(mock)).thenReturn(cenlServiceMock); Collection services = getServices(cacheLoaderWriterProvider, decoratorLoaderWriterProvider, storeProvider, cenlProvider); when(storeProvider - .createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(mock); + .createStore(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(mock); EhcacheManager manager = new EhcacheManager(cfg, services); manager.init(); @@ -494,7 +494,8 @@ InternalCache createNewEhcache(final String alias, final CacheConfi final InternalCache ehcache = super.createNewEhcache(alias, config, keyType, valueType); caches.add(alias); if(caches.size() == 1) { - when(storeProvider.createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))) + when(storeProvider.createStore( + ArgumentMatchers.>any(), ArgumentMatchers.>any())) .thenThrow(thrown); } return ehcache; @@ -668,7 +669,7 @@ public void testChangesToManagerAreReflectedInConfig() { Store store = mock(Store.class); CacheEventDispatcherFactory cacheEventNotificationListenerServiceProvider = mock(CacheEventDispatcherFactory.class); - when(storeProvider.createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(store); + when(storeProvider.createStore(any(Store.Configuration.class), ArgumentMatchers.any())).thenReturn(store); when(store.getConfigurationChangeListeners()).thenReturn(new ArrayList<>()); when(cacheEventNotificationListenerServiceProvider.createCacheEventDispatcher(store)).thenReturn(mock(CacheEventDispatcher.class)); @@ -715,7 +716,7 @@ public void testCachesAddedAtRuntimeGetReInited() { Store store = mock(Store.class); CacheEventDispatcherFactory cacheEventNotificationListenerServiceProvider = mock(CacheEventDispatcherFactory.class); - when(storeProvider.createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class))).thenReturn(store); + when(storeProvider.createStore(any(Store.Configuration.class), ArgumentMatchers.any())).thenReturn(store); when(store.getConfigurationChangeListeners()).thenReturn(new ArrayList<>()); when(cacheEventNotificationListenerServiceProvider.createCacheEventDispatcher(store)).thenReturn(mock(CacheEventDispatcher.class)); @@ -753,7 +754,7 @@ public void testCachesAddedAtRuntimeGetReInited() { public void testCloseWhenRuntimeCacheCreationFails() throws Exception { Store.Provider storeProvider = mock(Store.Provider.class); when(storeProvider.rank(any(Set.class), any(Collection.class))).thenReturn(1); - doThrow(new Error("Test EhcacheManager close.")).when(storeProvider).createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class)); + doThrow(new Error("Test EhcacheManager close.")).when(storeProvider).createStore(any(Store.Configuration.class), ArgumentMatchers.any()); Map> caches = newCacheMap(); DefaultConfiguration config = new DefaultConfiguration(caches, null); @@ -787,7 +788,7 @@ public void testCloseWhenRuntimeCacheCreationFails() throws Exception { public void testCloseWhenCacheCreationFailsDuringInitialization() throws Exception { Store.Provider storeProvider = mock(Store.Provider.class); when(storeProvider.rank(any(Set.class), any(Collection.class))).thenReturn(1); - doThrow(new Error("Test EhcacheManager close.")).when(storeProvider).createStore(any(Store.Configuration.class), any(ServiceConfiguration[].class)); + doThrow(new Error("Test EhcacheManager close.")).when(storeProvider).createStore(any(Store.Configuration.class), ArgumentMatchers.any()); CacheConfiguration cacheConfiguration = new TestCacheConfig<>(Long.class, String.class); Map> caches = newCacheMap(); diff --git a/ehcache-core/src/test/java/org/ehcache/core/PrefixLoggerTest.java b/ehcache-core/src/test/java/org/ehcache/core/PrefixLoggerTest.java index e3bf02c659..2ee8abd459 100644 --- a/ehcache-core/src/test/java/org/ehcache/core/PrefixLoggerTest.java +++ b/ehcache-core/src/test/java/org/ehcache/core/PrefixLoggerTest.java @@ -20,11 +20,9 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.Marker; -import org.slf4j.spi.LoggingEventBuilder; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.util.Arrays; import static org.mockito.Mockito.*; @@ -90,9 +88,7 @@ public void testAllMethodsDelegationWithEnrichment() throws InvocationTargetExce PrefixLogger prefixLogger = new PrefixLogger(mockLogger, prefix); for (Method prefixLogMethod : Logger.class.getDeclaredMethods()) { - if ((prefixLogMethod.getModifiers() & Modifier.PUBLIC) != 0 && - !prefixLogMethod.getReturnType().equals(LoggingEventBuilder.class) && - !prefixLogMethod.getReturnType().equals(boolean.class)) { + Class[] parameterTypes = prefixLogMethod.getParameterTypes(); Object[] parameters = new Object[parameterTypes.length]; for (int j = 0; j < parameterTypes.length; j++) { @@ -105,9 +101,9 @@ public void testAllMethodsDelegationWithEnrichment() throws InvocationTargetExce } } - prefixLogMethod.invoke(prefixLogger, parameters); - prefixLogMethod.invoke(verify(mockLogger, times(1)), enrichStringParamValues(parameters, isMsgParameter(prefixLogMethod))); - } + prefixLogMethod.invoke(prefixLogger, parameters); + prefixLogMethod.invoke(verify(mockLogger, times(1)), enrichStringParamValues(parameters, isMsgParameter(prefixLogMethod))); + } } diff --git a/ehcache-impl/build.gradle b/ehcache-impl/build.gradle index a1a37ae4ea..10a7b95a5f 100644 --- a/ehcache-impl/build.gradle +++ b/ehcache-impl/build.gradle @@ -43,7 +43,7 @@ task slowTest(type: Test) { testClassesDirs = sourceSets.slowTest.output.classesDirs classpath += sourceSets.slowTest.runtimeClasspath - binResultsDir file("$buildDir/slow-tests-results/binary/$name") + binaryResultsDirectory = file("$buildDir/slow-tests-results/binary/$name") reports.junitXml.destination = file("$buildDir/slow-tests-results") reports.html.destination = file("$buildDir/reports/slow-tests") } @@ -51,23 +51,15 @@ task slowTest(type: Test) { dependencies { api project(':ehcache-core') - implementation (group: 'org.terracotta', name: 'offheap-store', version: parent.offheapVersion) { - exclude group:'org.slf4j' - } - implementation (group: 'org.ehcache', name: 'sizeof', version: parent.sizeofVersion) { - exclude group: 'org.slf4j' - } - implementation (group: 'org.terracotta', name: 'terracotta-utilities-tools', version: parent.terracottaUtilitiesVersion) { - exclude group: 'org.slf4j' - } + implementation group: 'org.terracotta', name: 'offheap-store', version: parent.offheapVersion + implementation group: 'org.ehcache', name: 'sizeof', version: parent.sizeofVersion + implementation group: 'org.terracotta', name: 'terracotta-utilities-tools', version: parent.terracottaUtilitiesVersion compileOnly 'org.osgi:org.osgi.service.component.annotations:1.3.0' testImplementation testFixtures(project(':ehcache-core')) testImplementation project(':core-spi-test') testImplementation 'org.ow2.asm:asm:6.2' testImplementation 'org.ow2.asm:asm-commons:6.2' - testImplementation ("org.terracotta:statistics:$parent.statisticVersion") { - exclude group: 'org.slf4j', module: 'slf4j-api' - } + testImplementation ("org.terracotta:statistics:$parent.statisticVersion") } jar { @@ -80,6 +72,8 @@ jar { } compileUnsafe { + javaCompiler = javaToolchains.compilerFor(java.toolchain) + //no -Werror due to unsafe options.compilerArgs = ['-Xlint:all'] } diff --git a/ehcache-impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java index 5ceb07101b..ce20ee2ced 100644 --- a/ehcache-impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java +++ b/ehcache-impl/src/main/java/org/ehcache/config/builders/UserManagedCacheBuilder.java @@ -121,7 +121,7 @@ public class UserManagedCacheBuilder> imp private boolean useValueSerializingCopier; private Serializer keySerializer; private Serializer valueSerializer; - private volatile int dispatcherConcurrency = 4; + private int dispatcherConcurrency = 4; private List> eventListenerConfigurations = new ArrayList<>(); private ExecutorService unOrderedExecutor; private ExecutorService orderedExecutor; diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MemberUtils.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MemberUtils.java index f2d2e1b4d5..0849b9d234 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MemberUtils.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/internal/classes/commonslang/reflect/MemberUtils.java @@ -58,7 +58,6 @@ abstract class MemberUtils { * @param o the AccessibleObject to set as accessible * @return a boolean indicating whether the accessibility of the object was set to true. */ - @SuppressWarnings("deprecation") static boolean setAccessibleWorkaround(final AccessibleObject o) { if (o == null || o.isAccessible()) { return false; diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java index ddc472fa38..5f503ca55d 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java @@ -16,7 +16,6 @@ */ package org.ehcache.impl.internal.store.tiering; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.ehcache.Cache; import org.ehcache.config.ResourcePools; import org.ehcache.config.ResourceType; @@ -222,9 +221,8 @@ private void swapCachingTiers() { } } - @SuppressFBWarnings("NN_NAKED_NOTIFY") private void swapBackCachingTiers() { - if (!cachingTierRef.compareAndSet(noopCachingTier, realCachingTier)) { + if(!cachingTierRef.compareAndSet(noopCachingTier, realCachingTier)) { throw new AssertionError("Something bad happened"); } synchronized (noopCachingTier) { diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java b/ehcache-impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java index d90c7e4851..ca831aeff3 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/persistence/FileUtils.java @@ -110,6 +110,7 @@ static boolean tryRecursiveDelete(File file) { } } + @SuppressFBWarnings("DM_GC") private static void gc() { System.gc(); System.runFinalization(); diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java index 51176dcdec..54d60a9e3a 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/serialization/PlainJavaSerializer.java @@ -107,7 +107,7 @@ protected Class resolveProxyClass(String[] interfaces) throws ClassNotFoundEx interfaceClasses[i] = Class.forName(interfaces[i], false, classLoader); } - return Proxy.newProxyInstance(classLoader, interfaceClasses, (proxy, method, args) -> null).getClass(); + return Proxy.getProxyClass(classLoader, interfaceClasses); } private static final Map> primitiveClasses = new HashMap<>(); diff --git a/ehcache-impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java b/ehcache-impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java index 607d997e06..3402a4a863 100644 --- a/ehcache-impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/config/builders/CacheConfigurationBuilderTest.java @@ -391,10 +391,8 @@ public void testIncompatibleServiceRemovesExistingConfiguration() { CacheConfigurationBuilder newBuilder = oldBuilder.withService(newConfig); - assertThat(oldBuilder.build().getServiceConfigurations(), hasItem(sameInstance(oldConfig))); - assertThat(oldBuilder.build().getServiceConfigurations(), not(hasItem(sameInstance(newConfig)))); - assertThat(newBuilder.build().getServiceConfigurations(), hasItem(sameInstance(newConfig))); - assertThat(newBuilder.build().getServiceConfigurations(), not(hasItem(sameInstance(oldConfig)))); + assertThat(oldBuilder.build().getServiceConfigurations(), both(hasItem(sameInstance(oldConfig))).and(not(hasItem(sameInstance(newConfig))))); + assertThat(newBuilder.build().getServiceConfigurations(), both(hasItem(sameInstance(newConfig))).and(not(hasItem(sameInstance(oldConfig))))); } @Test @@ -402,14 +400,12 @@ public void testCompatibleServiceJoinsExistingConfiguration() { ServiceConfiguration oldConfig = new CompatibleServiceConfig(); ServiceConfiguration newConfig = new CompatibleServiceConfig(); - CacheConfigurationBuilder oldBuilder = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(oldConfig); + CacheConfigurationBuilder oldBuilder = newCacheConfigurationBuilder(Object.class, Object.class, heap(10)).withService(oldConfig); - CacheConfigurationBuilder newBuilder = oldBuilder.withService(newConfig); + CacheConfigurationBuilder newBuilder = oldBuilder.withService(newConfig); - assertThat(oldBuilder.build().getServiceConfigurations(), hasItem(sameInstance(oldConfig))); - assertThat(oldBuilder.build().getServiceConfigurations(), not(hasItem(sameInstance(newConfig)))); - assertThat(newBuilder.build().getServiceConfigurations(), hasItem(sameInstance(oldConfig))); - assertThat(newBuilder.build().getServiceConfigurations(), hasItem(sameInstance(newConfig))); + assertThat(oldBuilder.build().getServiceConfigurations(), both(hasItem(sameInstance(oldConfig))).and(not(hasItem(sameInstance(newConfig))))); + assertThat(newBuilder.build().getServiceConfigurations(), both(hasItem(sameInstance(oldConfig))).and(hasItem(sameInstance(newConfig)))); } @Test diff --git a/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java b/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java index bcfaaff5d7..6b38682668 100644 --- a/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java +++ b/ehcache-impl/src/test/java/org/ehcache/docs/ConfigurationDerivation.java @@ -207,7 +207,7 @@ public OptimizedDateSerializer(ClassLoader classLoader) {} @Override public ByteBuffer serialize(Date object) throws SerializerException { ByteBuffer buffer = ByteBuffer.allocate(8); - return buffer.putLong(object.getTime()).flip(); + return (ByteBuffer) buffer.putLong(object.getTime()).flip(); } @Override diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java index 9afa8d8a14..9dcad09ee4 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/tiering/TieredStoreTest.java @@ -34,7 +34,6 @@ import org.ehcache.impl.internal.store.heap.OnHeapStore; import org.ehcache.impl.internal.store.offheap.OffHeapStore; import org.ehcache.spi.service.Service; -import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.spi.service.ServiceProvider; import org.hamcrest.Matchers; import org.junit.Test; @@ -868,15 +867,15 @@ public void testReleaseStoreFlushes() throws Exception { OnHeapStore.Provider onHeapStoreProvider = mock(OnHeapStore.Provider.class); Set> cachingResources = Collections.>singleton( ResourceType.Core.HEAP); when(onHeapStoreProvider.rankCachingTier(eq(cachingResources), any(Collection.class))).thenReturn(1); - when(onHeapStoreProvider.createCachingTier(any(Set.class), any(Store.Configuration.class), - any(ServiceConfiguration[].class))) + when(onHeapStoreProvider.createCachingTier(eq(cachingResources), any(Store.Configuration.class), + ArgumentMatchers.any())) .thenReturn(stringCachingTier); OffHeapStore.Provider offHeapStoreProvider = mock(OffHeapStore.Provider.class); Set> authorityResources = Collections.>singleton( ResourceType.Core.OFFHEAP); when(offHeapStoreProvider.rankAuthority(eq(authorityResources), any(Collection.class))).thenReturn(1); - when(offHeapStoreProvider.createAuthoritativeTier(any(Set.class), - any(Store.Configuration.class), any(ServiceConfiguration[].class))) + when(offHeapStoreProvider.createAuthoritativeTier(eq(authorityResources), + any(Store.Configuration.class), ArgumentMatchers.any())) .thenReturn(stringAuthoritativeTier); Store.Configuration configuration = mock(Store.Configuration.class); diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java index 488513668e..31612486f1 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedFieldTest.java @@ -47,7 +47,7 @@ public void addingSerializableField() throws Exception { serializer.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(A_write.class, IncompatibleSerializable_write.class, Serializable_write.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(A_write.class)).getDeclaredConstructor().newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(A_write.class)).newInstance(); ByteBuffer encodedA = serializer.serialize(a); pushTccl(createClassNameRewritingLoader(A_read.class, IncompatibleSerializable_read.class)); @@ -65,7 +65,7 @@ public void addingExternalizableField() throws Exception { serializer.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(B_write.class, Externalizable_write.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(B_write.class)).getDeclaredConstructor().newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(B_write.class)).newInstance(); ByteBuffer encodedA = serializer.serialize(a); pushTccl(createClassNameRewritingLoader(B_read.class)); diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedSuperClassTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedSuperClassTest.java index ca4d245ddb..6e897bab53 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedSuperClassTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/AddedSuperClassTest.java @@ -41,7 +41,7 @@ public void testAddedSuperClass() throws Exception { serializer.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(A_2.class, AddedSuperClass_Hidden.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(A_2.class)).getDeclaredConstructor().newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(A_2.class)).newInstance(); ByteBuffer encodedA = serializer.serialize(a); pushTccl(createClassNameRewritingLoader(A_1.class)); @@ -58,7 +58,7 @@ public void testAddedSuperClassNotHidden() throws Exception { serializer.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(A_2.class, AddedSuperClass_Hidden.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(A_2.class)).getDeclaredConstructor().newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(A_2.class)).newInstance(); ByteBuffer encodedA = serializer.serialize(a); pushTccl(createClassNameRewritingLoader(A_1.class, AddedSuperClass_Hidden.class)); diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassLoaderTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassLoaderTest.java index c01a28e532..a7d9bb25bd 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassLoaderTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassLoaderTest.java @@ -42,7 +42,7 @@ public void testThreadContextLoader() throws Exception { serializer.init(new TransientStateRepository()); ClassLoader loader = newLoader(); - ByteBuffer encoded = serializer.serialize((Serializable) loader.loadClass(Foo.class.getName()).getDeclaredConstructor().newInstance()); + ByteBuffer encoded = serializer.serialize((Serializable) loader.loadClass(Foo.class.getName()).newInstance()); pushTccl(loader); try { @@ -58,7 +58,7 @@ public void testExplicitLoader() throws Exception { StatefulSerializer serializer = new CompactJavaSerializer<>(loader); serializer.init(new TransientStateRepository()); - ByteBuffer encoded = serializer.serialize((Serializable) loader.loadClass(Foo.class.getName()).getDeclaredConstructor().newInstance()); + ByteBuffer encoded = serializer.serialize((Serializable) loader.loadClass(Foo.class.getName()).newInstance()); // setting TCCL doesn't matter here, but set it to make sure it doesn't get used pushTccl(newLoader()); diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassUnloadingTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassUnloadingTest.java index 15aab1730d..b115b68eb7 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassUnloadingTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/CompactJavaSerializerClassUnloadingTest.java @@ -49,7 +49,7 @@ public void createSpecialObject() throws Exception { Class special = (Class) duplicate.loadClass(SpecialClass.class.getName()); classRef = new WeakReference<>(special); - specialObject = special.getDeclaredConstructor().newInstance(); + specialObject = special.newInstance(); } @Test diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/GetFieldTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/GetFieldTest.java index 151ee159ce..ccb69e6f9f 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/GetFieldTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/GetFieldTest.java @@ -44,7 +44,7 @@ public void testGetField() throws Exception { s.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(Foo_A.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(Foo_A.class)).getDeclaredConstructor().newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(Foo_A.class)).newInstance(); ByteBuffer encodedA = s.serialize(a); pushTccl(createClassNameRewritingLoader(Foo_B.class)); diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java index b68c09215a..ec1774fe36 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/JavaSerializer.java @@ -108,7 +108,6 @@ protected Class resolveClass(ObjectStreamClass desc) throws IOException, Clas } @Override - @SuppressWarnings("deprecation") protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException { Class[] interfaceClasses = new Class[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/PutFieldTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/PutFieldTest.java index 5122085349..bc2da6c360 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/PutFieldTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/PutFieldTest.java @@ -45,7 +45,7 @@ public void testWithAllPrimitivesAndString() throws Exception { s.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(Foo_A.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(Foo_A.class)).getDeclaredConstructor().newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(Foo_A.class)).newInstance(); ByteBuffer encodedA = s.serialize(a); pushTccl(Foo.class.getClassLoader()); @@ -72,7 +72,7 @@ public void testWithTwoStrings() throws Exception { s.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(Bar_A.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(Bar_A.class)).getDeclaredConstructor().newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(Bar_A.class)).newInstance(); ByteBuffer encodedA = s.serialize(a); pushTccl(Bar.class.getClassLoader()); diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/ReadObjectNoDataTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/ReadObjectNoDataTest.java index 5a30f20906..7c9bc2ca01 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/ReadObjectNoDataTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/ReadObjectNoDataTest.java @@ -44,7 +44,7 @@ public void test() throws Exception { ClassLoader loaderW = createClassNameRewritingLoader(C_W.class, B_W.class); - ByteBuffer b = s.serialize((Serializable) loaderW.loadClass(newClassName(C_W.class)).getDeclaredConstructor().newInstance()); + ByteBuffer b = s.serialize((Serializable) loaderW.loadClass(newClassName(C_W.class)).newInstance()); pushTccl(createClassNameRewritingLoader(C_R.class, B_R.class, A_R.class)); try { diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java index 795c8ed217..80246ae1a7 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/serialization/SerializeAfterEvolutionTest.java @@ -41,7 +41,7 @@ public void test() throws Exception { s.init(new TransientStateRepository()); ClassLoader loaderA = createClassNameRewritingLoader(A_old.class); - Serializable a = (Serializable) loaderA.loadClass(newClassName(A_old.class)).getDeclaredConstructor().newInstance(); + Serializable a = (Serializable) loaderA.loadClass(newClassName(A_old.class)).newInstance(); ByteBuffer encodedA = s.serialize(a); ClassLoader loaderB = createClassNameRewritingLoader(A_new.class); @@ -50,7 +50,7 @@ public void test() throws Exception { Serializable outA = s.read(encodedA); assertThat((Integer) outA.getClass().getField("integer").get(outA), is(42)); - Serializable b = (Serializable) loaderB.loadClass(newClassName(A_new.class)).getDeclaredConstructor().newInstance(); + Serializable b = (Serializable) loaderB.loadClass(newClassName(A_new.class)).newInstance(); Serializable outB = s.read(s.serialize(b)); assertThat((Integer) outB.getClass().getField("integer").get(outB), is(42)); } finally { diff --git a/ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java b/ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java index f1a16121e2..97ad217521 100644 --- a/ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java +++ b/ehcache-impl/src/unsafe/java/org/ehcache/impl/internal/concurrent/ConcurrentHashMap.java @@ -2583,6 +2583,7 @@ else if (f instanceof TreeBin) { * A padded cell for distributing counts. Adapted from LongAdder * and Striped64. See their internal docs for explanation. */ + @sun.misc.Contended static final class CounterCell { volatile long value; CounterCell(long x) { value = x; } diff --git a/ehcache-management/build.gradle b/ehcache-management/build.gradle index 7dcc0fb3df..055ec39134 100644 --- a/ehcache-management/build.gradle +++ b/ehcache-management/build.gradle @@ -29,9 +29,7 @@ publishing.publications.withType(MavenPublication) { dependencies { api project(':ehcache-core') implementation project(':ehcache-impl') - implementation ("org.terracotta:statistics:$statisticVersion") { - exclude group: 'org.slf4j' - } + implementation "org.terracotta:statistics:$statisticVersion" // optional: if we want xml config compileOnlyApi project(':ehcache-xml:ehcache-xml-spi') @@ -42,12 +40,9 @@ dependencies { compileOnlyApi ("org.terracotta.management:nms-agent-entity-client:$terracottaPlatformVersion") { // This is to avoid stats lib being directly used. exclude group:'org.terracotta', module:'statistics' - exclude group: 'org.slf4j' } - testImplementation ("org.terracotta.management:management-registry:$terracottaPlatformVersion") { - exclude group: 'org.slf4j' - } + testImplementation "org.terracotta.management:management-registry:$terracottaPlatformVersion" testImplementation project(':ehcache-xml') testImplementation "org.terracotta.common:common-json-support:$terracottaPlatformVersion" testImplementation testFixtures(project(':ehcache-xml')) diff --git a/ehcache-management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java b/ehcache-management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java index 6f4b5b774f..2b4f6ebd95 100644 --- a/ehcache-management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java +++ b/ehcache-management/src/test/java/org/ehcache/management/registry/DefaultManagementRegistryServiceTest.java @@ -120,7 +120,7 @@ public void descriptorOnHeapTest() { allDescriptors.addAll(ONHEAP_DESCRIPTORS); allDescriptors.addAll(CACHE_DESCRIPTORS); - assertThat(allDescriptors).hasSameElementsAs(descriptors); + assertThat(descriptors).hasSameElementsAs(allDescriptors); } } @@ -150,7 +150,7 @@ public void descriptorOnHeapTest_withoutStats() { allDescriptors.addAll(ONHEAP_NO_STATS_DESCRIPTORS); allDescriptors.addAll(CACHE_DESCRIPTORS); - assertThat(allDescriptors).hasSameElementsAs(descriptors); + assertThat(descriptors).hasSameElementsAs(allDescriptors); } } @@ -181,7 +181,7 @@ public void descriptorOffHeapTest() { allDescriptors.addAll(OFFHEAP_DESCRIPTORS); allDescriptors.addAll(CACHE_DESCRIPTORS); - assertThat(allDescriptors).hasSameElementsAs(descriptors); + assertThat(descriptors).hasSameElementsAs(allDescriptors); } } @@ -215,7 +215,7 @@ public void descriptorDiskStoreTest() throws Exception { allDescriptors.addAll(DISK_DESCRIPTORS); allDescriptors.addAll(CACHE_DESCRIPTORS); - assertThat(allDescriptors).hasSameElementsAs(descriptors); + assertThat(descriptors).hasSameElementsAs(allDescriptors); } } diff --git a/ehcache-transactions/build.gradle b/ehcache-transactions/build.gradle index 0944478484..152c25f0a8 100644 --- a/ehcache-transactions/build.gradle +++ b/ehcache-transactions/build.gradle @@ -119,9 +119,7 @@ dependencies { jakartaTestRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" jakartaTestImplementation "junit:junit:$junitVersion" jakartaTestImplementation "org.hamcrest:hamcrest-library:$hamcrestVersion" - jakartaTestImplementation ("org.terracotta:terracotta-utilities-test-tools:$terracottaUtilitiesVersion") { - exclude group: 'org.slf4j' - } + jakartaTestImplementation "org.terracotta:terracotta-utilities-test-tools:$terracottaUtilitiesVersion" } configurations { diff --git a/ehcache-transactions/src/common/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java b/ehcache-transactions/src/common/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java index 2da9e8c9f0..44b9cbac75 100644 --- a/ehcache-transactions/src/common/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java +++ b/ehcache-transactions/src/common/java/org/ehcache/transactions/xa/internal/SoftLockSerializer.java @@ -111,7 +111,6 @@ protected Class resolveClass(ObjectStreamClass desc) throws ClassNotFoundExce } @Override - @SuppressWarnings("deprecation") protected Class resolveProxyClass(String[] interfaces) throws ClassNotFoundException { Class[] interfaceClasses = new Class[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { diff --git a/ehcache-transactions/src/jakarta/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java b/ehcache-transactions/src/jakarta/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java index 290bca898e..97f78f02f9 100644 --- a/ehcache-transactions/src/jakarta/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java +++ b/ehcache-transactions/src/jakarta/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java @@ -55,8 +55,8 @@ public LookupTransactionManagerProvider(LookupTransactionManagerProviderConfigur throw new NullPointerException("LookupTransactionManagerProviderConfiguration cannot be null"); } try { - lookup = config.getTransactionManagerLookup().getDeclaredConstructor().newInstance(); - } catch (ReflectiveOperationException e) { + lookup = config.getTransactionManagerLookup().newInstance(); + } catch (InstantiationException | IllegalAccessException e) { throw new IllegalArgumentException("Could not instantiate lookup class", e); } } diff --git a/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java index 4f86374ad3..b8ea5a2764 100644 --- a/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java +++ b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/txmgr/provider/LookupTransactionManagerProvider.java @@ -56,8 +56,8 @@ public LookupTransactionManagerProvider(LookupTransactionManagerProviderConfigur throw new NullPointerException("LookupTransactionManagerProviderConfiguration cannot be null"); } try { - lookup = config.getTransactionManagerLookup().getDeclaredConstructor().newInstance(); - } catch (ReflectiveOperationException e) { + lookup = config.getTransactionManagerLookup().newInstance(); + } catch (InstantiationException | IllegalAccessException e) { throw new IllegalArgumentException("Could not instantiate lookup class", e); } } diff --git a/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java index c335c6cd0c..dab8615e97 100644 --- a/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java +++ b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/utils/JavaSerializer.java @@ -108,7 +108,6 @@ protected Class resolveClass(ObjectStreamClass desc) throws IOException, Clas } @Override - @SuppressWarnings("deprecation") protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException { Class[] interfaceClasses = new Class[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { diff --git a/ehcache-xml/ehcache-xml-spi/src/main/java/org/ehcache/xml/ParsingUtil.java b/ehcache-xml/ehcache-xml-spi/src/main/java/org/ehcache/xml/ParsingUtil.java index 6f0315b7db..073f74d274 100644 --- a/ehcache-xml/ehcache-xml-spi/src/main/java/org/ehcache/xml/ParsingUtil.java +++ b/ehcache-xml/ehcache-xml-spi/src/main/java/org/ehcache/xml/ParsingUtil.java @@ -20,9 +20,12 @@ import org.ehcache.javadoc.PublicApi; import java.math.BigInteger; +import java.security.PrivilegedAction; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static java.security.AccessController.doPrivileged; + @PublicApi public class ParsingUtil { @@ -33,7 +36,7 @@ public static String parsePropertyOrString(String s) { Matcher matcher = PADDED_SYSPROP.matcher(s); if (matcher.matches()) { String property = matcher.group("property"); - String value = System.getProperty(property); + String value = doPrivileged((PrivilegedAction) () -> System.getProperty(property)); if (value == null) { throw new IllegalStateException(String.format("Replacement for ${%s} not found!", property)); } else { @@ -71,7 +74,7 @@ public static String parseStringWithProperties(String s) { StringBuffer sb = new StringBuffer(); while (matcher.find()) { final String property = matcher.group("property"); - final String value = System.getProperty(property); + final String value = doPrivileged((PrivilegedAction) () -> System.getProperty(property)); if (value == null) { throw new IllegalStateException(String.format("Replacement for ${%s} not found!", property)); } diff --git a/ehcache-xml/src/jakarta/java/org/ehcache/xml/ConfigurationParser.java b/ehcache-xml/src/jakarta/java/org/ehcache/xml/ConfigurationParser.java index afcbc410c9..3b19d87feb 100644 --- a/ehcache-xml/src/jakarta/java/org/ehcache/xml/ConfigurationParser.java +++ b/ehcache-xml/src/jakarta/java/org/ehcache/xml/ConfigurationParser.java @@ -150,7 +150,7 @@ private static Stream stream(Iterable iterable) { CacheConfigurationBuilder parseServiceConfigurations(Document document, CacheConfigurationBuilder cacheBuilder, ClassLoader cacheClassLoader, CacheTemplate cacheDefinition) - throws ReflectiveOperationException { + throws ClassNotFoundException, IllegalAccessException, InstantiationException { cacheBuilder = CORE_CACHE_CONFIGURATION_PARSER.parse(cacheDefinition, cacheClassLoader, cacheBuilder); return serviceConfigurationParser.parse(document, cacheDefinition, cacheClassLoader, cacheBuilder); } @@ -194,7 +194,7 @@ private Map getTemplates(Document document, C private XmlConfiguration.Template parseTemplate(Document document, CacheTemplate template) { return new XmlConfiguration.Template() { @Override - public CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resources) throws ReflectiveOperationException { + public CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resources) throws ClassNotFoundException, InstantiationException, IllegalAccessException { checkTemplateTypeConsistency("key", classLoader, keyType, template); checkTemplateTypeConsistency("value", classLoader, valueType, template); @@ -228,7 +228,7 @@ public Document uriToDocument(URI uri) throws IOException, SAXException { return documentBuilder.parse(uri.toString()); } - public XmlConfigurationWrapper documentToConfig(Document document, ClassLoader classLoader, Map cacheClassLoaders) throws JAXBException, ReflectiveOperationException { + public XmlConfigurationWrapper documentToConfig(Document document, ClassLoader classLoader, Map cacheClassLoaders) throws JAXBException, ClassNotFoundException, InstantiationException, IllegalAccessException { Document annotatedDocument = stampExternalConfigurations(copyAndValidate(document)); Element root = annotatedDocument.getDocumentElement(); diff --git a/ehcache-xml/src/jakarta/java/org/ehcache/xml/CoreCacheConfigurationParser.java b/ehcache-xml/src/jakarta/java/org/ehcache/xml/CoreCacheConfigurationParser.java index 1c1126fd40..02666ca854 100644 --- a/ehcache-xml/src/jakarta/java/org/ehcache/xml/CoreCacheConfigurationParser.java +++ b/ehcache-xml/src/jakarta/java/org/ehcache/xml/CoreCacheConfigurationParser.java @@ -44,7 +44,7 @@ public class CoreCacheConfigurationParser { public CacheConfigurationBuilder parse(CacheTemplate cacheDefinition, ClassLoader cacheClassLoader, - CacheConfigurationBuilder cacheBuilder) throws ReflectiveOperationException { + CacheConfigurationBuilder cacheBuilder) throws ClassNotFoundException, IllegalAccessException, InstantiationException { final Expiry parsedExpiry = cacheDefinition.expiry(); if (parsedExpiry != null) { cacheBuilder = cacheBuilder.withExpiry(getExpiry(cacheClassLoader, parsedExpiry)); @@ -59,7 +59,7 @@ public CacheConfigurationBuilder parse(CacheTemplate cacheDefinitio @SuppressWarnings({"unchecked", "deprecation"}) private static ExpiryPolicy getExpiry(ClassLoader cacheClassLoader, Expiry parsedExpiry) - throws ReflectiveOperationException { + throws ClassNotFoundException, InstantiationException, IllegalAccessException { if (parsedExpiry.isUserDef()) { try { return getInstanceOfName(parsedExpiry.type(), cacheClassLoader, ExpiryPolicy.class); @@ -75,12 +75,12 @@ public CacheConfigurationBuilder parse(CacheTemplate cacheDefinitio } } - static T getInstanceOfName(String name, ClassLoader classLoader, Class type) throws ReflectiveOperationException { + static T getInstanceOfName(String name, ClassLoader classLoader, Class type) throws ClassNotFoundException, InstantiationException, IllegalAccessException { if (name == null) { return null; } Class klazz = getClassForName(name, classLoader); - return klazz.asSubclass(type).getDeclaredConstructor().newInstance(); + return klazz.asSubclass(type).newInstance(); } public CacheType unparse(CacheConfiguration cacheConfiguration, CacheType cacheType) { diff --git a/ehcache-xml/src/jakarta/java/org/ehcache/xml/XmlConfiguration.java b/ehcache-xml/src/jakarta/java/org/ehcache/xml/XmlConfiguration.java index 24db84de13..7db144bfb0 100644 --- a/ehcache-xml/src/jakarta/java/org/ehcache/xml/XmlConfiguration.java +++ b/ehcache-xml/src/jakarta/java/org/ehcache/xml/XmlConfiguration.java @@ -272,7 +272,7 @@ public URL getURL() { public CacheConfigurationBuilder newCacheConfigurationBuilderFromTemplate(final String name, final Class keyType, final Class valueType) - throws ReflectiveOperationException { + throws InstantiationException, IllegalAccessException, ClassNotFoundException { Template template = templates.get(name); if (template == null) { return null; @@ -307,7 +307,7 @@ public CacheConfigurationBuilder newCacheConfigurationBuilderFromTe final Class keyType, final Class valueType, final ResourcePools resourcePools) - throws ReflectiveOperationException { + throws InstantiationException, IllegalAccessException, ClassNotFoundException { Template template = templates.get(name); if (template == null) { return null; @@ -342,7 +342,7 @@ public CacheConfigurationBuilder newCacheConfigurationBuilderFromTe final Class keyType, final Class valueType, final Builder resourcePoolsBuilder) - throws ReflectiveOperationException { + throws InstantiationException, IllegalAccessException, ClassNotFoundException { return newCacheConfigurationBuilderFromTemplate(name, keyType, valueType, resourcePoolsBuilder.build()); } @@ -372,7 +372,7 @@ public FluentConfigurationBuilder derive() { } public interface Template { - CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resourcePools) throws ReflectiveOperationException; + CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resourcePools) throws ClassNotFoundException, InstantiationException, IllegalAccessException; } public static Class getClassForName(String name, ClassLoader classLoader) throws ClassNotFoundException { diff --git a/ehcache-xml/src/main/java/org/ehcache/xml/ConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/ConfigurationParser.java index 0f525243d1..275b7d35cc 100644 --- a/ehcache-xml/src/main/java/org/ehcache/xml/ConfigurationParser.java +++ b/ehcache-xml/src/main/java/org/ehcache/xml/ConfigurationParser.java @@ -149,7 +149,7 @@ private static Stream stream(Iterable iterable) { CacheConfigurationBuilder parseServiceConfigurations(Document document, CacheConfigurationBuilder cacheBuilder, ClassLoader cacheClassLoader, CacheTemplate cacheDefinition) - throws ReflectiveOperationException { + throws ClassNotFoundException, IllegalAccessException, InstantiationException { cacheBuilder = CORE_CACHE_CONFIGURATION_PARSER.parse(cacheDefinition, cacheClassLoader, cacheBuilder); return serviceConfigurationParser.parse(document, cacheDefinition, cacheClassLoader, cacheBuilder); } @@ -193,7 +193,7 @@ private Map getTemplates(Document document, C private XmlConfiguration.Template parseTemplate(Document document, CacheTemplate template) { return new XmlConfiguration.Template() { @Override - public CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resources) throws ReflectiveOperationException { + public CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resources) throws ClassNotFoundException, InstantiationException, IllegalAccessException { checkTemplateTypeConsistency("key", classLoader, keyType, template); checkTemplateTypeConsistency("value", classLoader, valueType, template); @@ -227,7 +227,7 @@ public Document uriToDocument(URI uri) throws IOException, SAXException { return documentBuilder.parse(uri.toString()); } - public XmlConfigurationWrapper documentToConfig(Document document, ClassLoader classLoader, Map cacheClassLoaders) throws JAXBException, ReflectiveOperationException { + public XmlConfigurationWrapper documentToConfig(Document document, ClassLoader classLoader, Map cacheClassLoaders) throws JAXBException, ClassNotFoundException, InstantiationException, IllegalAccessException { Document annotatedDocument = stampExternalConfigurations(copyAndValidate(document)); Element root = annotatedDocument.getDocumentElement(); diff --git a/ehcache-xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java index 1c1126fd40..02666ca854 100644 --- a/ehcache-xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java +++ b/ehcache-xml/src/main/java/org/ehcache/xml/CoreCacheConfigurationParser.java @@ -44,7 +44,7 @@ public class CoreCacheConfigurationParser { public CacheConfigurationBuilder parse(CacheTemplate cacheDefinition, ClassLoader cacheClassLoader, - CacheConfigurationBuilder cacheBuilder) throws ReflectiveOperationException { + CacheConfigurationBuilder cacheBuilder) throws ClassNotFoundException, IllegalAccessException, InstantiationException { final Expiry parsedExpiry = cacheDefinition.expiry(); if (parsedExpiry != null) { cacheBuilder = cacheBuilder.withExpiry(getExpiry(cacheClassLoader, parsedExpiry)); @@ -59,7 +59,7 @@ public CacheConfigurationBuilder parse(CacheTemplate cacheDefinitio @SuppressWarnings({"unchecked", "deprecation"}) private static ExpiryPolicy getExpiry(ClassLoader cacheClassLoader, Expiry parsedExpiry) - throws ReflectiveOperationException { + throws ClassNotFoundException, InstantiationException, IllegalAccessException { if (parsedExpiry.isUserDef()) { try { return getInstanceOfName(parsedExpiry.type(), cacheClassLoader, ExpiryPolicy.class); @@ -75,12 +75,12 @@ public CacheConfigurationBuilder parse(CacheTemplate cacheDefinitio } } - static T getInstanceOfName(String name, ClassLoader classLoader, Class type) throws ReflectiveOperationException { + static T getInstanceOfName(String name, ClassLoader classLoader, Class type) throws ClassNotFoundException, InstantiationException, IllegalAccessException { if (name == null) { return null; } Class klazz = getClassForName(name, classLoader); - return klazz.asSubclass(type).getDeclaredConstructor().newInstance(); + return klazz.asSubclass(type).newInstance(); } public CacheType unparse(CacheConfiguration cacheConfiguration, CacheType cacheType) { diff --git a/ehcache-xml/src/main/java/org/ehcache/xml/XmlConfiguration.java b/ehcache-xml/src/main/java/org/ehcache/xml/XmlConfiguration.java index b2c3f2433e..3363470e2a 100644 --- a/ehcache-xml/src/main/java/org/ehcache/xml/XmlConfiguration.java +++ b/ehcache-xml/src/main/java/org/ehcache/xml/XmlConfiguration.java @@ -271,7 +271,7 @@ public URL getURL() { public CacheConfigurationBuilder newCacheConfigurationBuilderFromTemplate(final String name, final Class keyType, final Class valueType) - throws ReflectiveOperationException { + throws InstantiationException, IllegalAccessException, ClassNotFoundException { Template template = templates.get(name); if (template == null) { return null; @@ -305,7 +305,7 @@ public CacheConfigurationBuilder newCacheConfigurationBuilderFromTe final Class keyType, final Class valueType, final ResourcePools resourcePools) - throws ReflectiveOperationException { + throws InstantiationException, IllegalAccessException, ClassNotFoundException { Template template = templates.get(name); if (template == null) { return null; @@ -339,7 +339,7 @@ public CacheConfigurationBuilder newCacheConfigurationBuilderFromTe final Class keyType, final Class valueType, final Builder resourcePoolsBuilder) - throws ReflectiveOperationException { + throws InstantiationException, IllegalAccessException, ClassNotFoundException { return newCacheConfigurationBuilderFromTemplate(name, keyType, valueType, resourcePoolsBuilder.build()); } @@ -369,7 +369,7 @@ public FluentConfigurationBuilder derive() { } public interface Template { - CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resourcePools) throws ReflectiveOperationException; + CacheConfigurationBuilder builderFor(ClassLoader classLoader, Class keyType, Class valueType, ResourcePools resourcePools) throws ClassNotFoundException, InstantiationException, IllegalAccessException; } public static Class getClassForName(String name, ClassLoader classLoader) throws ClassNotFoundException { diff --git a/ehcache-xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java b/ehcache-xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java index 3266ac2161..e33f0eb713 100644 --- a/ehcache-xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java +++ b/ehcache-xml/src/test/java/org/ehcache/xml/IntegrationConfigurationTest.java @@ -125,7 +125,7 @@ public void testLoaderWriter() throws ClassNotFoundException, SAXException, Inst final Cache cache = cacheManager.getCache("bar", Number.class, String.class); assertThat(cache, notNullValue()); assertThat(cache.get(1), notNullValue()); - final Number key = 42L; + final Number key = new Long(42); cache.put(key, "Bye y'all!"); assertThat(TestCacheLoaderWriter.lastWrittenKey, is(key)); @@ -133,7 +133,7 @@ public void testLoaderWriter() throws ClassNotFoundException, SAXException, Inst final Cache templateCache = cacheManager.getCache("template1", Number.class, String.class); assertThat(templateCache, notNullValue()); assertThat(templateCache.get(1), notNullValue()); - final Number key1 = 100L; + final Number key1 = new Long(100); templateCache.put(key1, "Bye y'all!"); assertThat(TestCacheLoaderWriter.lastWrittenKey, is(key1)); } diff --git a/ehcache/build.gradle b/ehcache/build.gradle index 145f067156..98cc84e224 100644 --- a/ehcache/build.gradle +++ b/ehcache/build.gradle @@ -69,8 +69,6 @@ configurations { jakartaContents { exclude group:'jakarta.xml.bind' } - javadocAdd - jakartaJavadocAdd } dependencies { @@ -96,12 +94,6 @@ dependencies { } } jakartaRuntimeOnly 'org.glassfish.jaxb:jaxb-runtime:[3,3.1)' - - javadocAdd 'com.github.spotbugs:spotbugs-annotations:4.9.8' - javadocAdd 'javax.xml.bind:jaxb-api:[2.2,3)' - - jakartaJavadocAdd 'com.github.spotbugs:spotbugs-annotations:4.9.8' - jakartaJavadocAdd 'jakarta.xml.bind:jakarta.xml.bind-api:[3,4)' } tasks.named('jakartaJar') { @@ -111,7 +103,7 @@ tasks.named('jakartaJar') { instruction Constants.BUNDLE_DESCRIPTION, 'Ehcache is an open-source caching library, compliant with the JSR-107 standard.' instruction Constants.BUNDLE_ACTIVATOR, 'org.ehcache.core.osgi.EhcacheActivator' instruction Constants.EXPORT_PACKAGE, '!org.ehcache.jsr107.tck, !org.ehcache.*.internal.*, org.ehcache.*' - instruction Constants.IMPORT_PACKAGE, 'javax.annotation.*;resolution:=optional, javax.cache.*;resolution:=optional, jdk.internal.misc;resolution:=optional, !javax.annotation, !sun.misc, jakarta.xml.bind*;version="[3,4)", *' + instruction Constants.IMPORT_PACKAGE, 'javax.cache.*;resolution:=optional, jdk.internal.misc;resolution:=optional, !javax.annotation, !sun.misc, jakarta.xml.bind*;version="[3,4)", *' } } @@ -122,14 +114,6 @@ tasks.named('jar') { instruction Constants.BUNDLE_DESCRIPTION, 'Ehcache is an open-source caching library, compliant with the JSR-107 standard.' instruction Constants.BUNDLE_ACTIVATOR, 'org.ehcache.core.osgi.EhcacheActivator' instruction Constants.EXPORT_PACKAGE, '!org.ehcache.jsr107.tck, !org.ehcache.*.internal.*, org.ehcache.*' - instruction Constants.IMPORT_PACKAGE, 'javax.annotation.*;resolution:=optional, javax.cache.*;resolution:=optional, jdk.internal.misc;resolution:=optional, !javax.annotation, !sun.misc, javax.xml.bind*;version="[2.2,3)", *' + instruction Constants.IMPORT_PACKAGE, 'javax.cache.*;resolution:=optional, jdk.internal.misc;resolution:=optional, !javax.annotation, !sun.misc, javax.xml.bind*;version="[2.2,3)", *' } } - -tasks.named('javadoc') { - classpath += configurations.javadocAdd -} - -tasks.named('jakartaJavadoc') { - classpath += configurations.jakartaJavadocAdd -} diff --git a/gradle.properties b/gradle.properties index a973c451c7..49162e7fe7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ ehcacheVersion = 3.11-SNAPSHOT offheapVersion = 2.5.6 statisticVersion = 2.1.3 jcacheVersion = 1.1.0 -slf4jVersion = 2.0.17 +slf4jVersion = 1.7.36 sizeofVersion = 0.4.4 # Terracotta clustered @@ -17,12 +17,10 @@ terracottaUtilitiesVersion = 0.0.19 # Test lib versions junitVersion = 4.13.1 -assertjVersion = 3.27.7 -byteBuddyVersion = 1.18.3 +assertjVersion = 3.22.0 hamcrestVersion = 2.2 -mockitoVersion = 5.12.0 +mockitoVersion = 4.3.1 jcacheTckVersion = 1.1.0 -logbackVersion = 1.5.26 sonatypeUser = OVERRIDE_ME sonatypePwd = OVERRIDE_ME diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..ccebba7710deaf9f98673a68957ea02138b60d0a 100644 GIT binary patch delta 39624 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 delta 37640 zcmY(pV{oQl@UEMQIdLYoZQHhO+nPMFZN0H=PmGB*$wZUnjWaPO#`&H7-?h&^-+I;R zs`a5)RbSorT?K|pUW9^CRe*v?z)jk`3-v@h+Kh<+Z{*45LEsZ32p!?75|!v%;9<=FBo{3 zRXe7ZM! z98qkC_kq3Jr|u(PUJ~iwCsJ*p-a(%Pqgj9Xc7Lc+p}K;6c)u(#FRF9=)wo4iY?p4? z60^8uurIVZQIm2}Ce`pi{UcuL|JWR#Q8Q{kW;nuMAGNtQh~oc6&3J6c<$o3S|5VZL z3u7$_36WS~;2Z71buHB@aK)V3L^u?)d zgL#sy&e{9ax^%(*s{V)IV@T%*!UNSBd;4;hcLk8Pe=pE0CuiO_IJ4fm^Y77!=TrFo zoh`WZNlqF9lihd(2H~4Tb~-DS1^(64wO9r#g_*WAa+amxcmVrRGJrkN7mtQxX*i_i z)<+_)tlALaYBUUoq0Ua;MP@iVh_L|~D(37j(?wz? zH)m`19Dj#1&V*2`b2-ZiEQ!yJt#^vxxg*64X#g`#J%-t-v$plgb=PvP(#c)s>9y7b zia~oDB#rs6W!COA<7^EAUGZ+oDkF@MMA#i>xh|YHyh}y{7$8zNEO<5xxxiDLg$P4b-Y1$G*5>uV zUS3pq1J;l+0lZpsti6iEQIx5uk^MRLBoj{ttVWACl|oS5nKj68VY0Gc7aeC$BJ8jj zOJY7VO(CumzCL^t5jhn@iNu|q84KnD=<_A zdu!zT6mz@J)LDflk;4=e9Y)D6N1$>&y?&_rrn(jkV6v+KV*+;gTjsyS5vg@l(vR3b zWJ+XMkIxyWiTvfj0A>dq5_)wLTyc&a<+vLiN^(sxvcN#kdN14v*xh#Mq8y&vfu!{* z6*7&MY+F>Q3qUL5H~;=>yDT2XY_CY`)P)3FFwH2X>`1n_*;bC{o$+g>X%?nvM%-jh z{Su%6)DM)s>(8&%@BC#c4QMzLh#-smk-I+w3c6 zvKP8e?Wjtrs`6uFL54F}HGH*3xYgPqw0cYfyc3EwSa=vazJ~dV>jie^&gSULF$&&* z9()2Rpu znE8a?Ed8MOFZsAmq#w2ju_f(GE2H2u@zv>w{bMm?o9u@pbMk$DrRtOAzCj}K1&~M= z3x4P=(l{yeU=jNh_4U5EFo-vvA`w}tQT>g_4UH=Hhxpp zUz@=oXPTamj%0)trn)RGmcHmFJ|vYE1EQUS0VzJdJQbE??HpA%$|iGf*ShFur0~

hZ6yjbL-Opwj#IyQ(UF?vIf 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 H_^bZ|3zHqB diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 740908bf52..761b8f0885 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-all.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787337..79a61d421c 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,10 +80,10 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' @@ -143,12 +143,16 @@ fi if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -205,6 +209,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index 107acd32c4..93e3f59f13 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/integration-test/build.gradle b/integration-test/build.gradle index 8f50fac865..7f1aae39e9 100644 --- a/integration-test/build.gradle +++ b/integration-test/build.gradle @@ -31,7 +31,5 @@ dependencies { testImplementation (group: 'org.codehaus.btm', name: 'btm', version: '2.1.4') { exclude group:'org.slf4j', module:'slf4j-api' } - testImplementation ("org.terracotta:statistics:$parent.statisticVersion") { - exclude group: 'org.slf4j', module: 'slf4j-api' - } + testImplementation "org.terracotta:statistics:$parent.statisticVersion" } diff --git a/integration-test/src/test/java/org/ehcache/integration/OverSizeMappingTest.java b/integration-test/src/test/java/org/ehcache/integration/OverSizeMappingTest.java index 29d7d37877..e23b6f9f8e 100644 --- a/integration-test/src/test/java/org/ehcache/integration/OverSizeMappingTest.java +++ b/integration-test/src/test/java/org/ehcache/integration/OverSizeMappingTest.java @@ -124,7 +124,7 @@ private static class ObjectSizeGreaterThanN implements Serializable { private ObjectSizeGreaterThanN(int n) { arr = new Integer[n]; for (int i = 0; i < arr.length; i++) { - arr[i] = i; + arr[i] = new Integer(i); } } diff --git a/osgi-test/build.gradle b/osgi-test/build.gradle index 68c6286d99..fca7b10ed6 100644 --- a/osgi-test/build.gradle +++ b/osgi-test/build.gradle @@ -57,8 +57,6 @@ dependencies { osgiModule project(':ehcache') osgiModule "org.slf4j:slf4j-simple:$parent.slf4jVersion" - // SLF4J 2.x requires osgi.serviceloader.processor; Apache Aries SPIFly provides it - osgiModule 'org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle:1.3.7' osgiModule 'org.apache.felix:org.apache.felix.scr:2.2.0' osgiModule 'com.sun.activation:javax.activation:1.2.0' @@ -79,11 +77,6 @@ configurations.all { .using(module('org.ops4j.pax.url:pax-url-classpath:2.6.11')) substitute(module('org.ops4j.pax.url:pax-url-link:2.6.8')) .using(module('org.ops4j.pax.url:pax-url-link:2.6.11')) - substitute(module('org.ops4j.pax.url:pax-url-aether:2.6.8')) - .using(module('org.ops4j.pax.url:pax-url-aether:3.0.2')) - substitute(module('org.apache.commons:commons-lang3:3.12.0')) - .using(module('org.apache.commons:commons-lang3:3.18.0')) - .because('CVE-2025-48924') substitute(module('org.osgi:org.osgi.util.function:1.1.0')) .using(module('org.osgi:org.osgi.util.function:1.2.0')) .because('Dependency divergence in org.osgi:org.osgi.util.promise:1.2.0') @@ -96,7 +89,7 @@ configurations.all { sourceSets { test { // Needed to allow PaxExam to see the test resources - output.resourcesDir = java.outputDir + output.resourcesDir = java.classesDirectory } } @@ -112,7 +105,7 @@ test { configurations { lowerBoundOsgiModule { resolutionStrategy.dependencySubstitution { - substitute module('org.glassfish.jaxb:jaxb-runtime') with module('com.sun.xml.bind:jaxb-osgi:2.2.8-b01') + substitute module('org.glassfish.jaxb:jaxb-runtime') using module('com.sun.xml.bind:jaxb-osgi:2.2.8-b01') } } } diff --git a/osgi-test/src/main/java/org/ehcache/osgi/OsgiTestUtils.java b/osgi-test/src/main/java/org/ehcache/osgi/OsgiTestUtils.java index e9599d4e9d..ed4558f20f 100644 --- a/osgi-test/src/main/java/org/ehcache/osgi/OsgiTestUtils.java +++ b/osgi-test/src/main/java/org/ehcache/osgi/OsgiTestUtils.java @@ -49,14 +49,6 @@ public static Option baseConfiguration(String ... path) { return composite( gradleBundle("org.slf4j:slf4j-api"), gradleBundle("org.slf4j:slf4j-simple").noStart(), - // ASM bundles required by SPI Fly - gradleBundle("org.ow2.asm:asm"), - gradleBundle("org.ow2.asm:asm-tree"), - gradleBundle("org.ow2.asm:asm-analysis"), - gradleBundle("org.ow2.asm:asm-commons"), - gradleBundle("org.ow2.asm:asm-util"), - // SPI Fly for SLF4J 2.x ServiceLoader support - gradleBundle("org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle"), gradleBundle("org.apache.felix:org.apache.felix.scr"), gradleBundle("org.osgi:org.osgi.util.promise"), gradleBundle("org.osgi:org.osgi.util.function"),