diff --git a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/avm-common-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/avm-common-SqlMap.xml
index 8c3406ef9b..d6ef9380b9 100644
--- a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/avm-common-SqlMap.xml
+++ b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/avm-common-SqlMap.xml
@@ -838,6 +838,17 @@
child_id = #childNodeId#
+
+
+
+
+
+
+
+
+ delete
+ from
+ avm_child_entries
+ where
+ parent_id = #parentNodeId# and
+ lower(name) = lower(#name#) and
+ child_id = #childNodeId#
+
+ -->
+
+
+
+ update
+ avm_child_entries
+ set
+ name = #name#
+ where
+ parent_id = #parentNodeId# and
+ child_id = #childNodeId#
+
+
+
delete
from
@@ -912,7 +966,16 @@
name = #name#
-
+
+ delete
+ from
+ avm_child_entries
+ where
+ parent_id = #parentNodeId# and
+ lower(name) = lower(#name#)
+
+
+
delete
from
diff --git a/source/java/org/alfresco/repo/avm/AVMRepository.java b/source/java/org/alfresco/repo/avm/AVMRepository.java
index 2ba414f7b0..790d94375d 100644
--- a/source/java/org/alfresco/repo/avm/AVMRepository.java
+++ b/source/java/org/alfresco/repo/avm/AVMRepository.java
@@ -721,7 +721,7 @@ public class AVMRepository
throw new AVMNotFoundException("Path not found.");
}
srcDir = (DirectoryNode) sPath.getCurrentNode();
-
+
Pair temp = srcDir.lookupChild(sPath, srcName, false);
srcNode = (temp == null) ? null : temp.getFirst();
if (srcNode == null)
@@ -760,108 +760,147 @@ public class AVMRepository
}
Pair temp = dstDir.lookupChild(dPath, dstName, true);
AVMNode child = (temp == null) ? null : temp.getFirst();
+
+ boolean renameCase = false;
if (child != null && child.getType() != AVMNodeType.DELETED_NODE)
{
- throw new AVMExistsException("Node exists: " + dstName);
- }
-
- Long parentAcl = dstDir.getAcl() == null ? null : dstDir.getAcl().getId();
-
- AVMNode dstNode = null;
- // We've passed the check, so we can go ahead and do the rename.
- if (srcNode.getType() == AVMNodeType.PLAIN_DIRECTORY)
- {
- // If the source is layered then the renamed thing needs to be layered also.
- if (sPath.isLayered())
+ String avmSrcPath = AVMUtil.extendAVMPath(srcPath, srcName);
+ String avmDstPath = AVMUtil.extendAVMPath(dstPath, dstName);
+
+ if ((avmSrcPath.equalsIgnoreCase(avmDstPath)) && (! srcName.equals(dstName)))
{
- // 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
- // we should allow renames from within one layer to within another
- // layer. Allowing it makes the logic absurdly complex.
- if (dPath.isLayered() && dPath.getTopLayer().equals(sPath.getTopLayer()))
+ // specific rename 'case' only (within a store)
+ if (fgLogger.isDebugEnabled())
{
- dstNode = new LayeredDirectoryNodeImpl((PlainDirectoryNode) srcNode, dstRepo, sPath, true, parentAcl, ACLCopyMode.COPY);
- ((LayeredDirectoryNode) dstNode).setLayerID(sPath.getTopLayer().getLayerID());
+ fgLogger.debug("rename: only change case: from "+avmSrcPath+" to "+avmDstPath);
+ }
+ renameCase = true;
+ }
+ else
+ {
+ throw new AVMExistsException("Node exists: " + dstName);
+ }
+ }
+
+ if (! renameCase)
+ {
+ // general rename/move
+
+ Long parentAcl = dstDir.getAcl() == null ? null : dstDir.getAcl().getId();
+
+ AVMNode dstNode = null;
+ // We've passed the check, so we can go ahead and do the rename.
+ if (srcNode.getType() == AVMNodeType.PLAIN_DIRECTORY)
+ {
+ // 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
+ // 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
+ // we should allow renames from within one layer to within another
+ // 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());
+ }
+ else
+ {
+ dstNode = new LayeredDirectoryNodeImpl((DirectoryNode) srcNode, dstRepo, sPath, srcName, parentAcl, ACLCopyMode.COPY);
+
+ // note: re-use generated node id as a layer id
+ ((LayeredDirectoryNode) dstNode).setLayerID(dstNode.getId());
+ }
+
+ AVMDAOs.Instance().fAVMNodeDAO.update(dstNode);
}
else
{
- dstNode = new LayeredDirectoryNodeImpl((DirectoryNode) srcNode, dstRepo, sPath, srcName, parentAcl, ACLCopyMode.COPY);
-
- // note: re-use generated node id as a layer id
- ((LayeredDirectoryNode) dstNode).setLayerID(dstNode.getId());
+ 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)))
+ {
+ 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());
+ }
+ 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())
+ {
+ Lookup srcLookup = lookup(-1, srcPath + "/" + srcName, true);
+ dstNode = new LayeredDirectoryNodeImpl((LayeredDirectoryNode) srcNode, dstRepo, srcLookup, true, parentAcl, ACLCopyMode.COPY);
+ }
+ else
+ {
+ 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
+ // of its destination parent. Otherwise it should get a new layer
+ // id.
+ if (dPath.isLayered())
+ {
+ ((LayeredDirectoryNode) dstNode).setLayerID(dPath.getTopLayer().getLayerID());
+ }
+ else
+ {
+ // note: re-use generated node id as a layer id
+ ((LayeredDirectoryNode) dstNode).setLayerID(dstNode.getId());
+ }
}
AVMDAOs.Instance().fAVMNodeDAO.update(dstNode);
}
- else
+ else if (srcNode.getType() == AVMNodeType.LAYERED_FILE)
{
- 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)))
- {
- 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 LayeredFileNodeImpl((LayeredFileNode) srcNode, dstRepo, parentAcl, ACLCopyMode.COPY);
}
else
+ // This is a plain file node.
{
- // 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())
- {
- Lookup srcLookup = lookup(-1, srcPath + "/" + srcName, true);
- dstNode = new LayeredDirectoryNodeImpl((LayeredDirectoryNode) srcNode, dstRepo, srcLookup, true, parentAcl, ACLCopyMode.COPY);
- }
- else
- {
- 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
- // of its destination parent. Otherwise it should get a new layer
- // id.
- if (dPath.isLayered())
- {
- ((LayeredDirectoryNode) dstNode).setLayerID(dPath.getTopLayer().getLayerID());
- }
- else
- {
- // note: re-use generated node id as a layer id
- ((LayeredDirectoryNode) dstNode).setLayerID(dstNode.getId());
- }
+ dstNode = new PlainFileNodeImpl((PlainFileNode) srcNode, dstRepo, parentAcl, ACLCopyMode.COPY);
}
- AVMDAOs.Instance().fAVMNodeDAO.update(dstNode);
- }
- else if (srcNode.getType() == AVMNodeType.LAYERED_FILE)
- {
- dstNode = new LayeredFileNodeImpl((LayeredFileNode) srcNode, dstRepo, parentAcl, ACLCopyMode.COPY);
+ srcDir.removeChild(sPath, srcName);
+ // srcDir.updateModTime();
+ // dstNode.setVersionID(dstRepo.getNextVersionID());
+ if (child != null)
+ {
+ dstNode.setAncestor(child);
+ }
+
+ //dstDir.updateModTime();
+ dstDir.putChild(dstName, dstNode);
+ if (child == null)
+ {
+ dstNode.setAncestor(srcNode);
+ }
}
else
- // This is a plain file node.
{
- dstNode = new PlainFileNodeImpl((PlainFileNode) srcNode, dstRepo, parentAcl, ACLCopyMode.COPY);
- }
- srcDir.removeChild(sPath, srcName);
- // srcDir.updateModTime();
- // dstNode.setVersionID(dstRepo.getNextVersionID());
- if (child != null)
- {
- dstNode.setAncestor(child);
- }
- //dstDir.updateModTime();
- dstDir.putChild(dstName, dstNode);
- if (child == null)
- {
- dstNode.setAncestor(srcNode);
+ // specific rename 'case' only (within a store)
+
+ forceCopy(AVMUtil.extendAVMPath(srcPath, srcName));
+
+ Pair result = srcDir.lookupChildEntry(sPath, srcName, false);
+ if (result != null)
+ {
+ ChildKey key = result.getFirst().getKey();
+ key.setName(srcName);
+ AVMDAOs.Instance().fChildEntryDAO.rename(key, dstName);
+ }
}
+
fLookupCache.onWrite(pathParts[0]);
}
finally
diff --git a/source/java/org/alfresco/repo/avm/AVMServiceLocalTest.java b/source/java/org/alfresco/repo/avm/AVMServiceLocalTest.java
index 45f43091c3..2d65096610 100644
--- a/source/java/org/alfresco/repo/avm/AVMServiceLocalTest.java
+++ b/source/java/org/alfresco/repo/avm/AVMServiceLocalTest.java
@@ -1214,8 +1214,7 @@ public class AVMServiceLocalTest extends TestCase
}
}
-
- public void testRename6() throws Exception
+ public void testRename1() throws Exception
{
try
{
@@ -1252,6 +1251,143 @@ public class AVMServiceLocalTest extends TestCase
}
}
+ public void testRename2() throws Exception
+ {
+ String fileLower = "foo";
+ String fileUpper = "FOO";
+
+ try
+ {
+ logger.debug("created 2 stores: main, layer");
+
+ fService.createDirectory("main:/", "a");
+ fService.createFile("main:/a", fileLower);
+
+ logger.debug("created: main:/a/"+fileLower);
+
+ AVMNodeDescriptor desc = fService.lookup(-1, "main:/a/"+fileLower);
+ assertNotNull(desc);
+ assertEquals("main:/a/"+fileLower, desc.getPath());
+
+ fService.createLayeredDirectory("main:/a", "layer:/", "a");
+
+ logger.debug("created: layer:/a/"+fileLower+" -> main:/a/"+fileLower);
+
+ assertNotNull(fService.lookup(-1, "layer:/a/"+fileLower));
+
+ List diffs = fSyncService.compare(-1, "layer:/a", -1, "main:/a", null);
+ assertEquals(0, diffs.size());
+
+ fService.rename("layer:/a/", fileLower, "layer:/a", fileUpper);
+
+ logger.debug("rename: layer:/a/"+fileLower+" -> layer:/a/"+fileUpper);
+
+ diffs = fSyncService.compare(-1, "layer:/a", -1, "main:/a", null);
+ assertEquals("[layer:/a/"+fileUpper+"[-1] > main:/a/"+fileUpper+"[-1]]", diffs.toString());
+
+ fSyncService.update(diffs, null, false, false, false, false, null, null);
+
+ logger.debug("update: layer:/a/"+fileUpper+" -> main:/a/"+fileUpper);
+
+ diffs = fSyncService.compare(-1, "layer:/a", -1, "main:/a", null);
+ assertEquals(0, diffs.size());
+
+ fSyncService.flatten("layer:/a", "main:/a");
+
+ logger.debug("flatten: layer:/a -> main:/a");
+
+ desc = fService.lookup(-1, "main:/a/"+fileLower);
+ assertNotNull(desc);
+ assertEquals("main:/a/"+fileUpper, desc.getPath());
+
+ desc = fService.lookup(-1, "main:/a/"+fileUpper);
+ assertNotNull(desc);
+ assertEquals("main:/a/"+fileUpper, desc.getPath());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+ public void testRename3() throws Exception
+ {
+ try
+ {
+ logger.debug("created 2 stores: main, layer");
+
+ fService.createDirectory("main:/", "a");
+ fService.createDirectory("main:/a", "b");
+ fService.createDirectory("main:/a/b", "c");
+
+ logger.debug("created: main:/a/b/c");
+
+ fService.createLayeredDirectory("main:/a", "layer:/", "a");
+
+ logger.debug("created: layer:/a -> main:/a");
+
+ List diffs = fSyncService.compare(-1, "layer:/a", -1, "main:/a", null);
+ assertEquals(0, diffs.size());
+
+ AVMNodeDescriptor desc = fService.lookup(-1, "main:/a/b");
+ assertNotNull(desc);
+ assertEquals("main:/a/b", desc.getPath());
+
+ desc = fService.lookup(-1, "main:/a/B");
+ assertNotNull(desc);
+ assertEquals("main:/a/b", desc.getPath());
+
+ desc = fService.lookup(-1, "layer:/a/b");
+ assertNotNull(desc);
+ assertEquals("layer:/a/b", desc.getPath());
+
+ fService.rename("layer:/a/", "b", "layer:/a", "B");
+
+ logger.debug("rename: layer:/a/b -> layer:/a/B");
+
+ desc = fService.lookup(-1, "main:/a/b");
+ assertNotNull(desc);
+ assertEquals("main:/a/b", desc.getPath());
+
+ desc = fService.lookup(-1, "layer:/a/B");
+ assertNotNull(desc);
+ assertEquals("layer:/a/B", desc.getPath());
+
+ desc = fService.lookup(-1, "layer:/a/b");
+ assertNotNull(desc);
+ assertEquals("layer:/a/B", desc.getPath());
+
+ diffs = fSyncService.compare(-1, "layer:/a", -1, "main:/a", null);
+ assertEquals("[layer:/a/B[-1] > main:/a/B[-1]]", diffs.toString());
+
+ fSyncService.update(diffs, null, false, false, false, false, null, null);
+
+ logger.debug("update: layer:/a/B -> main:/a/B");
+
+ diffs = fSyncService.compare(-1, "layer:/a", -1, "main:/a", null);
+ assertEquals(0, diffs.size());
+
+ fSyncService.flatten("layer:/a", "main:/a");
+
+ logger.debug("flatten: layer:/a -> main:/a");
+
+ desc = fService.lookup(-1, "main:/a/b");
+ assertNotNull(desc);
+ assertEquals("main:/a/B", desc.getPath());
+
+ desc = fService.lookup(-1, "main:/a/B");
+ assertNotNull(desc);
+ assertEquals("main:/a/B", desc.getPath());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+
/**
* Test file properties update ...
*/
diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java
index 3598ec47f4..6262473817 100644
--- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java
+++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java
@@ -5976,24 +5976,88 @@ public class AVMServiceTest extends AVMServiceTestBase
*/
public void testCaseInsensitive() throws Exception
{
+ String storeName = "caseIn";
+ String storeNameUpper = storeName.toUpperCase();
+ String storeNameLower = storeName.toLowerCase();
+
try
{
- setupBasicTree();
+ fService.createStore(storeName);
+
try
{
- fService.createFile("main:/a/b/c", "Foo").close();
+ fService.createStore(storeNameUpper);
fail();
}
catch (AVMExistsException e)
{
// Do nothing.
}
+
+ AVMStoreDescriptor storeDesc1 = fService.getStore(storeNameUpper);
+ assertNotNull(storeDesc1);
+ assertEquals(storeName, storeDesc1.getName());
+
+ AVMStoreDescriptor storeDesc2 = fService.getStore(storeNameLower);
+ assertNotNull(storeDesc2);
+ assertEquals(storeName, storeDesc2.getName());
+
+ assertEquals(storeDesc1, storeDesc2); // same id
+
+ fService.createDirectory(storeName+":/", "a");
+ fService.createDirectory(storeName+":/a", "B");
+ fService.createDirectory(storeName+":/a/B", "c");
+ fService.createFile(storeName+":/a/B/c", "Foo").close();
+
+ AVMNodeDescriptor desc1 = fService.lookup(-1, storeNameUpper+":/A/B/C/FOO");
+ assertNotNull(desc1);
+ assertEquals(storeName+":/a/B/c/Foo", desc1.getPath());
+
+ try
+ {
+ fService.createFile(storeName+":/a/B/c", "FoO").close();
+ fail();
+ }
+ catch (AVMExistsException e)
+ {
+ // Do nothing.
+ }
+
+ AVMNodeDescriptor desc2 = fService.lookup(-1, storeNameLower+":/a/b/c/foo");
+ assertNotNull(desc2);
+ assertEquals(storeName+":/a/B/c/Foo", desc2.getPath());
+
+ assertEquals(desc1, desc2); // same id
+
+ desc1 = fService.lookup(-1, storeNameUpper+":/A/B/C");
+ assertNotNull(desc1);
+ assertEquals(storeName+":/a/B/c", desc1.getPath());
+
+ try
+ {
+ fService.createFile(storeName+":/a/b", "C").close();
+ fail();
+ }
+ catch (AVMExistsException e)
+ {
+ // Do nothing.
+ }
+
+ desc2 = fService.lookup(-1, storeNameLower+":/a/b/c");
+ assertNotNull(desc2);
+ assertEquals(storeName+":/a/B/c", desc2.getPath());
+
+ assertEquals(desc1, desc2); // same id
}
catch (Exception e)
{
e.printStackTrace(System.err);
throw e;
}
+ finally
+ {
+ fService.purgeStore(storeName);
+ }
}
/**
diff --git a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java
index 25e0c96872..abd0b68e0e 100644
--- a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java
+++ b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java
@@ -1286,7 +1286,7 @@ public class AVMStoreImpl implements AVMStore
PropertyValue createdValue = getProperty(ContentModel.PROP_CREATED);
Date created = createdValue == null ? (new Date()) : (Date) createdValue.getValue(DataTypeDefinition.DATE);
created = (created == null) ? (new Date()) : created;
- return new AVMStoreDescriptor(getName(), creator, created.getTime());
+ return new AVMStoreDescriptor(getId(), getName(), creator, created.getTime());
}
/**
diff --git a/source/java/org/alfresco/repo/avm/AVMSyncServiceImpl.java b/source/java/org/alfresco/repo/avm/AVMSyncServiceImpl.java
index 0b215df363..a9883b2e24 100644
--- a/source/java/org/alfresco/repo/avm/AVMSyncServiceImpl.java
+++ b/source/java/org/alfresco/repo/avm/AVMSyncServiceImpl.java
@@ -161,9 +161,29 @@ public class AVMSyncServiceImpl implements AVMSyncService
int dstVersion, AVMNodeDescriptor dstDesc,
List result, NameMatcher excluder, boolean firstLevel)
{
+ String srcPath = srcDesc.getPath();
+ String dstPath = dstDesc.getPath();
+
+ String srcParts[] = AVMUtil.splitBase(srcPath);
+ String srcChildName = srcParts[1];
+
+ String dstParts[] = AVMUtil.splitBase(dstPath);
+ String dstChildName = dstParts[1];
+
+ if ((dstChildName.equalsIgnoreCase(srcChildName)) && (! dstChildName.equals(srcChildName)))
+ {
+ // specific rename 'case'
+ String dstParentPath = dstParts[0];
+ if (dstParentPath == null)
+ {
+ dstParentPath = AVMUtil.buildAVMPath(AVMUtil.getStoreName(dstPath), "");
+ }
+ dstPath = AVMUtil.extendAVMPath(dstParentPath, srcChildName);
+ }
+
// Determine how the source and destination nodes differ.
- if (excluder != null && (excluder.matches(srcDesc.getPath()) ||
- excluder.matches(dstDesc.getPath())))
+ if (excluder != null && (excluder.matches(srcPath) ||
+ excluder.matches(dstPath)))
{
return;
}
@@ -180,8 +200,8 @@ public class AVMSyncServiceImpl implements AVMSyncService
case AVMDifference.OLDER :
case AVMDifference.CONFLICT :
{
- result.add(new AVMDifference(srcVersion, srcDesc.getPath(),
- dstVersion, dstDesc.getPath(),
+ result.add(new AVMDifference(srcVersion, srcPath,
+ dstVersion, dstPath,
diffCode));
return;
}
@@ -190,7 +210,7 @@ public class AVMSyncServiceImpl implements AVMSyncService
// First special case: source is a layered directory which points to
// the destinations path, and we are comparing 'head' versions.
if (srcDesc.isLayeredDirectory() &&
- srcDesc.getIndirection().equals(dstDesc.getPath()) && srcVersion < 0 && dstVersion < 0)
+ srcDesc.getIndirection().equalsIgnoreCase(dstPath) && srcVersion < 0 && dstVersion < 0)
{
// skip firstLevel (root)
if (! firstLevel)
@@ -203,8 +223,8 @@ public class AVMSyncServiceImpl implements AVMSyncService
case AVMDifference.NEWER :
case AVMDifference.CONFLICT :
{
- result.add(new AVMDifference(srcVersion, srcDesc.getPath(),
- dstVersion, dstDesc.getPath(),
+ result.add(new AVMDifference(srcVersion, srcPath,
+ dstVersion, dstPath,
dirDiffCode));
return; // short circuit
}
@@ -235,19 +255,21 @@ public class AVMSyncServiceImpl implements AVMSyncService
{
AVMNodeDescriptor srcChild = srcList.get(name);
AVMNodeDescriptor dstChild = dstList.get(name);
- String dstPath = AVMNodeConverter.ExtendAVMPath(dstDesc.getPath(), name);
- if (excluder != null && (excluder.matches(srcChild.getPath()) ||
- excluder.matches(dstPath)))
+
+ String srcChildPath = srcChild.getPath();
+ String dstChildPath = AVMNodeConverter.ExtendAVMPath(dstPath, name);
+
+ if (excluder != null && (excluder.matches(srcChildPath) ||
+ excluder.matches(dstChildPath)))
{
continue;
}
if (dstChild == null)
{
// A missing destination child means the source is NEWER.
- result.add(new AVMDifference(srcVersion, srcChild.getPath(),
- dstVersion,
- dstPath,
- AVMDifference.NEWER));
+ result.add(new AVMDifference(srcVersion, srcChildPath,
+ dstVersion, dstChildPath,
+ AVMDifference.NEWER));
continue;
}
// Otherwise recursively invoke.
@@ -259,7 +281,7 @@ public class AVMSyncServiceImpl implements AVMSyncService
}
// Second special case. Just as above but reversed.
if (dstDesc.isLayeredDirectory() &&
- dstDesc.getIndirection().equals(srcDesc.getPath()) && srcVersion < 0 && dstVersion < 0)
+ dstDesc.getIndirection().equalsIgnoreCase(srcPath) && srcVersion < 0 && dstVersion < 0)
{
// skip firstLevel (root)
if (! firstLevel)
@@ -272,8 +294,8 @@ public class AVMSyncServiceImpl implements AVMSyncService
case AVMDifference.NEWER :
case AVMDifference.CONFLICT :
{
- result.add(new AVMDifference(srcVersion, srcDesc.getPath(),
- dstVersion, dstDesc.getPath(),
+ result.add(new AVMDifference(srcVersion, srcPath,
+ dstVersion, dstPath,
dirDiffCode));
return; // short circuit
}
@@ -303,18 +325,20 @@ public class AVMSyncServiceImpl implements AVMSyncService
{
AVMNodeDescriptor dstChild = dstList.get(name);
AVMNodeDescriptor srcChild = srcList.get(name);
- String srcPath = AVMNodeConverter.ExtendAVMPath(srcDesc.getPath(), name);
- if (excluder != null && (excluder.matches(srcPath) ||
- excluder.matches(dstChild.getPath())))
+
+ String srcChildPath = AVMNodeConverter.ExtendAVMPath(srcPath, name);
+ String dstChildPath = dstChild.getPath();
+
+ if (excluder != null && (excluder.matches(srcChildPath) ||
+ excluder.matches(dstChildPath)))
{
continue;
}
if (srcChild == null)
{
// Missing means the source is older.
- result.add(new AVMDifference(srcVersion,
- srcPath,
- dstVersion, dstChild.getPath(),
+ result.add(new AVMDifference(srcVersion, srcChildPath,
+ dstVersion, dstChildPath,
AVMDifference.OLDER));
continue;
}
@@ -335,18 +359,20 @@ public class AVMSyncServiceImpl implements AVMSyncService
{
AVMNodeDescriptor srcChild = srcList.get(name);
AVMNodeDescriptor dstChild = dstList.get(name);
- String dstPath = AVMNodeConverter.ExtendAVMPath(dstDesc.getPath(), name);
- if (excluder != null && (excluder.matches(srcChild.getPath()) ||
- excluder.matches(dstPath)))
+
+ String srcChildPath = srcChild.getPath();
+ String dstChildPath = AVMNodeConverter.ExtendAVMPath(dstPath, name);
+
+ if (excluder != null && (excluder.matches(srcChildPath) ||
+ excluder.matches(dstChildPath)))
{
continue;
}
if (dstChild == null)
{
// Not found in the destination means NEWER.
- result.add(new AVMDifference(srcVersion, srcChild.getPath(),
- dstVersion,
- dstPath,
+ result.add(new AVMDifference(srcVersion, srcChildPath,
+ dstVersion, dstChildPath,
AVMDifference.NEWER));
continue;
}
@@ -362,17 +388,20 @@ public class AVMSyncServiceImpl implements AVMSyncService
{
continue;
}
+
AVMNodeDescriptor dstChild = dstList.get(name);
- String srcPath = AVMNodeConverter.ExtendAVMPath(srcDesc.getPath(), name);
- if (excluder != null && (excluder.matches(srcPath) ||
- excluder.matches(dstChild.getPath())))
+
+ String srcChildPath = AVMNodeConverter.ExtendAVMPath(srcPath, name);
+ String dstChildPath = dstChild.getPath();
+
+ if (excluder != null && (excluder.matches(srcChildPath) ||
+ excluder.matches(dstChildPath)))
{
continue;
}
// An entry not found in the source is OLDER.
- result.add(new AVMDifference(srcVersion,
- srcPath,
- dstVersion, dstChild.getPath(),
+ result.add(new AVMDifference(srcVersion, srcChildPath,
+ dstVersion, dstChildPath,
AVMDifference.OLDER));
}
break;
diff --git a/source/java/org/alfresco/repo/avm/ChildEntryDAO.java b/source/java/org/alfresco/repo/avm/ChildEntryDAO.java
index 3948c8a434..7d0de0aef7 100644
--- a/source/java/org/alfresco/repo/avm/ChildEntryDAO.java
+++ b/source/java/org/alfresco/repo/avm/ChildEntryDAO.java
@@ -64,10 +64,10 @@ public interface ChildEntryDAO
public List getByChild(AVMNode child);
/**
- * Update a dirty ChildEntry.
- * @param child The dirty entry.
+ * Rename a child entry (specific rename 'case' only)
+ * @param child The one to rename.
*/
- public void update(ChildEntry child);
+ public void rename(ChildKey key, String newName);
/**
* Delete one.
diff --git a/source/java/org/alfresco/repo/avm/DirectoryNode.java b/source/java/org/alfresco/repo/avm/DirectoryNode.java
index 736605e0d5..2d51d7be3d 100644
--- a/source/java/org/alfresco/repo/avm/DirectoryNode.java
+++ b/source/java/org/alfresco/repo/avm/DirectoryNode.java
@@ -52,6 +52,14 @@ public interface DirectoryNode extends AVMNode
*/
public Pair lookupChild(Lookup lPath, String name, boolean includeDeleted);
+ /**
+ * Lookup a child entry.
+ * @param lPath The Lookup so far.
+ * @param name The name of the child to lookup.
+ * @param includeDeleted Include deleted nodes or not.
+ */
+ public Pair lookupChildEntry(Lookup lPath, String name, boolean includeDeleted);
+
/**
* Lookup a child node using an AVMNodeDescriptor as context.
* @param mine The node descriptor for this.
diff --git a/source/java/org/alfresco/repo/avm/DirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/DirectoryNodeImpl.java
index 9eef8019bd..416aa04d9b 100644
--- a/source/java/org/alfresco/repo/avm/DirectoryNodeImpl.java
+++ b/source/java/org/alfresco/repo/avm/DirectoryNodeImpl.java
@@ -21,6 +21,7 @@ package org.alfresco.repo.avm;
import org.alfresco.service.cmr.avm.AVMBadArgumentException;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMNotFoundException;
+import org.alfresco.util.Pair;
/**
* Base class for Directories.
@@ -82,4 +83,21 @@ public abstract class DirectoryNodeImpl extends AVMNodeImpl implements Directory
{
return AVMDAOs.Instance().fChildEntryDAO.existsParentChild(this, node);
}
+
+ /**
+ * Lookup a child node by name.
+ * @param lPath The lookup path so far.
+ * @param name The name to lookup.
+ * @param includeDeleted Whether to lookup deleted nodes.
+ * @return The child node or null.
+ */
+ public Pair lookupChild(Lookup lPath, String name, boolean includeDeleted)
+ {
+ Pair result = lookupChildEntry(lPath, name, includeDeleted);
+ if (result == null)
+ {
+ return null;
+ }
+ return new Pair(result.getFirst().getChild(), result.getSecond());
+ }
}
diff --git a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java
index a3db9b6ba4..b846086a54 100644
--- a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java
+++ b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java
@@ -444,10 +444,12 @@ public class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements Layer
*/
public Map getListing(Lookup lPath, String childNamePattern, boolean includeDeleted)
{
- // Get the base listing from the thing we indirect to.
Map listing = new HashMap();
+ Map baseLowerKeyName = new HashMap();
+
if (!getOpacity())
{
+ // If we are not opaque, get the underlying base listing (from the thing we indirect to)
Lookup lookup = AVMRepository.GetInstance().lookupDirectory(getUnderlyingVersion(lPath), getUnderlying(lPath));
if (lookup != null)
{
@@ -464,6 +466,7 @@ public class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements Layer
}
}
listing.put(entry.getKey(), entry.getValue());
+ baseLowerKeyName.put(entry.getKey().toLowerCase(), entry.getKey());
}
}
}
@@ -483,6 +486,13 @@ public class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements Layer
}
else
{
+ String keyName = baseLowerKeyName.get(entry.getKey().getName().toLowerCase());
+ if (keyName != null)
+ {
+ // specific rename 'case' only
+ listing.remove(keyName);
+ }
+
listing.put(entry.getKey().getName(), entry.getChild());
}
}
@@ -584,16 +594,18 @@ public class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements Layer
{
throw new AVMBadArgumentException("Illegal null argument.");
}
- SortedMap baseListing = new TreeMap(String.CASE_INSENSITIVE_ORDER);
- // If we are not opaque, get the underlying base listing.
+ SortedMap listing = new TreeMap(String.CASE_INSENSITIVE_ORDER);
+ Map baseLowerKeyName = new HashMap();
+
if (!getOpacity())
{
+ // If we are not opaque, get the underlying base listing (from the thing we indirect to)
Lookup lookup = AVMRepository.GetInstance().lookupDirectory(dir.getIndirectionVersion(), dir.getIndirection());
if (lookup != null)
{
DirectoryNode dirNode = (DirectoryNode) lookup.getCurrentNode();
- Map listing = dirNode.getListing(lookup, childNamePattern, includeDeleted);
- for (Map.Entry entry : listing.entrySet())
+ Map underListing = dirNode.getListing(lookup, childNamePattern, includeDeleted);
+ for (Map.Entry entry : underListing.entrySet())
{
if (entry.getValue().getType() == AVMNodeType.LAYERED_DIRECTORY ||
entry.getValue().getType() == AVMNodeType.PLAIN_DIRECTORY)
@@ -603,37 +615,45 @@ public class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements Layer
continue;
}
}
- baseListing.put(entry.getKey(),
+ listing.put(entry.getKey(),
entry.getValue().getDescriptor(dir.getPath(), entry.getKey(),
lookup.getCurrentIndirection(),
lookup.getCurrentIndirectionVersion()));
+
+ baseLowerKeyName.put(entry.getKey().toLowerCase(), entry.getKey());
}
}
}
- List children = AVMDAOs.Instance().fChildEntryDAO.getByParent(this, childNamePattern);
- for (ChildEntry child : children)
+ for (ChildEntry entry : AVMDAOs.Instance().fChildEntryDAO.getByParent(this, childNamePattern))
{
- if (child.getChild().getType() == AVMNodeType.LAYERED_DIRECTORY ||
- child.getChild().getType() == AVMNodeType.PLAIN_DIRECTORY)
+ if (entry.getChild().getType() == AVMNodeType.LAYERED_DIRECTORY ||
+ entry.getChild().getType() == AVMNodeType.PLAIN_DIRECTORY)
{
- if (!AVMRepository.GetInstance().can(null, child.getChild(), PermissionService.READ_CHILDREN, false))
+ if (!AVMRepository.GetInstance().can(null, entry.getChild(), PermissionService.READ_CHILDREN, false))
{
continue;
}
}
- if (!includeDeleted && child.getChild().getType() == AVMNodeType.DELETED_NODE)
+ if (!includeDeleted && entry.getChild().getType() == AVMNodeType.DELETED_NODE)
{
- baseListing.remove(child.getKey().getName());
+ listing.remove(entry.getKey().getName());
}
else
{
- baseListing.put(child.getKey().getName(), child.getChild()
- .getDescriptor(dir.getPath(), child.getKey().getName(), dir.getIndirection(), dir.getIndirectionVersion()));
+ String keyName = baseLowerKeyName.get(entry.getKey().getName().toLowerCase());
+ if (keyName != null)
+ {
+ // specific rename 'case' only
+ listing.remove(keyName);
+ }
+
+ listing.put(entry.getKey().getName(), entry.getChild()
+ .getDescriptor(dir.getPath(), entry.getKey().getName(), dir.getIndirection(), dir.getIndirectionVersion()));
}
}
- return baseListing;
+ return listing;
}
-
+
/**
* Get the names of nodes deleted in this directory.
*
@@ -652,9 +672,9 @@ public class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements Layer
}
return listing;
}
-
+
/**
- * Lookup a child by name.
+ * Lookup a child entry by name.
*
* @param lPath
* The Lookup.
@@ -664,9 +684,9 @@ public class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements Layer
* The version in which we are looking.
* @param write
* Whether this lookup is occurring in a write context.
- * @return The child or null if not found.
+ * @return The child entry or null if not found.
*/
- public Pair lookupChild(Lookup lPath, String name, boolean includeDeleted)
+ public Pair lookupChildEntry(Lookup lPath, String name, boolean includeDeleted)
{
ChildKey key = new ChildKey(this, name);
ChildEntry entry = AVMDAOs.Instance().fChildEntryDAO.get(key);
@@ -676,7 +696,7 @@ public class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements Layer
{
return null;
}
- Pair result = new Pair(entry.getChild(), true);
+ Pair result = new Pair(entry, true);
return result;
}
// Don't check our underlying directory if we are opaque.
@@ -689,7 +709,7 @@ public class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements Layer
if (lookup != null)
{
DirectoryNode dir = (DirectoryNode) lookup.getCurrentNode();
- Pair retVal = dir.lookupChild(lookup, name, includeDeleted);
+ Pair retVal = dir.lookupChildEntry(lookup, name, includeDeleted);
if (retVal != null)
{
retVal.setSecond(false);
diff --git a/source/java/org/alfresco/repo/avm/MultiTAVMService.java b/source/java/org/alfresco/repo/avm/MultiTAVMService.java
index cce9ce6087..b8937b63fa 100644
--- a/source/java/org/alfresco/repo/avm/MultiTAVMService.java
+++ b/source/java/org/alfresco/repo/avm/MultiTAVMService.java
@@ -982,6 +982,7 @@ public class MultiTAVMService implements AVMService
}
return new AVMStoreDescriptor(
+ store.getId(),
getBaseStoreName(store.getName()),
store.getCreator(),
store.getCreateDate());
diff --git a/source/java/org/alfresco/repo/avm/NOOPLookupCache.java b/source/java/org/alfresco/repo/avm/NOOPLookupCache.java
index 03478b7004..1326ff2375 100644
--- a/source/java/org/alfresco/repo/avm/NOOPLookupCache.java
+++ b/source/java/org/alfresco/repo/avm/NOOPLookupCache.java
@@ -18,7 +18,6 @@
*/
package org.alfresco.repo.avm;
-import org.alfresco.repo.avm.util.AVMUtil;
import org.alfresco.repo.avm.util.SimplePath;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.security.PermissionService;
@@ -91,20 +90,22 @@ public class NOOPLookupCache implements LookupCache
{
throw new AccessDeniedException("Not allowed to read children: " + path.get(i) + " ("+store.getName()+")");
}
- Pair child = dir.lookupChild(result, path.get(i), includeDeleted);
- if (child == null)
+ Pair childEntryResult = dir.lookupChildEntry(result, path.get(i), includeDeleted);
+ if (childEntryResult == null)
{
return null;
}
+ AVMNode child = childEntryResult.getFirst().getChild();
// Every element that is not the last needs to be a directory.
- if (child.getFirst().getType() != AVMNodeType.PLAIN_DIRECTORY &&
- child.getFirst().getType() != AVMNodeType.LAYERED_DIRECTORY)
+ if (child.getType() != AVMNodeType.PLAIN_DIRECTORY &&
+ child.getType() != AVMNodeType.LAYERED_DIRECTORY)
{
return null;
}
- prevDir = (DirectoryNode)child.getFirst();
- result.add(child.getFirst(), path.get(i), child.getSecond(), write);
+ prevDir = (DirectoryNode)child;
+ String lookupPathElementName = childEntryResult.getFirst().getKey().getName();
+ result.add(child, lookupPathElementName, childEntryResult.getSecond(), write);
dir = (DirectoryNode)result.getCurrentNode();
}
// Now look up the last element.
@@ -112,9 +113,8 @@ public class NOOPLookupCache implements LookupCache
{
throw new AccessDeniedException("Not allowed to read children: " + path.get(path.size() - 1) + " ("+store.getName()+")");
}
- Pair child = dir.lookupChild(result, path.get(path.size() - 1),
- includeDeleted);
- if (child == null)
+ Pair childEntryResult = dir.lookupChildEntry(result, path.get(path.size() - 1), includeDeleted);
+ if (childEntryResult == null)
{
if (write && (dir.getType() == AVMNodeType.LAYERED_DIRECTORY))
{
@@ -127,7 +127,7 @@ public class NOOPLookupCache implements LookupCache
{
return null;
}
- child = new Pair(AVMNodeUnwrapper.Unwrap(entry.getChild()), true);
+ childEntryResult = new Pair(entry, true);
}
else
{
@@ -139,7 +139,9 @@ public class NOOPLookupCache implements LookupCache
return null;
}
}
- result.add(child.getFirst(), path.get(path.size() - 1), child.getSecond(), write);
+ AVMNode child = childEntryResult.getFirst().getChild();
+ String lookupPathElementName = childEntryResult.getFirst().getKey().getName();
+ result.add(child, lookupPathElementName, childEntryResult.getSecond(), write);
return result;
}
diff --git a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java
index b1cfde3b5f..d9079cceb4 100644
--- a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java
+++ b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java
@@ -203,15 +203,15 @@ public class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDi
{
return new ArrayList();
}
-
+
/**
- * Lookup a child by name.
+ * Lookup a child entry by name.
* @param lPath The lookup path so far.
* @param name The name to lookup.
* @param includeDeleted Whether to lookup deleted nodes.
- * @return The child or null.
+ * @return The child entry or null.
*/
- public Pair lookupChild(Lookup lPath, String name, boolean includeDeleted)
+ public Pair lookupChildEntry(Lookup lPath, String name, boolean includeDeleted)
{
ChildKey key = new ChildKey(this, name);
ChildEntry entry = AVMDAOs.Instance().fChildEntryDAO.get(key);
@@ -223,7 +223,7 @@ public class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDi
{
return null;
}
- Pair result = new Pair(entry.getChild(), true);
+ Pair result = new Pair(entry, true);
return result;
}
diff --git a/source/java/org/alfresco/repo/avm/ibatis/ChildEntryDAOIbatis.java b/source/java/org/alfresco/repo/avm/ibatis/ChildEntryDAOIbatis.java
index 753917e758..5a2a61296d 100644
--- a/source/java/org/alfresco/repo/avm/ibatis/ChildEntryDAOIbatis.java
+++ b/source/java/org/alfresco/repo/avm/ibatis/ChildEntryDAOIbatis.java
@@ -21,6 +21,7 @@ package org.alfresco.repo.avm.ibatis;
import java.util.ArrayList;
import java.util.List;
+import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.avm.AVMDAOs;
import org.alfresco.repo.avm.AVMNode;
import org.alfresco.repo.avm.ChildEntry;
@@ -98,11 +99,21 @@ class ChildEntryDAOIbatis implements ChildEntryDAO
}
/* (non-Javadoc)
- * @see org.alfresco.repo.avm.ChildEntryDAO#update(org.alfresco.repo.avm.ChildEntry)
+ * @see org.alfresco.repo.avm.ChildEntryDAO#rename(org.alfresco.repo.avm.ChildKey, String)
*/
- public void update(ChildEntry child)
+ public void rename(ChildKey key, String newName)
{
- // NOOP
+ // direct rename should only be used if changing case
+ if (! key.getName().equalsIgnoreCase(newName))
+ {
+ throw new AlfrescoRuntimeException("Invalid rename (can only change case");
+ }
+
+ AVMChildEntryEntity childEntryEntity = AVMDAOs.Instance().newAVMNodeLinksDAO.getChildEntry(key.getParent().getId(), key.getName());
+
+ childEntryEntity.setName(newName);
+
+ AVMDAOs.Instance().newAVMNodeLinksDAO.updateChildEntry(childEntryEntity);
}
/* (non-Javadoc)
diff --git a/source/java/org/alfresco/repo/domain/avm/AVMNodeLinksDAO.java b/source/java/org/alfresco/repo/domain/avm/AVMNodeLinksDAO.java
index 5d48ae8313..be21fcdab9 100644
--- a/source/java/org/alfresco/repo/domain/avm/AVMNodeLinksDAO.java
+++ b/source/java/org/alfresco/repo/domain/avm/AVMNodeLinksDAO.java
@@ -68,6 +68,11 @@ public interface AVMNodeLinksDAO
*/
public AVMChildEntryEntity getChildEntry(long parentNodeId, long childNodeId);
+ /**
+ * Specific rename 'case' only
+ */
+ public void updateChildEntry(AVMChildEntryEntity childEntryEntity);
+
/**
* Delete one
*/
diff --git a/source/java/org/alfresco/repo/domain/avm/AbstractAVMNodeLinksDAOImpl.java b/source/java/org/alfresco/repo/domain/avm/AbstractAVMNodeLinksDAOImpl.java
index c7c1ae8fb7..cd7cfa1c6d 100644
--- a/source/java/org/alfresco/repo/domain/avm/AbstractAVMNodeLinksDAOImpl.java
+++ b/source/java/org/alfresco/repo/domain/avm/AbstractAVMNodeLinksDAOImpl.java
@@ -191,6 +191,24 @@ public abstract class AbstractAVMNodeLinksDAOImpl implements AVMNodeLinksDAO
return result;
}
+ /**
+ * {@inheritDoc}
+ */
+ public void updateChildEntry(AVMChildEntryEntity childEntryEntity)
+ {
+ ParameterCheck.mandatory("childEntryEntity", childEntryEntity);
+ ParameterCheck.mandatory("childEntryEntity.getParentNodeId()", childEntryEntity.getParentNodeId());
+ ParameterCheck.mandatory("childEntryEntity.getChildId()", childEntryEntity.getChildId());
+ ParameterCheck.mandatory("childEntryEntity.getName()", childEntryEntity.getName());
+
+ ChildKey key = new ChildKey(childEntryEntity.getParentNodeId(), childEntryEntity.getName());
+ int updated = avmChildEntryCache.updateValue(key, childEntryEntity);
+ if (updated < 1)
+ {
+ throw new ConcurrencyFailureException("AVMChildEntry for parent/name (" + key.getParentNodeId() + ", " + key.getName() + ") no longer exists");
+ }
+ }
+
/**
* {@inheritDoc}
*/
@@ -344,7 +362,7 @@ public abstract class AbstractAVMNodeLinksDAOImpl implements AVMNodeLinksDAO
public int updateValue(ChildKey key, AVMChildEntryEntity value)
{
- throw new UnsupportedOperationException("updateValue(Long, AVMChildEntryEntity");
+ return updateChildEntryEntity(value);
}
public int deleteByKey(ChildKey key)
@@ -367,6 +385,9 @@ public abstract class AbstractAVMNodeLinksDAOImpl implements AVMNodeLinksDAO
protected abstract AVMChildEntryEntity getChildEntryEntity(AVMChildEntryEntity childEntryEntity);
protected abstract void createChildEntryEntity(AVMChildEntryEntity childEntryEntity);
+
+ protected abstract int updateChildEntryEntity(AVMChildEntryEntity childEntryEntity); // specific rename 'case' only
+
protected abstract int deleteChildEntryEntity(long parentNodeId, String name);
protected abstract int deleteChildEntryEntity(long parentNodeId, long childNodeId);
protected abstract int deleteChildEntryEntities(long parentNodeId);
diff --git a/source/java/org/alfresco/repo/domain/avm/ibatis/AVMNodeLinksDAOImpl.java b/source/java/org/alfresco/repo/domain/avm/ibatis/AVMNodeLinksDAOImpl.java
index e81f94d634..6638cbc2f3 100644
--- a/source/java/org/alfresco/repo/domain/avm/ibatis/AVMNodeLinksDAOImpl.java
+++ b/source/java/org/alfresco/repo/domain/avm/ibatis/AVMNodeLinksDAOImpl.java
@@ -22,9 +22,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.alfresco.repo.domain.avm.AVMChildEntryEntity;
import org.alfresco.repo.domain.avm.AVMHistoryLinkEntity;
import org.alfresco.repo.domain.avm.AVMMergeLinkEntity;
-import org.alfresco.repo.domain.avm.AVMChildEntryEntity;
import org.alfresco.repo.domain.avm.AbstractAVMNodeLinksDAOImpl;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
@@ -37,15 +37,26 @@ import org.springframework.orm.ibatis.SqlMapClientTemplate;
public class AVMNodeLinksDAOImpl extends AbstractAVMNodeLinksDAOImpl
{
private static final String SELECT_AVM_NODE_CHILD_ENTRY ="alfresco.avm.select_AVMChildEntry"; // parent + name + child
+ private static final String SELECT_AVM_NODE_CHILD_ENTRY_L ="alfresco.avm.select_AVMChildEntryL"; // parent + lower(name) + child
+
private static final String SELECT_AVM_NODE_CHILD_ENTRY_BY_PARENT_AND_NAME ="alfresco.avm.select_AVMChildEntryByParentAndName"; // parent + name
+ private static final String SELECT_AVM_NODE_CHILD_ENTRY_BY_PARENT_AND_NAME_L ="alfresco.avm.select_AVMChildEntryByParentAndNameL"; // parent + lower(name)
+
private static final String SELECT_AVM_NODE_CHILD_ENTRY_BY_PARENT_AND_CHILD ="alfresco.avm.select_AVMChildEntryByParentAndChild"; // parent + child
private static final String SELECT_AVM_NODE_CHILD_ENTRIES_BY_PARENT ="alfresco.avm.select_AVMNodeChildEntriesByParent"; // parent
+
private static final String SELECT_AVM_NODE_CHILD_ENTRIES_BY_PARENT_AND_NAME_PATTERN ="alfresco.avm.select_AVMNodeChildEntriesByParentAndNamePattern"; // parent + name pattern
+ private static final String SELECT_AVM_NODE_CHILD_ENTRIES_BY_PARENT_AND_NAME_PATTERN_L ="alfresco.avm.select_AVMNodeChildEntriesByParentAndNamePatternL"; // parent + lower(name pattern)
+
private static final String SELECT_AVM_NODE_CHILD_ENTRIES_BY_CHILD ="alfresco.avm.select_AVMNodeChildEntriesByChild"; // child
private static final String INSERT_AVM_NODE_CHILD_ENTRY ="alfresco.avm.insert_AVMChildEntry"; // parent + name + child
+ private static final String UPDATE_AVM_NODE_CHILD_ENTRY ="alfresco.avm.update_AVMChildEntry"; // parent + child (update name)
+
private static final String DELETE_AVM_NODE_CHILD_ENTRY_BY_PARENT_AND_NAME ="alfresco.avm.delete_AVMChildEntryByParentAndName"; // parent + name
+ private static final String DELETE_AVM_NODE_CHILD_ENTRY_BY_PARENT_AND_NAME_L ="alfresco.avm.delete_AVMChildEntryByParentAndNameL"; // parent + lower(name)
+
private static final String DELETE_AVM_NODE_CHILD_ENTRY_BY_PARENT_AND_CHILD ="alfresco.avm.delete_AVMChildEntryByParentAndChild"; // parent + child
private static final String DELETE_AVM_NODE_CHILD_ENTRIES_BY_PARENT ="alfresco.avm.delete_AVMNodeChildEntriesByParent"; // parent
@@ -64,14 +75,27 @@ public class AVMNodeLinksDAOImpl extends AbstractAVMNodeLinksDAOImpl
private SqlMapClientTemplate template;
+ // Initial generic fix for ALF-1940 (pending SAIL-349)
+ // Note: in order to override to false DB must be setup to be case-insensitive (at least on column avm_child_entries.name)
+ private boolean toLower = true;
+
public void setSqlMapClientTemplate(SqlMapClientTemplate sqlMapClientTemplate)
{
this.template = sqlMapClientTemplate;
}
+ public void setToLower(boolean toLower)
+ {
+ this.toLower = toLower;
+ }
+
@Override
protected AVMChildEntryEntity getChildEntryEntity(AVMChildEntryEntity childEntryEntity)
{
+ if (toLower)
+ {
+ return (AVMChildEntryEntity) template.queryForObject(SELECT_AVM_NODE_CHILD_ENTRY_L, childEntryEntity);
+ }
return (AVMChildEntryEntity) template.queryForObject(SELECT_AVM_NODE_CHILD_ENTRY, childEntryEntity);
}
@@ -79,6 +103,11 @@ public class AVMNodeLinksDAOImpl extends AbstractAVMNodeLinksDAOImpl
protected AVMChildEntryEntity getChildEntryEntity(long parentNodeId, String name)
{
AVMChildEntryEntity childEntryEntity = new AVMChildEntryEntity(parentNodeId, name);
+
+ if (toLower)
+ {
+ return (AVMChildEntryEntity) template.queryForObject(SELECT_AVM_NODE_CHILD_ENTRY_BY_PARENT_AND_NAME_L, childEntryEntity);
+ }
return (AVMChildEntryEntity) template.queryForObject(SELECT_AVM_NODE_CHILD_ENTRY_BY_PARENT_AND_NAME, childEntryEntity);
}
@@ -105,6 +134,11 @@ public class AVMNodeLinksDAOImpl extends AbstractAVMNodeLinksDAOImpl
Map params = new HashMap(1);
params.put("id", parentNodeId);
params.put("pattern", childNamePattern);
+
+ if (toLower)
+ {
+ return (List) template.queryForList(SELECT_AVM_NODE_CHILD_ENTRIES_BY_PARENT_AND_NAME_PATTERN_L, params);
+ }
return (List) template.queryForList(SELECT_AVM_NODE_CHILD_ENTRIES_BY_PARENT_AND_NAME_PATTERN, params);
}
@@ -123,10 +157,24 @@ public class AVMNodeLinksDAOImpl extends AbstractAVMNodeLinksDAOImpl
template.insert(INSERT_AVM_NODE_CHILD_ENTRY, childEntryEntity);
}
+ @Override
+ protected int updateChildEntryEntity(AVMChildEntryEntity childEntryEntity)
+ {
+ // TODO: concurrency control - note: specific rename 'case' only
+ //childEntryEntity.incrementVers();
+
+ return template.update(UPDATE_AVM_NODE_CHILD_ENTRY, childEntryEntity);
+ }
+
@Override
protected int deleteChildEntryEntity(long parentNodeId, String name)
{
AVMChildEntryEntity childEntryEntity = new AVMChildEntryEntity(parentNodeId, name);
+
+ if (toLower)
+ {
+ return template.delete(DELETE_AVM_NODE_CHILD_ENTRY_BY_PARENT_AND_NAME_L, childEntryEntity);
+ }
return template.delete(DELETE_AVM_NODE_CHILD_ENTRY_BY_PARENT_AND_NAME, childEntryEntity);
}
diff --git a/source/java/org/alfresco/service/cmr/avm/AVMStoreDescriptor.java b/source/java/org/alfresco/service/cmr/avm/AVMStoreDescriptor.java
index 391e7127f8..61f27426d4 100644
--- a/source/java/org/alfresco/service/cmr/avm/AVMStoreDescriptor.java
+++ b/source/java/org/alfresco/service/cmr/avm/AVMStoreDescriptor.java
@@ -30,7 +30,12 @@ import org.springframework.extensions.surf.util.ISO8601DateFormat;
public class AVMStoreDescriptor implements Serializable
{
private static final long serialVersionUID = -4401863082685362175L;
-
+
+ /**
+ * The object id.
+ */
+ private long fID;
+
/**
* The name.
*/
@@ -46,15 +51,16 @@ public class AVMStoreDescriptor implements Serializable
*/
private long fCreateDate;
- public AVMStoreDescriptor(String name,
- String creator,
- long createDate)
+ public AVMStoreDescriptor(long id,
+ String name,
+ String creator,
+ long createDate)
{
fName = name;
fCreator = creator;
fCreateDate = createDate;
}
-
+
/**
* @return the fCreateDate
*/
@@ -62,7 +68,7 @@ public class AVMStoreDescriptor implements Serializable
{
return fCreateDate;
}
-
+
/**
* @return the fCreator
*/
@@ -70,7 +76,7 @@ public class AVMStoreDescriptor implements Serializable
{
return fCreator;
}
-
+
/**
* @return the fName
*/
@@ -79,8 +85,37 @@ public class AVMStoreDescriptor implements Serializable
return fName;
}
+ /**
+ * Get the object id.
+ * @return The object id.
+ */
+ public long getId()
+ {
+ return fID;
+ }
+
public String toString()
{
- return "[" + fName + ":" + fCreator + ":" + ISO8601DateFormat.format(new Date(fCreateDate)) + "]";
+ return "[" + fID + ":"+fName + ":" + fCreator + ":" + ISO8601DateFormat.format(new Date(fCreateDate)) + "]";
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!(obj instanceof AVMStoreDescriptor))
+ {
+ return false;
+ }
+ return fID == ((AVMStoreDescriptor)obj).fID;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return (int)fID;
}
}