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

ben-manes / caffeine / #5707

02 Aug 2026 12:45AM UTC coverage: 0.106% (-99.9%) from 100.0%
#5707

push

github

ben-manes
fix wikibench trace reader after overly strict audit fixes

0 of 4235 branches covered (0.0%)

9 of 8528 relevant lines covered (0.11%)

0.0 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/spi/CaffeineCachingProvider.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.spi;
17

18
import static javax.cache.configuration.OptionalFeature.STORE_BY_REFERENCE;
19

20
import java.io.IOException;
21
import java.lang.ref.WeakReference;
22
import java.net.URI;
23
import java.net.URL;
24
import java.util.ArrayList;
25
import java.util.Collections;
26
import java.util.Enumeration;
27
import java.util.HashMap;
28
import java.util.Map;
29
import java.util.Properties;
30
import java.util.WeakHashMap;
31

32
import javax.cache.CacheManager;
33
import javax.cache.Caching;
34
import javax.cache.configuration.OptionalFeature;
35
import javax.cache.spi.CachingProvider;
36

37
import org.jspecify.annotations.NullMarked;
38
import org.jspecify.annotations.Nullable;
39
import org.osgi.service.component.annotations.Activate;
40
import org.osgi.service.component.annotations.Component;
41

42
import com.github.benmanes.caffeine.jcache.CacheManagerImpl;
43
import com.google.errorprone.annotations.Var;
44
import com.google.errorprone.annotations.concurrent.GuardedBy;
45

46
/**
47
 * A provider that produces a JCache implementation backed by Caffeine. Typically, this provider is
48
 * instantiated using {@link Caching#getCachingProvider()} which discovers this implementation
49
 * through a {@link java.util.ServiceLoader}.
50
 * <p>
51
 * This provider is expected to be used for application life cycle events, like initialization. It
52
 * is not expected that all requests flow through the provider to obtain the cache manager and cache
53
 * instances for request operations. Internally, this implementation is synchronized to avoid using
54
 * excess memory due to its infrequent usage.
55
 *
56
 * @author ben.manes@gmail.com (Ben Manes)
57
 */
58
@Component
59
@NullMarked
60
public final class CaffeineCachingProvider implements CachingProvider {
61
  private static final ClassLoader DEFAULT_CLASS_LOADER =
×
62
      new JCacheClassLoader(Thread.currentThread().getContextClassLoader());
×
63

64
  @GuardedBy("itself")
65
  private final Map<ClassLoader, Map<URI, CacheManager>> cacheManagers;
66

67
  boolean isOsgiComponent;
68

69
  public CaffeineCachingProvider() {
×
70
    this.cacheManagers = new WeakHashMap<>(1);
×
71
  }
×
72

73
  @Override
74
  public ClassLoader getDefaultClassLoader() {
75
    return DEFAULT_CLASS_LOADER;
×
76
  }
77

78
  @Override
79
  public URI getDefaultURI() {
80
    return URI.create(getClass().getName());
×
81
  }
82

83
  @Override
84
  public Properties getDefaultProperties() {
85
    return new Properties();
×
86
  }
87

88
  @Override
89
  public CacheManager getCacheManager() {
90
    return getCacheManager(getDefaultURI(), getDefaultClassLoader());
×
91
  }
92

93
  @Override
94
  public CacheManager getCacheManager(URI uri, ClassLoader classLoader) {
95
    return getCacheManager(uri, classLoader, getDefaultProperties());
×
96
  }
97

98
  @Override
99
  public CacheManager getCacheManager(URI uri,
100
      ClassLoader classLoader, @Nullable Properties properties) {
101
    URI managerUri = getManagerUri(uri);
×
102
    ClassLoader managerClassLoader = getManagerClassLoader(classLoader);
×
103

104
    synchronized (cacheManagers) {
×
105
      Map<URI, CacheManager> cacheManagersByUri = cacheManagers.computeIfAbsent(
×
106
          managerClassLoader, any -> new HashMap<>());
×
107
      return cacheManagersByUri.computeIfAbsent(managerUri, any -> {
×
108
        Properties managerProperties = (properties == null) ? getDefaultProperties() : properties;
×
109
        return new CacheManagerImpl(this, isOsgiComponent,
×
110
            managerUri, managerClassLoader, managerProperties);
111
      });
112
    }
113
  }
114

115
  @Override
116
  public void close() {
117
    synchronized (cacheManagers) {
×
118
      for (ClassLoader classLoader : new ArrayList<>(cacheManagers.keySet())) {
×
119
        close(classLoader);
×
120
      }
×
121
    }
×
122
  }
×
123

124
  @Override
125
  @SuppressWarnings("PMD.CloseResource")
126
  public void close(ClassLoader classLoader) {
127
    synchronized (cacheManagers) {
×
128
      ClassLoader managerClassLoader = getManagerClassLoader(classLoader);
×
129
      Map<URI, CacheManager> cacheManagersByUri = cacheManagers.remove(managerClassLoader);
×
130
      if (cacheManagersByUri != null) {
×
131
        for (CacheManager cacheManager : cacheManagersByUri.values()) {
×
132
          cacheManager.close();
×
133
        }
×
134
      }
135
    }
×
136
  }
×
137

138
  @Override
139
  @SuppressWarnings("PMD.CloseResource")
140
  public void close(URI uri, ClassLoader classLoader) {
141
    synchronized (cacheManagers) {
×
142
      ClassLoader managerClassLoader = getManagerClassLoader(classLoader);
×
143
      Map<URI, CacheManager> cacheManagersByUri = cacheManagers.get(managerClassLoader);
×
144

145
      if (cacheManagersByUri != null) {
×
146
        CacheManager cacheManager = cacheManagersByUri.remove(getManagerUri(uri));
×
147
        if (cacheManager != null) {
×
148
          cacheManager.close();
×
149
        }
150
        if (cacheManagersByUri.isEmpty()) {
×
151
          cacheManagers.remove(managerClassLoader);
×
152
        }
153
      }
154
    }
×
155
  }
×
156

157
  @Override
158
  public boolean isSupported(OptionalFeature optionalFeature) {
159
    return (optionalFeature == STORE_BY_REFERENCE);
×
160
  }
161

162
  private URI getManagerUri(@Nullable URI uri) {
163
    return (uri == null) ? getDefaultURI() : uri;
×
164
  }
165

166
  private ClassLoader getManagerClassLoader(@Nullable ClassLoader classLoader) {
167
    return (classLoader == null) ? getDefaultClassLoader() : classLoader;
×
168
  }
169

170
  /**
171
   * A {@link ClassLoader} that combines {@code Thread.currentThread().getContextClassLoader()}
172
   * and {@code getClass().getClassLoader()}.
173
   */
174
  static class JCacheClassLoader extends ClassLoader {
175
    final WeakReference<ClassLoader> parent;
176

177
    JCacheClassLoader(@Nullable ClassLoader parent) {
178
      super(/* parent= */ null);
×
179
      this.parent = new WeakReference<>(parent);
×
180
    }
×
181

182
    @Override
183
    public Class<?> loadClass(String name) throws ClassNotFoundException {
184
      @Var ClassNotFoundException error = null;
×
185

186
      ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
×
187
      if ((contextClassLoader != null) && (contextClassLoader != DEFAULT_CLASS_LOADER)) {
×
188
        try {
189
          return contextClassLoader.loadClass(name);
×
190
        } catch (ClassNotFoundException e) {
×
191
          error = e;
×
192
        }
193
      }
194

195
      ClassLoader classClassLoader = getClassClassLoader();
×
196
      if ((classClassLoader != null) && (classClassLoader != contextClassLoader)) {
×
197
        try {
198
          return classClassLoader.loadClass(name);
×
199
        } catch (ClassNotFoundException e) {
×
200
          error = e;
×
201
        }
202
      }
203

204
      ClassLoader parentClassLoader = parent.get();
×
205
      if ((parentClassLoader != null)
×
206
          && (parentClassLoader != classClassLoader)
207
          && (parentClassLoader != contextClassLoader)) {
208
        try {
209
          return parentClassLoader.loadClass(name);
×
210
        } catch (ClassNotFoundException e) {
×
211
          error = e;
×
212
        }
213
      }
214
      throw (error == null) ? new ClassNotFoundException(name) : error;
×
215
    }
216

217
    @Override
218
    public @Nullable URL getResource(String name) {
219
      ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
×
220
      if ((contextClassLoader != null) && (contextClassLoader != DEFAULT_CLASS_LOADER)) {
×
221
        URL resource = contextClassLoader.getResource(name);
×
222
        if (resource != null) {
×
223
          return resource;
×
224
        }
225
      }
226

227
      ClassLoader classClassLoader = getClassClassLoader();
×
228
      if ((classClassLoader != null) && (classClassLoader != contextClassLoader)) {
×
229
        URL resource = classClassLoader.getResource(name);
×
230
        if (resource != null) {
×
231
          return resource;
×
232
        }
233
      }
234

235
      ClassLoader parentClassLoader = parent.get();
×
236
      if ((parentClassLoader != null)
×
237
          && (parentClassLoader != classClassLoader)
238
          && (parentClassLoader != contextClassLoader)) {
239
        return parentClassLoader.getResource(name);
×
240
      }
241

242
      return null;
×
243
    }
244

245
    @Override
246
    public Enumeration<URL> getResources(String name) throws IOException {
247
      var resources = new ArrayList<URL>();
×
248

249
      ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
×
250
      if ((contextClassLoader != null) && contextClassLoader != DEFAULT_CLASS_LOADER) {
×
251
        resources.addAll(Collections.list(contextClassLoader.getResources(name)));
×
252
      }
253

254
      ClassLoader classClassLoader = getClassClassLoader();
×
255
      if ((classClassLoader != null) && (classClassLoader != contextClassLoader)) {
×
256
        resources.addAll(Collections.list(classClassLoader.getResources(name)));
×
257
      }
258

259
      ClassLoader parentClassLoader = parent.get();
×
260
      if ((parentClassLoader != null)
×
261
          && (parentClassLoader != classClassLoader)
262
          && (parentClassLoader != contextClassLoader)) {
263
        resources.addAll(Collections.list(parentClassLoader.getResources(name)));
×
264
      }
265

266
      return Collections.enumeration(resources);
×
267
    }
268

269
    @Nullable ClassLoader getClassClassLoader() {
270
      return getClass().getClassLoader();
×
271
    }
272
  }
273

274
  @Activate
275
  @SuppressWarnings("unused")
276
  private void activate() {
277
    isOsgiComponent = true;
×
278
  }
×
279
}
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