From 29e3335cad8af6d75df03705bdb01ee5cff741c1 Mon Sep 17 00:00:00 2001 From: Britt Park Date: Fri, 2 Feb 2007 16:11:28 +0000 Subject: [PATCH] Added a cross repository copy service. It has a single method copy, which does a recursive copy of the source node into the destination node. This is a checkpoint; only AVM to AVM and Repo to AVM work so far. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5019 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/public-services-context.xml | 50 ++++ .../org/alfresco/repo/avm/AVMServiceTest.java | 11 + .../copy/CrossRepositoryCopyServiceImpl.java | 249 ++++++++++++++++++ .../CrossRepositoryCopyService.java | 21 ++ 4 files changed, 331 insertions(+) create mode 100644 source/java/org/alfresco/repo/copy/CrossRepositoryCopyServiceImpl.java create mode 100644 source/java/org/alfresco/service/cmr/repository/CrossRepositoryCopyService.java diff --git a/config/alfresco/public-services-context.xml b/config/alfresco/public-services-context.xml index a830294e78..cf793d3ad6 100644 --- a/config/alfresco/public-services-context.xml +++ b/config/alfresco/public-services-context.xml @@ -958,6 +958,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + copy + + + + + + + + org.alfresco.service.cmr.repository.CrossRepositoryCopyService + + + + crossRepositoryCopyService + + + + crossRepositoryCopyServiceWriteTxnAdvisor + + + + diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java index 81b7e2142e..ad6d64656a 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java @@ -42,6 +42,7 @@ import org.alfresco.repo.avm.actions.SimpleAVMPromoteAction; import org.alfresco.repo.avm.actions.SimpleAVMSubmitAction; import org.alfresco.repo.avm.util.BulkLoader; import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.repo.remote.RepoRemoteService; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.TransactionUtil; import org.alfresco.service.cmr.avm.AVMBadArgumentException; @@ -56,6 +57,9 @@ import org.alfresco.service.cmr.avm.VersionDescriptor; import org.alfresco.service.cmr.avmsync.AVMDifference; import org.alfresco.service.cmr.avmsync.AVMSyncException; import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.remote.RepoRemote; +import org.alfresco.service.cmr.repository.CrossRepositoryCopyService; +import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.PermissionService; @@ -226,6 +230,13 @@ public class AVMServiceTest extends AVMServiceTestBase { // This is a success. } + CrossRepositoryCopyService copyService = (CrossRepositoryCopyService)fContext.getBean("CrossRepositoryCopyService"); + RepoRemote remoteService = (RepoRemote)fContext.getBean("RepoRemoteService"); + Pair toCopy = remoteService.lookup(remoteService.getRoot(), "Guest Home"); + copyService.copy(toCopy.getFirst(), AVMNodeConverter.ToNodeRef(-1, "main:/"), "Guest Home"); + desc = fService.lookup(-1, "main:/Guest Home"); + assertTrue(desc.isDirectory()); + System.out.println(this.recursiveList("main", -1, true)); } catch (Exception e) { diff --git a/source/java/org/alfresco/repo/copy/CrossRepositoryCopyServiceImpl.java b/source/java/org/alfresco/repo/copy/CrossRepositoryCopyServiceImpl.java new file mode 100644 index 0000000000..25ee1454c8 --- /dev/null +++ b/source/java/org/alfresco/repo/copy/CrossRepositoryCopyServiceImpl.java @@ -0,0 +1,249 @@ +/** + * + */ +package org.alfresco.repo.copy; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.CopyService; +import org.alfresco.service.cmr.repository.CrossRepositoryCopyService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; + +/** + * Cross Repository Copying. + * @author britt + */ +public class CrossRepositoryCopyServiceImpl implements + CrossRepositoryCopyService +{ + /** + * The NodeService reference. + */ + private NodeService fNodeService; + + /** + * The FileFolderService reference. + */ + private FileFolderService fFileFolderService; + + /** + * The regular CopyService reference. + */ + private CopyService fCopyService; + + /** + * The AVMService. + */ + private AVMService fAVMService; + + /** + * The ContentService. + */ + private ContentService fContentService; + + /** + * The DictionaryService. + */ + private DictionaryService fDictionaryService; + + /** + * A default constructor. + */ + public CrossRepositoryCopyServiceImpl() + { + } + + // Setters for Spring. + + public void setAvmService(AVMService service) + { + fAVMService = service; + } + + public void setContentService(ContentService service) + { + fContentService = service; + } + + public void setCopyService(CopyService service) + { + fCopyService = service; + } + + public void setDictionaryService(DictionaryService service) + { + fDictionaryService = service; + } + + public void setFileFolderService(FileFolderService service) + { + fFileFolderService = service; + } + + public void setNodeService(NodeService service) + { + fNodeService = service; + } + + /** + * This copies recursively src, which may be a container or a content type + * to dst, which must be a container. Copied nodes will have the copied from aspect + * applied to them. + * @param src The node to copy. + * @param dst The container to copy it into. + * @param name The name to give the copy. + */ + public void copy(NodeRef src, NodeRef dst, String name) + { + StoreRef srcStoreRef = src.getStoreRef(); + StoreRef dstStoreRef = dst.getStoreRef(); + if (srcStoreRef.getProtocol().equals("avm")) + { + if (dstStoreRef.getProtocol().equals("avm")) + { + copyAVMToAVM(src, dst, name); + } + else + { + copyAVMToRepo(src, dst, name); + } + } + else + { + if (dstStoreRef.getProtocol().equals("avm")) + { + copyRepoToAVM(src, dst, name); + } + else + { + copyRepoToRepo(src, dst, name); + } + } + } + + /** + * Handle copying from AVM to AVM + * @param src Source node. + * @param dst Destination directory node. + * @param name Name to give copy. + */ + private void copyAVMToAVM(NodeRef src, NodeRef dst, String name) + { + Pair srcStorePath = AVMNodeConverter.ToAVMVersionPath(src); + Pair dstStorePath = AVMNodeConverter.ToAVMVersionPath(dst); + fAVMService.copy(srcStorePath.getFirst(), srcStorePath.getSecond(), + dstStorePath.getSecond(), name); + } + + /** + * Handle copying from AVM to Repo. + * @param src Source node. + * @param dst Destination Container. + * @param name The name to give the copy. + */ + private void copyAVMToRepo(NodeRef src, NodeRef dst, String name) + { + } + + /** + * Handle copying from Repo to AVM. + * @param src The source node. + * @param dst The destingation directory. + * @param name The name to give the copy. + */ + private void copyRepoToAVM(NodeRef src, NodeRef dst, String name) + { + QName srcType = fNodeService.getType(src); + Pair versionPath = AVMNodeConverter.ToAVMVersionPath(dst); + String childPath = AVMNodeConverter.ExtendAVMPath(versionPath.getSecond(), name); + NodeRef childNodeRef = AVMNodeConverter.ToNodeRef(-1, childPath); + if (fDictionaryService.isSubClass(srcType, ContentModel.TYPE_CONTENT)) + { + InputStream in = fContentService.getReader(src, ContentModel.PROP_CONTENT).getContentInputStream(); + OutputStream out = fAVMService.createFile(versionPath.getSecond(), name); + copyData(in, out); + copyPropsAndAspectsRepoToAVM(src, childNodeRef, childPath); + return; + } + if (fDictionaryService.isSubClass(srcType, ContentModel.TYPE_FOLDER)) + { + fAVMService.createDirectory(versionPath.getSecond(), name); + copyPropsAndAspectsRepoToAVM(src, childNodeRef, childPath); + List listing = fFileFolderService.list(src); + for (FileInfo info : listing) + { + copyRepoToAVM(info.getNodeRef(), childNodeRef, info.getName()); + } + return; + } + } + + /** + * Helper to copy properties and aspects. + * @param src The source node. + * @param dst The destination node. + * @param dstPath The destination AVM path. + */ + private void copyPropsAndAspectsRepoToAVM(NodeRef src, NodeRef dst, String dstPath) + { + Map props = fNodeService.getProperties(src); + fNodeService.setProperties(dst, props); + Set aspects = fNodeService.getAspects(src); + for (QName aspect : aspects) + { + fAVMService.addAspect(dstPath, aspect); + } + if (!fAVMService.hasAspect(-1, dstPath, ContentModel.ASPECT_COPIEDFROM)) + { + fAVMService.addAspect(dstPath, ContentModel.ASPECT_COPIEDFROM); + } + fNodeService.setProperty(dst, ContentModel.PROP_COPY_REFERENCE, src); + } + + /** + * Handle copying from Repo to Repo. + * @param src The source node. + * @param dst The destination container. + * @param name The name to give the copy. + */ + private void copyRepoToRepo(NodeRef src, NodeRef dst, String name) + { + } + + private void copyData(InputStream in, OutputStream out) + { + try + { + byte [] buff = new byte[8192]; + int read = 0; + while ((read = in.read(buff)) != -1) + { + out.write(buff, 0, read); + } + in.close(); + out.close(); + } + catch (IOException e) + { + throw new AlfrescoRuntimeException("I/O Error.", e); + } + } +} diff --git a/source/java/org/alfresco/service/cmr/repository/CrossRepositoryCopyService.java b/source/java/org/alfresco/service/cmr/repository/CrossRepositoryCopyService.java new file mode 100644 index 0000000000..61db5e7601 --- /dev/null +++ b/source/java/org/alfresco/service/cmr/repository/CrossRepositoryCopyService.java @@ -0,0 +1,21 @@ +/** + * + */ +package org.alfresco.service.cmr.repository; + +/** + * Simple interface for copying between the two repsitory implementations. + * @author britt + */ +public interface CrossRepositoryCopyService +{ + /** + * This copies recursively src, which may be a container or a content type + * to dst, which must be a container. Copied nodes will have the copied from aspect + * applied to them. + * @param src The node to copy. + * @param dst The container to copy it into. + * @param name The name to give the copy. + */ + public void copy(NodeRef src, NodeRef dst, String name); +}