mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Big honkin' merge from head. Sheesh!
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3617 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -31,6 +31,7 @@ import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
@@ -236,10 +237,80 @@ public class FileFolderPerformanceTester extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public void test_2_ordered_1_10() throws Exception
|
||||
private void readStructure(
|
||||
final NodeRef parentNodeRef,
|
||||
final int threadCount,
|
||||
final int repetitions,
|
||||
final double[] dumpPoints)
|
||||
{
|
||||
buildStructure(rootFolderRef, 2, false, 1, 10, null);
|
||||
final List<ChildAssociationRef> children = nodeService.getChildAssocs(parentNodeRef);
|
||||
Runnable runnable = new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
// authenticate
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
for (int i = 0; i < repetitions; i++)
|
||||
{
|
||||
// read the contents of each folder
|
||||
for (ChildAssociationRef childAssociationRef : children)
|
||||
{
|
||||
final NodeRef folderRef = childAssociationRef.getChildRef();
|
||||
TransactionWork<Object> readWork = new TransactionWork<Object>()
|
||||
{
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
// read the child associations of the folder
|
||||
nodeService.getChildAssocs(folderRef);
|
||||
// get the type
|
||||
nodeService.getType(folderRef);
|
||||
// done
|
||||
return null;
|
||||
};
|
||||
};
|
||||
TransactionUtil.executeInUserTransaction(transactionService, readWork, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// kick off the required number of threads
|
||||
logger.debug("\n" +
|
||||
"Starting " + threadCount +
|
||||
" threads reading properties and children of " + children.size() +
|
||||
" folder " + repetitions +
|
||||
" times.");
|
||||
ThreadGroup threadGroup = new ThreadGroup(getName());
|
||||
Thread[] threads = new Thread[threadCount];
|
||||
for (int i = 0; i < threadCount; i++)
|
||||
{
|
||||
threads[i] = new Thread(threadGroup, runnable, String.format("FileReader-%02d", i));
|
||||
threads[i].start();
|
||||
}
|
||||
// join each thread so that we wait for them all to finish
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
threads[i].join();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// not too serious - the worker threads are non-daemon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void test_1_ordered_1_10() throws Exception
|
||||
{
|
||||
buildStructure(rootFolderRef, 1, false, 1, 10, null);
|
||||
}
|
||||
// public void test_1_ordered_1_10_read() throws Exception
|
||||
// {
|
||||
// buildStructure(rootFolderRef, 1, false, 50, 1, null);
|
||||
// readStructure(rootFolderRef, 50, 1000, null);
|
||||
// }
|
||||
//
|
||||
// public void test_4_ordered_10_100() throws Exception
|
||||
// {
|
||||
@@ -250,24 +321,44 @@ public class FileFolderPerformanceTester extends TestCase
|
||||
// {
|
||||
// buildStructure(rootFolderRef, 4, true, 10, 100, new double[] {0.25, 0.50, 0.75});
|
||||
// }
|
||||
public void test_4_shuffled_100_100() throws Exception
|
||||
// public void test_1_ordered_100_100() throws Exception
|
||||
// {
|
||||
// buildStructure(
|
||||
// rootFolderRef,
|
||||
// 1,
|
||||
// false,
|
||||
// 100,
|
||||
// 100,
|
||||
// new double[] {0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
|
||||
// }
|
||||
// public void test_1_shuffled_10_400() throws Exception
|
||||
// {
|
||||
// buildStructure(
|
||||
// rootFolderRef,
|
||||
// 1,
|
||||
// true,
|
||||
// 10,
|
||||
// 400,
|
||||
// new double[] {0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
|
||||
// }
|
||||
public void test_4_shuffled_10_100() throws Exception
|
||||
{
|
||||
buildStructure(
|
||||
rootFolderRef,
|
||||
4,
|
||||
true,
|
||||
10,
|
||||
100,
|
||||
100,
|
||||
new double[] {0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
|
||||
new double[] {0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
|
||||
}
|
||||
// public void test_4_shuffled_1000_1000() throws Exception
|
||||
// public void test_1_ordered_1_50000() throws Exception
|
||||
// {
|
||||
// buildStructure(
|
||||
// rootFolderRef,
|
||||
// 4,
|
||||
// true,
|
||||
// 1000,
|
||||
// 1000,
|
||||
// new double[] {0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
|
||||
// 1,
|
||||
// false,
|
||||
// 1,
|
||||
// 50000,
|
||||
// new double[] {0.01, 0.02, 0.03, 0.04, 0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
|
||||
// }
|
||||
}
|
||||
|
@@ -39,12 +39,16 @@ import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.CopyService;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||
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.Path;
|
||||
import org.alfresco.service.cmr.search.QueryParameterDefinition;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.ResultSetRow;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
@@ -59,24 +63,30 @@ import org.apache.commons.logging.LogFactory;
|
||||
*/
|
||||
public class FileFolderServiceImpl implements FileFolderService
|
||||
{
|
||||
/** Shallow search for all files */
|
||||
private static final String XPATH_QUERY_SHALLOW_FILES =
|
||||
"./*" +
|
||||
"[(subtypeOf('" + ContentModel.TYPE_CONTENT + "'))]";
|
||||
|
||||
/** Shallow search for all folder */
|
||||
private static final String XPATH_QUERY_SHALLOW_FOLDERS =
|
||||
"./*" +
|
||||
"[not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" +
|
||||
" and (subtypeOf('" + ContentModel.TYPE_FOLDER + "'))]";
|
||||
|
||||
/** Shallow search for all files and folders */
|
||||
/** Shallow search for files and folders with a name pattern */
|
||||
private static final String XPATH_QUERY_SHALLOW_ALL =
|
||||
"./*" +
|
||||
"[like(@cm:name, $cm:name, false)" +
|
||||
" and not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" +
|
||||
" and (subtypeOf('" + ContentModel.TYPE_FOLDER + "') or subtypeOf('" + ContentModel.TYPE_CONTENT + "'))]";
|
||||
|
||||
/** Shallow search for all files and folders */
|
||||
private static final String LUCENE_QUERY_SHALLOW_ALL =
|
||||
"+PARENT:\"${cm:parent}\"" +
|
||||
"-TYPE:\"" + ContentModel.TYPE_SYSTEM_FOLDER + "\" ";
|
||||
|
||||
/** Shallow search for all files and folders */
|
||||
private static final String LUCENE_QUERY_SHALLOW_FOLDERS =
|
||||
"+PARENT:\"${cm:parent}\"" +
|
||||
"-TYPE:\"" + ContentModel.TYPE_SYSTEM_FOLDER + "\" " +
|
||||
"+TYPE:\"" + ContentModel.TYPE_FOLDER + "\" ";
|
||||
|
||||
/** Shallow search for all files and folders */
|
||||
private static final String LUCENE_QUERY_SHALLOW_FILES =
|
||||
"+PARENT:\"${cm:parent}\"" +
|
||||
"-TYPE:\"" + ContentModel.TYPE_SYSTEM_FOLDER + "\" " +
|
||||
"+TYPE:\"" + ContentModel.TYPE_CONTENT + "\" ";
|
||||
|
||||
/** Deep search for files and folders with a name pattern */
|
||||
private static final String XPATH_QUERY_DEEP_ALL =
|
||||
".//*" +
|
||||
@@ -85,8 +95,8 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
" and (subtypeOf('" + ContentModel.TYPE_FOLDER + "') or subtypeOf('" + ContentModel.TYPE_CONTENT + "'))]";
|
||||
|
||||
/** empty parameters */
|
||||
private static final QueryParameterDefinition[] PARAMS_EMPTY = new QueryParameterDefinition[0];
|
||||
private static final QueryParameterDefinition[] PARAMS_ANY_NAME = new QueryParameterDefinition[1];
|
||||
private static final QName PARAM_QNAME_PARENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "parent");
|
||||
|
||||
private static Log logger = LogFactory.getLog(FileFolderServiceImpl.class);
|
||||
|
||||
@@ -100,6 +110,7 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
|
||||
// TODO: Replace this with a more formal means of identifying "system" folders (i.e. aspect or UUID)
|
||||
private List systemPaths;
|
||||
private DataTypeDefinition dataTypeNodeRef;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
@@ -157,6 +168,7 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
dictionaryService.getDataType(DataTypeDefinition.TEXT),
|
||||
true,
|
||||
"%");
|
||||
dataTypeNodeRef = dictionaryService.getDataType(DataTypeDefinition.NODE_REF);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,22 +206,6 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
return fileInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that a file or folder with the given name does not already exist
|
||||
*
|
||||
* @throws FileExistsException if a same-named file or folder already exists
|
||||
*/
|
||||
private void checkExists(NodeRef parentFolderRef, String name)
|
||||
throws FileExistsException
|
||||
{
|
||||
// check for existing file or folder
|
||||
List<FileInfo> existingFileInfos = this.search(parentFolderRef, name, true, true, false);
|
||||
if (existingFileInfos.size() > 0)
|
||||
{
|
||||
throw new FileExistsException(existingFileInfos.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception when the type is not a valid File or Folder type
|
||||
*
|
||||
@@ -258,18 +254,10 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Use Lucene search to get file attributes without having to visit the node service
|
||||
*/
|
||||
public List<FileInfo> list(NodeRef contextNodeRef)
|
||||
{
|
||||
// execute the query
|
||||
List<NodeRef> nodeRefs = searchService.selectNodes(
|
||||
contextNodeRef,
|
||||
XPATH_QUERY_SHALLOW_ALL,
|
||||
PARAMS_ANY_NAME,
|
||||
namespaceService,
|
||||
false);
|
||||
List<NodeRef> nodeRefs = luceneSearch(contextNodeRef, true, true);
|
||||
// convert the noderefs
|
||||
List<FileInfo> results = toFileInfo(nodeRefs);
|
||||
// done
|
||||
@@ -282,18 +270,10 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Use Lucene search to get file attributes without having to visit the node service
|
||||
*/
|
||||
public List<FileInfo> listFiles(NodeRef contextNodeRef)
|
||||
{
|
||||
// execute the query
|
||||
List<NodeRef> nodeRefs = searchService.selectNodes(
|
||||
contextNodeRef,
|
||||
XPATH_QUERY_SHALLOW_FILES,
|
||||
PARAMS_EMPTY,
|
||||
namespaceService,
|
||||
false);
|
||||
List<NodeRef> nodeRefs = luceneSearch(contextNodeRef, false, true);
|
||||
// convert the noderefs
|
||||
List<FileInfo> results = toFileInfo(nodeRefs);
|
||||
// done
|
||||
@@ -306,18 +286,10 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Use Lucene search to get file attributes without having to visit the node service
|
||||
*/
|
||||
public List<FileInfo> listFolders(NodeRef contextNodeRef)
|
||||
{
|
||||
// execute the query
|
||||
List<NodeRef> nodeRefs = searchService.selectNodes(
|
||||
contextNodeRef,
|
||||
XPATH_QUERY_SHALLOW_FOLDERS,
|
||||
PARAMS_EMPTY,
|
||||
namespaceService,
|
||||
false);
|
||||
List<NodeRef> nodeRefs = luceneSearch(contextNodeRef, true, false);
|
||||
// convert the noderefs
|
||||
List<FileInfo> results = toFileInfo(nodeRefs);
|
||||
// done
|
||||
@@ -329,6 +301,20 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public NodeRef searchSimple(NodeRef contextNodeRef, String name)
|
||||
{
|
||||
NodeRef childNodeRef = nodeService.getChildByName(contextNodeRef, ContentModel.ASSOC_CONTAINS, name);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(
|
||||
"Simple name search results: \n" +
|
||||
" parent: " + contextNodeRef + "\n" +
|
||||
" name: " + name + "\n" +
|
||||
" result: " + childNodeRef);
|
||||
}
|
||||
return childNodeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #search(NodeRef, String, boolean, boolean, boolean)
|
||||
@@ -338,6 +324,7 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
return search(contextNodeRef, namePattern, true, true, includeSubFolders);
|
||||
}
|
||||
|
||||
private static final String LUCENE_MULTI_CHAR_WILDCARD = "*";
|
||||
/**
|
||||
* Full search with all options
|
||||
*/
|
||||
@@ -348,50 +335,9 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
boolean folderSearch,
|
||||
boolean includeSubFolders)
|
||||
{
|
||||
// shortcut if the search is requesting nothing
|
||||
if (!fileSearch && !folderSearch)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// get the raw nodeRefs
|
||||
List<NodeRef> nodeRefs = searchInternal(contextNodeRef, namePattern, fileSearch, folderSearch, includeSubFolders);
|
||||
|
||||
// if the name pattern is null, then we use the ANY pattern
|
||||
QueryParameterDefinition[] params = null;
|
||||
if (namePattern != null)
|
||||
{
|
||||
// the interface specifies the Lucene syntax, so perform a conversion
|
||||
namePattern = SearchLanguageConversion.convert(
|
||||
SearchLanguageConversion.DEF_LUCENE,
|
||||
SearchLanguageConversion.DEF_XPATH_LIKE,
|
||||
namePattern);
|
||||
|
||||
params = new QueryParameterDefinition[1];
|
||||
params[0] = new QueryParameterDefImpl(
|
||||
ContentModel.PROP_NAME,
|
||||
dictionaryService.getDataType(DataTypeDefinition.TEXT),
|
||||
true,
|
||||
namePattern);
|
||||
}
|
||||
else
|
||||
{
|
||||
params = PARAMS_ANY_NAME;
|
||||
}
|
||||
// determine the correct query to use
|
||||
String query = null;
|
||||
if (includeSubFolders)
|
||||
{
|
||||
query = XPATH_QUERY_DEEP_ALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
query = XPATH_QUERY_SHALLOW_ALL;
|
||||
}
|
||||
// execute the query
|
||||
List<NodeRef> nodeRefs = searchService.selectNodes(
|
||||
contextNodeRef,
|
||||
query,
|
||||
params,
|
||||
namespaceService,
|
||||
false);
|
||||
List<FileInfo> results = toFileInfo(nodeRefs);
|
||||
// eliminate unwanted files/folders
|
||||
Iterator<FileInfo> iterator = results.iterator();
|
||||
@@ -420,6 +366,133 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a full search, but doesn't translate the node references into
|
||||
* file info objects. This allows {@link #checkExists(NodeRef, String)} to
|
||||
* bypass the retrieval of node properties.
|
||||
*/
|
||||
private List<NodeRef> searchInternal(
|
||||
NodeRef contextNodeRef,
|
||||
String namePattern,
|
||||
boolean fileSearch,
|
||||
boolean folderSearch,
|
||||
boolean includeSubFolders)
|
||||
{
|
||||
// shortcut if the search is requesting nothing
|
||||
if (!fileSearch && !folderSearch)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (namePattern == null)
|
||||
{
|
||||
namePattern = LUCENE_MULTI_CHAR_WILDCARD; // default to wildcard
|
||||
}
|
||||
// now check if we can use Lucene to handle this query
|
||||
boolean useLucene = false;
|
||||
boolean anyName = namePattern.equals(LUCENE_MULTI_CHAR_WILDCARD);
|
||||
if (!includeSubFolders && anyName)
|
||||
{
|
||||
// Lucene only handles any name or exact name
|
||||
useLucene = true;
|
||||
}
|
||||
|
||||
List<NodeRef> nodeRefs = null;
|
||||
if (!useLucene) // go with the XPath queries
|
||||
{
|
||||
// if the name pattern is null, then we use the ANY pattern
|
||||
QueryParameterDefinition[] params = null;
|
||||
if (namePattern != null)
|
||||
{
|
||||
// the interface specifies the Lucene syntax, so perform a conversion
|
||||
namePattern = SearchLanguageConversion.convert(
|
||||
SearchLanguageConversion.DEF_LUCENE,
|
||||
SearchLanguageConversion.DEF_XPATH_LIKE,
|
||||
namePattern);
|
||||
|
||||
params = new QueryParameterDefinition[1];
|
||||
params[0] = new QueryParameterDefImpl(
|
||||
ContentModel.PROP_NAME,
|
||||
dictionaryService.getDataType(DataTypeDefinition.TEXT),
|
||||
true,
|
||||
namePattern);
|
||||
}
|
||||
else
|
||||
{
|
||||
params = PARAMS_ANY_NAME;
|
||||
}
|
||||
// determine the correct query to use
|
||||
String query = null;
|
||||
if (includeSubFolders)
|
||||
{
|
||||
query = XPATH_QUERY_DEEP_ALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
query = XPATH_QUERY_SHALLOW_ALL;
|
||||
}
|
||||
// execute the query
|
||||
nodeRefs = searchService.selectNodes(
|
||||
contextNodeRef,
|
||||
query,
|
||||
params,
|
||||
namespaceService,
|
||||
false);
|
||||
}
|
||||
else // go with Lucene queries
|
||||
{
|
||||
nodeRefs = luceneSearch(contextNodeRef, folderSearch, fileSearch);
|
||||
}
|
||||
// done
|
||||
return nodeRefs;
|
||||
}
|
||||
|
||||
private List<NodeRef> luceneSearch(NodeRef contextNodeRef, boolean folders, boolean files)
|
||||
{
|
||||
SearchParameters params = new SearchParameters();
|
||||
params.setLanguage(SearchService.LANGUAGE_LUCENE);
|
||||
params.addStore(contextNodeRef.getStoreRef());
|
||||
// set the parent parameter
|
||||
QueryParameterDefinition parentParamDef = new QueryParameterDefImpl(
|
||||
PARAM_QNAME_PARENT,
|
||||
dataTypeNodeRef,
|
||||
true,
|
||||
contextNodeRef.toString());
|
||||
params.addQueryParameterDefinition(parentParamDef);
|
||||
if (folders && files) // search for both files and folders
|
||||
{
|
||||
params.setQuery(LUCENE_QUERY_SHALLOW_ALL);
|
||||
}
|
||||
else if (folders) // search for folders only
|
||||
{
|
||||
params.setQuery(LUCENE_QUERY_SHALLOW_FOLDERS);
|
||||
}
|
||||
else if (files) // search for files only
|
||||
{
|
||||
params.setQuery(LUCENE_QUERY_SHALLOW_FILES);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Must search for either files or folders or both");
|
||||
}
|
||||
ResultSet rs = searchService.query(params);
|
||||
int length = rs.length();
|
||||
List<NodeRef> nodeRefs = new ArrayList<NodeRef>(length);
|
||||
try
|
||||
{
|
||||
for (ResultSetRow row : rs)
|
||||
{
|
||||
nodeRefs.add(row.getNodeRef());
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
rs.close();
|
||||
}
|
||||
// done
|
||||
return nodeRefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #move(NodeRef, NodeRef, String)
|
||||
@@ -467,10 +540,9 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
targetParentRef = assocRef.getParentRef();
|
||||
}
|
||||
|
||||
boolean checkExists = true;
|
||||
// there is nothing to do if both the name and parent folder haven't changed
|
||||
if (targetParentRef.equals(assocRef.getParentRef()))
|
||||
{
|
||||
// there is nothing to do if both the name and parent folder haven't changed
|
||||
if (newName.equals(beforeFileInfo.getName()))
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
@@ -484,18 +556,9 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
}
|
||||
else if (newName.equalsIgnoreCase(beforeFileInfo.getName()))
|
||||
{
|
||||
// name has only changed case so don't bother with exists check
|
||||
checkExists = false;
|
||||
}
|
||||
}
|
||||
|
||||
// check for existing file or folder (if name has changed)
|
||||
if (checkExists)
|
||||
{
|
||||
checkExists(targetParentRef, newName);
|
||||
}
|
||||
|
||||
|
||||
QName qname = QName.createQName(
|
||||
NamespaceService.CONTENT_MODEL_1_0_URI,
|
||||
QName.createValidLocalName(newName));
|
||||
@@ -536,8 +599,15 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
String currentName = (String)nodeService.getProperty(targetNodeRef, ContentModel.PROP_NAME);
|
||||
if (currentName.equals(newName) == false)
|
||||
{
|
||||
// changed the name property
|
||||
nodeService.setProperty(targetNodeRef, ContentModel.PROP_NAME, newName);
|
||||
try
|
||||
{
|
||||
// changed the name property
|
||||
nodeService.setProperty(targetNodeRef, ContentModel.PROP_NAME, newName);
|
||||
}
|
||||
catch (DuplicateChildNodeNameException e)
|
||||
{
|
||||
throw new FileExistsException(targetParentRef, newName);
|
||||
}
|
||||
}
|
||||
|
||||
// get the details after the operation
|
||||
@@ -581,9 +651,6 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
throw new AlfrescoRuntimeException("The type is not supported by this service: " + typeQName);
|
||||
}
|
||||
|
||||
// check for existing file or folder
|
||||
checkExists(parentNodeRef, name);
|
||||
|
||||
// set up initial properties
|
||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(11);
|
||||
properties.put(ContentModel.PROP_NAME, (Serializable) name);
|
||||
@@ -599,12 +666,21 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
QName qname = QName.createQName(
|
||||
NamespaceService.CONTENT_MODEL_1_0_URI,
|
||||
QName.createValidLocalName(name));
|
||||
ChildAssociationRef assocRef = nodeService.createNode(
|
||||
parentNodeRef,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
qname,
|
||||
typeQName,
|
||||
properties);
|
||||
ChildAssociationRef assocRef = null;
|
||||
try
|
||||
{
|
||||
assocRef = nodeService.createNode(
|
||||
parentNodeRef,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
qname,
|
||||
typeQName,
|
||||
properties);
|
||||
}
|
||||
catch (DuplicateChildNodeNameException e)
|
||||
{
|
||||
throw new FileExistsException(parentNodeRef, name);
|
||||
}
|
||||
|
||||
NodeRef nodeRef = assocRef.getChildRef();
|
||||
FileInfo fileInfo = toFileInfo(nodeRef);
|
||||
// done
|
||||
@@ -639,31 +715,25 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
|
||||
NodeRef currentParentRef = parentNodeRef;
|
||||
// just loop and create if necessary
|
||||
FileInfo lastFileInfo = null;
|
||||
for (String pathElement : pathElements)
|
||||
{
|
||||
try
|
||||
// does it exist?
|
||||
NodeRef nodeRef = searchSimple(currentParentRef, pathElement);
|
||||
if (nodeRef == null)
|
||||
{
|
||||
// not present - make it
|
||||
FileInfo createdFileInfo = create(currentParentRef, pathElement, folderTypeQName);
|
||||
currentParentRef = createdFileInfo.getNodeRef();
|
||||
lastFileInfo = createdFileInfo;
|
||||
}
|
||||
catch (FileExistsException e)
|
||||
else
|
||||
{
|
||||
// it exists - just get it
|
||||
List<FileInfo> fileInfos = search(currentParentRef, pathElement, false, true, false);
|
||||
if (fileInfos.size() == 0)
|
||||
{
|
||||
// ? It must have been removed
|
||||
throw new AlfrescoRuntimeException("Path element has just been removed: " + pathElement);
|
||||
}
|
||||
currentParentRef = fileInfos.get(0).getNodeRef();
|
||||
lastFileInfo = fileInfos.get(0);
|
||||
// it exists
|
||||
currentParentRef = nodeRef;
|
||||
}
|
||||
}
|
||||
// done
|
||||
return lastFileInfo;
|
||||
FileInfo fileInfo = toFileInfo(currentParentRef);
|
||||
return fileInfo;
|
||||
}
|
||||
|
||||
public List<FileInfo> getNamePath(NodeRef rootNodeRef, NodeRef nodeRef) throws FileNotFoundException
|
||||
|
@@ -66,7 +66,8 @@ public class FileFolderServiceImplTest extends TestCase
|
||||
private static final String NAME_L1_FILE_A = "L1- File A";
|
||||
private static final String NAME_L1_FILE_B = "L1- File B";
|
||||
private static final String NAME_L1_FILE_C = "L1- File C (%_)";
|
||||
private static final String NAME_DUPLICATE = "DUPLICATE";
|
||||
private static final String NAME_CHECK_FILE = "CHECK_FILE";
|
||||
private static final String NAME_CHECK_FOLDER = "CHECK_FOLDER";
|
||||
|
||||
private static final ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
|
||||
@@ -258,11 +259,11 @@ public class FileFolderServiceImplTest extends TestCase
|
||||
*/
|
||||
public void testGetByName() throws Exception
|
||||
{
|
||||
FileInfo fileInfo = getByName(NAME_DUPLICATE, true);
|
||||
FileInfo fileInfo = getByName(NAME_CHECK_FOLDER, true);
|
||||
assertNotNull(fileInfo);
|
||||
assertTrue(fileInfo.isFolder());
|
||||
|
||||
fileInfo = getByName(NAME_DUPLICATE, false);
|
||||
fileInfo = getByName(NAME_CHECK_FILE, false);
|
||||
assertNotNull(fileInfo);
|
||||
assertFalse(fileInfo.isFolder());
|
||||
}
|
||||
@@ -308,6 +309,10 @@ public class FileFolderServiceImplTest extends TestCase
|
||||
// make sure that it is an immediate child of the root
|
||||
List<FileInfo> checkFileInfos = fileFolderService.search(workingRootNodeRef, NAME_L1_FOLDER_A, false);
|
||||
assertEquals("Folder not moved to root", 1, checkFileInfos.size());
|
||||
// rename properly
|
||||
FileInfo checkFileInfo = fileFolderService.move(folderToMoveRef, null, "new name");
|
||||
checkFileInfos = fileFolderService.search(workingRootNodeRef, checkFileInfo.getName(), false);
|
||||
assertEquals("Folder not renamed in root", 1, checkFileInfos.size());
|
||||
// attempt illegal rename (existing)
|
||||
try
|
||||
{
|
||||
@@ -318,10 +323,6 @@ public class FileFolderServiceImplTest extends TestCase
|
||||
{
|
||||
// expected
|
||||
}
|
||||
// rename properly
|
||||
FileInfo checkFileInfo = fileFolderService.move(folderToMoveRef, null, "new name");
|
||||
checkFileInfos = fileFolderService.search(workingRootNodeRef, checkFileInfo.getName(), false);
|
||||
assertEquals("Folder not renamed in root", 1, checkFileInfos.size());
|
||||
}
|
||||
|
||||
public void testCopy() throws Exception
|
||||
@@ -417,19 +418,20 @@ public class FileFolderServiceImplTest extends TestCase
|
||||
{
|
||||
// create a completely new path below the root
|
||||
List<String> namePath = new ArrayList<String>(4);
|
||||
namePath.add("A");
|
||||
namePath.add("B");
|
||||
namePath.add("C");
|
||||
namePath.add("D");
|
||||
namePath.add("AAA");
|
||||
namePath.add("BBB");
|
||||
namePath.add("CCC");
|
||||
namePath.add("DDD");
|
||||
|
||||
FileInfo lastFileInfo = fileFolderService.makeFolders(rootNodeRef, namePath, ContentModel.TYPE_FOLDER);
|
||||
assertNotNull("First makeFolder failed", lastFileInfo);
|
||||
// check that a repeat works
|
||||
|
||||
FileInfo lastFileInfoAgain = fileFolderService.makeFolders(rootNodeRef, namePath, ContentModel.TYPE_FOLDER);
|
||||
assertNotNull("Repeat makeFolders failed", lastFileInfoAgain);
|
||||
assertEquals("Repeat created new leaf", lastFileInfo.getNodeRef(), lastFileInfoAgain.getNodeRef());
|
||||
// check that it worked
|
||||
List<FileInfo> checkInfos = fileFolderService.search(rootNodeRef, "D", false, true, true);
|
||||
List<FileInfo> checkInfos = fileFolderService.search(rootNodeRef, "DDD", false, true, true);
|
||||
assertEquals("Expected to find a result", 1, checkInfos.size());
|
||||
// get the path
|
||||
List<FileInfo> checkPathInfos = fileFolderService.getNamePath(rootNodeRef, checkInfos.get(0).getNodeRef());
|
||||
@@ -442,6 +444,27 @@ public class FileFolderServiceImplTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lucene only indexes terms that are 3 characters or more
|
||||
*/
|
||||
public void testMakeFoldersShortNames() throws Exception
|
||||
{
|
||||
// create a completely new path below the root
|
||||
List<String> namePath = new ArrayList<String>(4);
|
||||
namePath.add("A");
|
||||
namePath.add("B");
|
||||
namePath.add("C");
|
||||
namePath.add("D");
|
||||
|
||||
FileInfo lastFileInfo = fileFolderService.makeFolders(rootNodeRef, namePath, ContentModel.TYPE_FOLDER);
|
||||
assertNotNull("First makeFolder failed", lastFileInfo);
|
||||
// check that a repeat works
|
||||
|
||||
FileInfo lastFileInfoAgain = fileFolderService.makeFolders(rootNodeRef, namePath, ContentModel.TYPE_FOLDER);
|
||||
assertNotNull("Repeat makeFolders failed", lastFileInfoAgain);
|
||||
assertEquals("Repeat created new leaf", lastFileInfo.getNodeRef(), lastFileInfoAgain.getNodeRef());
|
||||
}
|
||||
|
||||
public void testGetNamePath() throws Exception
|
||||
{
|
||||
FileInfo fileInfo = getByName(NAME_L1_FILE_A, false);
|
||||
@@ -473,6 +496,22 @@ public class FileFolderServiceImplTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public void testSearchSimple() throws Exception
|
||||
{
|
||||
FileInfo folderInfo = getByName(NAME_L0_FOLDER_A, true);
|
||||
assertNotNull(folderInfo);
|
||||
NodeRef folderNodeRef = folderInfo.getNodeRef();
|
||||
// search for a file that is not there
|
||||
NodeRef phantomNodeRef = fileFolderService.searchSimple(folderNodeRef, "aaaaaaa");
|
||||
assertNull("Found non-existent node by name", phantomNodeRef);
|
||||
// search for a file that is there
|
||||
NodeRef fileNodeRef = fileFolderService.searchSimple(folderNodeRef, NAME_L1_FILE_A);
|
||||
assertNotNull("Didn't find file", fileNodeRef);
|
||||
// double check
|
||||
FileInfo checkInfo = getByName(NAME_L1_FILE_A, false);
|
||||
assertEquals("Incorrect node found", checkInfo.getNodeRef(), fileNodeRef);
|
||||
}
|
||||
|
||||
public void testResolveNamePath() throws Exception
|
||||
{
|
||||
FileInfo fileInfo = getByName(NAME_L1_FILE_A, false);
|
||||
@@ -524,4 +563,20 @@ public class FileFolderServiceImplTest extends TestCase
|
||||
String checkContent = reader.getContentString();
|
||||
assertEquals("Content mismatch", content, checkContent);
|
||||
}
|
||||
|
||||
public void testLongFileNames() throws Exception
|
||||
{
|
||||
String fileName =
|
||||
"12345678901234567890123456789012345678901234567890" +
|
||||
"12345678901234567890123456789012345678901234567890" +
|
||||
"12345678901234567890123456789012345678901234567890" +
|
||||
"12345678901234567890123456789012345678901234567890" +
|
||||
"12345678901234567890123456789012345678901234567890" +
|
||||
"12345678901234567890123456789012345678901234567890";
|
||||
FileInfo fileInfo = fileFolderService.create(workingRootNodeRef, fileName, ContentModel.TYPE_CONTENT);
|
||||
// see if we can get it again
|
||||
NodeRef fileNodeRef = fileFolderService.searchSimple(workingRootNodeRef, fileName);
|
||||
assertNotNull("Long filename not found", fileNodeRef);
|
||||
assertEquals(fileInfo.getNodeRef(), fileNodeRef);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user