diff --git a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/node-common-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/node-common-SqlMap.xml
index 3a80648bb6..29789aca16 100644
--- a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/node-common-SqlMap.xml
+++ b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/node-common-SqlMap.xml
@@ -384,6 +384,14 @@
id = #{id}
+
+ update alf_node set
+ version = version + 1,
+ transaction_id = #{idOne}
+ where
+ store_id = #{idTwo}
+
+
update alf_node set
version = #{version}
diff --git a/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java b/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java
index c2b58f982f..e1b807d0a3 100644
--- a/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java
+++ b/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java
@@ -850,6 +850,11 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
{
throw new ConcurrencyFailureException("Store not updated: " + oldStoreRef);
}
+ // Bring all the associated nodes into the current transaction
+ Long txnId = getCurrentTransaction().getId();
+ Long storeId = store.getId();
+ updateNodesInStore(txnId, storeId);
+
// All the NodeRef-based caches are invalid. ID-based caches are fine.
rootNodesCache.removeByKey(oldStoreRef);
allRootNodesCache.remove(oldStoreRef);
@@ -4827,6 +4832,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
protected abstract Long insertStore(StoreEntity store);
protected abstract int updateStoreRoot(StoreEntity store);
protected abstract int updateStore(StoreEntity store);
+ protected abstract int updateNodesInStore(Long txnId, Long storeId);
protected abstract Long insertNode(NodeEntity node);
protected abstract int updateNode(NodeUpdateEntity nodeUpdate);
protected abstract int updateNodes(Long txnId, List nodeIds);
diff --git a/source/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java b/source/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java
index 5f2e55db1d..6efc1c4d25 100644
--- a/source/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java
+++ b/source/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java
@@ -81,6 +81,7 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
private static final String INSERT_STORE = "alfresco.node.insert.insert_Store";
private static final String UPDATE_STORE_ROOT = "alfresco.node.update_StoreRoot";
private static final String UPDATE_STORE = "alfresco.node.update_Store";
+ private static final String UPDATE_NODES_IN_STORE = "alfresco.node.update_NodesInStore";
private static final String SELECT_STORE_ALL = "alfresco.node.select_StoreAll";
private static final String SELECT_STORE_BY_REF = "alfresco.node.select_StoreByRef";
private static final String SELECT_STORE_ROOT_NODE_BY_REF = "alfresco.node.select_StoreRootNodeByRef";
@@ -310,6 +311,15 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
return template.update(UPDATE_STORE, store);
}
+ @Override
+ protected int updateNodesInStore(Long txnId, Long storeId)
+ {
+ IdsEntity ids = new IdsEntity();
+ ids.setIdOne(txnId);
+ ids.setIdTwo(storeId);
+ return template.update(UPDATE_NODES_IN_STORE, ids);
+ }
+
@Override
protected Long insertNode(NodeEntity node)
{
diff --git a/source/java/org/alfresco/repo/node/BaseNodeServiceTest.java b/source/java/org/alfresco/repo/node/BaseNodeServiceTest.java
index 7ef5240790..60dce4d853 100644
--- a/source/java/org/alfresco/repo/node/BaseNodeServiceTest.java
+++ b/source/java/org/alfresco/repo/node/BaseNodeServiceTest.java
@@ -485,6 +485,10 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
List storeRefs = nodeService.getStores();
// check that the store ref is present
assertTrue("New store not present in list of stores", storeRefs.contains(storeRef));
+ // Get the root node
+ NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
+ assertTrue("Store should still exist", nodeService.exists(storeRef));
+ assertTrue("Node should still exist", nodeService.exists(rootNodeRef));
// Delete it
nodeService.deleteStore(storeRef);
storeRefs = nodeService.getStores();
@@ -497,6 +501,9 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
fail("NodeService should not have returned 'deleted' stores." + storeRefs);
}
}
+ // They should not exist as far as external code is concerned
+ assertFalse("Store should still exist", nodeService.exists(storeRef));
+ assertFalse("Node should still exist", nodeService.exists(rootNodeRef));
// Commit to ensure all is well
setComplete();
diff --git a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
index 0eb04c2aa9..109419668d 100644
--- a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
+++ b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
@@ -263,7 +263,16 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
{
// Delete the index
nodeIndexer.indexDeleteStore(storeRef);
- // Rename the store
+ // Cannot delete the root node but we can delete, without archive, all immediate children
+ NodeRef rootNodeRef = nodeDAO.getRootNode(storeRef).getSecond();
+ List childAssocRefs = getChildAssocs(rootNodeRef);
+ for (ChildAssociationRef childAssocRef : childAssocRefs)
+ {
+ NodeRef childNodeRef = childAssocRef.getChildRef();
+ // We do NOT want to archive these, so mark them as temporary
+ deleteNode(childNodeRef, false);
+ }
+ // Rename the store. This takes all the nodes with it.
StoreRef deletedStoreRef = new StoreRef(StoreRef.PROTOCOL_DELETED, GUID.generate());
nodeDAO.moveStore(storeRef, deletedStoreRef);
@@ -1044,7 +1053,20 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
/**
* Delete Node
*/
+ @Override
public void deleteNode(NodeRef nodeRef)
+ {
+ deleteNode(nodeRef, true);
+ }
+
+ /**
+ * Delete a node
+ *
+ * @param nodeRef the node to delete
+ * @param allowArchival true if normal archival may occur or
+ * false if the node must be forcibly deleted
+ */
+ private void deleteNode(NodeRef nodeRef, boolean allowArchival)
{
// The node(s) involved may not be pending deletion
checkPendingDelete(nodeRef);
@@ -1055,13 +1077,21 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
Boolean requiresDelete = null;
- // get the primary parent-child relationship before it is gone
- Pair childAssocPair = nodeDAO.getPrimaryParentAssoc(nodeId);
- ChildAssociationRef childAssocRef = childAssocPair.getSecond();
// get type and aspect QNames as they will be unavailable after the delete
QName nodeTypeQName = nodeDAO.getNodeType(nodeId);
Set nodeAspectQNames = nodeDAO.getNodeAspects(nodeId);
+ // Have we been asked to delete a store?
+ if (nodeTypeQName.equals(ContentModel.TYPE_STOREROOT))
+ {
+ throw new IllegalArgumentException("A store root node cannot be deleted: " + nodeRef);
+ }
+
+ // get the primary parent-child relationship before it is gone
+ Pair childAssocPair = nodeDAO.getPrimaryParentAssoc(nodeId);
+ ChildAssociationRef childAssocRef = childAssocPair.getSecond();
+
+ // Is this store
StoreRef storeRef = nodeRef.getStoreRef();
StoreRef archiveStoreRef = storeArchiveMap.get(storeRef);
@@ -1079,7 +1109,12 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
nodesPendingDeleteTxn.addAll(nodesPendingDelete); // We need to remove these later, again
// Work out whether we need to archive or delete the node.
- if (archiveStoreRef == null)
+ if (!allowArchival)
+ {
+ // No archival allowed
+ requiresDelete = true;
+ }
+ else if (archiveStoreRef == null)
{
// The store does not specify archiving
requiresDelete = true;
@@ -1162,6 +1197,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
}
invokeBeforeDeleteChildAssociation(secondaryParentAssocPair.getSecond());
}
+
// Primary child associations
if (archive)
{