/*
* Copyright 2006 GigaSpaces, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springmodules.cache.provider.gigaspaces;
import com.j_spaces.map.CacheFinder;
import com.j_spaces.map.IMap;
import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
import org.springframework.util.ObjectUtils;
import org.springmodules.cache.CacheException;
import org.springmodules.cache.CachingModel;
import org.springmodules.cache.FatalCacheException;
import org.springmodules.cache.FlushingModel;
import org.springmodules.cache.provider.AbstractCacheProviderFacade;
import org.springmodules.cache.provider.CacheAccessException;
import org.springmodules.cache.provider.CacheModelValidator;
import org.springmodules.cache.provider.CacheNotFoundException;
import org.springmodules.cache.provider.ObjectCannotBeCachedException;
import org.springmodules.cache.provider.ReflectionCacheModelEditor;
import java.beans.PropertyEditor;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* Implementation of
* <code>{@link org.springmodules.cache.provider.CacheProviderFacade}</code>
* that uses GigaSpaces as the underlying cache implementation.
*
* @author Omar Irbouh
* @author Lior Ben Yizhak
*/
public final class GigaSpacesFacade extends AbstractCacheProviderFacade {
private CacheModelValidator cacheModelValidator;
private Map cachesHolder = new HashMap();
/**
* Constructor.
*/
public GigaSpacesFacade() {
super();
cacheModelValidator = new GigaSpacesModelValidator();
}
/**
* Returns the validator of cache models. It is always an instance of
* <code>{@link GigaSpacesModelValidator}</code>.
*
* @return the validator of cache models
*/
public CacheModelValidator modelValidator() {
return cacheModelValidator;
}
/**
* @see org.springmodules.cache.provider.CacheProviderFacade#getCachingModelEditor()
*/
public PropertyEditor getCachingModelEditor() {
ReflectionCacheModelEditor editor = new ReflectionCacheModelEditor();
editor.setCacheModelClass(GigaSpacesCachingModel.class);
return editor;
}
/**
* @see org.springmodules.cache.provider.CacheProviderFacade#getFlushingModelEditor()
*/
public PropertyEditor getFlushingModelEditor() {
Map propertyEditors = new HashMap();
propertyEditors.put("cacheNames", new StringArrayPropertyEditor());
ReflectionCacheModelEditor editor = new ReflectionCacheModelEditor();
editor.setCacheModelClass(GigaSpacesFlushingModel.class);
editor.setCacheModelPropertyEditors(propertyEditors);
return editor;
}
/**
* Returns a GigaSpaces cache from the cache manager.
*
* @param model the model containing the name of the cache to retrieve
* @return the cache retrieved from the cache manager
* @throws CacheNotFoundException if the cache does not exist
* @throws CacheAccessException wrapping any unexpected exception thrown by the cache
*/
protected IMap getCache(CachingModel model) throws CacheNotFoundException,
CacheAccessException {
GigaSpacesCachingModel gigaSpacesCachingModel = (GigaSpacesCachingModel) model;
String cacheName = gigaSpacesCachingModel.getCacheName();
return getCache(cacheName);
}
/**
* Returns a GigaSpaces cache from the cache manager.
*
* @param name the name of the cache
* @return the cache retrieved from the cache manager
* @throws CacheNotFoundException if the cache does not exist
* @throws CacheAccessException wrapping any unexpected exception thrown by the cache
*/
protected IMap getCache(String name) throws CacheNotFoundException,
CacheAccessException {
IMap cache = (IMap) cachesHolder.get(name);
try {
if (cache == null) {
cache = (IMap) CacheFinder.find(name);
cachesHolder.put(name, cache);
}
} catch (Exception exception) {
throw new CacheAccessException(exception);
}
if (cache == null) {
throw new CacheNotFoundException(name);
}
return cache;
}
/**
* @return <code>true</code>. GigaSpaces can only store Serializable objects
* @see AbstractCacheProviderFacade#isSerializableCacheElementRequired()
*/
protected boolean isSerializableCacheElementRequired() {
return false;
}
/**
* Removes all the entries in the caches specified in the given flushing
* model. The flushing model should be an instance of
* <code>{@link GigaSpacesFlushingModel}</code>.
*
* @param model the flushing model.
* @throws CacheNotFoundException if the cache specified in the given model cannot be found.
* @throws CacheAccessException wrapping any unexpected exception thrown by the cache.
* @see AbstractCacheProviderFacade#onFlushCache(FlushingModel)
*/
protected void onFlushCache(FlushingModel model) throws CacheException {
GigaSpacesFlushingModel flushingModel = (GigaSpacesFlushingModel) model;
String[] cacheNames = flushingModel.getCacheNames();
if (!ObjectUtils.isEmpty(cacheNames)) {
CacheException cacheException = null;
int nameCount = cacheNames.length;
try {
for (int i = 0; i < nameCount; i++) {
IMap cache = getCache(cacheNames[i]);
cache.clear();
}
} catch (CacheException exception) {
cacheException = exception;
} catch (Exception exception) {
cacheException = new CacheAccessException(exception);
}
if (cacheException != null) {
throw cacheException;
}
}
}
/**
* Retrieves an object stored under the given key from the cache specified in
* the given caching model. The caching model should be an instance of
* <code>{@link GigaSpacesCachingModel}</code>.
*
* @param key the key of the cache entry
* @param model the caching model
* @return the object retrieved from the cache. Can be <code>null</code>.
* @throws CacheNotFoundException if the cache specified in the given model cannot be found.
* @throws CacheAccessException wrapping any unexpected exception thrown by the cache.
* @see AbstractCacheProviderFacade#onGetFromCache(Serializable,CachingModel)
*/
protected Object onGetFromCache(Serializable key, CachingModel model)
throws CacheException {
IMap cache = getCache(model);
GigaSpacesCachingModel gigaSpacesCachingModel = (GigaSpacesCachingModel) model;
Object cachedObject;
try {
Long waitForResponse = gigaSpacesCachingModel.getWaitForResponse();
if (waitForResponse != null) {
cachedObject = cache.get(key, waitForResponse.longValue());
} else {
cachedObject = cache.get(key);
}
} catch (Exception exception) {
throw new CacheAccessException(exception);
}
return cachedObject;
}
/**
* Stores the given object under the given key in the cache specified in the
* given caching model. The caching model should be an instance of
* <code>{@link GigaSpacesCachingModel}</code>.
*
* @param key the key of the cache entry
* @param model the caching model
* @param obj the object to store in the cache
* @throws ObjectCannotBeCachedException if the object to store is not an implementation of
* <code>java.io.Serializable</code>.
* @throws CacheNotFoundException if the cache specified in the given model cannot be found.
* @throws CacheAccessException wrapping any unexpected exception thrown by the cache.
* @see AbstractCacheProviderFacade#onPutInCache(Serializable,CachingModel,
*Object)
*/
protected void onPutInCache(Serializable key, CachingModel model, Object obj)
throws CacheException {
try {
GigaSpacesCachingModel gigaSpacesCachingModel = (GigaSpacesCachingModel) model;
IMap cache = getCache(gigaSpacesCachingModel);
Long timeToLive = gigaSpacesCachingModel.getTimeToLive();
if (timeToLive != null) {
cache.put(key, obj, timeToLive.longValue());
} else {
cache.put(key, obj);
}
} catch (Exception exception) {
throw new CacheAccessException(exception);
}
}
/**
* Removes the object stored under the given key from the cache specified in
* the given caching model. The caching model should be an instance of
* <code>{@link GigaSpacesCachingModel}</code>.
*
* @param key the key of the cache entry
* @param model the caching model
* @throws CacheNotFoundException if the cache specified in the given model cannot be found.
* @throws CacheAccessException wrapping any unexpected exception thrown by the cache.
* @see AbstractCacheProviderFacade#onRemoveFromCache(Serializable,
*CachingModel)
*/
protected void onRemoveFromCache(Serializable key, CachingModel model)
throws CacheException {
IMap cache = getCache(model);
try {
cache.remove(key);
} catch (Exception exception) {
throw new CacheAccessException(exception);
}
}
/**
* @throws FatalCacheException if the cache manager is <code>null</code>.
* @see AbstractCacheProviderFacade#validateCacheManager()
*/
protected void validateCacheManager() throws FatalCacheException {
// No implementation.
}
}