diff --git a/source/java/org/alfresco/repo/transfer/AbstractManifestProcessorBase.java b/source/java/org/alfresco/repo/transfer/AbstractManifestProcessorBase.java index 6b01a8e6a6..40e0de4cc9 100644 --- a/source/java/org/alfresco/repo/transfer/AbstractManifestProcessorBase.java +++ b/source/java/org/alfresco/repo/transfer/AbstractManifestProcessorBase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2015 Alfresco Software Limited. * * This file is part of Alfresco * @@ -19,9 +19,13 @@ package org.alfresco.repo.transfer; import java.io.File; +import java.io.Serializable; +import java.util.List; +import java.util.Map; import javax.transaction.UserTransaction; +import org.alfresco.model.ContentModel; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode; import org.alfresco.repo.transfer.manifest.TransferManifestHeader; @@ -30,6 +34,7 @@ import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode; import org.alfresco.repo.transfer.manifest.TransferManifestProcessor; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.transfer.TransferException; import org.alfresco.service.cmr.transfer.TransferProgress; import org.alfresco.service.cmr.transfer.TransferReceiver; @@ -270,4 +275,40 @@ public abstract class AbstractManifestProcessorBase implements TransferManifestP { receiver.getProgressMonitor().logMoved(transferId, sourceNode, destNode, oldPath, newParent, newPath); } + + /** + * Puts information about current childRef and its parentRef into log in TRACE level. Information includes 'name', 'fromRepositoryId', 'aliened' and + * 'invadedBy' properties. Additionally, collects the same information for children of childRef + * + * @param parentRef - {@link NodeRef} instance of child node + * @param childRef - {@link NodeRef} instance of parent of the childRef + * @param nodeService - {@link NodeService} instance to get properties and checking other states + * @param log - {@link Log} instance to put log for appropriate class + */ + protected void logInvasionHierarchy(NodeRef parentRef, NodeRef childRef, NodeService nodeService, Log log) + { + Map properties = nodeService.getProperties(childRef); + Map parentProperties = nodeService.getProperties(parentRef); + StringBuilder message = new StringBuilder("Information about '").append(properties.get(ContentModel.PROP_NAME)).append("' node:\n fromRepositoryId: ").append( + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)).append("\n").append(" invadedBy: ").append(properties.get(TransferModel.PROP_INVADED_BY)).append("\n") + .append(" alien: ").append(nodeService.hasAspect(childRef, TransferModel.ASPECT_ALIEN)).append("\n").append(" repositoryId: ").append( + properties.get(TransferModel.PROP_REPOSITORY_ID)).append("\n").append(" parent: ").append(parentProperties.get(ContentModel.PROP_NAME)).append("(") + .append(parentProperties.get(TransferModel.PROP_FROM_REPOSITORY_ID)).append(")").append(parentProperties.get(TransferModel.PROP_INVADED_BY)).append(": ").append( + nodeService.hasAspect(parentRef, TransferModel.ASPECT_ALIEN)).append("\n").append(" children:\n"); + + List childAssocs = nodeService.getChildAssocs(childRef); + + if ((null != childAssocs) && !childAssocs.isEmpty()) + { + for (ChildAssociationRef child : childAssocs) + { + properties = nodeService.getProperties(child.getChildRef()); + message.append(" ").append(properties.get(ContentModel.PROP_NAME)).append("(").append(properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)).append(")") + .append(properties.get(TransferModel.PROP_INVADED_BY)).append(": ").append(nodeService.hasAspect(child.getChildRef(), TransferModel.ASPECT_ALIEN)).append( + "\n"); + } + } + + log.trace(message.toString()); + } } diff --git a/source/java/org/alfresco/repo/transfer/AlienProcessorImpl.java b/source/java/org/alfresco/repo/transfer/AlienProcessorImpl.java index 4f859ff19b..d422835977 100644 --- a/source/java/org/alfresco/repo/transfer/AlienProcessorImpl.java +++ b/source/java/org/alfresco/repo/transfer/AlienProcessorImpl.java @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2005-2015 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ package org.alfresco.repo.transfer; import java.io.Serializable; @@ -5,14 +23,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Stack; import java.util.Vector; import org.alfresco.model.ContentModel; -import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.policy.BehaviourFilter; -import org.alfresco.repo.policy.JavaBehaviour; -import org.alfresco.repo.policy.Behaviour.NotificationFrequency; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.service.cmr.dictionary.DictionaryService; @@ -148,7 +164,46 @@ public class AlienProcessorImpl implements AlienProcessor currentAssoc = null; } } - } + + if (log.isTraceEnabled()) + { + logInvasionHierarchy(childAssocRef.getParentRef(), childAssocRef.getChildRef()); + } + } + + /** + * Puts information about current childRef and its parentRef into log in TRACE level. Information includes 'name', 'fromRepositoryId', 'aliened' and + * 'invadedBy' properties. Additionally, collects the same information for children of childRef + * + * @param parentRef - {@link NodeRef} instance of child node + * @param childRef - {@link NodeRef} instance of parent of the childRef + */ + protected void logInvasionHierarchy(NodeRef parentRef, NodeRef childRef) + { + Map properties = nodeService.getProperties(childRef); + Map parentProperties = nodeService.getProperties(parentRef); + StringBuilder message = new StringBuilder("Information about '").append(properties.get(ContentModel.PROP_NAME)).append("' node:\n fromRepositoryId: ").append( + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)).append("\n").append(" invadedBy: ").append(properties.get(TransferModel.PROP_INVADED_BY)).append("\n") + .append(" alien: ").append(nodeService.hasAspect(childRef, TransferModel.ASPECT_ALIEN)).append("\n").append(" repositoryId: ").append( + properties.get(TransferModel.PROP_REPOSITORY_ID)).append("\n").append(" parent: ").append(parentProperties.get(ContentModel.PROP_NAME)).append("(") + .append(parentProperties.get(TransferModel.PROP_FROM_REPOSITORY_ID)).append(")").append(parentProperties.get(TransferModel.PROP_INVADED_BY)).append(": ").append( + nodeService.hasAspect(parentRef, TransferModel.ASPECT_ALIEN)).append("\n").append(" children:\n"); + + List childAssocs = nodeService.getChildAssocs(childRef); + + if ((null != childAssocs) && !childAssocs.isEmpty()) + { + for (ChildAssociationRef child : childAssocs) + { + properties = nodeService.getProperties(child.getChildRef()); + message.append(" ").append(properties.get(ContentModel.PROP_NAME)).append("(").append(properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)).append(")") + .append(properties.get(TransferModel.PROP_INVADED_BY)).append(": ").append(nodeService.hasAspect(child.getChildRef(), TransferModel.ASPECT_ALIEN)).append( + "\n"); + } + } + + log.trace(message.toString()); + } public void beforeDeleteAlien(NodeRef deletedNodeRef, ChildAssociationRef oldAssoc) { @@ -540,7 +595,7 @@ public class AlienProcessorImpl implements AlienProcessor ChildAssociationRef startingParent = nodeService.getPrimaryParent(nodeToPrune); Stack foldersToRecalculate = new Stack(); - + /** * Now go and do the pruning. */ @@ -554,25 +609,72 @@ public class AlienProcessorImpl implements AlienProcessor * if from the repo with multiple alien invasions - leave alone but process children */ NodeRef currentNodeRef = nodesToPrune.pop(); - + + Map properties = null; + if (log.isDebugEnabled()) + { + properties = nodeService.getProperties(currentNodeRef); + } + + if (log.isDebugEnabled()) + { + log.debug("Current nodeRef (name: \"" + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + + "\", manifestId: \"" + fromRepositoryId + "\")" + currentNodeRef); + } + log.debug("pruneNode:" + currentNodeRef); - + if(getNodeService().hasAspect(currentNodeRef, TransferModel.ASPECT_ALIEN)) { - // Yes this is an alien node - ListinvadedBy = (List)getNodeService().getProperty(currentNodeRef, TransferModel.PROP_INVADED_BY); - if(invadedBy.contains(fromRepositoryId)) + if (log.isDebugEnabled()) { - // Yes we are invaded by fromRepositoryId - if(invadedBy.size() == 1) + log.debug("Current nodeRef has ASPECT_ALIEN (name: \"" + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + "\", manifestId: \"" + fromRepositoryId + "\")"); + } + + // Yes this is an alien node + List invadedBy = (List)getNodeService().getProperty(currentNodeRef, TransferModel.PROP_INVADED_BY); + String initialRepoId = (String) getNodeService().getProperty(currentNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID); + + if (log.isDebugEnabled()) + { + log.debug("Current nodeRef has PROP_INVADED_BY (name: \"" + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + "\", manifestId: \"" + fromRepositoryId + "\"): " + invadedBy); + } + + if ((null != invadedBy) && invadedBy.contains(fromRepositoryId)) + { + if (log.isDebugEnabled()) { + log.debug("Current nodeRef's PROP_INVADED_BY contains current manifestId (name: \"" + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + "\", manifestId: \"" + fromRepositoryId + "\")"); + } + + // Yes we are invaded by fromRepositoryId + if ((1 == invadedBy.size()) && fromRepositoryId.equalsIgnoreCase(initialRepoId)) + { + if (log.isDebugEnabled()) + { + log + .debug("Current nodeRef has only 1 element in PROP_INVADED_BY. Also MANIFEST_ID and INITIAL_REPOSITORY_ID are the same. Deleting the node... (name: \"" + + properties.get(ContentModel.PROP_NAME) + + "\", fromRepositoryId: \"" + + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + + "\", manifestId: \"" + fromRepositoryId + "\")"); + } + // we are invaded by a single repository which must be fromRepositoryId - log.debug("pruned - deleted node:" + currentNodeRef); getNodeService().deleteNode(currentNodeRef); } else { - log.debug("folder has multiple invaders"); + if (log.isDebugEnabled()) + { + log.debug("Current 'nodeRef' has more than 1 element in PROP_INVADED_BY. Adding its children to 'nodesToPrune' list... (name: \"" + + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + + "\", manifestId: \"" + fromRepositoryId + "\")"); + } + // multiple invasion - so it must be a folder List refs = nodeService.getChildAssocsByPropertyValue(currentNodeRef, TransferModel.PROP_INVADED_BY, fromRepositoryId); for(ChildAssociationRef ref : refs) @@ -589,12 +691,24 @@ public class AlienProcessorImpl implements AlienProcessor */ if(!foldersToRecalculate.contains(currentNodeRef)) { + if (log.isDebugEnabled()) + { + log.debug("Current 'nodeRef' is not in 'foldersToRecalculate' list. Adding it to the list... (name: \"" + properties.get(ContentModel.PROP_NAME) + + "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + "\", manifestId: \"" + fromRepositoryId + "\")"); + } + foldersToRecalculate.push(currentNodeRef); } } } else { + if (log.isDebugEnabled()) + { + log.debug("Current \"nodeRef\"'s PROP_INVADED_BY does not contain current 'manifestId' (name: \"" + properties.get(ContentModel.PROP_NAME) + + "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + "\", manifestId: \"" + fromRepositoryId + "\")"); + } + /** * Current node has been invaded by another repository * @@ -602,10 +716,15 @@ public class AlienProcessorImpl implements AlienProcessor */ getNodeService().hasAspect(currentNodeRef, TransferModel.ASPECT_TRANSFERRED); { - String fromRepoId = (String)getNodeService().getProperty(currentNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID); - if(fromRepositoryId.equalsIgnoreCase(fromRepoId)) + if(fromRepositoryId.equalsIgnoreCase(initialRepoId)) { - log.debug("folder is from the transferring repository"); + if (log.isDebugEnabled()) + { + log.debug("folder is from the transferring repository"); + log.debug("Current nodeRef has more than 1 element in PROP_INVADED_BY. Adding its children to 'nodesToPrune' list... (name: \"" + + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + + "\", manifestId: \"" + fromRepositoryId + "\")"); + } // invaded from somewhere else - so it must be a folder List refs = getNodeService().getChildAssocs(currentNodeRef); for(ChildAssociationRef ref : refs) @@ -621,6 +740,13 @@ public class AlienProcessorImpl implements AlienProcessor */ if(!foldersToRecalculate.contains(currentNodeRef)) { + if (log.isDebugEnabled()) + { + log.debug("Current 'nodeRef' is not in 'foldersToRecalculate' list. Adding it to the list... (name: \"" + + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + + "\", manifestId: \"" + fromRepositoryId + "\")"); + } + foldersToRecalculate.push(currentNodeRef); } } @@ -633,11 +759,24 @@ public class AlienProcessorImpl implements AlienProcessor // Current node does not contain alien nodes so it can be deleted. getNodeService().hasAspect(currentNodeRef, TransferModel.ASPECT_TRANSFERRED); { - String fromRepoId = (String)getNodeService().getProperty(currentNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID); - if(fromRepositoryId.equalsIgnoreCase(fromRepoId)) + if (log.isDebugEnabled()) { - // we are invaded by a single repository - log.debug("pruned - deleted non alien node:" + currentNodeRef); + log.debug("Current 'nodeRef' does not have ASPECT_ALIEN (name: \"" + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + "\", manifestId: \"" + fromRepositoryId + "\")"); + } + + String initialRepoId = (String) getNodeService().getProperty(currentNodeRef, TransferModel.PROP_REPOSITORY_ID); + if(fromRepositoryId.equalsIgnoreCase(initialRepoId)) + { + if (log.isDebugEnabled()) + { + log.debug("Current \"nodeRef\"'s has PROP_FROM_REPOSITORY_ID equal to current 'manifestId'. Deleting the node... (name: \"" + + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + + "\", manifestId: \"" + fromRepositoryId + "\")"); + // we are invaded by a single repository + log.debug("pruned - deleted non alien node:" + currentNodeRef); + } + getNodeService().deleteNode(currentNodeRef); } } @@ -745,44 +884,97 @@ public class AlienProcessorImpl implements AlienProcessor */ private boolean recalcInvasion(NodeRef folderNodeRef, String fromRepositoryId) { - ListfolderInvadedBy = (List)nodeService.getProperty(folderNodeRef, TransferModel.PROP_INVADED_BY); - + if (log.isTraceEnabled()) + { + log.trace("#################"); + log.trace("#RECALC INVASION#"); + log.trace("#################"); + } + + List folderInvadedBy = (List)nodeService.getProperty(folderNodeRef, TransferModel.PROP_INVADED_BY); + + if (log.isDebugEnabled()) + { + log.debug("Node(" + nodeService.getProperty(folderNodeRef, ContentModel.PROP_NAME) + ")" + folderInvadedBy + ": checking '" + fromRepositoryId + "' id..."); + } + boolean stillInvaded = false; - + boolean hasAlienChild = false; + //TODO need a more efficient query here List refs = nodeService.getChildAssocs(folderNodeRef); - for(ChildAssociationRef ref : refs) + + if (log.isDebugEnabled()) + { + log.debug("Children count: " + refs.size()); + log.debug("Is alien: " + nodeService.hasAspect(folderNodeRef, TransferModel.ASPECT_ALIEN)); + } + + String parentRepositoryId = (String) nodeService.getProperty(folderNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID); + for (ChildAssociationRef ref : refs) { NodeRef childNode = ref.getChildRef(); - ListchildInvadedBy = (List)getNodeService().getProperty(childNode, TransferModel.PROP_INVADED_BY); - - if(childInvadedBy != null && childInvadedBy.contains(fromRepositoryId)) + + if (log.isTraceEnabled()) { - log.debug("folder is still invaded"); + logInvasionHierarchy(folderNodeRef, childNode); + } + + Map properties = nodeService.getProperties(childNode); + List childInvadedBy = (List) properties.get(TransferModel.PROP_INVADED_BY); + String childRepositoryId = (String) properties.get(TransferModel.PROP_FROM_REPOSITORY_ID); + + hasAlienChild = hasAlienChild || parentRepositoryId.equalsIgnoreCase(childRepositoryId); + + if (!stillInvaded && (null != childInvadedBy) && (childInvadedBy.contains(fromRepositoryId) || fromRepositoryId.equalsIgnoreCase(childRepositoryId))) + { + if (log.isDebugEnabled()) + { + log.debug("This child contains current 'fromRepositoryId'. Current folder is still invaded by this repository"); + } + stillInvaded = true; - break; } } - - if(!stillInvaded) + + if (!stillInvaded) { - log.debug("folder is no longer invaded by this repo:" + folderNodeRef); - folderInvadedBy.remove(fromRepositoryId); - if(folderInvadedBy.size() > 0) + if (log.isDebugEnabled()) { - if(log.isDebugEnabled()) + log.debug("Current folder is not invaded by this repository. Updating 'invadedBy' property..."); + log.debug("folder is no longer invaded by this repo:" + folderNodeRef); + } + + folderInvadedBy.remove(fromRepositoryId); + if (folderInvadedBy.size() > 0) + { + if (log.isDebugEnabled()) { + log.debug("Current folder HAS ANOTHER invasions. Updating the 'invadedBy' property..."); log.debug("still invaded by:" + folderInvadedBy); } - getNodeService().setProperty(folderNodeRef, TransferModel.PROP_INVADED_BY, (Serializable)folderInvadedBy); + + getNodeService().setProperty(folderNodeRef, TransferModel.PROP_INVADED_BY, (Serializable) folderInvadedBy); } - else + else if (!hasAlienChild) { - log.debug("no longer alien:" + folderNodeRef); + if (log.isDebugEnabled()) + { + log.debug("no longer alien:" + folderNodeRef); + log.debug("This invasion was the last one for the current folder. Removing aspect 'ALIEN' completely..."); + } + getNodeService().removeAspect(folderNodeRef, TransferModel.ASPECT_ALIEN); } } - + + if (log.isTraceEnabled()) + { + log.trace("#################"); + log.trace("# COMPLETED #"); + log.trace("#################"); + } + return stillInvaded; } diff --git a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java index 281bbcd52b..186f7f6561 100644 --- a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java +++ b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java @@ -215,6 +215,12 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB // Does a corresponding node exist in this repo? if (resolvedNodes.resolvedChild != null) { + if (log.isTraceEnabled()) + { + log.trace("REPO_PRIMARY_MANIFEST_PROCESSOR - node DOES exist!"); + logInvasionHierarchy(resolvedNodes.resolvedParent, resolvedNodes.resolvedChild, nodeService, log); + } + // Yes, the corresponding node does exist. Update it. if (log.isDebugEnabled()) { @@ -222,6 +228,11 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB + resolvedNodes.resolvedChild); } update(node, resolvedNodes, primaryParentAssoc); + + if (log.isTraceEnabled()) + { + log.trace("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); + } } else { @@ -245,7 +256,19 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB { log.debug("Incoming noderef has no corresponding local noderef: " + node.getNodeRef()); } + + if (log.isTraceEnabled()) + { + log.trace("REPO_PRIMARY_MANIFEST_PROCESSOR - node DOES NOT esist yet! Name: '" + node.getProperties().get(ContentModel.PROP_NAME) + "', parentPath: '" + + node.getParentPath() + "'"); + } + create(node, resolvedNodes, primaryParentAssoc); + + if (log.isTraceEnabled()) + { + log.trace("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); + } } } diff --git a/source/java/org/alfresco/repo/transfer/RepoTertiaryManifestProcessorImpl.java b/source/java/org/alfresco/repo/transfer/RepoTertiaryManifestProcessorImpl.java index eb953263f6..0bc435503b 100644 --- a/source/java/org/alfresco/repo/transfer/RepoTertiaryManifestProcessorImpl.java +++ b/source/java/org/alfresco/repo/transfer/RepoTertiaryManifestProcessorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 Alfresco Software Limited. + * Copyright (C) 2009-2015 Alfresco Software Limited. * * This file is part of Alfresco * @@ -16,18 +16,21 @@ * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ - package org.alfresco.repo.transfer; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import org.alfresco.repo.transfer.CorrespondingNodeResolver.ResolvedParentChildPair; import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode; import org.alfresco.repo.transfer.manifest.TransferManifestHeader; import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.cmr.transfer.TransferReceiver; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -102,16 +105,90 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor //TODO Use more efficient query here. List expectedChildren = node.getChildAssocs(); - + + if (log.isDebugEnabled()) + { + log.debug("Checking node in TERTIARY_MANIFEST_PROCESSOR"); + } + + if ((null != resolvedNodes.resolvedParent) && nodeService.exists(resolvedNodes.resolvedParent)) + { + if (log.isTraceEnabled()) + { + logInvasionHierarchy(resolvedNodes.resolvedParent, nodeRef, nodeService, log); + } + } + else + { + List parentAssocs = nodeService.getParentAssocs(nodeRef); + + if (log.isTraceEnabled()) + { + logInvasionHierarchy(parentAssocs.iterator().next().getParentRef(), nodeRef, nodeService, log); + } + } + List expectedChildNodeRefs = new ArrayList(); - + Set expectedChildNodePaths = new HashSet(); + + if (log.isDebugEnabled()) + { + log.debug("Expected children:"); + } + for(ChildAssociationRef ref : expectedChildren) { if(log.isDebugEnabled()) { - log.debug("expecting child node" + ref); + log.debug("Expecting child node " + ref); + } + + NodeRef childRef = null; + if (nodeService.exists(ref.getChildRef())) + { + childRef = ref.getChildRef(); + + if (log.isTraceEnabled()) + { + logInvasionHierarchy(nodeRef, ref.getChildRef(), nodeService, log); + } + } + else + { + Path parentPath = node.getParentPath(); + parentPath = parentPath.subPath(0, (parentPath.size() - 1)); + parentPath.append(new Path.ChildAssocElement(ref)); + ResolvedParentChildPair resolvedChild = nodeResolver.resolveCorrespondingNode(ref.getChildRef(), ref, parentPath); + + if (null != resolvedChild.resolvedChild) + { + childRef = resolvedChild.resolvedChild; + + if (log.isDebugEnabled()) + { + log.debug("The node has been RESOLVED!"); + } + + if (log.isTraceEnabled()) + { + logInvasionHierarchy(resolvedChild.resolvedParent, resolvedChild.resolvedChild, nodeService, log); + } + } + else + { + if (log.isDebugEnabled()) + { + log.debug("The node DOES NOT exist in current repository! Processing will be made by its PATH!"); + } + + expectedChildNodePaths.add(parentPath); + } + } + + if (null != childRef) + { + expectedChildNodeRefs.add(childRef); } - expectedChildNodeRefs.add(ref.getChildRef()); } List actualChildren = nodeService.getChildAssocs(nodeRef); @@ -119,19 +196,35 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor /** * For each actual child association */ + if (log.isDebugEnabled()) + { + log.debug("Traversing ACTUAL children:"); + } + for(ChildAssociationRef child : actualChildren) { log.debug("checking child: " + child); if(child.isPrimary()) { + if (log.isTraceEnabled()) + { + logInvasionHierarchy(child.getParentRef(), child.getChildRef(), nodeService, log); + } + /** * yes it is a primary assoc * should it be there ? */ NodeRef childNodeRef = child.getChildRef(); - - if(!expectedChildNodeRefs.contains(childNodeRef)) + Path actualChildPath = nodeService.getPath(childNodeRef); + + if(!expectedChildNodeRefs.contains(childNodeRef) && !expectedChildNodePaths.contains(actualChildPath)) { + if (log.isDebugEnabled()) + { + log.debug("This child IS NOT EXPECTED!"); + } + /** * An unexpected child - if this node has been transferred then * it may need to be deleted. @@ -143,10 +236,16 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor { log.debug("an unexpected transferred child node:" + child); logComment("Transfer sync mode - checking unexpected child node:" + child); - String fromRepositoryId = (String)nodeService.getProperty(childNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID); + String fromRepositoryId = (String) nodeService.getProperty(childNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID); // Yes this is a transferred node. When syncing we only delete nodes that are "from" // the system that is transferring to this repo. + + if (log.isDebugEnabled()) + { + log.debug("'manifestRepositoryId': " + manifestRepositoryId); + } + if(fromRepositoryId != null && manifestRepositoryId != null) { if(nodeService.hasAspect(childNodeRef, TransferModel.ASPECT_ALIEN)) @@ -157,19 +256,36 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor */ log.debug("node to be deleted contains alien content so needs to be pruned." + childNodeRef); logComment("Transfer sync mode - node contains alien content so can't be deleted. " + childNodeRef); - alienProcessor.pruneNode(childNodeRef, fromRepositoryId); + alienProcessor.pruneNode(childNodeRef, manifestRepositoryId); } else { - // Node - log.debug("node not alien"); - if(manifestRepositoryId.equalsIgnoreCase(fromRepositoryId)) + // Node + if (log.isDebugEnabled()) { + log.debug("Node not alien. Trying to delete the node..."); + } + + String initialRepositoryId = (String) nodeService.getProperty(childNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID); + + if(manifestRepositoryId.equalsIgnoreCase(initialRepositoryId)) + { + if (log.isDebugEnabled()) + { + log.debug("Replication is initiated from the same repository from which this node was transferred! Deleting"); + } // Yes the manifest repository Id and the from repository Id match. // Destination node if from the transferring repo and needs to be deleted. logDeleted(node.getNodeRef(), childNodeRef, nodeService.getPath(childNodeRef).toString()); nodeService.deleteNode(childNodeRef); - log.debug("deleted node:" + childNodeRef); + } + else + { + if (log.isDebugEnabled()) + { + log + .debug("It is not an alien, but 'fromRepositoryId' is not equal to the 'manifestRepositoryId'! Cannot delete the foreign node..."); + } } } }