diff --git a/config/alfresco/model/permissionDefinitions.xml b/config/alfresco/model/permissionDefinitions.xml index 7c72635b37..b6e956cba3 100644 --- a/config/alfresco/model/permissionDefinitions.xml +++ b/config/alfresco/model/permissionDefinitions.xml @@ -106,6 +106,7 @@ + @@ -279,6 +280,15 @@ --> + + + + + + + @@ -536,4 +546,8 @@ + + + + diff --git a/source/java/org/alfresco/repo/admin/patch/impl/MoveWCMToGroupBasedPermissionsPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/MoveWCMToGroupBasedPermissionsPatch.java index 3af5b17286..c54fa710f3 100644 --- a/source/java/org/alfresco/repo/admin/patch/impl/MoveWCMToGroupBasedPermissionsPatch.java +++ b/source/java/org/alfresco/repo/admin/patch/impl/MoveWCMToGroupBasedPermissionsPatch.java @@ -41,6 +41,7 @@ import org.alfresco.repo.avm.AVMRepository; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.domain.hibernate.AclDaoComponentImpl; import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor; +import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor.StoreType; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; @@ -132,7 +133,10 @@ public class MoveWCMToGroupBasedPermissionsPatch extends AbstractPatch List stores = avmService.getStores(); for (AVMStoreDescriptor store : stores) { - switch (avmSnapShotTriggeredIndexingMethodInterceptor.getStoreType(store.getName())) + + Map storeProperties = avmService.getStoreProperties(store.getName()); + + switch (StoreType.getStoreType(store.getName(), store, storeProperties)) { /* Set permissions in staging */ case STAGING: diff --git a/source/java/org/alfresco/repo/admin/patch/impl/WCMPermissionPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/WCMPermissionPatch.java index 2ec49dd6f8..f37c4ed840 100644 --- a/source/java/org/alfresco/repo/admin/patch/impl/WCMPermissionPatch.java +++ b/source/java/org/alfresco/repo/admin/patch/impl/WCMPermissionPatch.java @@ -35,6 +35,7 @@ import org.alfresco.repo.avm.AVMRepository; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.domain.hibernate.AclDaoComponentImpl; import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor; +import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor.StoreType; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; @@ -103,7 +104,9 @@ public class WCMPermissionPatch extends AbstractPatch List stores = avmService.getStores(); for (AVMStoreDescriptor store : stores) { - switch (avmSnapShotTriggeredIndexingMethodInterceptor.getStoreType(store.getName())) + Map storeProperties = avmService.getStoreProperties(store.getName()); + + switch (StoreType.getStoreType(store.getName(), store, storeProperties)) { /* Set permissions in staging */ case STAGING: diff --git a/source/java/org/alfresco/repo/avm/AVMDiffPerformanceTest.java b/source/java/org/alfresco/repo/avm/AVMDiffPerformanceTest.java new file mode 100644 index 0000000000..d5240fd1b2 --- /dev/null +++ b/source/java/org/alfresco/repo/avm/AVMDiffPerformanceTest.java @@ -0,0 +1,79 @@ +package org.alfresco.repo.avm; + +import java.util.List; + +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.avmsync.AVMDifference; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.util.GUID; + +public class AVMDiffPerformanceTest extends AVMServiceTestBase +{ + + public void test_10000() throws Exception + { + fTransactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() { + + public Object execute() throws Throwable + { + try + { + fService.createStore("StagingArea"); + fService.createStore("SandBox"); + + fService.createDirectory("StagingArea:/", "www"); + fService.createDirectory("StagingArea:/www", "test"); + fService.createLayeredDirectory("StagingArea:/www", "SandBox:/", "www"); + + + for(int i = 0; i < 10000; i++) + { + String name = GUID.generate(); + fService.createFile("SandBox:/www", name).close(); + } + System.out.println("Create SandBox:/www"); + + + for(int i = 0; i < 10000; i++) + { + String name = GUID.generate(); + fService.createFile("SandBox:/www/test", name).close(); + } + System.out.println("Create SandBox:/www/test"); + + for(int i = 0; i < 10000; i++) + { + String name = GUID.generate(); + fService.createFile("StagingArea:/www", name).close(); + } + System.out.println("Create StagingArea:/www"); + + for(int i = 0; i < 10000; i++) + { + String name = GUID.generate(); + fService.createFile("StagingArea:/www/test", name).close(); + } + System.out.println("Create StagingArea:/www/test"); + + long start = System.nanoTime(); + List diffs = fSyncService.compare(-1, "SandBox:/www", -1, "StagingArea:/www", null); + long end = System.nanoTime(); + System.out.println("Diff in "+( (end-start)/1000000000.0f)); + + assertEquals(20000, diffs.size()); + + + } + finally + { + fService.purgeStore("StagingArea"); + fService.purgeStore("SandBox"); + } + return null; + }}); + + + } +} diff --git a/source/java/org/alfresco/repo/avm/AVMExpiredContentTest.java b/source/java/org/alfresco/repo/avm/AVMExpiredContentTest.java index a32e57ba33..fed3b92653 100644 --- a/source/java/org/alfresco/repo/avm/AVMExpiredContentTest.java +++ b/source/java/org/alfresco/repo/avm/AVMExpiredContentTest.java @@ -30,6 +30,7 @@ import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.avmsync.AVMSyncService; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.workflow.WorkflowService; @@ -59,6 +60,7 @@ public class AVMExpiredContentTest extends TestCase PersonService personService = serviceRegistry.getPersonService(); TransactionService transactionService = serviceRegistry.getTransactionService(); WorkflowService workflowService = serviceRegistry.getWorkflowService(); + SearchService searchService = serviceRegistry.getSearchService(); // construct the test processor this.processor = new AVMExpiredContentProcessor(); @@ -69,6 +71,7 @@ public class AVMExpiredContentTest extends TestCase this.processor.setPersonService(personService); this.processor.setTransactionService(transactionService); this.processor.setWorkflowService(workflowService); + this.processor.setSearchService(searchService); } public void testProcessor() throws Exception diff --git a/source/java/org/alfresco/repo/avm/AVMRepository.java b/source/java/org/alfresco/repo/avm/AVMRepository.java index 0a2ec1ad9c..c04ec225c1 100644 --- a/source/java/org/alfresco/repo/avm/AVMRepository.java +++ b/source/java/org/alfresco/repo/avm/AVMRepository.java @@ -40,6 +40,7 @@ import org.alfresco.repo.content.ContentStore; import org.alfresco.repo.domain.DbAccessControlList; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.domain.QNameDAO; +import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor.StoreType; import org.alfresco.repo.security.permissions.ACLCopyMode; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; @@ -69,13 +70,13 @@ import org.apache.commons.logging.LogFactory; /** * This or AVMStore are the implementors of the operations specified by AVMService. - * + * * @author britt */ public class AVMRepository { @SuppressWarnings("unused") - private static Log fgLogger = LogFactory.getLog(AVMRepository.class); + private static Log fgLogger = LogFactory.getLog(AVMRepository.class); /** * The single instance of AVMRepository. @@ -158,7 +159,7 @@ public class AVMRepository /** * Set the node issuer. For Spring. - * + * * @param nodeIssuer * The issuer. */ @@ -169,7 +170,7 @@ public class AVMRepository /** * Set the layer issuer. For Spring. - * + * * @param layerIssuer * The issuer. */ @@ -188,7 +189,7 @@ public class AVMRepository /** * Set the Lookup Cache instance. - * + * * @param cache * The instance to set. */ @@ -264,7 +265,7 @@ public class AVMRepository /** * Create a file. - * + * * @param path * The path to the containing directory. * @param name @@ -277,7 +278,8 @@ public class AVMRepository { String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); - if (store == null) { + if (store == null) + { throw new AVMNotFoundException("Store not found."); } fLookupCache.onWrite(pathParts[0]); @@ -292,7 +294,7 @@ public class AVMRepository /** * Create a file with the given File as content. - * + * * @param path * The path to the containing directory. * @param name @@ -322,7 +324,7 @@ public class AVMRepository /** * Create a new directory. - * + * * @param path * The path to the containing directory. * @param name @@ -351,7 +353,7 @@ public class AVMRepository /** * Create a new directory. This assumes that the parent is already copied and therefore should only be used with * great care. - * + * * @param parent * The parent node. * @param name @@ -369,25 +371,25 @@ public class AVMRepository { throw new AVMWrongTypeException("Not a directory."); } - if (!can(null, node, PermissionService.CREATE_CHILDREN)) + if (!can(null, node, PermissionService.CREATE_CHILDREN, true)) { throw new AccessDeniedException("Not allowed to write in: " + parent); } // We need the store to do anything so... - String [] pathParts = SplitPath(parent.getPath()); + String[] pathParts = SplitPath(parent.getPath()); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { throw new AVMNotFoundException("Store not found."); } - DirectoryNode dir = (DirectoryNode)node; + DirectoryNode dir = (DirectoryNode) node; DirectoryNode child = null; Long parentAcl = dir.getAcl() == null ? null : dir.getAcl().getId(); if (dir instanceof LayeredDirectoryNode) { - child = new LayeredDirectoryNodeImpl((String)null, store, null, parentAcl, ACLCopyMode.INHERIT); - ((LayeredDirectoryNode)child).setPrimaryIndirection(false); - ((LayeredDirectoryNode)child).setLayerID(parent.getLayerID()); + child = new LayeredDirectoryNodeImpl((String) null, store, null, parentAcl, ACLCopyMode.INHERIT); + ((LayeredDirectoryNode) child).setPrimaryIndirection(false); + ((LayeredDirectoryNode) child).setLayerID(parent.getLayerID()); } else { @@ -403,7 +405,7 @@ public class AVMRepository /** * Create a new layered directory. - * + * * @param srcPath * The target indirection for the new layered directory. * @param dstPath @@ -411,8 +413,7 @@ public class AVMRepository * @param name * The name for the new directory. */ - public void createLayeredDirectory(String srcPath, String dstPath, - String name) + public void createLayeredDirectory(String srcPath, String dstPath, String name) { if (dstPath.indexOf(srcPath) == 0) { @@ -438,7 +439,7 @@ public class AVMRepository /** * Create a new layered file. - * + * * @param srcPath * The target indirection for the new layered file. * @param dstPath @@ -468,7 +469,7 @@ public class AVMRepository /** * Create a new AVMStore. - * + * * @param name * The name to give the new AVMStore. */ @@ -489,7 +490,7 @@ public class AVMRepository /** * Create a new branch. - * + * * @param version * The version to branch off. * @param srcPath @@ -507,7 +508,7 @@ public class AVMRepository } // Lookup the src node. fLookupCount.set(1); - String [] pathParts; + String[] pathParts; Lookup sPath; List layeredEntries = null; try @@ -521,8 +522,7 @@ public class AVMRepository if (version < 0) { fLookupCache.onSnapshot(pathParts[0]); - version = - srcRepo.createSnapshot("Branch Snapshot", null, new HashMap()).get(pathParts[0]); + version = srcRepo.createSnapshot("Branch Snapshot", null, new HashMap()).get(pathParts[0]); } sPath = srcRepo.lookup(version, pathParts[1], false, false); if (sPath == null) @@ -552,8 +552,8 @@ public class AVMRepository { throw new AVMNotFoundException("Path not found."); } - DirectoryNode dirNode = (DirectoryNode)dPath.getCurrentNode(); - if (!can(dstRepo, dirNode, PermissionService.ADD_CHILDREN)) + DirectoryNode dirNode = (DirectoryNode) dPath.getCurrentNode(); + if (!can(dstRepo, dirNode, PermissionService.ADD_CHILDREN, dPath.getDirectlyContained())) { throw new AccessDeniedException("Not permitted to add children: " + dstPath); } @@ -567,21 +567,21 @@ public class AVMRepository if (srcNode.getType() == AVMNodeType.PLAIN_DIRECTORY) { - dstNode = new PlainDirectoryNodeImpl((PlainDirectoryNode)srcNode, dstRepo, inheritAcl, ACLCopyMode.INHERIT); + dstNode = new PlainDirectoryNodeImpl((PlainDirectoryNode) srcNode, dstRepo, inheritAcl, ACLCopyMode.INHERIT); } else if (srcNode.getType() == AVMNodeType.LAYERED_DIRECTORY) { - dstNode = - new LayeredDirectoryNodeImpl((LayeredDirectoryNode)srcNode, dstRepo, sPath, false, inheritAcl, ACLCopyMode.INHERIT); - ((LayeredDirectoryNode)dstNode).setLayerID(issueLayerID()); + dstNode = new LayeredDirectoryNodeImpl((LayeredDirectoryNode) srcNode, dstRepo, sPath, false, inheritAcl, ACLCopyMode.INHERIT); + ((LayeredDirectoryNode) dstNode).setLayerID(issueLayerID()); } else if (srcNode.getType() == AVMNodeType.LAYERED_FILE) { - dstNode = new LayeredFileNodeImpl((LayeredFileNode)srcNode, dstRepo, inheritAcl, ACLCopyMode.INHERIT); + dstNode = new LayeredFileNodeImpl((LayeredFileNode) srcNode, dstRepo, inheritAcl, ACLCopyMode.INHERIT); } - else // This is a plain file. + else + // This is a plain file. { - dstNode = new PlainFileNodeImpl((PlainFileNode)srcNode, dstRepo, inheritAcl, ACLCopyMode.INHERIT); + dstNode = new PlainFileNodeImpl((PlainFileNode) srcNode, dstRepo, inheritAcl, ACLCopyMode.INHERIT); } // dstNode.setVersionID(dstRepo.getNextVersionID()); dstNode.setAncestor(srcNode); @@ -599,8 +599,7 @@ public class AVMRepository continue; } String newPath = finalPath + path.substring(beginingPath.length()); - VersionLayeredNodeEntry newEntry = - new VersionLayeredNodeEntryImpl(latestVersion, newPath); + VersionLayeredNodeEntry newEntry = new VersionLayeredNodeEntryImpl(latestVersion, newPath); fVersionLayeredNodeEntryDAO.save(newEntry); } } @@ -612,7 +611,7 @@ public class AVMRepository /** * Get an output stream to a file. - * + * * @param path * The full path to the file. * @return An OutputStream. @@ -622,7 +621,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -640,7 +639,7 @@ public class AVMRepository /** * Get a content reader from a file node. - * + * * @param version * The version of the file. * @param path @@ -652,7 +651,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -668,7 +667,7 @@ public class AVMRepository /** * Get a ContentWriter to a file node. - * + * * @param path * The path to the file. * @return A ContentWriter. @@ -678,7 +677,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -696,7 +695,7 @@ public class AVMRepository /** * Rename a node. - * + * * @param srcPath * Source containing directory. * @param srcName @@ -706,8 +705,7 @@ public class AVMRepository * @param dstName * Destination name. */ - public void rename(String srcPath, String srcName, String dstPath, - String dstName) + public void rename(String srcPath, String srcName, String dstPath, String dstName) { // This is about as ugly as it gets. if ((dstPath + "/").indexOf(srcPath + srcName + "/") == 0) @@ -715,7 +713,7 @@ public class AVMRepository throw new AVMCycleException("Cyclic rename."); } fLookupCount.set(1); - String [] pathParts; + String[] pathParts; Lookup sPath; DirectoryNode srcDir; AVMNode srcNode; @@ -732,17 +730,19 @@ public class AVMRepository { throw new AVMNotFoundException("Path not found."); } - srcDir = (DirectoryNode)sPath.getCurrentNode(); - if (!can(srcRepo, srcDir, PermissionService.DELETE_CHILDREN) || !can(srcRepo, srcDir, PermissionService.ADD_CHILDREN)) - { - throw new AccessDeniedException("Not allowed to read or write: " + srcPath); - } + srcDir = (DirectoryNode) sPath.getCurrentNode(); + Pair temp = srcDir.lookupChild(sPath, srcName, false); srcNode = (temp == null) ? null : temp.getFirst(); if (srcNode == null) { throw new AVMNotFoundException("Not found: " + srcName); } + if (!can(srcRepo, srcNode, PermissionService.DELETE_NODE, false)) + { + throw new AccessDeniedException("Not allowed to delete target: " + srcPath); + } + fLookupCache.onDelete(pathParts[0]); } finally @@ -763,8 +763,8 @@ public class AVMRepository { throw new AVMNotFoundException("Path not found."); } - DirectoryNode dstDir = (DirectoryNode)dPath.getCurrentNode(); - if (!can(dstRepo, dstDir, PermissionService.ADD_CHILDREN)) + DirectoryNode dstDir = (DirectoryNode) dPath.getCurrentNode(); + if (!can(dstRepo, dstDir, PermissionService.ADD_CHILDREN, dPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write: " + dstPath); } @@ -792,47 +792,42 @@ public class AVMRepository // layer. Allowing it makes the logic absurdly complex. if (dPath.isLayered() && dPath.getTopLayer().equals(sPath.getTopLayer())) { - dstNode = new LayeredDirectoryNodeImpl((PlainDirectoryNode)srcNode, dstRepo, sPath, true, parentAcl, ACLCopyMode.COPY); - ((LayeredDirectoryNode)dstNode).setLayerID(sPath.getTopLayer().getLayerID()); + dstNode = new LayeredDirectoryNodeImpl((PlainDirectoryNode) srcNode, dstRepo, sPath, true, parentAcl, ACLCopyMode.COPY); + ((LayeredDirectoryNode) dstNode).setLayerID(sPath.getTopLayer().getLayerID()); } else { - dstNode = new LayeredDirectoryNodeImpl((DirectoryNode)srcNode, dstRepo, sPath, srcName, parentAcl, ACLCopyMode.COPY); - ((LayeredDirectoryNode)dstNode).setLayerID(issueLayerID()); + dstNode = new LayeredDirectoryNodeImpl((DirectoryNode) srcNode, dstRepo, sPath, srcName, parentAcl, ACLCopyMode.COPY); + ((LayeredDirectoryNode) dstNode).setLayerID(issueLayerID()); } } else { - dstNode = new PlainDirectoryNodeImpl((PlainDirectoryNode)srcNode, dstRepo, parentAcl, ACLCopyMode.COPY); + dstNode = new PlainDirectoryNodeImpl((PlainDirectoryNode) srcNode, dstRepo, parentAcl, ACLCopyMode.COPY); } } else if (srcNode.getType() == AVMNodeType.LAYERED_DIRECTORY) { - if (!sPath.isLayered() || (sPath.isInThisLayer() && - srcDir.getType() == AVMNodeType.LAYERED_DIRECTORY && - ((LayeredDirectoryNode)srcDir).directlyContains(srcNode))) + if (!sPath.isLayered() || (sPath.isInThisLayer() && srcDir.getType() == AVMNodeType.LAYERED_DIRECTORY && ((LayeredDirectoryNode) srcDir).directlyContains(srcNode))) { Lookup srcLookup = lookup(-1, srcPath + "/" + srcName, true); // Use the simple 'copy' constructor. - dstNode = - new LayeredDirectoryNodeImpl((LayeredDirectoryNode)srcNode, dstRepo, srcLookup, true, parentAcl, ACLCopyMode.COPY); - ((LayeredDirectoryNode)dstNode).setLayerID(((LayeredDirectoryNode)srcNode).getLayerID()); + dstNode = new LayeredDirectoryNodeImpl((LayeredDirectoryNode) srcNode, dstRepo, srcLookup, true, parentAcl, ACLCopyMode.COPY); + ((LayeredDirectoryNode) dstNode).setLayerID(((LayeredDirectoryNode) srcNode).getLayerID()); } else { // If the source node is a primary indirection, then the 'copy' constructor // is used. Otherwise the alternate constructor is called and its // indirection is calculated from it's source context. - if (((LayeredDirectoryNode)srcNode).getPrimaryIndirection()) + if (((LayeredDirectoryNode) srcNode).getPrimaryIndirection()) { Lookup srcLookup = lookup(-1, srcPath + "/" + srcName, true); - dstNode = - new LayeredDirectoryNodeImpl((LayeredDirectoryNode)srcNode, dstRepo, srcLookup, true, parentAcl, ACLCopyMode.COPY); + dstNode = new LayeredDirectoryNodeImpl((LayeredDirectoryNode) srcNode, dstRepo, srcLookup, true, parentAcl, ACLCopyMode.COPY); } else { - dstNode = - new LayeredDirectoryNodeImpl((DirectoryNode)srcNode, dstRepo, sPath, srcName, parentAcl, ACLCopyMode.COPY); + dstNode = new LayeredDirectoryNodeImpl((DirectoryNode) srcNode, dstRepo, sPath, srcName, parentAcl, ACLCopyMode.COPY); } // What needs to be done here is dependent on whether the // rename is to a layered context. If so then it should get the layer id @@ -840,21 +835,22 @@ public class AVMRepository // id. if (dPath.isLayered()) { - ((LayeredDirectoryNode)dstNode).setLayerID(dPath.getTopLayer().getLayerID()); + ((LayeredDirectoryNode) dstNode).setLayerID(dPath.getTopLayer().getLayerID()); } else { - ((LayeredDirectoryNode)dstNode).setLayerID(issueLayerID()); + ((LayeredDirectoryNode) dstNode).setLayerID(issueLayerID()); } } } else if (srcNode.getType() == AVMNodeType.LAYERED_FILE) { - dstNode = new LayeredFileNodeImpl((LayeredFileNode)srcNode, dstRepo, parentAcl, ACLCopyMode.COPY); + dstNode = new LayeredFileNodeImpl((LayeredFileNode) srcNode, dstRepo, parentAcl, ACLCopyMode.COPY); } - else // This is a plain file node. + else + // This is a plain file node. { - dstNode = new PlainFileNodeImpl((PlainFileNode)srcNode, dstRepo, parentAcl, ACLCopyMode.COPY); + dstNode = new PlainFileNodeImpl((PlainFileNode) srcNode, dstRepo, parentAcl, ACLCopyMode.COPY); } srcDir.removeChild(sPath, srcName); srcDir.updateModTime(); @@ -879,7 +875,7 @@ public class AVMRepository /** * Uncover a deleted name in a layered directory. - * + * * @param dirPath * The path to the layered directory. * @param name @@ -890,7 +886,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(dirPath); + String[] pathParts = SplitPath(dirPath); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -907,7 +903,7 @@ public class AVMRepository /** * Create a snapshot of a single AVMStore. - * + * * @param store * The name of the repository. * @param tag @@ -943,7 +939,7 @@ public class AVMRepository /** * Remove a node and everything underneath it. - * + * * @param path * The path to the containing directory. * @param name @@ -954,7 +950,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -971,7 +967,7 @@ public class AVMRepository /** * Get rid of all content that lives only in the given AVMStore. Also removes the AVMStore. - * + * * @param name * The name of the AVMStore to purge. */ @@ -987,7 +983,7 @@ public class AVMRepository fLookupCache.onDelete(name); AVMNode root = store.getRoot(); // TODO Probably a special PermissionService.PURGE is needed. - if (!can(store, root, PermissionService.DELETE_CHILDREN)) + if (!can(store, root, PermissionService.DELETE_CHILDREN, true)) { throw new AccessDeniedException("Not allowed to purge: " + name); } @@ -1013,7 +1009,7 @@ public class AVMRepository /** * Remove all content specific to a AVMRepository and version. - * + * * @param name * The name of the AVMStore. * @param version @@ -1034,7 +1030,7 @@ public class AVMRepository /** * Get an input stream from a file. - * + * * @param version * The version to look under. * @param path @@ -1046,7 +1042,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -1067,11 +1063,11 @@ public class AVMRepository { throw new AVMWrongTypeException(desc + " is not a File."); } - if (!can(null, node, PermissionService.READ_CONTENT)) + if (!can(null, node, PermissionService.READ_CONTENT, false)) { throw new AccessDeniedException("Not allowed to read content: " + desc); } - FileNode file = (FileNode)node; + FileNode file = (FileNode) node; ContentData data = file.getContentData(null); if (data == null) { @@ -1083,7 +1079,7 @@ public class AVMRepository /** * Get a listing of a directory. - * + * * @param version * The version to look under. * @param path @@ -1092,13 +1088,12 @@ public class AVMRepository * Whether to see DeletedNodes. * @return A List of FolderEntries. */ - public SortedMap getListing(int version, String path, - boolean includeDeleted) + public SortedMap getListing(int version, String path, boolean includeDeleted) { fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -1114,20 +1109,19 @@ public class AVMRepository /** * Get the list of nodes directly contained in a directory. - * + * * @param version * The version to look under. * @param path * The path to the directory to list. * @return A Map of names to descriptors. */ - public SortedMap getListingDirect(int version, String path, - boolean includeDeleted) + public SortedMap getListingDirect(int version, String path, boolean includeDeleted) { fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -1143,22 +1137,21 @@ public class AVMRepository /** * Get the list of nodes directly contained in a directory. - * + * * @param dir * The descriptor to the directory node. * @param includeDeleted * Whether to include deleted children. * @return A Map of names to descriptors. */ - public SortedMap - getListingDirect(AVMNodeDescriptor dir, boolean includeDeleted) + public SortedMap getListingDirect(AVMNodeDescriptor dir, boolean includeDeleted) { AVMNode node = fAVMNodeDAO.getByID(dir.getId()); if (node == null) { throw new AVMBadArgumentException("Invalid Node."); } - if (!can(null, node, PermissionService.READ_CHILDREN)) + if (!can(null, node, PermissionService.READ_CHILDREN, false)) { throw new AccessDeniedException("Not allowed to read children: " + dir); } @@ -1170,13 +1163,13 @@ public class AVMRepository { throw new AVMWrongTypeException("Not a directory."); } - LayeredDirectoryNode dirNode = (LayeredDirectoryNode)node; + LayeredDirectoryNode dirNode = (LayeredDirectoryNode) node; return dirNode.getListingDirect(dir, includeDeleted); } /** * Get a directory listing from a directory node descriptor. - * + * * @param dir * The directory node descriptor. * @return A SortedMap listing. @@ -1191,16 +1184,15 @@ public class AVMRepository { throw new AVMBadArgumentException("Invalid Node."); } - if (node.getType() != AVMNodeType.LAYERED_DIRECTORY && - node.getType() != AVMNodeType.PLAIN_DIRECTORY) + if (node.getType() != AVMNodeType.LAYERED_DIRECTORY && node.getType() != AVMNodeType.PLAIN_DIRECTORY) { throw new AVMWrongTypeException("Not a directory."); } - if (!can(null, node, PermissionService.READ_CHILDREN)) + if (!can(null, node, PermissionService.READ_CHILDREN, false)) { throw new AccessDeniedException("Not allowed to read children: " + dir); } - DirectoryNode dirNode = (DirectoryNode)node; + DirectoryNode dirNode = (DirectoryNode) node; SortedMap listing = dirNode.getListing(dir, includeDeleted); return listing; } @@ -1212,7 +1204,7 @@ public class AVMRepository /** * Get the names of deleted nodes in a directory. - * + * * @param version * The version to look under. * @param path @@ -1224,7 +1216,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -1240,7 +1232,7 @@ public class AVMRepository /** * Get descriptors of all AVMStores. - * + * * @return A list of all descriptors. */ @SuppressWarnings("unchecked") @@ -1257,7 +1249,7 @@ public class AVMRepository /** * Get a descriptor for an AVMStore. - * + * * @param name * The name to get. * @return The descriptor. @@ -1274,7 +1266,7 @@ public class AVMRepository /** * Get all version for a given AVMStore. - * + * * @param name * The name of the AVMStore. * @return A Set will all the version ids. @@ -1291,7 +1283,7 @@ public class AVMRepository /** * Get the set of versions between (inclusive) of the given dates. From or to may be null but not both. - * + * * @param name * The name of the AVMRepository. * @param from @@ -1312,7 +1304,7 @@ public class AVMRepository /** * Issue a node id. - * + * * @return The new id. */ public long issueID() @@ -1322,7 +1314,7 @@ public class AVMRepository /** * Issue a new layer id. - * + * * @return The new id. */ public long issueLayerID() @@ -1332,7 +1324,7 @@ public class AVMRepository /** * Get the indirection path for a layered node. - * + * * @param version * The version to look under. * @param path @@ -1344,7 +1336,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -1360,7 +1352,7 @@ public class AVMRepository /** * Get the next version id for the given AVMStore. - * + * * @param name * The name of the AVMStore. * @return The next version id. @@ -1377,7 +1369,7 @@ public class AVMRepository /** * Get the latest extant snapshotted version id. - * + * * @param name * The store name. */ @@ -1393,7 +1385,7 @@ public class AVMRepository /** * Get an AVMStore by name. - * + * * @param name * The name of the AVMStore. * @return The AVMStore. @@ -1406,7 +1398,7 @@ public class AVMRepository /** * Get a descriptor for an AVMStore root. - * + * * @param version * The version to get. * @param name @@ -1426,7 +1418,7 @@ public class AVMRepository // TODO Fix this awful mess regarding cycle detection. /** * Lookup a node. - * + * * @param version * The version to look under. * @param path @@ -1452,7 +1444,7 @@ public class AVMRepository { throw new AVMCycleException("Cycle in lookup."); } - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -1471,7 +1463,7 @@ public class AVMRepository /** * Lookup a descriptor from a directory descriptor. - * + * * @param dir * The directory descriptor. * @param name @@ -1488,13 +1480,12 @@ public class AVMRepository { throw new AVMNotFoundException("Not found: " + dir.getId()); } - if (node.getType() != AVMNodeType.LAYERED_DIRECTORY && - node.getType() != AVMNodeType.PLAIN_DIRECTORY) + if (node.getType() != AVMNodeType.LAYERED_DIRECTORY && node.getType() != AVMNodeType.PLAIN_DIRECTORY) { throw new AVMWrongTypeException("Not a directory."); } - DirectoryNode dirNode = (DirectoryNode)node; - if (!can(null, dirNode, PermissionService.READ_CHILDREN)) + DirectoryNode dirNode = (DirectoryNode) node; + if (!can(null, dirNode, PermissionService.READ_CHILDREN, false)) { throw new AccessDeniedException("Not allowed to read children: " + dir); } @@ -1508,7 +1499,7 @@ public class AVMRepository /** * Get all the paths to a particular node. - * + * * @param desc * The node descriptor. * @return The list of version, paths. @@ -1528,7 +1519,7 @@ public class AVMRepository /** * Get a single valid path for a node. - * + * * @param desc * The node descriptor. * @return A version, path @@ -1550,7 +1541,7 @@ public class AVMRepository /** * Get all paths for a node reachable by HEAD. - * + * * @param desc * The node descriptor. * @return A List of all the version, path Pairs that match. @@ -1570,7 +1561,7 @@ public class AVMRepository /** * Gets all the pass from to the given node starting from the give version root. - * + * * @param version * The version root. * @param node @@ -1587,7 +1578,7 @@ public class AVMRepository /** * Helper to get all version paths. - * + * * @param node * The current node we are examining. * @param components @@ -1601,7 +1592,7 @@ public class AVMRepository */ private void recursiveGetVersionPaths(AVMNode node, List components, List paths, DirectoryNode root, String storeName) { - if (!can(null, node, PermissionService.READ_CHILDREN)) + if (!can(null, node, PermissionService.READ_CHILDREN, false)) { return; } @@ -1623,7 +1614,7 @@ public class AVMRepository /** * Get all paths in a particular store in the head version for a particular node. - * + * * @param desc * The node descriptor. * @param store @@ -1650,7 +1641,7 @@ public class AVMRepository /** * Do the actual work. - * + * * @param node * The current node. * @param components @@ -1658,10 +1649,9 @@ public class AVMRepository * @param paths * The list to put full paths in. */ - private void recursiveGetPaths(AVMNode node, List components, - List> paths) + private void recursiveGetPaths(AVMNode node, List components, List> paths) { - if (!can(null, node, PermissionService.READ_CHILDREN)) + if (!can(null, node, PermissionService.READ_CHILDREN, false)) { return; } @@ -1692,7 +1682,7 @@ public class AVMRepository /** * Do the work of getting one path for a node. - * + * * @param node * The node to get the path of. * @param components @@ -1701,7 +1691,7 @@ public class AVMRepository */ private Pair recursiveGetAPath(AVMNode node, List components) { - if (!can(null, node, PermissionService.READ_CHILDREN)) + if (!can(null, node, PermissionService.READ_CHILDREN, false)) { return null; } @@ -1748,7 +1738,7 @@ public class AVMRepository /** * Do the actual work. - * + * * @param node * The current node. * @param components @@ -1756,10 +1746,9 @@ public class AVMRepository * @param paths * The list to put full paths in. */ - private void recursiveGetHeadPaths(AVMNode node, List components, - List> paths) + private void recursiveGetHeadPaths(AVMNode node, List components, List> paths) { - if (!can(null, node, PermissionService.READ_CHILDREN)) + if (!can(null, node, PermissionService.READ_CHILDREN, false)) { return; } @@ -1786,7 +1775,7 @@ public class AVMRepository /** * Do the actual work. - * + * * @param node * The current node. * @param components @@ -1794,11 +1783,9 @@ public class AVMRepository * @param paths * The list to put full paths in. */ - private void recursiveGetPathsInStoreHead(AVMNode node, List components, - List> paths, DirectoryNode root, - String storeName) + private void recursiveGetPathsInStoreHead(AVMNode node, List components, List> paths, DirectoryNode root, String storeName) { - if (!can(null, node, PermissionService.READ_CHILDREN)) + if (!can(null, node, PermissionService.READ_CHILDREN, false)) { return; } @@ -1820,7 +1807,7 @@ public class AVMRepository /** * Add a path to the list. - * + * * @param components * The path name components. * @param version @@ -1830,28 +1817,26 @@ public class AVMRepository * @param paths * The List to add to. */ - private void addPath(List components, int version, String storeName, - List> paths) + private void addPath(List components, int version, String storeName, List> paths) { paths.add(new Pair(version, makePath(components, storeName))); } /** * Alternate version. - * + * * @param components * @param storeName * @param paths */ - private void addPath(List components, String storeName, - List paths) + private void addPath(List components, String storeName, List paths) { paths.add(makePath(components, storeName)); } /** * Helper for generating paths. - * + * * @param components * The path components. * @param storeName @@ -1878,7 +1863,7 @@ public class AVMRepository /** * Get information about layering of a path. - * + * * @param version * The version to look under. * @param path @@ -1890,7 +1875,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -1901,13 +1886,11 @@ public class AVMRepository { throw new AVMNotFoundException("Path not found."); } - if (!can(store, lookup.getCurrentNode(), PermissionService.READ_PROPERTIES)) + if (!can(store, lookup.getCurrentNode(), PermissionService.READ_PROPERTIES, false)) { throw new AccessDeniedException("Not allowed to read properties: " + path); } - return new LayeringDescriptor(!lookup.getDirectlyContained(), - lookup.getAVMStore().getDescriptor(), - lookup.getFinalStore().getDescriptor()); + return new LayeringDescriptor(!lookup.getDirectlyContained(), lookup.getAVMStore().getDescriptor(), lookup.getFinalStore().getDescriptor()); } finally { @@ -1917,7 +1900,7 @@ public class AVMRepository /** * Lookup a directory specifically. - * + * * @param version * The version to look under. * @param path @@ -1938,7 +1921,7 @@ public class AVMRepository { throw new AVMCycleException("Cycle in lookup."); } - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -1957,14 +1940,14 @@ public class AVMRepository /** * Utility to split a path, foo:bar/baz into its repository and path parts. - * + * * @param path * The fully qualified path. * @return The repository name and the repository path. */ private String[] SplitPath(String path) { - String [] pathParts = path.split(":"); + String[] pathParts = path.split(":"); if (pathParts.length != 2) { throw new AVMException("Invalid path: " + path); @@ -1974,7 +1957,7 @@ public class AVMRepository /** * Make a directory into a primary indirection. - * + * * @param path * The full path. */ @@ -2000,7 +1983,7 @@ public class AVMRepository /** * Change what a layered directory points at. - * + * * @param path * The full path to the layered directory. * @param target @@ -2028,7 +2011,7 @@ public class AVMRepository /** * Get the history chain for a node. - * + * * @param desc * The node to get history of. * @param count @@ -2042,7 +2025,7 @@ public class AVMRepository { throw new AVMNotFoundException("Not found."); } - if (!can(null, node, PermissionService.READ_PROPERTIES)) + if (!can(null, node, PermissionService.READ_PROPERTIES, false)) { throw new AccessDeniedException("Not allowed to read properties: " + desc); } @@ -2058,7 +2041,7 @@ public class AVMRepository { break; } - if (!can(null, node, PermissionService.READ_PROPERTIES)) + if (!can(null, node, PermissionService.READ_PROPERTIES, false)) { break; } @@ -2069,7 +2052,7 @@ public class AVMRepository /** * Set the opacity of a layered directory. An opaque directory hides the things it points to via indirection. - * + * * @param path * The path to the layered directory. * @param opacity @@ -2097,7 +2080,7 @@ public class AVMRepository /** * Set a property on a node. - * + * * @param path * The path to the node. * @param name @@ -2110,7 +2093,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2127,7 +2110,7 @@ public class AVMRepository /** * Set a collection of properties at once. - * + * * @param path * The path to the node. * @param properties @@ -2138,7 +2121,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2155,7 +2138,7 @@ public class AVMRepository /** * Get a property by name for a node. - * + * * @param version * The version to look under. * @param path @@ -2169,7 +2152,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2185,7 +2168,7 @@ public class AVMRepository /** * Get a Map of all the properties of a node. - * + * * @param version * The version to look under. * @param path @@ -2197,7 +2180,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2213,7 +2196,7 @@ public class AVMRepository /** * Delete a single property from a node. - * + * * @param path * The path to the node. * @param name @@ -2224,7 +2207,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2241,7 +2224,7 @@ public class AVMRepository /** * Delete all properties on a node. - * + * * @param path * The path to the node. */ @@ -2250,7 +2233,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2267,7 +2250,7 @@ public class AVMRepository /** * Set a property on a store. Overwrites if property exists. - * + * * @param store * The AVMStore. * @param name @@ -2287,7 +2270,7 @@ public class AVMRepository /** * Set a group of properties on a store. Overwrites any properties that exist. - * + * * @param store * The AVMStore. * @param props @@ -2305,7 +2288,7 @@ public class AVMRepository /** * Get a property from a store. - * + * * @param store * The name of the store. * @param name @@ -2328,7 +2311,7 @@ public class AVMRepository /** * Queries a given store for properties with keys that match a given pattern. - * + * * @param store * The name of the store. * @param keyPattern @@ -2355,16 +2338,15 @@ public class AVMRepository /** * Queries all AVM stores for properties with keys that match a given pattern. - * + * * @param keyPattern * The sql 'like' pattern, inserted into a QName. * @return A List of Pairs of Store name, Map.Entry. */ - public Map> - queryStoresPropertyKeys(QName keyPattern) + public Map> queryStoresPropertyKeys(QName keyPattern) { List matches = fAVMStorePropertyDAO.queryByKeyPattern(keyPattern); - Map> results = new HashMap>(); + Map> results = new HashMap>(); for (AVMStoreProperty prop : matches) { String storeName = prop.getStore().getName(); @@ -2382,7 +2364,7 @@ public class AVMRepository /** * Get all the properties for a store. - * + * * @param store * The name of the Store. * @return A Map of all the properties. @@ -2403,7 +2385,7 @@ public class AVMRepository /** * Delete a property from a store. - * + * * @param store * The name of the store. * @param name @@ -2422,7 +2404,7 @@ public class AVMRepository /** * Get the common ancestor of two nodes if one exists. Unfortunately this is a quadratic problem, taking time * proportional to the product of the lengths of the left and right history chains. - * + * * @param left * The first node. * @param right @@ -2432,8 +2414,7 @@ public class AVMRepository * ancestor of left. Any other non null return is the common ancestor and indicates that left and right are * in conflict. */ - public AVMNodeDescriptor getCommonAncestor(AVMNodeDescriptor left, - AVMNodeDescriptor right) + public AVMNodeDescriptor getCommonAncestor(AVMNodeDescriptor left, AVMNodeDescriptor right) { AVMNode lNode = fAVMNodeDAO.getByID(left.getId()); AVMNode rNode = fAVMNodeDAO.getByID(right.getId()); @@ -2441,11 +2422,11 @@ public class AVMRepository { throw new AVMNotFoundException("Node not found."); } - if (!can(null, lNode, PermissionService.READ_PROPERTIES)) + if (!can(null, lNode, PermissionService.READ_PROPERTIES, false)) { throw new AccessDeniedException("Not allowed to read properties: " + left); } - if (!can(null, rNode, PermissionService.READ_PROPERTIES)) + if (!can(null, rNode, PermissionService.READ_PROPERTIES, false)) { throw new AccessDeniedException("Not allowed to read properties: " + right); } @@ -2497,7 +2478,7 @@ public class AVMRepository /** * Get the ContentData for a file. - * + * * @param version * The version to look under. * @param path @@ -2509,7 +2490,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); return store.getContentDataForRead(version, pathParts[1]); } @@ -2521,7 +2502,7 @@ public class AVMRepository /** * Get the ContentData for a file for writing. - * + * * @param path * The path to the file. * @return The ContentData object. @@ -2531,7 +2512,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2549,7 +2530,7 @@ public class AVMRepository /** * Set the ContentData on a file. - * + * * @param path * The path to the file. * @param data @@ -2560,7 +2541,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2577,7 +2558,7 @@ public class AVMRepository /** * Get the single instance of AVMRepository. - * + * * @return The single instance. */ public static AVMRepository GetInstance() @@ -2590,7 +2571,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2612,7 +2593,7 @@ public class AVMRepository /** * Add an aspect to an AVM Node. - * + * * @param path * The path to the node. * @param aspectName @@ -2623,7 +2604,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2640,7 +2621,7 @@ public class AVMRepository /** * Get all the aspects on an AVM node. - * + * * @param version * The version to look under. * @param path @@ -2652,7 +2633,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2668,7 +2649,7 @@ public class AVMRepository /** * Remove an aspect and all associated properties from a node. - * + * * @param path * The path to the node. * @param aspectName @@ -2679,7 +2660,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2696,7 +2677,7 @@ public class AVMRepository /** * Does a node have a particular aspect. - * + * * @param version * The version to look under. * @param path @@ -2710,7 +2691,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2726,7 +2707,7 @@ public class AVMRepository /** * Set the ACL on a node. - * + * * @param path * The path to the node. * @param acl @@ -2737,7 +2718,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2754,7 +2735,7 @@ public class AVMRepository /** * Get the ACL on a node. - * + * * @param version * The version to look under. * @param path @@ -2766,7 +2747,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2782,7 +2763,7 @@ public class AVMRepository /** * Link a node into a directory, directly. - * + * * @param parentPath * The path to the parent. * @param name @@ -2795,7 +2776,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(parentPath); + String[] pathParts = SplitPath(parentPath); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2810,11 +2791,10 @@ public class AVMRepository } } - /** * This is the danger version of link. It must be called on a copied and unsnapshotted directory. It blithely * inserts a child without checking if a child exists with a conflicting name. - * + * * @param parent * The parent directory. * @param name @@ -2829,12 +2809,12 @@ public class AVMRepository { throw new AVMWrongTypeException("Not a Directory."); } - DirectoryNode dir = (DirectoryNode)node; + DirectoryNode dir = (DirectoryNode) node; if (!dir.getIsNew()) { throw new AVMException("Directory has not already been copied."); } - if (!can(null, dir, PermissionService.ADD_CHILDREN)) + if (!can(null, dir, PermissionService.ADD_CHILDREN, false)) { throw new AccessDeniedException("Not allowed to write: " + parent); } @@ -2843,7 +2823,7 @@ public class AVMRepository /** * Remove name without leaving behind a deleted node. Dangerous if used unwisely. - * + * * @param path * The path to the layered directory. * @param name @@ -2854,7 +2834,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2871,11 +2851,11 @@ public class AVMRepository { throw new AVMWrongTypeException("Not a Layered Directory."); } - if (!can(store, node, PermissionService.DELETE_CHILDREN)) + if (!can(store, node, PermissionService.FLATTEN, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write in: " + path); } - LayeredDirectoryNode dir = (LayeredDirectoryNode)node; + LayeredDirectoryNode dir = (LayeredDirectoryNode) node; dir.flatten(name); } finally @@ -2886,7 +2866,7 @@ public class AVMRepository /** * Force a copy on write. - * + * * @param path * The path to force. */ @@ -2895,7 +2875,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2920,7 +2900,7 @@ public class AVMRepository /** * Rename a store. - * + * * @param sourceName * The original name. * @param destName @@ -2956,7 +2936,7 @@ public class AVMRepository /** * Revert a head path to a given version. This works by cloning the version to revert to, and then linking that new * version into head. The reverted version will have the previous head version as ancestor. - * + * * @param path * The path to the parent directory. * @param name @@ -2969,7 +2949,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -2986,7 +2966,7 @@ public class AVMRepository /** * Set the GUID on a node. - * + * * @param path * @param guid */ @@ -2995,7 +2975,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -3012,7 +2992,7 @@ public class AVMRepository /** * Set the encoding on a node. - * + * * @param path * @param encoding */ @@ -3021,7 +3001,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -3038,7 +3018,7 @@ public class AVMRepository /** * Set the mime type on a node. - * + * * @param path * @param encoding */ @@ -3047,7 +3027,7 @@ public class AVMRepository fLookupCount.set(1); try { - String [] pathParts = SplitPath(path); + String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); if (store == null) { @@ -3077,7 +3057,7 @@ public class AVMRepository /** * Do the actual work. - * + * * @param node * The current node. * @param components @@ -3085,18 +3065,16 @@ public class AVMRepository * @param paths * The list to put full paths in. */ - private void recursiveGetStoreVersionPaths(String storeName, AVMNode node, int version, List components, - List paths) + private void recursiveGetStoreVersionPaths(String storeName, AVMNode node, int version, List components, List paths) { - if (!can(null, node, PermissionService.READ)) + if (!can(null, node, PermissionService.READ, false)) { return; } if (node.getIsRoot()) { VersionRoot versionRoot = fVersionRootDAO.getByRoot(node); - if (versionRoot.getAvmStore().getName().equals(storeName) && - versionRoot.getVersionID() == version) + if (versionRoot.getAvmStore().getName().equals(storeName) && versionRoot.getVersionID() == version) { addPath(components, storeName, paths); return; @@ -3121,7 +3099,7 @@ public class AVMRepository { throw new AVMNotFoundException("Node not found: " + desc); } - if (!can(null, node, PermissionService.READ_PROPERTIES)) + if (!can(null, node, PermissionService.READ_PROPERTIES, false)) { throw new AccessDeniedException("Not allowed to read properties: " + desc); } @@ -3138,13 +3116,13 @@ public class AVMRepository { throw new AVMNotFoundException("Node not found: " + desc); } - if (!can(null, node, PermissionService.READ_CONTENT)) + if (!can(null, node, PermissionService.READ_CONTENT, false)) { throw new AccessDeniedException("Not allowed to read: " + desc); } if (node.getType() == AVMNodeType.PLAIN_FILE) { - PlainFileNode file = (PlainFileNode)node; + PlainFileNode file = (PlainFileNode) node; return file.getContentData(); } throw new AVMWrongTypeException("Not a Plain File: " + desc); @@ -3157,7 +3135,7 @@ public class AVMRepository { throw new AVMNotFoundException("Node not found: " + desc); } - if (!can(null, node, PermissionService.READ_PROPERTIES)) + if (!can(null, node, PermissionService.READ_PROPERTIES, false)) { throw new AccessDeniedException("Not allowed to read properties: " + desc); } @@ -3169,13 +3147,13 @@ public class AVMRepository /** * Evaluate permission on a node. I've got a bad feeling about this... + * * @param store * @param node * @param permission - * * @return */ - public boolean can(AVMStore store, AVMNode node, String permission) + public boolean can(AVMStore store, AVMNode node, String permission, boolean isDirectlyContained) { DbAccessControlList acl = node.getAcl(); @@ -3201,6 +3179,43 @@ public class AVMRepository // We're doing the hand unrolling of the proxy because Hibernate/CGLIB proxies are broken context.addDynamicAuthorityAssignment(AVMNodeUnwrapper.Unwrap(node).getBasicAttributes().getOwner(), PermissionService.OWNER_AUTHORITY); + if ((store != null) && isDirectlyContained) + { + StoreType storeType = StoreType.getStoreType(store.getName(), store.getDescriptor(), store.getProperties()); + switch (storeType) + { + case AUTHOR: + case AUTHOR_PREVIEW: + case AUTHOR_WORKFLOW: + case AUTHOR_WORKFLOW_PREVIEW: + String storeName = store.getName(); + int first = -1; + int second = -1; + first = storeName.indexOf("--"); + if (first >= 0) + { + second = storeName.indexOf("--", first + 2); + String storeOwner; + if (second >= 0) + { + storeOwner = storeName.substring(first + 2, second); + } + else + { + storeOwner = storeName.substring(first + 2); + } + context.addDynamicAuthorityAssignment(storeOwner, PermissionService.WCM_STORE_OWNER_AUTHORITY); + } + break; + case STAGING: + case STAGING_PREVIEW: + case UNKNOWN: + case WORKFLOW: + case WORKFLOW_PREVIEW: + default: + } + + } // Pass in node aspects Set nodeAspectQNames = qnameDAO.convertIdsToQNames(node.getAspects()); Set contextQNames = context.getAspects(); @@ -3224,7 +3239,7 @@ public class AVMRepository } context.getProperties().putAll(contextProperties); Long aclId = null; - if(acl != null) + if (acl != null) { aclId = acl.getId(); } @@ -3237,8 +3252,7 @@ public class AVMRepository context.setStoreAcl(storeAclID); } } - return fPermissionService.hasPermission(aclId, context, permission) - == AccessStatus.ALLOWED; + return fPermissionService.hasPermission(aclId, context, permission) == AccessStatus.ALLOWED; } public boolean can(String storeName, int version, String path, String permission) @@ -3248,7 +3262,7 @@ public class AVMRepository { AVMNode node = lookup.getCurrentNode(); AVMStore store = getAVMStoreByName(storeName); - return can(store, node, permission); + return can(store, node, permission, lookup.getDirectlyContained()); } else { @@ -3256,9 +3270,10 @@ public class AVMRepository return true; } } - + /** * Set the acl on a store. + * * @param storeName * @param acl */ @@ -3274,6 +3289,7 @@ public class AVMRepository /** * Get the ACL on a store. + * * @param storeName * @return */ diff --git a/source/java/org/alfresco/repo/avm/AVMServiceIndexTest.java b/source/java/org/alfresco/repo/avm/AVMServiceIndexTest.java index 47ea618112..201217b865 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceIndexTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceIndexTest.java @@ -44,129 +44,134 @@ public class AVMServiceIndexTest extends AVMServiceTestBase */ public void testAsyncIndex() throws Exception { - // Make sure the slate is clean ... - UserTransaction tx = fTransactionService.getUserTransaction(); - tx.begin(); - if (fService.getStore("avmAsynchronousTest") != null) + try { - assertTrue(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest")); + // Make sure the slate is clean ... + UserTransaction tx = fTransactionService.getUserTransaction(); + tx.begin(); + if (fService.getStore("avmAsynchronousTest") != null) + { + assertTrue(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest")); + fService.purgeStore("avmAsynchronousTest"); + assertTrue(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest")); + assertFalse(fIndexingInterceptor.hasIndexBeenCreated("bananaStoreWoof")); + } + else + { + assertFalse(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest")); + } + StoreRef storeRef = AVMNodeConverter.ToStoreRef("avmAsynchronousTest"); + Indexer indexer = fIndexerAndSearcher.getIndexer(storeRef); + if (indexer instanceof AVMLuceneIndexer) + { + AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer; + avmIndexer.deleteIndex("avmAsynchronousTest", IndexMode.SYNCHRONOUS); + } + tx.commit(); + + tx = fTransactionService.getUserTransaction(); + tx.begin(); + assertEquals(-1, fIndexingInterceptor.getLastIndexedSnapshot("bananaStoreWoof")); + assertEquals(-1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); + tx.commit(); + + // TODO: Suspend and resume indexing in case we are really unlucky and hit an index before we expect it. + + SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + ResultSet results; + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(0, results.length()); + results.close(); + + fService.createStore("avmAsynchronousTest"); + + tx = fTransactionService.getUserTransaction(); + tx.begin(); + assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); + tx.commit(); + + fService.createSnapshot("avmAsynchronousTest", null, null); + + tx = fTransactionService.getUserTransaction(); + tx.begin(); + assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); + tx.commit(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(1, results.length()); + results.close(); + + fService.createDirectory("avmAsynchronousTest:/", "a"); + fService.createDirectory("avmAsynchronousTest:/a", "b"); + fService.createDirectory("avmAsynchronousTest:/a/b", "c"); + + tx = fTransactionService.getUserTransaction(); + tx.begin(); + assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); + assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest")); + tx.commit(); + + fService.createSnapshot("avmAsynchronousTest", null, null); + + tx = fTransactionService.getUserTransaction(); + tx.begin(); + assertEquals(1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); + assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest")); + assertFalse(fIndexingInterceptor.isIndexUpToDateAndSearchable("avmAsynchronousTest")); + assertEquals(IndexMode.ASYNCHRONOUS, fIndexingInterceptor.getIndexMode("avmAsynchronousTest")); + assertEquals(IndexMode.SYNCHRONOUS, fIndexingInterceptor.getIndexMode("main")); + assertTrue(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 0)); + assertTrue(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 1)); + assertFalse(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 2)); + tx.commit(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(1, results.length()); + results.close(); + + Thread.sleep(180000); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(4, results.length()); + results.close(); + + tx = fTransactionService.getUserTransaction(); + tx.begin(); + assertEquals(1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); + assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest")); + assertTrue(fIndexingInterceptor.isIndexUpToDateAndSearchable("avmAsynchronousTest")); + tx.commit(); + fService.purgeStore("avmAsynchronousTest"); - assertTrue(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest")); - assertFalse(fIndexingInterceptor.hasIndexBeenCreated("bananaStoreWoof")); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(0, results.length()); + results.close(); + + fService.createStore("avmAsynchronousTest"); + fService.createSnapshot("avmAsynchronousTest", null, null); + fService.createDirectory("avmAsynchronousTest:/", "a"); + fService.createDirectory("avmAsynchronousTest:/a", "b"); + fService.createDirectory("avmAsynchronousTest:/a/b", "c"); + fService.createSnapshot("avmAsynchronousTest", null, null); + fService.purgeStore("avmAsynchronousTest"); + fService.createStore("avmAsynchronousTest"); + fService.createSnapshot("avmAsynchronousTest", null, null); + fService.createDirectory("avmAsynchronousTest:/", "a"); + fService.createDirectory("avmAsynchronousTest:/a", "b"); + fService.createDirectory("avmAsynchronousTest:/a/b", "c"); + fService.createSnapshot("avmAsynchronousTest", null, null); + + Thread.sleep(180000); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(4, results.length()); + results.close(); } - else + finally { - assertFalse(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest")); + fService.purgeStore("avmAsynchronousTest"); } - StoreRef storeRef = AVMNodeConverter.ToStoreRef("avmAsynchronousTest"); - Indexer indexer = fIndexerAndSearcher.getIndexer(storeRef); - if (indexer instanceof AVMLuceneIndexer) - { - AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer; - avmIndexer.deleteIndex("avmAsynchronousTest", IndexMode.SYNCHRONOUS); - } - tx.commit(); - - tx = fTransactionService.getUserTransaction(); - tx.begin(); - assertEquals(-1, fIndexingInterceptor.getLastIndexedSnapshot("bananaStoreWoof")); - assertEquals(-1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); - tx.commit(); - - // TODO: Suspend and resume indexing in case we are really unlucky and hit an index before we expect it. - - SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); - ResultSet results; - - results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); - assertEquals(0, results.length()); - results.close(); - - fService.createStore("avmAsynchronousTest"); - - tx = fTransactionService.getUserTransaction(); - tx.begin(); - assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); - tx.commit(); - - fService.createSnapshot("avmAsynchronousTest", null, null); - - tx = fTransactionService.getUserTransaction(); - tx.begin(); - assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); - tx.commit(); - - results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); - assertEquals(1, results.length()); - results.close(); - - fService.createDirectory("avmAsynchronousTest:/", "a"); - fService.createDirectory("avmAsynchronousTest:/a", "b"); - fService.createDirectory("avmAsynchronousTest:/a/b", "c"); - - tx = fTransactionService.getUserTransaction(); - tx.begin(); - assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); - assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest")); - tx.commit(); - - fService.createSnapshot("avmAsynchronousTest", null, null); - - tx = fTransactionService.getUserTransaction(); - tx.begin(); - assertEquals(1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); - assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest")); - assertFalse(fIndexingInterceptor.isIndexUpToDateAndSearchable("avmAsynchronousTest")); - assertEquals(IndexMode.ASYNCHRONOUS, fIndexingInterceptor.getIndexMode("avmAsynchronousTest")); - assertEquals(IndexMode.SYNCHRONOUS, fIndexingInterceptor.getIndexMode("main")); - assertTrue(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 0)); - assertTrue(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 1)); - assertFalse(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 2)); - tx.commit(); - - results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); - assertEquals(1, results.length()); - results.close(); - - Thread.sleep(180000); - - results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); - assertEquals(4, results.length()); - results.close(); - - tx = fTransactionService.getUserTransaction(); - tx.begin(); - assertEquals(1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); - assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest")); - assertTrue(fIndexingInterceptor.isIndexUpToDateAndSearchable("avmAsynchronousTest")); - tx.commit(); - - fService.purgeStore("avmAsynchronousTest"); - - results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); - assertEquals(0, results.length()); - results.close(); - - fService.createStore("avmAsynchronousTest"); - fService.createSnapshot("avmAsynchronousTest", null, null); - fService.createDirectory("avmAsynchronousTest:/", "a"); - fService.createDirectory("avmAsynchronousTest:/a", "b"); - fService.createDirectory("avmAsynchronousTest:/a/b", "c"); - fService.createSnapshot("avmAsynchronousTest", null, null); - fService.purgeStore("avmAsynchronousTest"); - fService.createStore("avmAsynchronousTest"); - fService.createSnapshot("avmAsynchronousTest", null, null); - fService.createDirectory("avmAsynchronousTest:/", "a"); - fService.createDirectory("avmAsynchronousTest:/a", "b"); - fService.createDirectory("avmAsynchronousTest:/a/b", "c"); - fService.createSnapshot("avmAsynchronousTest", null, null); - - Thread.sleep(180000); - - results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); - assertEquals(4, results.length()); - results.close(); - - fService.purgeStore("avmAsynchronousTest"); } } diff --git a/source/java/org/alfresco/repo/avm/AVMServicePermissionsTest.java b/source/java/org/alfresco/repo/avm/AVMServicePermissionsTest.java index 9b810c7c0d..3fa4c4681f 100644 --- a/source/java/org/alfresco/repo/avm/AVMServicePermissionsTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServicePermissionsTest.java @@ -324,7 +324,7 @@ public class AVMServicePermissionsTest extends TestCase AVMNode node = avmNodeDAO.getByID(desc.getId()); NodeRef nodeRef = AVMNodeConverter.ToNodeRef(-1, path); AVMStore store = AVMDAOs.Instance().fAVMStoreDAO.getByName(nodeRef.getStoreRef().getIdentifier()); - boolean can = AVMRepository.GetInstance().can(store, node, permission); + boolean can = AVMRepository.GetInstance().can(store, node, permission, AVMRepository.GetInstance().lookup(-1, path, false).getDirectlyContained()); return allowed ? can : !can; } finally @@ -343,11 +343,11 @@ public class AVMServicePermissionsTest extends TestCase AVMNode node = avmNodeDAO.getByID(desc.getId()); NodeRef nodeRef = AVMNodeConverter.ToNodeRef(-1, path); AVMStore store = AVMDAOs.Instance().fAVMStoreDAO.getByName(nodeRef.getStoreRef().getIdentifier()); - boolean can = AVMRepository.GetInstance().can(store, node, permission); + boolean can = AVMRepository.GetInstance().can(store, node, permission, AVMRepository.GetInstance().lookup(-1, path, false).getDirectlyContained()); long start = System.nanoTime(); for (int i = 0; i < count; i++) { - can = AVMRepository.GetInstance().can(null, node, permission); + can = AVMRepository.GetInstance().can(null, node, permission, AVMRepository.GetInstance().lookup(-1, path, false).getDirectlyContained()); } long end = System.nanoTime(); System.out.println("Can in " + ((end - start) / 10e9f / count)); diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java index 89a56e8854..1ee248f884 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java @@ -30,6 +30,7 @@ import java.io.InputStreamReader; import java.io.PrintStream; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -90,6 +91,69 @@ import org.alfresco.util.Pair; */ public class AVMServiceTest extends AVMServiceTestBase { + public void testDiffOrder() + { + try + { + fService.createStore("Bottom"); + fService.createStore("Top"); + + fService.createDirectory("Bottom:/", "www"); + fService.createLayeredDirectory("Bottom:/www", "Top:/", "www"); + + fService.createFile("Bottom:/www", "newInBottom"); + fService.createSnapshot("Bottom", null, null); + fService.createFile("Top:/www", "newInTop"); + fService.createSnapshot("Top", null, null); + fService.createFile("Bottom:/www", "file"); + fService.createSnapshot("Bottom", null, null); + fService.forceCopy("Top:/www/file"); + fService.createSnapshot("Top", null, null); + fService.forceCopy("Bottom:/www/file"); + fService.createSnapshot("Bottom", null, null); + + + List diffs = fSyncService.compare(-1, "Top:/", -1, "Bottom:/", null); + assertEquals( + 2, diffs.size()); + Collections.sort(diffs); + AVMDifference last = null; + for(AVMDifference current : diffs) + { + if(last != null) + { + assert(last.getOrderValue() < current.getOrderValue()); + } + last = current; + } + + diffs.add(new AVMDifference(1, null, -1, null, 0)); + diffs.add(new AVMDifference(1, null, -1, null, 1)); + diffs.add(new AVMDifference(1, null, -1, null, 2)); + diffs.add(new AVMDifference(1, null, -1, null, 3)); + diffs.add(new AVMDifference(1, null, -1, null, 4)); + diffs.add(new AVMDifference(1, null, -1, null, 5)); + diffs.add(new AVMDifference(1, null, -1, null, 6)); + + Collections.sort(diffs); + last = null; + for(AVMDifference current : diffs) + { + if(last != null) + { + assert(last.getOrderValue() < current.getOrderValue()); + } + last = current; + } + } + finally + { + fService.purgeStore("Bottom"); + fService.purgeStore("Top"); + } + + } + public void testETWOTWO570() throws Exception { // Check that read-write methods are properly intercepted @@ -5266,4 +5330,6 @@ public class AVMServiceTest extends AVMServiceTestBase fService.purgeStore("second"); } } + + } diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java b/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java index 144eed0329..1119a9c3d1 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java @@ -34,6 +34,7 @@ import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor; import org.alfresco.repo.search.IndexerAndSearcher; import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; +import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.avm.locking.AVMLockingService; @@ -88,9 +89,9 @@ public class AVMServiceTestBase extends TestCase protected static AuthenticationService fAuthService; - public void testSetup() + public void testSetup() throws Exception { - // NOOP + setupBasicTree(); } /** @@ -157,10 +158,12 @@ public class AVMServiceTestBase extends TestCase fAuthService.authenticate("admin", "admin".toCharArray()); - if (fService.getStore("main") == null) + if (fService.getStore("main") != null) { - fService.createStore("main"); + fService.purgeStore("main"); } + fService.createStore("main"); + if (!fLockingService.getWebProjects().contains("main")) { fLockingService.addWebProject("main"); @@ -184,6 +187,8 @@ public class AVMServiceTestBase extends TestCase // File alfData = new File("alf_data"); // File target = new File("alf_data" + now); // alfData.renameTo(target); + + AuthenticationUtil.clearCurrentSecurityContext(); } /** diff --git a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java index 570b059389..a06db64ddc 100644 --- a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java @@ -337,7 +337,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); - if (!fAVMRepository.can(this, dir, PermissionService.ADD_CHILDREN)) + if (!fAVMRepository.can(this, dir, PermissionService.ADD_CHILDREN, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write: " + path); } @@ -454,7 +454,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); - if (!fAVMRepository.can(this, dir, PermissionService.ADD_CHILDREN)) + if (!fAVMRepository.can(this, dir, PermissionService.ADD_CHILDREN, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write: " + path); } @@ -496,7 +496,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); - if (!fAVMRepository.can(this, dir, PermissionService.ADD_CHILDREN)) + if (!fAVMRepository.can(this, dir, PermissionService.ADD_CHILDREN, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write: " + path); } @@ -563,7 +563,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + dstPath + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); - if (!fAVMRepository.can(this, dir, PermissionService.ADD_CHILDREN)) + if (!fAVMRepository.can(this, dir, PermissionService.ADD_CHILDREN, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write: " + dstPath); } @@ -645,7 +645,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); - if (!fAVMRepository.can(this, dir, PermissionService.READ_CHILDREN)) + if (!fAVMRepository.can(this, dir, PermissionService.READ_CHILDREN, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read: " + path); } @@ -668,7 +668,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); - if (!fAVMRepository.can(this, dir, PermissionService.READ_CHILDREN)) + if (!fAVMRepository.can(this, dir, PermissionService.READ_CHILDREN, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read: " + path); } @@ -715,7 +715,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); - if (!fAVMRepository.can(this, dir, PermissionService.READ_CHILDREN)) + if (!fAVMRepository.can(this, dir, PermissionService.READ_CHILDREN, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read: " + path); } @@ -747,14 +747,18 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); - if (!fAVMRepository.can(this, dir, PermissionService.DELETE_CHILDREN)) - { - throw new AVMNotFoundException("Not allowed to write: " + path); - } - if (dir.lookupChild(lPath, name, false) == null) + Pair temp = dir.lookupChild(lPath, name, false); + AVMNode child = (temp == null) ? null : temp.getFirst(); + if (child == null) { throw new AVMNotFoundException("Does not exist: " + name); } + + if (!fAVMRepository.can(this, child, PermissionService.DELETE_NODE, false)) + { + throw new AVMNotFoundException("Not allowed to delete in store : " + getName() +" at " + path); + } + dir.removeChild(lPath, name); //dir.updateModTime(); } @@ -766,19 +770,25 @@ public class AVMStoreImpl implements AVMStore, Serializable */ public void uncover(String dirPath, String name) { - Lookup lPath = lookup(-1, dirPath, true, false); + Lookup lPath = lookupDirectory(-1, dirPath, true); if (lPath == null) { - throw new AVMNotFoundException("Path " + dirPath + " not found."); + throw new AVMNotFoundException("Directory path " + dirPath + " not found."); } - AVMNode node = lPath.getCurrentNode(); + DirectoryNode node = (DirectoryNode)lPath.getCurrentNode(); if (node.getType() != AVMNodeType.LAYERED_DIRECTORY) { throw new AVMWrongTypeException("Not a layered directory: " + dirPath); } - if (!fAVMRepository.can(this, node, PermissionService.DELETE_CHILDREN)) + Pair temp = node.lookupChild(lPath, name, true); + AVMNode child = (temp == null) ? null : temp.getFirst(); + if(child == null) { - throw new AccessDeniedException("Not allowed to write: " + dirPath); + throw new AVMNotFoundException("No child to recover at "+dirPath+" called "+name); + } + if (!fAVMRepository.can(this, child, PermissionService.DELETE_NODE, false)) + { + throw new AccessDeniedException("Not allowed to uncover: " + dirPath + " -> "+name); } ((LayeredDirectoryNode)node).uncover(lPath, name); node.updateModTime(); @@ -875,7 +885,7 @@ public class AVMStoreImpl implements AVMStore, Serializable { root = AVMDAOs.Instance().fAVMNodeDAO.getAVMStoreRoot(this, version); } - if (!fAVMRepository.can(this, root, PermissionService.READ_CHILDREN)) + if (!fAVMRepository.can(this, root, PermissionService.READ_CHILDREN, true)) { throw new AccessDeniedException("Not allowed to read: " + fName + "@" + version); } @@ -924,7 +934,7 @@ public class AVMStoreImpl implements AVMStore, Serializable return null; } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.READ_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.READ_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read: " + path); } @@ -957,7 +967,7 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMException("Not in a layered context: " + path); } - if (!fAVMRepository.can(this, dir, PermissionService.WRITE_PROPERTIES)) + if (!fAVMRepository.can(this, dir, PermissionService.WRITE_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write: " + path); } @@ -982,7 +992,7 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMException("Not in a layered context: " + path); } - if (!fAVMRepository.can(this, dir, PermissionService.WRITE_PROPERTIES)) + if (!fAVMRepository.can(this, dir, PermissionService.WRITE_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write: " + path); } @@ -1138,7 +1148,7 @@ public class AVMStoreImpl implements AVMStore, Serializable } AVMDAOs.Instance().fVersionLayeredNodeEntryDAO.delete(vRoot); AVMNode root = vRoot.getRoot(); - if (!fAVMRepository.can(null, root, PermissionService.DELETE_CHILDREN)) + if (!fAVMRepository.can(null, root, PermissionService.DELETE_CHILDREN, true)) { throw new AccessDeniedException("Not allowed to purge: " + fName + "@" + version); } @@ -1191,7 +1201,7 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMWrongTypeException("Not a LayeredDirectoryNode."); } - if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write: " + path); } @@ -1214,7 +1224,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write: " + path); } @@ -1237,7 +1247,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write: " + path); } @@ -1271,7 +1281,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.READ_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.READ_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read: " + path); } @@ -1304,7 +1314,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.READ_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.READ_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read: " + path); } @@ -1329,7 +1339,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write: " + path); } @@ -1360,7 +1370,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write: " + path); } @@ -1458,7 +1468,7 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMWrongTypeException("File Expected."); } - if (!fAVMRepository.can(this, node, PermissionService.READ_CONTENT)) + if (!fAVMRepository.can(this, node, PermissionService.READ_CONTENT, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read: " + path); } @@ -1485,7 +1495,7 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMWrongTypeException("File Expected."); } - if (!fAVMRepository.can(this, node, PermissionService.WRITE_CONTENT)) + if (!fAVMRepository.can(this, node, PermissionService.WRITE_CONTENT, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write content: " + path); } @@ -1534,7 +1544,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path not found: " + path); } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write properties: " + path); } @@ -1555,7 +1565,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write: " + path); } @@ -1581,7 +1591,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.READ_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.READ_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read properties: " + path); } @@ -1604,7 +1614,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write properties: " + path); } @@ -1642,7 +1652,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.READ_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.READ_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read properties: " + path); } @@ -1672,7 +1682,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.CHANGE_PERMISSIONS)) + if (!fAVMRepository.can(this, node, PermissionService.CHANGE_PERMISSIONS, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to change permissions: " + path); } @@ -1693,7 +1703,7 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMNotFoundException("Path " + path + " not found."); } - if (!fAVMRepository.can(this, lPath.getCurrentNode(), PermissionService.READ_PERMISSIONS)) + if (!fAVMRepository.can(this, lPath.getCurrentNode(), PermissionService.READ_PERMISSIONS, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read permissions: " + path + " in "+getName()); } @@ -1714,7 +1724,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + parentPath + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); - if (!fAVMRepository.can(null, dir, PermissionService.ADD_CHILDREN)) + if (!fAVMRepository.can(null, dir, PermissionService.ADD_CHILDREN, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to add children: " + parentPath); } @@ -1737,17 +1747,17 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); - if (!fAVMRepository.can(null, dir, PermissionService.DELETE_CHILDREN) || - !fAVMRepository.can(null, dir, PermissionService.ADD_CHILDREN)) - { - throw new AccessDeniedException("Not allowed to revert: " + path); - } + Pair temp = dir.lookupChild(lPath, name, true); AVMNode child = (temp == null) ? null : temp.getFirst(); if (child == null) { throw new AVMNotFoundException("Node not found: " + name); } + if (!fAVMRepository.can(null, child, PermissionService.WRITE, false)) + { + throw new AccessDeniedException("Not allowed to revert: " + path); + } AVMNode revertNode = AVMDAOs.Instance().fAVMNodeDAO.getByID(toRevertTo.getId()); if (revertNode == null) { @@ -1778,7 +1788,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path not found: " + path); } AVMNode node = lPath.getCurrentNode(); - if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write properties: " + path); } @@ -1800,7 +1810,7 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMWrongTypeException("Not a File: " + path); } - if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write properties: " + path); } @@ -1823,7 +1833,7 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMWrongTypeException("Not a File: " + path); } - if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES)) + if (!fAVMRepository.can(this, node, PermissionService.WRITE_PROPERTIES, lPath.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to write properties: " + path); } diff --git a/source/java/org/alfresco/repo/avm/AVMTestSuite.java b/source/java/org/alfresco/repo/avm/AVMTestSuite.java index c0e3484aa2..fac8913bc8 100644 --- a/source/java/org/alfresco/repo/avm/AVMTestSuite.java +++ b/source/java/org/alfresco/repo/avm/AVMTestSuite.java @@ -44,10 +44,12 @@ public class AVMTestSuite extends TestSuite suite.addTestSuite(AVMNodeConverterTest.class); suite.addTestSuite(AVMExpiredContentTest.class); suite.addTestSuite(FileNameValidatorTest.class); + suite.addTestSuite(AVMDeploymentAttemptCleanerTest.class); suite.addTestSuite(AVMServiceTestBase.class); suite.addTestSuite(AVMServiceTest.class); suite.addTestSuite(AVMServiceLocalTest.class); + suite.addTestSuite(AVMServicePermissionsTest.class); suite.addTestSuite(AVMServiceIndexTest.class); suite.addTestSuite(AVMServicePerfTest.class); @@ -58,7 +60,8 @@ public class AVMTestSuite extends TestSuite suite.addTestSuite(PurgeTestP.class); suite.addTestSuite(SimultaneousLoadTest.class); - + suite.addTestSuite(AVMDiffPerformanceTest.class); + return suite; } } diff --git a/source/java/org/alfresco/repo/avm/ChildEntryDAO.java b/source/java/org/alfresco/repo/avm/ChildEntryDAO.java index 40af96ab59..e5c1d54f65 100644 --- a/source/java/org/alfresco/repo/avm/ChildEntryDAO.java +++ b/source/java/org/alfresco/repo/avm/ChildEntryDAO.java @@ -48,6 +48,7 @@ public interface ChildEntryDAO /** * Get all the children of a given parent. * @param parent The parent. + * @param eager - true -> fetch children in the query * @return A List of ChildEntries. */ public List getByParent(DirectoryNode parent); diff --git a/source/java/org/alfresco/repo/avm/LayeredDirectoryNode.java b/source/java/org/alfresco/repo/avm/LayeredDirectoryNode.java index 9ea2d43939..ebaffbbe87 100644 --- a/source/java/org/alfresco/repo/avm/LayeredDirectoryNode.java +++ b/source/java/org/alfresco/repo/avm/LayeredDirectoryNode.java @@ -1,5 +1,7 @@ package org.alfresco.repo.avm; +import org.alfresco.repo.domain.DbAccessControlList; + /** * Interface for Layered Directories. * @author britt @@ -89,4 +91,6 @@ public interface LayeredDirectoryNode extends DirectoryNode, Layered * @return The opacity. */ public boolean getOpacity(); + + public void setAclAndInherit(LayeredDirectoryNode layeredDirectory, DbAccessControlList acl, String name); } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java index 9633b479d5..f0381ee605 100644 --- a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java @@ -157,7 +157,6 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec * @param repos * The AVMStore object we use. */ - @SuppressWarnings("unchecked") public LayeredDirectoryNodeImpl(LayeredDirectoryNode other, AVMStore repos, Lookup lookup, boolean copyAll, Long parentAcl, ACLCopyMode mode) { super(repos.getAVMRepository().issueID(), repos); @@ -200,7 +199,6 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec * @param lPath * The Lookup object. */ - @SuppressWarnings("unchecked") public LayeredDirectoryNodeImpl(PlainDirectoryNode other, AVMStore store, Lookup lPath, boolean copyContents, Long parentAcl, ACLCopyMode mode) { super(store.getAVMRepository().issueID(), store); @@ -431,7 +429,6 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec * The Lookup. * @return A Map from names to nodes. This is a sorted Map. */ - @SuppressWarnings("unchecked") public Map getListing(Lookup lPath, boolean includeDeleted) { // Get the base listing from the thing we indirect to. @@ -448,7 +445,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec if (entry.getValue().getType() == AVMNodeType.LAYERED_DIRECTORY || entry.getValue().getType() == AVMNodeType.PLAIN_DIRECTORY) { - if (!AVMRepository.GetInstance().can(lookup.getAVMStore(), entry.getValue(), PermissionService.READ_CHILDREN)) + if (!AVMRepository.GetInstance().can(lookup.getAVMStore(), entry.getValue(), PermissionService.READ_CHILDREN, false)) { continue; } @@ -462,7 +459,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec if (entry.getChild().getType() == AVMNodeType.LAYERED_DIRECTORY || entry.getChild().getType() == AVMNodeType.PLAIN_DIRECTORY) { - if (!AVMRepository.GetInstance().can(lPath.getAVMStore(), entry.getChild(), PermissionService.READ_CHILDREN)) + if (!AVMRepository.GetInstance().can(lPath.getAVMStore(), entry.getChild(), PermissionService.READ_CHILDREN, lPath.getDirectlyContained())) { continue; } @@ -494,7 +491,9 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec if (entry.getChild().getType() == AVMNodeType.LAYERED_DIRECTORY || entry.getChild().getType() == AVMNodeType.PLAIN_DIRECTORY) { - if (!AVMRepository.GetInstance().can(lPath != null ? lPath.getAVMStore() : null, entry.getChild(), PermissionService.READ_CHILDREN)) + if (!AVMRepository.GetInstance().can(lPath != null ? lPath.getAVMStore() : null, + entry.getChild(), PermissionService.READ_CHILDREN, + lPath != null ? lPath.getDirectlyContained() : false)) { continue; } @@ -526,7 +525,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec if (childNode.getType() == AVMNodeType.LAYERED_DIRECTORY || childNode.getType() == AVMNodeType.PLAIN_DIRECTORY) { - if (!AVMRepository.GetInstance().can(null, childNode, PermissionService.READ_CHILDREN)) + if (!AVMRepository.GetInstance().can(null, childNode, PermissionService.READ_CHILDREN, false)) { continue; } @@ -570,7 +569,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec if (entry.getValue().getType() == AVMNodeType.LAYERED_DIRECTORY || entry.getValue().getType() == AVMNodeType.PLAIN_DIRECTORY) { - if (!AVMRepository.GetInstance().can(null, entry.getValue(), PermissionService.READ_CHILDREN)) + if (!AVMRepository.GetInstance().can(null, entry.getValue(), PermissionService.READ_CHILDREN, false)) { continue; } @@ -588,7 +587,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec if (child.getChild().getType() == AVMNodeType.LAYERED_DIRECTORY || child.getChild().getType() == AVMNodeType.PLAIN_DIRECTORY) { - if (!AVMRepository.GetInstance().can(null, child.getChild(), PermissionService.READ_CHILDREN)) + if (!AVMRepository.GetInstance().can(null, child.getChild(), PermissionService.READ_CHILDREN, false)) { continue; } @@ -638,7 +637,6 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec * Whether this lookup is occurring in a write context. * @return The child or null if not found. */ - @SuppressWarnings("unchecked") public Pair lookupChild(Lookup lPath, String name, boolean includeDeleted) { ChildKey key = new ChildKey(this, name); @@ -733,7 +731,6 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec * @param name * The name of the child to remove. */ - @SuppressWarnings("unchecked") public void removeChild(Lookup lPath, String name) { if (DEBUG) @@ -874,7 +871,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec } } - protected void setAclAndInherit(LayeredDirectoryNodeImpl layeredDirectory, DbAccessControlList acl, String name) + public void setAclAndInherit(LayeredDirectoryNode layeredDirectory, DbAccessControlList acl, String name) { // Note ACLS may COW on next ACL change layeredDirectory.setAcl(acl); @@ -883,9 +880,9 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec { AVMNode node = directChildren.get(key); - if (node instanceof LayeredDirectoryNodeImpl) + if (node instanceof LayeredDirectoryNode) { - LayeredDirectoryNodeImpl childNode = (LayeredDirectoryNodeImpl) node; + LayeredDirectoryNode childNode = (LayeredDirectoryNode) node; DbAccessControlList currentAcl = node.getAcl(); if (currentAcl == null) { @@ -910,9 +907,9 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec } } } - else if (node instanceof PlainFileNodeImpl) + else if (node instanceof PlainFileNode) { - PlainFileNodeImpl childNode = (PlainFileNodeImpl) node; + PlainFileNode childNode = (PlainFileNode) node; DbAccessControlList currentAcl = node.getAcl(); if (currentAcl == null) { diff --git a/source/java/org/alfresco/repo/avm/NOOPLookupCache.java b/source/java/org/alfresco/repo/avm/NOOPLookupCache.java index 64f81c3c47..f2f0f965a7 100644 --- a/source/java/org/alfresco/repo/avm/NOOPLookupCache.java +++ b/source/java/org/alfresco/repo/avm/NOOPLookupCache.java @@ -92,7 +92,7 @@ public class NOOPLookupCache implements LookupCache // before the end. for (int i = 0; i < path.size() - 1; i++) { - if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN)) + if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN, result.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read children: " + path.get(i)); } @@ -111,7 +111,7 @@ public class NOOPLookupCache implements LookupCache dir = (DirectoryNode)result.getCurrentNode(); } // Now look up the last element. - if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN)) + if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN, result.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read children: " + path.get(path.size() - 1)); } diff --git a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java index 073d41f872..1d0f3796df 100644 --- a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java @@ -117,7 +117,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory if (child.getChild().getType() == AVMNodeType.LAYERED_DIRECTORY || child.getChild().getType() == AVMNodeType.PLAIN_DIRECTORY) { - if (!AVMRepository.GetInstance().can(lPath.getAVMStore(), child.getChild(), PermissionService.READ_CHILDREN)) + if (!AVMRepository.GetInstance().can(lPath.getAVMStore(), child.getChild(), PermissionService.READ_CHILDREN, lPath.getDirectlyContained())) { continue; } @@ -171,7 +171,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory if (child.getChild().getType() == AVMNodeType.LAYERED_DIRECTORY || child.getChild().getType() == AVMNodeType.PLAIN_DIRECTORY) { - if (!AVMRepository.GetInstance().can(null, child.getChild(), PermissionService.READ_CHILDREN)) + if (!AVMRepository.GetInstance().can(null, child.getChild(), PermissionService.READ_CHILDREN, false)) { continue; } diff --git a/source/java/org/alfresco/repo/avm/TransactionalLookupCache.java b/source/java/org/alfresco/repo/avm/TransactionalLookupCache.java index abcece7207..94b0537126 100644 --- a/source/java/org/alfresco/repo/avm/TransactionalLookupCache.java +++ b/source/java/org/alfresco/repo/avm/TransactionalLookupCache.java @@ -166,7 +166,7 @@ public class TransactionalLookupCache implements LookupCache, InitializingBean // before the end. for (int i = 0; i < path.size() - 1; i++) { - if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN)) + if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN, result.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read children: " + path.get(i)); } @@ -185,7 +185,7 @@ public class TransactionalLookupCache implements LookupCache, InitializingBean dir = (DirectoryNode)result.getCurrentNode(); } // Now look up the last element. - if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN)) + if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN, result.getDirectlyContained())) { throw new AccessDeniedException("Not allowed to read children: " + path.get(path.size() - 1)); } diff --git a/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml b/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml index b5dc4d6877..6a95720c10 100644 --- a/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml +++ b/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml @@ -11,7 +11,7 @@ name="AVMNodeImpl" proxy="AVMNode" optimistic-lock="version" - lazy="true"> + lazy="false"> @@ -78,11 +78,11 @@ + lazy="false"> + discriminator-value="layereddirectory" lazy="false"> @@ -102,7 +102,7 @@ + discriminator-value="plaindirectory" proxy="PlainDirectoryNode" lazy="false"> @@ -112,7 +112,7 @@ lazy="false"> + name="PlainFileNodeImpl" proxy="PlainFileNode" lazy="false"> @@ -120,7 +120,7 @@ + discriminator-value="layeredfile" proxy="LayeredFileNode" lazy="false"> @@ -190,7 +190,7 @@ - + diff --git a/source/java/org/alfresco/repo/avm/hibernate/ChildEntryDAOHibernate.java b/source/java/org/alfresco/repo/avm/hibernate/ChildEntryDAOHibernate.java index 7c5dc8f686..aca775324d 100644 --- a/source/java/org/alfresco/repo/avm/hibernate/ChildEntryDAOHibernate.java +++ b/source/java/org/alfresco/repo/avm/hibernate/ChildEntryDAOHibernate.java @@ -31,15 +31,19 @@ import org.alfresco.repo.avm.ChildEntryImpl; import org.alfresco.repo.avm.ChildEntryDAO; import org.alfresco.repo.avm.ChildKey; import org.alfresco.repo.avm.DirectoryNode; +import org.hibernate.Criteria; +import org.hibernate.FetchMode; import org.hibernate.Query; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Restrictions; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; /** * The Hibernate version of the ChildEntry DAO. + * * @author britt */ -class ChildEntryDAOHibernate extends HibernateDaoSupport implements - ChildEntryDAO +class ChildEntryDAOHibernate extends HibernateDaoSupport implements ChildEntryDAO { /** * Do nothing constructor. @@ -51,7 +55,9 @@ class ChildEntryDAOHibernate extends HibernateDaoSupport implements /** * Save an unsaved ChildEntry. - * @param entry The entry to save. + * + * @param entry + * The entry to save. */ public void save(ChildEntry entry) { @@ -60,64 +66,78 @@ class ChildEntryDAOHibernate extends HibernateDaoSupport implements /** * Get an entry by name and parent. - * @param name The name of the child to find. - * @param parent The parent to look in. + * + * @param name + * The name of the child to find. + * @param parent + * The parent to look in. * @return The ChildEntry or null if not foun. */ public ChildEntry get(ChildKey key) { SessionCacheChecker.instance.check(); - return (ChildEntry)getSession().get(ChildEntryImpl.class, key); + return (ChildEntry) getSession().get(ChildEntryImpl.class, key); } /** * Get all the children of a given parent. - * @param parent The parent. + * + * @param parent + * The parent. * @return A List of ChildEntries. */ @SuppressWarnings("unchecked") public List getByParent(DirectoryNode parent) { - Query query = - getSession().createQuery("from ChildEntryImpl ce where ce.key.parent = :parent"); - query.setEntity("parent", parent); - return (List)query.list(); + Criteria criteria = getSession().createCriteria(ChildEntryImpl.class, "ce"); + criteria.add(Restrictions.eq("ce.key.parent", parent)); + criteria.createCriteria("child", "cld").setFetchMode("ce.child", FetchMode.JOIN); + criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); + // Query query = + // getSession().createQuery("select ce, cld from ChildEntryImpl ce join child cld where ce.key.parent = + // :parent"); + // query.setEntity("parent", parent); + return (List) criteria.list(); } /** * Get the entry for a given child in a given parent. - * @param parent The parent. - * @param child The child. + * + * @param parent + * The parent. + * @param child + * The child. * @return The ChildEntry or null. */ public ChildEntry getByParentChild(DirectoryNode parent, AVMNode child) { - Query query = - getSession().createQuery("from ChildEntryImpl ce where ce.key.parent = :parent " + - "and ce.child = :child"); + Query query = getSession().createQuery("from ChildEntryImpl ce where ce.key.parent = :parent " + "and ce.child = :child"); query.setEntity("parent", parent); query.setEntity("child", child); SessionCacheChecker.instance.check(); - return (ChildEntry)query.uniqueResult(); + return (ChildEntry) query.uniqueResult(); } /** * Get all the ChildEntries corresponding to the given child. - * @param child The child for which to look up entries. + * + * @param child + * The child for which to look up entries. * @return The matching entries. */ @SuppressWarnings("unchecked") public List getByChild(AVMNode child) { - Query query = getSession().createQuery("from ChildEntryImpl ce " + - "where ce.child = :child"); + Query query = getSession().createQuery("from ChildEntryImpl ce " + "where ce.child = :child"); query.setEntity("child", child); - return (List)query.list(); + return (List) query.list(); } /** * Update a dirty ChildEntry. - * @param child The dirty entry. + * + * @param child + * The dirty entry. */ public void update(ChildEntry child) { @@ -126,17 +146,20 @@ class ChildEntryDAOHibernate extends HibernateDaoSupport implements /** * Delete one. - * @param child The one to delete. + * + * @param child + * The one to delete. */ public void delete(ChildEntry child) { getSession().delete(child); } - // TODO Does this have dangerous interactions with the cache? /** * Delete all children of the given parent. - * @param parent The parent. + * + * @param parent + * The parent. */ public void deleteByParent(AVMNode parent) { @@ -145,7 +168,9 @@ class ChildEntryDAOHibernate extends HibernateDaoSupport implements delete.executeUpdate(); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.alfresco.repo.avm.ChildEntryDAO#evict(org.alfresco.repo.avm.ChildEntry) */ public void evict(ChildEntry entry) diff --git a/source/java/org/alfresco/repo/domain/hibernate/AVMAccessControlListDAO.java b/source/java/org/alfresco/repo/domain/hibernate/AVMAccessControlListDAO.java index a10f0cc965..bdc8eea9f3 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/AVMAccessControlListDAO.java +++ b/source/java/org/alfresco/repo/domain/hibernate/AVMAccessControlListDAO.java @@ -34,8 +34,10 @@ import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.avm.AVMRepository; import org.alfresco.repo.domain.AccessControlListDAO; import org.alfresco.repo.domain.DbAccessControlList; +import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.domain.hibernate.AclDaoComponentImpl.Indirection; import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor; +import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor.StoreType; import org.alfresco.repo.search.impl.lucene.index.IndexInfo; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; @@ -54,6 +56,7 @@ import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.InvalidStoreRefException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.namespace.QName; import org.alfresco.util.EqualsHelper; import org.alfresco.util.Pair; import org.apache.commons.logging.Log; @@ -70,7 +73,7 @@ public class AVMAccessControlListDAO implements AccessControlListDAO * The logger. */ private static Log s_logger = LogFactory.getLog(AVMAccessControlListDAO.class); - + /** * Reference to the AVM Repository instance. */ @@ -268,8 +271,9 @@ public class AVMAccessControlListDAO implements AccessControlListDAO public void updateChangedAcls(NodeRef startingPoint, List changes) { - // If their are no actual changes there is nothing to do (the changes are all in TX and have already COWed so they can just change) - + // If their are no actual changes there is nothing to do (the changes are all in TX and have already COWed so + // they can just change) + boolean hasChanges = false; Long after = null; for (AclChange change : changes) @@ -282,22 +286,22 @@ public class AVMAccessControlListDAO implements AccessControlListDAO { after = change.getAfter(); } - - if(!EqualsHelper.nullSafeEquals(change.getTypeBefore(), change.getTypeAfter())) + + if (!EqualsHelper.nullSafeEquals(change.getTypeBefore(), change.getTypeAfter())) { hasChanges = true; } - if(!EqualsHelper.nullSafeEquals(change.getBefore(), change.getAfter())) + if (!EqualsHelper.nullSafeEquals(change.getBefore(), change.getAfter())) { hasChanges = true; } } - - if(!hasChanges) + + if (!hasChanges) { return; } - + Long inherited = null; if (after != null) { @@ -307,8 +311,6 @@ public class AVMAccessControlListDAO implements AccessControlListDAO updateChangedAclsImpl(startingPoint, changes, SetMode.ALL, inherited, after, indirections); } - - private void updateChangedAclsImpl(NodeRef startingPoint, List changes, SetMode mode, Long inherited, Long setAcl, Map> indirections) { hibernateSessionHelper.mark(); @@ -762,7 +764,10 @@ public class AVMAccessControlListDAO implements AccessControlListDAO { AVMNodeDescriptor root = fAVMService.getStoreRoot(-1, store.getName()); CounterSet update; - switch (avmSnapShotTriggeredIndexingMethodInterceptor.getStoreType(store.getName())) + + Map storeProperties = fAVMService.getStoreProperties(store.getName()); + + switch (StoreType.getStoreType(store.getName(), store, storeProperties)) { case AUTHOR: case AUTHOR_PREVIEW: @@ -773,7 +778,7 @@ public class AVMAccessControlListDAO implements AccessControlListDAO case WORKFLOW: case WORKFLOW_PREVIEW: AVMNodeDescriptor www = fAVMService.lookup(-1, store.getName() + ":/www"); - if(www != null) + if (www != null) { update = fixOldAvmAcls(www, false, indirections); result.add(update); diff --git a/source/java/org/alfresco/repo/domain/hibernate/AclDaoComponentImpl.java b/source/java/org/alfresco/repo/domain/hibernate/AclDaoComponentImpl.java index 804c3b9c09..5709ae3592 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/AclDaoComponentImpl.java +++ b/source/java/org/alfresco/repo/domain/hibernate/AclDaoComponentImpl.java @@ -1578,6 +1578,10 @@ public class AclDaoComponentImpl extends HibernateDaoSupport implements AclDaoCo } return toCopy; case REDIRECT: + if((toInheritFrom != null) && (toInheritFrom == toCopy)) + { + return getInheritedAccessControlList(toInheritFrom); + } aclToCopy = (DbAccessControlList) getHibernateTemplate().get(DbAccessControlListImpl.class, toCopy); aclToInheritFrom = null; if (toInheritFrom != null) diff --git a/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml b/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml index 916c504cbe..ced4516b58 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml +++ b/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml @@ -472,11 +472,12 @@ JOIN alf_store s on s.id = n.store_id WHERE c.qname_localname = :userName1 AND - p.qname_id = :qnameId AND + p.qname_id = :qnamePropId AND p.string_value = :userName2 AND + n.type_qname_id = :qnameTypeId AND n.node_deleted = :False AND - s.protocol = :storeProtocol AND - s.identifier = :storeIdentifier + s.protocol = :storeProtocol AND + s.identifier = :storeIdentifier @@ -488,7 +489,8 @@ JOIN alf_node_properties p ON n.id = p.node_id JOIN alf_store s on s.id = n.store_id WHERE - p.qname_id = :qnameId AND + p.qname_id = :qnamePropId AND + n.type_qname_id = :qnameTypeId AND n.node_deleted = :False AND s.protocol = :storeProtocol AND s.identifier = :storeIdentifier diff --git a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java index ad2e06fb37..d9b4778d38 100644 --- a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java +++ b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java @@ -44,6 +44,7 @@ import java.util.TreeMap; import java.util.zip.CRC32; import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.error.ExceptionStackUtil; import org.alfresco.model.ContentModel; import org.alfresco.repo.cache.SimpleCache; import org.alfresco.repo.domain.AuditableProperties; @@ -160,6 +161,18 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements /** Log to trace parent association caching: classname + .ParentAssocsCache */ private static Log loggerParentAssocsCache = LogFactory.getLog(HibernateNodeDaoServiceImpl.class.getName() + ".ParentAssocsCache"); + /** + * Exceptions that indicate duplicate child names violations. + */ + @SuppressWarnings("unchecked") + public static final Class[] DUPLICATE_CHILD_NAME_EXCEPTIONS; + static + { + DUPLICATE_CHILD_NAME_EXCEPTIONS = new Class[] { + ConstraintViolationException.class + }; + } + private QNameDAO qnameDAO; private UsageDeltaDAO usageDeltaDAO; private AclDaoComponent aclDaoComponent; @@ -1589,13 +1602,34 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements DirtySessionMethodInterceptor.flushSession(getSession(false)); Long assocId = (Long) getHibernateTemplate().execute(new HibernateCallback() { + @SuppressWarnings("unchecked") public Object doInHibernate(Session session) { try { - Object result = session.save(assoc); - DirtySessionMethodInterceptor.flushSession(session); - return result; + try + { + Object result = session.save(assoc); + DirtySessionMethodInterceptor.flushSession(session, true); + return result; + } + catch (Throwable e) + { + ConstraintViolationException constraintViolation = (ConstraintViolationException) ExceptionStackUtil.getCause( + e, + DUPLICATE_CHILD_NAME_EXCEPTIONS); + if (constraintViolation == null) + { + // It was something else + RuntimeException ee = AlfrescoRuntimeException.makeRuntimeException( + e, "Exception while flushing child assoc to database"); + throw ee; + } + else + { + throw constraintViolation; + } + } } catch (ConstraintViolationException e) { diff --git a/source/java/org/alfresco/repo/search/AVMSnapShotTriggeredIndexingMethodInterceptor.java b/source/java/org/alfresco/repo/search/AVMSnapShotTriggeredIndexingMethodInterceptor.java index a12b957ffa..e8f10276f9 100644 --- a/source/java/org/alfresco/repo/search/AVMSnapShotTriggeredIndexingMethodInterceptor.java +++ b/source/java/org/alfresco/repo/search/AVMSnapShotTriggeredIndexingMethodInterceptor.java @@ -35,6 +35,7 @@ import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.search.impl.lucene.AVMLuceneIndexer; import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avm.AVMStoreDescriptor; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.namespace.QName; import org.aopalliance.intercept.MethodInterceptor; @@ -307,9 +308,10 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte return false; } } - + /** - * Check if the index is up to date according to its index defintion i it does not check that all asynchronous work is done. + * Check if the index is up to date according to its index defintion i it does not check that all asynchronous work + * is done. * * @param store * @return @@ -362,7 +364,13 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte } else { - String storeType = getStoreType(store).toString(); + AVMStoreDescriptor avmStoreDescriptor = avmService.getStore(store); + Map storeProperties = null; + if (avmStoreDescriptor != null) + { + storeProperties = avmService.getStoreProperties(store); + } + String storeType = StoreType.getStoreType(store, avmStoreDescriptor, storeProperties).toString(); if (def.pattern.matcher(storeType).matches()) { mode = def.indexMode; @@ -403,54 +411,6 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte } } - public StoreType getStoreType(String name) - { - if (avmService.getStore(name) != null) - { - Map storeProperties = avmService.getStoreProperties(name); - if (storeProperties.containsKey(PROP_SANDBOX_STAGING_MAIN)) - { - return StoreType.STAGING; - } - else if (storeProperties.containsKey(PROP_SANDBOX_STAGING_PREVIEW)) - { - return StoreType.STAGING_PREVIEW; - } - else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_MAIN)) - { - return StoreType.AUTHOR; - } - else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_PREVIEW)) - { - return StoreType.AUTHOR_PREVIEW; - } - else if (storeProperties.containsKey(PROP_SANDBOX_WORKFLOW_MAIN)) - { - return StoreType.WORKFLOW; - } - else if (storeProperties.containsKey(PROP_SANDBOX_WORKFLOW_PREVIEW)) - { - return StoreType.WORKFLOW_PREVIEW; - } - else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_WORKFLOW_MAIN)) - { - return StoreType.AUTHOR_WORKFLOW; - } - else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_WORKFLOW_PREVIEW)) - { - return StoreType.AUTHOR_WORKFLOW_PREVIEW; - } - else - { - return StoreType.UNKNOWN; - } - } - else - { - return StoreType.UNKNOWN; - } - } - private enum DefinitionType { NAME, TYPE; @@ -459,6 +419,55 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte public enum StoreType { STAGING, STAGING_PREVIEW, AUTHOR, AUTHOR_PREVIEW, WORKFLOW, WORKFLOW_PREVIEW, AUTHOR_WORKFLOW, AUTHOR_WORKFLOW_PREVIEW, UNKNOWN; + + public static StoreType getStoreType(String name, AVMStoreDescriptor storeDescriptor, Map storeProperties) + { + // if (avmService.getStore(name) != null) + if (storeDescriptor != null) + { + // Map storeProperties = avmService.getStoreProperties(name); + if (storeProperties.containsKey(PROP_SANDBOX_STAGING_MAIN)) + { + return StoreType.STAGING; + } + else if (storeProperties.containsKey(PROP_SANDBOX_STAGING_PREVIEW)) + { + return StoreType.STAGING_PREVIEW; + } + else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_MAIN)) + { + return StoreType.AUTHOR; + } + else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_PREVIEW)) + { + return StoreType.AUTHOR_PREVIEW; + } + else if (storeProperties.containsKey(PROP_SANDBOX_WORKFLOW_MAIN)) + { + return StoreType.WORKFLOW; + } + else if (storeProperties.containsKey(PROP_SANDBOX_WORKFLOW_PREVIEW)) + { + return StoreType.WORKFLOW_PREVIEW; + } + else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_WORKFLOW_MAIN)) + { + return StoreType.AUTHOR_WORKFLOW; + } + else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_WORKFLOW_PREVIEW)) + { + return StoreType.AUTHOR_WORKFLOW_PREVIEW; + } + else + { + return StoreType.UNKNOWN; + } + } + else + { + return StoreType.UNKNOWN; + } + } } public boolean hasIndexBeenCreated(String store) @@ -484,7 +493,7 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte avmIndexer.createIndex(store, IndexMode.SYNCHRONOUS); } } - + public AVMLuceneIndexer getIndexer(String store) { StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); @@ -497,5 +506,4 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte return null; } - } diff --git a/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceTest.java b/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceTest.java index 1c8efd8865..ad2ccff861 100644 --- a/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceTest.java +++ b/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceTest.java @@ -937,7 +937,7 @@ public class PermissionServiceTest extends AbstractPermissionTest public void testGetSettablePermissionsForType() { Set answer = permissionService.getSettablePermissions(QName.createQName("sys", "base", namespacePrefixResolver)); - assertEquals(36, answer.size()); + assertEquals(38, answer.size()); answer = permissionService.getSettablePermissions(QName.createQName("cm", "ownable", namespacePrefixResolver)); assertEquals(0, answer.size()); @@ -957,22 +957,22 @@ public class PermissionServiceTest extends AbstractPermissionTest QName ownable = QName.createQName("cm", "ownable", namespacePrefixResolver); Set answer = permissionService.getSettablePermissions(rootNodeRef); - assertEquals(36, answer.size()); + assertEquals(38, answer.size()); nodeService.addAspect(rootNodeRef, ownable, null); answer = permissionService.getSettablePermissions(rootNodeRef); - assertEquals(36, answer.size()); + assertEquals(38, answer.size()); nodeService.removeAspect(rootNodeRef, ownable); answer = permissionService.getSettablePermissions(rootNodeRef); - assertEquals(36, answer.size()); + assertEquals(38, answer.size()); } public void testSimplePermissionOnRoot() { runAs("andy"); - assertEquals(36, permissionService.getPermissions(rootNodeRef).size()); + assertEquals(38, permissionService.getPermissions(rootNodeRef).size()); assertEquals(0, countGranted(permissionService.getPermissions(rootNodeRef))); assertEquals(0, permissionService.getAllSetPermissions(rootNodeRef).size()); @@ -984,7 +984,7 @@ public class PermissionServiceTest extends AbstractPermissionTest assertEquals(1, permissionService.getAllSetPermissions(rootNodeRef).size()); runAs("andy"); - assertEquals(36, permissionService.getPermissions(rootNodeRef).size()); + assertEquals(38, permissionService.getPermissions(rootNodeRef).size()); assertEquals(2, countGranted(permissionService.getPermissions(rootNodeRef))); assertTrue(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_PROPERTIES)) == AccessStatus.ALLOWED); @@ -1089,7 +1089,7 @@ public class PermissionServiceTest extends AbstractPermissionTest permissionService.setPermission(allowAndyRead); runAs("andy"); - assertEquals(36, permissionService.getPermissions(rootNodeRef).size()); + assertEquals(38, permissionService.getPermissions(rootNodeRef).size()); assertEquals(7, countGranted(permissionService.getPermissions(rootNodeRef))); assertEquals(1, permissionService.getAllSetPermissions(rootNodeRef).size()); diff --git a/source/java/org/alfresco/repo/security/permissions/impl/model/PermissionModelTest.java b/source/java/org/alfresco/repo/security/permissions/impl/model/PermissionModelTest.java index 51e4cad5c4..d41dbd84e8 100644 --- a/source/java/org/alfresco/repo/security/permissions/impl/model/PermissionModelTest.java +++ b/source/java/org/alfresco/repo/security/permissions/impl/model/PermissionModelTest.java @@ -90,7 +90,7 @@ public class PermissionModelTest extends AbstractPermissionTest // NB This has gone from 59 to 63, I believe, because of the for new WCM roles. // 63-97 from AVM permission fix up - assertEquals(97, grantees.size()); + assertEquals(99, grantees.size()); } public void testIncludePermissionGroups6() @@ -119,7 +119,7 @@ public class PermissionModelTest extends AbstractPermissionTest public void testGlobalPermissions() { Set globalPermissions = permissionModelDAO.getGlobalPermissionEntries(); - assertEquals(5, globalPermissions.size()); + assertEquals(6, globalPermissions.size()); } public void testRequiredPermissions() @@ -144,13 +144,13 @@ public class PermissionModelTest extends AbstractPermissionTest required = permissionModelDAO.getRequiredPermissions(SimplePermissionReference.getPermissionReference(QName.createQName("cm", "cmobject", namespacePrefixResolver), "Coordinator"), QName.createQName("cm", "cmobject", namespacePrefixResolver), Collections.emptySet(), On.NODE); - assertEquals(17, required.size()); + assertEquals(18, required.size()); required = permissionModelDAO.getRequiredPermissions(SimplePermissionReference.getPermissionReference(QName.createQName("sys", "base", namespacePrefixResolver), "FullControl"), QName.createQName("sys", "base", namespacePrefixResolver), Collections.emptySet(), On.NODE); - assertEquals(17, required.size()); + assertEquals(18, required.size()); diff --git a/source/java/org/alfresco/repo/security/person/PersonDaoImpl.java b/source/java/org/alfresco/repo/security/person/PersonDaoImpl.java index 445aeb559d..20e7c65c0a 100644 --- a/source/java/org/alfresco/repo/security/person/PersonDaoImpl.java +++ b/source/java/org/alfresco/repo/security/person/PersonDaoImpl.java @@ -56,11 +56,9 @@ public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao private static final String QUERY_PERSON_GET_ALL_PEOPLE = "person.getAllPeople"; private QNameDAO qnameDAO; - - private Long qNameId; - + private Long qNamePropId; + private Long qNameTypeId; private LocaleDAO localeDAO; - private DictionaryService dictionaryService; private StoreRef storeRef; @@ -89,7 +87,8 @@ public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao public Object doInHibernate(Session session) { SQLQuery query = (SQLQuery) session.getNamedQuery(QUERY_PERSON_GET_PERSON); - query.setParameter("qnameId", qNameId); + query.setParameter("qnamePropId", qNamePropId); + query.setParameter("qnameTypeId", qNameTypeId); query.setParameter("userName1", searchUserName); query.setParameter("userName2", searchUserName); query.setParameter("False", Boolean.FALSE); @@ -124,7 +123,8 @@ public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao public void init() { - qNameId = qnameDAO.getOrCreateQName(ContentModel.PROP_USERNAME).getFirst(); + qNamePropId = qnameDAO.getOrCreateQName(ContentModel.PROP_USERNAME).getFirst(); + qNameTypeId = qnameDAO.getOrCreateQName(ContentModel.TYPE_PERSON).getFirst(); } @SuppressWarnings("unchecked") @@ -139,7 +139,8 @@ public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao public Object doInHibernate(Session session) { SQLQuery query = (SQLQuery) session.getNamedQuery(QUERY_PERSON_GET_ALL_PEOPLE); - query.setParameter("qnameId", qNameId); + query.setParameter("qnamePropId", qNamePropId); + query.setParameter("qnameTypeId", qNameTypeId); query.setParameter("False", Boolean.FALSE); query.setParameter("storeProtocol", personStoreRef.getProtocol()); query.setParameter("storeIdentifier", personStoreRef.getIdentifier()); diff --git a/source/java/org/alfresco/repo/transaction/RetryingTransactionHelper.java b/source/java/org/alfresco/repo/transaction/RetryingTransactionHelper.java index adc6c6b6f7..2757a87675 100644 --- a/source/java/org/alfresco/repo/transaction/RetryingTransactionHelper.java +++ b/source/java/org/alfresco/repo/transaction/RetryingTransactionHelper.java @@ -354,16 +354,9 @@ public class RetryingTransactionHelper // Somebody else 'owns' the transaction, so just rethrow. if (txn == null) { - if (e instanceof RuntimeException) - { - throw (RuntimeException)e; - } - else - { - throw new AlfrescoRuntimeException( - "Exception from transactional callback: " + cb, - e); - } + RuntimeException ee = AlfrescoRuntimeException.makeRuntimeException( + e, "Exception from transactional callback: " + cb); + throw ee; } if (logger.isDebugEnabled()) { diff --git a/source/java/org/alfresco/service/cmr/avmsync/AVMDifference.java b/source/java/org/alfresco/service/cmr/avmsync/AVMDifference.java index 4f0fea565f..cb2be8c438 100644 --- a/source/java/org/alfresco/service/cmr/avmsync/AVMDifference.java +++ b/source/java/org/alfresco/service/cmr/avmsync/AVMDifference.java @@ -26,56 +26,65 @@ package org.alfresco.service.cmr.avmsync; import java.io.Serializable; /** - * Represents the difference between corresponding nodes - * in parallel avm node trees. It it indicates for the difference + * Represents the difference between corresponding nodes in parallel avm node trees. It it indicates for the difference * whether the source is older, newer, or in conflict with the destination. + * * @author britt */ -public class AVMDifference implements Serializable +public class AVMDifference implements Serializable, Comparable { private static final long serialVersionUID = -589722861571724954L; public static final int NEWER = 0; + public static final int OLDER = 1; + public static final int CONFLICT = 2; + public static final int DIRECTORY = 3; + public static final int SAME = 4; - + /** * Version number of the source node. */ private int fSourceVersion; - + /** * Path of the source node. */ private String fSourcePath; - + /** * Version number of the destination node. */ private int fDestVersion; - + /** * Path of the destination node. */ private String fDestPath; - + /** * The difference code. */ private int fDiffCode; - + /** * Make one up. - * @param srcVersion The source version. - * @param srcPath the source path. - * @param dstVersion The destination version. - * @param dstPath The destination path. - * @param diffCode The difference code, NEWER, OLDER, CONFLICT + * + * @param srcVersion + * The source version. + * @param srcPath + * the source path. + * @param dstVersion + * The destination version. + * @param dstPath + * The destination path. + * @param diffCode + * The difference code, NEWER, OLDER, CONFLICT */ - public AVMDifference(int srcVersion, String srcPath, - int dstVersion, String dstPath, int diffCode) + public AVMDifference(int srcVersion, String srcPath, int dstVersion, String dstPath, int diffCode) { fSourceVersion = srcVersion; fSourcePath = srcPath; @@ -83,36 +92,40 @@ public class AVMDifference implements Serializable fDestPath = dstPath; fDiffCode = diffCode; } - + /** * Get the source version number. + * * @return The source version number. */ public int getSourceVersion() { return fSourceVersion; } - + /** * Get the source path. + * * @return The source path. */ public String getSourcePath() { return fSourcePath; } - + /** * Get the destination version number. + * * @return The destination version number. */ public int getDestinationVersion() { return fDestVersion; } - + /** * Get the destination path. + * * @return The destination path. */ public String getDestinationPath() @@ -122,24 +135,27 @@ public class AVMDifference implements Serializable /** * Get the difference code, NEWER, OLDER, CONFLICT. + * * @return The difference code. */ public int getDifferenceCode() { return fDiffCode; } - + /** * Check for improperly initialized instances. + * * @return Whether source and destination are non null. */ public boolean isValid() { return fSourcePath != null && fDestPath != null; } - + /** * Get as String. + * * @return A String representation of this. */ @Override @@ -152,23 +168,23 @@ public class AVMDifference implements Serializable builder.append("] "); switch (fDiffCode) { - case SAME : - builder.append("= "); - break; - case NEWER : - builder.append("> "); - break; - case OLDER : - builder.append("< "); - break; - case CONFLICT : - builder.append("<> "); - break; - case DIRECTORY : - builder.append("| "); - break; - default : - builder.append("? "); + case SAME: + builder.append("= "); + break; + case NEWER: + builder.append("> "); + break; + case OLDER: + builder.append("< "); + break; + case CONFLICT: + builder.append("<> "); + break; + case DIRECTORY: + builder.append("| "); + break; + default: + builder.append("? "); } builder.append(fDestPath); builder.append("["); @@ -176,4 +192,28 @@ public class AVMDifference implements Serializable builder.append("]"); return builder.toString(); } + + public int compareTo(AVMDifference other) + { + return this.getOrderValue() - other.getOrderValue(); + } + + public int getOrderValue() + { + switch (fDiffCode) + { + case CONFLICT: + return 0; + case NEWER: + return 1; + case OLDER: + return 2; + case DIRECTORY: + return 3; + case SAME: + return 4; + default: + return 100; + } + } } diff --git a/source/java/org/alfresco/service/cmr/security/PermissionService.java b/source/java/org/alfresco/service/cmr/security/PermissionService.java index a6ea19eb29..5ac05b33a3 100644 --- a/source/java/org/alfresco/service/cmr/security/PermissionService.java +++ b/source/java/org/alfresco/service/cmr/security/PermissionService.java @@ -65,6 +65,11 @@ public interface PermissionService */ public static final String OWNER_AUTHORITY = "ROLE_OWNER"; + /** + * The authority that all owners of WCM stores have. + */ + public static final String WCM_STORE_OWNER_AUTHORITY = "ROLE_WCM_STORE_OWNER"; + /** * The dynamic authority used for the ownership of locks. */ @@ -163,6 +168,8 @@ public interface PermissionService public static final String WCM_CONTENT_REVIEWER = "ContentReviewer"; + public static final String FLATTEN = "Flatten"; + /** * Get the Owner Authority * diff --git a/source/java/org/alfresco/wcm/asset/AssetInfo.java b/source/java/org/alfresco/wcm/asset/AssetInfo.java index 82fe42e285..d2aa460c0a 100644 --- a/source/java/org/alfresco/wcm/asset/AssetInfo.java +++ b/source/java/org/alfresco/wcm/asset/AssetInfo.java @@ -60,4 +60,6 @@ public interface AssetInfo public Date getModifiedDate(); public String getAvmPath(); // absolute AVM path, eg. : + + public int getDiffCode(); // if applicable, eg. when getting list of changed assets (see AVMDifference for diff codes), else -1 } diff --git a/source/java/org/alfresco/wcm/asset/AssetInfoImpl.java b/source/java/org/alfresco/wcm/asset/AssetInfoImpl.java index 8f69c01328..44261fa38a 100644 --- a/source/java/org/alfresco/wcm/asset/AssetInfoImpl.java +++ b/source/java/org/alfresco/wcm/asset/AssetInfoImpl.java @@ -37,6 +37,7 @@ public class AssetInfoImpl implements AssetInfo private AVMNodeDescriptor node; private String lockOwner = null; // null if not locked private int sandboxVersion = -1; + private int diffCode = -1; // if applicable, eg. when getting list of modified assets /* package */ AssetInfoImpl(int sandboxVersion, AVMNodeDescriptor node, String lockOwner) { @@ -124,4 +125,14 @@ public class AssetInfoImpl implements AssetInfo { return node.getPath(); } + + public int getDiffCode() + { + return diffCode; + } + + public void setDiffCode(int diffCode) + { + this.diffCode = diffCode; + } } diff --git a/source/java/org/alfresco/wcm/sandbox/SandboxServiceImpl.java b/source/java/org/alfresco/wcm/sandbox/SandboxServiceImpl.java index 624e7bb781..856619500b 100644 --- a/source/java/org/alfresco/wcm/sandbox/SandboxServiceImpl.java +++ b/source/java/org/alfresco/wcm/sandbox/SandboxServiceImpl.java @@ -62,6 +62,7 @@ import org.alfresco.util.Pair; import org.alfresco.util.ParameterCheck; import org.alfresco.util.VirtServerUtils; import org.alfresco.wcm.asset.AssetInfo; +import org.alfresco.wcm.asset.AssetInfoImpl; import org.alfresco.wcm.asset.AssetService; import org.alfresco.wcm.util.WCMUtil; import org.alfresco.wcm.util.WCMWorkflowUtil; @@ -433,6 +434,8 @@ public class SandboxServiceImpl implements SandboxService AssetInfo asset = assetService.getAsset(parts[0], -1, parts[1], includeDeleted); if (asset != null) { + // TODO refactor + ((AssetInfoImpl)asset).setDiffCode(diff.getDifferenceCode()); assets.add(asset); } }