mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged V4.1-BUG-FIX to HEAD
40690: Removed 'repository-bm' project, which is no longer distributed, referenced or supported - Part of ALF-14420: Remove benchmarking tool (alfresco-bm.jar) from installer and Alfresco war installation file - Also: ALF-15588 40692: Removed 'repository-bm' project, which is no longer distributed, referenced or supported - Part of ALF-14420: Remove benchmarking tool (alfresco-bm.jar) from installer and Alfresco war installation file 40695: Fixed ALF-14420: Remove benchmarking tool (alfresco-bm.jar) from installer and Alfresco war installation file - Removed all related code as well 40700: Remove XAM Connector. Now built as a standalone project 40707: ALF-14399 Share Calendar changes dates when "All Day" is selected. Event comparator now checks if date strings contain a time zone, previously was failing because we strip time zones from all day events. 40708: Complete - task : ALF-14399 Share Calendar changes dates when "All Day" is selected. Added the time zone in which the recurrence rule was parsed to the recurrence rule string. 40711: Merged V3.4-BUG-FIX to V4.1-BUG-FIX 40700: (RECORD ONLY) Remove XAM Connector. Now built as a standalone project 40701: (RECORD ONLY) Remove Kofax. Now built as a standalone integration. 40703: (RECORD ONLY) Revert Kofax removal. 40704: (RECORD ONLY) Revert XAM Connector removal for V3.4. 40709: (RECORD ONLY) ALF-14752 - Collapse Links part at the WCM details page lead to error 40710: ALF-15592: Merged PATCHES/V3.4.8 to V3.4-BUG-FIX 40543: ALF-15507: Orphan content URLs when you overwrite a file with identical content in CIFS - Removed diffing behaviour that was leaking content URLs git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@40712 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -29,16 +29,12 @@ import org.alfresco.jlan.server.filesys.AccessDeniedException;
|
|||||||
import org.alfresco.jlan.server.filesys.DiskFullException;
|
import org.alfresco.jlan.server.filesys.DiskFullException;
|
||||||
import org.alfresco.jlan.server.filesys.FileAttribute;
|
import org.alfresco.jlan.server.filesys.FileAttribute;
|
||||||
import org.alfresco.jlan.server.filesys.FileInfo;
|
import org.alfresco.jlan.server.filesys.FileInfo;
|
||||||
import org.alfresco.jlan.server.filesys.FileOpenParams;
|
|
||||||
import org.alfresco.jlan.server.filesys.NetworkFile;
|
import org.alfresco.jlan.server.filesys.NetworkFile;
|
||||||
import org.alfresco.jlan.smb.SeekType;
|
import org.alfresco.jlan.smb.SeekType;
|
||||||
import org.alfresco.jlan.smb.server.SMBSrvSession;
|
import org.alfresco.jlan.smb.server.SMBSrvSession;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.content.AbstractContentReader;
|
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
import org.alfresco.repo.content.filestore.FileContentReader;
|
import org.alfresco.repo.content.filestore.FileContentReader;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
|
||||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||||
import org.alfresco.repo.transaction.TransactionListenerAdapter;
|
import org.alfresco.repo.transaction.TransactionListenerAdapter;
|
||||||
import org.alfresco.service.cmr.repository.ContentAccessor;
|
import org.alfresco.service.cmr.repository.ContentAccessor;
|
||||||
@@ -76,7 +72,6 @@ public class ContentNetworkFile extends NodeRefNetworkFile
|
|||||||
private FileChannel channel; // File channel to file content
|
private FileChannel channel; // File channel to file content
|
||||||
private ContentAccessor content; // content
|
private ContentAccessor content; // content
|
||||||
|
|
||||||
private String preUpdateContentURL;
|
|
||||||
|
|
||||||
// Indicate if file has been written to or truncated/resized
|
// Indicate if file has been written to or truncated/resized
|
||||||
private boolean modified;
|
private boolean modified;
|
||||||
@@ -336,7 +331,6 @@ public class ContentNetworkFile extends NodeRefNetworkFile
|
|||||||
throw new AccessDeniedException("The network file was created for read-only: " + this);
|
throw new AccessDeniedException("The network file was created for read-only: " + this);
|
||||||
}
|
}
|
||||||
|
|
||||||
preUpdateContentURL = null;
|
|
||||||
|
|
||||||
// Need to open content for write
|
// Need to open content for write
|
||||||
if (write)
|
if (write)
|
||||||
@@ -349,14 +343,6 @@ public class ContentNetworkFile extends NodeRefNetworkFile
|
|||||||
|
|
||||||
content = contentService.getWriter( getNodeRef(), ContentModel.PROP_CONTENT, false);
|
content = contentService.getWriter( getNodeRef(), ContentModel.PROP_CONTENT, false);
|
||||||
|
|
||||||
// Keep the original content for later comparison
|
|
||||||
|
|
||||||
ContentData preUpdateContentData = (ContentData) nodeService.getProperty( getNodeRef(), ContentModel.PROP_CONTENT);
|
|
||||||
if (preUpdateContentData != null)
|
|
||||||
{
|
|
||||||
preUpdateContentURL = preUpdateContentData.getContentUrl();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Indicate that we have a writable channel to the file
|
// Indicate that we have a writable channel to the file
|
||||||
|
|
||||||
writableChannel = true;
|
writableChannel = true;
|
||||||
@@ -484,29 +470,7 @@ public class ContentNetworkFile extends NodeRefNetworkFile
|
|||||||
|
|
||||||
final ContentData contentData = content.getContentData();
|
final ContentData contentData = content.getContentData();
|
||||||
|
|
||||||
// Update node properties, but only if the binary has changed (ETHREEOH-1861)
|
// Update node properties
|
||||||
|
|
||||||
ContentReader postUpdateContentReader = writer.getReader();
|
|
||||||
|
|
||||||
RunAsWork<ContentReader> getReader = new RunAsWork<ContentReader>()
|
|
||||||
{
|
|
||||||
public ContentReader doWork() throws Exception
|
|
||||||
{
|
|
||||||
return preUpdateContentURL == null ? null : contentService.getRawReader(preUpdateContentURL);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ContentReader preUpdateContentReader = AuthenticationUtil.runAs(getReader, AuthenticationUtil.getSystemUserName());
|
|
||||||
|
|
||||||
boolean contentChanged = preUpdateContentURL == null
|
|
||||||
|| !AbstractContentReader.compareContentReaders(preUpdateContentReader,
|
|
||||||
postUpdateContentReader);
|
|
||||||
|
|
||||||
if (contentChanged)
|
|
||||||
{
|
|
||||||
if(logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("content has changed - remove ASPECT_NO_CONTENT");
|
|
||||||
}
|
|
||||||
nodeService.removeAspect(contentNodeRef, ContentModel.ASPECT_NO_CONTENT);
|
nodeService.removeAspect(contentNodeRef, ContentModel.ASPECT_NO_CONTENT);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -518,7 +482,6 @@ public class ContentNetworkFile extends NodeRefNetworkFile
|
|||||||
setClosed( true);
|
setClosed( true);
|
||||||
throw new DiskFullException(qe.getMessage());
|
throw new DiskFullException(qe.getMessage());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Tidy up after ourselves after a successful commit. Otherwise leave things to allow a retry.
|
// Tidy up after ourselves after a successful commit. Otherwise leave things to allow a retry.
|
||||||
AlfrescoTransactionSupport.bindListener(new TransactionListenerAdapter()
|
AlfrescoTransactionSupport.bindListener(new TransactionListenerAdapter()
|
||||||
@@ -531,7 +494,6 @@ public class ContentNetworkFile extends NodeRefNetworkFile
|
|||||||
if(channel == null)
|
if(channel == null)
|
||||||
{
|
{
|
||||||
content = null;
|
content = null;
|
||||||
preUpdateContentURL = null;
|
|
||||||
setClosed( true);
|
setClosed( true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,324 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.alfresco.repo.model.filefolder.loader;
|
|
||||||
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
*/
|
|
||||||
public abstract class AbstractLoaderThread extends Thread
|
|
||||||
{
|
|
||||||
protected final LoaderSession session;
|
|
||||||
protected final String loaderName;
|
|
||||||
protected final long testPeriod;
|
|
||||||
protected final long testTotal;
|
|
||||||
protected final long testLoadDepth;
|
|
||||||
protected final boolean verbose;
|
|
||||||
|
|
||||||
private AtomicBoolean mustStop;
|
|
||||||
private Random random;
|
|
||||||
|
|
||||||
// Statistics
|
|
||||||
private int statCount;
|
|
||||||
private double statTotalMs;
|
|
||||||
|
|
||||||
private static EhCacheAdapter<String, NodeRef> 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 = CacheManager.create(url);
|
|
||||||
Cache cache = cacheManager.getCache("org.alfresco.LoaderUploadThread.PathCache");
|
|
||||||
|
|
||||||
pathCache = new EhCacheAdapter<String, NodeRef>();
|
|
||||||
pathCache.setCache(cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbstractLoaderThread(
|
|
||||||
LoaderSession session,
|
|
||||||
String loaderName,
|
|
||||||
long testPeriod,
|
|
||||||
long testTotal,
|
|
||||||
long testLoadDepth,
|
|
||||||
boolean verbose)
|
|
||||||
{
|
|
||||||
super(LoaderSession.THREAD_GROUP, "LoaderThread-" + loaderName);
|
|
||||||
|
|
||||||
this.session = session;
|
|
||||||
this.loaderName = loaderName;
|
|
||||||
this.testPeriod = testPeriod;
|
|
||||||
this.testTotal = testTotal < 1 ? Integer.MAX_VALUE : testTotal;
|
|
||||||
this.testLoadDepth = testLoadDepth;
|
|
||||||
this.verbose = verbose;
|
|
||||||
|
|
||||||
this.mustStop = new AtomicBoolean(false);
|
|
||||||
this.random = new Random();
|
|
||||||
|
|
||||||
this.statCount = 0;
|
|
||||||
this.statTotalMs = 0.0D;
|
|
||||||
|
|
||||||
// Check the load depth
|
|
||||||
if (this.testLoadDepth < 1 || this.testLoadDepth > this.session.getFolderProfiles().length)
|
|
||||||
{
|
|
||||||
throw new AlfrescoRuntimeException("The load depth must be [1," + this.session.getFolderProfiles().length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify the running thread to exit at the first available opportunity.
|
|
||||||
*/
|
|
||||||
public void setStop()
|
|
||||||
{
|
|
||||||
mustStop.set(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
int testCount = 0;
|
|
||||||
while (!mustStop.get())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Choose a server
|
|
||||||
int serverCount = session.getRemoteServers().size();
|
|
||||||
int serverIndex = random.nextInt(serverCount);
|
|
||||||
LoaderServerProxy serverProxy = session.getRemoteServers().get(serverIndex);
|
|
||||||
|
|
||||||
// Choose a working root node
|
|
||||||
int nodeCount = session.getWorkingRootNodeRefs().size();
|
|
||||||
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();
|
|
||||||
|
|
||||||
// Record stats
|
|
||||||
updateStats(startTime, endTime);
|
|
||||||
|
|
||||||
// Dump the specifics of the load
|
|
||||||
logVerbose(startTime, endTime, msg);
|
|
||||||
|
|
||||||
// Have we done this enough?
|
|
||||||
testCount++;
|
|
||||||
if (testCount > testTotal)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do we wait or continue immediately
|
|
||||||
long duration = endTime - startTime;
|
|
||||||
long mustWait = testPeriod - (long)(duration / 1000.0 / 1000.0);
|
|
||||||
if (mustWait >= 5)
|
|
||||||
{
|
|
||||||
synchronized(this)
|
|
||||||
{
|
|
||||||
this.wait(mustWait);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.doAfter(serverProxy, workingRootNodeRef);
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
session.logError("Loading error on '" + loaderName + "': " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void updateStats(long startTime, long endTime)
|
|
||||||
{
|
|
||||||
statCount++;
|
|
||||||
// Calculate the delta in milliseconds
|
|
||||||
double delta = ((double)(endTime - startTime) / 1000.0 / 1000.0);
|
|
||||||
// Now recalculate the average
|
|
||||||
statTotalMs += delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <pre>
|
|
||||||
* NAME+36\tCOUNT \tTIME \tAVERAGE TIME \tPER SECOND \tDESCRIPTION
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
private void logVerbose(long startTime, long endTime, String msg)
|
|
||||||
{
|
|
||||||
double delta = ((double)(endTime - startTime) / 1000.0 / 1000.0 / 1000.0);
|
|
||||||
|
|
||||||
double statTotalSec = statTotalMs / 1000.0;
|
|
||||||
double statPerSec = statCount / statTotalSec;
|
|
||||||
double statAveSec = statTotalSec / statCount;
|
|
||||||
// Summarize the results
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb
|
|
||||||
.append(String.format("%40s", loaderName)).append("\t")
|
|
||||||
.append(String.format("%15.0f", (float)statCount)).append("\t")
|
|
||||||
.append(String.format("%15.3f", delta)).append("\t")
|
|
||||||
.append(String.format("%15.3f", statPerSec)).append("\t")
|
|
||||||
.append(String.format("%15.3f", statAveSec)).append("\t")
|
|
||||||
.append(msg);
|
|
||||||
session.logVerbose(sb.toString(), verbose);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <pre>
|
|
||||||
* NAME+36\tCOUNT \tTOTAL TIME \tAVERAGE TIME \tPER SECOND \tDESCRIPTION
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @return Returns the summary of the results
|
|
||||||
*/
|
|
||||||
public String getSummary()
|
|
||||||
{
|
|
||||||
double statTotalSec = statTotalMs / 1000.0;
|
|
||||||
double statPerSec = statCount / statTotalSec;
|
|
||||||
double statAveSec = statTotalSec / statCount;
|
|
||||||
// Summarize the results
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb
|
|
||||||
.append(String.format("%40s", loaderName)).append("\t")
|
|
||||||
.append(String.format("%15.0f", (float)statCount)).append("\t")
|
|
||||||
.append(String.format("%15.3f", statTotalSec)).append("\t")
|
|
||||||
.append(String.format("%15.3f", statAveSec)).append("\t")
|
|
||||||
.append(String.format("%15.3f", statPerSec)).append("\t")
|
|
||||||
.append("");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param serverProxy the server to load
|
|
||||||
* @param workingRootNodeRef the root of the hierarchy to use
|
|
||||||
* @return a brief description of the loading
|
|
||||||
* @throws Exception any exception will be handled
|
|
||||||
*/
|
|
||||||
protected abstract String doLoading(
|
|
||||||
LoaderServerProxy serverProxy,
|
|
||||||
NodeRef workingRootNodeRef) throws Exception;
|
|
||||||
|
|
||||||
protected List<String> chooseFolderPath()
|
|
||||||
{
|
|
||||||
int[] folderProfiles = session.getFolderProfiles();
|
|
||||||
// We work through these until we get the required depth.
|
|
||||||
// The root node is ignored as it acts as the search root
|
|
||||||
List<String> path = new ArrayList<String>((int)testLoadDepth);
|
|
||||||
for (int i = 1; i < testLoadDepth; i++)
|
|
||||||
{
|
|
||||||
int folderProfile = folderProfiles[i];
|
|
||||||
int randomFolderId = random.nextInt(folderProfile);
|
|
||||||
String name = String.format("folder-%05d", randomFolderId);
|
|
||||||
path.add(name);
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected File getFile() throws Exception
|
|
||||||
{
|
|
||||||
File[] files = session.getSourceFiles();
|
|
||||||
File file = files[random.nextInt(files.length)];
|
|
||||||
if (!file.exists() || file.isDirectory())
|
|
||||||
{
|
|
||||||
throw new LoaderClientException("Cannot find loading file: " + file);
|
|
||||||
}
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates or find the folders based on caching.
|
|
||||||
*/
|
|
||||||
protected NodeRef makeFolders(
|
|
||||||
String ticket,
|
|
||||||
LoaderServerProxy serverProxy,
|
|
||||||
NodeRef workingRootNodeRef,
|
|
||||||
List<String> 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
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,461 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.alfresco.repo.model.filefolder.loader;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.StringTokenizer;
|
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class that communicates with the remote FileFolder interface to perform
|
|
||||||
* loading of the system using the standard models.
|
|
||||||
* <p>
|
|
||||||
* TODO: The transport interface must be hidden behind and implementation
|
|
||||||
* of the standard FileFolderService interface.
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
* @since 2.1
|
|
||||||
*/
|
|
||||||
public class FileFolderRemoteLoader
|
|
||||||
{
|
|
||||||
private static final String STORE_PROTOCOL = "FileFolderRemoteLoader";
|
|
||||||
|
|
||||||
private Properties properties;
|
|
||||||
private String username;
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
private LoaderSession session;
|
|
||||||
private AbstractLoaderThread[] threads;
|
|
||||||
|
|
||||||
public FileFolderRemoteLoader(Properties properties, String username, String password)
|
|
||||||
{
|
|
||||||
this.properties = properties;
|
|
||||||
this.username = username;
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void initialize() throws Exception
|
|
||||||
{
|
|
||||||
if (session != null || threads != null)
|
|
||||||
{
|
|
||||||
throw new AlfrescoRuntimeException("Application already initialized");
|
|
||||||
}
|
|
||||||
session = FileFolderRemoteLoader.makeSession(username, password, properties);
|
|
||||||
threads = FileFolderRemoteLoader.makeThreads(session, properties);
|
|
||||||
|
|
||||||
// Log the initial summaries
|
|
||||||
String summary = session.getSummary();
|
|
||||||
session.logVerbose(summary, true);
|
|
||||||
session.logSummary(summary);
|
|
||||||
session.logError(summary);
|
|
||||||
|
|
||||||
// Header the outputs
|
|
||||||
session.logVerbose(LoaderSession.getLineEnding(), true);
|
|
||||||
session.logVerbose(COLUMNS_VERBOSE, true);
|
|
||||||
session.logSummary(LoaderSession.getLineEnding());
|
|
||||||
session.logSummary(COLUMNS_SUMMARY);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String COLUMNS_VERBOSE =
|
|
||||||
String.format("%40s\t%15s\t%15s\t%15s\t%15s\t%15s",
|
|
||||||
"NAME", "COUNT", "TIME", "AVERAGE TIME", "PER SECOND", "DESCRIPTION");
|
|
||||||
private static final String COLUMNS_SUMMARY =
|
|
||||||
String.format("%40s\t%15s\t%15s\t%15s\t%15s\t%15s",
|
|
||||||
"NAME", "COUNT", "TOTAL TIME", "AVERAGE TIME", "PER SECOND", "DESCRIPTION");
|
|
||||||
|
|
||||||
public synchronized void start()
|
|
||||||
{
|
|
||||||
if (session == null || threads == null)
|
|
||||||
{
|
|
||||||
throw new AlfrescoRuntimeException("Application not initialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fire up the threads
|
|
||||||
for (Thread thread : threads)
|
|
||||||
{
|
|
||||||
thread.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void stop()
|
|
||||||
{
|
|
||||||
// Stop the threads
|
|
||||||
for (AbstractLoaderThread thread : threads)
|
|
||||||
{
|
|
||||||
thread.setStop();
|
|
||||||
}
|
|
||||||
// Now join each thread to make sure they all finish their current operation
|
|
||||||
for (AbstractLoaderThread thread : threads)
|
|
||||||
{
|
|
||||||
// Notify any waits
|
|
||||||
synchronized(thread)
|
|
||||||
{
|
|
||||||
thread.notifyAll();
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
thread.join();
|
|
||||||
}
|
|
||||||
catch (InterruptedException e) {}
|
|
||||||
}
|
|
||||||
// Log each thread's summary
|
|
||||||
for (AbstractLoaderThread thread : threads)
|
|
||||||
{
|
|
||||||
String summary = thread.getSummary();
|
|
||||||
session.logSummary(summary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dumpThreadSummaries()
|
|
||||||
{
|
|
||||||
System.out.println("");
|
|
||||||
System.out.println(COLUMNS_SUMMARY);
|
|
||||||
// Dump each thread's summary
|
|
||||||
for (AbstractLoaderThread thread : threads)
|
|
||||||
{
|
|
||||||
String summary = thread.getSummary();
|
|
||||||
System.out.println(summary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String PROP_SESSION_NAME = "session.name";
|
|
||||||
public static final String PROP_SESSION_SOURCE_DIR = "session.sourceDir";
|
|
||||||
public static final String PROP_SESSION_STORE_IDENTIFIERS = "session.storeIdentifiers";
|
|
||||||
public static final String PROP_SESSION_RMI_URLS = "session.rmiUrls";
|
|
||||||
public static final String PROP_SESSION_FOLDER_PROFILE = "session.folderProfile";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method to construct a session using the given properties.
|
|
||||||
*/
|
|
||||||
private static LoaderSession makeSession(String username, String password, Properties properties) throws Exception
|
|
||||||
{
|
|
||||||
// Name
|
|
||||||
String name = properties.getProperty(PROP_SESSION_NAME);
|
|
||||||
FileFolderRemoteLoader.checkProperty(PROP_SESSION_STORE_IDENTIFIERS, name);
|
|
||||||
|
|
||||||
// Source files
|
|
||||||
String sourceDirStr = properties.getProperty(PROP_SESSION_SOURCE_DIR);
|
|
||||||
File sourceDir = new File(sourceDirStr);
|
|
||||||
|
|
||||||
// Stores
|
|
||||||
String storeIdentifiersStr = properties.getProperty(PROP_SESSION_STORE_IDENTIFIERS);
|
|
||||||
FileFolderRemoteLoader.checkProperty(PROP_SESSION_STORE_IDENTIFIERS, storeIdentifiersStr);
|
|
||||||
StringTokenizer tokenizer = new StringTokenizer(storeIdentifiersStr, ",");
|
|
||||||
Set<StoreRef> storeRefs = new HashSet<StoreRef>();
|
|
||||||
while (tokenizer.hasMoreTokens())
|
|
||||||
{
|
|
||||||
String storeIdentifier = tokenizer.nextToken().trim();
|
|
||||||
storeRefs.add(new StoreRef(STORE_PROTOCOL, storeIdentifier));
|
|
||||||
}
|
|
||||||
FileFolderRemoteLoader.checkProperty(PROP_SESSION_STORE_IDENTIFIERS, storeRefs);
|
|
||||||
|
|
||||||
// RMI URLs
|
|
||||||
String rmiUrlsStr = properties.getProperty(PROP_SESSION_RMI_URLS);
|
|
||||||
FileFolderRemoteLoader.checkProperty(PROP_SESSION_RMI_URLS, rmiUrlsStr);
|
|
||||||
tokenizer = new StringTokenizer(rmiUrlsStr, ",");
|
|
||||||
Set<String> rmiUrls = new HashSet<String>();
|
|
||||||
while (tokenizer.hasMoreTokens())
|
|
||||||
{
|
|
||||||
String rmiUrl = tokenizer.nextToken().trim();
|
|
||||||
rmiUrls.add(rmiUrl);
|
|
||||||
}
|
|
||||||
FileFolderRemoteLoader.checkProperty(PROP_SESSION_STORE_IDENTIFIERS, rmiUrls);
|
|
||||||
|
|
||||||
// RMI URLs
|
|
||||||
String folderProfilesStr = properties.getProperty(PROP_SESSION_FOLDER_PROFILE);
|
|
||||||
FileFolderRemoteLoader.checkProperty(PROP_SESSION_FOLDER_PROFILE, folderProfilesStr);
|
|
||||||
tokenizer = new StringTokenizer(folderProfilesStr, ",");
|
|
||||||
ArrayList<Integer> folderProfilesList = new ArrayList<Integer>(5);
|
|
||||||
while (tokenizer.hasMoreTokens())
|
|
||||||
{
|
|
||||||
String folderProfileStr = tokenizer.nextToken().trim();
|
|
||||||
Integer folderProfile = Integer.valueOf(folderProfileStr);
|
|
||||||
folderProfilesList.add(folderProfile);
|
|
||||||
}
|
|
||||||
FileFolderRemoteLoader.checkProperty(PROP_SESSION_FOLDER_PROFILE, folderProfilesList);
|
|
||||||
int[] folderProfiles = new int[folderProfilesList.size()];
|
|
||||||
for (int i = 0; i < folderProfiles.length; i++)
|
|
||||||
{
|
|
||||||
folderProfiles[i] = folderProfilesList.get(i);
|
|
||||||
}
|
|
||||||
if (folderProfiles.length == 0 || folderProfiles[0] != 1)
|
|
||||||
{
|
|
||||||
throw new LoaderClientException(
|
|
||||||
"'" + PROP_SESSION_FOLDER_PROFILE + "' must always start with '1', " +
|
|
||||||
"which represents the root of the hierarchy, and have at least one other value. " +
|
|
||||||
"E.g. '1, 3'");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct
|
|
||||||
LoaderSession session = new LoaderSession(
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
name,
|
|
||||||
rmiUrls,
|
|
||||||
storeRefs,
|
|
||||||
sourceDir,
|
|
||||||
folderProfiles);
|
|
||||||
|
|
||||||
// Initialize the session
|
|
||||||
session.initialize();
|
|
||||||
|
|
||||||
// Done
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method to construct the worker threads.
|
|
||||||
*/
|
|
||||||
private static AbstractLoaderThread[] makeThreads(LoaderSession session, Properties properties) throws Exception
|
|
||||||
{
|
|
||||||
ArrayList<AbstractLoaderThread> threads = new ArrayList<AbstractLoaderThread>(3);
|
|
||||||
// Iterate over the properties and pick out the thread descriptors
|
|
||||||
for (Object o : properties.keySet())
|
|
||||||
{
|
|
||||||
String propertyName = (String)o;
|
|
||||||
if (!propertyName.startsWith("test.load."))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String name = propertyName;
|
|
||||||
|
|
||||||
// Get the type of the test
|
|
||||||
int lastIndex = propertyName.indexOf(".", 10);
|
|
||||||
if (lastIndex < 0)
|
|
||||||
{
|
|
||||||
throw new LoaderClientException(
|
|
||||||
"Invalid test loader property. " +
|
|
||||||
"It should be of the form 'test.load.upload.xyz=...': " + propertyName);
|
|
||||||
}
|
|
||||||
String type = propertyName.substring(10, lastIndex);
|
|
||||||
|
|
||||||
// Get the values
|
|
||||||
String valuesStr = properties.getProperty(propertyName);
|
|
||||||
FileFolderRemoteLoader.checkProperty(propertyName, valuesStr);
|
|
||||||
// Parse it into the well-known values
|
|
||||||
String[] strValues = new String[] {"1", "0", "0", "1", "false", "1"};
|
|
||||||
int index = 0;
|
|
||||||
StringTokenizer tokenizer = new StringTokenizer(valuesStr, ",");
|
|
||||||
while (tokenizer.hasMoreTokens())
|
|
||||||
{
|
|
||||||
String value = tokenizer.nextToken().trim();
|
|
||||||
if (value.length() > 0)
|
|
||||||
{
|
|
||||||
strValues[index] = value;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
if (index >= strValues.length)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
long testCount = 1L;
|
|
||||||
long testPeriod = 0L;
|
|
||||||
long testTotal = 0L;
|
|
||||||
long testDepth = 1L;
|
|
||||||
boolean testVerbose = false;
|
|
||||||
long filesPerIteration = 1;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
testCount = Long.parseLong(strValues[0]);
|
|
||||||
testPeriod = Long.parseLong(strValues[1]);
|
|
||||||
testTotal = Long.parseLong(strValues[2]);
|
|
||||||
testDepth = Long.parseLong(strValues[3]);
|
|
||||||
testVerbose = Boolean.parseBoolean(strValues[4]);
|
|
||||||
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]<, [filesPerIteration]>");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct
|
|
||||||
for (int i = 0; i < testCount; i++)
|
|
||||||
{
|
|
||||||
AbstractLoaderThread thread = null;
|
|
||||||
if (type.equals("upload"))
|
|
||||||
{
|
|
||||||
thread = new LoaderUploadThread(session, name, testPeriod, testTotal, testDepth, testVerbose, filesPerIteration);
|
|
||||||
}
|
|
||||||
else if (type.equals("totals"))
|
|
||||||
{
|
|
||||||
thread = new LoaderTotalsThread(session, name, testPeriod, testTotal, testDepth, testVerbose);
|
|
||||||
}
|
|
||||||
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
|
|
||||||
{
|
|
||||||
throw new LoaderClientException("Unknown test type: " + name);
|
|
||||||
}
|
|
||||||
threads.add(thread);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Done
|
|
||||||
AbstractLoaderThread[] ret = new AbstractLoaderThread[threads.size()];
|
|
||||||
return threads.toArray(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks for null values and empty collections.
|
|
||||||
*/
|
|
||||||
private static void checkProperty(String propertyName, Object propertyValue) throws LoaderClientException
|
|
||||||
{
|
|
||||||
if (propertyValue == null)
|
|
||||||
{
|
|
||||||
throw new LoaderClientException("'" + propertyName + "' must be provided.");
|
|
||||||
}
|
|
||||||
else if (propertyValue instanceof Collection)
|
|
||||||
{
|
|
||||||
Collection propertyCollection = (Collection) propertyValue;
|
|
||||||
int size = propertyCollection.size();
|
|
||||||
if (size == 0)
|
|
||||||
{
|
|
||||||
throw new LoaderClientException("'" + propertyName + "' does not have any values.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String ... args)
|
|
||||||
{
|
|
||||||
Map<String, String> argMap = ripArgs(args);
|
|
||||||
String username = argMap.get("username");
|
|
||||||
String password = argMap.get("password");
|
|
||||||
String config = argMap.get("config");
|
|
||||||
if (username == null || password == null || config == null)
|
|
||||||
{
|
|
||||||
printUsage();
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File propertiesFile = new File(config);
|
|
||||||
if (!propertiesFile.exists())
|
|
||||||
{
|
|
||||||
System.err.println("Unable to find config file: " + config);
|
|
||||||
}
|
|
||||||
Properties properties = new Properties();
|
|
||||||
properties.load(new FileInputStream(propertiesFile));
|
|
||||||
|
|
||||||
FileFolderRemoteLoader app = new FileFolderRemoteLoader(properties, username, password);
|
|
||||||
|
|
||||||
// Initialize
|
|
||||||
app.initialize();
|
|
||||||
|
|
||||||
// Run
|
|
||||||
app.start();
|
|
||||||
|
|
||||||
// Now lower this threads priority
|
|
||||||
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
|
|
||||||
|
|
||||||
// Wait for a quit signal
|
|
||||||
System.out.println("Running test " + app.session.getName() + ".");
|
|
||||||
System.out.println(" Enter 'q' to quit.");
|
|
||||||
System.out.println(" Enter 's' to dump a thread summary.");
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
int keyPress = System.in.read();
|
|
||||||
if (keyPress == 'Q' || keyPress == 'q')
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (keyPress == 'S' || keyPress == 's')
|
|
||||||
{
|
|
||||||
app.dumpThreadSummaries();
|
|
||||||
}
|
|
||||||
else if (System.in.available() > 0)
|
|
||||||
{
|
|
||||||
// Don't wait, just process
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// No more keypresses so just wait
|
|
||||||
Thread.yield();
|
|
||||||
}
|
|
||||||
// Finish off
|
|
||||||
app.stop();
|
|
||||||
System.out.println("The test is complete.");
|
|
||||||
}
|
|
||||||
catch (LoaderClientException e)
|
|
||||||
{
|
|
||||||
System.err.println(e.getMessage());
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
System.err.println("A failure prevented proper execution.");
|
|
||||||
e.printStackTrace();
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Map<String, String> ripArgs(String ... args)
|
|
||||||
{
|
|
||||||
Map<String, String> argsMap = new HashMap<String, String>(5);
|
|
||||||
for (String arg : args)
|
|
||||||
{
|
|
||||||
int index = arg.indexOf('=');
|
|
||||||
if (!arg.startsWith("--") || index < 0 || index == arg.length() - 1)
|
|
||||||
{
|
|
||||||
// Ignore it
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String name = arg.substring(2, index);
|
|
||||||
String value = arg.substring(index + 1, arg.length());
|
|
||||||
argsMap.put(name, value);
|
|
||||||
}
|
|
||||||
return argsMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void printUsage()
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("\n")
|
|
||||||
.append("Usage\n")
|
|
||||||
.append(" java -jar ... --username=<username> --password=<password> --config=<config file> \n");
|
|
||||||
System.out.println(sb.toString());
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
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<HashMap<String, Serializable>> arrVersionProp = new ArrayList<HashMap<String, Serializable>>();
|
|
||||||
|
|
||||||
byte[][] bytes = new byte[filesPerIteration][];
|
|
||||||
for (int i = 0; i < filesPerIteration; i++)
|
|
||||||
{
|
|
||||||
File file = getFile();
|
|
||||||
bytes[i] = FileCopyUtils.copyToByteArray(file);
|
|
||||||
arrVersionProp.add(new HashMap<String, Serializable>());
|
|
||||||
}
|
|
||||||
|
|
||||||
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<String> 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;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.alfresco.repo.model.filefolder.loader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class to catch non-critical issues.
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
*/
|
|
||||||
public class LoaderClientException extends Exception
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = -3306363763048881956L;
|
|
||||||
|
|
||||||
public LoaderClientException(String msg)
|
|
||||||
{
|
|
||||||
super(msg);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
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<String> 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;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,80 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.alfresco.repo.model.filefolder.loader;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.alfresco.service.cmr.model.FileInfo;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A loader thread that retrieves the folders beneath each directory from
|
|
||||||
* the root. This is an expensive process but should reach a stable execution time
|
|
||||||
* once the folders in the profile have all been created.
|
|
||||||
* @since 2.2
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
*/
|
|
||||||
public class LoaderListFoldersThread extends AbstractLoaderThread
|
|
||||||
{
|
|
||||||
public LoaderListFoldersThread(
|
|
||||||
LoaderSession session,
|
|
||||||
String loaderName,
|
|
||||||
long testPeriod,
|
|
||||||
long testTotal,
|
|
||||||
long testLoadDepth,
|
|
||||||
boolean verbose)
|
|
||||||
{
|
|
||||||
super(session, loaderName, testPeriod, testTotal, testLoadDepth, verbose);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Go to a directory and get a listing of the folders beneath it.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected String doLoading(LoaderServerProxy serverProxy, NodeRef workingRootNodeRef) throws Exception
|
|
||||||
{
|
|
||||||
int count = listFoldersRecursive(serverProxy, workingRootNodeRef, 0);
|
|
||||||
|
|
||||||
// Done
|
|
||||||
String msg = String.format("Found %d folders below node %s", count, workingRootNodeRef.toString());
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursive method to list all folders in the hierarchy.
|
|
||||||
* @return Returns the number of folders listed
|
|
||||||
*/
|
|
||||||
private int listFoldersRecursive(LoaderServerProxy serverProxy, NodeRef parentNodeRef, int count)
|
|
||||||
{
|
|
||||||
List<FileInfo> fileInfos = serverProxy.fileFolderRemote.listFolders(
|
|
||||||
serverProxy.ticket,
|
|
||||||
parentNodeRef);
|
|
||||||
for (FileInfo info : fileInfos)
|
|
||||||
{
|
|
||||||
if (!info.isFolder())
|
|
||||||
{
|
|
||||||
// Ooops
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
count += listFoldersRecursive(serverProxy, info.getNodeRef(), count);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.alfresco.repo.model.filefolder.loader;
|
|
||||||
|
|
||||||
import org.alfresco.service.cmr.remote.FileFolderRemote;
|
|
||||||
import org.alfresco.service.cmr.remote.LoaderRemote;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class to store remote service connections.
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
*/
|
|
||||||
public class LoaderServerProxy
|
|
||||||
{
|
|
||||||
public final String rmiUrl;
|
|
||||||
public final String ticket;
|
|
||||||
public final FileFolderRemote fileFolderRemote;
|
|
||||||
public final LoaderRemote loaderRemote;
|
|
||||||
|
|
||||||
public LoaderServerProxy(
|
|
||||||
String rmiUrl,
|
|
||||||
String ticket,
|
|
||||||
FileFolderRemote fileFolderRemote,
|
|
||||||
LoaderRemote loaderRemote)
|
|
||||||
{
|
|
||||||
this.rmiUrl = rmiUrl;
|
|
||||||
this.ticket = ticket;
|
|
||||||
this.fileFolderRemote = fileFolderRemote;
|
|
||||||
this.loaderRemote = loaderRemote;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -1,440 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.alfresco.repo.model.filefolder.loader;
|
|
||||||
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
|
||||||
import org.alfresco.error.StackTraceUtil;
|
|
||||||
import org.alfresco.model.ContentModel;
|
|
||||||
import org.alfresco.repo.remote.FileFolderRemoteClient;
|
|
||||||
import org.alfresco.service.cmr.model.FileInfo;
|
|
||||||
import org.alfresco.service.cmr.remote.LoaderRemote;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
|
||||||
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A description of session details.
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
public class LoaderSession
|
|
||||||
{
|
|
||||||
public static final ThreadGroup THREAD_GROUP = new ThreadGroup("FileFolderRemoteLoader");
|
|
||||||
|
|
||||||
private String username;
|
|
||||||
private String password;
|
|
||||||
private String name;
|
|
||||||
private Set<String> rmiUrls;
|
|
||||||
private Set<StoreRef> storeRefs;
|
|
||||||
private File outputFile;
|
|
||||||
private File sourceDir;
|
|
||||||
private int[] folderProfiles;
|
|
||||||
|
|
||||||
private List<LoaderServerProxy> remoteServers;
|
|
||||||
private List<NodeRef> workingRootNodeRefs;
|
|
||||||
private File[] sourceFiles;
|
|
||||||
private OutputStream outVerbose;
|
|
||||||
private OutputStream outSummary;
|
|
||||||
private OutputStream outError;
|
|
||||||
private long startTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public LoaderSession(
|
|
||||||
String username,
|
|
||||||
String password,
|
|
||||||
String name,
|
|
||||||
Set<String> rmiUrls,
|
|
||||||
Set<StoreRef> storeRefs,
|
|
||||||
File sourceDir,
|
|
||||||
int[] folderProfiles)
|
|
||||||
{
|
|
||||||
this.username = username;
|
|
||||||
this.password = password;
|
|
||||||
this.name = name;
|
|
||||||
this.rmiUrls = rmiUrls;
|
|
||||||
this.storeRefs = storeRefs;
|
|
||||||
this.sourceDir = sourceDir;
|
|
||||||
this.folderProfiles = folderProfiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName()
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<LoaderServerProxy> getRemoteServers()
|
|
||||||
{
|
|
||||||
return remoteServers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<NodeRef> getWorkingRootNodeRefs()
|
|
||||||
{
|
|
||||||
return workingRootNodeRefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public File[] getSourceFiles()
|
|
||||||
{
|
|
||||||
return sourceFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int[] getFolderProfiles()
|
|
||||||
{
|
|
||||||
return folderProfiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the object before first use.
|
|
||||||
*/
|
|
||||||
public synchronized void initialize() throws Exception
|
|
||||||
{
|
|
||||||
if (remoteServers != null)
|
|
||||||
{
|
|
||||||
throw new AlfrescoRuntimeException("The client has already been initialized");
|
|
||||||
}
|
|
||||||
remoteServers = LoaderSession.connect(rmiUrls, username, password);
|
|
||||||
workingRootNodeRefs = LoaderSession.makeStores(remoteServers, storeRefs);
|
|
||||||
LoaderSession.checkClustering(remoteServers, workingRootNodeRefs);
|
|
||||||
|
|
||||||
// Create the output file, if necessary
|
|
||||||
if (outputFile != null)
|
|
||||||
{
|
|
||||||
File outputDir = outputFile.getParentFile();
|
|
||||||
if (!outputDir.exists())
|
|
||||||
{
|
|
||||||
outputDir.mkdirs();
|
|
||||||
}
|
|
||||||
if (outputFile.exists())
|
|
||||||
{
|
|
||||||
System.out.println("The output file " + outputFile + " already exists.");
|
|
||||||
System.out.println("Are you sure you want to overwrite the file?");
|
|
||||||
int in = System.in.read();
|
|
||||||
if (in != 'Y' && in != 'y')
|
|
||||||
{
|
|
||||||
throw new LoaderClientException("The output file " + outputFile + " already exists");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the source files
|
|
||||||
sourceFiles = LoaderSession.getSourceFiles(sourceDir);
|
|
||||||
|
|
||||||
// Construct output and error files
|
|
||||||
long time = System.currentTimeMillis();
|
|
||||||
File fileVerbose = new File("./LoaderSession-" + name + "-"+ time + "-verbose.tsv");
|
|
||||||
File fileSummary = new File("./LoaderSession-" + name + "-"+ time + "-summary.tsv");
|
|
||||||
File fileError = new File("./LoaderSession-" + name + "-"+ time + "-error.tsv");
|
|
||||||
outVerbose = new BufferedOutputStream(new FileOutputStream(fileVerbose));
|
|
||||||
outSummary = new BufferedOutputStream(new FileOutputStream(fileSummary));
|
|
||||||
outError = new BufferedOutputStream(new FileOutputStream(fileError));
|
|
||||||
|
|
||||||
// Record the start time
|
|
||||||
startTime = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void close()
|
|
||||||
{
|
|
||||||
try { outVerbose.close(); } catch (Throwable e) {}
|
|
||||||
try { outSummary.close(); } catch (Throwable e) {}
|
|
||||||
try { outError.close(); } catch (Throwable e) {}
|
|
||||||
|
|
||||||
outVerbose = null;
|
|
||||||
outSummary = null;
|
|
||||||
outError = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect to the remote servers.
|
|
||||||
*/
|
|
||||||
private static List<LoaderServerProxy> connect(Set<String> rmiUrls, String username, String password) throws Exception
|
|
||||||
{
|
|
||||||
List<LoaderServerProxy> remoteServers = new ArrayList<LoaderServerProxy>(rmiUrls.size());
|
|
||||||
for (String rmiUrl : rmiUrls)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Ensure the RMI URL is consistent
|
|
||||||
if (!rmiUrl.endsWith("/"))
|
|
||||||
{
|
|
||||||
rmiUrl += "/";
|
|
||||||
}
|
|
||||||
// Get the FileFolderServiceTransport
|
|
||||||
FileFolderRemoteClient fileFolderRemote = new FileFolderRemoteClient(rmiUrl);
|
|
||||||
// Get the LoaderServiceTransport
|
|
||||||
RmiProxyFactoryBean loaderFactory = new RmiProxyFactoryBean();
|
|
||||||
loaderFactory.setRefreshStubOnConnectFailure(true);
|
|
||||||
loaderFactory.setServiceInterface(LoaderRemote.class);
|
|
||||||
loaderFactory.setServiceUrl(rmiUrl + LoaderRemote.SERVICE_NAME);
|
|
||||||
loaderFactory.afterPropertiesSet();
|
|
||||||
LoaderRemote loaderRemote = (LoaderRemote) loaderFactory.getObject();
|
|
||||||
|
|
||||||
// Authenticate
|
|
||||||
String ticket = loaderRemote.authenticate(username, password);
|
|
||||||
|
|
||||||
// Store the service references
|
|
||||||
LoaderServerProxy remoteServer = new LoaderServerProxy(
|
|
||||||
rmiUrl,
|
|
||||||
ticket,
|
|
||||||
fileFolderRemote,
|
|
||||||
loaderRemote);
|
|
||||||
remoteServers.add(remoteServer);
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
// Failed to connect.
|
|
||||||
System.err.println("\n" +
|
|
||||||
"ERROR: Failed to establish connection to server: \n" +
|
|
||||||
" Server: " + rmiUrl + "\n" +
|
|
||||||
" Error: " + e.getMessage());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check that there is at least one server
|
|
||||||
if (remoteServers.size() == 0)
|
|
||||||
{
|
|
||||||
throw new LoaderClientException("No remote servers are available");
|
|
||||||
}
|
|
||||||
return remoteServers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<NodeRef> makeStores(List<LoaderServerProxy> remoteServers, Set<StoreRef> storeRefs) throws Exception
|
|
||||||
{
|
|
||||||
// Take the first server and ensure that all the stores are available
|
|
||||||
LoaderServerProxy remoteServer = remoteServers.get(0);
|
|
||||||
|
|
||||||
List<NodeRef> workingRootNodeRefs = new ArrayList<NodeRef>(10);
|
|
||||||
for (StoreRef storeRef : storeRefs)
|
|
||||||
{
|
|
||||||
NodeRef workingRootNodeRef = remoteServer.loaderRemote.getOrCreateWorkingRoot(remoteServer.ticket, storeRef);
|
|
||||||
workingRootNodeRefs.add(workingRootNodeRef);
|
|
||||||
}
|
|
||||||
// Done
|
|
||||||
return workingRootNodeRefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void checkClustering(
|
|
||||||
List<LoaderServerProxy> remoteServers,
|
|
||||||
List<NodeRef> workingRootNodeRefs) throws Exception
|
|
||||||
{
|
|
||||||
List<String> problems = new ArrayList<String>(10);
|
|
||||||
for (LoaderServerProxy remoteServer : remoteServers)
|
|
||||||
{
|
|
||||||
String ticket = remoteServer.ticket;
|
|
||||||
for (NodeRef workingRootNodeRef : workingRootNodeRefs)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Get the working root node. If the cluster is correctly configured,
|
|
||||||
// it will be available on all the servers.
|
|
||||||
FileInfo fileInfo = remoteServer.fileFolderRemote.getFileInfo(ticket, workingRootNodeRef);
|
|
||||||
if (fileInfo == null)
|
|
||||||
{
|
|
||||||
problems.add("Cannot find the working root node on server: " + remoteServer.rmiUrl);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Now look for and create a file against which to store some content
|
|
||||||
String sampleFilename = "InitialSample.txt";
|
|
||||||
String sampleContent = "Sample content";
|
|
||||||
NodeRef sampleNodeRef = remoteServer.fileFolderRemote.searchSimple(ticket, workingRootNodeRef, sampleFilename);
|
|
||||||
if (sampleNodeRef == null)
|
|
||||||
{
|
|
||||||
FileInfo sampleFileInfo = remoteServer.fileFolderRemote.create(
|
|
||||||
ticket, workingRootNodeRef, sampleFilename, ContentModel.TYPE_CONTENT);
|
|
||||||
sampleNodeRef = sampleFileInfo.getNodeRef();
|
|
||||||
// Write some content
|
|
||||||
byte[] bytes = sampleContent.getBytes("UTF-8");
|
|
||||||
remoteServer.fileFolderRemote.putContent(ticket, sampleNodeRef, bytes, sampleFilename);
|
|
||||||
}
|
|
||||||
// Get the content and ensure that it is the same
|
|
||||||
byte[] bytes = remoteServer.fileFolderRemote.getContent(ticket, sampleNodeRef);
|
|
||||||
if (bytes == null)
|
|
||||||
{
|
|
||||||
problems.add("Sample content was not found on server: " + remoteServer.rmiUrl);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String checkContent = new String(bytes, "UTF-8");
|
|
||||||
if (!checkContent.equals(sampleContent))
|
|
||||||
{
|
|
||||||
problems.add("The sample content differed from expected: " + remoteServer.rmiUrl);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
System.err.println("ERROR: Failure whilst checking server: " + remoteServer.rmiUrl);
|
|
||||||
e.printStackTrace();
|
|
||||||
problems.add(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check for issues
|
|
||||||
if (problems.size() > 0)
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("\n")
|
|
||||||
.append("The working root node references could not be found on all the remote servers.\n")
|
|
||||||
.append("Please ensure that all the remote servers listed are active in a single cluster.");
|
|
||||||
for (String problem : problems)
|
|
||||||
{
|
|
||||||
sb.append("\n")
|
|
||||||
.append(" ").append(problem);
|
|
||||||
}
|
|
||||||
throw new LoaderClientException(sb.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static File[] getSourceFiles(File sourceDir) throws Exception
|
|
||||||
{
|
|
||||||
// Ensure that the source directory is present, if specified
|
|
||||||
if (sourceDir != null)
|
|
||||||
{
|
|
||||||
if (!sourceDir.exists())
|
|
||||||
{
|
|
||||||
throw new LoaderClientException("The source directory to contain upload files is missing: " + sourceDir);
|
|
||||||
}
|
|
||||||
// Check that there is something in it
|
|
||||||
File[] allFiles = sourceDir.listFiles();
|
|
||||||
ArrayList<File> sourceFiles = new ArrayList<File>(allFiles.length);
|
|
||||||
for (File file : allFiles)
|
|
||||||
{
|
|
||||||
if (file.isDirectory())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sourceFiles.add(file);
|
|
||||||
}
|
|
||||||
File[] ret = new File[sourceFiles.size()];
|
|
||||||
return sourceFiles.toArray(ret);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new File[] {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getLineEnding()
|
|
||||||
{
|
|
||||||
return System.getProperty("line.separator", "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void logVerbose(String msg, boolean verbose)
|
|
||||||
{
|
|
||||||
if (!verbose || outVerbose == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
byte[] bytes = msg.getBytes("UTF-8");
|
|
||||||
outVerbose.write(bytes);
|
|
||||||
outVerbose.write(getLineEnding().getBytes("UTF-8"));
|
|
||||||
outVerbose.flush();
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
System.err.println("Failed to write message to verbose file: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void logSummary(String msg)
|
|
||||||
{
|
|
||||||
if (outSummary == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
byte[] bytes = msg.getBytes("UTF-8");
|
|
||||||
outSummary.write(bytes);
|
|
||||||
outSummary.write(getLineEnding().getBytes("UTF-8"));
|
|
||||||
outSummary.flush();
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
System.err.println("Failed to write message to summary file: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void logError(String msg)
|
|
||||||
{
|
|
||||||
if (outSummary == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
byte[] bytes = msg.getBytes("UTF-8");
|
|
||||||
outError.write(bytes);
|
|
||||||
outError.write(getLineEnding().getBytes("UTF-8"));
|
|
||||||
outError.flush();
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
System.err.println("Failed to write message to error file: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void logError(String msg, Throwable e)
|
|
||||||
{
|
|
||||||
if (outSummary == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder(1024);
|
|
||||||
StackTraceUtil.buildStackTrace(msg, e.getStackTrace(), sb, 50);
|
|
||||||
byte[] bytes = sb.toString().getBytes("UTF-8");
|
|
||||||
outError.write(bytes);
|
|
||||||
outError.write(getLineEnding().getBytes("UTF-8"));
|
|
||||||
outError.flush();
|
|
||||||
}
|
|
||||||
catch (Throwable ee)
|
|
||||||
{
|
|
||||||
System.err.println("Failed to write message to error file: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSummary()
|
|
||||||
{
|
|
||||||
List<Integer> folderProfilesAsList = new ArrayList<Integer>(10);
|
|
||||||
for (int folderProfile : folderProfiles)
|
|
||||||
{
|
|
||||||
folderProfilesAsList.add(Integer.valueOf(folderProfile));
|
|
||||||
}
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("Session name: ").append(name).append(getLineEnding())
|
|
||||||
.append("RMI URLS: ").append(rmiUrls).append(getLineEnding())
|
|
||||||
.append("Store References: ").append(storeRefs).append(getLineEnding())
|
|
||||||
.append("Folder Profiles: ").append(folderProfilesAsList).append(getLineEnding())
|
|
||||||
.append("Start Time: ").append(new Date(startTime));
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.alfresco.repo.model.filefolder.loader;
|
|
||||||
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A loader thread that merely reports the size of the remote repository.
|
|
||||||
* @since 2.2
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
*/
|
|
||||||
public class LoaderTotalsThread extends AbstractLoaderThread
|
|
||||||
{
|
|
||||||
public LoaderTotalsThread(
|
|
||||||
LoaderSession session,
|
|
||||||
String loaderName,
|
|
||||||
long testPeriod,
|
|
||||||
long testTotal,
|
|
||||||
long testLoadDepth,
|
|
||||||
boolean verbose)
|
|
||||||
{
|
|
||||||
super(session, loaderName, testPeriod, testTotal, testLoadDepth, verbose);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the remote repository sizes and dumps those.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected String doLoading(LoaderServerProxy serverProxy, NodeRef workingRootNodeRef) throws Exception
|
|
||||||
{
|
|
||||||
return getTotalsMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSummary()
|
|
||||||
{
|
|
||||||
return super.getSummary() + getTotalsMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTotalsMessage()
|
|
||||||
{
|
|
||||||
LoaderServerProxy serverProxy = session.getRemoteServers().get(0);
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
// Get total
|
|
||||||
int totalNodeCount = serverProxy.loaderRemote.getNodeCount(
|
|
||||||
serverProxy.ticket);
|
|
||||||
sb.append(String.format("Total=%d", totalNodeCount));
|
|
||||||
// Get totals for each store
|
|
||||||
for (NodeRef nodeRef : session.getWorkingRootNodeRefs())
|
|
||||||
{
|
|
||||||
StoreRef storeRef = nodeRef.getStoreRef();
|
|
||||||
int storeNodeCount = serverProxy.loaderRemote.getNodeCount(
|
|
||||||
serverProxy.ticket,
|
|
||||||
storeRef);
|
|
||||||
sb.append(", ").append(storeRef.getIdentifier()).append("=").append(storeNodeCount);
|
|
||||||
}
|
|
||||||
// Done
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,105 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
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<String> 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;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,98 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.alfresco.repo.model.filefolder.loader;
|
|
||||||
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
public class LoaderUploadThread extends AbstractLoaderThread
|
|
||||||
{
|
|
||||||
|
|
||||||
private int filesPerUpload;
|
|
||||||
|
|
||||||
public LoaderUploadThread(
|
|
||||||
LoaderSession session,
|
|
||||||
String loaderName,
|
|
||||||
long testPeriod,
|
|
||||||
long testTotal,
|
|
||||||
long testLoadDepth,
|
|
||||||
boolean verbose,
|
|
||||||
long filesPerUpload)
|
|
||||||
{
|
|
||||||
super(session, loaderName, testPeriod, testTotal, testLoadDepth, verbose);
|
|
||||||
this.filesPerUpload = (int) filesPerUpload;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String doLoading(LoaderServerProxy serverProxy, NodeRef workingRootNodeRef) throws Exception
|
|
||||||
{
|
|
||||||
// Get a random folder
|
|
||||||
List<String> folderPath = super.chooseFolderPath();
|
|
||||||
// Make sure the folder exists
|
|
||||||
NodeRef folderNodeRef = makeFolders(serverProxy.ticket, serverProxy, workingRootNodeRef, folderPath);
|
|
||||||
|
|
||||||
// Build a set of files to upload
|
|
||||||
byte[][] bytes = new byte[filesPerUpload][];
|
|
||||||
String[] filenames = new String[filesPerUpload];
|
|
||||||
for (int i = 0; i < filesPerUpload; i++)
|
|
||||||
{
|
|
||||||
// Get a random file
|
|
||||||
File file = getFile();
|
|
||||||
bytes[i] = FileCopyUtils.copyToByteArray(file);
|
|
||||||
// Get the extension
|
|
||||||
filenames[i] = GUID.generate();
|
|
||||||
int index = file.getName().lastIndexOf('.');
|
|
||||||
if (index > 0)
|
|
||||||
{
|
|
||||||
String ext = file.getName().substring(index + 1, file.getName().length());
|
|
||||||
filenames[i] += ("." + ext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload it
|
|
||||||
FileInfo[] fileInfos = serverProxy.loaderRemote.uploadContent(
|
|
||||||
serverProxy.ticket,
|
|
||||||
folderNodeRef,
|
|
||||||
filenames,
|
|
||||||
bytes);
|
|
||||||
|
|
||||||
// Done
|
|
||||||
String msg = String.format("Uploaded %d files to folder: %s", fileInfos.length, folderPath.toString());
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSummary()
|
|
||||||
{
|
|
||||||
String summary = super.getSummary();
|
|
||||||
summary += (String.format("%d files per iteration", filesPerUpload));
|
|
||||||
return summary;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,24 +0,0 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
|
||||||
<ehcache>
|
|
||||||
|
|
||||||
<diskStore
|
|
||||||
path="java.io.tmpdir"/>
|
|
||||||
|
|
||||||
<defaultCache
|
|
||||||
maxElementsInMemory="5000"
|
|
||||||
eternal="true"
|
|
||||||
timeToIdleSeconds="0"
|
|
||||||
timeToLiveSeconds="0"
|
|
||||||
overflowToDisk="false"
|
|
||||||
>
|
|
||||||
</defaultCache>
|
|
||||||
|
|
||||||
<cache
|
|
||||||
name="org.alfresco.LoaderUploadThread.PathCache"
|
|
||||||
maxElementsInMemory="100000"
|
|
||||||
eternal="true"
|
|
||||||
overflowToDisk="true"
|
|
||||||
diskPersistent="true"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</ehcache>
|
|
@@ -1,256 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.alfresco.repo.remote;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.alfresco.service.cmr.model.FileExistsException;
|
|
||||||
import org.alfresco.service.cmr.model.FileInfo;
|
|
||||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
|
||||||
import org.alfresco.service.cmr.remote.FileFolderRemote;
|
|
||||||
import org.alfresco.service.cmr.repository.ContentData;
|
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
|
||||||
import org.alfresco.service.namespace.QName;
|
|
||||||
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Client side implementation of the remotable FileFolder interface.
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
public class FileFolderRemoteClient implements FileFolderRemote
|
|
||||||
{
|
|
||||||
private String rmiUrl;
|
|
||||||
private FileFolderRemote remotePeer;
|
|
||||||
|
|
||||||
public FileFolderRemoteClient(String rmiUrl)
|
|
||||||
{
|
|
||||||
// Ensure the RMI URL is consistent
|
|
||||||
if (!rmiUrl.endsWith("/"))
|
|
||||||
{
|
|
||||||
rmiUrl += "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
this.rmiUrl = rmiUrl;
|
|
||||||
// Connect
|
|
||||||
connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void connect()
|
|
||||||
{
|
|
||||||
// Get the FileFolderServiceTransport
|
|
||||||
RmiProxyFactoryBean fileFolderFactory = new RmiProxyFactoryBean();
|
|
||||||
fileFolderFactory.setRefreshStubOnConnectFailure(true);
|
|
||||||
fileFolderFactory.setServiceInterface(FileFolderRemote.class);
|
|
||||||
fileFolderFactory.setServiceUrl(rmiUrl + FileFolderRemote.SERVICE_NAME);
|
|
||||||
fileFolderFactory.afterPropertiesSet();
|
|
||||||
FileFolderRemote fileFolderRemote = (FileFolderRemote) fileFolderFactory.getObject();
|
|
||||||
this.remotePeer = fileFolderRemote;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public List<FileInfo> list(String ticket, final NodeRef contextNodeRef)
|
|
||||||
{
|
|
||||||
return remotePeer.list(ticket, contextNodeRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public List<FileInfo> listFiles(String ticket, final NodeRef folderNodeRef)
|
|
||||||
{
|
|
||||||
return remotePeer.listFiles(ticket, folderNodeRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public List<FileInfo> listFolders(String ticket, final NodeRef contextNodeRef)
|
|
||||||
{
|
|
||||||
return remotePeer.listFolders(ticket, contextNodeRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public NodeRef searchSimple(String ticket, final NodeRef contextNodeRef, final String name)
|
|
||||||
{
|
|
||||||
return remotePeer.searchSimple(ticket, contextNodeRef, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public List<FileInfo> search(
|
|
||||||
String ticket,
|
|
||||||
final NodeRef contextNodeRef,
|
|
||||||
final String namePattern,
|
|
||||||
final boolean includeSubFolders)
|
|
||||||
{
|
|
||||||
return remotePeer.search(ticket, contextNodeRef, namePattern, includeSubFolders);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public List<FileInfo> search(
|
|
||||||
String ticket,
|
|
||||||
final NodeRef contextNodeRef,
|
|
||||||
final String namePattern,
|
|
||||||
final boolean fileSearch,
|
|
||||||
final boolean folderSearch,
|
|
||||||
final boolean includeSubFolders)
|
|
||||||
{
|
|
||||||
return remotePeer.search(ticket, contextNodeRef, namePattern, fileSearch, folderSearch, includeSubFolders);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo rename(String ticket, final NodeRef fileFolderRef, final String newName) throws FileExistsException, FileNotFoundException
|
|
||||||
{
|
|
||||||
return remotePeer.rename(ticket, fileFolderRef, newName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo move(String ticket, final NodeRef sourceNodeRef, final NodeRef targetParentRef, final String newName)
|
|
||||||
throws FileExistsException, FileNotFoundException
|
|
||||||
{
|
|
||||||
return remotePeer.move(ticket, sourceNodeRef, targetParentRef, newName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo copy(String ticket, final NodeRef sourceNodeRef, final NodeRef targetParentRef, final String newName)
|
|
||||||
throws FileExistsException, FileNotFoundException
|
|
||||||
{
|
|
||||||
return remotePeer.copy(ticket, sourceNodeRef, targetParentRef, newName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo create(String ticket, final NodeRef parentNodeRef, final String name, final QName typeQName) throws FileExistsException
|
|
||||||
{
|
|
||||||
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}
|
|
||||||
*/
|
|
||||||
public void delete(String ticket, final NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
remotePeer.delete(ticket, nodeRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public void delete(String ticket, final NodeRef[] nodeRefs)
|
|
||||||
{
|
|
||||||
remotePeer.delete(ticket, nodeRefs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo makeFolders(String ticket, final NodeRef parentNodeRef, final List<String> pathElements, final QName folderTypeQName)
|
|
||||||
{
|
|
||||||
return remotePeer.makeFolders(ticket, parentNodeRef, pathElements, folderTypeQName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public List<FileInfo> getNamePath(String ticket, final NodeRef rootNodeRef, final NodeRef nodeRef) throws FileNotFoundException
|
|
||||||
{
|
|
||||||
return remotePeer.getNamePath(ticket, rootNodeRef, nodeRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo resolveNamePath(String ticket, final NodeRef rootNodeRef, final List<String> pathElements) throws FileNotFoundException
|
|
||||||
{
|
|
||||||
return remotePeer.resolveNamePath(ticket, rootNodeRef, pathElements);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo getFileInfo(String ticket, final NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
return remotePeer.getFileInfo(ticket, nodeRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public ContentData putContent(String ticket, NodeRef nodeRef, byte[] bytes, String filename)
|
|
||||||
{
|
|
||||||
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}
|
|
||||||
*/
|
|
||||||
public byte[] getContent(String ticket, NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
return remotePeer.getContent(ticket, nodeRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public ContentReader getReader(String ticket, NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public ContentWriter getWriter(String ticket, NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,686 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.alfresco.repo.remote;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.alfresco.repo.model.filefolder.FileFolderServiceImpl;
|
|
||||||
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.model.FileExistsException;
|
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
|
||||||
import org.alfresco.service.cmr.model.FileInfo;
|
|
||||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
|
||||||
import org.alfresco.service.cmr.remote.FileFolderRemote;
|
|
||||||
import org.alfresco.service.cmr.repository.ContentData;
|
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
|
||||||
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.security.AuthenticationService;
|
|
||||||
import org.alfresco.service.namespace.QName;
|
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Server side implementation of the <code>FileFolderService</code> transport
|
|
||||||
* layer. This is the class that gets exported remotely as it contains the
|
|
||||||
* explicit ticket arguments.
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
public class FileFolderRemoteServer implements FileFolderRemote
|
|
||||||
{
|
|
||||||
private RetryingTransactionHelper retryingTransactionHelper;
|
|
||||||
private AuthenticationService authenticationService;
|
|
||||||
private FileFolderService fileFolderService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param transactionService provides transactional support and retrying
|
|
||||||
*/
|
|
||||||
public void setTransactionService(TransactionService transactionService)
|
|
||||||
{
|
|
||||||
this.retryingTransactionHelper = transactionService.getRetryingTransactionHelper();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param authenticationService the service that will validate the tickets
|
|
||||||
*/
|
|
||||||
public void setAuthenticationService(AuthenticationService authenticationService)
|
|
||||||
{
|
|
||||||
this.authenticationService = authenticationService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param filefolderService the service that will do the work
|
|
||||||
*/
|
|
||||||
public void setFileFolderService(FileFolderService filefolderService)
|
|
||||||
{
|
|
||||||
this.fileFolderService = filefolderService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated The mimetype service is no longer needed.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void setMimetypeService(MimetypeService mimetypeService)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public List<FileInfo> list(String ticket, final NodeRef contextNodeRef)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<List<FileInfo>> callback = new RetryingTransactionCallback<List<FileInfo>>()
|
|
||||||
{
|
|
||||||
public List<FileInfo> execute() throws Throwable
|
|
||||||
{
|
|
||||||
return fileFolderService.list(contextNodeRef);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public List<FileInfo> listFiles(String ticket, final NodeRef folderNodeRef)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<List<FileInfo>> callback = new RetryingTransactionCallback<List<FileInfo>>()
|
|
||||||
{
|
|
||||||
public List<FileInfo> execute() throws Throwable
|
|
||||||
{
|
|
||||||
return fileFolderService.listFiles(folderNodeRef);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public List<FileInfo> listFolders(String ticket, final NodeRef contextNodeRef)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<List<FileInfo>> callback = new RetryingTransactionCallback<List<FileInfo>>()
|
|
||||||
{
|
|
||||||
public List<FileInfo> execute() throws Throwable
|
|
||||||
{
|
|
||||||
return fileFolderService.listFolders(contextNodeRef);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public NodeRef searchSimple(String ticket, final NodeRef contextNodeRef, final String name)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<NodeRef> callback = new RetryingTransactionCallback<NodeRef>()
|
|
||||||
{
|
|
||||||
public NodeRef execute() throws Throwable
|
|
||||||
{
|
|
||||||
return fileFolderService.searchSimple(contextNodeRef, name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public List<FileInfo> search(
|
|
||||||
String ticket,
|
|
||||||
final NodeRef contextNodeRef,
|
|
||||||
final String namePattern,
|
|
||||||
final boolean includeSubFolders)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<List<FileInfo>> callback = new RetryingTransactionCallback<List<FileInfo>>()
|
|
||||||
{
|
|
||||||
public List<FileInfo> execute() throws Throwable
|
|
||||||
{
|
|
||||||
return fileFolderService.search(contextNodeRef, namePattern, includeSubFolders);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public List<FileInfo> search(
|
|
||||||
String ticket,
|
|
||||||
final NodeRef contextNodeRef,
|
|
||||||
final String namePattern,
|
|
||||||
final boolean fileSearch,
|
|
||||||
final boolean folderSearch,
|
|
||||||
final boolean includeSubFolders)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<List<FileInfo>> callback = new RetryingTransactionCallback<List<FileInfo>>()
|
|
||||||
{
|
|
||||||
public List<FileInfo> execute() throws Throwable
|
|
||||||
{
|
|
||||||
return fileFolderService.search(contextNodeRef, namePattern, fileSearch, folderSearch, includeSubFolders);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo rename(String ticket, final NodeRef fileFolderRef, final String newName) throws FileExistsException, FileNotFoundException
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
|
||||||
{
|
|
||||||
public FileInfo execute() throws Throwable
|
|
||||||
{
|
|
||||||
return fileFolderService.rename(fileFolderRef, newName);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo move(String ticket, final NodeRef sourceNodeRef, final NodeRef targetParentRef, final String newName)
|
|
||||||
throws FileExistsException, FileNotFoundException
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
|
||||||
{
|
|
||||||
public FileInfo execute() throws Throwable
|
|
||||||
{
|
|
||||||
return fileFolderService.move(sourceNodeRef, targetParentRef, newName);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo copy(String ticket, final NodeRef sourceNodeRef, final NodeRef targetParentRef, final String newName)
|
|
||||||
throws FileExistsException, FileNotFoundException
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
|
||||||
{
|
|
||||||
public FileInfo execute() throws Throwable
|
|
||||||
{
|
|
||||||
return fileFolderService.copy(sourceNodeRef, targetParentRef, newName);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo create(String ticket, final NodeRef parentNodeRef, final String name, final QName typeQName) throws FileExistsException
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
|
||||||
{
|
|
||||||
public FileInfo execute() throws Throwable
|
|
||||||
{
|
|
||||||
return fileFolderService.create(parentNodeRef, name, typeQName);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@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<FileInfo[]> callback = new RetryingTransactionCallback<FileInfo[]>()
|
|
||||||
{
|
|
||||||
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}
|
|
||||||
*/
|
|
||||||
public void delete(String ticket, final NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<Object> callback = new RetryingTransactionCallback<Object>()
|
|
||||||
{
|
|
||||||
public Object execute() throws Throwable
|
|
||||||
{
|
|
||||||
fileFolderService.delete(nodeRef);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
retryingTransactionHelper.doInTransaction(callback, false, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public void delete(String ticket, final NodeRef[] nodeRefs)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<Object> callback = new RetryingTransactionCallback<Object>()
|
|
||||||
{
|
|
||||||
public Object execute() throws Throwable
|
|
||||||
{
|
|
||||||
for (NodeRef nodeRef : nodeRefs)
|
|
||||||
fileFolderService.delete(nodeRef);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
retryingTransactionHelper.doInTransaction(callback, false, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo makeFolders(String ticket, final NodeRef parentNodeRef, final List<String> pathElements, final QName folderTypeQName)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
|
||||||
{
|
|
||||||
public FileInfo execute() throws Throwable
|
|
||||||
{
|
|
||||||
return FileFolderServiceImpl.makeFolders(fileFolderService, parentNodeRef, pathElements, folderTypeQName);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public List<FileInfo> getNamePath(String ticket, final NodeRef rootNodeRef, final NodeRef nodeRef) throws FileNotFoundException
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<List<FileInfo>> callback = new RetryingTransactionCallback<List<FileInfo>>()
|
|
||||||
{
|
|
||||||
public List<FileInfo> execute() throws Throwable
|
|
||||||
{
|
|
||||||
return fileFolderService.getNamePath(rootNodeRef, nodeRef);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo resolveNamePath(String ticket, final NodeRef rootNodeRef, final List<String> pathElements) throws FileNotFoundException
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
|
||||||
{
|
|
||||||
public FileInfo execute() throws Throwable
|
|
||||||
{
|
|
||||||
return fileFolderService.resolveNamePath(rootNodeRef, pathElements);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public FileInfo getFileInfo(String ticket, final NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
|
||||||
{
|
|
||||||
public FileInfo execute() throws Throwable
|
|
||||||
{
|
|
||||||
return fileFolderService.getFileInfo(nodeRef);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public ContentData putContent(
|
|
||||||
String ticket,
|
|
||||||
final NodeRef nodeRef,
|
|
||||||
final byte[] bytes,
|
|
||||||
final String filename)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<ContentData> callback = new RetryingTransactionCallback<ContentData>()
|
|
||||||
{
|
|
||||||
public ContentData execute() throws Throwable
|
|
||||||
{
|
|
||||||
// Get a writer
|
|
||||||
ContentWriter writer = fileFolderService.getWriter(nodeRef);
|
|
||||||
|
|
||||||
// We need the mimetype and encoding finding for us
|
|
||||||
writer.guessEncoding();
|
|
||||||
writer.guessMimetype(filename);
|
|
||||||
|
|
||||||
// Make a stream
|
|
||||||
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
|
|
||||||
|
|
||||||
// Write the stream
|
|
||||||
writer.putContent(is);
|
|
||||||
|
|
||||||
// Done
|
|
||||||
return writer.getContentData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ContentData contentData = retryingTransactionHelper.doInTransaction(callback, false, true);
|
|
||||||
// Done
|
|
||||||
return contentData;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@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<ContentData[]> callback = new RetryingTransactionCallback<ContentData[]>()
|
|
||||||
{
|
|
||||||
public ContentData[] execute() throws Throwable
|
|
||||||
{
|
|
||||||
// Guess the mimetype
|
|
||||||
ContentData[] results = new ContentData[filenames.length];
|
|
||||||
|
|
||||||
for (int i = 0; i < filenames.length; i++)
|
|
||||||
{
|
|
||||||
// Get a writer
|
|
||||||
ContentWriter writer = fileFolderService.getWriter(nodeRefs[i]);
|
|
||||||
|
|
||||||
// We need the mimetype and encoding finding for us
|
|
||||||
writer.guessEncoding();
|
|
||||||
writer.guessMimetype(filenames[i]);
|
|
||||||
|
|
||||||
// Make a stream
|
|
||||||
ByteArrayInputStream is = new ByteArrayInputStream(bytes[i]);
|
|
||||||
|
|
||||||
// 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}
|
|
||||||
*/
|
|
||||||
public byte[] getContent(String ticket, final NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<byte[]> callback = new RetryingTransactionCallback<byte[]>()
|
|
||||||
{
|
|
||||||
public byte[] execute() throws Throwable
|
|
||||||
{
|
|
||||||
// Get a reader
|
|
||||||
ContentReader reader = fileFolderService.getReader(nodeRef);
|
|
||||||
if (!reader.exists())
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the content
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream((int)reader.getSize());
|
|
||||||
reader.getContent(bos);
|
|
||||||
|
|
||||||
// Done
|
|
||||||
return bos.toByteArray();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
byte[] bytes = retryingTransactionHelper.doInTransaction(callback, true, true);
|
|
||||||
// Done
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public ContentReader getReader(String ticket, NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public ContentWriter getWriter(String ticket, NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,434 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.alfresco.repo.remote;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
|
||||||
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.security.AuthenticationService;
|
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
|
||||||
import org.alfresco.service.namespace.QName;
|
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
|
||||||
import org.alfresco.util.PropertyMap;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Server side implementation of the <code>LoaderServiceTransport</code> transport
|
|
||||||
* layer. This is the class that gets exported remotely as it contains the
|
|
||||||
* explicit ticket arguments.
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
public class LoaderRemoteServer implements LoaderRemote
|
|
||||||
{
|
|
||||||
private static Log logger = LogFactory.getLog(LoaderRemoteServer.class);
|
|
||||||
|
|
||||||
/** The association for the working root node: <b>sys:LoaderServiceWorkingRoot</b> */
|
|
||||||
private static final QName ASSOC_WORKING_ROOT = QName.createQName(
|
|
||||||
NamespaceService.SYSTEM_MODEL_1_0_URI,
|
|
||||||
"LoaderServiceWorkingRoot");
|
|
||||||
|
|
||||||
private RetryingTransactionHelper retryingTransactionHelper;
|
|
||||||
private AuthenticationService authenticationService;
|
|
||||||
private NodeService nodeService;
|
|
||||||
private FileFolderService fileFolderService;
|
|
||||||
private FileFolderRemote fileFolderRemote;
|
|
||||||
private CheckOutCheckInService checkOutCheckInService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param transactionService provides transactional support and retrying
|
|
||||||
*/
|
|
||||||
public void setTransactionService(TransactionService transactionService)
|
|
||||||
{
|
|
||||||
this.retryingTransactionHelper = transactionService.getRetryingTransactionHelper();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param authenticationService the service that will validate the tickets
|
|
||||||
*/
|
|
||||||
public void setAuthenticationService(AuthenticationService authenticationService)
|
|
||||||
{
|
|
||||||
this.authenticationService = authenticationService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param nodeService the service that will do the work
|
|
||||||
*/
|
|
||||||
public void setNodeService(NodeService nodeService)
|
|
||||||
{
|
|
||||||
this.nodeService = nodeService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param fileFolderService the file-specific service
|
|
||||||
*/
|
|
||||||
public void setFileFolderService(FileFolderService fileFolderService)
|
|
||||||
{
|
|
||||||
this.fileFolderService = fileFolderService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFileFolderRemote(FileFolderRemote fileFolderRemote)
|
|
||||||
{
|
|
||||||
this.fileFolderRemote = fileFolderRemote;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated The mimetype service is no longer needed.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void setMimetypeService(MimetypeService mimetypeService)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCheckOutCheckInService(CheckOutCheckInService checkOutCheckInService)
|
|
||||||
{
|
|
||||||
this.checkOutCheckInService = checkOutCheckInService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public String authenticate(String username, String password)
|
|
||||||
{
|
|
||||||
// We need to authenticate
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.authenticate(username, password.toCharArray());
|
|
||||||
String ticket = authenticationService.getCurrentTicket();
|
|
||||||
// Done
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("Authenticated: " + username);
|
|
||||||
}
|
|
||||||
return ticket;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public NodeRef getOrCreateWorkingRoot(String ticket, final StoreRef storeRef)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<NodeRef> callback = new RetryingTransactionCallback<NodeRef>()
|
|
||||||
{
|
|
||||||
public NodeRef execute() throws Throwable
|
|
||||||
{
|
|
||||||
NodeRef rootNodeRef = null;
|
|
||||||
// Check if the store exists
|
|
||||||
if (!nodeService.exists(storeRef))
|
|
||||||
{
|
|
||||||
nodeService.createStore(storeRef.getProtocol(), storeRef.getIdentifier());
|
|
||||||
}
|
|
||||||
rootNodeRef = nodeService.getRootNode(storeRef);
|
|
||||||
// Look for the working root
|
|
||||||
List<ChildAssociationRef> assocRefs = nodeService.getChildAssocs(
|
|
||||||
rootNodeRef,
|
|
||||||
ContentModel.ASSOC_CHILDREN,
|
|
||||||
ASSOC_WORKING_ROOT);
|
|
||||||
NodeRef workingRootNodeRef = null;
|
|
||||||
if (assocRefs.size() > 0)
|
|
||||||
{
|
|
||||||
// Just use the first one
|
|
||||||
workingRootNodeRef = assocRefs.get(0).getChildRef();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
String username = authenticationService.getCurrentUserName();
|
|
||||||
// We have to make it. Touch the root node to act as an optimistic lock.
|
|
||||||
nodeService.setProperty(rootNodeRef, ContentModel.PROP_AUTHOR, username);
|
|
||||||
// Add a cm:folder below the root
|
|
||||||
PropertyMap properties = new PropertyMap();
|
|
||||||
properties.put(ContentModel.PROP_NAME, "Loader Application Root");
|
|
||||||
workingRootNodeRef = nodeService.createNode(
|
|
||||||
rootNodeRef,
|
|
||||||
ContentModel.ASSOC_CHILDREN,
|
|
||||||
ASSOC_WORKING_ROOT,
|
|
||||||
ContentModel.TYPE_FOLDER,
|
|
||||||
properties).getChildRef();
|
|
||||||
}
|
|
||||||
// Done
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("Got working root node: " + workingRootNodeRef);
|
|
||||||
}
|
|
||||||
return workingRootNodeRef;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public int getNodeCount(String ticket)
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException("getNodeCount cannot be accurately determined at low cost.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public int getNodeCount(String ticket, final StoreRef storeRef)
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException("getNodeCount cannot be accurately determined at low cost.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileInfo[] uploadContent(
|
|
||||||
String ticket,
|
|
||||||
final NodeRef folderNodeRef,
|
|
||||||
final String[] filenames,
|
|
||||||
final byte[][] bytes)
|
|
||||||
{
|
|
||||||
if (filenames.length < bytes.length)
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("The number of files must match the number of binary byte arrays given.");
|
|
||||||
}
|
|
||||||
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
|
|
||||||
// Make the call
|
|
||||||
RetryingTransactionCallback<FileInfo[]> callback = new RetryingTransactionCallback<FileInfo[]>()
|
|
||||||
{
|
|
||||||
public FileInfo[] execute() throws Throwable
|
|
||||||
{
|
|
||||||
FileInfo[] results = new FileInfo[filenames.length];
|
|
||||||
// Create each file
|
|
||||||
for (int i = 0; i < filenames.length; i++)
|
|
||||||
{
|
|
||||||
// Create the file
|
|
||||||
FileInfo newFileInfo = fileFolderService.create(
|
|
||||||
folderNodeRef,
|
|
||||||
filenames[i],
|
|
||||||
ContentModel.TYPE_CONTENT);
|
|
||||||
results[i] = newFileInfo;
|
|
||||||
NodeRef newFileNodeRef = newFileInfo.getNodeRef();
|
|
||||||
|
|
||||||
// Get a writer
|
|
||||||
ContentWriter writer = fileFolderService.getWriter(newFileNodeRef);
|
|
||||||
|
|
||||||
// We need the encoding and mimetype guessing
|
|
||||||
writer.guessMimetype(filenames[i]);
|
|
||||||
writer.guessEncoding();
|
|
||||||
|
|
||||||
// Make a stream
|
|
||||||
ByteArrayInputStream is = new ByteArrayInputStream(bytes[i]);
|
|
||||||
|
|
||||||
// Write the stream
|
|
||||||
writer.putContent(is);
|
|
||||||
}
|
|
||||||
// Done
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.popAuthentication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public void coci(String ticket, final NodeRef[] nodeRef, byte[][] bytes, List<HashMap<String, Serializable>> 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<String, Serializable>());
|
|
||||||
}
|
|
||||||
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<NodeRef> callback = new RetryingTransactionCallback<NodeRef>()
|
|
||||||
{
|
|
||||||
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<FileInfo[]> callback = new RetryingTransactionCallback<FileInfo[]>()
|
|
||||||
{
|
|
||||||
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<String, Serializable> versionProperties)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
RetryingTransactionCallback<NodeRef> callback = new RetryingTransactionCallback<NodeRef>()
|
|
||||||
{
|
|
||||||
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<HashMap<String, Serializable>> versionProperties)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.pushAuthentication();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticationService.validate(ticket);
|
|
||||||
RetryingTransactionCallback<NodeRef[]> callback = new RetryingTransactionCallback<NodeRef[]>()
|
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,212 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.alfresco.service.cmr.remote;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.alfresco.service.cmr.model.FileExistsException;
|
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
|
||||||
import org.alfresco.service.cmr.model.FileInfo;
|
|
||||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
|
||||||
import org.alfresco.service.cmr.repository.ContentData;
|
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
|
||||||
import org.alfresco.service.namespace.QName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remote transport interface for the <code>FileFolderService</code>. This includes the
|
|
||||||
* authentication tickets and abstracts the stream transport as well.
|
|
||||||
* <p/>
|
|
||||||
* <b>NOTE:</b> This is not a production API and will most definitely be changed or removed.
|
|
||||||
*
|
|
||||||
* @see org.alfresco.service.cmr.model.FileFolderService
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
* @since 2.2.
|
|
||||||
*/
|
|
||||||
public interface FileFolderRemote
|
|
||||||
{
|
|
||||||
/** The service name <b>org.alfresco.FileFolderRemote</b> */
|
|
||||||
public static final String SERVICE_NAME = "org.alfresco.FileFolderRemote";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#list(NodeRef)
|
|
||||||
*/
|
|
||||||
public List<FileInfo> list(String ticket, NodeRef contextNodeRef);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#listFiles(NodeRef)
|
|
||||||
*/
|
|
||||||
public List<FileInfo> listFiles(String ticket, NodeRef folderNodeRef);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#listFolders(NodeRef)
|
|
||||||
*/
|
|
||||||
public List<FileInfo> listFolders(String ticket, NodeRef contextNodeRef);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#searchSimple(NodeRef, String)
|
|
||||||
*/
|
|
||||||
public NodeRef searchSimple(String ticket, NodeRef contextNodeRef, String name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#search(NodeRef, String, boolean)
|
|
||||||
*/
|
|
||||||
public List<FileInfo> search(
|
|
||||||
String ticket,
|
|
||||||
NodeRef contextNodeRef,
|
|
||||||
String namePattern,
|
|
||||||
boolean includeSubFolders);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#search(NodeRef, String, boolean, boolean, boolean)
|
|
||||||
*/
|
|
||||||
public List<FileInfo> search(
|
|
||||||
String ticket,
|
|
||||||
NodeRef contextNodeRef,
|
|
||||||
String namePattern,
|
|
||||||
boolean fileSearch,
|
|
||||||
boolean folderSearch,
|
|
||||||
boolean includeSubFolders);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#rename(NodeRef, String)
|
|
||||||
*/
|
|
||||||
public FileInfo rename(String ticket, NodeRef fileFolderRef, String newName) throws FileExistsException, FileNotFoundException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#move(NodeRef, NodeRef, String)
|
|
||||||
*/
|
|
||||||
public FileInfo move(String ticket, NodeRef sourceNodeRef, NodeRef targetParentRef, String newName)
|
|
||||||
throws FileExistsException, FileNotFoundException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#copy(NodeRef, NodeRef, String)
|
|
||||||
*/
|
|
||||||
public FileInfo copy(String ticket, NodeRef sourceNodeRef, NodeRef targetParentRef, String newName)
|
|
||||||
throws FileExistsException, FileNotFoundException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#create(NodeRef, String, QName)
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
*
|
|
||||||
* @see FileFolderService#delete(NodeRef)
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
*
|
|
||||||
* @see FileFolderService#makeFolders(NodeRef, List, QName)
|
|
||||||
*/
|
|
||||||
public FileInfo makeFolders(String ticket, NodeRef parentNodeRef, List<String> pathElements, QName folderTypeQName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#getNamePath(NodeRef, NodeRef)
|
|
||||||
*/
|
|
||||||
public List<FileInfo> getNamePath(String ticket, NodeRef rootNodeRef, NodeRef nodeRef) throws FileNotFoundException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#resolveNamePath(NodeRef, List)
|
|
||||||
*/
|
|
||||||
public FileInfo resolveNamePath(String ticket, NodeRef rootNodeRef, List<String> pathElements) throws FileNotFoundException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#getFileInfo(NodeRef)
|
|
||||||
*/
|
|
||||||
public FileInfo getFileInfo(String ticket, NodeRef nodeRef);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Refactor!!!
|
|
||||||
* The dirtiest of hacks. When time permits, the APIs and implementations will be properly refactored.
|
|
||||||
* For now, this remains adequate for small files.
|
|
||||||
*/
|
|
||||||
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!!!
|
|
||||||
*/
|
|
||||||
public byte[] getContent(String ticket, NodeRef nodeRef);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#getReader(NodeRef)
|
|
||||||
*/
|
|
||||||
public ContentReader getReader(String ticket, NodeRef nodeRef);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token the authentication ticket
|
|
||||||
*
|
|
||||||
* @see FileFolderService#getWriter(NodeRef)
|
|
||||||
*/
|
|
||||||
public ContentWriter getWriter(String ticket, NodeRef nodeRef);
|
|
||||||
}
|
|
@@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.alfresco.service.cmr.remote;
|
|
||||||
|
|
||||||
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
|
|
||||||
* interfaces.
|
|
||||||
*
|
|
||||||
* @see FileFolderRemote
|
|
||||||
*
|
|
||||||
* @author Derek Hulley
|
|
||||||
* @since 2.2.
|
|
||||||
*/
|
|
||||||
public interface LoaderRemote
|
|
||||||
{
|
|
||||||
/** The service name <b>org.alfresco.LoaderRemote</b> */
|
|
||||||
public static final String SERVICE_NAME = "org.alfresco.LoaderRemote";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authenticate on the server using the given username and password
|
|
||||||
*
|
|
||||||
* @return the authentication ticket
|
|
||||||
*/
|
|
||||||
public String authenticate(String username, String password);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the working <b>cm:folder</b> node for the given store. If there is no working
|
|
||||||
* root node, then one is created.
|
|
||||||
*
|
|
||||||
* @param ticket the authentication ticket
|
|
||||||
* @param storeRef the store reference
|
|
||||||
* @return a working <b>cm:folder</b> to use as the root for loading,
|
|
||||||
* or <tt>null</tt> if it is not available.
|
|
||||||
*/
|
|
||||||
public NodeRef getOrCreateWorkingRoot(String ticket, StoreRef storeRef);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ticket the authentication ticket
|
|
||||||
* @return Returns the total number of ADM nodes
|
|
||||||
*/
|
|
||||||
public int getNodeCount(String ticket);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ticket the authentication ticket
|
|
||||||
* @param storeRef the store to query against
|
|
||||||
* @return Returns the total number of nodes for the given ADM store
|
|
||||||
*/
|
|
||||||
public int getNodeCount(String ticket, StoreRef storeRef);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Upload multiple files to a folder.
|
|
||||||
*
|
|
||||||
* @param ticket the authentication ticket
|
|
||||||
* @param folderNodeRef the folder to upload to
|
|
||||||
* @param filenames the names of the files to upload
|
|
||||||
* @param bytes the contents of the files
|
|
||||||
* @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<HashMap<String, Serializable>> 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<HashMap<String, Serializable>> versionProperties);
|
|
||||||
|
|
||||||
}
|
|
Reference in New Issue
Block a user