HHH-10770 JCache 2nd-level cache
* Provider and CacheManager creation * Caches creation * Region class hierarchy * Different access strategies
This commit is contained in:
parent
030f442f3c
commit
a872885a43
|
@ -0,0 +1,20 @@
|
||||||
|
dependencies {
|
||||||
|
compile project( ':hibernate-core' )
|
||||||
|
compile( libraries.jcache )
|
||||||
|
|
||||||
|
testCompile project( ':hibernate-testing' )
|
||||||
|
testCompile( libraries.mockito )
|
||||||
|
testRuntime( libraries.ehcache3 )
|
||||||
|
}
|
||||||
|
|
||||||
|
def pomName() {
|
||||||
|
return 'Hibernate/JCache Integration'
|
||||||
|
}
|
||||||
|
|
||||||
|
def pomDescription() {
|
||||||
|
return 'Integration for javax.cache into Hibernate as a second-level caching service'
|
||||||
|
}
|
||||||
|
|
||||||
|
def osgiDescription() {
|
||||||
|
return pomDescription()
|
||||||
|
}
|
45
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheCollectionRegion.java
vendored
Normal file
45
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheCollectionRegion.java
vendored
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import javax.cache.Cache;
|
||||||
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
|
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.jcache.access.NonStrictCollectionRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.jcache.access.ReadOnlyCollectionRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.jcache.access.ReadWriteCollectionRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.spi.CacheDataDescription;
|
||||||
|
import org.hibernate.cache.spi.CollectionRegion;
|
||||||
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
|
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheCollectionRegion extends JCacheTransactionalDataRegion implements CollectionRegion {
|
||||||
|
|
||||||
|
public JCacheCollectionRegion(Cache<Object, Object> cache, CacheDataDescription metadata, SessionFactoryOptions options) {
|
||||||
|
super( cache, metadata, options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
|
||||||
|
switch ( accessType ) {
|
||||||
|
case READ_ONLY:
|
||||||
|
return new ReadOnlyCollectionRegionAccessStrategy( this );
|
||||||
|
case NONSTRICT_READ_WRITE:
|
||||||
|
return new NonStrictCollectionRegionAccessStrategy( this );
|
||||||
|
case READ_WRITE:
|
||||||
|
return new ReadWriteCollectionRegionAccessStrategy( this );
|
||||||
|
case TRANSACTIONAL:
|
||||||
|
throw new UnsupportedOperationException( "Implement me!" );
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException( "Unknown AccessType: " + accessType.name() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheEntityRegion.java
vendored
Normal file
50
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheEntityRegion.java
vendored
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import javax.cache.Cache;
|
||||||
|
|
||||||
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.jcache.access.NonStrictEntityRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.jcache.access.ReadOnlyEntityRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.jcache.access.ReadWriteEntityRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.spi.CacheDataDescription;
|
||||||
|
import org.hibernate.cache.spi.EntityRegion;
|
||||||
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
|
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheEntityRegion extends JCacheTransactionalDataRegion implements EntityRegion {
|
||||||
|
|
||||||
|
public JCacheEntityRegion(Cache<Object, Object> cache, CacheDataDescription metadata, SessionFactoryOptions options) {
|
||||||
|
super( cache, metadata, options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
|
||||||
|
throwIfAccessTypeUnsupported( accessType );
|
||||||
|
switch ( accessType ) {
|
||||||
|
case READ_ONLY:
|
||||||
|
return new ReadOnlyEntityRegionAccessStrategy( this );
|
||||||
|
case NONSTRICT_READ_WRITE:
|
||||||
|
return new NonStrictEntityRegionAccessStrategy( this );
|
||||||
|
case READ_WRITE:
|
||||||
|
return new ReadWriteEntityRegionAccessStrategy( this );
|
||||||
|
case TRANSACTIONAL:
|
||||||
|
return createTransactionalEntityRegionAccessStrategy();
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException( "Unknown AccessType: " + accessType );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected EntityRegionAccessStrategy createTransactionalEntityRegionAccessStrategy() {
|
||||||
|
throw new UnsupportedOperationException("No org.hibernate.cache.spi.access.AccessType.TRANSACTIONAL support");
|
||||||
|
}
|
||||||
|
}
|
44
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheGeneralDataRegion.java
vendored
Normal file
44
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheGeneralDataRegion.java
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import javax.cache.Cache;
|
||||||
|
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.spi.GeneralDataRegion;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheGeneralDataRegion extends JCacheRegion implements GeneralDataRegion {
|
||||||
|
|
||||||
|
public JCacheGeneralDataRegion(Cache<Object, Object> cache) {
|
||||||
|
super( cache );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object get(SharedSessionContractImplementor session, Object key) throws CacheException {
|
||||||
|
return cache.get( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(SharedSessionContractImplementor session, Object key, Object value) throws CacheException {
|
||||||
|
cache.put( key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void evict(Object key) throws CacheException {
|
||||||
|
cache.remove( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void evictAll() throws CacheException {
|
||||||
|
cache.removeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
39
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheMessageLogger.java
vendored
Normal file
39
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheMessageLogger.java
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import org.jboss.logging.annotations.LogMessage;
|
||||||
|
import org.jboss.logging.annotations.Message;
|
||||||
|
import org.jboss.logging.annotations.MessageLogger;
|
||||||
|
|
||||||
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
|
||||||
|
import static org.jboss.logging.Logger.Level.WARN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
@MessageLogger(projectCode = "HHH")
|
||||||
|
public interface JCacheMessageLogger extends CoreMessageLogger {
|
||||||
|
|
||||||
|
static final int NAMESPACE = 40000;
|
||||||
|
|
||||||
|
@LogMessage(level = WARN)
|
||||||
|
@Message(
|
||||||
|
value = "Attempt to restart an already started JCacheRegionFactory. Use sessionFactory.close() between " +
|
||||||
|
"repeated calls to buildSessionFactory. Using previously created JCacheRegionFactory.",
|
||||||
|
id = NAMESPACE + 1
|
||||||
|
)
|
||||||
|
void attemptToRestartAlreadyStartedJCacheProvider();
|
||||||
|
|
||||||
|
@LogMessage(level = WARN)
|
||||||
|
@Message(
|
||||||
|
value = "Attempt to restop an already stopped JCacheRegionFactory.",
|
||||||
|
id = NAMESPACE + 2
|
||||||
|
)
|
||||||
|
void attemptToRestopAlreadyStoppedJCacheProvider();
|
||||||
|
}
|
45
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheNaturalIdRegion.java
vendored
Normal file
45
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheNaturalIdRegion.java
vendored
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import javax.cache.Cache;
|
||||||
|
|
||||||
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.jcache.access.NonStrictNaturalIdRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.jcache.access.ReadOnlyNaturalIdRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.jcache.access.ReadWriteNaturalIdRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.spi.CacheDataDescription;
|
||||||
|
import org.hibernate.cache.spi.NaturalIdRegion;
|
||||||
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
|
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheNaturalIdRegion extends JCacheTransactionalDataRegion implements NaturalIdRegion {
|
||||||
|
|
||||||
|
public JCacheNaturalIdRegion(Cache<Object, Object> cache, CacheDataDescription metadata, SessionFactoryOptions options) {
|
||||||
|
super( cache, metadata, options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NaturalIdRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
|
||||||
|
switch ( accessType ) {
|
||||||
|
case READ_ONLY:
|
||||||
|
return new ReadOnlyNaturalIdRegionAccessStrategy( this );
|
||||||
|
case NONSTRICT_READ_WRITE:
|
||||||
|
return new NonStrictNaturalIdRegionAccessStrategy( this );
|
||||||
|
case READ_WRITE:
|
||||||
|
return new ReadWriteNaturalIdRegionAccessStrategy( this );
|
||||||
|
case TRANSACTIONAL:
|
||||||
|
throw new UnsupportedOperationException( "Implement me!" );
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException( "Unknown AccessType: " + accessType.name() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheQueryResultsRegion.java
vendored
Normal file
22
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheQueryResultsRegion.java
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import javax.cache.Cache;
|
||||||
|
|
||||||
|
import org.hibernate.cache.spi.QueryResultsRegion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheQueryResultsRegion extends JCacheGeneralDataRegion implements QueryResultsRegion {
|
||||||
|
|
||||||
|
public JCacheQueryResultsRegion(Cache<Object, Object> cache) {
|
||||||
|
super( cache );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.cache.Cache;
|
||||||
|
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.spi.Region;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheRegion implements Region {
|
||||||
|
|
||||||
|
protected final Cache<Object, Object> cache;
|
||||||
|
|
||||||
|
public JCacheRegion(Cache<Object, Object> cache) {
|
||||||
|
if(cache == null) {
|
||||||
|
throw new NullPointerException("JCacheRegion requires a Cache!");
|
||||||
|
}
|
||||||
|
this.cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return cache.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() throws CacheException {
|
||||||
|
cache.getCacheManager().destroyCache( cache.getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Object key) {
|
||||||
|
return cache.containsKey( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSizeInMemory() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getElementCountInMemory() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getElementCountOnDisk() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map toMap() {
|
||||||
|
final Map<Object, Object> map = new HashMap<Object, Object>();
|
||||||
|
for ( Cache.Entry<Object, Object> entry : cache ) {
|
||||||
|
map.put( entry.getKey(), entry.getValue() );
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long nextTimestamp() {
|
||||||
|
return JCacheRegionFactory.nextTS();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTimeout() {
|
||||||
|
return JCacheRegionFactory.timeOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache<Object, Object> getCache() {
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
}
|
207
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheRegionFactory.java
vendored
Normal file
207
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheRegionFactory.java
vendored
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import javax.cache.Cache;
|
||||||
|
import javax.cache.CacheManager;
|
||||||
|
import javax.cache.Caching;
|
||||||
|
import javax.cache.configuration.Configuration;
|
||||||
|
import javax.cache.configuration.MutableConfiguration;
|
||||||
|
import javax.cache.spi.CachingProvider;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.spi.CacheDataDescription;
|
||||||
|
import org.hibernate.cache.spi.CollectionRegion;
|
||||||
|
import org.hibernate.cache.spi.EntityRegion;
|
||||||
|
import org.hibernate.cache.spi.NaturalIdRegion;
|
||||||
|
import org.hibernate.cache.spi.QueryResultsRegion;
|
||||||
|
import org.hibernate.cache.spi.RegionFactory;
|
||||||
|
import org.hibernate.cache.spi.TimestampsRegion;
|
||||||
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheRegionFactory implements RegionFactory {
|
||||||
|
|
||||||
|
private static final String PROP_PREFIX = "hibernate.javax.cache";
|
||||||
|
|
||||||
|
public static final String PROVIDER = PROP_PREFIX + ".provider";
|
||||||
|
public static final String CONFIG_URI = PROP_PREFIX + ".uri";
|
||||||
|
|
||||||
|
private static final JCacheMessageLogger LOG = Logger.getMessageLogger(
|
||||||
|
JCacheMessageLogger.class,
|
||||||
|
JCacheRegionFactory.class.getName()
|
||||||
|
);
|
||||||
|
|
||||||
|
private final AtomicBoolean started = new AtomicBoolean( false );
|
||||||
|
private volatile CacheManager cacheManager;
|
||||||
|
private SessionFactoryOptions options;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(final SessionFactoryOptions options, final Properties properties) throws CacheException {
|
||||||
|
if ( started.compareAndSet( false, true ) ) {
|
||||||
|
synchronized ( this ) {
|
||||||
|
this.options = options;
|
||||||
|
try {
|
||||||
|
final CachingProvider cachingProvider;
|
||||||
|
final String provider = getProp( properties, PROVIDER );
|
||||||
|
if ( provider != null ) {
|
||||||
|
cachingProvider = Caching.getCachingProvider( provider );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cachingProvider = Caching.getCachingProvider();
|
||||||
|
}
|
||||||
|
final CacheManager cacheManager;
|
||||||
|
final String cacheManagerUri = getProp( properties, CONFIG_URI );
|
||||||
|
if ( cacheManagerUri != null ) {
|
||||||
|
URI uri;
|
||||||
|
try {
|
||||||
|
uri = new URI( cacheManagerUri );
|
||||||
|
}
|
||||||
|
catch ( URISyntaxException e ) {
|
||||||
|
throw new CacheException( "Couldn't create URI from " + cacheManagerUri, e );
|
||||||
|
}
|
||||||
|
cacheManager = cachingProvider.getCacheManager( uri, cachingProvider.getDefaultClassLoader() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cacheManager = cachingProvider.getCacheManager();
|
||||||
|
}
|
||||||
|
this.cacheManager = cacheManager;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if ( this.cacheManager == null ) {
|
||||||
|
started.set( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG.attemptToRestartAlreadyStartedJCacheProvider();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
if ( started.compareAndSet( true, false ) ) {
|
||||||
|
synchronized ( this ) {
|
||||||
|
cacheManager.close();
|
||||||
|
cacheManager = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG.attemptToRestopAlreadyStoppedJCacheProvider();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMinimalPutsEnabledByDefault() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessType getDefaultAccessType() {
|
||||||
|
return AccessType.READ_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long nextTimestamp() {
|
||||||
|
return nextTS();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityRegion buildEntityRegion(final String regionName, final Properties properties, final CacheDataDescription metadata)
|
||||||
|
throws CacheException {
|
||||||
|
final Cache<Object, Object> cache = getOrCreateCache( regionName, properties, metadata );
|
||||||
|
return new JCacheEntityRegion( cache, metadata, options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NaturalIdRegion buildNaturalIdRegion(final String regionName, final Properties properties, final CacheDataDescription metadata)
|
||||||
|
throws CacheException {
|
||||||
|
final Cache<Object, Object> cache = getOrCreateCache( regionName, properties, metadata );
|
||||||
|
return new JCacheNaturalIdRegion( cache, metadata, options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CollectionRegion buildCollectionRegion(final String regionName, final Properties properties, final CacheDataDescription metadata)
|
||||||
|
throws CacheException {
|
||||||
|
final Cache<Object, Object> cache = getOrCreateCache( regionName, properties, metadata );
|
||||||
|
return new JCacheCollectionRegion( cache, metadata, options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResultsRegion buildQueryResultsRegion(final String regionName, final Properties properties)
|
||||||
|
throws CacheException {
|
||||||
|
final Cache<Object, Object> cache = getOrCreateCache( regionName, properties, null );
|
||||||
|
return new JCacheQueryResultsRegion( cache );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimestampsRegion buildTimestampsRegion(final String regionName, final Properties properties)
|
||||||
|
throws CacheException {
|
||||||
|
final Cache<Object, Object> cache = getOrCreateCache( regionName, properties, null );
|
||||||
|
return new JCacheTimestampsRegion( cache );
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isStarted() {
|
||||||
|
return started.get() && cacheManager != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Cache<Object, Object> getOrCreateCache(String regionName, Properties properties, CacheDataDescription metadata) {
|
||||||
|
checkStatus();
|
||||||
|
final Cache<Object, Object> cache = cacheManager.getCache( regionName );
|
||||||
|
if ( cache == null ) {
|
||||||
|
try {
|
||||||
|
return cacheManager.createCache( regionName, newDefaultConfig( properties, metadata ) );
|
||||||
|
}
|
||||||
|
catch ( CacheException e ) {
|
||||||
|
final Cache<Object, Object> existing = cacheManager.getCache( regionName );
|
||||||
|
if ( existing != null ) {
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Configuration<Object, Object> newDefaultConfig(Properties properties, CacheDataDescription metadata) {
|
||||||
|
return new MutableConfiguration<Object, Object>();
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheManager getCacheManager() {
|
||||||
|
return cacheManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long nextTS() {
|
||||||
|
return System.currentTimeMillis() / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int timeOut() {
|
||||||
|
return (int) (TimeUnit.SECONDS.toMillis(60) / 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getProp(Properties properties, String prop) {
|
||||||
|
return properties != null ? properties.getProperty( prop ) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkStatus() {
|
||||||
|
if(!isStarted()) {
|
||||||
|
throw new IllegalStateException("JCacheRegionFactory not yet started!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheTimestampsRegion.java
vendored
Normal file
22
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheTimestampsRegion.java
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import javax.cache.Cache;
|
||||||
|
|
||||||
|
import org.hibernate.cache.spi.TimestampsRegion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheTimestampsRegion extends JCacheGeneralDataRegion implements TimestampsRegion {
|
||||||
|
|
||||||
|
public JCacheTimestampsRegion(Cache<Object, Object> cache) {
|
||||||
|
super( cache );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
78
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheTransactionalDataRegion.java
vendored
Normal file
78
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/JCacheTransactionalDataRegion.java
vendored
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.cache.Cache;
|
||||||
|
import javax.cache.processor.EntryProcessor;
|
||||||
|
|
||||||
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
|
import org.hibernate.cache.spi.CacheDataDescription;
|
||||||
|
import org.hibernate.cache.spi.TransactionalDataRegion;
|
||||||
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheTransactionalDataRegion extends JCacheRegion implements TransactionalDataRegion {
|
||||||
|
|
||||||
|
private static final Set<AccessType> SUPPORTED_ACCESS_TYPES
|
||||||
|
= EnumSet.of( AccessType.READ_ONLY, AccessType.NONSTRICT_READ_WRITE, AccessType.READ_WRITE );
|
||||||
|
|
||||||
|
private final CacheDataDescription metadata;
|
||||||
|
private final SessionFactoryOptions options;
|
||||||
|
|
||||||
|
public JCacheTransactionalDataRegion(Cache<Object, Object> cache, CacheDataDescription metadata, SessionFactoryOptions options) {
|
||||||
|
super( cache );
|
||||||
|
this.metadata = metadata;
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTransactionAware() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CacheDataDescription getCacheDataDescription() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void throwIfAccessTypeUnsupported(AccessType accessType) {
|
||||||
|
if ( supportedAccessTypes().contains( accessType ) ) {
|
||||||
|
throw new UnsupportedOperationException( "This doesn't JCacheTransactionalDataRegion doesn't support " + accessType );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<AccessType> supportedAccessTypes() {
|
||||||
|
return SUPPORTED_ACCESS_TYPES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
cache.removeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object get(Object key) {
|
||||||
|
return cache.get( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(Object key) {
|
||||||
|
cache.remove( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(Object key, Object value) {
|
||||||
|
cache.put( key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionFactoryOptions getSessionFactoryOptions() {
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T invoke(Object key, EntryProcessor<Object, Object, T> entryProcessor, Object... args) {
|
||||||
|
return cache.invoke( key, entryProcessor, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,338 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import javax.cache.processor.EntryProcessor;
|
||||||
|
import javax.cache.processor.EntryProcessorException;
|
||||||
|
import javax.cache.processor.MutableEntry;
|
||||||
|
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.jcache.JCacheTransactionalDataRegion;
|
||||||
|
import org.hibernate.cache.spi.access.SoftLock;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class AbstractReadWriteRegionAccessStrategy<R extends JCacheTransactionalDataRegion> {
|
||||||
|
protected final R region;
|
||||||
|
protected final Comparator versionComparator;
|
||||||
|
private final UUID uuid = UUID.randomUUID();
|
||||||
|
private final AtomicLong nextLockId = new AtomicLong();
|
||||||
|
|
||||||
|
public AbstractReadWriteRegionAccessStrategy(R region) {
|
||||||
|
this.versionComparator = region.getCacheDataDescription().getVersionComparator();
|
||||||
|
this.region = region;
|
||||||
|
}
|
||||||
|
|
||||||
|
public R getRegion() {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException {
|
||||||
|
final Lockable item = (Lockable) region.get( key );
|
||||||
|
|
||||||
|
final boolean readable = item != null && item.isReadable( txTimestamp );
|
||||||
|
if ( readable ) {
|
||||||
|
return item.getValue();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version) throws CacheException {
|
||||||
|
return region.invoke(
|
||||||
|
key, new EntryProcessor<Object, Object, Boolean>() {
|
||||||
|
@Override
|
||||||
|
public Boolean process(MutableEntry<Object, Object> entry, Object... args)
|
||||||
|
throws EntryProcessorException {
|
||||||
|
final Lockable item = (Lockable) entry.getValue();
|
||||||
|
final boolean writeable = item == null || item.isWriteable(
|
||||||
|
(Long) args[1],
|
||||||
|
args[2],
|
||||||
|
versionComparator
|
||||||
|
);
|
||||||
|
if ( writeable ) {
|
||||||
|
entry.setValue( new Item( args[0], args[2], region.nextTimestamp() ) );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, value, txTimestamp, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
|
||||||
|
throws CacheException {
|
||||||
|
return putFromLoad( session, key, value, txTimestamp, version );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException {
|
||||||
|
return region.invoke(
|
||||||
|
key, new EntryProcessor<Object, Object, SoftLock>() {
|
||||||
|
@Override
|
||||||
|
public SoftLock process(MutableEntry<Object, Object> entry, Object... args)
|
||||||
|
throws EntryProcessorException {
|
||||||
|
final Lockable item = (Lockable) entry.getValue();
|
||||||
|
final long timeout = region.nextTimestamp() + region.getTimeout();
|
||||||
|
final Lock lock = ( item == null ) ? new Lock(
|
||||||
|
timeout,
|
||||||
|
(UUID) args[0],
|
||||||
|
(Long) args[1],
|
||||||
|
args[2]
|
||||||
|
)
|
||||||
|
: item.lock( timeout, (UUID) args[0], (Long) args[1] );
|
||||||
|
entry.setValue( lock );
|
||||||
|
return lock;
|
||||||
|
}
|
||||||
|
}, uuid, nextLockId(), version
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException {
|
||||||
|
region.invoke(
|
||||||
|
key, new EntryProcessor<Object, Object, Void>() {
|
||||||
|
@Override
|
||||||
|
public Void process(MutableEntry<Object, Object> entry, Object... args)
|
||||||
|
throws EntryProcessorException {
|
||||||
|
final Lockable item = (Lockable) entry.getValue();
|
||||||
|
|
||||||
|
if ( (item != null) && item.isUnlockable( (SoftLock) args[0] ) ) {
|
||||||
|
( (Lock) item ).unlock( region.nextTimestamp() );
|
||||||
|
entry.setValue( item );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entry.setValue( null );
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(SharedSessionContractImplementor session, Object key) throws CacheException {
|
||||||
|
region.remove( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAll() throws CacheException {
|
||||||
|
region.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void evict(Object key) throws CacheException {
|
||||||
|
region.remove( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void evictAll() throws CacheException {
|
||||||
|
region.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoftLock lockRegion() throws CacheException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unlockRegion(SoftLock lock) throws CacheException {
|
||||||
|
throw new UnsupportedOperationException( "JCache doesn't support region locking" );
|
||||||
|
}
|
||||||
|
|
||||||
|
private long nextLockId() {
|
||||||
|
return nextLockId.getAndIncrement();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface type implemented by all wrapper objects in the cache.
|
||||||
|
*/
|
||||||
|
protected static interface Lockable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> if the enclosed value can be read by a transaction started at the given time.
|
||||||
|
*/
|
||||||
|
public boolean isReadable(long txTimestamp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> if the enclosed value can be replaced with one of the given version by a
|
||||||
|
* transaction started at the given time.
|
||||||
|
*/
|
||||||
|
public boolean isWriteable(long txTimestamp, Object version, Comparator versionComparator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the enclosed value.
|
||||||
|
*/
|
||||||
|
public Object getValue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> if the given lock can be unlocked using the given SoftLock instance as a handle.
|
||||||
|
*/
|
||||||
|
public boolean isUnlockable(SoftLock lock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locks this entry, stamping it with the UUID and lockId given, with the lock timeout occuring at the specified
|
||||||
|
* time. The returned Lock object can be used to unlock the entry in the future.
|
||||||
|
*/
|
||||||
|
public Lock lock(long timeout, UUID uuid, long lockId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper type representing unlocked items.
|
||||||
|
*/
|
||||||
|
protected static final class Item implements Serializable, Lockable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final Object value;
|
||||||
|
private final Object version;
|
||||||
|
private final long timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an unlocked item wrapping the given value with a version and creation timestamp.
|
||||||
|
*/
|
||||||
|
Item(Object value, Object version, long timestamp) {
|
||||||
|
this.value = value;
|
||||||
|
this.version = version;
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReadable(long txTimestamp) {
|
||||||
|
return txTimestamp > timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) {
|
||||||
|
return version != null && versionComparator.compare( version, newVersion ) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUnlockable(SoftLock lock) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Lock lock(long timeout, UUID uuid, long lockId) {
|
||||||
|
return new Lock( timeout, uuid, lockId, version );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper type representing locked items.
|
||||||
|
*/
|
||||||
|
public static final class Lock implements Serializable, Lockable, SoftLock {
|
||||||
|
private static final long serialVersionUID = 2L;
|
||||||
|
|
||||||
|
private final UUID sourceUuid;
|
||||||
|
private final long lockId;
|
||||||
|
private final Object version;
|
||||||
|
|
||||||
|
private long timeout;
|
||||||
|
private boolean concurrent;
|
||||||
|
private int multiplicity = 1;
|
||||||
|
private long unlockTimestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a locked item with the given identifiers and object version.
|
||||||
|
*/
|
||||||
|
public Lock(long timeout, UUID sourceUuid, long lockId, Object version) {
|
||||||
|
this.timeout = timeout;
|
||||||
|
this.lockId = lockId;
|
||||||
|
this.version = version;
|
||||||
|
this.sourceUuid = sourceUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReadable(long txTimestamp) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings({ "SimplifiableIfStatement", "unchecked" })
|
||||||
|
public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) {
|
||||||
|
if ( txTimestamp > timeout ) {
|
||||||
|
// if timedout then allow write
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( multiplicity > 0 ) {
|
||||||
|
// if still locked then disallow write
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return version == null
|
||||||
|
? txTimestamp > unlockTimestamp
|
||||||
|
: versionComparator.compare( version, newVersion ) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUnlockable(SoftLock lock) {
|
||||||
|
return equals( lock );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("SimplifiableIfStatement")
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( o == this ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( o instanceof Lock ) {
|
||||||
|
return ( lockId == ( (Lock) o ).lockId ) && sourceUuid.equals( ( (Lock) o ).sourceUuid );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int hash = ( sourceUuid != null ? sourceUuid.hashCode() : 0 );
|
||||||
|
int temp = (int) lockId;
|
||||||
|
for ( int i = 1; i < Long.SIZE / Integer.SIZE; i++ ) {
|
||||||
|
temp ^= ( lockId >>> ( i * Integer.SIZE ) );
|
||||||
|
}
|
||||||
|
return hash + temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this Lock has been concurrently locked by more than one transaction.
|
||||||
|
*/
|
||||||
|
public boolean wasLockedConcurrently() {
|
||||||
|
return concurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Lock lock(long timeout, UUID uuid, long lockId) {
|
||||||
|
concurrent = true;
|
||||||
|
multiplicity++;
|
||||||
|
this.timeout = timeout;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlocks this Lock, and timestamps the unlock event.
|
||||||
|
*/
|
||||||
|
public void unlock(long timestamp) {
|
||||||
|
if ( --multiplicity == 0 ) {
|
||||||
|
unlockTimestamp = timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Lock Source-UUID:" + sourceUuid + " Lock-ID:" + lockId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
97
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/access/JCacheRegionAccessStrategy.java
vendored
Normal file
97
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/access/JCacheRegionAccessStrategy.java
vendored
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.jcache.JCacheTransactionalDataRegion;
|
||||||
|
import org.hibernate.cache.spi.access.RegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.spi.access.SoftLock;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
abstract class JCacheRegionAccessStrategy<R extends JCacheTransactionalDataRegion> implements RegionAccessStrategy {
|
||||||
|
|
||||||
|
private final R region;
|
||||||
|
|
||||||
|
public JCacheRegionAccessStrategy(R region) {
|
||||||
|
if ( region == null ) {
|
||||||
|
throw new NullPointerException( "Requires a non-null JCacheTransactionalDataRegion" );
|
||||||
|
}
|
||||||
|
this.region = region;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException {
|
||||||
|
return region.get( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version) throws CacheException {
|
||||||
|
final SessionFactoryOptions options = region.getSessionFactoryOptions();
|
||||||
|
final boolean minimalPutOverride = options != null && options.isMinimalPutsEnabled();
|
||||||
|
return putFromLoad( session, key, value, txTimestamp, version, minimalPutOverride );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
|
||||||
|
throws CacheException {
|
||||||
|
if ( minimalPutOverride && region.contains( key ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
region.put( key, value );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SoftLock lockRegion() throws CacheException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException {
|
||||||
|
evict( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unlockRegion(SoftLock lock) throws CacheException {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(SharedSessionContractImplementor session, Object key) throws CacheException {
|
||||||
|
region.remove( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAll() throws CacheException {
|
||||||
|
region.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void evict(Object key) throws CacheException {
|
||||||
|
region.remove( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void evictAll() throws CacheException {
|
||||||
|
region.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public R getRegion() {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
|
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
|
import org.hibernate.cache.jcache.JCacheCollectionRegion;
|
||||||
|
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class NonStrictCollectionRegionAccessStrategy
|
||||||
|
extends JCacheRegionAccessStrategy<JCacheCollectionRegion>
|
||||||
|
implements CollectionRegionAccessStrategy {
|
||||||
|
|
||||||
|
public NonStrictCollectionRegionAccessStrategy(JCacheCollectionRegion jCacheCollectionRegion) {
|
||||||
|
super( jCacheCollectionRegion );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
|
||||||
|
return DefaultCacheKeysFactory.createCollectionKey( id, persister, factory, tenantIdentifier );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getCacheKeyId(Object cacheKey) {
|
||||||
|
return DefaultCacheKeysFactory.getCollectionId( cacheKey );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
|
import org.hibernate.cache.jcache.JCacheEntityRegion;
|
||||||
|
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.spi.access.SoftLock;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class NonStrictEntityRegionAccessStrategy extends JCacheRegionAccessStrategy<JCacheEntityRegion>
|
||||||
|
implements EntityRegionAccessStrategy {
|
||||||
|
|
||||||
|
public NonStrictEntityRegionAccessStrategy(JCacheEntityRegion jCacheEntityRegion) {
|
||||||
|
super( jCacheEntityRegion );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean insert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException {
|
||||||
|
getRegion().put( key, value );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean update(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion)
|
||||||
|
throws CacheException {
|
||||||
|
getRegion().remove( key );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
|
||||||
|
throws CacheException {
|
||||||
|
getRegion().remove( key );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
|
||||||
|
return DefaultCacheKeysFactory.createEntityKey( id, persister, factory, tenantIdentifier );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getCacheKeyId(Object cacheKey) {
|
||||||
|
return DefaultCacheKeysFactory.getEntityId( cacheKey );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
|
import org.hibernate.cache.jcache.JCacheNaturalIdRegion;
|
||||||
|
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.spi.access.SoftLock;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class NonStrictNaturalIdRegionAccessStrategy
|
||||||
|
extends JCacheRegionAccessStrategy<JCacheNaturalIdRegion>
|
||||||
|
implements NaturalIdRegionAccessStrategy {
|
||||||
|
|
||||||
|
public NonStrictNaturalIdRegionAccessStrategy(JCacheNaturalIdRegion jCacheNaturalIdRegion) {
|
||||||
|
super( jCacheNaturalIdRegion );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean insert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean update(SharedSessionContractImplementor session, Object key, Object value) throws CacheException {
|
||||||
|
remove( session, key );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, SoftLock lock) throws CacheException {
|
||||||
|
unlockItem( session, key, lock );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SharedSessionContractImplementor session) {
|
||||||
|
return DefaultCacheKeysFactory.createNaturalIdKey( naturalIdValues, persister, session );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] getNaturalIdValues(Object cacheKey) {
|
||||||
|
return DefaultCacheKeysFactory.getNaturalIdValues( cacheKey );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
|
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
|
import org.hibernate.cache.jcache.JCacheCollectionRegion;
|
||||||
|
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class ReadOnlyCollectionRegionAccessStrategy
|
||||||
|
extends JCacheRegionAccessStrategy<JCacheCollectionRegion>
|
||||||
|
implements CollectionRegionAccessStrategy {
|
||||||
|
|
||||||
|
public ReadOnlyCollectionRegionAccessStrategy(JCacheCollectionRegion jCacheCollectionRegion) {
|
||||||
|
super( jCacheCollectionRegion );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
|
||||||
|
return DefaultCacheKeysFactory.createCollectionKey( id, persister, factory, tenantIdentifier );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getCacheKeyId(Object cacheKey) {
|
||||||
|
return DefaultCacheKeysFactory.getCollectionId( cacheKey );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
|
import org.hibernate.cache.jcache.JCacheEntityRegion;
|
||||||
|
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.spi.access.SoftLock;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class ReadOnlyEntityRegionAccessStrategy extends JCacheRegionAccessStrategy<JCacheEntityRegion>
|
||||||
|
implements EntityRegionAccessStrategy {
|
||||||
|
|
||||||
|
public ReadOnlyEntityRegionAccessStrategy(JCacheEntityRegion jCacheEntityRegion) {
|
||||||
|
super( jCacheEntityRegion );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean insert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException {
|
||||||
|
getRegion().put( key, value );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean update(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion)
|
||||||
|
throws CacheException {
|
||||||
|
throw new UnsupportedOperationException( "This is a ReadOnly strategy!" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
|
||||||
|
throws CacheException {
|
||||||
|
throw new UnsupportedOperationException( "This is a ReadOnly strategy!" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
|
||||||
|
return DefaultCacheKeysFactory.createEntityKey( id, persister, factory, tenantIdentifier );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getCacheKeyId(Object cacheKey) {
|
||||||
|
return DefaultCacheKeysFactory.getEntityId( cacheKey );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
|
import org.hibernate.cache.jcache.JCacheNaturalIdRegion;
|
||||||
|
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.spi.access.SoftLock;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class ReadOnlyNaturalIdRegionAccessStrategy
|
||||||
|
extends JCacheRegionAccessStrategy<JCacheNaturalIdRegion>
|
||||||
|
implements NaturalIdRegionAccessStrategy {
|
||||||
|
|
||||||
|
public ReadOnlyNaturalIdRegionAccessStrategy(JCacheNaturalIdRegion jCacheNaturalIdRegion) {
|
||||||
|
super( jCacheNaturalIdRegion );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean insert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException {
|
||||||
|
getRegion().put( key, value );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean update(SharedSessionContractImplementor session, Object key, Object value) throws CacheException {
|
||||||
|
throw new UnsupportedOperationException( "This is a ReadOnly strategy!" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, SoftLock lock) throws CacheException {
|
||||||
|
throw new UnsupportedOperationException( "This is a ReadOnly strategy!" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SharedSessionContractImplementor session) {
|
||||||
|
return DefaultCacheKeysFactory.createNaturalIdKey( naturalIdValues, persister, session );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] getNaturalIdValues(Object cacheKey) {
|
||||||
|
return DefaultCacheKeysFactory.getNaturalIdValues( cacheKey );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
|
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
|
import org.hibernate.cache.jcache.JCacheCollectionRegion;
|
||||||
|
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class ReadWriteCollectionRegionAccessStrategy
|
||||||
|
extends AbstractReadWriteRegionAccessStrategy<JCacheCollectionRegion>
|
||||||
|
implements CollectionRegionAccessStrategy {
|
||||||
|
|
||||||
|
public ReadWriteCollectionRegionAccessStrategy(JCacheCollectionRegion jCacheCollectionRegion) {
|
||||||
|
super( jCacheCollectionRegion );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
|
||||||
|
return DefaultCacheKeysFactory.createCollectionKey( id, persister, factory, tenantIdentifier );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getCacheKeyId(Object cacheKey) {
|
||||||
|
return DefaultCacheKeysFactory.getCollectionId( cacheKey );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
|
import javax.cache.processor.EntryProcessor;
|
||||||
|
import javax.cache.processor.EntryProcessorException;
|
||||||
|
import javax.cache.processor.MutableEntry;
|
||||||
|
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
|
import org.hibernate.cache.jcache.JCacheEntityRegion;
|
||||||
|
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.spi.access.SoftLock;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class ReadWriteEntityRegionAccessStrategy
|
||||||
|
extends AbstractReadWriteRegionAccessStrategy<JCacheEntityRegion>
|
||||||
|
implements EntityRegionAccessStrategy {
|
||||||
|
|
||||||
|
|
||||||
|
public ReadWriteEntityRegionAccessStrategy(JCacheEntityRegion region) {
|
||||||
|
super( region );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean insert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException {
|
||||||
|
return region.invoke(
|
||||||
|
key, new EntryProcessor<Object, Object, Boolean>() {
|
||||||
|
@Override
|
||||||
|
public Boolean process(MutableEntry<Object, Object> entry, Object... args)
|
||||||
|
throws EntryProcessorException {
|
||||||
|
if ( !entry.exists() ) {
|
||||||
|
entry.setValue( new Item( args[0], args[1], (Long) args[2] ) );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, value, version, region.nextTimestamp()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean update(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion)
|
||||||
|
throws CacheException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
|
||||||
|
throws CacheException {
|
||||||
|
return region.invoke(
|
||||||
|
key, new EntryProcessor<Object, Object, Boolean>() {
|
||||||
|
@Override
|
||||||
|
public Boolean process(MutableEntry<Object, Object> entry, Object... args)
|
||||||
|
throws EntryProcessorException {
|
||||||
|
final Lockable item = (Lockable) entry.getValue();
|
||||||
|
|
||||||
|
if ( item != null && item.isUnlockable( (SoftLock) args[3] ) ) {
|
||||||
|
final Lock lockItem = (Lock) item;
|
||||||
|
if ( lockItem.wasLockedConcurrently() ) {
|
||||||
|
lockItem.unlock( (Long) args[1] );
|
||||||
|
entry.setValue( lockItem );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entry.setValue( new Item( args[0], args[1], (Long) args[4] ) );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entry.setValue( null );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}, value, currentVersion, previousVersion, lock, region.nextTimestamp()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
|
||||||
|
return DefaultCacheKeysFactory.createEntityKey( id, persister, factory, tenantIdentifier );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getCacheKeyId(Object cacheKey) {
|
||||||
|
return DefaultCacheKeysFactory.getEntityId( cacheKey );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
|
import javax.cache.processor.EntryProcessor;
|
||||||
|
import javax.cache.processor.EntryProcessorException;
|
||||||
|
import javax.cache.processor.MutableEntry;
|
||||||
|
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
|
import org.hibernate.cache.jcache.JCacheNaturalIdRegion;
|
||||||
|
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||||
|
import org.hibernate.cache.spi.access.SoftLock;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class ReadWriteNaturalIdRegionAccessStrategy
|
||||||
|
extends AbstractReadWriteRegionAccessStrategy<JCacheNaturalIdRegion>
|
||||||
|
implements NaturalIdRegionAccessStrategy {
|
||||||
|
|
||||||
|
public ReadWriteNaturalIdRegionAccessStrategy(JCacheNaturalIdRegion jCacheNaturalIdRegion) {
|
||||||
|
super ( jCacheNaturalIdRegion );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean insert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException {
|
||||||
|
return region.invoke(
|
||||||
|
key, new EntryProcessor<Object, Object, Boolean>() {
|
||||||
|
@Override
|
||||||
|
public Boolean process(MutableEntry<Object, Object> entry, Object... args)
|
||||||
|
throws EntryProcessorException {
|
||||||
|
if ( !entry.exists() ) {
|
||||||
|
entry.setValue( new Item( args[0], null, (Long) args[1] ) );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, value, region.nextTimestamp()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean update(SharedSessionContractImplementor session, Object key, Object value)
|
||||||
|
throws CacheException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, SoftLock lock)
|
||||||
|
throws CacheException {
|
||||||
|
return region.invoke(
|
||||||
|
key, new EntryProcessor<Object, Object, Boolean>() {
|
||||||
|
@Override
|
||||||
|
public Boolean process(MutableEntry<Object, Object> entry, Object... args)
|
||||||
|
throws EntryProcessorException {
|
||||||
|
final Lockable item = (Lockable) entry.getValue();
|
||||||
|
|
||||||
|
if ( item != null && item.isUnlockable( (SoftLock) args[1] ) ) {
|
||||||
|
final Lock lockItem = (Lock) item;
|
||||||
|
if ( lockItem.wasLockedConcurrently() ) {
|
||||||
|
lockItem.unlock( region.nextTimestamp() );
|
||||||
|
entry.setValue( lockItem );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entry.setValue( new Item( args[0], null, (Long) args[2] ) );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entry.setValue( null );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}, value, lock, region.nextTimestamp()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SharedSessionContractImplementor session) {
|
||||||
|
return DefaultCacheKeysFactory.createNaturalIdKey( naturalIdValues, persister, session );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] getNaturalIdValues(Object cacheKey) {
|
||||||
|
return DefaultCacheKeysFactory.getNaturalIdValues( cacheKey );
|
||||||
|
}
|
||||||
|
}
|
11
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/access/package-info.java
vendored
Normal file
11
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/access/package-info.java
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access strategies for the JSR-107 Hibernate caching provider.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache.access;
|
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hibernate caching provider for JSR-107 compliant caches.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
34
hibernate-jcache/src/test/java/org/hibernate/cache/jcache/JCacheEntityRegionTest.java
vendored
Normal file
34
hibernate-jcache/src/test/java/org/hibernate/cache/jcache/JCacheEntityRegionTest.java
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import javax.cache.Cache;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
|
import org.hibernate.cfg.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheEntityRegionTest {
|
||||||
|
|
||||||
|
private JCacheEntityRegion region;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void createRegion() {
|
||||||
|
final Cache<Object, Object> cache = Mockito.mock( Cache.class );
|
||||||
|
region = new JCacheEntityRegion( cache, null, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException.class)
|
||||||
|
public void testThrowsWhenCreatingTxRegionAccess() {
|
||||||
|
region.buildAccessStrategy( AccessType.TRANSACTIONAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException.class)
|
||||||
|
public void testThrowsWhenCreatingTxRegionAccessExplicitly() {
|
||||||
|
region.createTransactionalEntityRegionAccessStrategy();
|
||||||
|
}
|
||||||
|
}
|
54
hibernate-jcache/src/test/java/org/hibernate/cache/jcache/JCacheGeneralDataRegionTest.java
vendored
Normal file
54
hibernate-jcache/src/test/java/org/hibernate/cache/jcache/JCacheGeneralDataRegionTest.java
vendored
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import javax.cache.Cache;
|
||||||
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheGeneralDataRegionTest {
|
||||||
|
|
||||||
|
JCacheGeneralDataRegion region;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void createRegion() {
|
||||||
|
final Cache<Object, Object> mock = Mockito.mock( Cache.class );
|
||||||
|
region = new JCacheGeneralDataRegion( mock );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDelegatesGetToCache() {
|
||||||
|
region.get( Mockito.mock(SessionImplementor.class), "foo" );
|
||||||
|
verify( region.getCache() ).get( "foo" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDelegatesPutToCache() {
|
||||||
|
region.put( Mockito.mock(SessionImplementor.class), "foo", "bar" );
|
||||||
|
verify( region.getCache() ).put( "foo", "bar" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDelegatesEvictKeyToCache() {
|
||||||
|
region.evict( "foo" );
|
||||||
|
verify( region.getCache() ).remove( "foo" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDelegatesEvictAllToCache() {
|
||||||
|
region.evictAll();
|
||||||
|
verify( region.getCache() ).removeAll();
|
||||||
|
}
|
||||||
|
}
|
132
hibernate-jcache/src/test/java/org/hibernate/cache/jcache/JCacheRegionFactoryTest.java
vendored
Normal file
132
hibernate-jcache/src/test/java/org/hibernate/cache/jcache/JCacheRegionFactoryTest.java
vendored
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import javax.cache.Cache;
|
||||||
|
import javax.cache.CacheManager;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
|
|
||||||
|
import static java.util.Collections.EMPTY_MAP;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||||
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
|
import static org.hamcrest.CoreMatchers.sameInstance;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheRegionFactoryTest {
|
||||||
|
|
||||||
|
private JCacheRegionFactory factory;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void createFactory() {
|
||||||
|
factory = new JCacheRegionFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsInitiallyNotStarted() {
|
||||||
|
assertThat( factory.isStarted(), is( false ) );
|
||||||
|
assertThat( factory.getCacheManager(), nullValue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMaintainsStartedFlag() {
|
||||||
|
factory.start( null, EMPTY_MAP );
|
||||||
|
assertThat( factory.isStarted(), is( true ) );
|
||||||
|
assertThat( factory.getCacheManager(), notNullValue() );
|
||||||
|
factory.stop();
|
||||||
|
assertThat( factory.isStarted(), is( false ) );
|
||||||
|
assertThat( factory.getCacheManager(), nullValue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = javax.cache.CacheException.class)
|
||||||
|
public void testFailsOnNotFindingProvider() {
|
||||||
|
final Properties properties = new Properties();
|
||||||
|
properties.setProperty( JCacheRegionFactory.PROVIDER, "no.such.thing" );
|
||||||
|
factory.start( null, properties );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = CacheException.class)
|
||||||
|
public void testFailsOnInvalidURI() {
|
||||||
|
final Properties properties = new Properties();
|
||||||
|
properties.setProperty( JCacheRegionFactory.CONFIG_URI, "_fil:" );
|
||||||
|
factory.start( null, properties );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultAccessIsReadWrite() {
|
||||||
|
assertThat( factory.getDefaultAccessType(), is( AccessType.READ_WRITE ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsesMinimalPutsAsDefault() {
|
||||||
|
assertThat( factory.isMinimalPutsEnabledByDefault(), is( true ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemainsStoppedOnFailure() {
|
||||||
|
final Properties properties = new Properties();
|
||||||
|
properties.setProperty( JCacheRegionFactory.CONFIG_URI, "_fil:" );
|
||||||
|
try {
|
||||||
|
factory.start( null, properties );
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( CacheException e ) {
|
||||||
|
assertThat( factory.isStarted(), is( false ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
properties.setProperty( JCacheRegionFactory.PROVIDER, "no.such.thing" );
|
||||||
|
try {
|
||||||
|
factory.start( null, properties );
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch ( javax.cache.CacheException e ) {
|
||||||
|
assertThat( factory.isStarted(), is( false ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStopsCacheManagerOnShutdown() {
|
||||||
|
factory.start( null, EMPTY_MAP );
|
||||||
|
final CacheManager cacheManager = factory.getCacheManager();
|
||||||
|
assertThat( cacheManager.isClosed(), is( false ) );
|
||||||
|
factory.stop();
|
||||||
|
assertThat(cacheManager.isClosed(), is(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException.class)
|
||||||
|
public void testThrowsIllegalStateExceptionWhenNotStarted() {
|
||||||
|
factory.getOrCreateCache( "foo", null, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatesNonExistingCacheNamedLikeRegion() {
|
||||||
|
factory.start( null, EMPTY_MAP );
|
||||||
|
final Cache<Object, Object> foo = factory.getOrCreateCache( "foo", null, null );
|
||||||
|
assertThat( foo, notNullValue());
|
||||||
|
assertThat( factory.getCacheManager().getCache( "foo" ), sameInstance( foo ));
|
||||||
|
assertThat( factory.getOrCreateCache( "foo", null, null ), sameInstance( foo ));
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void stopFactory() {
|
||||||
|
if ( factory.isStarted() ) {
|
||||||
|
factory.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
88
hibernate-jcache/src/test/java/org/hibernate/cache/jcache/JCacheRegionTest.java
vendored
Normal file
88
hibernate-jcache/src/test/java/org/hibernate/cache/jcache/JCacheRegionTest.java
vendored
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.cache.Cache;
|
||||||
|
import javax.cache.CacheManager;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheRegionTest {
|
||||||
|
|
||||||
|
public static final String CACHE_NAME = "foo";
|
||||||
|
private JCacheRegion region;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void createRegion() {
|
||||||
|
final Cache mock = Mockito.mock( Cache.class );
|
||||||
|
when( mock.getName() ).thenReturn( CACHE_NAME );
|
||||||
|
this.region = new JCacheRegion( mock );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDestroyCallsDestroyCacheOnCacheManager() {
|
||||||
|
final Cache<Object, Object> cache = region.getCache();
|
||||||
|
CacheManager cacheManager = Mockito.mock( CacheManager.class );
|
||||||
|
when( cache.getCacheManager() ).thenReturn( cacheManager );
|
||||||
|
when( cacheManager.getCache( CACHE_NAME ) ).thenReturn( cache );
|
||||||
|
region.destroy();
|
||||||
|
verify( cacheManager ).destroyCache( CACHE_NAME );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDelegatesGetNameToCache() {
|
||||||
|
assertThat( region.getName(), is( CACHE_NAME ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDelegatesContainsToCache() {
|
||||||
|
final Cache<Object, Object> cache = region.getCache();
|
||||||
|
region.contains( "bar" );
|
||||||
|
verify( cache ).containsKey( "bar" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSupportsToMap() {
|
||||||
|
final Cache<Object, Object> cache = region.getCache();
|
||||||
|
final Iterator mock = Mockito.mock( Iterator.class );
|
||||||
|
when( mock.hasNext() ).thenReturn( true ).thenReturn( false );
|
||||||
|
when( mock.next() ).thenReturn( new Cache.Entry<Object, Object>() {
|
||||||
|
@Override
|
||||||
|
public Object getKey() {
|
||||||
|
return "foo";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue() {
|
||||||
|
return "bar";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T unwrap(Class<T> clazz) {
|
||||||
|
throw new UnsupportedOperationException( "Implement me!" );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
when( cache.iterator() ).thenReturn( mock );
|
||||||
|
final Map<String, String> map = region.toMap();
|
||||||
|
assertThat( map.size(), is(1) );
|
||||||
|
assertThat( map.get( "foo" ), equalTo( "bar" ));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
71
hibernate-jcache/src/test/java/org/hibernate/cache/jcache/JCacheTransactionalDataRegionTest.java
vendored
Normal file
71
hibernate-jcache/src/test/java/org/hibernate/cache/jcache/JCacheTransactionalDataRegionTest.java
vendored
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package org.hibernate.cache.jcache;
|
||||||
|
|
||||||
|
import javax.cache.Cache;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class JCacheTransactionalDataRegionTest {
|
||||||
|
|
||||||
|
private JCacheTransactionalDataRegion region;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void createRegion() {
|
||||||
|
final Cache<Object, Object> cache = Mockito.mock( Cache.class );
|
||||||
|
region = new JCacheTransactionalDataRegion( cache, null, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = NullPointerException.class)
|
||||||
|
public void testThrowsOnNullCache() {
|
||||||
|
new JCacheTransactionalDataRegion( null, null, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsNotTransactionAware() {
|
||||||
|
assertThat( region.isTransactionAware(), is( false ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDelegatesClearToCache() {
|
||||||
|
final Cache<Object, Object> cache = region.getCache();
|
||||||
|
region.clear();
|
||||||
|
verify( cache ).removeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDelegatesGetToCache() {
|
||||||
|
final Cache<Object, Object> cache = region.getCache();
|
||||||
|
region.get( "foo" );
|
||||||
|
verify( cache ).get( "foo" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSupportsAllAccessTypesButTx() {
|
||||||
|
for ( AccessType type : AccessType.values() ) {
|
||||||
|
if ( type != AccessType.TRANSACTIONAL ) {
|
||||||
|
assertThat(
|
||||||
|
"JCacheTransactionalDataRegion should support " + type,
|
||||||
|
region.supportedAccessTypes().contains( type ),
|
||||||
|
is( true )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assertThat(
|
||||||
|
"JCacheTransactionalDataRegion NOT should support " + type,
|
||||||
|
region.supportedAccessTypes().contains( type ),
|
||||||
|
is( false )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -110,6 +110,8 @@ ext {
|
||||||
|
|
||||||
c3p0: "com.mchange:c3p0:0.9.2.1",
|
c3p0: "com.mchange:c3p0:0.9.2.1",
|
||||||
ehcache: "net.sf.ehcache:ehcache:2.10.1",
|
ehcache: "net.sf.ehcache:ehcache:2.10.1",
|
||||||
|
ehcache3: "org.ehcache:ehcache:3.0.0",
|
||||||
|
jcache: "javax.cache:cache-api:1.0.0",
|
||||||
proxool: "proxool:proxool:0.8.3",
|
proxool: "proxool:proxool:0.8.3",
|
||||||
hikaricp: "com.zaxxer:HikariCP-java6:2.3.9"
|
hikaricp: "com.zaxxer:HikariCP-java6:2.3.9"
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ include 'hibernate-c3p0'
|
||||||
include 'hibernate-proxool'
|
include 'hibernate-proxool'
|
||||||
include 'hibernate-hikaricp'
|
include 'hibernate-hikaricp'
|
||||||
|
|
||||||
|
include 'hibernate-jcache'
|
||||||
include 'hibernate-ehcache'
|
include 'hibernate-ehcache'
|
||||||
include 'hibernate-infinispan'
|
include 'hibernate-infinispan'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue