Java tutorial
/** * Most of the code in the Qalingo project is copyrighted Hoteia and licensed * under the Apache License Version 2.0 (release version 0.8.0) * http://www.apache.org/licenses/LICENSE-2.0 * * Copyright (c) Hoteia, 2012-2014 * http://www.hoteia.com - http://twitter.com/hoteia - contact@hoteia.com * */ package org.hoteia.qalingo.core.aop.cache; import java.lang.reflect.Field; import java.lang.reflect.Method; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.hoteia.qalingo.core.domain.AbstractEntity; import org.hoteia.qalingo.core.fetchplan.FetchPlan; import org.hoteia.qalingo.core.pojo.RequestData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.ehcache.EhCacheCacheManager; import org.springframework.stereotype.Component; @Component(value = "cacheManagementAspect") public class CacheManagementAspect { private final Logger logger = LoggerFactory.getLogger(getClass()); public static final String DEFAULT_CACHE_NAME = "web_cache_common"; public static final String CACHE_NAME = "CACHE_NAME"; public static final String CACHE_TYPE_MISC = "CACHE_TYPE_MISC"; public static final String CACHE_BY_ID = "CACHE_BY_ID"; public static final String CACHE_BY_CODE = "CACHE_BY_CODE"; @Autowired private EhCacheCacheManager ehCacheCacheManager; public Object around(ProceedingJoinPoint joinPoint) throws Throwable { Object returnObject = null; try { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Class classTarget = signature.getReturnType(); Object[] args = joinPoint.getArgs(); String suffix = ""; FetchPlan askedFetchPlan = null; FetchPlan loadedFetchPlan = null; String cacheType = CACHE_TYPE_MISC; // TOD : Denis : blind le code pour tester les arg differement entre une method get* et find* et autre if (joinPoint.getSignature().toShortString().contains("ById")) { // FIRST ARG IS A LONG FOR THE GET METHOD : SO THIS A GET BY ID cacheType = CACHE_BY_ID; } else if (joinPoint.getSignature().toShortString().contains("ByCode")) { // FIRST ARG IS A STRING FOR THE GET METHOD : SO THIS A GET BY CODE cacheType = CACHE_BY_CODE; } for (int i = 0; i < args.length; i++) { Object arg = args[i]; if (arg instanceof Object[]) { Object[] objects = (Object[]) arg; for (int j = 0; j < objects.length; j++) { Object object = (Object) objects[j]; if (object instanceof FetchPlan) { FetchPlan fetchPlan = (FetchPlan) object; if (fetchPlan != null && !fetchPlan.getFetchModes().isEmpty()) { askedFetchPlan = fetchPlan; } } } } if (arg instanceof RequestData) { RequestData requestData = (RequestData) arg; if (!suffix.endsWith("_")) { suffix = suffix + "_"; } suffix = suffix + requestData.getMarketPlace().getCode() + "_" + requestData.getMarket().getCode() + "_" + requestData.getMarketArea().getCode() + "_" + requestData.getMarketAreaLocalization().getCode() + "_" + requestData.getMarketAreaRetailer().getCode() + "_" + requestData.getMarketAreaCurrency().getCode(); } else if (arg instanceof AbstractEntity) { AbstractEntity argEntity = (AbstractEntity) arg; if (!suffix.endsWith("_")) { suffix = suffix + "_"; } Method[] methods = argEntity.getClass().getMethods(); for (int j = 0; j < methods.length; j++) { Method methodIt = methods[j]; if (methodIt.getName().equals("getId")) { Long id = (Long) methodIt.invoke(argEntity); suffix = suffix + id; } } } else { if (arg != null && !(arg instanceof java.lang.Object[]) && !(arg instanceof AbstractEntity)) { if (!suffix.endsWith("_")) { suffix = suffix + "_"; } suffix = suffix + arg.toString(); } } } String key = null; String cacheName = DEFAULT_CACHE_NAME; if (classTarget != null) { try { Field cacheField = null; Field[] fields = classTarget.getFields(); for (int i = 0; i < fields.length; i++) { Field fieldIt = fields[i]; if (fieldIt.getName().equals(CACHE_NAME)) { cacheField = fieldIt; } } if (cacheField != null) { cacheName = (String) cacheField.get(CACHE_NAME); } } catch (IllegalAccessException e) { if (logger.isDebugEnabled()) { logger.debug("IllegalAccessException code.", e); } } } // CACHE TYPE if (cacheType.equals(CACHE_TYPE_MISC)) { key = joinPoint.getSignature().toShortString() + suffix; if (!cacheName.contains("_misc")) { cacheName = cacheName + "_misc"; } } else if (cacheType.equals(CACHE_BY_CODE)) { // TODO : Denis : utiliser un cache de type cacheName_link_code_id pour avoir l'id en fonction du code key = classTarget.getName() + suffix; cacheName = cacheName + "_link_code_id"; } else { key = classTarget.getName() + suffix; } Cache cache = getCacheManager() != null && StringUtils.isNotEmpty(cacheName) ? getCacheManager().getCache(cacheName) : null; if (cache != null) { if (cache.isKeyInCache(key)) { Element element = cache.get(key); if (element != null && !element.isExpired()) { // WE TEST IF THE FETCH PLAN ARE EQUALS returnObject = element.getObjectValue(); if (returnObject instanceof AbstractEntity) { AbstractEntity entity = (AbstractEntity) returnObject; if (entity.getFetchPlan() != null) { loadedFetchPlan = entity.getFetchPlan(); } if (cacheType.equals(CACHE_BY_ID)) { // ENTITY : UPDATE THE CACHE LINK ID CODE String cacheNameIdCodeLink = cacheName + "_link_code_id"; Cache cacheLinkIdCode = getCacheManager() != null && StringUtils.isNotEmpty(cacheNameIdCodeLink) ? getCacheManager().getCache(cacheNameIdCodeLink) : null; if (cacheLinkIdCode != null) { String newKey = null; String codeValue = null; try { Method[] methods = classTarget.getMethods(); for (int i = 0; i < methods.length; i++) { Method methodIt = methods[i]; if (methodIt.getName().equals("getId")) { Long id = (Long) methodIt.invoke(returnObject); newKey = classTarget.getName() + "_" + id; } if (methodIt.getName().equals("getCode")) { codeValue = (String) methodIt.invoke(returnObject); } if (newKey != null && codeValue != null) { break; } } } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("IllegalAccessException.", e); } } if (newKey != null) { cacheLinkIdCode.put(new Element(newKey, codeValue)); } } } if (cacheType.equals(CACHE_BY_CODE)) { String cacheNameEntityById = cacheName.replace("_link_code_id", ""); Cache cacheEntityById = getCacheManager() != null && StringUtils.isNotEmpty(cacheNameEntityById) ? getCacheManager().getCache(cacheNameEntityById) : null; String newKey = null; Method[] methods = classTarget.getMethods(); for (int i = 0; i < methods.length; i++) { Method methodIt = methods[i]; if (methodIt.getName().equals("getId")) { Long id = (Long) methodIt.invoke(returnObject); newKey = classTarget.getName() + "_" + id; break; } } if (cacheEntityById != null) { if (cacheEntityById.isKeyInCache(newKey)) { Element elementEntityById = cacheEntityById.get(newKey); if (elementEntityById != null && !elementEntityById.isExpired()) { returnObject = elementEntityById.getObjectValue(); } } } } } else if (returnObject instanceof Long) { if (cacheType.equals(CACHE_BY_CODE)) { String cacheNameEntityById = cacheName.replace("_link_code_id", ""); Cache cacheEntityById = getCacheManager() != null && StringUtils.isNotEmpty(cacheNameEntityById) ? getCacheManager().getCache(cacheNameEntityById) : null; String newKey = classTarget.getName() + "_" + returnObject; if (cacheEntityById.isKeyInCache(newKey)) { Element finalElement = cacheEntityById.get(newKey); if (finalElement != null && !finalElement.isExpired()) { // WE WILL TEST IF THE FETCH PLAN ARE EQUALS returnObject = finalElement.getObjectValue(); } } else { // WE RESET THE returnObject WHICH HAS THE LONG VALUE - THIS WILL TRIGGER THE LOAD BY DAO returnObject = null; } } } } } if (returnObject == null) { if (loadedFetchPlan != null) { args = ArrayUtils.add(args, loadedFetchPlan); returnObject = joinPoint.proceed(args); } else { returnObject = joinPoint.proceed(); } if (returnObject != null && cacheType.equals(CACHE_BY_CODE)) { // PUT IN THE RIGHT ENTITY CACHE String cacheNameEntityById = cacheName.replace("_link_code_id", ""); Cache cacheEntityById = getCacheManager() != null && StringUtils.isNotEmpty(cacheNameEntityById) ? getCacheManager().getCache(cacheNameEntityById) : null; String newKey = null; Method[] methods = classTarget.getMethods(); Long value = null; for (int i = 0; i < methods.length; i++) { Method methodIt = methods[i]; if (methodIt.getName().equals("getId")) { Long id = (Long) methodIt.invoke(returnObject); newKey = classTarget.getName() + "_" + id; value = id; break; } } if (cacheEntityById != null) { cacheEntityById.put(new Element(newKey, returnObject)); } cache.put(new Element(key, value)); } else { cache.put(new Element(key, returnObject)); } } else { if (returnObject instanceof AbstractEntity) { AbstractEntity entity = (AbstractEntity) returnObject; if (entity.getFetchPlan() != null) { loadedFetchPlan = entity.getFetchPlan(); } if (askedFetchPlan != null) { if (loadedFetchPlan != null && !loadedFetchPlan.containAllTargetFetchPlans(askedFetchPlan)) { // ENTITY IS LOAD WITHOUT FETCHPLAN - WE RESET THE returnObject TO TRIGGER THE RELOAD WITH THE FETCHPLAN // WE WILL ADD LOADED FETCH PLAN AND ASKED FETCH PLAN TO THE INVOCATED METHOD returnObject = null; } // for (Iterator<SpecificFetchMode> iterator = askedFetchPlan.iterator(); iterator.hasNext();) { // SpecificFetchMode specificFetchMode = (SpecificFetchMode) iterator.next(); // if(loadedFetchPlan == null){ // // ENTITY IS LOAD WITHOUT FETCHPLAN - WE RESET THE returnObject TO TRIGGER THE RELOAD WITH THE FETCHPLAN // returnObject = null; // break; // } else if (!loadedFetchPlan.contains(specificFetchMode)){ // // ENTITY IS LOAD WITH A DIFF FETCHPLAN - WE RESET THE returnObject TO TRIGGER THE RELOAD // returnObject = null; // break; // } // } if (returnObject == null) { if (loadedFetchPlan != null) { for (int i = 0; i < args.length; i++) { Object arg = args[i]; if (arg instanceof Object[]) { Object[] objects = (Object[]) arg; for (int j = 0; j < objects.length; j++) { Object object = (Object) objects[j]; if (object instanceof FetchPlan) { // WE ARE IN THE FETCHPLAN OBJECT ARRAY objects = ArrayUtils.add(objects, entity.getFetchPlan()); args = ArrayUtils.remove(args, i); args = ArrayUtils.add(args, objects); break; } } } } returnObject = joinPoint.proceed(args); } // else { // returnObject = joinPoint.proceed(); // } if (returnObject != null) { if (cacheType.equals(CACHE_BY_CODE)) { // PUT IN THE RIGHT ENTITY CACHE String cacheNameEntityById = cacheName.replace("_link_code_id", ""); Cache cacheEntityById = getCacheManager() != null && StringUtils.isNotEmpty(cacheNameEntityById) ? getCacheManager().getCache(cacheNameEntityById) : null; String newKey = null; Method[] methods = classTarget.getMethods(); Long value = null; for (int i = 0; i < methods.length; i++) { Method methodIt = methods[i]; if (methodIt.getName().equals("getId")) { Long id = (Long) methodIt.invoke(returnObject); newKey = classTarget.getName() + "_" + id; value = id; break; } } if (cacheEntityById != null) { cacheEntityById.put(new Element(newKey, returnObject)); } cache.put(new Element(key, value)); } else { cache.put(new Element(key, returnObject)); } } } } } } } } catch (Exception e) { logger.error("Failed to load datas with Cache AOP!", e); } return returnObject; } public CacheManager getCacheManager() { return ehCacheCacheManager.getCacheManager(); } }