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

ben-manes / caffeine / #3896

pending completion
#3896

push

github-actions

ben-manes
upgrade jamm library (memory meter)

7542 of 7616 relevant lines covered (99.03%)

0.99 hits per line

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

92.55
/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.List;
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.checkerframework.checker.nullness.qual.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.concurrent.GuardedBy;
43

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

60
  @GuardedBy("itself")
61
  final Map<ClassLoader, Map<URI, CacheManager>> cacheManagers;
62

63
  boolean isOsgiComponent;
64

65
  public CaffeineCachingProvider() {
1✔
66
    this.cacheManagers = new WeakHashMap<>(1);
1✔
67
  }
1✔
68

69
  @Override
70
  public ClassLoader getDefaultClassLoader() {
71
    return DEFAULT_CLASS_LOADER;
1✔
72
  }
73

74
  @Override
75
  public URI getDefaultURI() {
76
    return URI.create(getClass().getName());
1✔
77
  }
78

79
  @Override
80
  public Properties getDefaultProperties() {
81
    return new Properties();
1✔
82
  }
83

84
  @Override
85
  public CacheManager getCacheManager() {
86
    return getCacheManager(getDefaultURI(), getDefaultClassLoader());
1✔
87
  }
88

89
  @Override
90
  public CacheManager getCacheManager(URI uri, ClassLoader classLoader) {
91
    return getCacheManager(uri, classLoader, getDefaultProperties());
1✔
92
  }
93

94
  @Override
95
  public CacheManager getCacheManager(URI uri, ClassLoader classLoader, Properties properties) {
96
    URI managerURI = getManagerUri(uri);
1✔
97
    ClassLoader managerClassLoader = getManagerClassLoader(classLoader);
1✔
98

99
    synchronized (cacheManagers) {
1✔
100
      Map<URI, CacheManager> cacheManagersByURI = cacheManagers.computeIfAbsent(
1✔
101
          managerClassLoader, any -> new HashMap<>());
1✔
102
      return cacheManagersByURI.computeIfAbsent(managerURI, any -> {
1✔
103
        Properties managerProperties = (properties == null) ? getDefaultProperties() : properties;
1✔
104
        return new CacheManagerImpl(this, isOsgiComponent,
1✔
105
            managerURI, managerClassLoader, managerProperties);
106
      });
107
    }
108
  }
109

110
  @Override
111
  public void close() {
112
    synchronized (cacheManagers) {
1✔
113
      for (ClassLoader classLoader : new ArrayList<>(cacheManagers.keySet())) {
1✔
114
        close(classLoader);
1✔
115
      }
1✔
116
    }
1✔
117
  }
1✔
118

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

133
  @Override
134
  @SuppressWarnings("PMD.CloseResource")
135
  public void close(URI uri, ClassLoader classLoader) {
136
    synchronized (cacheManagers) {
1✔
137
      ClassLoader managerClassLoader = getManagerClassLoader(classLoader);
1✔
138
      Map<URI, CacheManager> cacheManagersByURI = cacheManagers.get(managerClassLoader);
1✔
139

140
      if (cacheManagersByURI != null) {
1✔
141
        CacheManager cacheManager = cacheManagersByURI.remove(getManagerUri(uri));
1✔
142
        if (cacheManager != null) {
1✔
143
          cacheManager.close();
1✔
144
        }
145
        if (cacheManagersByURI.isEmpty()) {
1✔
146
          cacheManagers.remove(managerClassLoader);
1✔
147
        }
148
      }
149
    }
1✔
150
  }
1✔
151

152
  @Override
153
  public boolean isSupported(OptionalFeature optionalFeature) {
154
    return (optionalFeature == STORE_BY_REFERENCE);
1✔
155
  }
156

157
  private URI getManagerUri(URI uri) {
158
    return (uri == null) ? getDefaultURI() : uri;
1✔
159
  }
160

161
  private ClassLoader getManagerClassLoader(ClassLoader classLoader) {
162
    return (classLoader == null) ? getDefaultClassLoader() : classLoader;
1✔
163
  }
164

165
  /**
166
   * A {@link ClassLoader} that combines {@code Thread.currentThread().getContextClassLoader()}
167
   * and {@code getClass().getClassLoader()}.
168
   */
169
  private static final class JCacheClassLoader extends ClassLoader {
170

171
    public JCacheClassLoader() {
172
      super(Thread.currentThread().getContextClassLoader());
1✔
173
    }
1✔
174

175
    @Override
176
    public Class<?> loadClass(String name) throws ClassNotFoundException {
177
      ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
1✔
178
      ClassNotFoundException error = null;
1✔
179
      if ((contextClassLoader != null) && (contextClassLoader != DEFAULT_CLASS_LOADER)) {
1✔
180
        try {
181
          return contextClassLoader.loadClass(name);
1✔
182
        } catch (ClassNotFoundException e) {
1✔
183
          error = e;
1✔
184
        }
185
      }
186

187
      ClassLoader classClassLoader = getClass().getClassLoader();
1✔
188
      if ((classClassLoader != null) && (classClassLoader != contextClassLoader)) {
1✔
189
        try {
190
          return classClassLoader.loadClass(name);
1✔
191
        } catch (ClassNotFoundException e) {
1✔
192
          error = e;
1✔
193
        }
194
      }
195

196
      ClassLoader parentClassLoader = getParent();
1✔
197
      if ((parentClassLoader != null)
1✔
198
          && (parentClassLoader != classClassLoader)
199
          && (parentClassLoader != contextClassLoader)) {
200
        try {
201
          return parentClassLoader.loadClass(name);
×
202
        } catch (ClassNotFoundException e) {
×
203
          error = e;
×
204
        }
205
      }
206
      throw (error == null) ? new ClassNotFoundException(name) : error;
1✔
207
    }
208

209
    @Override
210
    public @Nullable URL getResource(String name) {
211
      ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
1✔
212
      if ((contextClassLoader != null) && (contextClassLoader != DEFAULT_CLASS_LOADER)) {
1✔
213
        URL resource = contextClassLoader.getResource(name);
1✔
214
        if (resource != null) {
1✔
215
          return resource;
1✔
216
        }
217
      }
218

219
      ClassLoader classClassLoader = getClass().getClassLoader();
1✔
220
      if ((classClassLoader != null) && (classClassLoader != contextClassLoader)) {
1✔
221
        URL resource = classClassLoader.getResource(name);
1✔
222
        if (resource != null) {
1✔
223
          return resource;
1✔
224
        }
225
      }
226

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

237
      return null;
1✔
238
    }
239

240
    @Override
241
    public Enumeration<URL> getResources(String name) throws IOException {
242
      List<URL> resources = new ArrayList<>();
1✔
243

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

249
      ClassLoader classClassLoader = getClass().getClassLoader();
1✔
250
      if ((classClassLoader != null) && (classClassLoader != contextClassLoader)) {
1✔
251
        resources.addAll(Collections.list(classClassLoader.getResources(name)));
1✔
252
      }
253

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

261
      return Collections.enumeration(resources);
1✔
262
    }
263
  }
264

265
  @Activate
266
  @SuppressWarnings("unused")
267
  private void activate() {
268
    isOsgiComponent = true;
1✔
269
  }
1✔
270
}
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

© 2025 Coveralls, Inc