package kr.pe.kwonnam.hibernate4memcached; import kr.pe.kwonnam.hibernate4memcached.memcached.MemcachedAdapter; import kr.pe.kwonnam.hibernate4memcached.regions.*; import kr.pe.kwonnam.hibernate4memcached.timestamper.HibernateCacheTimestamper; import kr.pe.kwonnam.hibernate4memcached.timestamper.HibernateCacheTimestamperJvmImpl; import kr.pe.kwonnam.hibernate4memcached.util.OverridableReadOnlyProperties; import kr.pe.kwonnam.hibernate4memcached.util.OverridableReadOnlyPropertiesImpl; import kr.pe.kwonnam.hibernate4memcached.util.PropertiesUtils; import org.apache.commons.lang3.StringUtils; import org.hibernate.cache.CacheException; import org.hibernate.cache.spi.*; import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Properties; /** * Hibernate 4 Memcached Cache Region Factory * * @author KwonNam Son ([email protected]) */ public class Hibernate4MemcachedRegionFactory implements RegionFactory { private final Logger log = LoggerFactory.getLogger(Hibernate4MemcachedRegionFactory.class); /** * Memcached Max expiry seconds is 30 days */ public static final int MEMCACHED_MAX_EPIRY_SECONDS = 60 * 60 * 24 * 30; public static final AccessType DEFAULT_ACCESS_TYPE = AccessType.NONSTRICT_READ_WRITE; public static final String REGION_EXPIRY_SECONDS_PROPERTY_KEY_PREFIX = "h4m.expiry.seconds"; public static final String MEMCACHED_ADAPTER_CLASS_PROPERTY_KEY = "h4m.adapter.class"; public static final String TIMESTAMPER_PROPERTY_KEY = "h4m.timestamper.class"; public static final Class<?> DEFAULT_TIMESTAMPER_CLASS = HibernateCacheTimestamperJvmImpl.class; private Settings settings; private Properties cacheProviderConfigProperties; private MemcachedAdapter memcachedAdapter; private HibernateCacheTimestamper hibernateCacheTimestamper; public Hibernate4MemcachedRegionFactory() { // no op } public Hibernate4MemcachedRegionFactory(Properties properties) { } @Override public void start(Settings settings, Properties properties) throws CacheException { log.debug("# start Hibernate4MemcachedRegionFactory."); this.settings = settings; cacheProviderConfigProperties = populateCacheProviderConfigProperties(properties); OverridableReadOnlyProperties mergedConfigProperties = new OverridableReadOnlyPropertiesImpl(properties, cacheProviderConfigProperties); memcachedAdapter = populateMemcachedProvider(mergedConfigProperties); hibernateCacheTimestamper = populateTimestamper(settings, mergedConfigProperties); } Properties populateCacheProviderConfigProperties(Properties properties) { String configPath = properties.getProperty(AvailableSettings.CACHE_PROVIDER_CONFIG); if (StringUtils.isEmpty(configPath)) { return new Properties(); } return PropertiesUtils.loadFromClasspath(configPath); } MemcachedAdapter populateMemcachedProvider(OverridableReadOnlyProperties properties) { String adapterClass = properties.getRequiredProperty(MEMCACHED_ADAPTER_CLASS_PROPERTY_KEY); MemcachedAdapter adapter; try { Class<?> clazz = Class.forName(adapterClass); adapter = (MemcachedAdapter) clazz.newInstance(); } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } adapter.init(properties); return adapter; } HibernateCacheTimestamper populateTimestamper(Settings settings, OverridableReadOnlyProperties properties) { String timestamperClazzName = properties.getProperty(TIMESTAMPER_PROPERTY_KEY, DEFAULT_TIMESTAMPER_CLASS.getName()); HibernateCacheTimestamper timestamper; try { Class<?> clazz = Class.forName(timestamperClazzName); timestamper = (HibernateCacheTimestamper) clazz.newInstance(); } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } timestamper.setSettings(settings); timestamper.setProperties(properties); timestamper.setMemcachedAdapter(memcachedAdapter); timestamper.init(); return timestamper; } @Override public void stop() { log.debug("# stop Hibernate4MemcachedRegionFactory."); memcachedAdapter.destroy(); } @Override public boolean isMinimalPutsEnabledByDefault() { return false; } @Override public AccessType getDefaultAccessType() { return AccessType.NONSTRICT_READ_WRITE; } @Override public long nextTimestamp() { return hibernateCacheTimestamper.next(); } @Override public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException { return new EntityMemcachedRegion(regionName, new OverridableReadOnlyPropertiesImpl(properties, cacheProviderConfigProperties), metadata, settings, memcachedAdapter, hibernateCacheTimestamper); } @Override public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException { return new NaturalIdMemcachedRegion(regionName, new OverridableReadOnlyPropertiesImpl(properties, cacheProviderConfigProperties), metadata, settings, memcachedAdapter, hibernateCacheTimestamper); } @Override public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException { return new CollectionMemcachedRegion(regionName, new OverridableReadOnlyPropertiesImpl(properties, cacheProviderConfigProperties), metadata, settings, memcachedAdapter, hibernateCacheTimestamper); } @Override public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException { return new QueryResultsMemcachedRegion(regionName, new OverridableReadOnlyPropertiesImpl(properties, cacheProviderConfigProperties), settings, memcachedAdapter, hibernateCacheTimestamper); } @Override public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException { return new TimestampMemcachedRegion(regionName, new OverridableReadOnlyPropertiesImpl(properties, cacheProviderConfigProperties), settings, memcachedAdapter, hibernateCacheTimestamper); } }