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

ben-manes / caffeine / #5173

29 Dec 2025 05:27AM UTC coverage: 0.0% (-100.0%) from 100.0%
#5173

push

github

ben-manes
speed up development ci build

0 of 3838 branches covered (0.0%)

0 of 7869 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/CacheManagerImpl.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;
17

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

20
import java.lang.ref.WeakReference;
21
import java.net.URI;
22
import java.util.ArrayList;
23
import java.util.Collection;
24
import java.util.Collections;
25
import java.util.Map;
26
import java.util.Properties;
27
import java.util.concurrent.ConcurrentHashMap;
28

29
import javax.cache.Cache;
30
import javax.cache.CacheException;
31
import javax.cache.CacheManager;
32
import javax.cache.configuration.CompleteConfiguration;
33
import javax.cache.configuration.Configuration;
34
import javax.cache.spi.CachingProvider;
35

36
import org.jspecify.annotations.Nullable;
37

38
/**
39
 * An implementation of JSR-107 {@link CacheManager} that manages Caffeine-based caches.
40
 *
41
 * @author ben.manes@gmail.com (Ben Manes)
42
 */
43
@SuppressWarnings("PMD.CloseResource")
44
public final class CacheManagerImpl implements CacheManager {
45
  final WeakReference<ClassLoader> classLoaderReference;
46
  final Map<String, CacheProxy<?, ?>> caches;
47
  final CachingProvider cacheProvider;
48
  final Properties properties;
49
  final Object lock;
50
  final URI uri;
51

52
  final boolean runsAsAnOsgiBundle;
53

54
  volatile boolean closed;
55

56
  public CacheManagerImpl(CachingProvider cacheProvider, boolean runsAsAnOsgiBundle,
57
      URI uri, ClassLoader classLoader, Properties properties) {
×
58
    this.classLoaderReference = new WeakReference<>(requireNonNull(classLoader));
×
59
    this.cacheProvider = requireNonNull(cacheProvider);
×
60
    this.runsAsAnOsgiBundle = runsAsAnOsgiBundle;
×
61
    this.properties = requireNonNull(properties);
×
62
    this.caches = new ConcurrentHashMap<>();
×
63
    this.uri = requireNonNull(uri);
×
64
    this.lock = new Object();
×
65
  }
×
66

67
  @Override
68
  public CachingProvider getCachingProvider() {
69
    return cacheProvider;
×
70
  }
71

72
  @Override
73
  public URI getURI() {
74
    return uri;
×
75
  }
76

77
  @Override
78
  public @Nullable ClassLoader getClassLoader() {
79
    return classLoaderReference.get();
×
80
  }
81

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

87
  @Override
88
  public <K, V, C extends Configuration<K, V>> Cache<K, V> createCache(
89
      String cacheName, C configuration) {
90
    ClassLoader old = Thread.currentThread().getContextClassLoader();
×
91
    try {
92
      if (runsAsAnOsgiBundle) {
×
93
        // override the context class loader with the CachingManager's classloader
94
        Thread.currentThread().setContextClassLoader(getClassLoader());
×
95
      }
96
      requireNotClosed();
×
97
      requireNonNull(configuration);
×
98

99
      CacheProxy<?, ?> cache = caches.compute(cacheName, (name, existing) -> {
×
100
        if (existing != null) {
×
101
          throw new CacheException("Cache " + cacheName + " already exists");
×
102
        } else if (CacheFactory.isDefinedExternally(this, cacheName)) {
×
103
          throw new CacheException("Cache " + cacheName + " is configured externally");
×
104
        }
105
        return CacheFactory.createCache(this, cacheName, configuration);
×
106
      });
107

108
      @SuppressWarnings("unchecked")
109
      var config = cache.getConfiguration(CompleteConfiguration.class);
×
110
      enableManagement(cache.getName(), config.isManagementEnabled());
×
111
      enableStatistics(cache.getName(), config.isStatisticsEnabled());
×
112

113
      @SuppressWarnings("unchecked")
114
      var castedCache = (Cache<K, V>) cache;
×
115
      return castedCache;
×
116
    } finally {
117
      Thread.currentThread().setContextClassLoader(old);
×
118
    }
119
  }
120

121
  @Override
122
  public <K, V> @Nullable Cache<K, V> getCache(
123
      String cacheName, Class<K> keyType, Class<V> valueType) {
124
    ClassLoader old = Thread.currentThread().getContextClassLoader();
×
125
    try {
126
      if (runsAsAnOsgiBundle) {
×
127
        // override the context class loader with the CachingManager's classloader
128
        Thread.currentThread().setContextClassLoader(getClassLoader());
×
129
      }
130
      CacheProxy<K, V> cache = getCache(cacheName);
×
131
      if (cache == null) {
×
132
        return null;
×
133
      }
134
      requireNonNull(keyType);
×
135
      requireNonNull(valueType);
×
136

137
      @SuppressWarnings("unchecked")
138
      var config = cache.getConfiguration(CompleteConfiguration.class);
×
139
      if (keyType != config.getKeyType()) {
×
140
        throw new ClassCastException("Incompatible cache key types specified, expected "
×
141
            + config.getKeyType() + " but " + keyType + " was specified");
×
142
      } else if (valueType != config.getValueType()) {
×
143
        throw new ClassCastException("Incompatible cache value types specified, expected "
×
144
            + config.getValueType() + " but " + valueType + " was specified");
×
145
      }
146
      return cache;
×
147
    } finally {
148
      Thread.currentThread().setContextClassLoader(old);
×
149
    }
150
  }
151

152
  @Override
153
  public <K, V> @Nullable CacheProxy<K, V> getCache(String cacheName) {
154
    ClassLoader old = Thread.currentThread().getContextClassLoader();
×
155
    try {
156
      if (runsAsAnOsgiBundle) {
×
157
        // override the context class loader with the CachingManager's classloader
158
        Thread.currentThread().setContextClassLoader(getClassLoader());
×
159
      }
160
      requireNonNull(cacheName);
×
161
      requireNotClosed();
×
162

163
      CacheProxy<?, ?> cache = caches.computeIfAbsent(cacheName, name -> {
×
164
        CacheProxy<?, ?> created = CacheFactory.tryToCreateFromExternalSettings(this, name);
×
165
        if (created != null) {
×
166
          @SuppressWarnings("unchecked")
167
          var config = created.getConfiguration(CompleteConfiguration.class);
×
168
          created.enableManagement(config.isManagementEnabled());
×
169
          created.enableStatistics(config.isStatisticsEnabled());
×
170
        }
171
        return created;
×
172
      });
173

174
      @SuppressWarnings("unchecked")
175
      var castedCache = (CacheProxy<K, V>) cache;
×
176
      return castedCache;
×
177
    } finally {
178
      Thread.currentThread().setContextClassLoader(old);
×
179
    }
180
  }
181

182
  @Override
183
  public Collection<String> getCacheNames() {
184
    requireNotClosed();
×
185
    return Collections.unmodifiableCollection(new ArrayList<>(caches.keySet()));
×
186
  }
187

188
  @Override
189
  public void destroyCache(String cacheName) {
190
    requireNotClosed();
×
191

192
    Cache<?, ?> cache = caches.remove(cacheName);
×
193
    if (cache != null) {
×
194
      cache.close();
×
195
    }
196
  }
×
197

198
  @Override
199
  public void enableManagement(String cacheName, boolean enabled) {
200
    requireNotClosed();
×
201

202
    CacheProxy<?, ?> cache = caches.get(cacheName);
×
203
    if (cache == null) {
×
204
      return;
×
205
    }
206
    cache.enableManagement(enabled);
×
207
  }
×
208

209
  @Override
210
  public void enableStatistics(String cacheName, boolean enabled) {
211
    requireNotClosed();
×
212

213
    CacheProxy<?, ?> cache = caches.get(cacheName);
×
214
    if (cache == null) {
×
215
      return;
×
216
    }
217
    cache.enableStatistics(enabled);
×
218
  }
×
219

220
  @Override
221
  public void close() {
222
    if (isClosed()) {
×
223
      return;
×
224
    }
225
    synchronized (lock) {
×
226
      if (!isClosed()) {
×
227
        cacheProvider.close(uri, classLoaderReference.get());
×
228
        for (Cache<?, ?> cache : caches.values()) {
×
229
          cache.close();
×
230
        }
×
231
        closed = true;
×
232
      }
233
    }
×
234
  }
×
235

236
  @Override
237
  public boolean isClosed() {
238
    return closed;
×
239
  }
240

241
  @Override
242
  public <T> T unwrap(Class<T> clazz) {
243
    if (clazz.isInstance(this)) {
×
244
      return clazz.cast(this);
×
245
    }
246
    throw new IllegalArgumentException("Unwrapping to " + clazz
×
247
        + " is not a supported by this implementation");
248
  }
249

250
  /** Checks that the cache manager is not closed. */
251
  private void requireNotClosed() {
252
    if (isClosed()) {
×
253
      throw new IllegalStateException();
×
254
    }
255
  }
×
256
}
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