This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 80b7a3bcaa org.apache.juneau.common.reflect API improvements
80b7a3bcaa is described below
commit 80b7a3bcaa2de750506a31d30c70b993ac3fbdd1
Author: James Bognar <[email protected]>
AuthorDate: Fri Nov 21 13:23:50 2025 -0500
org.apache.juneau.common.reflect API improvements
---
.../apache/juneau/common/collections/Cache.java | 73 +++++------
.../apache/juneau/common/collections/Cache2.java | 68 ++++------
.../apache/juneau/common/collections/Cache3.java | 45 ++++---
.../apache/juneau/common/collections/Cache4.java | 45 ++++---
.../apache/juneau/common/collections/Cache5.java | 45 ++++---
.../juneau/common/collections/CacheMode.java | 128 ++++++++++++++++++
.../juneau/common/reflect/AnnotationProvider.java | 146 ++++++++++++++++-----
.../juneau/common/utils/MimeTypeDetector.java | 26 ++--
.../juneau/common/collections/Cache2_Test.java | 4 +-
.../juneau/common/collections/Cache3_Test.java | 4 +-
.../juneau/common/collections/Cache4_Test.java | 4 +-
.../juneau/common/collections/Cache5_Test.java | 4 +-
.../juneau/common/collections/Cache_Test.java | 10 +-
.../juneau/common/utils/MimeTypeDetector_Test.java | 7 +-
14 files changed, 415 insertions(+), 194 deletions(-)
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache.java
index 5c48fd291c..7094c2fd62 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache.java
@@ -16,6 +16,7 @@
*/
package org.apache.juneau.common.collections;
+import static org.apache.juneau.common.collections.CacheMode.*;
import static org.apache.juneau.common.utils.AssertionUtils.*;
import static org.apache.juneau.common.utils.SystemUtils.*;
import static org.apache.juneau.common.utils.Utils.*;
@@ -94,7 +95,7 @@ import org.apache.juneau.common.function.*;
* <p>
* The following system properties can be used to configure default cache
behavior:
* <ul class='spaced-list'>
- * <li><c>juneau.cache.disable</c> - Disables all caching (default:
<jk>false</jk>)
+ * <li><c>juneau.cache.mode</c> - Cache mode: NONE/WEAK/FULL (default:
FULL, case-insensitive)
* <li><c>juneau.cache.maxSize</c> - Maximum cache size before eviction
(default: 1000)
* <li><c>juneau.cache.logOnExit</c> - Log cache statistics on shutdown
(default: <jk>false</jk>)
* </ul>
@@ -152,7 +153,7 @@ import org.apache.juneau.common.function.*;
public class Cache<K,V> {
// Internal map with Tuple1 keys for content-based equality (especially
for arrays)
- private final ConcurrentHashMap<Tuple1<K>,V> map = new
ConcurrentHashMap<>();
+ private final Map<Tuple1<K>,V> map;
/**
* Cache of Tuple1 wrapper objects to minimize object creation on
repeated get/put calls.
@@ -161,7 +162,7 @@ public class Cache<K,V> {
* Uses WeakHashMap so wrappers can be GC'd when keys are no longer
referenced.
* This provides a significant performance improvement for caches with
repeated key access.
*/
- private final Map<K,Tuple1<K>> wrapperCache = synchronizedMap(new
WeakHashMap<>());
+ private final Map<K,Tuple1<K>> wrapperCache;
/**
* Gets or creates a Tuple1 wrapper for the given key.
@@ -206,14 +207,14 @@ public class Cache<K,V> {
* @param <V> The value type.
*/
public static class Builder<K,V> {
- boolean disableCaching;
+ CacheMode cacheMode;
int maxSize;
String id;
boolean logOnExit;
Function<K,V> supplier;
Builder() {
- disableCaching = env("juneau.cache.disable", false);
+ cacheMode = CacheMode.parse(env("juneau.cache.mode",
"FULL"));
maxSize = env("juneau.cache.maxSize", 1000);
logOnExit = env("juneau.cache.logOnExit", false);
id = "Cache";
@@ -229,50 +230,39 @@ public class Cache<K,V> {
}
/**
- * Disables caching entirely.
+ * Sets the caching mode for this cache.
*
* <p>
- * When disabled, the {@link Cache#get(Object)} and {@link
Cache#get(Object, Supplier)} methods
- * will always invoke the supplier and never store or retrieve
values from the cache.
- *
- * <p>
- * This is useful for:
+ * Available modes:
* <ul>
- * <li>Testing scenarios where you want fresh computation
each time
- * <li>Development environments where caching might hide
issues
- * <li>Temporarily disabling caching without code changes
+ * <li>{@link CacheMode#NONE NONE} - No caching (always
invoke supplier)
+ * <li>{@link CacheMode#WEAK WEAK} - Weak caching (uses
{@link WeakHashMap})
+ * <li>{@link CacheMode#FULL FULL} - Full caching (uses
{@link ConcurrentHashMap}, default)
* </ul>
*
- * @return This object for method chaining.
- */
- public Builder<K,V> disableCaching() {
- disableCaching = true;
- return this;
- }
-
- /**
- * Conditionally disables or enables caching.
- *
- * <p>
- * When disabled, the {@link Cache#get(Object)} and {@link
Cache#get(Object, Supplier)} methods
- * will always invoke the supplier and never store or retrieve
values from the cache.
- *
- * <p>
- * This is typically used when the disable flag comes from an
external configuration or system property.
- *
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
- * Cache<String,Object> <jv>cache</jv> =
Cache.<jsm>of</jsm>(String.<jk>class</jk>, Object.<jk>class</jk>)
- *
.disableCaching(Boolean.<jsm>getBoolean</jsm>(<js>"myapp.disableCache"</js>))
+ * <jc>// No caching for testing</jc>
+ * Cache<String,Object> <jv>cache1</jv> =
Cache.<jsm>of</jsm>(String.<jk>class</jk>, Object.<jk>class</jk>)
+ * .cacheMode(CacheMode.<jsf>NONE</jsf>)
+ * .build();
+ *
+ * <jc>// Weak caching for Class metadata</jc>
+ * Cache<Class<?>,ClassMeta> <jv>cache2</jv> =
Cache.<jsm>of</jsm>(Class.<jk>class</jk>, ClassMeta.<jk>class</jk>)
+ * .cacheMode(CacheMode.<jsf>WEAK</jsf>)
+ * .build();
+ *
+ * <jc>// Full caching (default)</jc>
+ * Cache<String,Pattern> <jv>cache3</jv> =
Cache.<jsm>of</jsm>(String.<jk>class</jk>, Pattern.<jk>class</jk>)
+ * .cacheMode(CacheMode.<jsf>FULL</jsf>)
* .build();
* </p>
*
- * @param value If <jk>true</jk>, caching is disabled. If
<jk>false</jk>, caching is enabled (default).
+ * @param value The caching mode.
* @return This object for method chaining.
- * @see #disableCaching()
*/
- public Builder<K,V> disableCaching(boolean value) {
- disableCaching = value;
+ public Builder<K,V> cacheMode(CacheMode value) {
+ cacheMode = value;
return this;
}
@@ -432,8 +422,15 @@ public class Cache<K,V> {
*/
protected Cache(Builder<K,V> builder) {
this.maxSize = builder.maxSize;
- this.disableCaching = builder.disableCaching;
+ this.disableCaching = builder.cacheMode == NONE;
this.supplier = builder.supplier != null ? builder.supplier :
(K)->null;
+ if (builder.cacheMode == WEAK) {
+ this.map = synchronizedMap(new WeakHashMap<>());
+ this.wrapperCache = synchronizedMap(new
WeakHashMap<>());
+ } else {
+ this.map = new ConcurrentHashMap<>();
+ this.wrapperCache = synchronizedMap(new
WeakHashMap<>());
+ }
if (builder.logOnExit) {
shutdownMessage(() -> builder.id + ": hits=" +
cacheHits.get() + ", misses: " + size());
}
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache2.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache2.java
index 9d90fc8e48..ab8bfda19b 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache2.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache2.java
@@ -16,10 +16,14 @@
*/
package org.apache.juneau.common.collections;
+import static org.apache.juneau.common.collections.CacheMode.*;
+
import static org.apache.juneau.common.utils.AssertionUtils.*;
import static org.apache.juneau.common.utils.SystemUtils.*;
import static org.apache.juneau.common.utils.Utils.*;
+import java.util.*;
+import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import org.apache.juneau.common.function.*;
@@ -78,7 +82,7 @@ import org.apache.juneau.common.function.*;
* <p>
* The following system properties can be used to configure default cache
behavior:
* <ul class='spaced-list'>
- * <li><c>juneau.cache.disable</c> - Disables all caching (default:
<jk>false</jk>)
+ * <li><c>juneau.cache.mode</c> - Cache mode: NONE/WEAK/FULL (default:
FULL, case-insensitive)
* <li><c>juneau.cache.maxSize</c> - Maximum cache size before eviction
(default: 1000)
* <li><c>juneau.cache.logOnExit</c> - Log cache statistics on shutdown
(default: <jk>false</jk>)
* </ul>
@@ -133,7 +137,7 @@ import org.apache.juneau.common.function.*;
public class Cache2<K1,K2,V> {
// Internal map with Tuple2 keys for content-based equality (especially
for arrays)
- private final java.util.concurrent.ConcurrentHashMap<Tuple2<K1,K2>,V>
map = new java.util.concurrent.ConcurrentHashMap<>();
+ private final java.util.Map<Tuple2<K1,K2>,V> map;
/**
* Builder for creating configured {@link Cache2} instances.
@@ -157,14 +161,14 @@ public class Cache2<K1,K2,V> {
* @param <V> The value type.
*/
public static class Builder<K1,K2,V> {
- boolean disableCaching;
+ CacheMode cacheMode;
int maxSize;
String id;
boolean logOnExit;
Function2<K1,K2,V> supplier;
Builder() {
- disableCaching = env("juneau.cache.disable", false);
+ cacheMode = CacheMode.parse(env("juneau.cache.mode",
"FULL"));
maxSize = env("juneau.cache.maxSize", 1000);
logOnExit = env("juneau.cache.logOnExit", false);
id = "Cache2";
@@ -180,50 +184,21 @@ public class Cache2<K1,K2,V> {
}
/**
- * Disables caching entirely.
- *
- * <p>
- * When disabled, the {@link Cache2#get(Object, Object)} and
- * {@link Cache2#get(Object, Object,
java.util.function.Supplier)} methods will always invoke
- * the supplier and never store or retrieve values from the
cache.
+ * Sets the caching mode for this cache.
*
* <p>
- * This is useful for:
+ * Available modes:
* <ul>
- * <li>Testing scenarios where you want fresh computation
each time
- * <li>Development environments where caching might hide
issues
- * <li>Temporarily disabling caching without code changes
+ * <li>{@link CacheMode#NONE NONE} - No caching (always
invoke supplier)
+ * <li>{@link CacheMode#WEAK WEAK} - Weak caching (uses
{@link WeakHashMap})
+ * <li>{@link CacheMode#FULL FULL} - Full caching (uses
{@link ConcurrentHashMap}, default)
* </ul>
*
+ * @param value The caching mode.
* @return This object for method chaining.
*/
- public Builder<K1,K2,V> disableCaching() {
- disableCaching = true;
- return this;
- }
-
- /**
- * Optionally disables caching based on the provided flag.
- *
- * <p>
- * When disabled, the {@link Cache2#get(Object, Object)} and
- * {@link Cache2#get(Object, Object,
java.util.function.Supplier)} methods will always invoke
- * the supplier and never store or retrieve values from the
cache.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bjava'>
- * <jk>boolean</jk> <jv>disable</jv> =
env(<js>"disable.caching"</js>, <jk>false</jk>);
- * Cache2<String,String,Config> <jv>cache</jv> =
Cache2
- * .<jsm>of</jsm>(String.<jk>class</jk>,
String.<jk>class</jk>, Config.<jk>class</jk>)
- * .disableCaching(<jv>disable</jv>)
- * .build();
- * </p>
- *
- * @param value If <jk>true</jk>, disables caching.
- * @return This object for method chaining.
- */
- public Builder<K1,K2,V> disableCaching(boolean value) {
- disableCaching = value;
+ public Builder<K1,K2,V> cacheMode(CacheMode value) {
+ cacheMode = value;
return this;
}
@@ -377,7 +352,7 @@ public class Cache2<K1,K2,V> {
}
private final int maxSize;
- private final boolean disableCaching;
+ private final CacheMode cacheMode;
private final Function2<K1,K2,V> supplier;
private final AtomicInteger cacheHits = new AtomicInteger();
@@ -388,8 +363,13 @@ public class Cache2<K1,K2,V> {
*/
protected Cache2(Builder<K1,K2,V> builder) {
this.maxSize = builder.maxSize;
- this.disableCaching = builder.disableCaching;
+ this.cacheMode = builder.cacheMode;
this.supplier = builder.supplier;
+ if (builder.cacheMode == WEAK) {
+ this.map = Collections.synchronizedMap(new
WeakHashMap<>());
+ } else {
+ this.map = new ConcurrentHashMap<>();
+ }
if (builder.logOnExit) {
shutdownMessage(() -> builder.id + ": hits=" +
cacheHits.get() + ", misses: " + size());
}
@@ -467,7 +447,7 @@ public class Cache2<K1,K2,V> {
*/
public V get(K1 key1, K2 key2, java.util.function.Supplier<V> supplier)
{
assertArgsNotNull("key1", key1, "key2", key2);
- if (disableCaching)
+ if (cacheMode == NONE)
return supplier.get();
Tuple2<K1,K2> wrapped = Tuple2.of(key1, key2);
V v = map.get(wrapped);
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache3.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache3.java
index a018e4122e..a134446141 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache3.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache3.java
@@ -16,10 +16,14 @@
*/
package org.apache.juneau.common.collections;
+import static org.apache.juneau.common.collections.CacheMode.*;
+
import static org.apache.juneau.common.utils.AssertionUtils.*;
import static org.apache.juneau.common.utils.SystemUtils.*;
import static org.apache.juneau.common.utils.Utils.*;
+import java.util.*;
+import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import org.apache.juneau.common.function.*;
@@ -77,7 +81,7 @@ import org.apache.juneau.common.function.*;
public class Cache3<K1,K2,K3,V> {
// Internal map with Tuple3 keys for content-based equality (especially
for arrays)
- private final
java.util.concurrent.ConcurrentHashMap<Tuple3<K1,K2,K3>,V> map = new
java.util.concurrent.ConcurrentHashMap<>();
+ private final java.util.Map<Tuple3<K1,K2,K3>,V> map;
/**
* Builder for creating configured {@link Cache3} instances.
@@ -88,14 +92,14 @@ public class Cache3<K1,K2,K3,V> {
* @param <V> The value type.
*/
public static class Builder<K1,K2,K3,V> {
- boolean disableCaching;
+ CacheMode cacheMode;
int maxSize;
String id;
boolean logOnExit;
Function3<K1,K2,K3,V> supplier;
Builder() {
- disableCaching = env("juneau.cache.disable", false);
+ cacheMode = CacheMode.parse(env("juneau.cache.mode",
"FULL"));
maxSize = env("juneau.cache.maxSize", 1000);
logOnExit = env("juneau.cache.logOnExit", false);
id = "Cache3";
@@ -111,23 +115,21 @@ public class Cache3<K1,K2,K3,V> {
}
/**
- * Disables caching entirely.
+ * Sets the caching mode for this cache.
*
- * @return This object for method chaining.
- */
- public Builder<K1,K2,K3,V> disableCaching() {
- disableCaching = true;
- return this;
- }
-
- /**
- * Optionally disables caching based on the provided flag.
+ * <p>
+ * Available modes:
+ * <ul>
+ * <li>{@link CacheMode#NONE NONE} - No caching (always
invoke supplier)
+ * <li>{@link CacheMode#WEAK WEAK} - Weak caching (uses
{@link WeakHashMap})
+ * <li>{@link CacheMode#FULL FULL} - Full caching (uses
{@link ConcurrentHashMap}, default)
+ * </ul>
*
- * @param value If <jk>true</jk>, disables caching.
+ * @param value The caching mode.
* @return This object for method chaining.
*/
- public Builder<K1,K2,K3,V> disableCaching(boolean value) {
- disableCaching = value;
+ public Builder<K1,K2,K3,V> cacheMode(CacheMode value) {
+ cacheMode = value;
return this;
}
@@ -218,7 +220,7 @@ public class Cache3<K1,K2,K3,V> {
}
private final int maxSize;
- private final boolean disableCaching;
+ private final CacheMode cacheMode;
private final Function3<K1,K2,K3,V> supplier;
private final AtomicInteger cacheHits = new AtomicInteger();
@@ -229,8 +231,13 @@ public class Cache3<K1,K2,K3,V> {
*/
protected Cache3(Builder<K1,K2,K3,V> builder) {
this.maxSize = builder.maxSize;
- this.disableCaching = builder.disableCaching;
+ this.cacheMode = builder.cacheMode;
this.supplier = builder.supplier;
+ if (builder.cacheMode == WEAK) {
+ this.map = Collections.synchronizedMap(new
WeakHashMap<>());
+ } else {
+ this.map = new ConcurrentHashMap<>();
+ }
if (builder.logOnExit) {
shutdownMessage(() -> builder.id + ": hits=" +
cacheHits.get() + ", misses: " + size());
}
@@ -263,7 +270,7 @@ public class Cache3<K1,K2,K3,V> {
*/
public V get(K1 key1, K2 key2, K3 key3, java.util.function.Supplier<V>
supplier) {
assertArgsNotNull("key1", key1, "key2", key2, "key3", key3);
- if (disableCaching)
+ if (cacheMode == NONE)
return supplier.get();
Tuple3<K1,K2,K3> wrapped = Tuple3.of(key1, key2, key3);
V v = map.get(wrapped);
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache4.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache4.java
index 3fda8bd97c..e61958a23a 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache4.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache4.java
@@ -16,10 +16,14 @@
*/
package org.apache.juneau.common.collections;
+import static org.apache.juneau.common.collections.CacheMode.*;
+
import static org.apache.juneau.common.utils.AssertionUtils.*;
import static org.apache.juneau.common.utils.SystemUtils.*;
import static org.apache.juneau.common.utils.Utils.*;
+import java.util.*;
+import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import org.apache.juneau.common.function.*;
@@ -63,7 +67,7 @@ import org.apache.juneau.common.function.*;
public class Cache4<K1,K2,K3,K4,V> {
// Internal map with Tuple4 keys for content-based equality (especially
for arrays)
- private final
java.util.concurrent.ConcurrentHashMap<Tuple4<K1,K2,K3,K4>,V> map = new
java.util.concurrent.ConcurrentHashMap<>();
+ private final java.util.Map<Tuple4<K1,K2,K3,K4>,V> map;
/**
* Builder for creating configured {@link Cache4} instances.
@@ -75,14 +79,14 @@ public class Cache4<K1,K2,K3,K4,V> {
* @param <V> The value type.
*/
public static class Builder<K1,K2,K3,K4,V> {
- boolean disableCaching;
+ CacheMode cacheMode;
int maxSize;
String id;
boolean logOnExit;
Function4<K1,K2,K3,K4,V> supplier;
Builder() {
- disableCaching = env("juneau.cache.disable", false);
+ cacheMode = CacheMode.parse(env("juneau.cache.mode",
"FULL"));
maxSize = env("juneau.cache.maxSize", 1000);
logOnExit = env("juneau.cache.logOnExit", false);
id = "Cache4";
@@ -98,23 +102,21 @@ public class Cache4<K1,K2,K3,K4,V> {
}
/**
- * Disables caching entirely.
+ * Sets the caching mode for this cache.
*
- * @return This object for method chaining.
- */
- public Builder<K1,K2,K3,K4,V> disableCaching() {
- disableCaching = true;
- return this;
- }
-
- /**
- * Optionally disables caching based on the provided flag.
+ * <p>
+ * Available modes:
+ * <ul>
+ * <li>{@link CacheMode#NONE NONE} - No caching (always
invoke supplier)
+ * <li>{@link CacheMode#WEAK WEAK} - Weak caching (uses
{@link WeakHashMap})
+ * <li>{@link CacheMode#FULL FULL} - Full caching (uses
{@link ConcurrentHashMap}, default)
+ * </ul>
*
- * @param value If <jk>true</jk>, disables caching.
+ * @param value The caching mode.
* @return This object for method chaining.
*/
- public Builder<K1,K2,K3,K4,V> disableCaching(boolean value) {
- disableCaching = value;
+ public Builder<K1,K2,K3,K4,V> cacheMode(CacheMode value) {
+ cacheMode = value;
return this;
}
@@ -208,7 +210,7 @@ public class Cache4<K1,K2,K3,K4,V> {
}
private final int maxSize;
- private final boolean disableCaching;
+ private final CacheMode cacheMode;
private final Function4<K1,K2,K3,K4,V> supplier;
private final AtomicInteger cacheHits = new AtomicInteger();
@@ -219,8 +221,13 @@ public class Cache4<K1,K2,K3,K4,V> {
*/
protected Cache4(Builder<K1,K2,K3,K4,V> builder) {
this.maxSize = builder.maxSize;
- this.disableCaching = builder.disableCaching;
+ this.cacheMode = builder.cacheMode;
this.supplier = builder.supplier;
+ if (builder.cacheMode == WEAK) {
+ this.map = Collections.synchronizedMap(new
WeakHashMap<>());
+ } else {
+ this.map = new ConcurrentHashMap<>();
+ }
if (builder.logOnExit) {
shutdownMessage(() -> builder.id + ": hits=" +
cacheHits.get() + ", misses: " + size());
}
@@ -255,7 +262,7 @@ public class Cache4<K1,K2,K3,K4,V> {
*/
public V get(K1 key1, K2 key2, K3 key3, K4 key4,
java.util.function.Supplier<V> supplier) {
assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4);
- if (disableCaching)
+ if (cacheMode == NONE)
return supplier.get();
Tuple4<K1,K2,K3,K4> wrapped = Tuple4.of(key1, key2, key3, key4);
V v = map.get(wrapped);
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache5.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache5.java
index 5c49ac6dfd..ee7c5afb86 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache5.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache5.java
@@ -16,10 +16,14 @@
*/
package org.apache.juneau.common.collections;
+import static org.apache.juneau.common.collections.CacheMode.*;
+
import static org.apache.juneau.common.utils.AssertionUtils.*;
import static org.apache.juneau.common.utils.SystemUtils.*;
import static org.apache.juneau.common.utils.Utils.*;
+import java.util.*;
+import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import org.apache.juneau.common.function.*;
@@ -65,7 +69,7 @@ import org.apache.juneau.common.function.*;
public class Cache5<K1,K2,K3,K4,K5,V> {
// Internal map with Tuple5 keys for content-based equality (especially
for arrays)
- private final
java.util.concurrent.ConcurrentHashMap<Tuple5<K1,K2,K3,K4,K5>,V> map = new
java.util.concurrent.ConcurrentHashMap<>();
+ private final java.util.Map<Tuple5<K1,K2,K3,K4,K5>,V> map;
/**
* Builder for creating configured {@link Cache5} instances.
@@ -78,14 +82,14 @@ public class Cache5<K1,K2,K3,K4,K5,V> {
* @param <V> The value type.
*/
public static class Builder<K1,K2,K3,K4,K5,V> {
- boolean disableCaching;
+ CacheMode cacheMode;
int maxSize;
String id;
boolean logOnExit;
Function5<K1,K2,K3,K4,K5,V> supplier;
Builder() {
- disableCaching = env("juneau.cache.disable", false);
+ cacheMode = CacheMode.parse(env("juneau.cache.mode",
"FULL"));
maxSize = env("juneau.cache.maxSize", 1000);
logOnExit = env("juneau.cache.logOnExit", false);
id = "Cache5";
@@ -101,23 +105,21 @@ public class Cache5<K1,K2,K3,K4,K5,V> {
}
/**
- * Disables caching entirely.
+ * Sets the caching mode for this cache.
*
- * @return This object for method chaining.
- */
- public Builder<K1,K2,K3,K4,K5,V> disableCaching() {
- disableCaching = true;
- return this;
- }
-
- /**
- * Optionally disables caching based on the provided flag.
+ * <p>
+ * Available modes:
+ * <ul>
+ * <li>{@link CacheMode#NONE NONE} - No caching (always
invoke supplier)
+ * <li>{@link CacheMode#WEAK WEAK} - Weak caching (uses
{@link WeakHashMap})
+ * <li>{@link CacheMode#FULL FULL} - Full caching (uses
{@link ConcurrentHashMap}, default)
+ * </ul>
*
- * @param value If <jk>true</jk>, disables caching.
+ * @param value The caching mode.
* @return This object for method chaining.
*/
- public Builder<K1,K2,K3,K4,K5,V> disableCaching(boolean value) {
- disableCaching = value;
+ public Builder<K1,K2,K3,K4,K5,V> cacheMode(CacheMode value) {
+ cacheMode = value;
return this;
}
@@ -214,7 +216,7 @@ public class Cache5<K1,K2,K3,K4,K5,V> {
}
private final int maxSize;
- private final boolean disableCaching;
+ private final CacheMode cacheMode;
private final Function5<K1,K2,K3,K4,K5,V> supplier;
private final AtomicInteger cacheHits = new AtomicInteger();
@@ -225,8 +227,13 @@ public class Cache5<K1,K2,K3,K4,K5,V> {
*/
protected Cache5(Builder<K1,K2,K3,K4,K5,V> builder) {
this.maxSize = builder.maxSize;
- this.disableCaching = builder.disableCaching;
+ this.cacheMode = builder.cacheMode;
this.supplier = builder.supplier;
+ if (builder.cacheMode == WEAK) {
+ this.map = Collections.synchronizedMap(new
WeakHashMap<>());
+ } else {
+ this.map = new ConcurrentHashMap<>();
+ }
if (builder.logOnExit) {
shutdownMessage(() -> builder.id + ": hits=" +
cacheHits.get() + ", misses: " + size());
}
@@ -263,7 +270,7 @@ public class Cache5<K1,K2,K3,K4,K5,V> {
*/
public V get(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5,
java.util.function.Supplier<V> supplier) {
assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4, "key5", key5);
- if (disableCaching)
+ if (cacheMode == NONE)
return supplier.get();
Tuple5<K1,K2,K3,K4,K5> wrapped = Tuple5.of(key1, key2, key3,
key4, key5);
V v = map.get(wrapped);
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/CacheMode.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/CacheMode.java
new file mode 100644
index 0000000000..55ddb5a9b8
--- /dev/null
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/CacheMode.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.juneau.common.collections;
+
+/**
+ * Cache modes for {@link Cache} and related cache classes.
+ *
+ * <p>
+ * Defines how cache storage is implemented and when cached entries may be
evicted.
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul>
+ * <li class='jc'>{@link Cache}
+ * <li class='jc'>{@link Cache2}
+ * <li class='jc'>{@link Cache3}
+ * <li class='jc'>{@link Cache4}
+ * <li class='jc'>{@link Cache5}
+ * </ul>
+ */
+public enum CacheMode {
+
+ /**
+ * No caching - all lookups invoke the supplier.
+ *
+ * <p>
+ * When this mode is used, the cache will not store any values. Every
call to
+ * {@link Cache#get(Object)} or {@link Cache#get(Object,
java.util.function.Supplier)}
+ * will invoke the supplier to compute the value.
+ *
+ * <p>
+ * This mode is useful for:
+ * <ul>
+ * <li>Testing scenarios where you want fresh computation each time
+ * <li>Development environments where caching might hide issues
+ * <li>Temporarily disabling caching without code changes
+ * </ul>
+ */
+ NONE,
+
+ /**
+ * Weak caching - uses {@link java.util.WeakHashMap} for storage.
+ *
+ * <p>
+ * Cache entries can be garbage collected when keys are no longer
strongly referenced elsewhere.
+ * The WeakHashMap is wrapped with {@link
java.util.Collections#synchronizedMap(java.util.Map)}
+ * for thread safety.
+ *
+ * <p>
+ * This mode is useful for:
+ * <ul>
+ * <li>Caching metadata about objects that may be unloaded (e.g.,
{@link Class} objects)
+ * <li>Memory-sensitive applications where cache entries should
not prevent garbage collection
+ * <li>Scenarios where keys have limited lifetimes
+ * </ul>
+ *
+ * <p>
+ * <b>Note:</b> Weak caching comes with performance trade-offs:
+ * <ul>
+ * <li>Slightly slower access due to synchronization overhead
+ * <li>Entries may be removed unpredictably by the garbage
collector
+ * <li>Not suitable for high-concurrency scenarios
+ * </ul>
+ */
+ WEAK,
+
+ /**
+ * Full caching - uses {@link java.util.concurrent.ConcurrentHashMap}
for storage.
+ *
+ * <p>
+ * Provides the best performance with lock-free reads and writes.
Cached entries
+ * will remain in memory until explicitly removed or the cache is
cleared due to
+ * exceeding the maximum size.
+ *
+ * <p>
+ * This is the default and recommended mode for most use cases,
offering:
+ * <ul>
+ * <li>Excellent performance with no synchronization overhead for
reads
+ * <li>Thread-safe concurrent access
+ * <li>Predictable memory usage (entries stay until evicted)
+ * <li>Suitable for high-concurrency scenarios
+ * </ul>
+ */
+ FULL;
+
+ /**
+ * Parses a string value into a {@link CacheMode}.
+ *
+ * <p>
+ * Performs case-insensitive matching against the enum constant names.
+ *
+ * <h5 class='section'>Examples:</h5>
+ * <p class='bjava'>
+ * CacheMode.<jsm>parse</jsm>(<js>"none"</js>); <jc>// Returns
NONE</jc>
+ * CacheMode.<jsm>parse</jsm>(<js>"WEAK"</js>); <jc>// Returns
WEAK</jc>
+ * CacheMode.<jsm>parse</jsm>(<js>"Full"</js>); <jc>// Returns
FULL</jc>
+ * CacheMode.<jsm>parse</jsm>(<jk>null</jk>); <jc>// Returns
FULL (default)</jc>
+ * CacheMode.<jsm>parse</jsm>(<js>"invalid"</js>); <jc>// Returns
FULL (default)</jc>
+ * </p>
+ *
+ * @param value The string value to parse. Can be <jk>null</jk>.
+ * @return The corresponding {@link CacheMode}, or {@link #FULL} if the
value is <jk>null</jk> or invalid.
+ */
+ public static CacheMode parse(String value) {
+ if (value == null)
+ return FULL;
+ switch (value.toUpperCase()) {
+ case "NONE": return NONE;
+ case "WEAK": return WEAK;
+ case "FULL": return FULL;
+ default: return FULL;
+ }
+ }
+}
+
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationProvider.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationProvider.java
index bb2405e533..8418e5a16d 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationProvider.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationProvider.java
@@ -21,6 +21,7 @@ import static
org.apache.juneau.common.utils.CollectionUtils.*;
import static org.apache.juneau.common.utils.ThrowableUtils.*;
import static org.apache.juneau.common.utils.Utils.*;
import static org.apache.juneau.common.reflect.AnnotationTraversal.*;
+import static org.apache.juneau.common.collections.CacheMode.*;
import static java.util.stream.Stream.*;
import java.lang.annotation.*;
@@ -180,10 +181,55 @@ import org.apache.juneau.common.collections.*;
*/
public class AnnotationProvider {
+
//-----------------------------------------------------------------------------------------------------------------
+ // System properties
+
//-----------------------------------------------------------------------------------------------------------------
+
/**
- * Disable annotation caching.
+ * Caching mode for annotation lookups.
+ *
+ * <p>
+ * System property: <c>juneau.annotationProvider.caching</c>
+ * <br>Valid values: <c>NONE</c>, <c>WEAK</c>, <c>FULL</c>
(case-insensitive)
+ * <br>Default: <c>FULL</c>
+ *
+ * <ul>
+ * <li><c>NONE</c> - Disables all caching (always recompute)
+ * <li><c>WEAK</c> - Uses WeakHashMap (allows GC of cached entries)
+ * <li><c>FULL</c> - Uses ConcurrentHashMap (best performance)
+ * </ul>
*/
- private static final boolean DISABLE_ANNOTATION_CACHING =
Boolean.getBoolean("juneau.disableAnnotationCaching");
+ private static final CacheMode CACHING_MODE =
CacheMode.parse(System.getProperty("juneau.annotationProvider.caching",
"FULL"));
+
+ /**
+ * Enable logging of cache statistics on JVM shutdown.
+ *
+ * <p>
+ * System property: <c>juneau.annotationProvider.caching.logOnExit</c>
+ * <br>Valid values: <c>TRUE</c>, <c>FALSE</c> (case-insensitive)
+ * <br>Default: <c>FALSE</c>
+ */
+ private static final boolean LOG_ON_EXIT =
b(System.getProperty("juneau.annotationProvider.caching.logOnExit"));
+
+ /**
+ * Enable performance instrumentation for tracking method call counts.
+ *
+ * <p>
+ * System property: <c>juneau.annotationProvider.instrumentation</c>
+ * <br>Valid values: <c>TRUE</c>, <c>FALSE</c> (case-insensitive)
+ * <br>Default: <c>FALSE</c>
+ */
+ private static final boolean ENABLE_INSTRUMENTATION =
b(System.getProperty("juneau.annotationProvider.instrumentation"));
+
+ /**
+ * Enable new optimized code path for annotation lookups.
+ *
+ * <p>
+ * System property: <c>juneau.annotationProvider.useNewCode</c>
+ * <br>Valid values: <c>TRUE</c>, <c>FALSE</c> (case-insensitive)
+ * <br>Default: <c>FALSE</c>
+ */
+ private static final boolean ENABLE_NEW_CODE =
b(System.getProperty("juneau.annotationProvider.useNewCode"));
/**
* Default instance.
@@ -195,9 +241,6 @@ public class AnnotationProvider {
//-----------------------------------------------------------------------------------------------------------------
private static final Map<String, Long> methodCallCounts = new
java.util.concurrent.ConcurrentHashMap<>();
- private static final boolean ENABLE_INSTRUMENTATION =
Boolean.getBoolean("juneau.instrumentAnnotationProvider");
-// private static final boolean ENABLE_NEW_CODE =
Boolean.getBoolean("juneau.annotationProvider.enableNewCode");
- private static final boolean ENABLE_NEW_CODE = true;
static {
if (ENABLE_INSTRUMENTATION) {
@@ -252,11 +295,13 @@ public class AnnotationProvider {
* </ul>
*/
public static class Builder {
- boolean disableCaching;
+ CacheMode cacheMode;
+ boolean logOnExit;
ReflectionMap.Builder<Annotation> runtimeAnnotations =
ReflectionMap.create(Annotation.class);
Builder() {
- disableCaching = DISABLE_ANNOTATION_CACHING;
+ cacheMode = CACHING_MODE;
+ logOnExit = LOG_ON_EXIT;
}
/**
@@ -269,26 +314,42 @@ public class AnnotationProvider {
}
/**
- * Disables annotation caching entirely.
+ * Sets the caching mode for annotation lookups.
*
* <p>
- * When disabled, annotation lookups will always perform fresh
searches without caching results.
+ * Available modes:
+ * <ul>
+ * <li><c>NONE</c> - Disables all caching (always
recompute)
+ * <li><c>WEAK</c> - Uses WeakHashMap (allows GC of cached
entries)
+ * <li><c>FULL</c> - Uses ConcurrentHashMap (best
performance)
+ * </ul>
+ *
+ * @param value The caching mode.
+ * @return This object for method chaining.
+ */
+ public Builder cacheMode(CacheMode value) {
+ cacheMode = value;
+ return this;
+ }
+
+ /**
+ * Enables logging of cache statistics on JVM shutdown.
*
* @return This object for method chaining.
*/
- public Builder disableCaching() {
- disableCaching = true;
+ public Builder logOnExit() {
+ logOnExit = true;
return this;
}
/**
- * Conditionally disables or enables annotation caching.
+ * Conditionally enables logging of cache statistics on JVM
shutdown.
*
- * @param value Whether to disable caching.
+ * @param value Whether to log on exit.
* @return This object for method chaining.
*/
- public Builder disableCaching(boolean value) {
- disableCaching = value;
+ public Builder logOnExit(boolean value) {
+ logOnExit = value;
return this;
}
@@ -352,11 +413,11 @@ public class AnnotationProvider {
* .value(MySwap.<jk>class</jk>)
* .build();
*
- * <jc>// Add all runtime annotations to the provider</jc>
- * AnnotationProvider <jv>provider</jv> = AnnotationProvider
- * .<jsm>create</jsm>()
- * .addRuntimeAnnotations(<jv>beanAnnotation</jv>,
<jv>multiAnnotation</jv>, <jv>stringAnnotation</jv>, <jv>swapAnnotation</jv>)
- * .build();
+ * <jc>// Add all runtime annotations to the provider</jc>
+ * AnnotationProvider <jv>provider</jv> = AnnotationProvider
+ * .<jsm>create</jsm>()
+ * .addRuntimeAnnotations(<jv>beanAnnotation</jv>,
<jv>multiAnnotation</jv>, <jv>stringAnnotation</jv>, <jv>swapAnnotation</jv>)
+ * .build();
* </p>
*
* <p>
@@ -456,26 +517,41 @@ public class AnnotationProvider {
* @param builder The builder containing configuration settings.
*/
protected AnnotationProvider(Builder builder) {
- this.classRuntimeAnnotations =
Cache.<Class<?>,List<AnnotationInfo<Annotation>>>create()
+ var classCache =
Cache.<Class<?>,List<AnnotationInfo<Annotation>>>create()
.supplier(this::findClassRuntimeAnnotations)
- .disableCaching(builder.disableCaching)
- .build();
- this.methodRuntimeAnnotations =
Cache.<Method,List<AnnotationInfo<Annotation>>>create()
+ .cacheMode(builder.cacheMode);
+ if (builder.logOnExit)
+
classCache.logOnExit("AnnotationProvider.classRuntimeAnnotations");
+ this.classRuntimeAnnotations = classCache.build();
+
+ var methodCache =
Cache.<Method,List<AnnotationInfo<Annotation>>>create()
.supplier(this::findMethodRuntimeAnnotations)
- .disableCaching(builder.disableCaching)
- .build();
- this.fieldRuntimeAnnotations =
Cache.<Field,List<AnnotationInfo<Annotation>>>create()
+ .cacheMode(builder.cacheMode);
+ if (builder.logOnExit)
+
methodCache.logOnExit("AnnotationProvider.methodRuntimeAnnotations");
+ this.methodRuntimeAnnotations = methodCache.build();
+
+ var fieldCache =
Cache.<Field,List<AnnotationInfo<Annotation>>>create()
.supplier(this::findFieldRuntimeAnnotations)
- .disableCaching(builder.disableCaching)
- .build();
- this.constructorRuntimeAnnotations =
Cache.<Constructor<?>,List<AnnotationInfo<Annotation>>>create()
+ .cacheMode(builder.cacheMode);
+ if (builder.logOnExit)
+
fieldCache.logOnExit("AnnotationProvider.fieldRuntimeAnnotations");
+ this.fieldRuntimeAnnotations = fieldCache.build();
+
+ var constructorCache =
Cache.<Constructor<?>,List<AnnotationInfo<Annotation>>>create()
.supplier(this::findConstructorRuntimeAnnotations)
- .disableCaching(builder.disableCaching)
- .build();
- this.cache =
Cache3.<Class<?>,ElementInfo,AnnotationTraversal[],List>create()
+ .cacheMode(builder.cacheMode);
+ if (builder.logOnExit)
+
constructorCache.logOnExit("AnnotationProvider.constructorRuntimeAnnotations");
+ this.constructorRuntimeAnnotations = constructorCache.build();
+
+ var cache3 =
Cache3.<Class<?>,ElementInfo,AnnotationTraversal[],List>create()
.supplier(this::findCached)
- .disableCaching(builder.disableCaching)
- .build();
+ .cacheMode(builder.cacheMode);
+ if (builder.logOnExit)
+ cache3.logOnExit("AnnotationProvider.cache");
+ this.cache = cache3.build();
+
this.annotationMap = builder.runtimeAnnotations.build();
}
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/utils/MimeTypeDetector.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/utils/MimeTypeDetector.java
index e10de92b86..478b3783cc 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/utils/MimeTypeDetector.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/utils/MimeTypeDetector.java
@@ -16,6 +16,7 @@
*/
package org.apache.juneau.common.utils;
+import static org.apache.juneau.common.collections.CacheMode.*;
import static org.apache.juneau.common.utils.AssertionUtils.*;
import static org.apache.juneau.common.utils.FileUtils.*;
import static org.apache.juneau.common.utils.Utils.*;
@@ -75,7 +76,7 @@ public class MimeTypeDetector {
private final Map<String,String> fileMap = new
ConcurrentHashMap<>();
private boolean nioContentBasedDetection = true;
private int cacheSize = 1000;
- private boolean cacheDisabled = false;
+ private CacheMode cacheMode = FULL;
private boolean cacheLogOnExit = false;
private String defaultType = "application/octet-stream";
@@ -132,13 +133,21 @@ public class MimeTypeDetector {
}
/**
- * Enables or disables the cache.
+ * Sets the caching mode for MIME type lookups.
*
- * @param value Whether to disable the cache.
+ * <p>
+ * Available modes:
+ * <ul>
+ * <li>{@link CacheMode#NONE NONE} - No caching (always
recompute)
+ * <li>{@link CacheMode#WEAK WEAK} - Weak caching (uses
{@link java.util.WeakHashMap})
+ * <li>{@link CacheMode#FULL FULL} - Full caching (uses
{@link java.util.concurrent.ConcurrentHashMap}, default)
+ * </ul>
+ *
+ * @param value The caching mode.
* @return This builder.
*/
- public Builder setCacheDisabled(boolean value) {
- cacheDisabled = value;
+ public Builder setCacheMode(CacheMode value) {
+ cacheMode = value;
return this;
}
@@ -257,11 +266,10 @@ public class MimeTypeDetector {
this.defaultType = builder.defaultType;
// Create cache for file-based lookups
- var cacheBuilder = Cache.of(String.class,
String.class).maxSize(builder.cacheSize);
+ var cacheBuilder = Cache.of(String.class, String.class)
+ .maxSize(builder.cacheSize)
+ .cacheMode(builder.cacheMode);
- if (builder.cacheDisabled) {
- cacheBuilder.disableCaching();
- }
if (builder.cacheLogOnExit) {
cacheBuilder.logOnExit("MimeTypeDetector");
}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache2_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache2_Test.java
index 8af66c587c..793a1cb370 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache2_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache2_Test.java
@@ -16,6 +16,8 @@
*/
package org.apache.juneau.common.collections;
+import static org.apache.juneau.common.collections.CacheMode.*;
+
import static org.junit.jupiter.api.Assertions.*;
import static org.apache.juneau.junit.bct.BctAssertions.*;
@@ -171,7 +173,7 @@ class Cache2_Test extends TestBase {
var defaultCallCount = new AtomicInteger();
var overrideCallCount = new AtomicInteger();
var x = Cache2.of(String.class, Integer.class, String.class)
- .disableCaching()
+ .cacheMode(NONE)
.supplier((k1, k2) -> {
defaultCallCount.incrementAndGet();
return k1 + ":" + k2;
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache3_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache3_Test.java
index 8981e63a14..d34df21009 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache3_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache3_Test.java
@@ -16,6 +16,8 @@
*/
package org.apache.juneau.common.collections;
+import static org.apache.juneau.common.collections.CacheMode.*;
+
import static org.junit.jupiter.api.Assertions.*;
import static org.apache.juneau.junit.bct.BctAssertions.*;
@@ -75,7 +77,7 @@ class Cache3_Test extends TestBase {
void a04_disableCaching() {
var callCount = new AtomicInteger();
var x = Cache3.of(String.class, String.class, Integer.class,
String.class)
- .disableCaching()
+ .cacheMode(NONE)
.supplier((k1, k2, k3) -> {
callCount.incrementAndGet();
return "value";
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache4_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache4_Test.java
index 59dd58254e..41005643fe 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache4_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache4_Test.java
@@ -16,6 +16,8 @@
*/
package org.apache.juneau.common.collections;
+import static org.apache.juneau.common.collections.CacheMode.*;
+
import static org.junit.jupiter.api.Assertions.*;
import static org.apache.juneau.junit.bct.BctAssertions.*;
@@ -76,7 +78,7 @@ class Cache4_Test extends TestBase {
void a04_disableCaching() {
var callCount = new AtomicInteger();
var x = Cache4.of(String.class, String.class, String.class,
Integer.class, String.class)
- .disableCaching()
+ .cacheMode(NONE)
.supplier((k1, k2, k3, k4) -> {
callCount.incrementAndGet();
return "value";
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache5_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache5_Test.java
index 0075a83093..696ea8df47 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache5_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache5_Test.java
@@ -16,6 +16,8 @@
*/
package org.apache.juneau.common.collections;
+import static org.apache.juneau.common.collections.CacheMode.*;
+
import static org.junit.jupiter.api.Assertions.*;
import static org.apache.juneau.junit.bct.BctAssertions.*;
@@ -77,7 +79,7 @@ class Cache5_Test extends TestBase {
void a04_disableCaching() {
var callCount = new AtomicInteger();
var x = Cache5.of(String.class, String.class, String.class,
String.class, Integer.class, String.class)
- .disableCaching()
+ .cacheMode(NONE)
.supplier((k1, k2, k3, k4, k5) -> {
callCount.incrementAndGet();
return "value";
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache_Test.java
index 4954cca8c4..954858ce09 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache_Test.java
@@ -16,6 +16,8 @@
*/
package org.apache.juneau.common.collections;
+import static org.apache.juneau.common.collections.CacheMode.*;
+
import static org.apache.juneau.junit.bct.BctAssertions.*;
import static org.junit.jupiter.api.Assertions.*;
@@ -199,7 +201,7 @@ class Cache_Test extends TestBase {
@Test void a10_disabled_neverCaches() {
var cache = Cache.of(String.class, String.class)
- .disableCaching()
+ .cacheMode(NONE)
.build();
var callCount = new AtomicInteger();
@@ -222,7 +224,7 @@ class Cache_Test extends TestBase {
@Test void a11_disabled_sizeAlwaysZero() {
var cache = Cache.of(String.class, Integer.class)
- .disableCaching()
+ .cacheMode(NONE)
.build();
cache.get("one", () -> 1);
@@ -234,7 +236,7 @@ class Cache_Test extends TestBase {
@Test void a12_disabled_clearHasNoEffect() {
var cache = Cache.of(String.class, Integer.class)
- .disableCaching()
+ .cacheMode(NONE)
.build();
cache.clear(); // Should not throw
@@ -256,7 +258,7 @@ class Cache_Test extends TestBase {
@Test void a14_builder_chaining() {
var cache = Cache.of(String.class, String.class)
.maxSize(100)
- .disableCaching()
+ .cacheMode(NONE)
.build();
// Disabled takes precedence
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/utils/MimeTypeDetector_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/utils/MimeTypeDetector_Test.java
index 5866d5a2d1..cfd6a491ad 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/common/utils/MimeTypeDetector_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/utils/MimeTypeDetector_Test.java
@@ -21,6 +21,7 @@ import static org.junit.jupiter.api.Assertions.*;
import java.io.*;
import java.nio.file.*;
+import org.apache.juneau.common.collections.*;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.io.*;
@@ -142,7 +143,7 @@ public class MimeTypeDetector_Test {
@Test
public void testSetCacheDisabled() {
var detector = MimeTypeDetector.builder()
- .setCacheDisabled(true)
+ .setCacheMode(CacheMode.NONE)
.addExtensionType("test", "application/x-test")
.build();
@@ -371,7 +372,7 @@ public class MimeTypeDetector_Test {
@Test
public void testCacheDisabled() {
var detector = MimeTypeDetector.builder()
- .setCacheDisabled(true)
+ .setCacheMode(CacheMode.NONE)
.addExtensionType("test", "application/x-test")
.build();
@@ -405,7 +406,7 @@ public class MimeTypeDetector_Test {
.addExtensionType("custom", "application/x-custom")
.addNioContentBasedDetection(false)
.setCacheSize(100)
- .setCacheDisabled(false)
+ .setCacheMode(CacheMode.FULL)
.setCacheLogOnExit(true)
.setDefaultType("application/unknown")
.addTypes("text/html html htm")