/* * Copyright (C) 2005-2012 BetaCONCEPT Limited * * This file is part of Astroboa. * * Astroboa is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Astroboa is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Astroboa. If not, see <http://www.gnu.org/licenses/>. */ package org.betaconceptframework.astroboa.test.engine.cache; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.commons.collections.CollectionUtils; import org.betaconceptframework.astroboa.api.model.ContentObject; import org.betaconceptframework.astroboa.api.model.RepositoryUser; import org.betaconceptframework.astroboa.api.model.Topic; import org.betaconceptframework.astroboa.api.model.io.FetchLevel; import org.betaconceptframework.astroboa.api.model.io.ResourceRepresentationType; import org.betaconceptframework.astroboa.api.model.query.CacheRegion; import org.betaconceptframework.astroboa.api.model.query.CmsOutcome; import org.betaconceptframework.astroboa.api.model.query.criteria.TopicCriteria; import org.betaconceptframework.astroboa.engine.cache.CmsRepositoryCache; import org.betaconceptframework.astroboa.engine.cache.regions.JcrQueryCacheRegion; import org.betaconceptframework.astroboa.model.factory.CmsCriteriaFactory; import org.betaconceptframework.astroboa.test.AstroboaTestContext; import org.betaconceptframework.astroboa.test.engine.AbstractRepositoryTest; import org.jboss.cache.Fqn; import org.jboss.cache.Node; import org.testng.Assert; import org.testng.annotations.Test; /** * @author Gregory Chomatas (gchomatas@betaconcept.com) * @author Savvas Triantafyllou (striantafyllou@betaconcept.com) * */ public class JcrCacheTest extends AbstractRepositoryTest{ private CmsRepositoryCache cmsRepositoryCache; private JcrQueryCacheRegion jcrQueryCacheRegion; @Test public void testContentObjectCahe() throws Throwable{ //Create content object for test RepositoryUser systemUser = getSystemUser(); ContentObject contentObject = createContentObject(systemUser, "testContentObjectCache"); contentObject = contentService.save(contentObject, false, true, null); //Create one version contentObject.setSystemName("testContentObjectCache"); contentObject = contentService.save(contentObject, false, true, null); markObjectForRemoval(contentObject); contentObject = contentService.getContentObject(contentObject.getId(), ResourceRepresentationType.CONTENT_OBJECT_INSTANCE, FetchLevel.ENTITY, CacheRegion.NONE, null, false); //Double check directly to cache Fqn contentObjectCacheFQN = JcrQueryCacheRegion.constructJcrQueryFQN(contentObject.getId(), CacheRegion.FIVE_MINUTES); Assert.assertFalse(cmsRepositoryCache.getCache().getRoot().hasChild(contentObjectCacheFQN), "ContentObject "+ contentObject.getId() + " has been cached under region "+ contentObjectCacheFQN); //Now cache results in every possible region and perform the same tests for (CacheRegion cacheRegion : CacheRegion.values()){ String contentObjectIdentifier = contentObject.getId(); Fqn parentFqn = Fqn.fromRelativeElements(JcrQueryCacheRegion.JCR_QUERY_NODE_FQN, cacheRegion.getRegionName(), authenticationToken); Object contentObjectResult = contentService.getContentObject(contentObjectIdentifier, ResourceRepresentationType.CONTENT_OBJECT_INSTANCE, FetchLevel.ENTITY, cacheRegion, null, false); checkContentObjectCache(contentObjectResult, cacheRegion, contentObjectIdentifier, parentFqn, "CONTENT_OBJECT_INSTANCE"); contentObjectResult = contentService.getContentObject(contentObjectIdentifier, ResourceRepresentationType.XML, FetchLevel.ENTITY, cacheRegion, null, true); checkContentObjectCache(contentObjectResult, cacheRegion, contentObjectIdentifier, parentFqn, "XML"); contentObjectResult = contentService.getContentObject(contentObjectIdentifier, ResourceRepresentationType.JSON, FetchLevel.ENTITY, cacheRegion, null, true); checkContentObjectCache(contentObjectResult, cacheRegion, contentObjectIdentifier, parentFqn,"JSON"); contentObjectResult = contentService.getContentObject(contentObjectIdentifier, ResourceRepresentationType.CONTENT_OBJECT_LIST, FetchLevel.ENTITY, cacheRegion, null, false); checkContentObjectCache(contentObjectResult, cacheRegion, contentObjectIdentifier, parentFqn, "CONTENT_OBJECT_LIST"); } //Finally remove all cached results jcrQueryCacheRegion.removeCacheEntriesForAuthenticationToken(authenticationToken); for (CacheRegion cacheRegion : CacheRegion.values()){ Fqn authenticationTokenFqn = Fqn.fromRelativeElements(JcrQueryCacheRegion.JCR_QUERY_NODE_FQN,cacheRegion.getRegionName(), authenticationToken); Assert.assertTrue(! cmsRepositoryCache.getCache().getRoot().hasChild(authenticationTokenFqn), "Cache node was not removed "+ authenticationTokenFqn.toString()+ " \n"+ dumpCacheToLog()); } } private void checkContentObjectCache(Object returnedResult, CacheRegion cacheRegion, String contentObjectIdentifier, Fqn parentFqn, String cacheKey) throws Throwable { if (cacheKey == null){ cacheKey = contentObjectIdentifier; } try{ Fqn contentObjectCacheFQN = JcrQueryCacheRegion.constructJcrQueryFQN(contentObjectIdentifier, cacheRegion); final Object contentObjectFromCache = jcrQueryCacheRegion.getContentObjectFromCache(contentObjectIdentifier, cacheRegion, cacheKey); Assert.assertNotNull(returnedResult, "Did not returned newly created content object test for jcr cache "+ cacheRegion); if (cacheRegion != CacheRegion.NONE){ //Results should be cached Assert.assertNotNull(contentObjectFromCache, "ContentObject "+contentObjectIdentifier+ " is not cached in region "+ cacheRegion ); Assert.assertSame(returnedResult, contentObjectFromCache, " Cache did not return the same objects for caching content object "+ contentObjectIdentifier+" in region "+ cacheRegion+ " under key "+cacheKey); Assert.assertTrue(cmsRepositoryCache.getCache().getRoot().hasChild(contentObjectCacheFQN),"ContentObject "+contentObjectIdentifier+" has not been cached in region "+ cacheRegion); final Node node = (Node)cmsRepositoryCache.getCache().getRoot().getChild(contentObjectCacheFQN); Assert.assertTrue(node.getKeys().contains(cacheKey),"ContentObject "+contentObjectIdentifier+" has been cached in region "+ cacheRegion + " but no key "+ cacheKey + " exists inside this region \n"+ node.getData()); //Finally FQN should contain CacheRegion and authentication token Assert.assertTrue(contentObjectCacheFQN.isChildOf(parentFqn), "Query results are stored under the wrong FQN " + contentObjectCacheFQN + "Its parent FQN should be "+parentFqn.toString() + " but was " + contentObjectCacheFQN.getParent().toString() + " instead."); } else{ //Results should not be cached Assert.assertNull(contentObjectFromCache, "ContentObject "+contentObjectIdentifier+" is cached in region "+ cacheRegion ); //Double check directly to cache contentObjectCacheFQN = JcrQueryCacheRegion.constructJcrQueryFQN(contentObjectIdentifier, cacheRegion); Assert.assertFalse(cmsRepositoryCache.getCache().getRoot().hasChild(contentObjectCacheFQN), "ContentObject "+contentObjectIdentifier+ " has been cached in region "+ cacheRegion); } } catch(Throwable t){ logger.error("Cache dump " + dumpCacheToLog()); throw t; } } private String dumpCacheToLog() { return dumpNodeToLogError(cmsRepositoryCache.getCache().getRoot()); } @Test public void testAuthenticationTokenRegion() throws Exception{ //Create a test topic Topic topic = cmsRepositoryEntityFactory.newTopic(); topic.setName("topicTestForJcrCache"); topic.addLocalizedLabel("en", "topicTestForJcrCache"); topic.setOwner(getSystemUser()); topic.setTaxonomy(taxonomyService.getBuiltInSubjectTaxonomy("el")); topic = topicService.save(topic); markTopicForRemoval(topic); //Create a simple query TopicCriteria topicCriteria = CmsCriteriaFactory.newTopicCriteria(); topicCriteria.addNameEqualsCriterion("topicTestForJcrCache"); topicCriteria.setOffsetAndLimit(0,1); topicCriteria.doNotCacheResults(); //Execute query CmsOutcome<Topic> outcome = topicService.searchTopics(topicCriteria, ResourceRepresentationType.TOPIC_LIST); Assert.assertTrue(outcome != null && outcome.getCount() == 1, "Did not returned newly created topic test for jcr cache"); //Results should not be cached Assert.assertNull(jcrQueryCacheRegion.getJcrQueryResults(topicCriteria), "Query results are cached but they should not be."+ " \n"+ dumpCacheToLog() ); //Double check directly to cache Fqn queryCacheFQN = JcrQueryCacheRegion.constructJcrQueryFQN(topicCriteria.getXPathQuery(), topicCriteria.getCacheRegion()); Assert.assertTrue(! cmsRepositoryCache.getCache().getRoot().hasChild(queryCacheFQN), "Query "+ topicCriteria.getXPathQuery() + " has been cached under region "+ queryCacheFQN+ " \n"+ dumpCacheToLog()); //Now cache results in every possible region and perform the same tests for (CacheRegion cacheRegion : CacheRegion.values()){ Fqn parentFqn = Fqn.fromRelativeElements(JcrQueryCacheRegion.JCR_QUERY_NODE_FQN,cacheRegion.getRegionName(), authenticationToken); topicCriteria.setCacheable(cacheRegion); //Execute query outcome = topicService.searchTopics(topicCriteria, ResourceRepresentationType.TOPIC_LIST); Assert.assertTrue(outcome != null && outcome.getCount() == 1, "Did not return newly created topic test for jcr cache. "+ " \n"+ dumpCacheToLog()); if (cacheRegion != CacheRegion.NONE){ //Results should be cached Assert.assertNotNull(jcrQueryCacheRegion.getJcrQueryResults(topicCriteria), "Query results are not cached in region "+ cacheRegion + " \n"+ dumpCacheToLog()); //Double check directly to cache queryCacheFQN = JcrQueryCacheRegion.constructJcrQueryFQN(topicCriteria.getXPathQuery(), topicCriteria.getCacheRegion()); Assert.assertTrue(cmsRepositoryCache.getCache().getRoot().hasChild(queryCacheFQN), "Query "+ topicCriteria.getXPathQuery() + " has not been cached under region "+ queryCacheFQN+ " \n"+ dumpCacheToLog()); //Finally FQN should contain CacheRegion and authentication token Assert.assertTrue(queryCacheFQN.isChildOf(parentFqn), "Query results are stored under the wrong FQN " + queryCacheFQN + "Its parent FQN should be "+parentFqn.toString()+ " but was " + queryCacheFQN.getParent().toString() + " instead."+ " \n"+ dumpCacheToLog()); } else{ //Results should not be cached Assert.assertNull(jcrQueryCacheRegion.getJcrQueryResults(topicCriteria), "Query results are cached in region "+ cacheRegion + " \n"+ dumpCacheToLog()); //Double check directly to cache queryCacheFQN = JcrQueryCacheRegion.constructJcrQueryFQN(topicCriteria.getXPathQuery(), topicCriteria.getCacheRegion()); Assert.assertFalse(cmsRepositoryCache.getCache().getRoot().hasChild(queryCacheFQN), "Query "+ topicCriteria.getXPathQuery() + " has been cached under region "+ queryCacheFQN+ " \n"+ dumpCacheToLog()); } } //Finally remove all cached results jcrQueryCacheRegion.removeCacheEntriesForAuthenticationToken(authenticationToken); for (CacheRegion cacheRegion : CacheRegion.values()){ if (cacheRegion != CacheRegion.NONE){ Fqn authenticationTokenFqn = Fqn.fromRelativeElements(JcrQueryCacheRegion.JCR_QUERY_NODE_FQN,cacheRegion.getRegionName(), authenticationToken); Assert.assertTrue(! cmsRepositoryCache.getCache().getRoot().hasChild(authenticationTokenFqn), "Cache node was not removed "+ authenticationTokenFqn.toString()+ " \n"+ dumpCacheToLog()); } } } private String dumpNodeToLogError(Node node){ StringBuffer sb = new StringBuffer(); sb.append(node.getFqn().toString()); sb.append("\n"); if (node.dataSize() > 0){ Map data = node.getData(); sb.append("Data\n"); for (Iterator it = data.keySet().iterator(); it.hasNext();) { Object key = it.next(); sb.append("\tKey: "); sb.append(key); sb.append("\tValue: "); sb.append(data.get(key)); sb.append("\n"); } } Set children = node.getChildren(); if (CollectionUtils.isNotEmpty(children)){ for (Iterator iterator = children.iterator(); iterator.hasNext();) { Node childNode = (Node) iterator.next(); sb.append(dumpNodeToLogError(childNode)); } } return sb.toString(); } @Override protected void postSetup() throws Exception { super.postSetup(); cmsRepositoryCache = (CmsRepositoryCache) AstroboaTestContext.INSTANCE.getApplicationContext().getBean("cmsRepositoryCache"); jcrQueryCacheRegion = (JcrQueryCacheRegion) AstroboaTestContext.INSTANCE.getApplicationContext().getBean("jcrQueryCacheRegion"); } }