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

ben-manes / caffeine / #5156

03 Dec 2025 03:21AM UTC coverage: 0.0% (-100.0%) from 100.0%
#5156

push

github

ben-manes
add loading type to parameterized test dimensions to reduce task size

0 of 3834 branches covered (0.0%)

0 of 7848 relevant lines covered (0.0%)

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.net.URI;
22
import java.net.URL;
23
import java.util.ArrayList;
24
import java.util.Collections;
25
import java.util.Enumeration;
26
import java.util.HashMap;
27
import java.util.Map;
28
import java.util.Properties;
29
import java.util.WeakHashMap;
30

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

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

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

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

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

66
  boolean isOsgiComponent;
67

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

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

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

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

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

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

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

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

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

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

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

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

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

160
  private URI getManagerUri(URI uri) {
161
    return (uri == null) ? getDefaultURI() : uri;
×
162
  }
163

164
  private ClassLoader getManagerClassLoader(ClassLoader classLoader) {
165
    return (classLoader == null) ? getDefaultClassLoader() : classLoader;
×
166
  }
167

168
  /**
169
   * A {@link ClassLoader} that combines {@code Thread.currentThread().getContextClassLoader()}
170
   * and {@code getClass().getClassLoader()}.
171
   */
172
  static class JCacheClassLoader extends ClassLoader {
173

174
    public JCacheClassLoader(@Nullable ClassLoader parent) {
175
      super(parent);
×
176
    }
×
177

178
    @Override
179
    public Class<?> loadClass(String name) throws ClassNotFoundException {
180
      @Var ClassNotFoundException error = null;
×
181

182
      ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
×
183
      if ((contextClassLoader != null) && (contextClassLoader != DEFAULT_CLASS_LOADER)) {
×
184
        try {
185
          return contextClassLoader.loadClass(name);
×
186
        } catch (ClassNotFoundException e) {
×
187
          error = e;
×
188
        }
189
      }
190

191
      ClassLoader classClassLoader = getClassClassLoader();
×
192
      if ((classClassLoader != null) && (classClassLoader != contextClassLoader)) {
×
193
        try {
194
          return classClassLoader.loadClass(name);
×
195
        } catch (ClassNotFoundException e) {
×
196
          error = e;
×
197
        }
198
      }
199

200
      ClassLoader parentClassLoader = getParent();
×
201
      if ((parentClassLoader != null)
×
202
          && (parentClassLoader != classClassLoader)
203
          && (parentClassLoader != contextClassLoader)) {
204
        try {
205
          return parentClassLoader.loadClass(name);
×
206
        } catch (ClassNotFoundException e) {
×
207
          error = e;
×
208
        }
209
      }
210
      throw (error == null) ? new ClassNotFoundException(name) : error;
×
211
    }
212

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

223
      ClassLoader classClassLoader = getClassClassLoader();
×
224
      if ((classClassLoader != null) && (classClassLoader != contextClassLoader)) {
×
225
        URL resource = classClassLoader.getResource(name);
×
226
        if (resource != null) {
×
227
          return resource;
×
228
        }
229
      }
230

231
      ClassLoader parentClassLoader = getParent();
×
232
      if ((parentClassLoader != null)
×
233
          && (parentClassLoader != classClassLoader)
234
          && (parentClassLoader != contextClassLoader)) {
235
        return parentClassLoader.getResource(name);
×
236
      }
237

238
      return null;
×
239
    }
240

241
    @Override
242
    public Enumeration<URL> getResources(String name) throws IOException {
243
      var resources = new ArrayList<URL>();
×
244

245
      ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
×
246
      if ((contextClassLoader != null) && contextClassLoader != DEFAULT_CLASS_LOADER) {
×
247
        resources.addAll(Collections.list(contextClassLoader.getResources(name)));
×
248
      }
249

250
      ClassLoader classClassLoader = getClassClassLoader();
×
251
      if ((classClassLoader != null) && (classClassLoader != contextClassLoader)) {
×
252
        resources.addAll(Collections.list(classClassLoader.getResources(name)));
×
253
      }
254

255
      ClassLoader parentClassLoader = getParent();
×
256
      if ((parentClassLoader != null)
×
257
          && (parentClassLoader != classClassLoader)
258
          && (parentClassLoader != contextClassLoader)) {
259
        resources.addAll(Collections.list(parentClassLoader.getResources(name)));
×
260
      }
261

262
      return Collections.enumeration(resources);
×
263
    }
264

265
    @Nullable ClassLoader getClassClassLoader() {
266
      return getClass().getClassLoader();
×
267
    }
268
  }
269

270
  @Activate
271
  @SuppressWarnings("unused")
272
  private void activate() {
273
    isOsgiComponent = true;
×
274
  }
×
275
}
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