[ACS-9572] Show proper message for duplicate unzipping (#3356)

This commit is contained in:
SatyamSah5
2025-05-20 15:15:42 +05:30
committed by GitHub
parent db74a6e7f2
commit a86fa21880
6 changed files with 1994 additions and 1866 deletions

View File

@@ -80,6 +80,11 @@ function runAction(p_params)
{ {
result.fileExist = true; result.fileExist = true;
} }
if (error.indexOf("FolderExistsException") != -1)
{
result.fileExist = true;
result.type = "folder";
}
} }
results.push(result); results.push(result);

View File

@@ -58,6 +58,7 @@ import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.model.FileExistsException; import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FolderExistsException;
import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
@@ -73,6 +74,7 @@ import org.alfresco.util.TempFileProvider;
* *
* @author gavinc * @author gavinc
*/ */
@SuppressWarnings("PMD.PreserveStackTrace")
public class ImporterActionExecuter extends ActionExecuterAbstractBase public class ImporterActionExecuter extends ActionExecuterAbstractBase
{ {
public static final String NAME = "import"; public static final String NAME = "import";
@@ -366,7 +368,11 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
catch (FileExistsException e) catch (FileExistsException e)
{ {
// TODO: add failed file info to status message? // TODO: add failed file info to status message?
throw new AlfrescoRuntimeException("Failed to process ZIP file.", e); if (e.getType().equalsIgnoreCase("folder"))
{
throw new FolderExistsException(root, file.getName());
}
throw e;
} }
} }
} }

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited * Copyright (C) 2005 - 2025 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@@ -40,6 +40,10 @@ import java.util.ResourceBundle.Control;
import java.util.Set; import java.util.Set;
import java.util.Stack; import java.util.Stack;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.query.CannedQueryFactory; import org.alfresco.query.CannedQueryFactory;
import org.alfresco.query.CannedQueryResults; import org.alfresco.query.CannedQueryResults;
@@ -94,9 +98,6 @@ import org.alfresco.util.Pair;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.alfresco.util.SearchLanguageConversion; import org.alfresco.util.SearchLanguageConversion;
import org.alfresco.util.registry.NamedObjectRegistry; import org.alfresco.util.registry.NamedObjectRegistry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
/** /**
* Implementation of the file/folder-specific service. * Implementation of the file/folder-specific service.
@@ -108,35 +109,31 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
private static final String CANNED_QUERY_FILEFOLDER_LIST = "fileFolderGetChildrenCannedQueryFactory"; private static final String CANNED_QUERY_FILEFOLDER_LIST = "fileFolderGetChildrenCannedQueryFactory";
/** Shallow search for files and folders with a name pattern */ /** Shallow search for files and folders with a name pattern */
private static final String XPATH_QUERY_SHALLOW_ALL = private static final String XPATH_QUERY_SHALLOW_ALL = "./*" +
"./*" + "[like(@cm:name, $cm:name, false)" +
"[like(@cm:name, $cm:name, false)" + " and not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" +
" and not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" + " and (subtypeOf('" + ContentModel.TYPE_FOLDER + "') or subtypeOf('" + ContentModel.TYPE_CONTENT + "')" +
" and (subtypeOf('" + ContentModel.TYPE_FOLDER + "') or subtypeOf('" + ContentModel.TYPE_CONTENT + "')" + " or subtypeOf('" + ContentModel.TYPE_LINK + "'))]";
" or subtypeOf('" + ContentModel.TYPE_LINK + "'))]";
/** Deep search for files and folders with a name pattern */ /** Deep search for files and folders with a name pattern */
private static final String XPATH_QUERY_DEEP_ALL = private static final String XPATH_QUERY_DEEP_ALL = ".//*" +
".//*" + "[like(@cm:name, $cm:name, false)" +
"[like(@cm:name, $cm:name, false)" + " and not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" +
" and not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" + " and (subtypeOf('" + ContentModel.TYPE_FOLDER + "') or subtypeOf('" + ContentModel.TYPE_CONTENT + "')" +
" and (subtypeOf('" + ContentModel.TYPE_FOLDER + "') or subtypeOf('" + ContentModel.TYPE_CONTENT + "')" + " or subtypeOf('" + ContentModel.TYPE_LINK + "'))]";
" or subtypeOf('" + ContentModel.TYPE_LINK + "'))]";
/** Deep search for folders with a name pattern */ /** Deep search for folders with a name pattern */
private static final String XPATH_QUERY_DEEP_FOLDERS = private static final String XPATH_QUERY_DEEP_FOLDERS = ".//*" +
".//*" + "[like(@cm:name, $cm:name, false)" +
"[like(@cm:name, $cm:name, false)" + " and not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" +
" and not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" + " and (subtypeOf('" + ContentModel.TYPE_FOLDER + "'))]";
" and (subtypeOf('" + ContentModel.TYPE_FOLDER + "'))]";
/** Deep search for files with a name pattern */ /** Deep search for files with a name pattern */
private static final String XPATH_QUERY_DEEP_FILES = private static final String XPATH_QUERY_DEEP_FILES = ".//*" +
".//*" + "[like(@cm:name, $cm:name, false)" +
"[like(@cm:name, $cm:name, false)" + " and not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" +
" and not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" + " and (subtypeOf('" + ContentModel.TYPE_CONTENT + "')" +
" and (subtypeOf('" + ContentModel.TYPE_CONTENT + "')" + " or subtypeOf('" + ContentModel.TYPE_LINK + "'))]";
" or subtypeOf('" + ContentModel.TYPE_LINK + "'))]";
private static Log logger = LogFactory.getLog(FileFolderServiceImpl.class); private static Log logger = LogFactory.getLog(FileFolderServiceImpl.class);
@@ -168,7 +165,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
{ {
super(); super();
fileFolderTrait=new ExtendedTrait<FileFolderServiceTrait>(AJProxyTrait.create(createFileFolderTrait(),FileFolderServiceTrait.class)); fileFolderTrait = new ExtendedTrait<FileFolderServiceTrait>(AJProxyTrait.create(createFileFolderTrait(), FileFolderServiceTrait.class));
} }
public void setNamespaceService(NamespaceService namespaceService) public void setNamespaceService(NamespaceService namespaceService)
@@ -245,17 +242,17 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
return preserveAuditableData; return preserveAuditableData;
} }
public void init() public void init()
{ {}
}
/** /**
* Helper method to convert node reference instances to file info * Helper method to convert node reference instances to file info
* *
* @param nodeRefs the node references * @param nodeRefs
* the node references
* @return Return a list of file info * @return Return a list of file info
* @throws InvalidTypeException if the node is not a valid type * @throws InvalidTypeException
* if the node is not a valid type
*/ */
private List<FileInfo> toFileInfo(List<NodeRef> nodeRefs) throws InvalidTypeException private List<FileInfo> toFileInfo(List<NodeRef> nodeRefs) throws InvalidTypeException
{ {
@@ -269,7 +266,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
} }
catch (InvalidNodeRefException inre) catch (InvalidNodeRefException inre)
{ {
logger.warn("toFileInfo: "+inre); logger.warn("toFileInfo: " + inre);
// skip // skip
} }
} }
@@ -292,7 +289,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
boolean isHidden = false; boolean isHidden = false;
Client client = FileFilterMode.getClient(); Client client = FileFilterMode.getClient();
if(hiddenAspect.getVisibility(client, nodeRef) == Visibility.HiddenAttribute) if (hiddenAspect.getVisibility(client, nodeRef) == Visibility.HiddenAttribute)
{ {
isHidden = true; isHidden = true;
} }
@@ -369,7 +366,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
} }
@Override @Override
@Extend(traitAPI=FileFolderServiceTrait.class,extensionAPI=FileFolderServiceExtension.class) @Extend(traitAPI = FileFolderServiceTrait.class, extensionAPI = FileFolderServiceExtension.class)
public List<FileInfo> list(NodeRef contextNodeRef) public List<FileInfo> list(NodeRef contextNodeRef)
{ {
// execute the query // execute the query
@@ -414,23 +411,25 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
} }
PermissionCheckedCollectionMixin.create(nodeInfos, nodeRefs); PermissionCheckedCollectionMixin.create(nodeInfos, nodeRefs);
return new PagingResults<FileInfo>() return new PagingResults<FileInfo>() {
{
@Override @Override
public String getQueryExecutionId() public String getQueryExecutionId()
{ {
return results.getQueryExecutionId(); return results.getQueryExecutionId();
} }
@Override @Override
public List<FileInfo> getPage() public List<FileInfo> getPage()
{ {
return nodeInfos; return nodeInfos;
} }
@Override @Override
public boolean hasMoreItems() public boolean hasMoreItems()
{ {
return results.hasMoreItems(); return results.hasMoreItems();
} }
@Override @Override
public Pair<Integer, Integer> getTotalResultCount() public Pair<Integer, Integer> getTotalResultCount()
{ {
@@ -440,22 +439,22 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.cmr.model.FileFolderService#list(org.alfresco.service.cmr.repository.NodeRef, boolean, boolean, java.util.Set, org.alfresco.service.cmr.model.PagingSortRequest) *
*/ * @see org.alfresco.service.cmr.model.FileFolderService#list(org.alfresco.service.cmr.repository.NodeRef, boolean, boolean, java.util.Set, org.alfresco.service.cmr.model.PagingSortRequest) */
@Auditable(parameters = {"contextNodeRef", "files", "folders", "ignoreQNames", "sortProps", "pagingRequest"}) @Auditable(parameters = {"contextNodeRef", "files", "folders", "ignoreQNames", "sortProps", "pagingRequest"})
@Override @Override
@Extend(traitAPI = FileFolderServiceTrait.class, extensionAPI = FileFolderServiceExtension.class) @Extend(traitAPI = FileFolderServiceTrait.class, extensionAPI = FileFolderServiceExtension.class)
public PagingResults<FileInfo> list(NodeRef contextNodeRef, public PagingResults<FileInfo> list(NodeRef contextNodeRef,
boolean files, boolean files,
boolean folders, boolean folders,
Set<QName> ignoreQNames, Set<QName> ignoreQNames,
List<Pair<QName, Boolean>> sortProps, List<Pair<QName, Boolean>> sortProps,
PagingRequest pagingRequest) PagingRequest pagingRequest)
{ {
ParameterCheck.mandatory("contextNodeRef", contextNodeRef); ParameterCheck.mandatory("contextNodeRef", contextNodeRef);
ParameterCheck.mandatory("pagingRequest", pagingRequest); ParameterCheck.mandatory("pagingRequest", pagingRequest);
Pair<Set<QName>,Set<QName>> pair = buildSearchTypesAndIgnoreAspects(files, folders, ignoreQNames); Pair<Set<QName>, Set<QName>> pair = buildSearchTypesAndIgnoreAspects(files, folders, ignoreQNames);
Set<QName> searchTypeQNames = pair.getFirst(); Set<QName> searchTypeQNames = pair.getFirst();
Set<QName> ignoreAspectQNames = pair.getSecond(); Set<QName> ignoreAspectQNames = pair.getSecond();
@@ -465,13 +464,13 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
} }
@Override @Override
@Extend(traitAPI=FileFolderServiceTrait.class,extensionAPI=FileFolderServiceExtension.class) @Extend(traitAPI = FileFolderServiceTrait.class, extensionAPI = FileFolderServiceExtension.class)
public PagingResults<FileInfo> list(NodeRef contextNodeRef, boolean files, boolean folders, String pattern, Set<QName> ignoreQNames, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest) public PagingResults<FileInfo> list(NodeRef contextNodeRef, boolean files, boolean folders, String pattern, Set<QName> ignoreQNames, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest)
{ {
ParameterCheck.mandatory("contextNodeRef", contextNodeRef); ParameterCheck.mandatory("contextNodeRef", contextNodeRef);
ParameterCheck.mandatory("pagingRequest", pagingRequest); ParameterCheck.mandatory("pagingRequest", pagingRequest);
Pair<Set<QName>,Set<QName>> pair = buildSearchTypesAndIgnoreAspects(files, folders, ignoreQNames); Pair<Set<QName>, Set<QName>> pair = buildSearchTypesAndIgnoreAspects(files, folders, ignoreQNames);
Set<QName> searchTypeQNames = pair.getFirst(); Set<QName> searchTypeQNames = pair.getFirst();
Set<QName> ignoreAspectQNames = pair.getSecond(); Set<QName> ignoreAspectQNames = pair.getSecond();
@@ -480,25 +479,24 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
return getPagingResults(pagingRequest, results); return getPagingResults(pagingRequest, results);
} }
@Override @Override
@Extend(traitAPI=FileFolderServiceTrait.class,extensionAPI=FileFolderServiceExtension.class) @Extend(traitAPI = FileFolderServiceTrait.class, extensionAPI = FileFolderServiceExtension.class)
public PagingResults<FileInfo> list(NodeRef rootNodeRef, Set<QName> searchTypeQNames, Set<QName> ignoreAspectQNames, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest) public PagingResults<FileInfo> list(NodeRef rootNodeRef, Set<QName> searchTypeQNames, Set<QName> ignoreAspectQNames, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest)
{ {
CannedQueryResults<NodeRef> results = listImpl(rootNodeRef, null, searchTypeQNames, ignoreAspectQNames, sortProps, pagingRequest); CannedQueryResults<NodeRef> results = listImpl(rootNodeRef, null, searchTypeQNames, ignoreAspectQNames, sortProps, pagingRequest);
return getPagingResults(pagingRequest, results); return getPagingResults(pagingRequest, results);
} }
@Override @Override
public PagingResults<FileInfo> list(NodeRef rootNodeRef, public PagingResults<FileInfo> list(NodeRef rootNodeRef,
Set<QName> assocTypeQNames, Set<QName> assocTypeQNames,
Set<QName> searchTypeQNames, Set<QName> searchTypeQNames,
Set<QName> ignoreAspectQNames, Set<QName> ignoreAspectQNames,
List<Pair<QName, Boolean>> sortProps, List<Pair<QName, Boolean>> sortProps,
List<FilterProp> filterProps, List<FilterProp> filterProps,
PagingRequest pagingRequest) PagingRequest pagingRequest)
{ {
CannedQueryResults<NodeRef> results = listImpl(rootNodeRef, null, assocTypeQNames, searchTypeQNames, ignoreAspectQNames, sortProps, filterProps, pagingRequest); CannedQueryResults<NodeRef> results = listImpl(rootNodeRef, null, assocTypeQNames, searchTypeQNames, ignoreAspectQNames, sortProps, filterProps, pagingRequest);
return getPagingResults(pagingRequest, results); return getPagingResults(pagingRequest, results);
} }
@@ -525,20 +523,20 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
* @param pagingRequest * @param pagingRequest
* @return * @return
*/ */
private CannedQueryResults<NodeRef> listImpl(NodeRef contextNodeRef, String pattern, Set<QName> searchTypeQNames, Set<QName> ignoreAspectQNames, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest) private CannedQueryResults<NodeRef> listImpl(NodeRef contextNodeRef, String pattern, Set<QName> searchTypeQNames, Set<QName> ignoreAspectQNames, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest)
{ {
return listImpl(contextNodeRef, pattern, Collections.singleton(ContentModel.ASSOC_CONTAINS), searchTypeQNames, ignoreAspectQNames, sortProps, null, pagingRequest); return listImpl(contextNodeRef, pattern, Collections.singleton(ContentModel.ASSOC_CONTAINS), searchTypeQNames, ignoreAspectQNames, sortProps, null, pagingRequest);
} }
private CannedQueryResults<NodeRef> listImpl(NodeRef contextNodeRef, String pattern, Set<QName> assocTypeQNames, Set<QName> searchTypeQNames, Set<QName> ignoreAspectQNames, private CannedQueryResults<NodeRef> listImpl(NodeRef contextNodeRef, String pattern, Set<QName> assocTypeQNames, Set<QName> searchTypeQNames, Set<QName> ignoreAspectQNames,
List<Pair<QName, Boolean>> sortProps, List<FilterProp> filterProps, PagingRequest pagingRequest) List<Pair<QName, Boolean>> sortProps, List<FilterProp> filterProps, PagingRequest pagingRequest)
{ {
Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null); Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null);
// get canned query // get canned query
GetChildrenCannedQueryFactory getChildrenCannedQueryFactory = (GetChildrenCannedQueryFactory)cannedQueryRegistry.getNamedObject(CANNED_QUERY_FILEFOLDER_LIST); GetChildrenCannedQueryFactory getChildrenCannedQueryFactory = (GetChildrenCannedQueryFactory) cannedQueryRegistry.getNamedObject(CANNED_QUERY_FILEFOLDER_LIST);
GetChildrenCannedQuery cq = (GetChildrenCannedQuery)getChildrenCannedQueryFactory.getCannedQuery(contextNodeRef, pattern, assocTypeQNames, searchTypeQNames, ignoreAspectQNames, filterProps, sortProps, pagingRequest); GetChildrenCannedQuery cq = (GetChildrenCannedQuery) getChildrenCannedQueryFactory.getCannedQuery(contextNodeRef, pattern, assocTypeQNames, searchTypeQNames, ignoreAspectQNames, filterProps, sortProps, pagingRequest);
// execute canned query // execute canned query
CannedQueryResults<NodeRef> results = cq.execute(); CannedQueryResults<NodeRef> results = cq.execute();
@@ -552,7 +550,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
Pair<Integer, Integer> totalCount = (pagingRequest.getRequestTotalCountMax() > 0 ? results.getTotalResultCount() : null); Pair<Integer, Integer> totalCount = (pagingRequest.getRequestTotalCountMax() > 0 ? results.getTotalResultCount() : null);
int pageNum = (skipCount / maxItems) + 1; int pageNum = (skipCount / maxItems) + 1;
logger.debug("List: "+cnt+" items in "+(System.currentTimeMillis()-start)+" msecs [pageNum="+pageNum+",skip="+skipCount+",max="+maxItems+",hasMorePages="+hasMoreItems+",totalCount="+totalCount+",parentNodeRef="+contextNodeRef+"]"); logger.debug("List: " + cnt + " items in " + (System.currentTimeMillis() - start) + " msecs [pageNum=" + pageNum + ",skip=" + skipCount + ",max=" + maxItems + ",hasMorePages=" + hasMoreItems + ",totalCount=" + totalCount + ",parentNodeRef=" + contextNodeRef + "]");
} }
return results; return results;
@@ -627,7 +625,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
String filename = resourceHelper.toBundleName(base, candidateLocale) + "." + ext; String filename = resourceHelper.toBundleName(base, candidateLocale) + "." + ext;
// Attempt to find the file // Attempt to find the file
NodeRef foundNodeRef = searchSimple(parentNodeRef, filename); NodeRef foundNodeRef = searchSimple(parentNodeRef, filename);
if (foundNodeRef != null) // TODO: Check for read permissions if (foundNodeRef != null) // TODO: Check for read permissions
{ {
resultNodeRef = foundNodeRef; resultNodeRef = foundNodeRef;
break; break;
@@ -648,9 +646,9 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
{ {
logger.trace( logger.trace(
"Simple name search results: \n" + "Simple name search results: \n" +
" parent: " + contextNodeRef + "\n" + " parent: " + contextNodeRef + "\n" +
" name: " + name + "\n" + " name: " + name + "\n" +
" result: " + childNodeRef); " result: " + childNodeRef);
} }
return childNodeRef; return childNodeRef;
} }
@@ -659,7 +657,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
* @see #search(NodeRef, String, boolean, boolean, boolean) * @see #search(NodeRef, String, boolean, boolean, boolean)
*/ */
@Override @Override
@Extend(traitAPI=FileFolderServiceTrait.class,extensionAPI=FileFolderServiceExtension.class) @Extend(traitAPI = FileFolderServiceTrait.class, extensionAPI = FileFolderServiceExtension.class)
public List<FileInfo> search(NodeRef contextNodeRef, String namePattern, boolean includeSubFolders) public List<FileInfo> search(NodeRef contextNodeRef, String namePattern, boolean includeSubFolders)
{ {
return search(contextNodeRef, namePattern, true, true, includeSubFolders); return search(contextNodeRef, namePattern, true, true, includeSubFolders);
@@ -671,7 +669,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
* Full search with all options * Full search with all options
*/ */
@Override @Override
@Extend(traitAPI=FileFolderServiceTrait.class,extensionAPI=FileFolderServiceExtension.class) @Extend(traitAPI = FileFolderServiceTrait.class, extensionAPI = FileFolderServiceExtension.class)
public List<FileInfo> search( public List<FileInfo> search(
NodeRef contextNodeRef, NodeRef contextNodeRef,
String namePattern, String namePattern,
@@ -713,9 +711,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
} }
/** /**
* Performs a full search, but doesn't translate the node references into * 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.
* file info objects. This allows {@link #checkExists(NodeRef, String)} to
* bypass the retrieval of node properties.
*/ */
private List<NodeRef> searchInternal( private List<NodeRef> searchInternal(
NodeRef contextNodeRef, NodeRef contextNodeRef,
@@ -732,7 +728,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
if (namePattern == null) if (namePattern == null)
{ {
namePattern = LUCENE_MULTI_CHAR_WILDCARD; // default to wildcard namePattern = LUCENE_MULTI_CHAR_WILDCARD; // default to wildcard
} }
// now check if we can use Lucene to handle this query // now check if we can use Lucene to handle this query
boolean anyName = namePattern.equals(LUCENE_MULTI_CHAR_WILDCARD); boolean anyName = namePattern.equals(LUCENE_MULTI_CHAR_WILDCARD);
@@ -741,9 +737,9 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
if (anyName) if (anyName)
{ {
// This is search for any name // This is search for any name
if(includeSubFolders) if (includeSubFolders)
{ {
nodeRefs = listSimpleDeep(contextNodeRef, fileSearch, folderSearch, null); nodeRefs = listSimpleDeep(contextNodeRef, fileSearch, folderSearch, null);
} }
else else
{ {
@@ -775,12 +771,12 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
if (includeSubFolders) if (includeSubFolders)
{ {
// this is a deep search // this is a deep search
if(!fileSearch && folderSearch) if (!fileSearch && folderSearch)
{ {
// This is a folder search only; // This is a folder search only;
query = XPATH_QUERY_DEEP_FOLDERS; query = XPATH_QUERY_DEEP_FOLDERS;
} }
else if(fileSearch && !folderSearch) else if (fileSearch && !folderSearch)
{ {
// This is a folder search only; // This is a folder search only;
query = XPATH_QUERY_DEEP_FILES; query = XPATH_QUERY_DEEP_FILES;
@@ -896,27 +892,24 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
} }
/** /**
* A deep version of listSimple. Which recursively walks down the tree from a given starting point, returning * A deep version of listSimple. Which recursively walks down the tree from a given starting point, returning the node refs of files or folders found along the way.
* the node refs of files or folders found along the way.
* <p> * <p>
* The folder filter is called for each sub-folder to determine whether to search in that sub-folder, should a subfolder be excluded * The folder filter is called for each sub-folder to determine whether to search in that sub-folder, should a subfolder be excluded then all its chidren are excluded as well.
* then all its chidren are excluded as well.
* *
* @param contextNodeRef the starting point. * @param contextNodeRef
* @param files return nodes of type files. * the starting point.
* @param folders return nodes of type folders. * @param files
* @param folderFilter filter controls which folders to search. If null then all subfolders are searched. * return nodes of type files.
* @param folders
* return nodes of type folders.
* @param folderFilter
* filter controls which folders to search. If null then all subfolders are searched.
* @return list of node references * @return list of node references
*/ */
/* <p> /* <p> MER: I've added this rather than changing listSimple to minimise the risk of breaking the existing code. This is a quick performance improvement between using XPath which is awful or adding new methods to the NodeService/DB This is also a dangerous method in that it can return a lot of data and take a long time. */
* MER: I've added this rather than changing listSimple to minimise the risk of breaking
* the existing code. This is a quick performance improvement between using
* XPath which is awful or adding new methods to the NodeService/DB This is also a dangerous method in that it can return a
* lot of data and take a long time.
*/
private List<NodeRef> listSimpleDeep(NodeRef contextNodeRef, boolean files, boolean folders, SubFolderFilter folderFilter) private List<NodeRef> listSimpleDeep(NodeRef contextNodeRef, boolean files, boolean folders, SubFolderFilter folderFilter)
{ {
if(logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("searchSimpleDeep contextNodeRef:" + contextNodeRef); logger.debug("searchSimpleDeep contextNodeRef:" + contextNodeRef);
} }
@@ -928,7 +921,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
Set<QName> folderTypeQNames = buildFolderTypes(); Set<QName> folderTypeQNames = buildFolderTypes();
Set<QName> fileTypeQNames = (files ? buildFileTypes() : new HashSet<QName>(0)); Set<QName> fileTypeQNames = (files ? buildFileTypes() : new HashSet<QName>(0));
if(!folders && !files) if (!folders && !files)
{ {
return Collections.emptyList(); return Collections.emptyList();
@@ -944,7 +937,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
toSearch.push(contextNodeRef); toSearch.push(contextNodeRef);
// Now we need to walk down the folders. // Now we need to walk down the folders.
while(!toSearch.empty()) while (!toSearch.empty())
{ {
NodeRef currentDir = toSearch.pop(); NodeRef currentDir = toSearch.pop();
@@ -954,10 +947,10 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
{ {
// We have some child folders // We have some child folders
boolean include = true; boolean include = true;
if(folderFilter != null) if (folderFilter != null)
{ {
include = folderFilter.isEnterSubfolder(folderRef); include = folderFilter.isEnterSubfolder(folderRef);
if(include) if (include)
{ {
// yes search in these subfolders // yes search in these subfolders
toSearch.push(folderRef.getChildRef()); toSearch.push(folderRef.getChildRef());
@@ -969,13 +962,13 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
toSearch.push(folderRef.getChildRef()); toSearch.push(folderRef.getChildRef());
} }
if(folders && include) if (folders && include)
{ {
result.add(folderRef.getChildRef()); result.add(folderRef.getChildRef());
} }
} }
if(files) if (files)
{ {
// Add the files in the current dir // Add the files in the current dir
List<ChildAssociationRef> fileAssocRefs = nodeService.getChildAssocs(currentDir, fileTypeQNames); List<ChildAssociationRef> fileAssocRefs = nodeService.getChildAssocs(currentDir, fileTypeQNames);
@@ -986,8 +979,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
} }
} }
if (logger.isDebugEnabled())
if(logger.isDebugEnabled())
{ {
logger.debug("searchSimpleDeep finished size:" + result.size()); logger.debug("searchSimpleDeep finished size:" + result.size());
} }
@@ -1000,7 +992,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
* @see #move(NodeRef, NodeRef, String) * @see #move(NodeRef, NodeRef, String)
*/ */
@Override @Override
@Extend(traitAPI=FileFolderServiceTrait.class,extensionAPI=FileFolderServiceExtension.class) @Extend(traitAPI = FileFolderServiceTrait.class, extensionAPI = FileFolderServiceExtension.class)
public FileInfo rename(NodeRef sourceNodeRef, String newName) throws FileExistsException, FileNotFoundException public FileInfo rename(NodeRef sourceNodeRef, String newName) throws FileExistsException, FileNotFoundException
{ {
return moveOrCopy(sourceNodeRef, null, null, newName, true); return moveOrCopy(sourceNodeRef, null, null, newName, true);
@@ -1045,7 +1037,8 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
/** /**
* Implements both move and copy behaviour * Implements both move and copy behaviour
* *
* @param move true to move, otherwise false to copy * @param move
* true to move, otherwise false to copy
*/ */
private FileInfo moveOrCopy(NodeRef sourceNodeRef, NodeRef sourceParentRef, NodeRef targetParentRef, String newName, boolean move) throws FileExistsException, FileNotFoundException private FileInfo moveOrCopy(NodeRef sourceNodeRef, NodeRef sourceParentRef, NodeRef targetParentRef, String newName, boolean move) throws FileExistsException, FileNotFoundException
{ {
@@ -1119,7 +1112,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
if (nameChanged) if (nameChanged)
{ {
// The name will be changing, so we really need to set the node's name to the new // The name will be changing, so we really need to set the node's name to the new
// name. This can't be done at the same time as the move - to avoid incorrect violations // name. This can't be done at the same time as the move - to avoid incorrect violations
// of the name constraints, the cm:name is set to something random and will be reset // of the name constraints, the cm:name is set to something random and will be reset
// to the correct name later. // to the correct name later.
nodeService.setProperty(sourceNodeRef, ContentModel.PROP_NAME, GUID.generate()); nodeService.setProperty(sourceNodeRef, ContentModel.PROP_NAME, GUID.generate());
@@ -1182,7 +1175,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
try try
{ {
// Copy the node. The cm:name will be dropped and reset later. // Copy the node. The cm:name will be dropped and reset later.
targetNodeRef = copyService.copy( targetNodeRef = copyService.copy(
sourceNodeRef, sourceNodeRef,
targetParentRef, targetParentRef,
@@ -1197,7 +1190,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
} }
// Only update the name if it has changed // Only update the name if it has changed
String currentName = (String)nodeService.getProperty(targetNodeRef, ContentModel.PROP_NAME); String currentName = (String) nodeService.getProperty(targetNodeRef, ContentModel.PROP_NAME);
// ALF-13949: WorkingCopyAspect intentionally generates new names for all copies of working copies (which no // ALF-13949: WorkingCopyAspect intentionally generates new names for all copies of working copies (which no
// longer have the working copy aspect) so leave these alone after copy // longer have the working copy aspect) so leave these alone after copy
@@ -1209,13 +1202,13 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
nodeService.setProperty(targetNodeRef, ContentModel.PROP_NAME, newName); nodeService.setProperty(targetNodeRef, ContentModel.PROP_NAME, newName);
// May need to update the mimetype, to support apps using .tmp files when saving // May need to update the mimetype, to support apps using .tmp files when saving
ContentData contentData = (ContentData)nodeService.getProperty(targetNodeRef, ContentModel.PROP_CONTENT); ContentData contentData = (ContentData) nodeService.getProperty(targetNodeRef, ContentModel.PROP_CONTENT);
// Check the newName and oldName extensions. // Check the newName and oldName extensions.
// Keep previous mimetype if // Keep previous mimetype if
// 1. new extension is empty // 1. new extension is empty
// 2. new extension is '.tmp' // 2. new extension is '.tmp'
// 3. extension was not changed, // 3. extension was not changed,
// //
// It fixes the ETWOTWO-16 issue. // It fixes the ETWOTWO-16 issue.
String oldExt = getExtension(beforeFileInfo.getName(), true).getSecond(); String oldExt = getExtension(beforeFileInfo.getName(), true).getSecond();
@@ -1259,8 +1252,9 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
* *
* TODO: Replace this with a more formal means of identifying "system" folders (i.e. aspect or UUID) * TODO: Replace this with a more formal means of identifying "system" folders (i.e. aspect or UUID)
* *
* @param nodeRef node to check * @param nodeRef
* @return true => system folder path based node * node to check
* @return true => system folder path based node
*/ */
private boolean isSystemPath(NodeRef nodeRef) private boolean isSystemPath(NodeRef nodeRef)
{ {
@@ -1292,13 +1286,13 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
switch (type) switch (type)
{ {
case SYSTEM_FOLDER: case SYSTEM_FOLDER:
throw new InvalidTypeException("System Folders are not handled by this service :" + typeQName); throw new InvalidTypeException("System Folders are not handled by this service :" + typeQName);
case INVALID: case INVALID:
throw new InvalidTypeException("Type is not handled by this service: " + typeQName); throw new InvalidTypeException("Type is not handled by this service: " + typeQName);
case FILE: case FILE:
case FOLDER: case FOLDER:
default: default:
} }
// create the node // create the node
@@ -1320,7 +1314,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
} }
catch (DuplicateChildNodeNameException e) catch (DuplicateChildNodeNameException e)
{ {
throw new FileExistsException(parentNodeRef, name); throw new FileExistsException(parentNodeRef, name, typeQName.getLocalName());
} }
NodeRef nodeRef = assocRef.getChildRef(); NodeRef nodeRef = assocRef.getChildRef();
@@ -1351,12 +1345,14 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
/** /**
* Checks for the presence of, and creates as necessary, the folder structure in the provided path. * Checks for the presence of, and creates as necessary, the folder structure in the provided path.
* <p> * <p>
* An empty path list is not allowed as it would be impossible to necessarily return file info * An empty path list is not allowed as it would be impossible to necessarily return file info for the parent node - it might not be a folder node.
* for the parent node - it might not be a folder node. *
* @param parentNodeRef the node under which the path will be created * @param parentNodeRef
* @param pathElements the folder name path to create - may not be empty * the node under which the path will be created
* @param folderTypeQName the types of nodes to create. This must be a valid subtype of * @param pathElements
* {@link org.alfresco.model.ContentModel#TYPE_FOLDER they folder type}. * the folder name path to create - may not be empty
* @param folderTypeQName
* the types of nodes to create. This must be a valid subtype of {@link org.alfresco.model.ContentModel#TYPE_FOLDER they folder type}.
* @return Returns the info of the last folder in the path. * @return Returns the info of the last folder in the path.
* @deprecated Use FileFolderUtil.makeFolders rather than directly accessing this implementation class. * @deprecated Use FileFolderUtil.makeFolders rather than directly accessing this implementation class.
*/ */
@@ -1368,12 +1364,14 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
/** /**
* Checks for the presence of, and creates as necessary, the folder structure in the provided path. * Checks for the presence of, and creates as necessary, the folder structure in the provided path.
* <p> * <p>
* An empty path list is not allowed as it would be impossible to necessarily return file info * An empty path list is not allowed as it would be impossible to necessarily return file info for the parent node - it might not be a folder node.
* for the parent node - it might not be a folder node. *
* @param parentNodeRef the node under which the path will be created * @param parentNodeRef
* @param pathElements the folder name path to create - may not be empty * the node under which the path will be created
* @param folderTypeQName the types of nodes to create. This must be a valid subtype of * @param pathElements
* {@link org.alfresco.model.ContentModel#TYPE_FOLDER they folder type}. * the folder name path to create - may not be empty
* @param folderTypeQName
* the types of nodes to create. This must be a valid subtype of {@link org.alfresco.model.ContentModel#TYPE_FOLDER they folder type}.
* @return Returns the info of the last folder in the path. * @return Returns the info of the last folder in the path.
* @deprecated Use FileFolderUtil.makeFolders rather than directly accessing this implementation class. * @deprecated Use FileFolderUtil.makeFolders rather than directly accessing this implementation class.
*/ */
@@ -1385,18 +1383,18 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
/** /**
* Get the file or folder information from the root down to and including the node provided. * Get the file or folder information from the root down to and including the node provided.
* <ul> * <ul>
* <li>The root node can be of any type and is not included in the path list.</li> * <li>The root node can be of any type and is not included in the path list.</li>
* <li>Only the primary path is considered. If the target node is not a descendant of the * <li>Only the primary path is considered. If the target node is not a descendant of the root along purely primary associations, then an exception is generated.</li>
* root along purely primary associations, then an exception is generated.</li> * <li>If an invalid type is encountered along the path, then an exception is generated.</li>
* <li>If an invalid type is encountered along the path, then an exception is generated.</li>
* </ul> * </ul>
* *
* @param rootNodeRef the start of the returned path, or null if the <b>store</b> root * @param rootNodeRef
* node must be assumed. * the start of the returned path, or null if the <b>store</b> root node must be assumed.
* @param nodeRef a reference to the file or folder * @param nodeRef
* @return Returns a list of file/folder infos from the root (excluded) down to and * a reference to the file or folder
* including the destination file or folder * @return Returns a list of file/folder infos from the root (excluded) down to and including the destination file or folder
* @throws FileNotFoundException if the node could not be found * @throws FileNotFoundException
* if the node could not be found
*/ */
@Override @Override
public List<FileInfo> getNamePath(NodeRef rootNodeRef, NodeRef nodeRef) throws FileNotFoundException public List<FileInfo> getNamePath(NodeRef rootNodeRef, NodeRef nodeRef) throws FileNotFoundException
@@ -1431,8 +1429,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
} }
// we found the root and expect to be building the path up // we found the root and expect to be building the path up
// Run as system as the user could not have access to all folders in the path, see ALF-13816 // Run as system as the user could not have access to all folders in the path, see ALF-13816
FileInfo pathInfo = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<FileInfo>() FileInfo pathInfo = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<FileInfo>() {
{
public FileInfo doWork() throws Exception public FileInfo doWork() throws Exception
{ {
return toFileInfo(childNodeRef, true); return toFileInfo(childNodeRef, true);
@@ -1441,10 +1438,10 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
// we can't append a path element to the results if there is already a (non-folder) file at the tail // we can't append a path element to the results if there is already a (non-folder) file at the tail
// since this would result in a path anomoly - file's cannot contain other files. // since this would result in a path anomoly - file's cannot contain other files.
if (!results.isEmpty() && !results.get(results.size()-1).isFolder()) if (!results.isEmpty() && !results.get(results.size() - 1).isFolder())
{ {
throw new InvalidTypeException( throw new InvalidTypeException(
"File is not the last element in path: files cannot contain other files."); "File is not the last element in path: files cannot contain other files.");
} }
results.add(pathInfo); results.add(pathInfo);
} }
@@ -1472,18 +1469,18 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
/** /**
* Get the file or folder names from the root down to and including the node provided. * Get the file or folder names from the root down to and including the node provided.
* <ul> * <ul>
* <li>The root node can be of any type and is not included in the path list.</li> * <li>The root node can be of any type and is not included in the path list.</li>
* <li>Only the primary path is considered. If the target node is not a descendant of the * <li>Only the primary path is considered. If the target node is not a descendant of the root along purely primary associations, then an exception is generated.</li>
* root along purely primary associations, then an exception is generated.</li> * <li>If an invalid type is encountered along the path, then an exception is generated.</li>
* <li>If an invalid type is encountered along the path, then an exception is generated.</li>
* </ul> * </ul>
* *
* @param rootNodeRef the start of the returned path, or null if the <b>store</b> root * @param rootNodeRef
* node must be assumed. * the start of the returned path, or null if the <b>store</b> root node must be assumed.
* @param nodeRef a reference to the file or folder * @param nodeRef
* @return Returns a list of file/folder names from the root (excluded) down to and * a reference to the file or folder
* including the destination file or folder * @return Returns a list of file/folder names from the root (excluded) down to and including the destination file or folder
* @throws FileNotFoundException if the node could not be found * @throws FileNotFoundException
* if the node could not be found
*/ */
@Override @Override
public List<String> getNameOnlyPath(NodeRef rootNodeRef, final NodeRef nodeRef) throws FileNotFoundException public List<String> getNameOnlyPath(NodeRef rootNodeRef, final NodeRef nodeRef) throws FileNotFoundException
@@ -1498,8 +1495,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
final NodeRef rNodeRef = rootNodeRef; final NodeRef rNodeRef = rootNodeRef;
final ArrayList<String> results = new ArrayList<String>(10); final ArrayList<String> results = new ArrayList<String>(10);
// Run as system as the user could not have access to all folders in the path, see ALF-13816 // Run as system as the user could not have access to all folders in the path, see ALF-13816
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Void>() AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Void>() {
{
public Void doWork() throws Exception public Void doWork() throws Exception
{ {
// get the primary path // get the primary path
@@ -1552,9 +1548,10 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
// the runAs() is too keen on wrapping everything in an outer RuntimeException - which we don't want. // the runAs() is too keen on wrapping everything in an outer RuntimeException - which we don't want.
if (e.getCause() instanceof FileNotFoundException) if (e.getCause() instanceof FileNotFoundException)
{ {
throw (FileNotFoundException)e.getCause(); throw (FileNotFoundException) e.getCause();
} }
else throw e; else
throw e;
} }
} }
@@ -1693,8 +1690,9 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
Visibility webDavVisibility = isHidden ? Visibility.NotVisible : Visibility.Visible; Visibility webDavVisibility = isHidden ? Visibility.NotVisible : Visibility.Visible;
for (Client client : hiddenAspect.getClients()) for (Client client : hiddenAspect.getClients())
{ {
Visibility clientVisibility = client == FileFilterMode.getClient() ? webDavVisibility : hiddenAspect Visibility clientVisibility = client == FileFilterMode.getClient() ? webDavVisibility
.getVisibility(client, nodeRef); : hiddenAspect
.getVisibility(client, nodeRef);
if (clientVisibility != Visibility.Visible) if (clientVisibility != Visibility.Visible)
{ {
allVisible = false; allVisible = false;
@@ -1718,7 +1716,7 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
} }
@Override @Override
public <M extends Trait> ExtendedTrait<M> getTrait(Class<? extends M> traitAPI) public <M extends Trait> ExtendedTrait<M> getTrait(Class<? extends M> traitAPI)
{ {
return (ExtendedTrait<M>) fileFolderTrait; return (ExtendedTrait<M>) fileFolderTrait;
} }
@@ -1739,22 +1737,22 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
@Override @Override
public Pair<Set<QName>, Set<QName>> buildSearchTypesAndIgnoreAspects(boolean files, boolean folders, public Pair<Set<QName>, Set<QName>> buildSearchTypesAndIgnoreAspects(boolean files, boolean folders,
Set<QName> ignoreQNameTypes) Set<QName> ignoreQNameTypes)
{ {
return thisService.buildSearchTypesAndIgnoreAspects(files, return thisService.buildSearchTypesAndIgnoreAspects(files,
folders, folders,
ignoreQNameTypes); ignoreQNameTypes);
} }
@Override @Override
public FileInfo createFileInfo(NodeRef nodeRef, QName typeQName, boolean isFolder, boolean isHidden, public FileInfo createFileInfo(NodeRef nodeRef, QName typeQName, boolean isFolder, boolean isHidden,
Map<QName, Serializable> properties) Map<QName, Serializable> properties)
{ {
return new FileInfoImpl(nodeRef, return new FileInfoImpl(nodeRef,
typeQName, typeQName,
isFolder, isFolder,
isHidden, isHidden,
properties); properties);
} }
@Override @Override
@@ -1772,39 +1770,39 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
@Override @Override
public PagingResults<FileInfo> list(final NodeRef contextNodeRef, final boolean files, final boolean folders, public PagingResults<FileInfo> list(final NodeRef contextNodeRef, final boolean files, final boolean folders,
final String pattern, final Set<QName> ignoreQNames, final List<Pair<QName, Boolean>> sortProps, final String pattern, final Set<QName> ignoreQNames, final List<Pair<QName, Boolean>> sortProps,
final PagingRequest pagingRequest) final PagingRequest pagingRequest)
{ {
return thisService.list(contextNodeRef, return thisService.list(contextNodeRef,
files, files,
folders, folders,
pattern, pattern,
ignoreQNames, ignoreQNames,
sortProps, sortProps,
pagingRequest); pagingRequest);
} }
@Override @Override
public PagingResults<FileInfo> list(final NodeRef rootNodeRef, final Set<QName> searchTypeQNames, public PagingResults<FileInfo> list(final NodeRef rootNodeRef, final Set<QName> searchTypeQNames,
final Set<QName> ignoreAspectQNames, final List<Pair<QName, Boolean>> sortProps, final Set<QName> ignoreAspectQNames, final List<Pair<QName, Boolean>> sortProps,
final PagingRequest pagingRequest) final PagingRequest pagingRequest)
{ {
return thisService.list(rootNodeRef, return thisService.list(rootNodeRef,
searchTypeQNames, searchTypeQNames,
ignoreAspectQNames, ignoreAspectQNames,
sortProps, sortProps,
pagingRequest); pagingRequest);
} }
@Override @Override
public List<FileInfo> search(final NodeRef contextNodeRef, final String namePattern, final boolean fileSearch, public List<FileInfo> search(final NodeRef contextNodeRef, final String namePattern, final boolean fileSearch,
final boolean folderSearch, final boolean includeSubFolders) final boolean folderSearch, final boolean includeSubFolders)
{ {
return thisService.search(contextNodeRef, return thisService.search(contextNodeRef,
namePattern, namePattern,
fileSearch, fileSearch,
folderSearch, folderSearch,
includeSubFolders); includeSubFolders);
} }
@Override @Override
@@ -1815,20 +1813,19 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
} }
public PagingResults<FileInfo> list(NodeRef contextNodeRef, public PagingResults<FileInfo> list(NodeRef contextNodeRef,
boolean files, boolean files,
boolean folders, boolean folders,
Set<QName> ignoreQNames, Set<QName> ignoreQNames,
List<Pair<QName, Boolean>> sortProps, List<Pair<QName, Boolean>> sortProps,
PagingRequest pagingRequest) PagingRequest pagingRequest)
{ {
return thisService.list(contextNodeRef, return thisService.list(contextNodeRef,
files, files,
folders, folders,
ignoreQNames, ignoreQNames,
sortProps, sortProps,
pagingRequest); pagingRequest);
} }
}; };
} }

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited * Copyright (C) 2005 - 2025 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@@ -43,14 +43,23 @@ public class FileExistsException extends AlfrescoRuntimeException
private NodeRef parentNodeRef; private NodeRef parentNodeRef;
private String name; private String name;
private String type;
public FileExistsException(NodeRef parentNodeRef, String name) public FileExistsException(NodeRef parentNodeRef, String name)
{ {
super(MESSAGE_ID, new Object[] { name }); super(MESSAGE_ID, new Object[]{name});
this.parentNodeRef = parentNodeRef; this.parentNodeRef = parentNodeRef;
this.name = name; this.name = name;
} }
public FileExistsException(NodeRef parentNodeRef, String name, String type)
{
super(MESSAGE_ID, new Object[]{name});
this.parentNodeRef = parentNodeRef;
this.name = name;
this.type = type;
}
public NodeRef getParentNodeRef() public NodeRef getParentNodeRef()
{ {
return parentNodeRef; return parentNodeRef;
@@ -60,4 +69,9 @@ public class FileExistsException extends AlfrescoRuntimeException
{ {
return name; return name;
} }
public String getType()
{
return type;
}
} }

View File

@@ -0,0 +1,62 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2025 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.service.cmr.model;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Common exception thrown when an operation fails because of a name clash of folder.
*
*/
@AlfrescoPublicApi
public class FolderExistsException extends AlfrescoRuntimeException
{
private static final String MESSAGE_ID = "file_folder_service.file_exists_message";
private static final long serialVersionUID = -4133713912784624118L;
private NodeRef parentNodeRef;
private String name;
public FolderExistsException(NodeRef parentNodeRef, String name)
{
super(MESSAGE_ID, new Object[]{name});
this.parentNodeRef = parentNodeRef;
this.name = name;
}
public NodeRef getParentNodeRef()
{
return parentNodeRef;
}
public String getName()
{
return name;
}
}

View File

@@ -48,6 +48,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.model.FolderExistsException;
import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -62,7 +63,7 @@ import org.alfresco.util.test.junitrules.ApplicationContextInit;
* *
* @author abalmus * @author abalmus
*/ */
@SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") @SuppressWarnings("PMD.UnitTestsShouldIncludeAssert")
public class ImporterActionExecuterTest public class ImporterActionExecuterTest
{ {
// Rule to initialise the default Alfresco spring configuration // Rule to initialise the default Alfresco spring configuration
@@ -340,6 +341,49 @@ public class ImporterActionExecuterTest
}); });
} }
@Test
public void testDuplicateUnzipping() throws IOException
{
final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper();
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>() {
@Override
public Void execute() throws Throwable
{
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
// create test data
NodeRef zipFileNodeRef = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, ContentModel.ASSOC_CHILDREN, ContentModel.TYPE_CONTENT).getChildRef();
NodeRef targetFolderNodeRef = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, ContentModel.ASSOC_CHILDREN, ContentModel.TYPE_FOLDER).getChildRef();
putContent(zipFileNodeRef, "import-archive-test/accentCharTestZip.zip");
Action action = createAction(zipFileNodeRef, "ImporterActionExecuterTestActionDefinition", targetFolderNodeRef);
try
{
importerActionExecuter.setUncompressedBytesLimit("100000");
importerActionExecuter.execute(action, zipFileNodeRef);
// unzip again to duplicate node
importerActionExecuter.execute(action, zipFileNodeRef);
}
catch (FolderExistsException e)
{
assertTrue(e.getMessage().contains("File or folder accentCharTestZip already exists"));
}
finally
{
// clean test data
nodeService.deleteNode(targetFolderNodeRef);
nodeService.deleteNode(zipFileNodeRef);
}
return null;
}
});
}
private void putContent(NodeRef zipFileNodeRef, String resource) private void putContent(NodeRef zipFileNodeRef, String resource)
{ {
URL url = AbstractContentTransformerTest.class.getClassLoader().getResource(resource); URL url = AbstractContentTransformerTest.class.getClassLoader().getResource(resource);