/* * Copyright (C) 2003-2010 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.services.jcr.impl.dataflow.persistent; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import org.databene.contiperf.PerfTest; import org.databene.contiperf.junit.ContiPerfRule; import org.exoplatform.services.jcr.JcrImplBaseTest; import org.exoplatform.services.jcr.config.WorkspaceEntry; import org.exoplatform.services.jcr.core.WorkspaceContainerFacade; import org.exoplatform.services.jcr.dataflow.ItemStateChangesLog; import org.exoplatform.services.jcr.dataflow.persistent.PersistedNodeData; import org.exoplatform.services.jcr.dataflow.persistent.PersistedPropertyData; import org.exoplatform.services.jcr.dataflow.persistent.WorkspaceStorageCache; import org.exoplatform.services.jcr.dataflow.persistent.WorkspaceStorageCacheListener; import org.exoplatform.services.jcr.datamodel.ItemData; import org.exoplatform.services.jcr.datamodel.ItemType; import org.exoplatform.services.jcr.datamodel.NodeData; import org.exoplatform.services.jcr.datamodel.PropertyData; import org.exoplatform.services.jcr.datamodel.QPath; import org.exoplatform.services.jcr.datamodel.QPathEntry; import org.exoplatform.services.jcr.datamodel.ValueData; import org.exoplatform.services.jcr.impl.Constants; import org.exoplatform.services.jcr.impl.core.PropertyImpl; import org.exoplatform.services.jcr.impl.core.itemfilters.ExactQPathEntryFilter; import org.exoplatform.services.jcr.impl.core.itemfilters.PatternQPathEntryFilter; import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter; import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder; import org.exoplatform.services.jcr.impl.storage.WorkspaceDataContainerBase; import org.exoplatform.services.jcr.storage.WorkspaceDataContainer; import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import java.io.FileInputStream; import java.io.InputStream; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.List; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.atomic.AtomicInteger; import javax.jcr.InvalidItemStateException; import javax.jcr.Node; import javax.jcr.PropertyType; import javax.jcr.RepositoryException; /** * Created by The eXo Platform SAS * Author : Nicolas Filotto * nicolas.filotto@exoplatform.com * 29 mars 2010 */ public class TestCacheableWorkspaceDataManager { private static final int TOTAL_THREADS = 100; private static final int TIMES = 20; private static final int TOTAL_TIMES = TIMES * TOTAL_THREADS; // We need it as a variable since to be compatible with JUnit 4, the class must not extend TestCase so we // cannot extend BaseVersionTest. But as we need all the logic inside, we use it as a variable private JcrImplBaseTest test; @Rule public ContiPerfRule rule = new ContiPerfRule(); private final AtomicInteger step = new AtomicInteger(); private CyclicBarrier startSignal = new CyclicBarrier(TOTAL_THREADS); private CacheableWorkspaceDataManager cwdm; private WorkspaceDataContainer wdc; private MyWorkspaceStorageConnection con; private NodeData nodeData; @Before public void setUp() throws Exception { this.test = new JcrImplBaseTest(); test.setUp(); this.con = new MyWorkspaceStorageConnection(); this.wdc = new MyWorkspaceDataContainer(con); WorkspaceContainerFacade wsc = test.getRepository().getWorkspaceContainer("ws"); WorkspaceEntry wconf = (WorkspaceEntry)wsc.getComponent(WorkspaceEntry.class); this.cwdm = new CacheableWorkspaceDataManager(wconf, wdc, new MyWorkspaceStorageCache(), new SystemDataContainerHolder(wdc)); } @After public void tearDown() throws Exception { this.con = null; this.wdc = null; this.cwdm = null; test.after(); } @Test @PerfTest(invocations = TOTAL_THREADS, threads = TOTAL_THREADS) public void testGetItemById() throws Exception { assertEquals(0, con.getItemDataByIdCalls.get()); startSignal.await(); for (int i = 0; i < TIMES; i++) { ItemData item = cwdm.getItemData("getItemData"); assertNotNull(item); } assertEquals(1, con.getItemDataByIdCalls.get()); } @Test @PerfTest(invocations = TOTAL_THREADS, threads = TOTAL_THREADS) public void testGetItemDataByNodeDataNQPathEntry() throws Exception { if (step.compareAndSet(0, 1)) { nodeData = new PersistedNodeData("getItemData", new QPath(new QPathEntry[]{}), null, 0, 1, null, null, null); } assertEquals(0, con.getItemDataByNodeDataNQPathEntryCalls.get()); startSignal.await(); for (int i = 0; i < TIMES; i++) { ItemData item = cwdm.getItemData(nodeData, new QPathEntry("http://www.foo.com", "foo", 0), ItemType.NODE); assertNotNull(item); } assertEquals(1, con.getItemDataByNodeDataNQPathEntryCalls.get()); } @Test @PerfTest(invocations = TOTAL_THREADS, threads = TOTAL_THREADS) public void testGetChildPropertiesData() throws Exception { if (step.compareAndSet(0, 1)) { nodeData = new PersistedNodeData("getChildPropertiesData", null, null, 0, 1, null, null, null); } assertEquals(0, con.getChildPropertiesDataCalls.get()); startSignal.await(); for (int i = 0; i < TIMES; i++) { List<PropertyData> properties = cwdm.getChildPropertiesData(nodeData); assertNotNull(properties); assertFalse(properties.isEmpty()); } assertEquals(1, con.getChildPropertiesDataCalls.get()); startSignal.await(); for (int i = 0; i < TIMES; i++) { List<PropertyData> properties = cwdm.getChildPropertiesData(nodeData, true); assertNotNull(properties); assertFalse(properties.isEmpty()); } startSignal.await(); assertEquals(1 + TOTAL_TIMES, con.getChildPropertiesDataCalls.get()); } @Test @PerfTest(invocations = TOTAL_THREADS, threads = TOTAL_THREADS) public void testListChildPropertiesData() throws Exception { if (step.compareAndSet(0, 1)) { nodeData = new PersistedNodeData("listChildPropertiesData", null, null, 0, 1, null, null, null); } assertEquals(0, con.listChildPropertiesDataCalls.get()); startSignal.await(); for (int i = 0; i < TIMES; i++) { List<PropertyData> properties = cwdm.listChildPropertiesData(nodeData); assertNotNull(properties); assertFalse(properties.isEmpty()); } assertEquals(1, con.listChildPropertiesDataCalls.get()); startSignal.await(); for (int i = 0; i < TIMES; i++) { List<PropertyData> properties = cwdm.listChildPropertiesData(nodeData, true); assertNotNull(properties); assertFalse(properties.isEmpty()); } startSignal.await(); assertEquals(1 + TOTAL_TIMES, con.listChildPropertiesDataCalls.get()); } @Test @PerfTest(invocations = TOTAL_THREADS, threads = TOTAL_THREADS) public void testGetChildNodes() throws Exception { if (step.compareAndSet(0, 1)) { nodeData = new PersistedNodeData("getChildNodes", null, null, 0, 1, null, null, null); } assertEquals(0, con.getChildNodesDataCalls.get()); startSignal.await(); for (int i = 0; i < TIMES; i++) { List<NodeData> nodes = cwdm.getChildNodesData(nodeData); assertNotNull(nodes); assertFalse(nodes.isEmpty()); } assertEquals(1, con.getChildNodesDataCalls.get()); startSignal.await(); for (int i = 0; i < TIMES; i++) { List<NodeData> nodes = cwdm.getChildNodesData(nodeData, true); assertNotNull(nodes); assertFalse(nodes.isEmpty()); } startSignal.await(); assertEquals(1 + TOTAL_TIMES, con.getChildNodesDataCalls.get()); } @Test @PerfTest(invocations = TOTAL_THREADS, threads = TOTAL_THREADS) public void testGetChildNodesCount() throws Exception { if (step.compareAndSet(0, 1)) { nodeData = new PersistedNodeData("getChildNodesCount", null, null, 0, 1, null, null, null); } assertEquals(0, con.getChildNodesCountCalls.get()); startSignal.await(); for (int i = 0; i < TIMES; i++) { int result = cwdm.getChildNodesCount(nodeData); assertEquals(1, result); } assertEquals(1, con.getChildNodesCountCalls.get()); } @Test public void testBigFileWithCacheEnabledById() throws Exception { WorkspaceContainerFacade wsc = test.getRepository().getWorkspaceContainer("ws"); CacheableWorkspaceDataManager cwdm = (CacheableWorkspaceDataManager)wsc.getComponent(CacheableWorkspaceDataManager.class); if (!cwdm.cache.isEnabled()) return; Node testLocalBigFiles = test.getRoot().addNode("testBigFileWithCacheEnabledById"); // 300 Kb String path = test.createBLOBTempFile(300).getAbsolutePath(); Node localBigFile = testLocalBigFiles.addNode("bigFile", "nt:file"); Node contentNode = localBigFile.addNode("jcr:content", "nt:resource"); InputStream is = new FileInputStream(path); PropertyImpl data = (PropertyImpl)contentNode.setProperty("jcr:data", is); contentNode.setProperty("jcr:mimeType", "application/octet-stream "); contentNode.setProperty("jcr:lastModified", Calendar.getInstance()); test.getSession().save(); String id = data.getInternalIdentifier(); PropertyData pData = (PropertyData)cwdm.getCachedItemData(id); assertNotNull(pData); List<ValueData> vals = pData.getValues(); assertTrue(vals != null); assertFalse(vals.isEmpty()); assertTrue(vals.get(0) instanceof StreamPersistedValueData); StreamPersistedValueData fpvd = (StreamPersistedValueData)vals.get(0); assertTrue(fpvd.getFile() != null || fpvd.getUrl() != null); assertTrue(cwdm.getItemData(id) == pData); // Simulate cases where the file is null such as during a replication of StreamPersistedValueData with a spool file as file // on all other cluster nodes the spool file doesn't exist so file will be set to null if (fpvd.getFile() != null) fpvd.setPersistedFile(null); else fpvd.setPersistedURL(null, false); assertFalse(cwdm.getItemData(id) == pData); assertTrue(cwdm.getItemData(id) == cwdm.getCachedItemData(id)); } @Test public void testBigFileWithCacheEnabledByPath() throws Exception { WorkspaceContainerFacade wsc = test.getRepository().getWorkspaceContainer("ws"); CacheableWorkspaceDataManager cwdm = (CacheableWorkspaceDataManager)wsc.getComponent(CacheableWorkspaceDataManager.class); if (!cwdm.cache.isEnabled()) return; Node testLocalBigFiles = test.getRoot().addNode("testBigFileWithCacheEnabledByPath"); // 300 Kb String path = test.createBLOBTempFile(300).getAbsolutePath(); Node localBigFile = testLocalBigFiles.addNode("bigFile", "nt:file"); Node contentNode = localBigFile.addNode("jcr:content", "nt:resource"); InputStream is = new FileInputStream(path); PropertyImpl data = (PropertyImpl)contentNode.setProperty("jcr:data", is); contentNode.setProperty("jcr:mimeType", "application/octet-stream "); contentNode.setProperty("jcr:lastModified", Calendar.getInstance()); test.getSession().save(); QPathEntry qpeProp = new QPathEntry(Constants.NS_JCR_URI, "data", 0); PropertyData pData = (PropertyData)cwdm.getCachedItemData(data.parentData(), qpeProp, ItemType.PROPERTY); assertNotNull(pData); List<ValueData> vals = pData.getValues(); assertTrue(vals != null); assertFalse(vals.isEmpty()); assertTrue(vals.get(0) instanceof StreamPersistedValueData); StreamPersistedValueData fpvd = (StreamPersistedValueData)vals.get(0); assertTrue(fpvd.getFile() != null || fpvd.getUrl() != null); assertTrue(cwdm.getItemData(data.parentData(), qpeProp, ItemType.PROPERTY) == pData); // Simulate cases where the file is null such as during a replication of StreamPersistedValueData with a spool file as file // on all other cluster nodes the spool file doesn't exist so file will be set to null if (fpvd.getFile() != null) fpvd.setPersistedFile(null); else fpvd.setPersistedURL(null, false); assertFalse(cwdm.getItemData(data.parentData(), qpeProp, ItemType.PROPERTY) == pData); assertTrue(cwdm.getItemData(data.parentData(), qpeProp, ItemType.PROPERTY) == cwdm.getCachedItemData( data.parentData(), qpeProp, ItemType.PROPERTY)); } @Test public void testBigFileWithCacheEnabledByProps() throws Exception { WorkspaceContainerFacade wsc = test.getRepository().getWorkspaceContainer("ws"); CacheableWorkspaceDataManager cwdm = (CacheableWorkspaceDataManager)wsc.getComponent(CacheableWorkspaceDataManager.class); if (!cwdm.cache.isEnabled()) return; Node testLocalBigFiles = test.getRoot().addNode("testBigFileWithCacheEnabledByProps"); // 300 Kb String path = test.createBLOBTempFile(300).getAbsolutePath(); Node localBigFile = testLocalBigFiles.addNode("bigFile", "nt:file"); Node contentNode = localBigFile.addNode("jcr:content", "nt:resource"); InputStream is = new FileInputStream(path); PropertyImpl data = (PropertyImpl)contentNode.setProperty("jcr:data", is); contentNode.setProperty("jcr:mimeType", "application/octet-stream "); contentNode.setProperty("jcr:lastModified", Calendar.getInstance()); test.getSession().save(); // Load cache first cwdm.getChildPropertiesData(data.parentData()); List<PropertyData> props = cwdm.cache.getChildProperties(data.parentData()); PropertyData pData = null; for (PropertyData pd : props) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData = pd; break; } } assertNotNull(pData); List<ValueData> vals = pData.getValues(); assertTrue(vals != null); assertFalse(vals.isEmpty()); assertTrue(vals.get(0) instanceof StreamPersistedValueData); StreamPersistedValueData fpvd = (StreamPersistedValueData)vals.get(0); assertTrue(fpvd.getFile() != null || fpvd.getUrl() != null); PropertyData pData2 = null; for (PropertyData pd : cwdm.getChildPropertiesData(data.parentData())) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData2 = pd; break; } } assertTrue(pData2 == pData); // Simulate cases where the file is null such as during a replication of StreamPersistedValueData with a spool file as file // on all other cluster nodes the spool file doesn't exist so file will be set to null if (fpvd.getFile() != null) fpvd.setPersistedFile(null); else fpvd.setPersistedURL(null, false); pData2 = null; for (PropertyData pd : cwdm.getChildPropertiesData(data.parentData())) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData2 = pd; break; } } assertFalse(pData2 == pData); pData2 = null; for (PropertyData pd : cwdm.getChildPropertiesData(data.parentData())) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData2 = pd; break; } } PropertyData pData3 = null; for (PropertyData pd : cwdm.cache.getChildProperties(data.parentData())) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData3 = pd; break; } } assertTrue(pData2 == pData3); } /** * Using getChildPropertiesData with parentData */ @Test public void testBigFileWithCacheEnabledByPattern1() throws Exception { WorkspaceContainerFacade wsc = test.getRepository().getWorkspaceContainer("ws"); CacheableWorkspaceDataManager cwdm = (CacheableWorkspaceDataManager)wsc.getComponent(CacheableWorkspaceDataManager.class); if (!cwdm.cache.isEnabled()) return; Node testLocalBigFiles = test.getRoot().addNode("testBigFileWithCacheEnabledByPattern1"); // 300 Kb String path = test.createBLOBTempFile(300).getAbsolutePath(); Node localBigFile = testLocalBigFiles.addNode("bigFile", "nt:file"); Node contentNode = localBigFile.addNode("jcr:content", "nt:resource"); InputStream is = new FileInputStream(path); PropertyImpl data = (PropertyImpl)contentNode.setProperty("jcr:data", is); contentNode.setProperty("jcr:mimeType", "application/octet-stream "); contentNode.setProperty("jcr:lastModified", Calendar.getInstance()); test.getSession().save(); // Load cache first cwdm.getChildPropertiesData(data.parentData()); List<PropertyData> props = cwdm.cache.getChildProperties(data.parentData()); PropertyData pData = null; for (PropertyData pd : props) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData = pd; break; } } assertNotNull(pData); List<ValueData> vals = pData.getValues(); assertTrue(vals != null); assertFalse(vals.isEmpty()); assertTrue(vals.get(0) instanceof StreamPersistedValueData); StreamPersistedValueData fpvd = (StreamPersistedValueData)vals.get(0); assertTrue(fpvd.getFile() != null || fpvd.getUrl() != null); PropertyData pData2 = null; List<QPathEntryFilter> itemDataFilters = Collections.singletonList((QPathEntryFilter)new PatternQPathEntryFilter(new QPathEntry("*", "*", 0))); for (PropertyData pd : cwdm.getChildPropertiesData(data.parentData(), itemDataFilters)) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData2 = pd; break; } } assertTrue(pData2 == pData); // Simulate cases where the file is null such as during a replication of StreamPersistedValueData with a spool file as file // on all other cluster nodes the spool file doesn't exist so file will be set to null if (fpvd.getFile() != null) fpvd.setPersistedFile(null); else fpvd.setPersistedURL(null, false); pData2 = null; for (PropertyData pd : cwdm.getChildPropertiesData(data.parentData(), itemDataFilters)) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData2 = pd; break; } } assertFalse(pData2 == pData); pData2 = null; for (PropertyData pd : cwdm.getChildPropertiesData(data.parentData(), itemDataFilters)) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData2 = pd; break; } } PropertyData pData3 = null; for (PropertyData pd : cwdm.cache.getChildProperties(data.parentData())) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData3 = pd; break; } } assertTrue(pData2 == pData3); } /** * Using getChildPropertiesData with parentData and pattern */ @Test public void testBigFileWithCacheEnabledByPattern2() throws Exception { WorkspaceContainerFacade wsc = test.getRepository().getWorkspaceContainer("ws"); CacheableWorkspaceDataManager cwdm = (CacheableWorkspaceDataManager)wsc.getComponent(CacheableWorkspaceDataManager.class); if (!cwdm.cache.isEnabled()) return; Node testLocalBigFiles = test.getRoot().addNode("testBigFileWithCacheEnabledByPattern2"); // 300 Kb String path = test.createBLOBTempFile(300).getAbsolutePath(); Node localBigFile = testLocalBigFiles.addNode("bigFile", "nt:file"); Node contentNode = localBigFile.addNode("jcr:content", "nt:resource"); InputStream is = new FileInputStream(path); PropertyImpl data = (PropertyImpl)contentNode.setProperty("jcr:data", is); contentNode.setProperty("jcr:mimeType", "application/octet-stream "); contentNode.setProperty("jcr:lastModified", Calendar.getInstance()); test.getSession().save(); // Load cache first QPathEntryFilter filter = new PatternQPathEntryFilter(new QPathEntry("*", "*", 0)); List<QPathEntryFilter> itemDataFilters = Collections.singletonList((QPathEntryFilter)filter); cwdm.getChildPropertiesData(data.parentData(), itemDataFilters); List<PropertyData> props = cwdm.cache.getChildProperties(data.parentData(), filter); PropertyData pData = null; for (PropertyData pd : props) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData = pd; break; } } assertNotNull(pData); List<ValueData> vals = pData.getValues(); assertTrue(vals != null); assertFalse(vals.isEmpty()); assertTrue(vals.get(0) instanceof StreamPersistedValueData); StreamPersistedValueData fpvd = (StreamPersistedValueData)vals.get(0); assertTrue(fpvd.getFile() != null || fpvd.getUrl() != null); PropertyData pData2 = null; for (PropertyData pd : cwdm.getChildPropertiesData(data.parentData(), itemDataFilters)) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData2 = pd; break; } } assertTrue(pData2 == pData); // Simulate cases where the file is null such as during a replication of StreamPersistedValueData with a spool file as file // on all other cluster nodes the spool file doesn't exist so file will be set to null if (fpvd.getFile() != null) fpvd.setPersistedFile(null); else fpvd.setPersistedURL(null, false); pData2 = null; for (PropertyData pd : cwdm.getChildPropertiesData(data.parentData(), itemDataFilters)) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData2 = pd; break; } } assertFalse(pData2 == pData); pData2 = null; for (PropertyData pd : cwdm.getChildPropertiesData(data.parentData(), itemDataFilters)) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData2 = pd; break; } } PropertyData pData3 = null; for (PropertyData pd : cwdm.cache.getChildProperties(data.parentData(), filter)) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData3 = pd; break; } } assertTrue(pData2 == pData3); } /** * Using get with parentData, QPathEntry and index */ @Test public void testBigFileWithCacheEnabledByPattern3() throws Exception { WorkspaceContainerFacade wsc = test.getRepository().getWorkspaceContainer("ws"); CacheableWorkspaceDataManager cwdm = (CacheableWorkspaceDataManager)wsc.getComponent(CacheableWorkspaceDataManager.class); if (!cwdm.cache.isEnabled()) return; Node testLocalBigFiles = test.getRoot().addNode("testBigFileWithCacheEnabledByPattern3"); // 300 Kb String path = test.createBLOBTempFile(300).getAbsolutePath(); Node localBigFile = testLocalBigFiles.addNode("bigFile", "nt:file"); Node contentNode = localBigFile.addNode("jcr:content", "nt:resource"); InputStream is = new FileInputStream(path); PropertyImpl data = (PropertyImpl)contentNode.setProperty("jcr:data", is); contentNode.setProperty("jcr:mimeType", "application/octet-stream "); contentNode.setProperty("jcr:lastModified", Calendar.getInstance()); test.getSession().save(); // Load cache first QPathEntry qpeProp = new QPathEntry(Constants.NS_JCR_URI, "data", 0); ExactQPathEntryFilter filter = new ExactQPathEntryFilter(qpeProp); List<QPathEntryFilter> itemDataFilters = Collections.singletonList((QPathEntryFilter)filter); cwdm.getChildPropertiesData(data.parentData(), itemDataFilters); PropertyData pData = (PropertyData)cwdm.getCachedItemData(data.parentData(), qpeProp, ItemType.PROPERTY); assertNotNull(pData); List<ValueData> vals = pData.getValues(); assertTrue(vals != null); assertFalse(vals.isEmpty()); assertTrue(vals.get(0) instanceof StreamPersistedValueData); StreamPersistedValueData fpvd = (StreamPersistedValueData)vals.get(0); assertTrue(fpvd.getFile() != null || fpvd.getUrl() != null); PropertyData pData2 = null; for (PropertyData pd : cwdm.getChildPropertiesData(data.parentData(), itemDataFilters)) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData2 = pd; break; } } assertTrue(pData2 == pData); // Simulate cases where the file is null such as during a replication of StreamPersistedValueData with a spool file as file // on all other cluster nodes the spool file doesn't exist so file will be set to null if (fpvd.getFile() != null) fpvd.setPersistedFile(null); else fpvd.setPersistedURL(null, false); pData2 = null; for (PropertyData pd : cwdm.getChildPropertiesData(data.parentData(), itemDataFilters)) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData2 = pd; break; } } assertFalse(pData2 == pData); pData2 = null; for (PropertyData pd : cwdm.getChildPropertiesData(data.parentData(), itemDataFilters)) { if (pd.getIdentifier().equals(data.getInternalIdentifier())) { pData2 = pd; break; } } assertTrue(pData2 == cwdm.getCachedItemData(data.parentData(), qpeProp, ItemType.PROPERTY)); } private static class MyWorkspaceStorageCache implements WorkspaceStorageCache { private volatile List<NodeData> childNodes; public void addChildNodes(NodeData parent, List<NodeData> childNodes) { this.childNodes = childNodes; } private volatile List<PropertyData> childProperties; public void addChildProperties(NodeData parent, List<PropertyData> childProperties) { this.childProperties = childProperties; } private volatile List<PropertyData> childPropertiesList; public void addChildPropertiesList(NodeData parent, List<PropertyData> childProperties) { this.childPropertiesList = childProperties; } public void beginTransaction() { } public void commitTransaction() { } private volatile ItemData itemData; public ItemData get(String parentIdentifier, QPathEntry name, ItemType itemType) { if (itemData != null && itemType.isSuitableFor(itemData)) { return itemData; } return null; } public ItemData get(String identifier) { return itemData; } public List<NodeData> getChildNodes(NodeData parent) { return childNodes; } public List<PropertyData> getChildProperties(NodeData parent) { return childProperties; } public long getSize() { return 0; } public boolean isEnabled() { return true; } /** * {@inheritDoc} */ public boolean isPatternSupported() { return false; } /** * {@inheritDoc} */ public boolean isChildNodesByPageSupported() { return false; } public List<PropertyData> listChildProperties(NodeData parentData) { return childPropertiesList; } public void put(ItemData item) { this.itemData = item; } public void remove(ItemData item) { this.itemData = null; } public void remove(String identifier, ItemData item) { } public void rollbackTransaction() { } public boolean isTXAware() { return true; } public void onSaveItems(ItemStateChangesLog itemStates) { } public int getChildNodesCount(NodeData parent) { return childNodes != null ? childNodes.size() : count; } public List<PropertyData> getReferencedProperties(String identifier) { return null; } public void addReferencedProperties(String identifier, List<PropertyData> refProperties) { } public void addChildProperties(NodeData parent, QPathEntryFilter pattern, List<PropertyData> childProperties) { } public List<PropertyData> getChildProperties(NodeData parent, QPathEntryFilter pattern) { return null; } public void addChildNodes(NodeData parent, QPathEntryFilter pattern, List<NodeData> childNodes) { } public List<NodeData> getChildNodes(NodeData parent, QPathEntryFilter pattern) { return null; } public List<NodeData> getChildNodesByPage(NodeData parent, int fromOrderNum) { return null; } public void addChildNodesByPage(NodeData parent, List<NodeData> childs, int fromOrderNum) { } /** * @see org.exoplatform.services.jcr.dataflow.persistent.WorkspaceStorageCache#addListener(org.exoplatform.services.jcr.dataflow.persistent.WorkspaceStorageCacheListener) */ public void addListener(WorkspaceStorageCacheListener listener) throws UnsupportedOperationException { } /** * @see org.exoplatform.services.jcr.dataflow.persistent.WorkspaceStorageCache#removeListener(org.exoplatform.services.jcr.dataflow.persistent.WorkspaceStorageCacheListener) */ public void removeListener(WorkspaceStorageCacheListener listener) throws UnsupportedOperationException { } private volatile int count = -1; /** * @see org.exoplatform.services.jcr.dataflow.persistent.WorkspaceStorageCache#addChildNodesCount(org.exoplatform.services.jcr.datamodel.NodeData, int) */ public void addChildNodesCount(NodeData parent, int count) { this.count = count; } } private static class MyWorkspaceStorageConnection implements WorkspaceStorageConnection { public void add(NodeData data) throws RepositoryException, UnsupportedOperationException, InvalidItemStateException, IllegalStateException { } public void add(PropertyData data, ChangedSizeHandler sizeHandler) throws RepositoryException, UnsupportedOperationException, InvalidItemStateException, IllegalStateException { } public void close() throws IllegalStateException, RepositoryException { } public void commit() throws IllegalStateException, RepositoryException { } public void prepare() throws IllegalStateException, RepositoryException { } public void delete(NodeData data) throws RepositoryException, UnsupportedOperationException, InvalidItemStateException, IllegalStateException { } public void delete(PropertyData data, ChangedSizeHandler sizeHandler) throws RepositoryException, UnsupportedOperationException, InvalidItemStateException, IllegalStateException { } public AtomicInteger getChildNodesCountCalls = new AtomicInteger(); public int getChildNodesCount(NodeData parent) throws RepositoryException { getChildNodesCountCalls.incrementAndGet(); return 1; } public AtomicInteger getChildNodesDataCalls = new AtomicInteger(); public List<NodeData> getChildNodesData(NodeData parent) throws RepositoryException, IllegalStateException { getChildNodesDataCalls.incrementAndGet(); return Arrays.asList((NodeData)new PersistedNodeData("getChildNodesData", null, null, 0, 1, null, null, null)); } public AtomicInteger getChildPropertiesDataCalls = new AtomicInteger(); public List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException, IllegalStateException { getChildPropertiesDataCalls.incrementAndGet(); return Arrays.asList((PropertyData)new PersistedPropertyData("getChildPropertiesData", null, null, 0, PropertyType.STRING, false, Arrays.asList((ValueData)new ByteArrayPersistedValueData(1, "foo".getBytes())), new SimplePersistedSize(0))); } public List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> pattern) throws RepositoryException, IllegalStateException { getChildPropertiesDataCalls.incrementAndGet(); return Arrays.asList((PropertyData)new PersistedPropertyData("getChildPropertiesDataByPattern", null, null, 0, PropertyType.STRING, false, Arrays.asList((ValueData)new ByteArrayPersistedValueData(1, "foo".getBytes())), new SimplePersistedSize(0))); } public AtomicInteger getItemDataByNodeDataNQPathEntryCalls = new AtomicInteger(); public ItemData getItemData(NodeData parentData, QPathEntry name, ItemType itemType) throws RepositoryException, IllegalStateException { getItemDataByNodeDataNQPathEntryCalls.incrementAndGet(); if (itemType != ItemType.PROPERTY) { return new PersistedNodeData("getItemData", null, null, 0, 1, null, null, null); } return null; } public AtomicInteger getItemDataByIdCalls = new AtomicInteger(); public ItemData getItemData(String identifier) throws RepositoryException, IllegalStateException { getItemDataByIdCalls.incrementAndGet(); return new PersistedNodeData("getItemData", null, null, 0, 1, null, null, null); } public AtomicInteger getReferencesDataCalls = new AtomicInteger(); public List<PropertyData> getReferencesData(String nodeIdentifier) throws RepositoryException, IllegalStateException, UnsupportedOperationException { getReferencesDataCalls.incrementAndGet(); return Arrays.asList((PropertyData)new PersistedPropertyData("getReferencesData", null, null, 0, PropertyType.STRING, false, Arrays.asList((ValueData)new ByteArrayPersistedValueData(1, "foo".getBytes())), new SimplePersistedSize(0))); } public boolean isOpened() { return true; } public AtomicInteger listChildPropertiesDataCalls = new AtomicInteger(); public List<PropertyData> listChildPropertiesData(NodeData parent) throws RepositoryException, IllegalStateException { listChildPropertiesDataCalls.incrementAndGet(); return Arrays.asList((PropertyData)new PersistedPropertyData("listChildPropertiesData", null, null, 0, PropertyType.STRING, false, Arrays.asList((ValueData)new ByteArrayPersistedValueData(1, "foo".getBytes())), new SimplePersistedSize(0))); } public void rename(NodeData data) throws RepositoryException, UnsupportedOperationException, InvalidItemStateException, IllegalStateException { } public void rollback() throws IllegalStateException, RepositoryException { } public void update(NodeData data) throws RepositoryException, UnsupportedOperationException, InvalidItemStateException, IllegalStateException { } public void update(PropertyData data, ChangedSizeHandler sizeHandler) throws RepositoryException, UnsupportedOperationException, InvalidItemStateException, IllegalStateException { } public int getLastOrderNumber(NodeData parent) throws RepositoryException { return -1; } public List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> pattern) throws RepositoryException, IllegalStateException { return null; } public boolean getChildNodesDataByPage(NodeData parent, int fromOrderNum, int offset, int pageSize, List<NodeData> childs) throws RepositoryException { return false; } /** * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#getACLHolders() */ public List<ACLHolder> getACLHolders() throws RepositoryException, IllegalStateException, UnsupportedOperationException { return null; } /** * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#getNodesCount() */ public long getNodesCount() throws RepositoryException { throw new UnsupportedOperationException(); } public boolean hasItemData(NodeData parentData, QPathEntry name, ItemType itemType) throws RepositoryException, IllegalStateException { return getItemData(parentData, name, itemType) != null; } public long getWorkspaceDataSize() throws RepositoryException { return 0; } public long getNodeDataSize(String parentId) throws RepositoryException { return 0; } }; private static class MyWorkspaceDataContainer extends WorkspaceDataContainerBase { private WorkspaceStorageConnection con; public MyWorkspaceDataContainer(WorkspaceStorageConnection con) { this.con = con; } public boolean isCheckSNSNewConnection() { return false; } public boolean isSame(WorkspaceDataContainer another) { return false; } public WorkspaceStorageConnection openConnection() throws RepositoryException { return con; } public WorkspaceStorageConnection openConnection(boolean readOnly) throws RepositoryException { return con; } public WorkspaceStorageConnection reuseConnection(WorkspaceStorageConnection original) throws RepositoryException { return con; } public String getInfo() { return "MyWorkspaceDataContainer"; } public String getName() { return "MyWorkspaceDataContainer"; } public String getStorageVersion() { return "0"; } public String getUniqueName() { return "MyWorkspaceDataContainer"; } }; }