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

ben-manes / caffeine / #5651

18 Jul 2026 03:26AM UTC coverage: 66.303% (-33.7%) from 100.0%
#5651

push

github

ben-manes
dependency updates

2809 of 4164 branches covered (67.46%)

5584 of 8422 relevant lines covered (66.3%)

0.66 hits per line

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

0.0
/guava/src/main/java/com/github/benmanes/caffeine/guava/CaffeinatedGuavaLoadingCache.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.guava;
17

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

20
import java.io.Serializable;
21
import java.util.HashMap;
22
import java.util.Map;
23
import java.util.Set;
24
import java.util.concurrent.CompletableFuture;
25
import java.util.concurrent.ExecutionException;
26
import java.util.concurrent.Executor;
27

28
import org.jspecify.annotations.Nullable;
29

30
import com.github.benmanes.caffeine.cache.CacheLoader;
31
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
32
import com.google.common.cache.CacheLoader.UnsupportedLoadingOperationException;
33
import com.google.common.cache.LoadingCache;
34
import com.google.common.collect.ImmutableList;
35
import com.google.common.collect.ImmutableMap;
36
import com.google.common.util.concurrent.ExecutionError;
37
import com.google.common.util.concurrent.FutureCallback;
38
import com.google.common.util.concurrent.Futures;
39
import com.google.common.util.concurrent.ListenableFuture;
40
import com.google.common.util.concurrent.UncheckedExecutionException;
41

42
/**
43
 * A Caffeine-backed loading cache through a Guava facade.
44
 *
45
 * @author ben.manes@gmail.com (Ben Manes)
46
 */
47
@SuppressWarnings("serial")
48
final class CaffeinatedGuavaLoadingCache<K, V>
49
    extends CaffeinatedGuavaCache<K, V> implements LoadingCache<K, V> {
50
  private static final ThreadLocal<Boolean> nullBulkLoad = new ThreadLocal<>();
×
51
  private static final long serialVersionUID = 1L;
52

53
  private final com.github.benmanes.caffeine.cache.LoadingCache<K, V> cache;
54

55
  CaffeinatedGuavaLoadingCache(com.github.benmanes.caffeine.cache.LoadingCache<K, V> cache) {
56
    super(cache);
×
57
    this.cache = cache;
×
58
  }
×
59

60
  @Override
61
  @SuppressWarnings("PMD.PreserveStackTrace")
62
  public V get(K key) throws ExecutionException {
63
    requireNonNull(key);
×
64
    try {
65
      return cache.get(key);
×
66
    } catch (InvalidCacheLoadException e) {
×
67
      throw e;
×
68
    } catch (CacheLoaderException e) {
×
69
      throw new ExecutionException(e.getCause());
×
70
    } catch (RuntimeException e) {
×
71
      throw new UncheckedExecutionException(e);
×
72
    } catch (Error e) {
×
73
      throw new ExecutionError(e);
×
74
    }
75
  }
76

77
  @Override
78
  @SuppressWarnings({"CatchingUnchecked", "PMD.PreserveStackTrace"})
79
  public V getUnchecked(K key) {
80
    requireNonNull(key);
×
81
    try {
82
      return cache.get(key);
×
83
    } catch (InvalidCacheLoadException e) {
×
84
      throw e;
×
85
    } catch (CacheLoaderException e) {
×
86
      throw new UncheckedExecutionException(e.getCause());
×
87
    } catch (Exception e) {
×
88
      throw new UncheckedExecutionException(e);
×
89
    } catch (Error e) {
×
90
      throw new ExecutionError(e);
×
91
    }
92
  }
93

94
  @Override
95
  @SuppressWarnings({"CatchingUnchecked", "PMD.PreserveStackTrace"})
96
  public ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException {
97
    requireNonNull(keys);
×
98
    var keysToLoad = ImmutableList.copyOf(keys);
×
99
    try {
100
      Map<K, V> result = cache.getAll(keysToLoad);
×
101
      if (nullBulkLoad.get() != null) {
×
102
        throw new InvalidCacheLoadException("null key or value");
×
103
      }
104
      for (K key : keysToLoad) {
×
105
        if (!result.containsKey(key)) {
×
106
          throw new InvalidCacheLoadException("loadAll failed to return a value for " + key);
×
107
        }
108
      }
×
109
      return ImmutableMap.copyOf(result);
×
110
    } catch (InvalidCacheLoadException e) {
×
111
      throw e;
×
112
    } catch (CacheLoaderException e) {
×
113
      throw new ExecutionException(e.getCause());
×
114
    } catch (Exception e) {
×
115
      throw new UncheckedExecutionException(e);
×
116
    } catch (Error e) {
×
117
      throw new ExecutionError(e);
×
118
    } finally {
119
      nullBulkLoad.remove();
×
120
    }
121
  }
122

123
  @Override
124
  @SuppressWarnings("deprecation")
125
  public V apply(K key) {
126
    return getUnchecked(key);
×
127
  }
128

129
  @Override
130
  @SuppressWarnings("FutureReturnValueIgnored")
131
  public void refresh(K key) {
132
    cache.refresh(key);
×
133
  }
×
134

135
  abstract static class CaffeinatedLoader<K, V> implements CacheLoader<K, V>, Serializable {
136
    private static final long serialVersionUID = 1L;
137

138
    final com.google.common.cache.CacheLoader<K, V> cacheLoader;
139

140
    CaffeinatedLoader(com.google.common.cache.CacheLoader<K, V> cacheLoader) {
×
141
      this.cacheLoader = requireNonNull(cacheLoader);
×
142
    }
×
143
    @SuppressWarnings("ConstantValue")
144
    @Override public CompletableFuture<V> asyncReload(K key, V oldValue, Executor executor) {
145
      var future = new CompletableFuture<V>();
×
146
      try {
147
        ListenableFuture<V> reloader = cacheLoader.reload(key, oldValue);
×
148
        if (reloader == null) {
×
149
          future.completeExceptionally(new InvalidCacheLoadException("null future"));
×
150
        } else {
151
          Futures.addCallback(reloader, new FutureCompleter<>(future), Runnable::run);
×
152
        }
153
      } catch (Throwable t) {
×
154
        future.completeExceptionally(t);
×
155
      }
×
156
      return future;
×
157
    }
158
    /** Sequentially loads each missing entry. */
159
    @SuppressWarnings("PMD.SignatureDeclareThrowsException")
160
    Map<K, V> loadSequentially(Set<? extends K> keys) throws Exception {
161
      var result = new HashMap<K, V>(keys.size(), /* loadFactor= */ 1.0f);
×
162
      for (K key : keys) {
×
163
        result.put(key, load(key));
×
164
      }
×
165
      return result;
×
166
    }
167
  }
168

169
  static class InternalSingleLoader<K, V> extends CaffeinatedLoader<K, V> {
170
    private static final long serialVersionUID = 1L;
171

172
    InternalSingleLoader(com.google.common.cache.CacheLoader<K, V> cacheLoader) {
173
      super(cacheLoader);
×
174
    }
×
175
    @SuppressWarnings("ConstantValue")
176
    @Override public V load(K key) {
177
      try {
178
        V value = cacheLoader.load(key);
×
179
        if (value == null) {
×
180
          throw new InvalidCacheLoadException("null value");
×
181
        }
182
        return value;
×
183
      } catch (RuntimeException | Error e) {
×
184
        throw e;
×
185
      } catch (InterruptedException e) {
×
186
        Thread.currentThread().interrupt();
×
187
        throw new CacheLoaderException(e);
×
188
      } catch (Exception e) {
×
189
        throw new CacheLoaderException(e);
×
190
      }
191
    }
192
  }
193

194
  static final class InternalBulkLoader<K, V> extends InternalSingleLoader<K, V> {
195
    private static final long serialVersionUID = 1L;
196

197
    InternalBulkLoader(com.google.common.cache.CacheLoader<K, V> cacheLoader) {
198
      super(cacheLoader);
×
199
    }
×
200
    @SuppressWarnings("ConstantValue")
201
    @Override public Map<K, V> loadAll(Set<? extends K> keys) {
202
      try {
203
        Map<K, V> loaded;
204
        try {
205
          loaded = cacheLoader.loadAll(keys);
×
206
        } catch (UnsupportedLoadingOperationException e) {
×
207
          return loadSequentially(keys);
×
208
        }
×
209
        if (loaded == null) {
×
210
          throw new InvalidCacheLoadException("null map");
×
211
        }
212
        var result = new HashMap<K, V>(loaded.size(), /* loadFactor= */ 1.0f);
×
213
        loaded.forEach((key, value) -> {
×
214
          if ((key == null) || (value == null)) {
×
215
            nullBulkLoad.set(true);
×
216
          } else {
217
            result.put(key, value);
×
218
          }
219
        });
×
220
        return result;
×
221
      } catch (RuntimeException | Error e) {
×
222
        throw e;
×
223
      } catch (InterruptedException e) {
×
224
        Thread.currentThread().interrupt();
×
225
        throw new CacheLoaderException(e);
×
226
      } catch (Exception e) {
×
227
        throw new CacheLoaderException(e);
×
228
      }
229
    }
230
  }
231

232
  static class ExternalSingleLoader<K, V> extends CaffeinatedLoader<K, V> {
233
    private static final long serialVersionUID = 1L;
234

235
    ExternalSingleLoader(com.google.common.cache.CacheLoader<K, V> cacheLoader) {
236
      super(cacheLoader);
×
237
    }
×
238
    @SuppressWarnings("ConstantValue")
239
    @Override public V load(K key) throws Exception {
240
      V value = cacheLoader.load(key);
×
241
      if (value == null) {
×
242
        throw new InvalidCacheLoadException("null value");
×
243
      }
244
      return value;
×
245
    }
246
  }
247

248
  static final class ExternalBulkLoader<K, V> extends ExternalSingleLoader<K, V> {
249
    private static final long serialVersionUID = 1L;
250

251
    ExternalBulkLoader(com.google.common.cache.CacheLoader<K, V> cacheLoader) {
252
      super(cacheLoader);
×
253
    }
×
254
    @SuppressWarnings("ConstantValue")
255
    @Override public Map<K, V> loadAll(Set<? extends K> keys) throws Exception {
256
      Map<K, V> loaded;
257
      try {
258
        loaded = cacheLoader.loadAll(keys);
×
259
      } catch (UnsupportedLoadingOperationException e) {
×
260
        return loadSequentially(keys);
×
261
      }
×
262
      if (loaded == null) {
×
263
        throw new InvalidCacheLoadException("null map");
×
264
      }
265
      for (var value : loaded.values()) {
×
266
        if (value == null) {
×
267
          throw new InvalidCacheLoadException("null value");
×
268
        }
269
      }
×
270
      return loaded;
×
271
    }
272
  }
273

274
  static final class FutureCompleter<V> implements FutureCallback<V> {
275
    final CompletableFuture<V> future;
276

277
    FutureCompleter(CompletableFuture<V> future) {
×
278
      this.future = future;
×
279
    }
×
280
    @Override public void onSuccess(@Nullable V value) {
281
      if (value == null) {
×
282
        future.completeExceptionally(new InvalidCacheLoadException("null value"));
×
283
      } else {
284
        future.complete(value);
×
285
      }
286
    }
×
287
    @Override public void onFailure(Throwable t) {
288
      future.completeExceptionally(t);
×
289
    }
×
290
  }
291
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc