From e5bef04dbff12c7616b887f5da143df77cbe9ada Mon Sep 17 00:00:00 2001 From: Britt Park Date: Thu, 4 Oct 2007 17:32:10 +0000 Subject: [PATCH] Renames of directories now behave as one would expect. (Fixes WCM-856) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6920 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../org/alfresco/repo/avm/AVMInterpreter.java | 36 +- .../org/alfresco/repo/avm/AVMRepository.java | 314 +++++++++--------- .../org/alfresco/repo/avm/AVMServiceTest.java | 283 +++++++++------- .../repo/avm/LayeredDirectoryNodeImpl.java | 96 +++--- 4 files changed, 394 insertions(+), 335 deletions(-) diff --git a/source/java/org/alfresco/repo/avm/AVMInterpreter.java b/source/java/org/alfresco/repo/avm/AVMInterpreter.java index 15ed91cb9b..259cea635f 100644 --- a/source/java/org/alfresco/repo/avm/AVMInterpreter.java +++ b/source/java/org/alfresco/repo/avm/AVMInterpreter.java @@ -56,12 +56,12 @@ public class AVMInterpreter * The service interface. */ private AVMService fService; - + /** * The sync service. */ private AVMSyncService fSyncService; - + /** * The reader for interaction. */ @@ -73,12 +73,12 @@ public class AVMInterpreter private BulkLoader fLoader; /** - * Main entry point. + * Main entry point. * Syntax: AVMInteractiveConsole storage (new|old). */ public static void main(String[] args) { - FileSystemXmlApplicationContext context = + FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("config/alfresco/application-context.xml"); AVMInterpreter console = new AVMInterpreter(); console.setAvmService((AVMService)context.getBean("AVMService")); @@ -106,7 +106,7 @@ public class AVMInterpreter { fService = service; } - + /** * Set the AVM sync service. * @param syncService @@ -115,7 +115,7 @@ public class AVMInterpreter { fSyncService = syncService; } - + /** * Set the bulk loader. * @param loader @@ -124,7 +124,7 @@ public class AVMInterpreter { fLoader = loader; } - + /** * A Read-Eval-Print loop. */ @@ -181,7 +181,7 @@ public class AVMInterpreter return "Not Found."; } Map listing = - fService.getDirectoryListing(desc); + fService.getDirectoryListing(desc, true); for (String name : listing.keySet()) { out.println(name + " " + listing.get(name)); @@ -320,9 +320,9 @@ public class AVMInterpreter { return "Syntax Error."; } - BufferedReader reader = + BufferedReader reader = new BufferedReader( - new InputStreamReader(fService.getFileInputStream(Integer.parseInt(command[2]), + new InputStreamReader(fService.getFileInputStream(Integer.parseInt(command[2]), command[1]))); String l; while ((l = reader.readLine()) != null) @@ -361,7 +361,7 @@ public class AVMInterpreter { return "Syntax Error."; } - PrintStream ps = + PrintStream ps = new PrintStream(fService.getFileOutputStream(command[1])); String l; while (!(l = in.readLine()).equals("")) @@ -376,7 +376,7 @@ public class AVMInterpreter { return "Syntax Error."; } - PrintStream ps = + PrintStream ps = new PrintStream(fService.createFile(command[1], command[2])); String l; while (!(l = in.readLine()).equals("")) @@ -415,7 +415,7 @@ public class AVMInterpreter { return "Syntax Error."; } - + fService.deleteNodeProperty(command[1], QName.createQName(command[2])); out.println("deleted property " + command[2] + " of " + command[1]); } @@ -483,7 +483,7 @@ public class AVMInterpreter return "Not Found."; } out.println(desc); - Map props = + Map props = fService.getStoreProperties(command[1]); for (QName name : props.keySet()) { @@ -512,7 +512,7 @@ public class AVMInterpreter { return "Syntax Error."; } - AVMDifference diff = new AVMDifference(Integer.parseInt(command[2]), command[1], + AVMDifference diff = new AVMDifference(Integer.parseInt(command[2]), command[1], -1, command[3], AVMDifference.NEWER); List diffs = new ArrayList(); diffs.add(diff); @@ -552,7 +552,7 @@ public class AVMInterpreter private void recursiveList(PrintStream out, AVMNodeDescriptor dir, int indent) { - Map listing = fService.getDirectoryListing(dir); + Map listing = fService.getDirectoryListing(dir, true); for (String name : listing.keySet()) { AVMNodeDescriptor child = listing.get(name); @@ -568,7 +568,7 @@ public class AVMInterpreter } } } - - + + diff --git a/source/java/org/alfresco/repo/avm/AVMRepository.java b/source/java/org/alfresco/repo/avm/AVMRepository.java index fe49a558c2..56cd0853e4 100644 --- a/source/java/org/alfresco/repo/avm/AVMRepository.java +++ b/source/java/org/alfresco/repo/avm/AVMRepository.java @@ -65,22 +65,22 @@ public class AVMRepository { @SuppressWarnings("unused") private static Log fgLogger = LogFactory.getLog(AVMRepository.class); - + /** * The single instance of AVMRepository. */ private static AVMRepository fgInstance; - + /** * The current lookup count. */ private ThreadLocal fLookupCount; - + /** * The node id issuer. */ private Issuer fNodeIssuer; - + /** * The layer id issuer. */ @@ -90,46 +90,46 @@ public class AVMRepository * Reference to the ContentStoreImpl */ private ContentStore fContentStore; - + /** * The Lookup Cache instance. */ private LookupCache fLookupCache; - + private AVMStoreDAO fAVMStoreDAO; - + private AVMNodeDAO fAVMNodeDAO; - + private VersionRootDAO fVersionRootDAO; - + private VersionLayeredNodeEntryDAO fVersionLayeredNodeEntryDAO; - + private AVMStorePropertyDAO fAVMStorePropertyDAO; - + private ChildEntryDAO fChildEntryDAO; // A bunch of TransactionListeners that do work for this. - + /** * One for create store. */ private CreateStoreTxnListener fCreateStoreTxnListener; - + /** * One for purge store. */ private PurgeStoreTxnListener fPurgeStoreTxnListener; - + /** * One for create version. */ private CreateVersionTxnListener fCreateVersionTxnListener; - + /** * One for purge version. */ private PurgeVersionTxnListener fPurgeVersionTxnListener; - + /** * Create a new one. */ @@ -138,7 +138,7 @@ public class AVMRepository fLookupCount = new ThreadLocal(); fgInstance = this; } - + /** * Set the node issuer. For Spring. * @param nodeIssuer The issuer. @@ -156,7 +156,7 @@ public class AVMRepository { fLayerIssuer = layerIssuer; } - + /** * Set the ContentService. */ @@ -164,7 +164,7 @@ public class AVMRepository { fContentStore = store; } - + /** * Set the Lookup Cache instance. * @param cache The instance to set. @@ -178,7 +178,7 @@ public class AVMRepository { fCreateStoreTxnListener = listener; } - + public void setPurgeStoreTxnListener(PurgeStoreTxnListener listener) { fPurgeStoreTxnListener = listener; @@ -198,32 +198,32 @@ public class AVMRepository { fAVMStoreDAO = dao; } - + public void setAvmNodeDAO(AVMNodeDAO dao) { fAVMNodeDAO = dao; } - + public void setVersionRootDAO(VersionRootDAO dao) { fVersionRootDAO = dao; } - + public void setVersionLayeredNodeEntryDAO(VersionLayeredNodeEntryDAO dao) { fVersionLayeredNodeEntryDAO = dao; } - + public void setAvmStorePropertyDAO(AVMStorePropertyDAO dao) { fAVMStorePropertyDAO = dao; } - + public void setChildEntryDAO(ChildEntryDAO dao) { fChildEntryDAO = dao; } - + /** * Create a file. * @param path The path to the containing directory. @@ -232,7 +232,7 @@ public class AVMRepository public OutputStream createFile(String path, String name) { fLookupCount.set(1); - try + try { String[] pathParts = SplitPath(path); AVMStore store = getAVMStoreByName(pathParts[0]); @@ -245,8 +245,8 @@ public class AVMRepository } finally { - fLookupCount.set(null); - } + fLookupCount.set(null); + } } /** @@ -272,9 +272,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Create a new directory. * @param path The path to the containing directory. @@ -297,7 +297,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } /** @@ -341,7 +341,7 @@ public class AVMRepository fLookupCache.onWrite(pathParts[0]); return child.getDescriptor(parent.getPath(), name, parent.getIndirection(), parent.getIndirectionVersion()); } - + /** * Create a new layered directory. * @param srcPath The target indirection for the new layered directory. @@ -370,7 +370,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } /** @@ -396,7 +396,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } /** @@ -411,7 +411,7 @@ public class AVMRepository throw new AVMExistsException("AVMStore exists: " + name); } // Newing up the object causes it to be written to the db. - @SuppressWarnings("unused") + @SuppressWarnings("unused") AVMStore rep = new AVMStoreImpl(this, name); // Special handling for AVMStore creation. rep.getRoot().setStoreNew(null); @@ -447,7 +447,7 @@ public class AVMRepository if (version < 0) { fLookupCache.onSnapshot(pathParts[0]); - version = + version = srcRepo.createSnapshot("Branch Snapshot", null, new HashMap()).get(pathParts[0]); } sPath = srcRepo.lookup(version, pathParts[1], false, false); @@ -461,7 +461,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } // Lookup the destination directory. fLookupCount.set(1); try @@ -481,7 +481,7 @@ public class AVMRepository DirectoryNode dirNode = (DirectoryNode)dPath.getCurrentNode(); AVMNode srcNode = sPath.getCurrentNode(); AVMNode dstNode = null; - // We do different things depending on what kind of thing we're + // We do different things depending on what kind of thing we're // branching from. I'd be considerably happier if we disallowed // certain scenarios, but Jon won't let me :P (bhp). if (srcNode.getType() == AVMNodeType.PLAIN_DIRECTORY) @@ -490,8 +490,8 @@ public class AVMRepository } else if (srcNode.getType() == AVMNodeType.LAYERED_DIRECTORY) { - dstNode = - new LayeredDirectoryNodeImpl((LayeredDirectoryNode)srcNode, dstRepo); + dstNode = + new LayeredDirectoryNodeImpl((LayeredDirectoryNode)srcNode, dstRepo, sPath, false); ((LayeredDirectoryNode)dstNode).setLayerID(issueLayerID()); } else if (srcNode.getType() == AVMNodeType.LAYERED_FILE) @@ -526,9 +526,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Get an output stream to a file. * @param path The full path to the file. @@ -552,9 +552,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Get a content reader from a file node. * @param version The version of the file. @@ -576,10 +576,10 @@ public class AVMRepository } finally { - fLookupCount.set(null); + fLookupCount.set(null); } } - + /** * Get a ContentWriter to a file node. * @param path The path to the file. @@ -605,7 +605,7 @@ public class AVMRepository fLookupCount.set(null); } } - + /** * Rename a node. * @param srcPath Source containing directory. @@ -616,7 +616,7 @@ public class AVMRepository public void rename(String srcPath, String srcName, String dstPath, String dstName) { - // This is about as ugly as it gets. + // This is about as ugly as it gets. if ((dstPath + "/").indexOf(srcPath + srcName + "/") == 0) { throw new AVMCycleException("Cyclic rename."); @@ -651,7 +651,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } fLookupCount.set(1); try { @@ -680,7 +680,7 @@ public class AVMRepository // If the source is layered then the renamed thing needs to be layered also. if (sPath.isLayered()) { - // If this is a rename happening in the same layer we make a new + // If this is a rename happening in the same layer we make a new // OverlayedDirectoryNode that is not a primary indirection layer. // Otherwise we do make the new OverlayedDirectoryNode a primary // Indirection layer. This complexity begs the question of whether @@ -688,7 +688,7 @@ 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, false); + dstNode = new LayeredDirectoryNodeImpl((PlainDirectoryNode)srcNode, dstRepo, sPath, true); ((LayeredDirectoryNode)dstNode).setLayerID(sPath.getTopLayer().getLayerID()); } else @@ -708,9 +708,10 @@ public class AVMRepository 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); + new LayeredDirectoryNodeImpl((LayeredDirectoryNode)srcNode, dstRepo, srcLookup, true); ((LayeredDirectoryNode)dstNode).setLayerID(((LayeredDirectoryNode)srcNode).getLayerID()); } else @@ -720,8 +721,9 @@ public class AVMRepository // indirection is calculated from it's source context. if (((LayeredDirectoryNode)srcNode).getPrimaryIndirection()) { + Lookup srcLookup = lookup(-1, srcPath + "/" + srcName, true); dstNode = - new LayeredDirectoryNodeImpl((LayeredDirectoryNode)srcNode, dstRepo); + new LayeredDirectoryNodeImpl((LayeredDirectoryNode)srcNode, dstRepo, srcLookup, true); } else { @@ -729,7 +731,7 @@ public class AVMRepository new LayeredDirectoryNodeImpl((DirectoryNode)srcNode, dstRepo, sPath, srcName); } // 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 + // rename is to a layered context. If so then it should get the layer id // of its destination parent. Otherwise it should get a new layer // id. if (dPath.isLayered()) @@ -768,7 +770,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } /** @@ -793,7 +795,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } /** @@ -842,7 +844,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } /** @@ -880,7 +882,7 @@ public class AVMRepository fAVMStoreDAO.invalidateCache(); fPurgeStoreTxnListener.storePurged(name); } - + /** * Remove all content specific to a AVMRepository and version. * @param name The name of the AVMStore. @@ -921,7 +923,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } public InputStream getInputStream(AVMNodeDescriptor desc) @@ -940,7 +942,7 @@ public class AVMRepository ContentReader reader = fContentStore.getReader(data.getContentUrl()); return reader.getContentInputStream(); } - + /** * Get a listing of a directory. * @param version The version to look under. @@ -965,7 +967,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } /** @@ -991,16 +993,16 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * 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 + public SortedMap getListingDirect(AVMNodeDescriptor dir, boolean includeDeleted) { AVMNode node = fAVMNodeDAO.getByID(dir.getId()); @@ -1019,7 +1021,7 @@ public class AVMRepository LayeredDirectoryNode dirNode = (LayeredDirectoryNode)node; return dirNode.getListingDirect(dir, includeDeleted); } - + /** * Get a directory listing from a directory node descriptor. * @param dir The directory node descriptor. @@ -1046,9 +1048,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Get the names of deleted nodes in a directory. * @param version The version to look under. @@ -1071,9 +1073,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Get descriptors of all AVMStores. * @return A list of all descriptors. @@ -1104,7 +1106,7 @@ public class AVMRepository } return store.getDescriptor(); } - + /** * Get all version for a given AVMStore. * @param name The name of the AVMStore. @@ -1121,7 +1123,7 @@ public class AVMRepository } /** - * Get the set of versions between (inclusive) of the given dates. + * 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 The earliest date. @@ -1137,7 +1139,7 @@ public class AVMRepository } return store.getVersions(from, to); } - + /** * Issue a node id. * @return The new id. @@ -1155,7 +1157,7 @@ public class AVMRepository { return fLayerIssuer.issue(); } - + /** * Get the indirection path for a layered node. * @param version The version to look under. @@ -1178,7 +1180,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } /** @@ -1195,7 +1197,7 @@ public class AVMRepository } return store.getNextVersionID(); } - + /** * Get the latest extant snapshotted version id. * @param name The store name. @@ -1209,7 +1211,7 @@ public class AVMRepository } return store.getLastVersionID(); } - + /** * Get an AVMStore by name. * @param name The name of the AVMStore. @@ -1236,7 +1238,7 @@ public class AVMRepository } return store.getRoot(version); } - + // TODO Fix this awful mess regarding cycle detection. /** * Lookup a node. @@ -1278,7 +1280,7 @@ public class AVMRepository } } } - + /** * Lookup a descriptor from a directory descriptor. * @param dir The directory descriptor. @@ -1306,9 +1308,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Get all the paths to a particular node. * @param desc The node descriptor. @@ -1326,7 +1328,7 @@ public class AVMRepository recursiveGetPaths(node, components, paths); return paths; } - + /** * Get a single valid path for a node. * @param desc The node descriptor. @@ -1342,7 +1344,7 @@ public class AVMRepository List components = new ArrayList(); return recursiveGetAPath(node, components); } - + /** * Get all paths for a node reachable by HEAD. * @param desc The node descriptor. @@ -1369,7 +1371,7 @@ public class AVMRepository */ public List getVersionPaths(VersionRoot version, AVMNode node) { - List paths = new ArrayList(); + List paths = new ArrayList(); List components = new ArrayList(); recursiveGetVersionPaths(node, components, paths, version.getRoot(), version.getAvmStore().getName()); return paths; @@ -1382,7 +1384,7 @@ public class AVMRepository * @param paths The list to contain found paths. * @param root The root node of the version. * @param storeName The name of the store. - */ + */ private void recursiveGetVersionPaths(AVMNode node, List components, List paths, DirectoryNode root, String storeName) { if (node.equals(root)) @@ -1425,14 +1427,14 @@ public class AVMRepository recursiveGetPathsInStoreHead(node, components, paths, st.getRoot(), store); return paths; } - + /** * Do the actual work. * @param node The current node. * @param components The currently accumulated path components. * @param paths The list to put full paths in. */ - private void recursiveGetPaths(AVMNode node, List components, + private void recursiveGetPaths(AVMNode node, List components, List> paths) { if (node.getIsRoot()) @@ -1496,14 +1498,14 @@ public class AVMRepository } return null; } - + /** * Do the actual work. * @param node The current node. * @param components The currently accumulated path components. * @param paths The list to put full paths in. */ - private void recursiveGetHeadPaths(AVMNode node, List components, + private void recursiveGetHeadPaths(AVMNode node, List components, List> paths) { if (node.getIsRoot()) @@ -1533,7 +1535,7 @@ public class AVMRepository * @param components The currently accumulated path components. * @param paths The list to put full paths in. */ - private void recursiveGetPathsInStoreHead(AVMNode node, List components, + private void recursiveGetPathsInStoreHead(AVMNode node, List components, List> paths, DirectoryNode root, String storeName) { @@ -1557,15 +1559,15 @@ public class AVMRepository * Add a path to the list. * @param components The path name components. * @param version The version id. - * @param storeName The name of the + * @param storeName The name of the * @param paths The List to add to. */ - private void addPath(List components, int version, String storeName, + private void addPath(List components, int version, String storeName, List> paths) { paths.add(new Pair(version, makePath(components, storeName))); } - + /** * Alternate version. * @param components @@ -1577,7 +1579,7 @@ public class AVMRepository { paths.add(makePath(components, storeName)); } - + /** * Helper for generating paths. * @param components The path components. @@ -1601,7 +1603,7 @@ public class AVMRepository } return pathBuilder.toString(); } - + /** * Get information about layering of a path. * @param version The version to look under. @@ -1631,9 +1633,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Lookup a directory specifically. * @param version The version to look under. @@ -1707,7 +1709,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } /** @@ -1732,9 +1734,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Get the history chain for a node. * @param desc The node to get history of. @@ -1764,7 +1766,7 @@ public class AVMRepository } return history; } - + /** * Set the opacity of a layered directory. An opaque directory hides * the things it points to via indirection. @@ -1788,9 +1790,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Set a property on a node. * @param path The path to the node. @@ -1814,9 +1816,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Set a collection of properties at once. * @param path The path to the node. @@ -1839,9 +1841,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Get a property by name for a node. * @param version The version to look under. @@ -1865,9 +1867,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Get a Map of all the properties of a node. * @param version The version to look under. @@ -1890,9 +1892,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Delete a single property from a node. * @param path The path to the node. @@ -1915,7 +1917,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } /** @@ -1939,9 +1941,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Set a property on a store. Overwrites if property exists. * @param store The AVMStore. @@ -1957,7 +1959,7 @@ public class AVMRepository } st.setProperty(name, value); } - + /** * Set a group of properties on a store. Overwrites any properties that exist. * @param store The AVMStore. @@ -1972,7 +1974,7 @@ public class AVMRepository } st.setProperties(props); } - + /** * Get a property from a store. * @param store The name of the store. @@ -1992,9 +1994,9 @@ public class AVMRepository } return st.getProperty(name); } - + /** - * Queries a given store for properties with keys that match a given pattern. + * Queries a given store for properties with keys that match a given pattern. * @param store The name of the store. * @param keyPattern The sql 'like' pattern, inserted into a QName. * @return A Map of the matching key value pairs. @@ -2018,22 +2020,22 @@ public class AVMRepository } /** - * Queries all AVM stores for properties with keys that matcha given pattern. + * Queries all AVM stores for properties with keys that matcha 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) { - List matches = + List matches = fAVMStorePropertyDAO.queryByKeyPattern(keyPattern); - Map> results = + Map> results = new HashMap>(); for (AVMStoreProperty prop : matches) { String storeName = prop.getStore().getName(); Map pairs = null; - if ((pairs = results.get(storeName)) == null) + if ((pairs = results.get(storeName)) == null) { pairs = new HashMap(); results.put(storeName, pairs); @@ -2042,7 +2044,7 @@ public class AVMRepository } return results; } - + /** * Get all the properties for a store. * @param store The name of the Store. @@ -2061,7 +2063,7 @@ public class AVMRepository } return st.getProperties(); } - + /** * Delete a property from a store. * @param store The name of the store. @@ -2076,7 +2078,7 @@ public class AVMRepository } st.deleteProperty(name); } - + /** * Get the common ancestor of two nodes if one exists. Unfortunately * this is a quadratic problem, taking time proportional to the product @@ -2162,7 +2164,7 @@ public class AVMRepository fLookupCount.set(null); } } - + /** * Get the ContentData for a file for writing. * @param path The path to the file. @@ -2186,7 +2188,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } /** @@ -2211,9 +2213,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Get the single instance of AVMRepository. * @return The single instance. @@ -2222,7 +2224,7 @@ public class AVMRepository { return fgInstance; } - + public void setMetaDataFrom(String path, AVMNodeDescriptor from) { fLookupCount.set(1); @@ -2245,9 +2247,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Add an aspect to an AVM Node. * @param path The path to the node. @@ -2270,9 +2272,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Get all the aspects on an AVM node. * @param version The version to look under. @@ -2295,9 +2297,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Remove an aspect and all associated properties from a node. * @param path The path to the node. @@ -2320,9 +2322,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Does a node have a particular aspect. * @param version The version to look under. @@ -2346,9 +2348,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Set the ACL on a node. * @param path The path to the node. @@ -2371,9 +2373,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Get the ACL on a node. * @param version The version to look under. @@ -2396,9 +2398,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Link a node into a directory, directly. * @param parentPath The path to the parent. @@ -2422,9 +2424,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * This is the danger version of link. It must be called on * a copied and unsnapshotted directory. It blithely inserts @@ -2447,9 +2449,9 @@ public class AVMRepository } dir.link(name, child); } - + /** - * Remove name without leaving behind a deleted node. Dangerous + * Remove name without leaving behind a deleted node. Dangerous * if used unwisely. * @param path The path to the layered directory. * @param name The name of the child. @@ -2483,9 +2485,9 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } - + /** * Force a copy on write. * @param path The path to force. @@ -2514,7 +2516,7 @@ public class AVMRepository finally { fLookupCount.set(null); - } + } } /** @@ -2548,7 +2550,7 @@ public class AVMRepository fPurgeStoreTxnListener.storePurged(sourceName); fCreateStoreTxnListener.storeCreated(destName); } - + /** * 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. @@ -2576,7 +2578,7 @@ public class AVMRepository fLookupCount.set(null); } } - + /** * Set the GUID on a node. * @param path @@ -2601,7 +2603,7 @@ public class AVMRepository fLookupCount.set(null); } } - + /** * Set the encoding on a node. * @param path @@ -2664,14 +2666,14 @@ public class AVMRepository recursiveGetStoreVersionPaths(store, node, version, components, paths); return paths; } - + /** * Do the actual work. * @param node The current node. * @param components The currently accumulated path components. * @param paths The list to put full paths in. */ - private void recursiveGetStoreVersionPaths(String storeName, AVMNode node, int version, List components, + private void recursiveGetStoreVersionPaths(String storeName, AVMNode node, int version, List components, List paths) { if (node.getIsRoot()) diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java index 4f0fdec11b..6db10b92be 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java @@ -96,11 +96,47 @@ import org.alfresco.util.Pair; /** * Big test of AVM behavior. - * + * * @author britt */ public class AVMServiceTest extends AVMServiceTestBase { + public void testRename6() + { + try + { + setupBasicTree(); + fService.createStore("layer"); + fService.createLayeredDirectory("main:/a", "layer:/", "a"); + fService.rename("layer:/a/b", "c", "layer:/a/b", "z"); + System.out.println(recursiveContents("layer:/", -1, true)); + List diffs = fSyncService.compare(-1, "layer:/a", -1, "main:/a", null); + System.out.println(diffs); + fSyncService.update(diffs, null, false, false, false, false, null, null); + System.out.println(recursiveContents("layer:/", -1, true)); + System.out.println(recursiveContents("main:/", -1, true)); + fSyncService.flatten("layer:/a", "main:/a"); + System.out.println(recursiveContents("layer:/", -1, true)); + System.out.println(recursiveContents("main:/", -1, true)); + fService.createFile("layer:/a/b/z", "fudge").close(); + fService.rename("layer:/a/b", "z", "layer:/a/b", "y"); + System.out.println(recursiveContents("layer:/", -1, true)); + diffs = fSyncService.compare(-1, "layer:/a", -1, "main:/a", null); + System.out.println(diffs); + fSyncService.update(diffs, null, false, false, false, false, null, null); + System.out.println(recursiveContents("layer:/", -1, true)); + System.out.println(recursiveContents("main:/", -1, true)); + fSyncService.flatten("layer:/a", "main:/a"); + System.out.println(recursiveContents("layer:/", -1, true)); + System.out.println(recursiveContents("main:/", -1, true)); + } + catch (Exception e) + { + e.printStackTrace(); + fail(); + } + } + public void testSpacesInStoreNames() { try @@ -115,7 +151,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + public void testHeadPathsInLayers() { try @@ -143,7 +179,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Minimal testing of Locking Aware service. */ @@ -154,17 +190,17 @@ public class AVMServiceTest extends AVMServiceTestBase AuthenticationService authService = (AuthenticationService)fContext.getBean("AuthenticationService"); try { - fService.setStoreProperty("main", QName.createQName(null, ".dns.main"), + fService.setStoreProperty("main", QName.createQName(null, ".dns.main"), new PropertyValue(DataTypeDefinition.TEXT, "Nothing.")); fService.createStore("test"); - fService.setStoreProperty("test", QName.createQName(null, ".dns.test.main"), + fService.setStoreProperty("test", QName.createQName(null, ".dns.test.main"), new PropertyValue(DataTypeDefinition.TEXT, "Nothing.")); setupBasicTree0(); authService.authenticateAsGuest(); // assertEquals(0, fLockingService.getUsersLocks("admin").size()); List diffs = fSyncService.compare(-1, "main:/", -1, "test:/", null); fSyncService.update(diffs, null, false, false, false, false, null, null); - RetryingTransactionHelper.RetryingTransactionCallback cb = + RetryingTransactionHelper.RetryingTransactionCallback cb = new RetryingTransactionHelper.RetryingTransactionCallback() { public Object execute() @@ -172,7 +208,7 @@ public class AVMServiceTest extends AVMServiceTestBase { BulkLoader loader = new BulkLoader(); loader.setAvmService(fService); - loader.recursiveLoad("source/java/org/alfresco/repo/avm", "main:/"); + loader.recursiveLoad("source/java/org/alfresco/repo/avm", "main:/"); return null; } }; @@ -232,13 +268,13 @@ public class AVMServiceTest extends AVMServiceTestBase try { setupBasicTree(); - + StoreRef storeRef = AVMNodeConverter.ToStoreRef("main"); SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); ResultSet results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}SillyProperty")+":\"Silly\""); assertEquals(0, results.length()); results.close(); - + QName name = QName.createQName("silly.uri", "SillyProperty"); PropertyValue value = new PropertyValue(DataTypeDefinition.TEXT, "Silly Property Value"); fService.setNodeProperty("main:/a/b/c/foo", name, value); @@ -251,8 +287,8 @@ public class AVMServiceTest extends AVMServiceTestBase Map props = fService.getNodeProperties(-1, "main:/a/b/c/foo"); assertEquals(1, props.size()); assertEquals(value.toString(), props.get(name).toString()); - - + + props = new HashMap(); QName n1 = QName.createQName("silly.uri", "Prop1"); PropertyValue p1 = new PropertyValue(DataTypeDefinition.DATETIME, new Date(System.currentTimeMillis())); @@ -270,38 +306,38 @@ public class AVMServiceTest extends AVMServiceTestBase assertEquals(p1.toString(), props.get(n1).toString()); assertEquals(p2.toString(), props.get(n2).toString()); assertEquals(p3.toString(), props.get(n3).toString()); - + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop1")+":\"" + props.get(n1).getStringValue() +"\""); assertEquals(1, results.length()); results.close(); results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop2")+":\"" + props.get(n2).getStringValue() +"\""); assertEquals(1, results.length()); results.close(); - + fService.deleteNodeProperty("main:/a/b/c/bar", n1); fService.createSnapshot("main", null, null); - + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop1")+":\"" + props.get(n1).getStringValue() +"\""); assertEquals(0, results.length()); results.close(); results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop2")+":\"" + props.get(n2).getStringValue() +"\""); assertEquals(1, results.length()); results.close(); - + props = fService.getNodeProperties(-1, "main:/a/b/c/bar"); assertEquals(2, props.size()); assertEquals(p2.toString(), props.get(n2).toString()); assertEquals(p3.toString(), props.get(n3).toString()); fService.deleteNodeProperties("main:/a/b/c/bar"); fService.createSnapshot("main", null, null); - + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop1")+":\"" + p1.getStringValue() +"\""); assertEquals(0, results.length()); results.close(); results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop2")+":\"" + props.get(n2).getStringValue() +"\""); assertEquals(0, results.length()); results.close(); - + props = fService.getNodeProperties(-1, "main:/a/b/c/bar"); assertEquals(0, props.size()); fService.removeNode("main:/a/b/c/foo"); @@ -361,9 +397,9 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - - - + + + public void testForceCopyDeleted() { try @@ -1075,7 +1111,7 @@ public class AVMServiceTest extends AVMServiceTestBase }; TransactionService transactionService = (TransactionService) fContext.getBean("transactionService"); transactionService.getRetryingTransactionHelper().doInTransaction(new TxnWork()); - + results = searchService.query(storeRef, "lucene", "TEXT:\"HEAD\""); assertEquals(0, results.length()); results.close(); @@ -1769,7 +1805,7 @@ public class AVMServiceTest extends AVMServiceTestBase }; TransactionService transactionService = (TransactionService) fContext.getBean("transactionService"); transactionService.getRetryingTransactionHelper().doInTransaction(new TxnWork()); - + diffs = fSyncService.compare(-1, "area:/a", -1, "main:/a", null); assertEquals(0, diffs.size()); System.out.println(recursiveList("area", -1, true)); @@ -1814,7 +1850,7 @@ public class AVMServiceTest extends AVMServiceTestBase }; TransactionService transactionService = (TransactionService) fContext.getBean("transactionService"); transactionService.getRetryingTransactionHelper().doInTransaction(new TxnWork()); - + diffs = fSyncService.compare(-1, "area:/a", -1, "main:/a", null); assertEquals(0, diffs.size()); System.out.println(recursiveList("area", -1, true)); @@ -2877,9 +2913,11 @@ public class AVMServiceTest extends AVMServiceTestBase assertEquals("baz", list.get(0)); assertEquals("figs", list.get(1)); // Rename /layer/d to /layer/e and uncover /layer/d + System.out.println(recursiveContents("main:/", -1, true)); fService.rename("main:/layer", "d", "main:/layer", "e"); fService.uncover("main:/layer", "d"); fService.createSnapshot("main", null, null); + System.out.println(recursiveContents("main:/", -1, true)); // History unchanged. checkHistory(history, "main"); // /layer/d contains figs. @@ -2887,11 +2925,12 @@ public class AVMServiceTest extends AVMServiceTestBase assertEquals(1, listing.size()); list = new ArrayList(listing.keySet()); assertEquals("figs", list.get(0)); - // /layer/e contains baz. + // /layer/e contains baz and figs. listing = fService.getDirectoryListing(-1, "main:/layer/e"); - assertEquals(1, listing.size()); + assertEquals(2, listing.size()); list = new ArrayList(listing.keySet()); assertEquals("baz", list.get(0)); + assertEquals("figs", list.get(1)); for (String val : history.values()) { System.out.println(val); @@ -3592,8 +3631,8 @@ public class AVMServiceTest extends AVMServiceTestBase results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); assertEquals(0, results.length()); results.close(); - - + + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); assertEquals(1, results.length()); results.close(); @@ -3605,7 +3644,7 @@ public class AVMServiceTest extends AVMServiceTestBase results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/brenamed\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/brenamed/c\""); assertEquals(1, results.length()); results.close(); @@ -3618,7 +3657,7 @@ public class AVMServiceTest extends AVMServiceTestBase assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); assertEquals(1, results.length()); results.close(); @@ -3666,7 +3705,7 @@ public class AVMServiceTest extends AVMServiceTestBase results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); assertEquals(2, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*/*\""); assertEquals(0, results.length()); results.close(); @@ -3702,7 +3741,7 @@ public class AVMServiceTest extends AVMServiceTestBase System.out.println(history.get(2)); l = fService.getDirectoryListing(-1, "main:/d"); assertEquals(0, l.size()); - + // Text index StoreRef storeRef = AVMNodeConverter.ToStoreRef("main"); SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); @@ -3841,7 +3880,7 @@ public class AVMServiceTest extends AVMServiceTestBase results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); assertEquals(0, results.length()); results.close(); - + } catch (Exception e) { @@ -4704,224 +4743,224 @@ public class AVMServiceTest extends AVMServiceTestBase } } - + protected void runQueriesForInitialRenameStructure(String store) { StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); - - + + SearchService searchService = fIndexerAndSearcher.getSearcher(AVMNodeConverter.ToStoreRef(store), true); - + // Note "a" is a stop word and therefore not findable ... - + ResultSet results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_CREATOR)+":admin"); assertEquals(7, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_MODIFIER)+":admin"); assertEquals(7, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_OWNER)+":admin"); assertEquals(7, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_NODE_UUID)+":unknown"); assertEquals(7, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_STORE_PROTOCOL)+":avm"); assertEquals(7, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_STORE_IDENTIFIER)+":"+store); assertEquals(7, results.length()); results.close(); - + // Basic paths - + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); assertEquals(7, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); assertEquals(6, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); assertEquals(3, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); assertEquals(2, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); assertEquals(0, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); assertEquals(2, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); assertEquals(2, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); assertEquals(2, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); assertEquals(0, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); assertEquals(0, results.length()); results.close(); } - - + + protected void runQueriesForInitialRenameStructureAndInitialLayers(String store) { StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); - - + + SearchService searchService = fIndexerAndSearcher.getSearcher(AVMNodeConverter.ToStoreRef(store), true); - + // Note "a" is a stop word and therefore not findable ... - + ResultSet results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_CREATOR)+":admin"); assertEquals(9, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_MODIFIER)+":admin"); assertEquals(7, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_OWNER)+":admin"); assertEquals(7, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_NODE_UUID)+":unknown"); assertEquals(7, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_STORE_PROTOCOL)+":avm"); assertEquals(7, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_STORE_IDENTIFIER)+":"+store); assertEquals(7, results.length()); results.close(); - + // Basic paths - + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); assertEquals(7, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); assertEquals(6, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); assertEquals(3, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); assertEquals(2, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); assertEquals(1, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); assertEquals(0, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); assertEquals(2, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); assertEquals(2, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); assertEquals(2, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); assertEquals(0, results.length()); results.close(); - + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); assertEquals(0, results.length()); results.close(); } - + /** * Test rename behavior of an overlayed file withing a layer. */ @@ -5178,7 +5217,7 @@ public class AVMServiceTest extends AVMServiceTestBase try { setupBasicTree(); - + StoreRef storeRef = AVMNodeConverter.ToStoreRef("main"); SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); ResultSet results = searchService.query(storeRef, "lucene", "ASPECT:\"" + ContentModel.ASPECT_TITLED.toString() +"\""); @@ -5187,7 +5226,7 @@ public class AVMServiceTest extends AVMServiceTestBase results = searchService.query(storeRef, "lucene", "ASPECT:\"" + ContentModel.ASPECT_AUDITABLE.toString() +"\""); assertEquals(0, results.length()); results.close(); - + fService.addAspect("main:/a/b/c/foo", ContentModel.ASPECT_TITLED); fService.addAspect("main:/a/b/c/foo", ContentModel.ASPECT_AUDITABLE); Map properties = new HashMap(); @@ -5198,14 +5237,14 @@ public class AVMServiceTest extends AVMServiceTestBase properties.put(ContentModel.PROP_MODIFIER, new PropertyValue(DataTypeDefinition.TEXT, "Quentin")); fService.setNodeProperties("main:/a/b/c/foo", properties); fService.createSnapshot("main", null, null); - + results = searchService.query(storeRef, "lucene", "ASPECT:\"" + ContentModel.ASPECT_TITLED.toString() +"\""); assertEquals(1, results.length()); results.close(); results = searchService.query(storeRef, "lucene", "ASPECT:\"" + ContentModel.ASPECT_AUDITABLE.toString() +"\""); assertEquals(1, results.length()); results.close(); - + fService.removeNode("main:/a/b/c/bar"); fService.addAspect("main:/a/b/c/bar", ContentModel.ASPECT_TITLED); Set names = fService.getAspects(-1, "main:/a/b/c/foo"); @@ -5215,15 +5254,15 @@ public class AVMServiceTest extends AVMServiceTestBase assertTrue(fService.hasAspect(-1, "main:/a/b/c/foo", ContentModel.ASPECT_TITLED)); fService.removeAspect("main:/a/b/c/foo", ContentModel.ASPECT_TITLED); fService.createSnapshot("main", null, null); - + results = searchService.query(storeRef, "lucene", "ASPECT:\"" + ContentModel.ASPECT_TITLED.toString() +"\""); assertEquals(0, results.length()); results.close(); results = searchService.query(storeRef, "lucene", "ASPECT:\"" + ContentModel.ASPECT_AUDITABLE.toString() +"\""); assertEquals(1, results.length()); results.close(); - - + + fService.getFileOutputStream("main:/a/b/c/foo").close(); assertFalse(fService.hasAspect(-1, "main:/a/b/c/foo", ContentModel.ASPECT_TITLED)); assertTrue(fService.hasAspect(-1, "main:/a/b/c/foo", ContentModel.ASPECT_AUDITABLE)); @@ -5567,52 +5606,52 @@ public class AVMServiceTest extends AVMServiceTestBase 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")); @@ -5624,31 +5663,31 @@ public class AVMServiceTest extends AVMServiceTestBase 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"); @@ -5662,9 +5701,9 @@ public class AVMServiceTest extends AVMServiceTestBase 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(); diff --git a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java index 4fdc7cc258..01a9bb4d37 100644 --- a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java @@ -53,34 +53,34 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec * The layer id. */ private long fLayerID; - + /** * The pointer to the underlying directory. */ private String fIndirection; - + /** * Whether this is a primary indirection node. */ private boolean fPrimaryIndirection; - + /** * Whether this is opaque. */ private boolean fOpacity; - + /** * The indirection version. */ private int fIndirectionVersion; - + /** * Default constructor. Called by Hibernate. */ protected LayeredDirectoryNodeImpl() { } - + /** * Make a new one from a specified indirection path. * @param indirection The indirection path to set. @@ -111,7 +111,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec copyAspects(toCopy); } } - + /** * Kind of copy constructor, sort of. * @param other The LayeredDirectoryNode we are copied from. @@ -119,7 +119,8 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec */ @SuppressWarnings("unchecked") public LayeredDirectoryNodeImpl(LayeredDirectoryNode other, - AVMStore repos) + AVMStore repos, + Lookup lookup, boolean copyAll) { super(repos.getAVMRepository().issueID(), repos); fIndirection = other.getIndirection(); @@ -128,12 +129,20 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec fLayerID = -1; fOpacity = false; AVMDAOs.Instance().fAVMNodeDAO.save(this); - for (ChildEntry child : AVMDAOs.Instance().fChildEntryDAO.getByParent(other)) + Map children = null; + if (copyAll) { - ChildKey key = new ChildKey(this, child.getKey().getName()); - ChildEntryImpl newChild = new ChildEntryImpl(key, - child.getChild()); - AVMDAOs.Instance().fChildEntryDAO.save(newChild); + children = other.getListing(lookup, true); + } + else + { + children = other.getListingDirect(lookup, true); + } + for (Map.Entry child : children.entrySet()) + { + ChildKey key = new ChildKey(this, child.getKey()); + ChildEntry entry = new ChildEntryImpl(key, child.getValue()); + AVMDAOs.Instance().fChildEntryDAO.save(entry); } setVersionID(other.getVersionID() + 1); AVMDAOs.Instance().fAVMNodeDAO.flush(); @@ -141,7 +150,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec copyAspects(other); copyACLs(other); } - + /** * Construct one from a PlainDirectoryNode. Called when a COW is performed in a layered * context. @@ -200,12 +209,19 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec fOpacity = false; setVersionID(dir.getVersionID() + 1); AVMDAOs.Instance().fAVMNodeDAO.save(this); + Map children = dir.getListing(srcLookup, true); + for (Map.Entry child : children.entrySet()) + { + ChildKey key = new ChildKey(this, child.getKey()); + ChildEntry entry = new ChildEntryImpl(key, child.getValue()); + AVMDAOs.Instance().fChildEntryDAO.save(entry); + } AVMDAOs.Instance().fAVMNodeDAO.flush(); copyProperties(dir); copyAspects(dir); copyACLs(dir); - } - + } + /** * Is this a primary indirection node. * @return Whether this is a primary indirection. @@ -214,7 +230,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec { return fPrimaryIndirection; } - + /** * Set the primary indirection state of this. * @param has Whether this is a primary indirection node. @@ -223,7 +239,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec { fPrimaryIndirection = has; } - + /** * Get the indirection path. * @return The indirection path. @@ -232,7 +248,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec { return fIndirection; } - + /** * Get the underlying path in the Lookup's context. * @param lPath The Lookup. @@ -264,7 +280,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec } return lPath.getCurrentIndirectionVersion(); } - + /** * Get the layer id. * @return The layer id. @@ -273,7 +289,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec { return fLayerID; } - + /** * Set the layer id. * @param id The id to set. @@ -282,7 +298,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec { fLayerID = id; } - + /** * Copy on write logic. * @param lPath @@ -298,7 +314,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec // This means that this is being seen indirectly through the topmost // layer. The following creates a node that will inherit its // indirection from its parent. - newMe = new LayeredDirectoryNodeImpl((String)null, + newMe = new LayeredDirectoryNodeImpl((String)null, store, this); newMe.setPrimaryIndirection(false); newMe.setLayerID(lPath.getTopLayer().getLayerID()); @@ -307,7 +323,9 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec { // A simple copy is made. newMe = new LayeredDirectoryNodeImpl(this, - store); + store, + lPath, + false); newMe.setLayerID(getLayerID()); } newMe.setAncestor(this); @@ -412,7 +430,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec * @param includeDeleted Whether to inlude deleted nodes. * @return A Map of Strings to descriptors. */ - public SortedMap getListingDirect(AVMNodeDescriptor dir, + public SortedMap getListingDirect(AVMNodeDescriptor dir, boolean includeDeleted) { List children = AVMDAOs.Instance().fChildEntryDAO.getByParent(this); @@ -430,14 +448,14 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec } return listing; } - + /** * Get a listing from a directory node descriptor. * @param dir The directory node descriptor. * @param includeDeleted Should DeletedNodes be shown. * @return A Map of names to node descriptors. */ - public SortedMap getListing(AVMNodeDescriptor dir, + public SortedMap getListing(AVMNodeDescriptor dir, boolean includeDeleted) { if (dir.getPath() == null || dir.getIndirection() == null) @@ -500,7 +518,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec } /** - * Lookup a child by name. + * Lookup a child by name. * @param lPath The Lookup. * @param name The name we are looking. * @param version The version in which we are looking. @@ -556,7 +574,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec { throw new AVMBadArgumentException("Illegal null argument."); } - ChildKey key = new ChildKey(this, name); + ChildKey key = new ChildKey(this, name); ChildEntry entry = AVMDAOs.Instance().fChildEntryDAO.get(key); if (entry != null) { @@ -627,7 +645,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec { child = temp.getFirst(); } - indirect = true; + indirect = true; } if (child != null && (indirect || child.getStoreNew() == null || child.getAncestor() != null)) { @@ -644,7 +662,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec AVMDAOs.Instance().fAVMNodeDAO.flush(); } } - + /** * Get the type of this node. * @return The type of this node. @@ -663,7 +681,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec { return "[LD:" + getId() + ":" + getUnderlying(lPath) + "]"; } - + /** * Set the primary indirection. No COW. * @param path The indirection path. @@ -677,7 +695,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec fIndirection = path; fPrimaryIndirection = true; } - + /** * Make this node become a primary indirection. COW. * @param lPath The Lookup. @@ -704,7 +722,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec } rawSetPrimary(target); } - + /** * Let anything behind name in this become visible. * @param lPath The Lookup. @@ -727,7 +745,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec AVMDAOs.Instance().fChildEntryDAO.delete(entry); } } - + /** * Get the descriptor for this node. * @param lPath The Lookup. @@ -798,7 +816,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec fPrimaryIndirection, fLayerID, fOpacity, - -1, + -1, -1); } @@ -822,7 +840,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec } else { - indirection = parentIndirection.endsWith("/") ? parentIndirection + name : + indirection = parentIndirection.endsWith("/") ? parentIndirection + name : parentIndirection + "/" + name; indirectionVersion = parentIndirectionVersion; } @@ -929,7 +947,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec ChildEntry newChild = new ChildEntryImpl(key, node); AVMDAOs.Instance().fChildEntryDAO.save(newChild); } - + /** * Remove name without leaving behind a deleted node. * @param name The name of the child to flatten. @@ -962,7 +980,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec fIndirectionVersion = version; } } - + /** * Get the indirection version. * @return The indirection version.