diff --git a/config/alfresco/extension/bm-remote-loader-context.xml.sample b/config/alfresco/extension/bm-remote-loader-context.xml.sample index 69aa98ef56..50d48a5741 100644 --- a/config/alfresco/extension/bm-remote-loader-context.xml.sample +++ b/config/alfresco/extension/bm-remote-loader-context.xml.sample @@ -57,6 +57,12 @@ + + + + + + diff --git a/source/java/org/alfresco/repo/model/filefolder/loader/AbstractLoaderThread.java b/source/java/org/alfresco/repo/model/filefolder/loader/AbstractLoaderThread.java index d289e39267..8e4d72fcb9 100644 --- a/source/java/org/alfresco/repo/model/filefolder/loader/AbstractLoaderThread.java +++ b/source/java/org/alfresco/repo/model/filefolder/loader/AbstractLoaderThread.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -28,10 +28,18 @@ import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Random; +import java.util.Collections; import java.util.concurrent.atomic.AtomicBoolean; +import java.net.URL; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.model.FileExistsException; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.cache.EhCacheAdapter; +import net.sf.ehcache.CacheManager; +import net.sf.ehcache.Cache; /** * A description of what the remote loader should do. @@ -54,6 +62,19 @@ public abstract class AbstractLoaderThread extends Thread private int statCount; private double statTotalMs; + private static EhCacheAdapter pathCache; + + static + { + System.setProperty(CacheManager.ENABLE_SHUTDOWN_HOOK_PROPERTY, "TRUE"); + URL url = LoaderUploadThread.class.getResource("/org/alfresco/repo/model/filefolder/loader/loader-ehcache.xml"); + CacheManager cacheManager = new CacheManager(url); + Cache cache = cacheManager.getCache("org.alfresco.LoaderUploadThread.PathCache"); + + pathCache = new EhCacheAdapter(); + pathCache.setCache(cache); + } + public AbstractLoaderThread( LoaderSession session, String loaderName, @@ -110,6 +131,8 @@ public abstract class AbstractLoaderThread extends Thread int nodeIndex = random.nextInt(nodeCount); NodeRef workingRootNodeRef = session.getWorkingRootNodeRefs().get(nodeIndex); + this.doBefore(serverProxy, workingRootNodeRef); + long startTime = System.nanoTime(); String msg = doLoading(serverProxy, workingRootNodeRef); long endTime = System.nanoTime(); @@ -137,6 +160,7 @@ public abstract class AbstractLoaderThread extends Thread this.wait(mustWait); } } + this.doAfter(serverProxy, workingRootNodeRef); } catch (Throwable e) { @@ -238,4 +262,69 @@ public abstract class AbstractLoaderThread extends Thread } return file; } + + + /** + * Creates or find the folders based on caching. + */ + protected NodeRef makeFolders( + String ticket, + LoaderServerProxy serverProxy, + NodeRef workingRootNodeRef, + List folderPath) throws Exception + { + // Iterate down the path, checking the cache and populating it as necessary + NodeRef currentParentNodeRef = workingRootNodeRef; + String currentKey = workingRootNodeRef.toString(); + + for (String aFolderPath : folderPath) + { + currentKey += ("/" + aFolderPath); + // Is this there? + NodeRef nodeRef = pathCache.get(currentKey); + if (nodeRef != null) + { + // Found it + currentParentNodeRef = nodeRef; + // Step into the next level + continue; + } + + // It is not there, so create it + try + { + FileInfo folderInfo = serverProxy.fileFolderRemote.makeFolders( + serverProxy.ticket, + currentParentNodeRef, + Collections.singletonList(aFolderPath), + ContentModel.TYPE_FOLDER); + currentParentNodeRef = folderInfo.getNodeRef(); + } catch (FileExistsException e) + { + currentParentNodeRef = pathCache.get(currentKey); + } + + + // Cache the new node + pathCache.put(currentKey, currentParentNodeRef); + + } + // Done + return currentParentNodeRef; + } + + + /** + * Run before record stats + */ + protected void doBefore(LoaderServerProxy loaderServerProxy, NodeRef nodeRef) throws Exception + { + } + + /** + * Run after record stats + */ + protected void doAfter(LoaderServerProxy loaderServerProxy, NodeRef nodeRef) throws Exception + { + } } diff --git a/source/java/org/alfresco/repo/model/filefolder/loader/FileFolderRemoteLoader.java b/source/java/org/alfresco/repo/model/filefolder/loader/FileFolderRemoteLoader.java index a83bf1fad6..3253d694a0 100644 --- a/source/java/org/alfresco/repo/model/filefolder/loader/FileFolderRemoteLoader.java +++ b/source/java/org/alfresco/repo/model/filefolder/loader/FileFolderRemoteLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -286,7 +286,7 @@ public class FileFolderRemoteLoader long testTotal = 0L; long testDepth = 1L; boolean testVerbose = false; - long filesPerUpload = 1; + long filesPerIteration = 1; try { testCount = Long.parseLong(strValues[0]); @@ -294,13 +294,13 @@ public class FileFolderRemoteLoader testTotal = Long.parseLong(strValues[2]); testDepth = Long.parseLong(strValues[3]); testVerbose = Boolean.parseBoolean(strValues[4]); - filesPerUpload = Long.parseLong(strValues[5]); + filesPerIteration = Long.parseLong(strValues[5]); } catch (Throwable e) { throw new LoaderClientException( "Unable to parse the loader configuration for '" + name + "'. " + LoaderSession.getLineEnding() + - "The correct format is [threadCount], [period(ms)], [total], [folder depth], [verbose]<, [filesPerUpload]>"); + "The correct format is [threadCount], [period(ms)], [total], [folder depth], [verbose]<, [filesPerIteration]>"); } // Construct @@ -309,7 +309,7 @@ public class FileFolderRemoteLoader AbstractLoaderThread thread = null; if (type.equals("upload")) { - thread = new LoaderUploadThread(session, name, testPeriod, testTotal, testDepth, testVerbose, filesPerUpload); + thread = new LoaderUploadThread(session, name, testPeriod, testTotal, testDepth, testVerbose, filesPerIteration); } else if (type.equals("totals")) { @@ -318,6 +318,20 @@ public class FileFolderRemoteLoader else if (type.equals("listFolders")) { thread = new LoaderListFoldersThread(session, name, testPeriod, testTotal, testDepth, testVerbose); + + } + else if(type.equals("delete")) + { + thread = new LoaderDeleteThread(session, name, testPeriod, testTotal, testDepth, testVerbose, filesPerIteration); + } + else if(type.equals("update")) + { + thread = new LoaderUpdateThread(session, name, testPeriod, testTotal, testDepth, testVerbose, filesPerIteration); + + } + else if(type.equals("coci")) + { + thread = new LoaderCOCIThread(session, name, testPeriod, testTotal, testDepth, testVerbose, filesPerIteration); } else { diff --git a/source/java/org/alfresco/repo/model/filefolder/loader/LoaderCOCIThread.java b/source/java/org/alfresco/repo/model/filefolder/loader/LoaderCOCIThread.java new file mode 100644 index 0000000000..d38174ba0f --- /dev/null +++ b/source/java/org/alfresco/repo/model/filefolder/loader/LoaderCOCIThread.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2005-2008 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.model.filefolder.loader; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.GUID; +import org.alfresco.model.ContentModel; +import org.springframework.util.FileCopyUtils; + +import java.util.*; +import java.io.Serializable; +import java.io.File; + +/** + * Loader thread that coci documents to the remote repository. + */ + +public class LoaderCOCIThread extends AbstractLoaderThread +{ + private int filesPerIteration; + private FileInfo[] filesInfo; + + public LoaderCOCIThread(LoaderSession session, String loaderName, long testPeriod, long testTotal, long testLoadDepth, boolean verbose, long filesPerIteration) + { + super(session, loaderName, testPeriod, testTotal, testLoadDepth, verbose); + this.filesPerIteration = (int) filesPerIteration; + } + + @Override + protected String doLoading(LoaderServerProxy serverProxy, NodeRef workingRootNodeRef) throws Exception + { + + List> arrVersionProp = new ArrayList>(); + + byte[][] bytes = new byte[filesPerIteration][]; + for (int i = 0; i < filesPerIteration; i++) + { + File file = getFile(); + bytes[i] = FileCopyUtils.copyToByteArray(file); + arrVersionProp.add(new HashMap()); + } + + serverProxy.loaderRemote.coci(serverProxy.ticket, getNodesRef(filesInfo), bytes, arrVersionProp); + + return String.format("update version %d files in folder: %s", filesPerIteration, workingRootNodeRef.toString()); + } + + @Override + protected void doBefore(LoaderServerProxy loaderServerProxy, NodeRef nodeRef) throws Exception + { + // Get a random folder + List folderPath = super.chooseFolderPath(); + + //makeFolders + NodeRef folderNodeRef = makeFolders(loaderServerProxy.ticket, loaderServerProxy, nodeRef, folderPath); + + String[] fileNames = new String[filesPerIteration]; + NodeRef[] parentNodeRefs = new NodeRef[filesPerIteration]; + QName[] types = new QName[filesPerIteration]; + + // Build a set of files to coci + for (int i = 0; i < filesPerIteration; i++) + { + fileNames[i] = GUID.generate(); + parentNodeRefs[i] = folderNodeRef; + types[i] = ContentModel.TYPE_CONTENT; + } + + filesInfo = loaderServerProxy.fileFolderRemote.create(loaderServerProxy.ticket, parentNodeRefs, fileNames, types); + } + + + public String getSummary() + { + String summary = super.getSummary(); + summary += String.format("%d files per iteration", filesPerIteration); + return summary; + } + + NodeRef[] getNodesRef(FileInfo[] filesInfoList) + { + NodeRef[] nr = new NodeRef[filesInfoList.length]; + for (int i = 0; i < filesInfoList.length; i++) + { + nr[i] = (filesInfoList[i].getNodeRef()); + } + return nr; + } +} diff --git a/source/java/org/alfresco/repo/model/filefolder/loader/LoaderDeleteThread.java b/source/java/org/alfresco/repo/model/filefolder/loader/LoaderDeleteThread.java new file mode 100644 index 0000000000..490c7405da --- /dev/null +++ b/source/java/org/alfresco/repo/model/filefolder/loader/LoaderDeleteThread.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2005-2008 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.model.filefolder.loader; + +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.GUID; +import org.springframework.util.FileCopyUtils; + +import java.io.File; +import java.util.List; + +/** + * Loader thread that deletes documents to the remote repository. + */ +public class LoaderDeleteThread extends AbstractLoaderThread +{ + private FileInfo[] filesInfo; + private int filesPerIteration; + + public LoaderDeleteThread( + LoaderSession loaderSession, + String loaderName, + long testPeriod, + long testTotal, + long testLoadDepth, + boolean verbose, + long filesPerIteration) + { + super(loaderSession, loaderName, testPeriod, testTotal, testLoadDepth, verbose); + this.filesPerIteration = (int) filesPerIteration; + } + + @Override + protected String doLoading(LoaderServerProxy loaderServerProxy, NodeRef nodeRef) throws Exception + { + // Delete it + loaderServerProxy.fileFolderRemote.delete(loaderServerProxy.ticket, getNodesRef(filesInfo)); + + // Done + String msg = String.format("Deleted %d files from folder: %s", filesInfo.length, nodeRef.toString()); + + return msg; + } + + @Override + protected void doBefore(LoaderServerProxy loaderServerProxy, NodeRef workingRootNodeRef) throws Exception + { + // Get a random folder + List folderPath = super.chooseFolderPath(); + + //makeFolders + NodeRef folderNodeRef = makeFolders(loaderServerProxy.ticket, loaderServerProxy, workingRootNodeRef, folderPath); + + byte[][] bytes = new byte[filesPerIteration][]; + String[] fileNames = new String[filesPerIteration]; + NodeRef[] parentNodeRefs = new NodeRef[filesPerIteration]; + QName[] types = new QName[filesPerIteration]; + + // Build a set of files to delete + for (int i = 0; i < filesPerIteration; i++) + { + File file = getFile(); + bytes[i] = FileCopyUtils.copyToByteArray(file); + fileNames[i] = GUID.generate(); + parentNodeRefs[i] = folderNodeRef; + types[i] = ContentModel.TYPE_CONTENT; + } + + filesInfo = loaderServerProxy.fileFolderRemote.create(loaderServerProxy.ticket, parentNodeRefs, fileNames, types); + + loaderServerProxy.fileFolderRemote.putContent(loaderServerProxy.ticket, getNodesRef(filesInfo), bytes, fileNames); + } + + NodeRef[] getNodesRef(FileInfo[] filesInfoList) + { + NodeRef[] nr = new NodeRef[filesInfoList.length]; + for (int i = 0; i < filesInfoList.length; i++) + { + nr[i] = (filesInfoList[i].getNodeRef()); + } + return nr; + } + + public String getSummary() + { + String summary = super.getSummary(); + summary += (String.format("%d files per iteration", filesPerIteration)); + return summary; + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/model/filefolder/loader/LoaderUpdateThread.java b/source/java/org/alfresco/repo/model/filefolder/loader/LoaderUpdateThread.java new file mode 100644 index 0000000000..5e598fc0e2 --- /dev/null +++ b/source/java/org/alfresco/repo/model/filefolder/loader/LoaderUpdateThread.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2005-2008 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.model.filefolder.loader; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.GUID; +import org.alfresco.model.ContentModel; +import org.springframework.util.FileCopyUtils; + +import java.util.List; +import java.io.File; + +/** + * Loader thread that updates documents to the remote repository. + */ + +public class LoaderUpdateThread extends AbstractLoaderThread +{ + private FileInfo[] filesInfo; + private int filesPerIteration; + + public LoaderUpdateThread( + LoaderSession session, + String loaderName, + long testPeriod, + long testTotal, + long testLoadDepth, + boolean verbose, + long filesPerIteration) + { + super(session, loaderName, testPeriod, testTotal, testLoadDepth, verbose); + this.filesPerIteration = (int)filesPerIteration; + } + + @Override + protected void doBefore(LoaderServerProxy loaderServerProxy, NodeRef nodeRef) throws Exception + { + // Get a random folder + List folderPath = super.chooseFolderPath(); + + //makeFolders + NodeRef folderNodeRef = makeFolders(loaderServerProxy.ticket, loaderServerProxy, nodeRef, folderPath); + + String[] fileNames = new String[filesPerIteration]; + NodeRef[] pareNodeRefs = new NodeRef[filesPerIteration]; + QName[] types = new QName[filesPerIteration]; + + // Build a set of files to update + for (int i = 0; i < filesPerIteration; i++) + { + fileNames[i] = GUID.generate(); + pareNodeRefs[i] = folderNodeRef; + types[i] = ContentModel.TYPE_CONTENT; + } + filesInfo = loaderServerProxy.fileFolderRemote.create(loaderServerProxy.ticket, pareNodeRefs, fileNames, types); + } + + @Override + protected String doLoading(LoaderServerProxy loaderServerProxy, NodeRef nodeRef) throws Exception + { + byte[][] bytes = new byte[filesPerIteration][]; + String[] fileNames = new String[filesPerIteration]; + NodeRef[] nodeRefs = new NodeRef[filesPerIteration]; + + for (int i = 0; i < filesPerIteration; i++) + { + File file = getFile(); + bytes[i] = FileCopyUtils.copyToByteArray(file); + fileNames[i] = filesInfo[i].getName(); + nodeRefs[i] = filesInfo[i].getNodeRef(); + } + + //Update it + loaderServerProxy.fileFolderRemote.putContent(loaderServerProxy.ticket, nodeRefs, bytes, fileNames); + + // Done + return String.format("Updated %d files in folder: %s", filesInfo.length, nodeRef.toString()); + } + + + public String getSummary() + { + String summary = super.getSummary(); + summary += (String.format("%d files per iteration", filesPerIteration)); + return summary; + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/model/filefolder/loader/LoaderUploadThread.java b/source/java/org/alfresco/repo/model/filefolder/loader/LoaderUploadThread.java index 660b460dbe..228da24626 100644 --- a/source/java/org/alfresco/repo/model/filefolder/loader/LoaderUploadThread.java +++ b/source/java/org/alfresco/repo/model/filefolder/loader/LoaderUploadThread.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -24,21 +24,14 @@ */ package org.alfresco.repo.model.filefolder.loader; -import java.io.File; -import java.net.URL; -import java.util.Collections; -import java.util.List; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.CacheManager; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.cache.EhCacheAdapter; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.util.GUID; import org.springframework.util.FileCopyUtils; +import java.io.File; +import java.util.List; + /** * Loader thread that puts documents to the remote repository. * @@ -47,18 +40,6 @@ import org.springframework.util.FileCopyUtils; */ public class LoaderUploadThread extends AbstractLoaderThread { - private static EhCacheAdapter pathCache; - - static - { - System.setProperty(CacheManager.ENABLE_SHUTDOWN_HOOK_PROPERTY, "TRUE"); - URL url = LoaderUploadThread.class.getResource("/org/alfresco/repo/model/filefolder/loader/loader-ehcache.xml"); - CacheManager cacheManager = new CacheManager(url); - Cache cache = cacheManager.getCache("org.alfresco.LoaderUploadThread.PathCache"); - - pathCache = new EhCacheAdapter(); - pathCache.setCache(cache); - } private int filesPerUpload; @@ -75,44 +56,6 @@ public class LoaderUploadThread extends AbstractLoaderThread this.filesPerUpload = (int) filesPerUpload; } - /** - * Creates or find the folders based on caching. - */ - private NodeRef makeFolders( - String ticket, - LoaderServerProxy serverProxy, - NodeRef workingRootNodeRef, - List folderPath) throws Exception - { - // Iterate down the path, checking the cache and populating it as necessary - NodeRef currentParentNodeRef = workingRootNodeRef; - String currentKey = workingRootNodeRef.toString(); - for (String pathElement : folderPath) - { - currentKey += ("/" + pathElement); - // Is this there? - NodeRef nodeRef = pathCache.get(currentKey); - if (nodeRef != null) - { - // Found it - currentParentNodeRef = nodeRef; - // Step into the next level - continue; - } - // It is not there, so create it - FileInfo folderInfo = serverProxy.fileFolderRemote.makeFolders( - serverProxy.ticket, - currentParentNodeRef, - Collections.singletonList(pathElement), - ContentModel.TYPE_FOLDER); - currentParentNodeRef = folderInfo.getNodeRef(); - // Cache the new node - pathCache.put(currentKey, currentParentNodeRef); - } - // Done - return currentParentNodeRef; - } - @Override protected String doLoading(LoaderServerProxy serverProxy, NodeRef workingRootNodeRef) throws Exception { diff --git a/source/java/org/alfresco/repo/remote/FileFolderRemoteClient.java b/source/java/org/alfresco/repo/remote/FileFolderRemoteClient.java index a1de8781a0..d30f7bed78 100644 --- a/source/java/org/alfresco/repo/remote/FileFolderRemoteClient.java +++ b/source/java/org/alfresco/repo/remote/FileFolderRemoteClient.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -165,6 +165,13 @@ public class FileFolderRemoteClient implements FileFolderRemote return remotePeer.create(ticket, parentNodeRef, name, typeQName); } + /** + * {@inheritDoc} + */ + public FileInfo[] create(String ticket, final NodeRef[] parentNodeRefs, final String[] names, final QName[] typesQName) throws FileExistsException + { + return remotePeer.create(ticket, parentNodeRefs, names, typesQName); + } /** * {@inheritDoc} */ @@ -173,6 +180,14 @@ public class FileFolderRemoteClient implements FileFolderRemote remotePeer.delete(ticket, nodeRef); } + /** + * {@inheritDoc} + */ + public void delete(String ticket, final NodeRef[] nodeRefs) + { + remotePeer.delete(ticket, nodeRefs); + } + /** * {@inheritDoc} */ @@ -213,6 +228,14 @@ public class FileFolderRemoteClient implements FileFolderRemote return remotePeer.putContent(ticket, nodeRef, bytes, filename); } + /** + * {@inheritDoc} + */ + public ContentData[] putContent(String ticket, NodeRef nodeRefs[], byte[][] bytes, String[] filenames) + { + return remotePeer.putContent(ticket, nodeRefs, bytes, filenames); + } + /** * {@inheritDoc} */ diff --git a/source/java/org/alfresco/repo/remote/FileFolderRemoteServer.java b/source/java/org/alfresco/repo/remote/FileFolderRemoteServer.java index be8b3baf82..b1eeaa0ee8 100644 --- a/source/java/org/alfresco/repo/remote/FileFolderRemoteServer.java +++ b/source/java/org/alfresco/repo/remote/FileFolderRemoteServer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -357,6 +357,36 @@ public class FileFolderRemoteServer implements FileFolderRemote } } + /** + * {@inheritDoc} + */ + public FileInfo[] create(String ticket, final NodeRef[] parentNodeRefs, final String[] names, final QName[] typesQName) throws FileExistsException + { + AuthenticationUtil.pushAuthentication(); + try + { + authenticationService.validate(ticket); + // Make the call + RetryingTransactionCallback callback = new RetryingTransactionCallback() + { + public FileInfo[] execute() throws Throwable + { + FileInfo[] result = new FileInfo[parentNodeRefs.length]; + for (int i = 0; i< result.length; i++) + { + result[i] = fileFolderService.create(parentNodeRefs[i], names[i], typesQName[i]); + } + return result; + } + }; + return retryingTransactionHelper.doInTransaction(callback, false, true); + } + finally + { + AuthenticationUtil.popAuthentication(); + } + } + /** * {@inheritDoc} */ @@ -383,6 +413,33 @@ public class FileFolderRemoteServer implements FileFolderRemote } } + /** + * {@inheritDoc} + */ + public void delete(String ticket, final NodeRef[] nodeRefs) + { + AuthenticationUtil.pushAuthentication(); + try + { + authenticationService.validate(ticket); + // Make the call + RetryingTransactionCallback callback = new RetryingTransactionCallback() + { + public Object execute() throws Throwable + { + for (NodeRef nodeRef : nodeRefs) + fileFolderService.delete(nodeRef); + return null; + } + }; + retryingTransactionHelper.doInTransaction(callback, false, true); + } + finally + { + AuthenticationUtil.popAuthentication(); + } + } + /** * {@inheritDoc} */ @@ -532,6 +589,62 @@ public class FileFolderRemoteServer implements FileFolderRemote } } + /** + * {@inheritDoc} + */ + public ContentData[] putContent( + String ticket, + final NodeRef[] nodeRefs, + final byte[][] bytes, + final String[] filenames) + { + AuthenticationUtil.pushAuthentication(); + try + { + authenticationService.validate(ticket); + // Make the call + RetryingTransactionCallback callback = new RetryingTransactionCallback() + { + public ContentData[] execute() throws Throwable + { + // Guess the mimetype + ContentData[] results = new ContentData[filenames.length]; + + for (int i = 0; i < filenames.length; i++) + { + + String mimetype = mimetypeService.guessMimetype(filenames[i]); + + // Get a writer + ContentWriter writer = fileFolderService.getWriter(nodeRefs[i]); + // Make a stream + ByteArrayInputStream is = new ByteArrayInputStream(bytes[i]); + // Guess the encoding + ContentCharsetFinder charsetFinder = mimetypeService.getContentCharsetFinder(); + Charset charset = charsetFinder.getCharset(is, mimetype); + // Set metadata + writer.setEncoding(charset.name()); + writer.setMimetype(mimetype); + + // Write the stream + writer.putContent(is); + results[i] = writer.getContentData(); + } + // Done + return results; + } + }; + ContentData[] contentData = retryingTransactionHelper.doInTransaction(callback, false, true); + // Done + return contentData; + } + finally + { + AuthenticationUtil.popAuthentication(); + } + } + + /** * {@inheritDoc} */ diff --git a/source/java/org/alfresco/repo/remote/LoaderRemoteServer.java b/source/java/org/alfresco/repo/remote/LoaderRemoteServer.java index 9777ce495a..57c1f4858f 100644 --- a/source/java/org/alfresco/repo/remote/LoaderRemoteServer.java +++ b/source/java/org/alfresco/repo/remote/LoaderRemoteServer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -24,25 +24,18 @@ */ package org.alfresco.repo.remote; -import java.io.ByteArrayInputStream; -import java.nio.charset.Charset; -import java.util.List; - import org.alfresco.model.ContentModel; import org.alfresco.repo.content.encoding.ContentCharsetFinder; import org.alfresco.repo.node.db.NodeDaoService; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.remote.FileFolderRemote; import org.alfresco.service.cmr.remote.LoaderRemote; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.ContentWriter; -import org.alfresco.service.cmr.repository.MimetypeService; -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.cmr.repository.*; import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -51,6 +44,13 @@ import org.alfresco.util.PropertyMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import java.io.ByteArrayInputStream; +import java.io.Serializable; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Server side implementation of the LoaderServiceTransport transport * layer. This is the class that gets exported remotely as it contains the @@ -73,7 +73,9 @@ public class LoaderRemoteServer implements LoaderRemote private NodeService nodeService; private NodeDaoService nodeDaoService; private FileFolderService fileFolderService; + private FileFolderRemote fileFolderRemote; private MimetypeService mimetypeService; + private CheckOutCheckInService checkOutCheckInService; /** * @param transactionService provides transactional support and retrying @@ -115,6 +117,11 @@ public class LoaderRemoteServer implements LoaderRemote this.fileFolderService = fileFolderService; } + public void setFileFolderRemote(FileFolderRemote fileFolderRemote) + { + this.fileFolderRemote = fileFolderRemote; + } + /** * @param mimetypeService used to determine encoding, etc */ @@ -123,6 +130,11 @@ public class LoaderRemoteServer implements LoaderRemote this.mimetypeService = mimetypeService; } + public void setCheckOutCheckInService(CheckOutCheckInService checkOutCheckInService) + { + this.checkOutCheckInService = checkOutCheckInService; + } + /** * {@inheritDoc} */ @@ -285,4 +297,154 @@ public class LoaderRemoteServer implements LoaderRemote AuthenticationUtil.popAuthentication(); } } + + /** + * {@inheritDoc} + */ + public void coci(String ticket, final NodeRef[] nodeRef, byte[][] bytes, List> versionProperties) + { + FileInfo[] workingCopy = checkout(ticket, nodeRef); + String[] fna = new String[bytes.length]; + for (int i = 0; i < workingCopy.length; i++) + { + fna[i] = workingCopy[i].getName(); + versionProperties.add(new HashMap()); + } + fileFolderRemote.putContent(ticket, getNodesRef(workingCopy), bytes, fna); + checkin(ticket, getNodesRef(workingCopy), versionProperties); + } + + NodeRef[] getNodesRef(FileInfo[] filesInfoList) + { + NodeRef[] nr = new NodeRef[filesInfoList.length]; + for (int i = 0; i < filesInfoList.length; i++) + { + nr[i] = (filesInfoList[i].getNodeRef()); + } + return nr; + } + + /** + * {@inheritDoc} + */ + public NodeRef checkout(String ticket,final NodeRef nodeRef) + { + + AuthenticationUtil.pushAuthentication(); + try + { + authenticationService.validate(ticket); + RetryingTransactionCallback callback = new RetryingTransactionCallback() + { + public NodeRef execute() throws Throwable + { + //check out current document + return checkOutCheckInService.checkout(nodeRef); + } + + }; + return retryingTransactionHelper.doInTransaction(callback, false, true); + + } + finally + { + AuthenticationUtil.popAuthentication(); + } + } + + /** + * {@inheritDoc} + */ + public FileInfo[] checkout(String ticket, final NodeRef[] nodeRef) + { + AuthenticationUtil.pushAuthentication(); + try + { + authenticationService.validate(ticket); + RetryingTransactionCallback callback = new RetryingTransactionCallback() + { + public FileInfo[] execute() throws Throwable + { + FileInfo[] arr = new FileInfo[nodeRef.length]; + + for(int i = 0; i < nodeRef.length; i++) + { + //check out current document + arr[i] = fileFolderService.getFileInfo(checkOutCheckInService.checkout(nodeRef[i])); + } + //Done + return arr; + } + + }; + return retryingTransactionHelper.doInTransaction(callback, false, true); + + } + finally + { + AuthenticationUtil.popAuthentication(); + } + } + + /** + * {@inheritDoc} + */ + public NodeRef checkin(String ticket, + final NodeRef workingCopyNodeRef, + final Map versionProperties) + { + AuthenticationUtil.pushAuthentication(); + try + { + authenticationService.validate(ticket); + RetryingTransactionCallback callback = new RetryingTransactionCallback() + { + public NodeRef execute() throws Throwable + { + //check in current document + return checkOutCheckInService.checkin(workingCopyNodeRef,versionProperties); + } + }; + return retryingTransactionHelper.doInTransaction(callback, false, true); + } + finally + { + AuthenticationUtil.popAuthentication(); + } + } + + /** + * {@inheritDoc} + */ + public NodeRef [] checkin(String ticket, final NodeRef [] workingCopyNodeRef, + final List> versionProperties) + { + AuthenticationUtil.pushAuthentication(); + + try + { + authenticationService.validate(ticket); + RetryingTransactionCallback callback = new RetryingTransactionCallback() + { + public NodeRef [] execute() throws Throwable + { + NodeRef [] nr = new NodeRef[workingCopyNodeRef.length]; + for(int i = 0; i < workingCopyNodeRef.length;i++) + { + //check in current document + nr[i] = checkOutCheckInService.checkin(workingCopyNodeRef[i],versionProperties.get(i)); + } + //Done + return nr; + } + + }; + return retryingTransactionHelper.doInTransaction(callback, false, true); + + } + finally + { + AuthenticationUtil.popAuthentication(); + } + } } diff --git a/source/java/org/alfresco/service/cmr/remote/FileFolderRemote.java b/source/java/org/alfresco/service/cmr/remote/FileFolderRemote.java index 55ff569e2d..252269ef53 100644 --- a/source/java/org/alfresco/service/cmr/remote/FileFolderRemote.java +++ b/source/java/org/alfresco/service/cmr/remote/FileFolderRemote.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -134,6 +134,13 @@ public interface FileFolderRemote */ public FileInfo create(String ticket, NodeRef parentNodeRef, String name, QName typeQName) throws FileExistsException; + /** + * @param token the authentication ticket + * + * This is additional method to avoid multiple authorisation during creating files + */ + public FileInfo[] create(String ticket, NodeRef[] parentNodeRefs, String[] names, QName[] typesQName) throws FileExistsException; + /** * @param token the authentication ticket * @@ -141,6 +148,13 @@ public interface FileFolderRemote */ public void delete(String ticket, NodeRef nodeRef); + /** + * @param token the authentication ticket + * + * This is additional method to avoid multiple authorisation during deleting files + */ + public void delete(String ticket, NodeRef[] nodeRefs); + /** * @param token the authentication ticket * @@ -176,6 +190,13 @@ public interface FileFolderRemote */ public ContentData putContent(String ticket, NodeRef nodeRef, byte[] bytes, String filename); + /** + * @param token the authentication ticket + * + * This is additional method to avoid multiple authorisation during putting content + */ + public ContentData[] putContent(String ticket, NodeRef nodeRefs[], byte[][] bytes, String[] filenames); + /** * TODO: Refactor!!! */ diff --git a/source/java/org/alfresco/service/cmr/remote/LoaderRemote.java b/source/java/org/alfresco/service/cmr/remote/LoaderRemote.java index f9a238eb6a..2bd8aa940b 100644 --- a/source/java/org/alfresco/service/cmr/remote/LoaderRemote.java +++ b/source/java/org/alfresco/service/cmr/remote/LoaderRemote.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -28,6 +28,10 @@ import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.StoreRef; +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; + /** * Remote transport interface for the Loader application. This adds functionality * that is generally required by the application and that is not available on other @@ -84,4 +88,38 @@ public interface LoaderRemote * @return Returns the details of each file created */ public FileInfo[] uploadContent(String ticket, NodeRef folderNodeRef, String[] filenames, byte[][] bytes); + + /** + * Check in Check out files. + * + * @param ticket the authentication ticket + * @param nodeRef a reference to the node to checkout + * @param bytes the contents of the files + * @param versionProperties the version properties. If null is passed then the original node + * is NOT versioned during the checkin operation. + */ + public void coci(String ticket, final NodeRef[] nodeRef, byte[][] bytes, List> versionProperties); + + /** + * Check out files. + * + * @param ticket the authentication ticket + * @param nodeRef a reference to the node to checkout + * @return a node reference to the created working copy + */ + public FileInfo[] checkout(String ticket, NodeRef[] nodeRef); + + /** + * Check in files. + * + * @param ticket the authentication ticket + * @param workingCopyNodeRef the working copy node reference + * @param versionProperties the version properties. If null is passed then the original node + * is NOT versioned during the checkin operation. + * @return the node reference to the original node, updated with the checked in + * state + */ + public NodeRef[] checkin(String ticket, NodeRef[] workingCopyNodeRef, + List> versionProperties); + }