Skip to content

Commit 83fa8e1

Browse files
jhoellercbeams
authored andcommitted
Add initial support for JCache-compliant providers
Issue: SPR-8774
1 parent 86fabb2 commit 83fa8e1

File tree

5 files changed

+320
-0
lines changed

5 files changed

+320
-0
lines changed

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ project('spring-context') {
217217
exclude group: 'org.slf4j', module: 'slf4j-api'
218218
}
219219
compile("joda-time:joda-time:1.6", optional)
220+
compile("javax.cache:cache-api:0.5", optional)
220221
compile("net.sf.ehcache:ehcache-core:2.0.0", optional)
221222
compile("org.slf4j:slf4j-api:1.6.1", optional)
222223
compile("org.codehaus.jsr166-mirror:jsr166:1.7.0", provided)
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright 2002-2012 the original author or authors.
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+
17+
package org.springframework.cache.jcache;
18+
19+
import java.io.Serializable;
20+
21+
import javax.cache.Status;
22+
23+
import org.springframework.cache.Cache;
24+
import org.springframework.cache.support.SimpleValueWrapper;
25+
import org.springframework.util.Assert;
26+
27+
/**
28+
* {@link org.springframework.cache.Cache} implementation on top of a
29+
* {@link javax.cache.Cache} instance.
30+
*
31+
* @author Juergen Hoeller
32+
* @since 3.2
33+
*/
34+
public class JCacheCache implements Cache {
35+
36+
private static final Object NULL_HOLDER = new NullHolder();
37+
38+
@SuppressWarnings("rawtypes")
39+
private final javax.cache.Cache cache;
40+
41+
private final boolean allowNullValues;
42+
43+
44+
/**
45+
* Create an {@link org.springframework.cache.jcache.JCacheCache} instance.
46+
* @param jcache backing JCache Cache instance
47+
*/
48+
public JCacheCache(javax.cache.Cache<?,?> jcache) {
49+
this(jcache, true);
50+
}
51+
52+
/**
53+
* Create an {@link org.springframework.cache.jcache.JCacheCache} instance.
54+
* @param jcache backing JCache Cache instance
55+
* @param allowNullValues whether to accept and convert null values for this cache
56+
*/
57+
public JCacheCache(javax.cache.Cache<?,?> jcache, boolean allowNullValues) {
58+
Assert.notNull(jcache, "Cache must not be null");
59+
Status status = jcache.getStatus();
60+
Assert.isTrue(Status.STARTED.equals(status),
61+
"A 'started' cache is required - current cache is " + status.toString());
62+
this.cache = jcache;
63+
this.allowNullValues = allowNullValues;
64+
}
65+
66+
67+
public String getName() {
68+
return this.cache.getName();
69+
}
70+
71+
public javax.cache.Cache<?,?> getNativeCache() {
72+
return this.cache;
73+
}
74+
75+
public boolean isAllowNullValues() {
76+
return this.allowNullValues;
77+
}
78+
79+
@SuppressWarnings("unchecked")
80+
public ValueWrapper get(Object key) {
81+
Object value = this.cache.get(key);
82+
return (value != null ? new SimpleValueWrapper(fromStoreValue(value)) : null);
83+
}
84+
85+
@SuppressWarnings("unchecked")
86+
public void put(Object key, Object value) {
87+
this.cache.put(key, toStoreValue(value));
88+
}
89+
90+
@SuppressWarnings("unchecked")
91+
public void evict(Object key) {
92+
this.cache.remove(key);
93+
}
94+
95+
public void clear() {
96+
this.cache.removeAll();
97+
}
98+
99+
100+
/**
101+
* Convert the given value from the internal store to a user value
102+
* returned from the get method (adapting <code>null</code>).
103+
* @param storeValue the store value
104+
* @return the value to return to the user
105+
*/
106+
protected Object fromStoreValue(Object storeValue) {
107+
if (this.allowNullValues && storeValue == NULL_HOLDER) {
108+
return null;
109+
}
110+
return storeValue;
111+
}
112+
113+
/**
114+
* Convert the given user value, as passed into the put method,
115+
* to a value in the internal store (adapting <code>null</code>).
116+
* @param userValue the given user value
117+
* @return the value to store
118+
*/
119+
protected Object toStoreValue(Object userValue) {
120+
if (this.allowNullValues && userValue == null) {
121+
return NULL_HOLDER;
122+
}
123+
return userValue;
124+
}
125+
126+
127+
@SuppressWarnings("serial")
128+
private static class NullHolder implements Serializable {
129+
}
130+
131+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright 2002-2012 the original author or authors.
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+
17+
package org.springframework.cache.jcache;
18+
19+
import java.util.Collection;
20+
import java.util.LinkedHashSet;
21+
22+
import javax.cache.Status;
23+
24+
import org.springframework.cache.Cache;
25+
import org.springframework.cache.support.AbstractCacheManager;
26+
import org.springframework.util.Assert;
27+
28+
/**
29+
* {@link org.springframework.cache.CacheManager} implementation
30+
* backed by a JCache {@link javax.cache.CacheManager}.
31+
*
32+
* @author Juergen Hoeller
33+
* @since 3.2
34+
*/
35+
public class JCacheCacheManager extends AbstractCacheManager {
36+
37+
private javax.cache.CacheManager cacheManager;
38+
39+
private boolean allowNullValues = true;
40+
41+
42+
/**
43+
* Set the backing JCache {@link javax.cache.CacheManager}.
44+
*/
45+
public void setCacheManager(javax.cache.CacheManager cacheManager) {
46+
this.cacheManager = cacheManager;
47+
}
48+
49+
/**
50+
* Return the backing JCache {@link javax.cache.CacheManager}.
51+
*/
52+
public javax.cache.CacheManager getCacheManager() {
53+
return this.cacheManager;
54+
}
55+
56+
/**
57+
* Specify whether to accept and convert null values for all caches
58+
* in this cache manager.
59+
* <p>Default is "true", despite JSR-107 itself not supporting null values.
60+
* An internal holder object will be used to store user-level null values.
61+
*/
62+
public void setAllowNullValues(boolean allowNullValues) {
63+
this.allowNullValues = allowNullValues;
64+
}
65+
66+
/**
67+
* Return whether this cache manager accepts and converts null values
68+
* for all of its caches.
69+
*/
70+
public boolean isAllowNullValues() {
71+
return this.allowNullValues;
72+
}
73+
74+
75+
@Override
76+
protected Collection<Cache> loadCaches() {
77+
Assert.notNull(this.cacheManager, "A backing CacheManager is required");
78+
Status status = this.cacheManager.getStatus();
79+
Assert.isTrue(Status.STARTED.equals(status),
80+
"A 'started' JCache CacheManager is required - current cache is " + status.toString());
81+
82+
Collection<Cache> caches = new LinkedHashSet<Cache>();
83+
for (javax.cache.Cache<?,?> jcache : this.cacheManager.getCaches()) {
84+
caches.add(new JCacheCache(jcache, this.allowNullValues));
85+
}
86+
return caches;
87+
}
88+
89+
@Override
90+
public Cache getCache(String name) {
91+
Cache cache = super.getCache(name);
92+
if (cache == null) {
93+
// check the JCache cache again
94+
// (in case the cache was added at runtime)
95+
javax.cache.Cache<?,?> jcache = this.cacheManager.getCache(name);
96+
if (jcache != null) {
97+
cache = new JCacheCache(jcache, this.allowNullValues);
98+
addCache(cache);
99+
}
100+
}
101+
return cache;
102+
}
103+
104+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2002-2012 the original author or authors.
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+
17+
package org.springframework.cache.jcache;
18+
19+
import javax.cache.CacheManager;
20+
import javax.cache.Caching;
21+
22+
import org.springframework.beans.factory.BeanClassLoaderAware;
23+
import org.springframework.beans.factory.FactoryBean;
24+
import org.springframework.beans.factory.InitializingBean;
25+
26+
/**
27+
* {@link FactoryBean} for a JCache {@link javax.cache.CacheManager},
28+
* obtaining a pre-defined CacheManager by name through the standard
29+
* JCache {@link javax.cache.Caching} class.
30+
*
31+
* @author Juergen Hoeller
32+
* @since 3.2
33+
* @see javax.cache.Caching#getCacheManager()
34+
* @see javax.cache.Caching#getCacheManager(String)
35+
*/
36+
public class JCacheManagerFactoryBean implements FactoryBean<CacheManager>, BeanClassLoaderAware, InitializingBean {
37+
38+
private String cacheManagerName = Caching.DEFAULT_CACHE_MANAGER_NAME;
39+
40+
private ClassLoader beanClassLoader;
41+
42+
private CacheManager cacheManager;
43+
44+
45+
/**
46+
* Specify the name of the desired CacheManager.
47+
* Default is JCache's default.
48+
* @see Caching#DEFAULT_CACHE_MANAGER_NAME
49+
*/
50+
public void setCacheManagerName(String cacheManagerName) {
51+
this.cacheManagerName = cacheManagerName;
52+
}
53+
54+
public void setBeanClassLoader(ClassLoader classLoader) {
55+
this.beanClassLoader = classLoader;
56+
}
57+
58+
public void afterPropertiesSet() {
59+
this.cacheManager = (this.beanClassLoader != null ?
60+
Caching.getCacheManager(this.beanClassLoader, this.cacheManagerName) :
61+
Caching.getCacheManager(this.cacheManagerName));
62+
}
63+
64+
65+
public CacheManager getObject() {
66+
return this.cacheManager;
67+
}
68+
69+
public Class<?> getObjectType() {
70+
return (this.cacheManager != null ? this.cacheManager.getClass() : CacheManager.class);
71+
}
72+
73+
public boolean isSingleton() {
74+
return true;
75+
}
76+
77+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* Implementation package for JSR-107 (javax.cache aka "JCache") based caches.
3+
* Provides a {@link org.springframework.cache.CacheManager CacheManager}
4+
* and {@link org.springframework.cache.Cache Cache} implementation for
5+
* use in a Spring context, using a JSR-107 compliant cache provider.
6+
*/
7+
package org.springframework.cache.jcache;

0 commit comments

Comments
 (0)