mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged BRANCHES/DEV/V3.4-BUG-FIX to HEAD:
32244: Fix for ALF-11435: 32246: Fix for ALF-11435 (part 2) 32247: Fix for ALF-11435 (part 3) plus make sure that hidden files have the noindex aspect applied git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@32388 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -36,7 +36,6 @@ import org.alfresco.jlan.server.filesys.FileName;
|
||||
import org.alfresco.jlan.server.filesys.FileType;
|
||||
import org.alfresco.jlan.util.WildCard;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.model.filefolder.FileFolderServiceImpl;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileFolderUtil;
|
||||
@@ -71,7 +70,7 @@ public class CifsHelper
|
||||
private FileFolderService fileFolderService;
|
||||
private MimetypeService mimetypeService;
|
||||
private PermissionService permissionService;
|
||||
|
||||
|
||||
private Set<QName> excludedTypes = new HashSet<QName>();
|
||||
|
||||
private boolean isReadOnlyFlagOnFolders = false;
|
||||
@@ -87,8 +86,8 @@ public class CifsHelper
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
@@ -124,7 +123,7 @@ public class CifsHelper
|
||||
this.excludedTypes.add(QName.createQName(exType));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Controls whether the read only flag is set on folders. This flag, when set, may cause problematic # behaviour in
|
||||
* Windows clients and doesn't necessarily mean a folder can't be written to. See ALF-6727. Should we ever set the
|
||||
@@ -286,6 +285,19 @@ public class CifsHelper
|
||||
if (name != null)
|
||||
{
|
||||
fileInfo.setFileName(name);
|
||||
|
||||
// Check for file names that should be hidden
|
||||
|
||||
if(nodeService.hasAspect(fileInfo.getNodeRef(), ContentModel.ASPECT_HIDDEN))
|
||||
{
|
||||
// Add the hidden file attribute
|
||||
int attr = fileInfo.getFileAttributes();
|
||||
if (( attr & FileAttribute.Hidden) == 0)
|
||||
{
|
||||
attr += FileAttribute.Hidden;
|
||||
fileInfo.setFileAttributes( attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read/write access
|
||||
@@ -704,4 +716,5 @@ public class CifsHelper
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -746,7 +746,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
|
||||
this.folderCacheLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
List<FileInfo> fileInfos = fileFolderService.listFiles(contextNodeRef);
|
||||
List<FileInfo> fileInfos = fileFolderService.removeHiddenFiles(fileFolderService.listFiles(contextNodeRef));
|
||||
final NavigableMap<Long, FileInfo> currentSearch = new TreeMap<Long, FileInfo>();
|
||||
|
||||
switch (viewMode)
|
||||
@@ -1047,7 +1047,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
|
||||
// Only list this folder if we have a wildcard name. Otherwise do a direct lookup by name.
|
||||
if (name.contains("*") || name.contains("%"))
|
||||
{
|
||||
list = fileFolderService.listFolders(root);
|
||||
list = fileFolderService.removeHiddenFiles(fileFolderService.listFolders(root));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -256,9 +256,16 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
// Is it a folder
|
||||
QName typeQName = nodeService.getType(nodeRef);
|
||||
boolean isFolder = isFolder(typeQName);
|
||||
boolean isHidden = false;
|
||||
|
||||
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_HIDDEN))
|
||||
{
|
||||
isHidden = true;
|
||||
}
|
||||
|
||||
// Construct the file info and add to the results
|
||||
FileInfo fileInfo = new FileInfoImpl(nodeRef, typeQName, isFolder, properties);
|
||||
FileInfo fileInfo = new FileInfoImpl(nodeRef, typeQName, isFolder, isHidden, properties);
|
||||
|
||||
// Done
|
||||
return fileInfo;
|
||||
}
|
||||
@@ -569,7 +576,7 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
}
|
||||
return childNodeRef;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see #search(NodeRef, String, boolean, boolean, boolean)
|
||||
*/
|
||||
@@ -1434,4 +1441,19 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
}
|
||||
return new Pair<String, String>(base, ext);
|
||||
}
|
||||
|
||||
public List<FileInfo> removeHiddenFiles(List<FileInfo> files)
|
||||
{
|
||||
List<FileInfo> ret = new ArrayList<FileInfo>(files.size());
|
||||
|
||||
for(FileInfo file : files)
|
||||
{
|
||||
if(!nodeService.hasAspect(file.getNodeRef(), ContentModel.ASPECT_HIDDEN))
|
||||
{
|
||||
ret.add(file);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@@ -33,6 +33,7 @@ import javax.transaction.UserTransaction;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.jlan.server.FileFilterMode;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.model.ForumModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
@@ -1277,6 +1278,35 @@ public class FileFolderServiceImplTest extends TestCase
|
||||
beforeSleep.compareTo((Date)nodeService.getProperty(destinationFolderNodeRef, ContentModel.PROP_MODIFIED)) < 0);
|
||||
}
|
||||
|
||||
public void testHiddenFiles()
|
||||
{
|
||||
FileFilterMode.setMode(FileFilterMode.Mode.ENHANCED);
|
||||
|
||||
NodeRef parent = fileFolderService.create(rootNodeRef, "New Folder", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef child = fileFolderService.create(parent, "file.tmp", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_TEMPORARY));
|
||||
assertTrue(!nodeService.hasAspect(child, ContentModel.ASPECT_HIDDEN));
|
||||
|
||||
NodeRef parent1 = fileFolderService.create(rootNodeRef, ".TemporaryItems", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef child1 = fileFolderService.create(parent1, "file1", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
assertTrue(nodeService.hasAspect(child1, ContentModel.ASPECT_TEMPORARY));
|
||||
assertTrue(nodeService.hasAspect(child1, ContentModel.ASPECT_HIDDEN));
|
||||
|
||||
NodeRef parent2 = fileFolderService.create(rootNodeRef, "Folder 2", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef child2 = fileFolderService.create(parent2, "Thumbs.db", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
assertTrue(!nodeService.hasAspect(child2, ContentModel.ASPECT_TEMPORARY));
|
||||
assertTrue(nodeService.hasAspect(child2, ContentModel.ASPECT_HIDDEN));
|
||||
|
||||
List<FileInfo> children = fileFolderService.list(parent);
|
||||
assertEquals(1, children.size());
|
||||
|
||||
children = fileFolderService.list(parent1);
|
||||
assertEquals(1, children.size());
|
||||
|
||||
children = fileFolderService.list(parent2);
|
||||
assertEquals(1, children.size());
|
||||
}
|
||||
|
||||
public void testPatterns()
|
||||
{
|
||||
// sanity checks only (see also GetChildrenCannedQueryTest)
|
||||
|
@@ -42,6 +42,7 @@ public class FileInfoImpl implements FileInfo
|
||||
private NodeRef linkNodeRef;
|
||||
private boolean isFolder;
|
||||
private boolean isLink;
|
||||
private boolean isHindden;
|
||||
private Map<QName, Serializable> properties;
|
||||
private QName typeQName;
|
||||
|
||||
@@ -52,6 +53,7 @@ public class FileInfoImpl implements FileInfo
|
||||
NodeRef nodeRef,
|
||||
QName typeQName,
|
||||
boolean isFolder,
|
||||
boolean isHidden,
|
||||
Map<QName, Serializable> properties)
|
||||
{
|
||||
this.nodeRef = nodeRef;
|
||||
@@ -59,6 +61,7 @@ public class FileInfoImpl implements FileInfo
|
||||
|
||||
this.isFolder = isFolder;
|
||||
this.properties = properties;
|
||||
this.isHindden = isHidden;
|
||||
|
||||
// Check if this is a link node
|
||||
if ( properties.containsKey( ContentModel.PROP_LINK_DESTINATION))
|
||||
@@ -135,6 +138,10 @@ public class FileInfoImpl implements FileInfo
|
||||
return isLink;
|
||||
}
|
||||
|
||||
public boolean isHidden() {
|
||||
return isHindden;
|
||||
}
|
||||
|
||||
public NodeRef getLinkNodeRef()
|
||||
{
|
||||
return linkNodeRef;
|
||||
|
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package org.alfresco.repo.model.filefolder;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.jlan.server.FileFilterMode;
|
||||
import org.alfresco.jlan.server.FileFilterMode.Mode;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.Path;
|
||||
import org.alfresco.service.cmr.repository.Path.Element;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.PatternFilter;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* An interceptor that intercepts the FileFolderService create method, creating files and folders as the system user
|
||||
* and applying temporary and hidden aspects when they match a pattern.
|
||||
*
|
||||
*/
|
||||
public class FilenameFilteringInterceptor implements MethodInterceptor
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(FilenameFilteringInterceptor.class);
|
||||
|
||||
private NodeService nodeService;
|
||||
private PermissionService permissionService;
|
||||
|
||||
private PatternFilter temporaryFiles;
|
||||
private PatternFilter hiddenFiles;
|
||||
private PatternFilter systemPaths;
|
||||
|
||||
public FilenameFilteringInterceptor()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of regular expressions that represent patterns of hidden files.
|
||||
*
|
||||
*/
|
||||
public void setHiddenFiles(PatternFilter hiddenFiles)
|
||||
{
|
||||
this.hiddenFiles = hiddenFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of regular expressions that represent patterns of temporary files.
|
||||
*
|
||||
*/
|
||||
public void setTemporaryFiles(PatternFilter temporaryFiles)
|
||||
{
|
||||
this.temporaryFiles = temporaryFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of regular expressions that represent patterns of system paths.
|
||||
*
|
||||
*/
|
||||
public void setSystemPaths(PatternFilter systemPaths)
|
||||
{
|
||||
this.systemPaths = systemPaths;
|
||||
}
|
||||
|
||||
public Mode getMode()
|
||||
{
|
||||
return FileFilterMode.getMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeService the service to use to apply the <b>sys:temporary</b> aspect
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
private void checkTemporaryAspect(boolean isTemporary, FileInfo fileInfo)
|
||||
{
|
||||
NodeRef nodeRef = fileInfo.getNodeRef();
|
||||
|
||||
if(isTemporary)
|
||||
{
|
||||
// it matched, so apply the temporary and hidden aspects
|
||||
nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY, null);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Applied temporary marker: " + fileInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there was NOT a match then the file should not be marked as temporary
|
||||
// after any of the operations in question.
|
||||
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TEMPORARY))
|
||||
{
|
||||
// Remove the aspect
|
||||
nodeService.removeAspect(nodeRef, ContentModel.ASPECT_TEMPORARY);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Removed temporary marker: " + fileInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkHiddenAspect(boolean isHidden, FileInfo fileInfo)
|
||||
{
|
||||
NodeRef nodeRef = fileInfo.getNodeRef();
|
||||
|
||||
if (isHidden)
|
||||
{
|
||||
nodeService.addAspect(nodeRef, ContentModel.ASPECT_HIDDEN, null);
|
||||
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>(2);
|
||||
props.put(ContentModel.PROP_IS_INDEXED, Boolean.FALSE);
|
||||
props.put(ContentModel.PROP_IS_CONTENT_INDEXED, Boolean.FALSE);
|
||||
nodeService.addAspect(nodeRef, ContentModel.ASPECT_INDEX_CONTROL, props);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Applied hidden marker: " + fileInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_HIDDEN))
|
||||
{
|
||||
// Remove the aspect
|
||||
nodeService.removeAspect(nodeRef, ContentModel.ASPECT_HIDDEN);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Removed hidden marker: " + fileInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addIndexedAspect(FileInfo fileInfo)
|
||||
{
|
||||
NodeRef nodeRef = fileInfo.getNodeRef();
|
||||
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>(2);
|
||||
props.put(ContentModel.PROP_IS_INDEXED, Boolean.FALSE);
|
||||
props.put(ContentModel.PROP_IS_CONTENT_INDEXED, Boolean.FALSE);
|
||||
nodeService.addAspect(nodeRef, ContentModel.ASPECT_INDEX_CONTROL, props);
|
||||
}
|
||||
|
||||
private Object runAsSystem(MethodInvocation invocation) throws Throwable
|
||||
{
|
||||
Object ret = null;
|
||||
|
||||
// We're creating in enhanced mode and have a matching filename or path. Switch to
|
||||
// the system user to do the operation.
|
||||
|
||||
AuthenticationUtil.pushAuthentication();
|
||||
try
|
||||
{
|
||||
AuthenticationUtil.setRunAsUserSystem();
|
||||
ret = invocation.proceed();
|
||||
}
|
||||
finally
|
||||
{
|
||||
AuthenticationUtil.popAuthentication();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private boolean isSystemPath(NodeRef parentNodeRef, String filename)
|
||||
{
|
||||
boolean ret = false;
|
||||
Path path = nodeService.getPath(parentNodeRef);
|
||||
|
||||
Iterator<Element> it = path.iterator();
|
||||
while(it.hasNext())
|
||||
{
|
||||
Path.ChildAssocElement elem = (Path.ChildAssocElement)it.next();
|
||||
QName qname = elem.getRef().getQName();
|
||||
if(qname != null && systemPaths.isFiltered(qname.getLocalName()))
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Object invoke(final MethodInvocation invocation) throws Throwable
|
||||
{
|
||||
// execute and get the result
|
||||
String methodName = invocation.getMethod().getName();
|
||||
Object ret = null;
|
||||
|
||||
// do the invocation
|
||||
if (methodName.startsWith("create"))
|
||||
{
|
||||
NodeRef nodeRef = (NodeRef)invocation.getArguments()[0];
|
||||
String filename = (String)invocation.getArguments()[1];
|
||||
|
||||
if(getMode() == Mode.ENHANCED)
|
||||
{
|
||||
if(systemPaths.isFiltered(filename))
|
||||
{
|
||||
// it's a system file/folder, create as system and allow full control to all authorities
|
||||
ret = runAsSystem(invocation);
|
||||
permissionService.setPermission(((FileInfo)ret).getNodeRef(), PermissionService.ALL_AUTHORITIES, PermissionService.FULL_CONTROL, true);
|
||||
|
||||
// it's always marked temporary and hidden
|
||||
checkTemporaryAspect(true, (FileInfo)ret);
|
||||
checkHiddenAspect(true, (FileInfo)ret);
|
||||
addIndexedAspect((FileInfo)ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's not a temporary file/folder, create as normal
|
||||
ret = invocation.proceed();
|
||||
|
||||
// if it's on a temporary path check whether temporary and hidden aspects need to be applied
|
||||
if(isSystemPath(nodeRef, filename))
|
||||
{
|
||||
checkTemporaryAspect(true, (FileInfo)ret);
|
||||
checkHiddenAspect(true, (FileInfo)ret);
|
||||
addIndexedAspect((FileInfo)ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
checkTemporaryAspect(temporaryFiles.isFiltered(filename), (FileInfo)ret);
|
||||
boolean isHidden = hiddenFiles.isFiltered(filename);
|
||||
checkHiddenAspect(isHidden, (FileInfo)ret);
|
||||
if(isHidden)
|
||||
{
|
||||
addIndexedAspect((FileInfo)ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = invocation.proceed();
|
||||
|
||||
checkTemporaryAspect(temporaryFiles.isFiltered(filename), (FileInfo)ret);
|
||||
}
|
||||
}
|
||||
else if (methodName.startsWith("rename") ||
|
||||
methodName.startsWith("move") ||
|
||||
methodName.startsWith("copy"))
|
||||
{
|
||||
ret = invocation.proceed();
|
||||
|
||||
FileInfo fileInfo = (FileInfo) ret;
|
||||
String filename = fileInfo.getName();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Checking filename returned by " + methodName + ": " + filename);
|
||||
}
|
||||
|
||||
// check against all the regular expressions
|
||||
checkTemporaryAspect(temporaryFiles.isFiltered(filename), fileInfo);
|
||||
|
||||
boolean isHidden = hiddenFiles.isFiltered(filename);
|
||||
checkHiddenAspect(isHidden, fileInfo);
|
||||
if(isHidden)
|
||||
{
|
||||
addIndexedAspect((FileInfo)ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = invocation.proceed();
|
||||
}
|
||||
|
||||
// done
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.model.filefolder;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* An interceptor for the {@link org.alfresco.service.cmr.model.FileFolderService FileFolderService}
|
||||
* that marks files or folders with the <b>sys:temporary</b> aspect depending on the
|
||||
* name pattern {@link #setFilterRegularExpressions(List) provided}.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class TempFileMarkerInterceptor implements MethodInterceptor
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(TempFileMarkerInterceptor.class);
|
||||
|
||||
private NodeService nodeService;
|
||||
private List<String> filterRegularExpressions;
|
||||
|
||||
public TempFileMarkerInterceptor()
|
||||
{
|
||||
filterRegularExpressions = Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeService the service to use to apply the <b>sys:temporary</b> aspect
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of regular expressions that represent patterns of temporary files.
|
||||
*
|
||||
* @param regexps list of regular expressions
|
||||
*
|
||||
* @see String#matches(java.lang.String)
|
||||
*/
|
||||
public void setFilterRegularExpressions(List<String> regexps)
|
||||
{
|
||||
this.filterRegularExpressions = regexps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles <b>rename</b>, <b>move</b>, <b>copy</b>
|
||||
*/
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable
|
||||
{
|
||||
Object ret = invocation.proceed();
|
||||
|
||||
// execute and get the result
|
||||
String methodName = invocation.getMethod().getName();
|
||||
if (methodName.startsWith("create") ||
|
||||
methodName.startsWith("rename") ||
|
||||
methodName.startsWith("move") ||
|
||||
methodName.startsWith("copy"))
|
||||
{
|
||||
FileInfo fileInfo = (FileInfo) ret;
|
||||
String filename = fileInfo.getName();
|
||||
NodeRef nodeRef = fileInfo.getNodeRef();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Checking filename returned by " + methodName + ": " + filename);
|
||||
}
|
||||
|
||||
// check against all the regular expressions
|
||||
boolean matched = false;
|
||||
for (String regexp : filterRegularExpressions)
|
||||
{
|
||||
if (!filename.matches(regexp))
|
||||
{
|
||||
// it is not a match - try next one
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
matched = true;
|
||||
// it matched, so apply the aspect
|
||||
nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY, null);
|
||||
// no further checking required
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Applied temporary marker: " + fileInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If there was NOT a match then the file should not be marked as temporary
|
||||
// after any of the operations in question.
|
||||
if (!matched && nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TEMPORARY))
|
||||
{
|
||||
// Remove the aspect
|
||||
nodeService.removeAspect(nodeRef, ContentModel.ASPECT_TEMPORARY);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Removed temporary marker: " + fileInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
// done
|
||||
return ret;
|
||||
}
|
||||
}
|
@@ -53,7 +53,7 @@ public interface FileFolderService
|
||||
*/
|
||||
@Auditable(parameters = {"contextNodeRef"})
|
||||
public List<FileInfo> list(NodeRef contextNodeRef);
|
||||
|
||||
|
||||
/**
|
||||
* Lists page of immediate child files and/or folders of the given context node
|
||||
* with optional filtering (exclusion of certain child file/folder subtypes) and sorting
|
||||
@@ -396,4 +396,12 @@ public interface FileFolderService
|
||||
*/
|
||||
@Auditable(parameters = {"typeQName"})
|
||||
public FileFolderServiceType getType(QName typeQName);
|
||||
|
||||
/**
|
||||
* Removes any hidden files from the file list.
|
||||
*
|
||||
* @param files
|
||||
* @return a list of files with hidden files removed
|
||||
*/
|
||||
public List<FileInfo> removeHiddenFiles(List<FileInfo> files);
|
||||
}
|
||||
|
@@ -52,6 +52,11 @@ public interface FileInfo extends PermissionCheckValue, Serializable
|
||||
*/
|
||||
public boolean isLink();
|
||||
|
||||
/**
|
||||
* @return true if this instance represents a hidden file
|
||||
*/
|
||||
public boolean isHidden();
|
||||
|
||||
/**
|
||||
* @return Return the reference to the node that this node is linked to
|
||||
*/
|
||||
|
Reference in New Issue
Block a user