package org.hoteia.qalingo.core.web.cache.util; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.xml.XMLConstants; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.SchemaFactory; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.aspectj.lang.reflect.MethodSignature; import org.ehcache.Cache; import org.ehcache.CacheManager; import org.ehcache.xml.XmlConfiguration; import org.ehcache.xml.model.BaseCacheType; import org.ehcache.xml.model.CacheType; import org.ehcache.xml.model.ConfigType; import org.hoteia.qalingo.core.annotation.CacheEntityInformation; import org.hoteia.qalingo.core.domain.AbstractEntity; import org.hoteia.qalingo.core.domain.impl.DomainEntity; import org.hoteia.qalingo.core.fetchplan.FetchPlan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; import org.w3c.dom.Element; import org.xml.sax.SAXException; @Service("cacheService") public class CacheService { protected final Log logger = LogFactory.getLog(getClass()); @Autowired private CacheManager cacheManager; @Autowired protected ApplicationContext applicationContext; @Value("${cache.configuration.location}") protected String ehcacheConfiguration; public List<CacheType> getCaches() { List<CacheType> caches = new ArrayList<CacheType>(); try { Resource resource = applicationContext.getResource(ehcacheConfiguration); Class<ConfigType> configTypeClass = ConfigType.class; JAXBContext jaxbContext = JAXBContext.newInstance(ConfigType.class.getPackage().getName(), configTypeClass.getClassLoader()); Collection<Source> schemaSources = new ArrayList<Source>(); schemaSources.add(new StreamSource(XmlConfiguration.class.getResource("/ehcache-core.xsd").openStream())); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); factory.setIgnoringComments(true); factory.setIgnoringElementContentWhitespace(true); factory.setSchema(SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(schemaSources.toArray(new Source[schemaSources.size()]))); DocumentBuilder domBuilder = factory.newDocumentBuilder(); Element dom = domBuilder.parse(resource.getFile()).getDocumentElement(); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); ConfigType config = unmarshaller.unmarshal(dom, configTypeClass).getValue(); List<BaseCacheType> baseCacheTypes = config.getCacheOrCacheTemplate(); for (BaseCacheType baseCacheType : baseCacheTypes) { caches.add((CacheType)baseCacheType); } } catch (JAXBException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } return caches; } public void flushCaches(List<CacheType> caches) throws ClassNotFoundException { for (CacheType cache : caches) { flushCache(cache); } } public void flushCache(CacheType cache) throws ClassNotFoundException { if(cache != null){ Cache cacheRuntime = getCache(cache.getAlias(), Class.forName(cache.getKeyType().getValue()), Class.forName(cache.getValueType().getValue())); cacheRuntime.clear(); } } public Cache getCache(String cacheAlias, Class key, Class type) throws ClassNotFoundException { if(StringUtils.isNotEmpty(cacheAlias)){ return cacheManager.getCache(cacheAlias, key, type); } return null; } public void flushCacheEntity(String cacheAlias) throws ClassNotFoundException { if(StringUtils.isNotEmpty(cacheAlias)){ Cache cache = getCache(cacheAlias, String.class, DomainEntity.class); cache.clear(); } } public void flushCacheEntity(String entityClass, String id) { if(StringUtils.isNotEmpty(entityClass) && StringUtils.isNotEmpty(id)){ try { Class classObject = Class.forName(entityClass); CacheEntityInformation cacheEntityInformation = (CacheEntityInformation) classObject.getAnnotation(CacheEntityInformation.class); String cacheName = cacheEntityInformation.cacheName(); logger.debug("CacheEntityInformation from annotation : cacheName= '" + cacheName + "'"); String key = buildEntityKey(classObject, id); Cache cache = cacheManager.getCache(cacheName, String.class, AbstractEntity.class); cache.remove(key); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } public String buildCommonKey(MethodSignature signature, Object[] args){ StringBuffer key = new StringBuffer(); key.append(signature.toShortString()); if(args != null && args.length > 0){ for (Object arg : args) { if (arg instanceof DomainEntity) { AbstractEntity argEntity = (AbstractEntity) arg; Method[] methods = argEntity.getClass().getMethods(); for (Method methodIt : methods) { if (methodIt.getName().equals("getId")) { Long id; try { id = (Long) methodIt.invoke(argEntity); key.append("_"); key.append(id); } catch (Exception e) { // NOTHING } } } } else { if (arg != null && !(arg instanceof Object[]) && !(arg instanceof DomainEntity)&& !(arg instanceof FetchPlan)) { key.append("_"); key.append(arg.toString()); } } } } return key.toString(); } public String buildEntityKey(Class classReturnType, String id){ StringBuffer key = new StringBuffer(); key.append(classReturnType.getName()); key.append("_"); key.append(id); return key.toString(); } public String buildCodeIdKey(MethodSignature signature, String code){ StringBuffer key = new StringBuffer(); Class classReturnType = signature.getReturnType(); key.append(classReturnType.getName()); key.append("_"); key.append(code); return key.toString(); } // public String buildCodeIdKey(MethodSignature signature, Object[] args){ // String code = null; // if(args != null && args.length > 0){ // for (Object arg : args) { // if (arg != null && !(arg instanceof Object[]) && !(arg instanceof AbstractEntity)&& !(arg instanceof FetchPlan)) { // code = arg.toString(); // } // } // } // return buildCodeIdKey(signature, code); // } }