/**
* Copyright 2008-2016 Qualogy Solutions B.V.
*
* 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 com.qualogy.qafe.core.datastore;
import java.util.Date;
import java.util.Map;
import java.util.logging.Logger;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
import com.qualogy.qafe.bind.core.application.ApplicationContext;
import com.qualogy.qafe.bind.integration.service.Method;
import com.qualogy.qafe.bind.integration.service.ServiceRef;
import com.qualogy.qafe.platform.distribution.DistributionFactory;
public class CacheHandler {
private final static Logger logger = Logger.getLogger(CacheHandler.class.getName());
public final static String KEY_SHARED_CACHE = "$SHARED_CACHING";
public final static String KEY_DELIMITER = "_$$_";
public final static int NO_CACHING = -1;
public final static int UNLIMITED_CACHING = 0;
private static CacheHandler instance = null;
private Map<Long,CacheObject> store;
public static CacheHandler getInstance() {
if (instance == null) {
instance = new CacheHandler();
}
return instance;
}
private CacheHandler() {
store = DistributionFactory.getInstance().getDistributionManager().getCacheManager().getDistributedMap(KEY_SHARED_CACHE);
}
public void store(String key, Object value) {
store.put(getChecksumValue(key), new CacheObject(value));
}
public Object retrieve(String key) {
Object cacheObject = store.get(getChecksumValue(key));
if(cacheObject != null) {
return ((CacheObject)cacheObject).getValue();
}
return null;
}
public boolean contains(String key) {
return store.containsKey(getChecksumValue(key));
}
public void remove(String key) {
store.remove(getChecksumValue(key));
}
public boolean isCached(ServiceRef serviceRef) {
if (serviceRef != null) {
Method method = serviceRef.getMethod();
long cachDuration = getCacheDuration(method);
if (cachDuration > NO_CACHING) {
return true;
}
}
return false;
}
public boolean hasCache(ApplicationContext applicationContext, ServiceRef serviceRef, String cacheToken) {
if (isCached(serviceRef)) {
String cacheKey = generateKey(applicationContext, serviceRef, cacheToken);
if (store.containsKey(getChecksumValue(cacheKey))) {
Method method = serviceRef.getMethod();
if (!isCacheExpired(cacheKey, method)) {
return true;
}
}
}
return false;
}
public String generateKey(ApplicationContext applicationContext, ServiceRef serviceRef, String cacheToken) {
if ((serviceRef != null) && (applicationContext != null)) {
Method method = serviceRef.getMethod();
String applicationId = applicationContext.getId().toString();
String serviceId = serviceRef.getRef().getId();
String methodId = method.getId();
return generate(applicationId, serviceId, methodId, cacheToken);
}
return null;
}
private boolean isCacheExpired(String cacheKey, Method method) {
long expiration = getCacheDuration(method);
if(expiration == UNLIMITED_CACHING) {
return false;
}
Date cacheStartTime = store.get(getChecksumValue(cacheKey)).getStartTime();
if (cacheStartTime != null) {
expiration += cacheStartTime.getTime();
}
Date currentTime = new Date();
return (currentTime.getTime() > expiration);
}
private long getCacheDuration(Method method) {
if (method != null) {
return method.getCache();
}
return NO_CACHING;
}
private String generate(String... values) {
StringBuffer sb = new StringBuffer();
if (values != null) {
for (int i=0; i<values.length; i++) {
String value = values[i];
if (value != null) {
String delimiter = KEY_DELIMITER;
if (i == 0) {
delimiter = "";
}
sb.append(delimiter + value);
}
}
}
if (sb.length() != 0) {
return sb.toString();
}
return null;
}
public static Long getChecksumValue(String key) {
Checksum checksum = new CRC32();
byte[] bytes = key.getBytes();
checksum.update(key.getBytes(), 0, bytes.length);
return checksum.getValue();
}
class CacheObject {
private Object value;
private Date startTime;
public CacheObject(Object value) {
this.value = value;
this.startTime = new Date();
}
public Object getValue() {
return value;
}
public Date getStartTime() {
return startTime;
}
}
}