diff --git a/config/alfresco/action-services-context.xml b/config/alfresco/action-services-context.xml index 73a133d9b2..f525758b20 100644 --- a/config/alfresco/action-services-context.xml +++ b/config/alfresco/action-services-context.xml @@ -567,10 +567,10 @@ - + - + false @@ -590,7 +590,7 @@ - + diff --git a/source/java/org/alfresco/repo/avm/AVMLockingAwareService.java b/source/java/org/alfresco/repo/avm/AVMLockingAwareService.java index 48542b8ad4..99e860289e 100644 --- a/source/java/org/alfresco/repo/avm/AVMLockingAwareService.java +++ b/source/java/org/alfresco/repo/avm/AVMLockingAwareService.java @@ -34,6 +34,7 @@ import java.util.Map; import java.util.Set; import java.util.SortedMap; +import org.alfresco.repo.avm.util.AVMUtil; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.service.cmr.avm.AVMBadArgumentException; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; @@ -703,10 +704,11 @@ public class AVMLockingAwareService implements AVMService, ApplicationContextAwa */ public void removeNode(String parent, String name) { - grabLock(parent + '/' + name); + String path = AVMUtil.extendAVMPath(parent, name); + grabLock(path); fService.removeNode(parent, name); String[] storePath = parent.split(":"); - fService.createSnapshot(storePath[0], null, null); + fService.createSnapshot(storePath[0], null, "Removed "+path); String webProject = getWebProject(storePath[0]); if (webProject != null) { @@ -722,7 +724,7 @@ public class AVMLockingAwareService implements AVMService, ApplicationContextAwa grabLock(path); fService.removeNode(path); String[] storePath = path.split(":"); - fService.createSnapshot(storePath[0], null, null); + fService.createSnapshot(storePath[0], null, "Removed "+path); String webProject = getWebProject(storePath[0]); if (webProject != null) { diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java index 58bfbdccf9..f40618154c 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java @@ -1259,47 +1259,62 @@ public class AVMServiceTest extends AVMServiceTestBase try { setupBasicTree(); + ContentWriter writer = fService.getContentWriter("main:/a/b/c/foo"); writer.setEncoding("UTF-8"); writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); writer.putContent("I am main:/a/b/c/foo V1"); fService.createSnapshot("main", "v1", null); + writer = fService.getContentWriter("main:/a/b/c/foo"); writer.setEncoding("UTF-8"); writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); writer.putContent("I am main:/a/b/c/foo V2"); fService.createSnapshot("main", "v2", null); + writer = fService.getContentWriter("main:/a/b/c/foo"); writer.setEncoding("UTF-8"); writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); writer.putContent("I am main:/a/b/c/foo V3"); fService.createSnapshot("main", "v3", null); + writer = fService.getContentWriter("main:/a/b/c/foo"); writer.setEncoding("UTF-8"); writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); writer.putContent("I am main:/a/b/c/foo V4"); fService.createSnapshot("main", "v4", null); + writer = fService.getContentWriter("main:/a/b/c/foo"); writer.setEncoding("UTF-8"); writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); writer.putContent("I am main:/a/b/c/foo V5"); fService.createSnapshot("main", "v5", null); + writer = fService.getContentWriter("main:/a/b/c/foo"); writer.setEncoding("UTF-8"); writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); writer.putContent("I am main:/a/b/c/foo HEAD"); + StoreRef storeRef = AVMNodeConverter.ToStoreRef("main"); + SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + ResultSet results = searchService.query(storeRef, "lucene", "TEXT:\"HEAD\""); assertEquals(0, results.length()); results.close(); + results = searchService.query(storeRef, "lucene", "TEXT:\"V5\""); assertEquals(1, results.length()); results.close(); - + + results = searchService.query(storeRef, "lucene", "TEXT:\"V2\""); + assertEquals(0, results.length()); + results.close(); + AVMNodeDescriptor desc = fService.lookup(-1, "main:/a/b/c/foo"); List history = fService.getHistory(desc, 100); AVMNodeDescriptor toRevert = history.get(3); + final ActionImpl action = new ActionImpl(null, GUID.generate(), AVMRevertToVersionAction.NAME); action.setParameterValue(AVMRevertToVersionAction.TOREVERT, toRevert); final AVMRevertToVersionAction revert = (AVMRevertToVersionAction) fContext.getBean("avm-revert-to-version"); @@ -1307,26 +1322,15 @@ public class AVMServiceTest extends AVMServiceTestBase { public Object execute() throws Exception { + // note: including implicit snapshot revert.execute(action, AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c/foo")); return null; } - } - ; + }; + TransactionService transactionService = (TransactionService) fContext.getBean("transactionService"); transactionService.getRetryingTransactionHelper().doInTransaction(new TxnWork()); - - results = searchService.query(storeRef, "lucene", "TEXT:\"HEAD\""); - assertEquals(0, results.length()); - results.close(); - results = searchService.query(storeRef, "lucene", "TEXT:\"V5\""); - assertEquals(1, results.length()); - results.close(); - results = searchService.query(storeRef, "lucene", "TEXT:\"V2\""); - assertEquals(0, results.length()); - results.close(); - - fService.createSnapshot("main", "reverted", null); - + results = searchService.query(storeRef, "lucene", "TEXT:\"HEAD\""); assertEquals(0, results.length()); results.close(); @@ -1336,7 +1340,6 @@ public class AVMServiceTest extends AVMServiceTestBase results = searchService.query(storeRef, "lucene", "TEXT:\"V2\""); assertEquals(1, results.length()); results.close(); - } catch (Exception e) { diff --git a/source/java/org/alfresco/repo/avm/actions/AVMRevertToVersionAction.java b/source/java/org/alfresco/repo/avm/actions/AVMRevertToVersionAction.java index 257cf9f23c..9b0d669ad4 100644 --- a/source/java/org/alfresco/repo/avm/actions/AVMRevertToVersionAction.java +++ b/source/java/org/alfresco/repo/avm/actions/AVMRevertToVersionAction.java @@ -29,6 +29,7 @@ import java.util.List; import org.alfresco.repo.action.ParameterDefinitionImpl; import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.repo.avm.util.AVMUtil; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ParameterDefinition; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; @@ -77,9 +78,12 @@ public class AVMRevertToVersionAction extends ActionExecuterAbstractBase { Pair versionPath = AVMNodeConverter.ToAVMVersionPath(actionedUponNodeRef); - AVMNodeDescriptor toRevert = + AVMNodeDescriptor toRevertTo = (AVMNodeDescriptor)action.getParameterValue(TOREVERT); - fAVMService.revert(versionPath.getSecond(), toRevert); + fAVMService.revert(versionPath.getSecond(), toRevertTo); + + String[] storePath = AVMUtil.splitPath(versionPath.getSecond()); + fAVMService.createSnapshot(storePath[0], null, "Reverted "+versionPath.getSecond()+" to version "+toRevertTo.getVersionID()); } /* (non-Javadoc) diff --git a/source/java/org/alfresco/wcm/sandbox/SandboxServiceImpl.java b/source/java/org/alfresco/wcm/sandbox/SandboxServiceImpl.java index b6ef34514e..71d3813293 100644 --- a/source/java/org/alfresco/wcm/sandbox/SandboxServiceImpl.java +++ b/source/java/org/alfresco/wcm/sandbox/SandboxServiceImpl.java @@ -961,30 +961,28 @@ public class SandboxServiceImpl implements SandboxService List assetsToRevert = new ArrayList(assets.size()); - List tasks = null; + List wfRelativePaths = WCMWorkflowUtil.getAssociatedPathsForSandbox(avmSyncService, workflowService, sbStoreId); + for (AssetInfo asset : assets) { - if (tasks == null) + if (! asset.getSandboxId().equals(sbStoreId)) { - tasks = WCMWorkflowUtil.getAssociatedTasksForSandbox(workflowService, WCMUtil.getSandboxStoreId(asset.getAvmPath())); + // belts-and-braces + logger.warn("revertListAssets: Skip assert "+asset.getPath()+" (was "+asset.getSandboxId()+", expected "+sbStoreId+")"); + continue; } - // TODO refactor getAssociatedTasksForNode to use AssetInfo instead of AVMNodeDescriptor - AVMNodeDescriptor node = ((AssetInfoImpl)asset).getAVMNodeDescriptor(); - - if (node != null) + // check if in workflow + if (! wfRelativePaths.contains(asset.getPath())) { - if (WCMWorkflowUtil.getAssociatedTasksForNode(avmService, node, tasks).size() == 0) - { - assetsToRevert.add(asset); - - if (VirtServerUtils.requiresUpdateNotification(asset.getAvmPath())) - { - // Bind the post-commit transaction listener with data required for virtualization server notification - UpdateSandboxTransactionListener tl = new UpdateSandboxTransactionListener(asset.getAvmPath()); - AlfrescoTransactionSupport.bindListener(tl); - } - } + assetsToRevert.add(asset); + + if (VirtServerUtils.requiresUpdateNotification(asset.getAvmPath())) + { + // Bind the post-commit transaction listener with data required for virtualization server notification + UpdateSandboxTransactionListener tl = new UpdateSandboxTransactionListener(asset.getAvmPath()); + AlfrescoTransactionSupport.bindListener(tl); + } } } diff --git a/source/java/org/alfresco/wcm/util/WCMWorkflowUtil.java b/source/java/org/alfresco/wcm/util/WCMWorkflowUtil.java index d863feee3e..328c5d2231 100644 --- a/source/java/org/alfresco/wcm/util/WCMWorkflowUtil.java +++ b/source/java/org/alfresco/wcm/util/WCMWorkflowUtil.java @@ -24,6 +24,7 @@ */ package org.alfresco.wcm.util; +import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -36,6 +37,8 @@ import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avm.AVMNotFoundException; import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.avm.LayeringDescriptor; +import org.alfresco.service.cmr.avmsync.AVMDifference; +import org.alfresco.service.cmr.avmsync.AVMSyncService; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.workflow.WorkflowService; @@ -56,7 +59,7 @@ import org.apache.commons.logging.LogFactory; public class WCMWorkflowUtil { private static final Log logger = LogFactory.getLog(WCMWorkflowUtil.class); - + public static NodeRef createWorkflowPackage(WorkflowService workflowService, AVMService avmService, SandboxInfo sandboxInfo) { // create package paths (layered to user sandbox area as target) @@ -81,25 +84,30 @@ public class WCMWorkflowUtil public static List getAssociatedTasksForSandbox(WorkflowService workflowService, final String storeName) { + long start = System.currentTimeMillis(); + String fromPath = WCMUtil.buildStoreRootPath(storeName); WorkflowTaskQuery query = new WorkflowTaskQuery(); - + HashMap props = new HashMap(1, 1.0f); - + props.put(WCMWorkflowModel.PROP_FROM_PATH, fromPath); query.setProcessCustomProps(props); query.setActive(true); - + List tasks = workflowService.queryTasks(query); - - if (logger.isDebugEnabled()) + + if (logger.isTraceEnabled()) { - logger.debug("found " + tasks.size() + " tasks originating user sandbox " + fromPath); + logger.trace("getAssociatedTasksForSandbox: "+storeName+" (found "+tasks.size()+" tasks originating user sandbox "+fromPath+") in "+(System.currentTimeMillis()-start)+" msecs"); } return tasks; } - + + /** + * @deprecated since 3.2 + */ public static List getAssociatedTasksForNode(AVMService avmService, AVMNodeDescriptor node, List tasks) { List result = new LinkedList(); @@ -139,10 +147,58 @@ public class WCMWorkflowUtil return result; } - + + /** + * @deprecated since 3.2 + */ public static List getAssociatedTasksForNode(WorkflowService workflowService, AVMService avmService, AVMNodeDescriptor node) { - final List tasks = WCMWorkflowUtil.getAssociatedTasksForSandbox(workflowService, WCMUtil.getSandboxStoreId(node.getPath())); + final List tasks = getAssociatedTasksForSandbox(workflowService, WCMUtil.getSandboxStoreId(node.getPath())); return getAssociatedTasksForNode(avmService, node, tasks); } + + public static List getAssociatedPathsForSandbox(AVMSyncService avmSyncService, WorkflowService workflowService, String sandboxName) + { + long start = System.currentTimeMillis(); + + List tasks = getAssociatedTasksForSandbox(workflowService, sandboxName); + List storeRelativePaths = getAssociatedPathsForSandboxTasks(avmSyncService, sandboxName, tasks); + + if (logger.isDebugEnabled()) + { + logger.debug("getAssociatedPathsForSandbox: "+sandboxName+" (tasks="+tasks.size()+", paths="+storeRelativePaths.size()+") in "+(System.currentTimeMillis()-start)+" msecs"); + } + + return storeRelativePaths; + } + + private static List getAssociatedPathsForSandboxTasks(AVMSyncService avmSyncService, String sandboxName, List tasks) + { + long start = System.currentTimeMillis(); + + String stagingSandboxName = WCMUtil.buildStagingStoreName(WCMUtil.getWebProjectStoreId(sandboxName)); + List storeRelativePaths = new ArrayList(tasks.size()); + + for (WorkflowTask task : tasks) + { + final NodeRef ref = task.path.instance.workflowPackage; + + String wfPath = AVMNodeConverter.ToAVMVersionPath(ref).getSecond(); + String stagingSandboxPath = WCMUtil.getCorrespondingPath(wfPath, stagingSandboxName); + + List diffs = avmSyncService.compare(-1, wfPath, -1, stagingSandboxPath, null); + + for (AVMDifference diff : diffs) + { + storeRelativePaths.add(WCMUtil.getStoreRelativePath(diff.getSourcePath())); + } + } + + if (logger.isTraceEnabled()) + { + logger.trace("getAssociatedPathsForSandboxTasks: "+sandboxName+" (tasks="+tasks.size()+", paths="+storeRelativePaths.size()+") in "+(System.currentTimeMillis()-start)+" msecs"); + } + + return storeRelativePaths; + } }