mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-01 14:41:46 +00:00
[ACS-9572] Show proper message for duplicate unzipping (#3356)
This commit is contained in:
@@ -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);
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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,31 +109,27 @@ 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 + "')" +
|
||||||
@@ -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
|
||||||
{
|
{
|
||||||
@@ -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,8 +439,8 @@ 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)
|
||||||
@@ -480,7 +479,6 @@ 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)
|
||||||
@@ -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,
|
||||||
@@ -896,24 +892,21 @@ 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())
|
||||||
@@ -986,7 +979,6 @@ 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());
|
||||||
@@ -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
|
||||||
{
|
{
|
||||||
@@ -1259,7 +1252,8 @@ 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
|
||||||
|
* node to check
|
||||||
* @return true => system folder path based node
|
* @return true => system folder path based node
|
||||||
*/
|
*/
|
||||||
private boolean isSystemPath(NodeRef nodeRef)
|
private boolean isSystemPath(NodeRef nodeRef)
|
||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
@@ -1386,17 +1384,17 @@ 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);
|
||||||
@@ -1473,17 +1470,17 @@ 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
|
||||||
@@ -1554,7 +1550,8 @@ public class FileFolderServiceImpl extends AbstractBaseCopyService implements Fi
|
|||||||
{
|
{
|
||||||
throw (FileNotFoundException) e.getCause();
|
throw (FileNotFoundException) e.getCause();
|
||||||
}
|
}
|
||||||
else throw e;
|
else
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1693,7 +1690,8 @@ 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
|
||||||
|
: hiddenAspect
|
||||||
.getVisibility(client, nodeRef);
|
.getVisibility(client, nodeRef);
|
||||||
if (clientVisibility != Visibility.Visible)
|
if (clientVisibility != Visibility.Visible)
|
||||||
{
|
{
|
||||||
@@ -1815,7 +1813,6 @@ 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,
|
||||||
|
@@ -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,6 +43,7 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -51,6 +52,14 @@ public class FileExistsException extends AlfrescoRuntimeException
|
|||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user