diff --git a/build.gradle b/build.gradle
index f70b755a316..f77c116a0ff 100644
--- a/build.gradle
+++ b/build.gradle
@@ -217,6 +217,7 @@ project('spring-context') {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
compile("joda-time:joda-time:1.6", optional)
+ compile("javax.cache:cache-api:0.5", optional)
compile("net.sf.ehcache:ehcache-core:2.0.0", optional)
compile("org.slf4j:slf4j-api:1.6.1", optional)
compile("org.codehaus.jsr166-mirror:jsr166:1.7.0", provided)
diff --git a/spring-context/src/main/java/org/springframework/cache/jcache/JCacheCache.java b/spring-context/src/main/java/org/springframework/cache/jcache/JCacheCache.java
new file mode 100644
index 00000000000..0e66d5ebe48
--- /dev/null
+++ b/spring-context/src/main/java/org/springframework/cache/jcache/JCacheCache.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cache.jcache;
+
+import java.io.Serializable;
+
+import javax.cache.Status;
+
+import org.springframework.cache.Cache;
+import org.springframework.cache.support.SimpleValueWrapper;
+import org.springframework.util.Assert;
+
+/**
+ * {@link org.springframework.cache.Cache} implementation on top of a
+ * {@link javax.cache.Cache} instance.
+ *
+ * @author Juergen Hoeller
+ * @since 3.2
+ */
+public class JCacheCache implements Cache {
+
+ private static final Object NULL_HOLDER = new NullHolder();
+
+ @SuppressWarnings("rawtypes")
+ private final javax.cache.Cache cache;
+
+ private final boolean allowNullValues;
+
+
+ /**
+ * Create an {@link org.springframework.cache.jcache.JCacheCache} instance.
+ * @param jcache backing JCache Cache instance
+ */
+ public JCacheCache(javax.cache.Cache,?> jcache) {
+ this(jcache, true);
+ }
+
+ /**
+ * Create an {@link org.springframework.cache.jcache.JCacheCache} instance.
+ * @param jcache backing JCache Cache instance
+ * @param allowNullValues whether to accept and convert null values for this cache
+ */
+ public JCacheCache(javax.cache.Cache,?> jcache, boolean allowNullValues) {
+ Assert.notNull(jcache, "Cache must not be null");
+ Status status = jcache.getStatus();
+ Assert.isTrue(Status.STARTED.equals(status),
+ "A 'started' cache is required - current cache is " + status.toString());
+ this.cache = jcache;
+ this.allowNullValues = allowNullValues;
+ }
+
+
+ public String getName() {
+ return this.cache.getName();
+ }
+
+ public javax.cache.Cache,?> getNativeCache() {
+ return this.cache;
+ }
+
+ public boolean isAllowNullValues() {
+ return this.allowNullValues;
+ }
+
+ @SuppressWarnings("unchecked")
+ public ValueWrapper get(Object key) {
+ Object value = this.cache.get(key);
+ return (value != null ? new SimpleValueWrapper(fromStoreValue(value)) : null);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void put(Object key, Object value) {
+ this.cache.put(key, toStoreValue(value));
+ }
+
+ @SuppressWarnings("unchecked")
+ public void evict(Object key) {
+ this.cache.remove(key);
+ }
+
+ public void clear() {
+ this.cache.removeAll();
+ }
+
+
+ /**
+ * Convert the given value from the internal store to a user value
+ * returned from the get method (adapting null).
+ * @param storeValue the store value
+ * @return the value to return to the user
+ */
+ protected Object fromStoreValue(Object storeValue) {
+ if (this.allowNullValues && storeValue == NULL_HOLDER) {
+ return null;
+ }
+ return storeValue;
+ }
+
+ /**
+ * Convert the given user value, as passed into the put method,
+ * to a value in the internal store (adapting null).
+ * @param userValue the given user value
+ * @return the value to store
+ */
+ protected Object toStoreValue(Object userValue) {
+ if (this.allowNullValues && userValue == null) {
+ return NULL_HOLDER;
+ }
+ return userValue;
+ }
+
+
+ @SuppressWarnings("serial")
+ private static class NullHolder implements Serializable {
+ }
+
+}
diff --git a/spring-context/src/main/java/org/springframework/cache/jcache/JCacheCacheManager.java b/spring-context/src/main/java/org/springframework/cache/jcache/JCacheCacheManager.java
new file mode 100644
index 00000000000..fe7212c145d
--- /dev/null
+++ b/spring-context/src/main/java/org/springframework/cache/jcache/JCacheCacheManager.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cache.jcache;
+
+import java.util.Collection;
+import java.util.LinkedHashSet;
+
+import javax.cache.Status;
+
+import org.springframework.cache.Cache;
+import org.springframework.cache.support.AbstractCacheManager;
+import org.springframework.util.Assert;
+
+/**
+ * {@link org.springframework.cache.CacheManager} implementation
+ * backed by a JCache {@link javax.cache.CacheManager}.
+ *
+ * @author Juergen Hoeller
+ * @since 3.2
+ */
+public class JCacheCacheManager extends AbstractCacheManager {
+
+ private javax.cache.CacheManager cacheManager;
+
+ private boolean allowNullValues = true;
+
+
+ /**
+ * Set the backing JCache {@link javax.cache.CacheManager}.
+ */
+ public void setCacheManager(javax.cache.CacheManager cacheManager) {
+ this.cacheManager = cacheManager;
+ }
+
+ /**
+ * Return the backing JCache {@link javax.cache.CacheManager}.
+ */
+ public javax.cache.CacheManager getCacheManager() {
+ return this.cacheManager;
+ }
+
+ /**
+ * Specify whether to accept and convert null values for all caches
+ * in this cache manager.
+ *
Default is "true", despite JSR-107 itself not supporting null values.
+ * An internal holder object will be used to store user-level null values.
+ */
+ public void setAllowNullValues(boolean allowNullValues) {
+ this.allowNullValues = allowNullValues;
+ }
+
+ /**
+ * Return whether this cache manager accepts and converts null values
+ * for all of its caches.
+ */
+ public boolean isAllowNullValues() {
+ return this.allowNullValues;
+ }
+
+
+ @Override
+ protected Collection