diff --git a/source/java/org/alfresco/email/server/AliasableAspectCopyBehaviourCallback.java b/source/java/org/alfresco/email/server/AliasableAspectCopyBehaviourCallback.java new file mode 100644 index 0000000000..855678929f --- /dev/null +++ b/source/java/org/alfresco/email/server/AliasableAspectCopyBehaviourCallback.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012-2012 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.email.server; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Map; + +import org.alfresco.repo.copy.CopyBehaviourCallback; +import org.alfresco.repo.copy.CopyDetails; +import org.alfresco.repo.copy.DefaultCopyBehaviourCallback; +import org.alfresco.service.namespace.QName; + +public class AliasableAspectCopyBehaviourCallback extends DefaultCopyBehaviourCallback +{ + static final CopyBehaviourCallback INSTANCE = new AliasableAspectCopyBehaviourCallback(); + + /** + * Disallows copying of the {@link ASPECT_ALIASABLE aspect. + */ + @Override + public boolean getMustCopy(QName classQName, CopyDetails copyDetails) + { + if (classQName.equals(EmailServerModel.ASPECT_ALIASABLE)) + { + return false; + } + else + { + return true; + } + } + + /** + * Prevents copying off the {@link ContentModel#PROP_NAME cm:name} property. + */ + @Override + public Map getCopyProperties( + QName classQName, + CopyDetails copyDetails, + Map properties) + { + if (classQName.equals(EmailServerModel.ASPECT_ALIASABLE)) + { + return Collections.emptyMap(); + } + return properties; + } +} + + diff --git a/source/java/org/alfresco/repo/admin/patch/impl/AliasableAspectPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/AliasableAspectPatch.java new file mode 100644 index 0000000000..ae1a15ec1a --- /dev/null +++ b/source/java/org/alfresco/repo/admin/patch/impl/AliasableAspectPatch.java @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2005-2010 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.admin.patch.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.alfresco.email.server.AliasableAspect; +import org.alfresco.email.server.EmailServerModel; +import org.alfresco.repo.admin.patch.AbstractPatch; +import org.alfresco.repo.batch.BatchProcessWorkProvider; +import org.alfresco.repo.batch.BatchProcessor; +import org.alfresco.repo.batch.BatchProcessor.BatchProcessWorker; +import org.alfresco.repo.domain.node.NodeDAO; +import org.alfresco.repo.domain.patch.PatchDAO; +import org.alfresco.repo.domain.qname.QNameDAO; +import org.alfresco.repo.policy.BehaviourFilter; +import org.alfresco.service.cmr.attributes.AttributeService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Patch to duplicate the AliasableAspect into the attributes service. + * + * Inbound email. + * + * @author mrogers + * + */ +public class AliasableAspectPatch extends AbstractPatch +{ + private static final String MSG_SUCCESS = "patch.emailAliasableAspect.result"; + + private AttributeService attributeService; + private NodeDAO nodeDAO; + private PatchDAO patchDAO; + private QNameDAO qnameDAO; + private BehaviourFilter behaviourFilter; + + private final int batchThreads = 3; + private final int batchSize = 40; + private final long count = batchThreads * batchSize; + + private static Log logger = LogFactory.getLog(AliasableAspectPatch.class); + + + @Override + protected String applyInternal() throws Exception + { + BatchProcessWorkProvider workProvider = new BatchProcessWorkProvider() + { + final List result = new ArrayList(); + + Long aspectQNameId = 0L; + long maxNodeId = getPatchDAO().getMaxAdmNodeID(); + + long minSearchNodeId = 1; + long maxSearchNodeId = count; + + Pair val = getQnameDAO().getQName(EmailServerModel.ASPECT_ALIASABLE ); + + public int getTotalEstimatedWorkSize() + { + return result.size(); + } + + public Collection getNextWork() + { + if(val != null) + { + Long aspectQNameId = val.getFirst(); + + result.clear(); + + while (result.isEmpty() && minSearchNodeId < maxNodeId) + { + List nodeids = getPatchDAO().getNodesByAspectQNameId(aspectQNameId, minSearchNodeId, maxSearchNodeId); + + for(Long nodeid : nodeids) + { + NodeRef.Status status = getNodeDAO().getNodeIdStatus(nodeid); + if(!status.isDeleted()) + { + result.add(status.getNodeRef()); + } + } + minSearchNodeId = minSearchNodeId + count; + maxSearchNodeId = maxSearchNodeId + count; + } + } + + return result; + } + }; + + BatchProcessor batchProcessor = new BatchProcessor( + "AliasableAspectPatch", + transactionService.getRetryingTransactionHelper(), + workProvider, + batchThreads, + batchSize, + applicationEventPublisher, + logger, + 1000); + + BatchProcessWorker worker = new BatchProcessWorker() + { + + public void afterProcess() throws Throwable + { + } + + public void beforeProcess() throws Throwable + { + } + + public String getIdentifier(NodeRef entry) + { + return entry.toString(); + } + + public void process(NodeRef entry) throws Throwable + { + String alias = (String)nodeService.getProperty(entry, EmailServerModel.PROP_ALIAS); + if(alias != null) + { + NodeRef existing = (NodeRef) getAttributeService().getAttribute(AliasableAspect.ALIASABLE_ATTRIBUTE_KEY_1, + AliasableAspect.ALIASABLE_ATTRIBUTE_KEY_2, + AliasableAspect.normaliseAlias(alias)); + + if(existing != null) + { + if(!existing.equals(entry)) + { + // alias is used by more than one node - warning of some sort? + if(logger.isWarnEnabled()) + { + logger.warn("Email alias is not unique, alias:" + alias + " nodeRef:" + entry); + } + + try + { + behaviourFilter.disableBehaviour(EmailServerModel.ASPECT_ALIASABLE); + nodeService.removeAspect(entry, EmailServerModel.ASPECT_ALIASABLE); + + } + finally + { + behaviourFilter.enableBehaviour(EmailServerModel.ASPECT_ALIASABLE); + } + } + + // else do nothing - attribute already exists. + } + else + { + if(logger.isDebugEnabled()) + { + logger.debug("creating email alias attribute for " + alias); + } + getAttributeService().createAttribute(entry, AliasableAspect.ALIASABLE_ATTRIBUTE_KEY_1, AliasableAspect.ALIASABLE_ATTRIBUTE_KEY_2, AliasableAspect.normaliseAlias(alias)); + } + } + } + + }; + + // Now set the batch processor to work + + batchProcessor.process(worker, true); + + return MSG_SUCCESS; + } + + + public void setAttributeService(AttributeService attributeService) + { + this.attributeService = attributeService; + } + + + public AttributeService getAttributeService() + { + return attributeService; + } + + + public void setNodeDAO(NodeDAO nodeDAO) + { + this.nodeDAO = nodeDAO; + } + + + public NodeDAO getNodeDAO() + { + return nodeDAO; + } + + + public void setPatchDAO(PatchDAO patchDAO) + { + this.patchDAO = patchDAO; + } + + + public PatchDAO getPatchDAO() + { + return patchDAO; + } + + + public void setQnameDAO(QNameDAO qnameDAO) + { + this.qnameDAO = qnameDAO; + } + + + public QNameDAO getQnameDAO() + { + return qnameDAO; + } + + + public void setBehaviourFilter(BehaviourFilter behaviourFilter) + { + this.behaviourFilter = behaviourFilter; + } + + + public BehaviourFilter getBehaviourFilter() + { + return behaviourFilter; + } + + +}