• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ben-manes / caffeine / #5612

11 Jul 2026 03:47PM UTC coverage: 71.292% (-28.7%) from 100.0%
#5612

push

github

ben-manes
Preserve timestamps on a raced same-instance refresh

The automatic refreshIfNeeded path checked for an equal-value reload
before the ABA/ownership check and returned without preserving the
timestamps, so a reload completing after a concurrent put(k,
sameInstance) did a full update — shifting the entry's expiration
forward by the reload's in-flight duration and stomping the write.
Mirror the explicit-refresh fix: check ownership first. An owned
reload installs the value (refreshing metadata even for a same
instance), while a raced reload preserves the write's timestamps and
only notifies REPLACED when the value differs.

2957 of 4134 branches covered (71.53%)

3 of 3 new or added lines in 1 file covered. (100.0%)

2408 existing lines in 53 files now uncovered.

5980 of 8388 relevant lines covered (71.29%)

0.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/jcache/src/main/java/com/github/benmanes/caffeine/jcache/configuration/CaffeineConfiguration.java
1
/*
2
 * Copyright 2015 Ben Manes. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package com.github.benmanes.caffeine.jcache.configuration;
17

18
import static java.util.Objects.requireNonNull;
19

20
import java.util.Iterator;
21
import java.util.Objects;
22
import java.util.Optional;
23
import java.util.OptionalLong;
24
import java.util.Spliterator;
25
import java.util.concurrent.Executor;
26
import java.util.concurrent.ForkJoinPool;
27

28
import javax.cache.configuration.CacheEntryListenerConfiguration;
29
import javax.cache.configuration.CompleteConfiguration;
30
import javax.cache.configuration.Factory;
31
import javax.cache.configuration.MutableConfiguration;
32
import javax.cache.expiry.ExpiryPolicy;
33
import javax.cache.integration.CacheLoader;
34
import javax.cache.integration.CacheWriter;
35

36
import org.jspecify.annotations.NullMarked;
37
import org.jspecify.annotations.Nullable;
38

39
import com.github.benmanes.caffeine.cache.Expiry;
40
import com.github.benmanes.caffeine.cache.Scheduler;
41
import com.github.benmanes.caffeine.cache.Ticker;
42
import com.github.benmanes.caffeine.cache.Weigher;
43
import com.github.benmanes.caffeine.jcache.copy.Copier;
44
import com.github.benmanes.caffeine.jcache.copy.JavaSerializationCopier;
45
import com.google.errorprone.annotations.CanIgnoreReturnValue;
46

47
/**
48
 * A JCache configuration with Caffeine specific settings.
49
 * <p>
50
 * The initial settings disable <code>store by value</code> so that entries are not copied when
51
 * crossing the {@link javax.cache.Cache} API boundary. If enabled and the {@link Copier} is not
52
 * explicitly set, then the {@link JavaSerializationCopier} will be used. This differs from
53
 * {@link MutableConfiguration} which enables <code>store by value</code> at construction.
54
 *
55
 * @author ben.manes@gmail.com (Ben Manes)
56
 */
57
@NullMarked
58
public final class CaffeineConfiguration<K, V> implements CompleteConfiguration<K, V> {
UNCOV
59
  private static final Factory<Scheduler> DISABLED_SCHEDULER = Scheduler::disabledScheduler;
×
UNCOV
60
  private static final Factory<Copier> JAVA_COPIER = JavaSerializationCopier::new;
×
UNCOV
61
  private static final Factory<Executor> COMMON_POOL = ForkJoinPool::commonPool;
×
UNCOV
62
  private static final Factory<Ticker> SYSTEM_TICKER = Ticker::systemTicker;
×
63
  private static final long serialVersionUID = 1L;
64

65
  private final MutableConfiguration<K, V> delegate;
66
  private final boolean readOnly;
67

68
  private @Nullable Factory<Weigher<K, V>> weigherFactory;
69
  private @Nullable Factory<Expiry<K, V>> expiryFactory;
70

71
  private Factory<Scheduler> schedulerFactory;
72
  private Factory<Executor> executorFactory;
73
  private Factory<Copier> copierFactory;
74
  private Factory<Ticker> tickerFactory;
75

76
  private @Nullable Long refreshAfterWriteNanos;
77
  private @Nullable Long expireAfterAccessNanos;
78
  private @Nullable Long expireAfterWriteNanos;
79
  private @Nullable Long maximumWeight;
80
  private @Nullable Long maximumSize;
81
  private boolean nativeStatistics;
82

UNCOV
83
  public CaffeineConfiguration() {
×
UNCOV
84
    delegate = new MutableConfiguration<>();
×
UNCOV
85
    delegate.setStoreByValue(false);
×
UNCOV
86
    schedulerFactory = DISABLED_SCHEDULER;
×
UNCOV
87
    tickerFactory = SYSTEM_TICKER;
×
UNCOV
88
    executorFactory = COMMON_POOL;
×
UNCOV
89
    copierFactory = JAVA_COPIER;
×
UNCOV
90
    readOnly = false;
×
UNCOV
91
  }
×
92

93
  /** Returns a modifiable copy of the configuration. */
94
  public CaffeineConfiguration(CompleteConfiguration<K, V> configuration) {
UNCOV
95
    this(configuration, /* readOnly= */ false);
×
UNCOV
96
  }
×
97

UNCOV
98
  private CaffeineConfiguration(CompleteConfiguration<K, V> configuration, boolean readOnly) {
×
UNCOV
99
    delegate = new MutableConfiguration<>(configuration);
×
UNCOV
100
    if (configuration instanceof CaffeineConfiguration<?, ?>) {
×
UNCOV
101
      var config = (CaffeineConfiguration<K, V>) configuration;
×
UNCOV
102
      refreshAfterWriteNanos = config.refreshAfterWriteNanos;
×
UNCOV
103
      expireAfterAccessNanos = config.expireAfterAccessNanos;
×
UNCOV
104
      expireAfterWriteNanos = config.expireAfterWriteNanos;
×
UNCOV
105
      nativeStatistics = config.nativeStatistics;
×
UNCOV
106
      schedulerFactory = config.schedulerFactory;
×
UNCOV
107
      executorFactory = config.executorFactory;
×
UNCOV
108
      expiryFactory = config.expiryFactory;
×
UNCOV
109
      copierFactory = config.copierFactory;
×
UNCOV
110
      tickerFactory = config.tickerFactory;
×
UNCOV
111
      weigherFactory = config.weigherFactory;
×
UNCOV
112
      maximumWeight = config.maximumWeight;
×
UNCOV
113
      maximumSize = config.maximumSize;
×
UNCOV
114
    } else {
×
UNCOV
115
      schedulerFactory = DISABLED_SCHEDULER;
×
UNCOV
116
      tickerFactory = SYSTEM_TICKER;
×
UNCOV
117
      executorFactory = COMMON_POOL;
×
UNCOV
118
      copierFactory = JAVA_COPIER;
×
119
    }
UNCOV
120
    this.readOnly = readOnly;
×
UNCOV
121
  }
×
122

123
  /** Returns an unmodifiable copy of this configuration. */
124
  public CaffeineConfiguration<K, V> immutableCopy() {
UNCOV
125
    return new CaffeineConfiguration<>(this, /* readOnly= */ true);
×
126
  }
127

128
  private void checkIfReadOnly() {
UNCOV
129
    if (readOnly) {
×
UNCOV
130
      throw new UnsupportedOperationException();
×
131
    }
UNCOV
132
  }
×
133

134
  @Override
135
  public Class<K> getKeyType() {
UNCOV
136
    return delegate.getKeyType();
×
137
  }
138

139
  @Override
140
  public Class<V> getValueType() {
UNCOV
141
    return delegate.getValueType();
×
142
  }
143

144
  /** See {@link MutableConfiguration#setTypes}. */
145
  @CanIgnoreReturnValue
146
  public CaffeineConfiguration<K, V> setTypes(Class<K> keyType, Class<V> valueType) {
UNCOV
147
    checkIfReadOnly();
×
UNCOV
148
    delegate.setTypes(keyType, valueType);
×
UNCOV
149
    return this;
×
150
  }
151

152
  @Override
153
  public Iterable<CacheEntryListenerConfiguration<K, V>> getCacheEntryListenerConfigurations() {
UNCOV
154
    return new UnmodifiableIterable<>(delegate.getCacheEntryListenerConfigurations());
×
155
  }
156

157
  /** See {@link MutableConfiguration#addCacheEntryListenerConfiguration}. */
158
  @CanIgnoreReturnValue
159
  public CaffeineConfiguration<K, V> addCacheEntryListenerConfiguration(
160
      CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration) {
UNCOV
161
    checkIfReadOnly();
×
UNCOV
162
    delegate.addCacheEntryListenerConfiguration(cacheEntryListenerConfiguration);
×
UNCOV
163
    return this;
×
164
  }
165

166
  /** See {@link MutableConfiguration#removeCacheEntryListenerConfiguration}. */
167
  @CanIgnoreReturnValue
168
  public CaffeineConfiguration<K, V> removeCacheEntryListenerConfiguration(
169
      CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration) {
UNCOV
170
    checkIfReadOnly();
×
UNCOV
171
    delegate.removeCacheEntryListenerConfiguration(cacheEntryListenerConfiguration);
×
UNCOV
172
    return this;
×
173
  }
174

175
  @Override
176
  public @Nullable Factory<CacheLoader<K, V>> getCacheLoaderFactory() {
UNCOV
177
    return delegate.getCacheLoaderFactory();
×
178
  }
179

180
  /** See {@link MutableConfiguration#setCacheLoaderFactory}. */
181
  @CanIgnoreReturnValue
182
  public CaffeineConfiguration<K, V> setCacheLoaderFactory(
183
      @Nullable Factory<? extends CacheLoader<K, V>> factory) {
UNCOV
184
    checkIfReadOnly();
×
UNCOV
185
    delegate.setCacheLoaderFactory(factory);
×
UNCOV
186
    return this;
×
187
  }
188

189
  @Override
190
  public @Nullable Factory<CacheWriter<? super K, ? super V>> getCacheWriterFactory() {
UNCOV
191
    return delegate.getCacheWriterFactory();
×
192
  }
193

194
  /** Returns a writer created by the configured factory or null if not set. */
195
  public @Nullable CacheWriter<K , V> getCacheWriter() {
UNCOV
196
    var factory = delegate.getCacheWriterFactory();
×
UNCOV
197
    if (factory != null) {
×
198
      @SuppressWarnings("unchecked")
UNCOV
199
      var writer = (CacheWriter<K, V>) factory.create();
×
UNCOV
200
      return writer;
×
201
    }
UNCOV
202
    return null;
×
203
  }
204

205
  /** Returns if the cache writer factory is specified. */
206
  public boolean hasCacheWriter() {
UNCOV
207
    return getCacheWriterFactory() != null;
×
208
  }
209

210
  /** See {@link MutableConfiguration#setCacheWriterFactory}. */
211
  @CanIgnoreReturnValue
212
  public CaffeineConfiguration<K, V> setCacheWriterFactory(
213
      @Nullable Factory<? extends CacheWriter<? super K, ? super V>> factory) {
UNCOV
214
    checkIfReadOnly();
×
UNCOV
215
    delegate.setCacheWriterFactory(factory);
×
UNCOV
216
    return this;
×
217
  }
218

219
  @Override
220
  public Factory<ExpiryPolicy> getExpiryPolicyFactory() {
UNCOV
221
    return delegate.getExpiryPolicyFactory();
×
222
  }
223

224
  /** See {@link MutableConfiguration#setExpiryPolicyFactory}. */
225
  @CanIgnoreReturnValue
226
  public CaffeineConfiguration<K, V> setExpiryPolicyFactory(
227
      @Nullable Factory<? extends ExpiryPolicy> factory) {
UNCOV
228
    checkIfReadOnly();
×
UNCOV
229
    delegate.setExpiryPolicyFactory(factory);
×
UNCOV
230
    return this;
×
231
  }
232

233
  @Override
234
  public boolean isReadThrough() {
UNCOV
235
    return delegate.isReadThrough();
×
236
  }
237

238
  /** See {@link MutableConfiguration#setReadThrough}. */
239
  @CanIgnoreReturnValue
240
  public CaffeineConfiguration<K, V> setReadThrough(boolean isReadThrough) {
UNCOV
241
    checkIfReadOnly();
×
UNCOV
242
    delegate.setReadThrough(isReadThrough);
×
UNCOV
243
    return this;
×
244
  }
245

246
  @Override
247
  public boolean isWriteThrough() {
UNCOV
248
    return delegate.isWriteThrough();
×
249
  }
250

251
  /** See {@link MutableConfiguration#setWriteThrough}. */
252
  @CanIgnoreReturnValue
253
  public CaffeineConfiguration<K, V> setWriteThrough(boolean isWriteThrough) {
UNCOV
254
    checkIfReadOnly();
×
UNCOV
255
    delegate.setWriteThrough(isWriteThrough);
×
UNCOV
256
    return this;
×
257
  }
258

259
  @Override
260
  public boolean isStoreByValue() {
UNCOV
261
    return delegate.isStoreByValue();
×
262
  }
263

264
  /** See {@link MutableConfiguration#setStoreByValue}. */
265
  @CanIgnoreReturnValue
266
  public CaffeineConfiguration<K, V> setStoreByValue(boolean isStoreByValue) {
UNCOV
267
    checkIfReadOnly();
×
UNCOV
268
    delegate.setStoreByValue(isStoreByValue);
×
UNCOV
269
    return this;
×
270
  }
271

272
  /**
273
   * Checks whether native statistics collection is enabled in this cache.
274
   * <p>
275
   * The default value is <code>false</code>.
276
   *
277
   * @return true if native statistics collection is enabled
278
   */
279
  public boolean isNativeStatisticsEnabled() {
UNCOV
280
    return nativeStatistics;
×
281
  }
282

283
  /**
284
   * Sets whether native statistics gathering is enabled on a cache.
285
   *
286
   * @param enabled true to enable native statistics, false to disable.
287
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
288
   */
289
  @CanIgnoreReturnValue
290
  public CaffeineConfiguration<K, V> setNativeStatisticsEnabled(boolean enabled) {
UNCOV
291
    checkIfReadOnly();
×
UNCOV
292
    this.nativeStatistics = enabled;
×
UNCOV
293
    return this;
×
294
  }
295

296
  @Override
297
  public boolean isStatisticsEnabled() {
UNCOV
298
    return delegate.isStatisticsEnabled();
×
299
  }
300

301
  /** See {@link MutableConfiguration#setStatisticsEnabled}. */
302
  @CanIgnoreReturnValue
303
  public CaffeineConfiguration<K, V> setStatisticsEnabled(boolean enabled) {
UNCOV
304
    checkIfReadOnly();
×
UNCOV
305
    delegate.setStatisticsEnabled(enabled);
×
UNCOV
306
    return this;
×
307
  }
308

309
  /** See {@link CompleteConfiguration#isManagementEnabled}. */
310
  @Override
311
  public boolean isManagementEnabled() {
UNCOV
312
    return delegate.isManagementEnabled();
×
313
  }
314

315
  /** See {@link MutableConfiguration#setManagementEnabled}. */
316
  @CanIgnoreReturnValue
317
  public CaffeineConfiguration<K, V> setManagementEnabled(boolean enabled) {
UNCOV
318
    checkIfReadOnly();
×
UNCOV
319
    delegate.setManagementEnabled(enabled);
×
UNCOV
320
    return this;
×
321
  }
322

323
  /**
324
   * Returns the {@link Factory} for the {@link Copier} to be used for the cache.
325
   *
326
   * @return the {@link Factory} for the {@link Copier}
327
   */
328
  public Factory<Copier> getCopierFactory() {
UNCOV
329
    return copierFactory;
×
330
  }
331

332
  /**
333
   * Set the {@link Factory} for the {@link Copier}.
334
   *
335
   * @param factory the {@link Copier} {@link Factory}
336
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
337
   */
338
  @CanIgnoreReturnValue
339
  public CaffeineConfiguration<K, V> setCopierFactory(Factory<Copier> factory) {
UNCOV
340
    checkIfReadOnly();
×
UNCOV
341
    copierFactory = requireNonNull(factory);
×
UNCOV
342
    return this;
×
343
  }
344

345
  /**
346
   * Returns the {@link Factory} for the {@link Scheduler} to be used for the cache.
347
   *
348
   * @return the {@link Factory} for the {@link Scheduler}
349
   */
350
  public Factory<Scheduler> getSchedulerFactory() {
UNCOV
351
    return schedulerFactory;
×
352
  }
353

354
  /**
355
   * Set the {@link Factory} for the {@link Scheduler}.
356
   *
357
   * @param factory the {@link Scheduler} {@link Factory}
358
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
359
   */
360
  @CanIgnoreReturnValue
361
  public CaffeineConfiguration<K, V> setSchedulerFactory(Factory<Scheduler> factory) {
UNCOV
362
    checkIfReadOnly();
×
UNCOV
363
    schedulerFactory = requireNonNull(factory);
×
UNCOV
364
    return this;
×
365
  }
366

367
  /**
368
   * Returns the {@link Factory} for the {@link Ticker} to be used for the cache.
369
   *
370
   * @return the {@link Factory} for the {@link Ticker}
371
   */
372
  public Factory<Ticker> getTickerFactory() {
UNCOV
373
    return tickerFactory;
×
374
  }
375

376
  /**
377
   * Set the {@link Factory} for the {@link Ticker}.
378
   *
379
   * @param factory the {@link Ticker} {@link Factory}
380
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
381
   */
382
  @CanIgnoreReturnValue
383
  public CaffeineConfiguration<K, V> setTickerFactory(Factory<Ticker> factory) {
UNCOV
384
    checkIfReadOnly();
×
UNCOV
385
    tickerFactory = requireNonNull(factory);
×
UNCOV
386
    return this;
×
387
  }
388

389
  /**
390
   * Returns the {@link Factory} for the {@link Executor} to be used for the cache.
391
   *
392
   * @return the {@link Factory} for the {@link Executor}
393
   */
394
  public Factory<Executor> getExecutorFactory() {
UNCOV
395
    return executorFactory;
×
396
  }
397

398
  /**
399
   * Set the {@link Factory} for the {@link Executor}.
400
   *
401
   * @param factory the {@link Executor} {@link Factory}
402
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
403
   */
404
  @CanIgnoreReturnValue
405
  public CaffeineConfiguration<K, V> setExecutorFactory(Factory<Executor> factory) {
UNCOV
406
    checkIfReadOnly();
×
UNCOV
407
    executorFactory = requireNonNull(factory);
×
UNCOV
408
    return this;
×
409
  }
410

411
  /**
412
   * Returns the refresh after write in nanoseconds.
413
   *
414
   * @return the duration in nanoseconds
415
   */
416
  public OptionalLong getRefreshAfterWrite() {
UNCOV
417
    return (refreshAfterWriteNanos == null)
×
UNCOV
418
        ? OptionalLong.empty()
×
UNCOV
419
        : OptionalLong.of(refreshAfterWriteNanos);
×
420
  }
421

422
  /**
423
   * Set the refresh after write in nanoseconds.
424
   *
425
   * @param refreshAfterWriteNanos the duration in nanoseconds
426
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
427
   */
428
  @CanIgnoreReturnValue
429
  @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
430
  public CaffeineConfiguration<K, V> setRefreshAfterWrite(OptionalLong refreshAfterWriteNanos) {
UNCOV
431
    checkIfReadOnly();
×
UNCOV
432
    this.refreshAfterWriteNanos = refreshAfterWriteNanos.isPresent()
×
UNCOV
433
        ? refreshAfterWriteNanos.getAsLong()
×
UNCOV
434
        : null;
×
UNCOV
435
    return this;
×
436
  }
437

438
  /**
439
   * Returns the expire after write in nanoseconds.
440
   *
441
   * @return the duration in nanoseconds
442
   */
443
  public OptionalLong getExpireAfterWrite() {
UNCOV
444
    return (expireAfterWriteNanos == null)
×
UNCOV
445
        ? OptionalLong.empty()
×
UNCOV
446
        : OptionalLong.of(expireAfterWriteNanos);
×
447
  }
448

449
  /**
450
   * Set the expire after write in nanoseconds.
451
   *
452
   * @param expireAfterWriteNanos the duration in nanoseconds
453
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
454
   */
455
  @CanIgnoreReturnValue
456
  @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
457
  public CaffeineConfiguration<K, V> setExpireAfterWrite(OptionalLong expireAfterWriteNanos) {
UNCOV
458
    checkIfReadOnly();
×
UNCOV
459
    this.expireAfterWriteNanos = expireAfterWriteNanos.isPresent()
×
UNCOV
460
        ? expireAfterWriteNanos.getAsLong()
×
UNCOV
461
        : null;
×
UNCOV
462
    return this;
×
463
  }
464

465
  /**
466
   * Returns the expire after access in nanoseconds.
467
   *
468
   * @return the duration in nanoseconds
469
   */
470
  public OptionalLong getExpireAfterAccess() {
UNCOV
471
    return (expireAfterAccessNanos == null)
×
UNCOV
472
        ? OptionalLong.empty()
×
UNCOV
473
        : OptionalLong.of(expireAfterAccessNanos);
×
474
  }
475

476
  /**
477
   * Set the expire after write in nanoseconds.
478
   *
479
   * @param expireAfterAccessNanos the duration in nanoseconds
480
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
481
   */
482
  @CanIgnoreReturnValue
483
  @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
484
  public CaffeineConfiguration<K, V> setExpireAfterAccess(OptionalLong expireAfterAccessNanos) {
UNCOV
485
    checkIfReadOnly();
×
UNCOV
486
    this.expireAfterAccessNanos = expireAfterAccessNanos.isPresent()
×
UNCOV
487
        ? expireAfterAccessNanos.getAsLong()
×
UNCOV
488
        : null;
×
UNCOV
489
    return this;
×
490
  }
491

492
  /**
493
   * Returns the {@link Factory} for the {@link Expiry} to be used for the cache.
494
   *
495
   * @return the {@link Factory} for the {@link Expiry}
496
   */
497
  public Optional<Factory<Expiry<K, V>>> getExpiryFactory() {
UNCOV
498
    return Optional.ofNullable(expiryFactory);
×
499
  }
500

501
  /**
502
   * Set the {@link Factory} for the {@link Expiry}.
503
   *
504
   * @param factory the {@link Expiry} {@link Factory}
505
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
506
   */
507
  @CanIgnoreReturnValue
508
  @SuppressWarnings({"OptionalUsedAsFieldOrParameterType", "unchecked"})
509
  public CaffeineConfiguration<K, V> setExpiryFactory(
510
      Optional<Factory<? extends Expiry<K, V>>> factory) {
UNCOV
511
    checkIfReadOnly();
×
UNCOV
512
    expiryFactory = (Factory<Expiry<K, V>>) factory.orElse(null);
×
UNCOV
513
    return this;
×
514
  }
515

516
  /**
517
   * Returns the maximum size to be used for the cache.
518
   *
519
   * @return the maximum size
520
   */
521
  public OptionalLong getMaximumSize() {
UNCOV
522
    return (maximumSize == null)
×
UNCOV
523
        ? OptionalLong.empty()
×
UNCOV
524
        : OptionalLong.of(maximumSize);
×
525
  }
526

527
  /**
528
   * Set the maximum size.
529
   *
530
   * @param maximumSize the maximum size
531
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
532
   */
533
  @CanIgnoreReturnValue
534
  @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
535
  public CaffeineConfiguration<K, V> setMaximumSize(OptionalLong maximumSize) {
UNCOV
536
    checkIfReadOnly();
×
UNCOV
537
    this.maximumSize = maximumSize.isPresent()
×
UNCOV
538
        ? maximumSize.getAsLong()
×
UNCOV
539
        : null;
×
UNCOV
540
    return this;
×
541
  }
542

543
  /**
544
   * Returns the maximum weight to be used for the cache.
545
   *
546
   * @return the maximum weight
547
   */
548
  public OptionalLong getMaximumWeight() {
UNCOV
549
    return (maximumWeight == null)
×
UNCOV
550
        ? OptionalLong.empty()
×
UNCOV
551
        : OptionalLong.of(maximumWeight);
×
552
  }
553

554
  /**
555
   * Set the maximum weight.
556
   *
557
   * @param maximumWeight the maximum weighted size
558
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
559
   */
560
  @CanIgnoreReturnValue
561
  @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
562
  public CaffeineConfiguration<K, V> setMaximumWeight(OptionalLong maximumWeight) {
UNCOV
563
    checkIfReadOnly();
×
UNCOV
564
    this.maximumWeight = maximumWeight.isPresent()
×
UNCOV
565
        ? maximumWeight.getAsLong()
×
UNCOV
566
        : null;
×
UNCOV
567
    return this;
×
568
  }
569

570
  /**
571
   * Returns the {@link Factory} for the {@link Weigher} to be used for the cache.
572
   *
573
   * @return the {@link Factory} for the {@link Weigher}
574
   */
575
  public Optional<Factory<Weigher<K, V>>> getWeigherFactory() {
UNCOV
576
    return Optional.ofNullable(weigherFactory);
×
577
  }
578

579
  /**
580
   * Set the {@link Factory} for the {@link Weigher}.
581
   *
582
   * @param factory the {@link Weigher} {@link Factory}
583
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
584
   */
585
  @CanIgnoreReturnValue
586
  @SuppressWarnings({"OptionalUsedAsFieldOrParameterType", "unchecked"})
587
  public CaffeineConfiguration<K, V> setWeigherFactory(
588
      Optional<Factory<? extends Weigher<K, V>>> factory) {
UNCOV
589
    checkIfReadOnly();
×
UNCOV
590
    weigherFactory = (Factory<Weigher<K, V>>) factory.orElse(null);
×
UNCOV
591
    return this;
×
592
  }
593

594
  @Override
595
  public boolean equals(@Nullable Object o) {
UNCOV
596
    if (o == this) {
×
UNCOV
597
      return true;
×
UNCOV
598
    } else if (!(o instanceof CaffeineConfiguration<?, ?>)) {
×
UNCOV
599
      return false;
×
600
    }
UNCOV
601
    var config = (CaffeineConfiguration<?, ?>) o;
×
UNCOV
602
    return (nativeStatistics == config.nativeStatistics)
×
UNCOV
603
        && Objects.equals(refreshAfterWriteNanos, config.refreshAfterWriteNanos)
×
UNCOV
604
        && Objects.equals(expireAfterAccessNanos, config.expireAfterAccessNanos)
×
UNCOV
605
        && Objects.equals(expireAfterWriteNanos, config.expireAfterWriteNanos)
×
UNCOV
606
        && Objects.equals(schedulerFactory, config.schedulerFactory)
×
UNCOV
607
        && Objects.equals(executorFactory, config.executorFactory)
×
UNCOV
608
        && Objects.equals(weigherFactory, config.weigherFactory)
×
UNCOV
609
        && Objects.equals(copierFactory, config.copierFactory)
×
UNCOV
610
        && Objects.equals(expiryFactory, config.expiryFactory)
×
UNCOV
611
        && Objects.equals(maximumWeight, config.maximumWeight)
×
UNCOV
612
        && Objects.equals(tickerFactory, config.tickerFactory)
×
UNCOV
613
        && Objects.equals(maximumSize, config.maximumSize)
×
UNCOV
614
        && delegate.equals(config.delegate);
×
615
  }
616

617
  @Override
618
  public int hashCode() {
UNCOV
619
    return Objects.hash(nativeStatistics, refreshAfterWriteNanos, expireAfterAccessNanos,
×
620
        expireAfterWriteNanos, schedulerFactory, executorFactory, weigherFactory, expiryFactory,
621
        copierFactory, maximumWeight, tickerFactory, maximumSize, delegate);
622
  }
623

624
  private static final class UnmodifiableIterable<E> implements Iterable<E> {
625
    private final Iterable<E> delegate;
626

UNCOV
627
    private UnmodifiableIterable(Iterable<E> delegate) {
×
UNCOV
628
      this.delegate = delegate;
×
UNCOV
629
    }
×
630
    @Override public Iterator<E> iterator() {
UNCOV
631
      var iterator = delegate.iterator();
×
UNCOV
632
      return new Iterator<>() {
×
633
        @Override public boolean hasNext() {
UNCOV
634
          return iterator.hasNext();
×
635
        }
636
        @Override public E next() {
UNCOV
637
          return iterator.next();
×
638
        }
639
      };
640
    }
641
    @Override public Spliterator<E> spliterator() {
UNCOV
642
      return delegate.spliterator();
×
643
    }
644
    @Override public String toString() {
UNCOV
645
      return delegate.toString();
×
646
    }
647
  }
648
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc