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:
@@ -80,12 +80,8 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean name="temporaryFiles" class="org.alfresco.util.PatternFilter">
|
||||||
<bean name="tempFileMarkerInterceptor" class="org.alfresco.repo.model.filefolder.TempFileMarkerInterceptor">
|
<property name="patterns">
|
||||||
<property name="nodeService">
|
|
||||||
<ref bean="nodeService" />
|
|
||||||
</property>
|
|
||||||
<property name="filterRegularExpressions">
|
|
||||||
<list>
|
<list>
|
||||||
<value><![CDATA[.*\.tmp]]></value>
|
<value><![CDATA[.*\.tmp]]></value>
|
||||||
<value><![CDATA[.*\.temp]]></value>
|
<value><![CDATA[.*\.temp]]></value>
|
||||||
@@ -94,7 +90,36 @@
|
|||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<!-- Files matching one of these patterns will be marked with the 'hidden' aspect -->
|
||||||
|
<bean name="hiddenFiles" class="org.alfresco.util.PatternFilter">
|
||||||
|
<property name="patterns">
|
||||||
|
<list>
|
||||||
|
<value><![CDATA[\..*]]></value>
|
||||||
|
<value><![CDATA[Thumbs\.db]]></value>
|
||||||
|
<value><![CDATA[Desktop\.ini]]></value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Paths matching one of these patterns will be treated as temporary paths -->
|
||||||
|
<bean name="systemPaths" class="org.alfresco.util.PatternFilter">
|
||||||
|
<property name="patterns">
|
||||||
|
<list>
|
||||||
|
<value><![CDATA[.*\.TemporaryItems.*]]></value>
|
||||||
|
<value><![CDATA[.*\.DS_Store.*]]></value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean name="filenameFilteringInterceptor" class="org.alfresco.repo.model.filefolder.FilenameFilteringInterceptor">
|
||||||
|
<property name="nodeService" ref="nodeService" />
|
||||||
|
<property name="permissionService" ref="permissionService" />
|
||||||
|
<property name="systemPaths" ref="systemPaths" />
|
||||||
|
<property name="hiddenFiles" ref="hiddenFiles" />
|
||||||
|
<property name="temporaryFiles" ref="temporaryFiles" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
<!-- Multilingual specific service -->
|
<!-- Multilingual specific service -->
|
||||||
<bean name="multilingualContentService" class="org.alfresco.repo.model.ml.MultilingualContentServiceImpl" >
|
<bean name="multilingualContentService" class="org.alfresco.repo.model.ml.MultilingualContentServiceImpl" >
|
||||||
<property name="nodeService">
|
<property name="nodeService">
|
||||||
|
@@ -155,6 +155,13 @@
|
|||||||
<!-- Explicitly turn off archiving for all nodes with this aspect -->
|
<!-- Explicitly turn off archiving for all nodes with this aspect -->
|
||||||
<archive>false</archive>
|
<archive>false</archive>
|
||||||
</aspect>
|
</aspect>
|
||||||
|
|
||||||
|
<!-- aspect to tag hidden nodes -->
|
||||||
|
<aspect name="sys:hidden">
|
||||||
|
<title>Hidden</title>
|
||||||
|
<!-- Explicitly turn off archiving for all nodes with this aspect -->
|
||||||
|
<archive>false</archive>
|
||||||
|
</aspect>
|
||||||
|
|
||||||
<!-- aspect to tag nodes which are, by default, undeletable -->
|
<!-- aspect to tag nodes which are, by default, undeletable -->
|
||||||
<aspect name="sys:undeletable">
|
<aspect name="sys:undeletable">
|
||||||
|
@@ -745,7 +745,6 @@
|
|||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- File/Folder Service -->
|
<!-- File/Folder Service -->
|
||||||
|
|
||||||
<bean id="FileFolderService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
<bean id="FileFolderService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||||
<property name="proxyInterfaces">
|
<property name="proxyInterfaces">
|
||||||
<value>org.alfresco.service.cmr.model.FileFolderService</value>
|
<value>org.alfresco.service.cmr.model.FileFolderService</value>
|
||||||
@@ -756,12 +755,12 @@
|
|||||||
<property name="interceptorNames">
|
<property name="interceptorNames">
|
||||||
<list>
|
<list>
|
||||||
<idref local="FileFolderService_transaction"/>
|
<idref local="FileFolderService_transaction"/>
|
||||||
|
<idref bean="filenameFilteringInterceptor"/>
|
||||||
<idref local="AuditMethodInterceptor"/>
|
<idref local="AuditMethodInterceptor"/>
|
||||||
<idref local="exceptionTranslator"/>
|
<idref local="exceptionTranslator"/>
|
||||||
<idref bean="FileFolderService_security"/>
|
<idref bean="FileFolderService_security"/>
|
||||||
<idref bean="mlTranslationInterceptor"/>
|
<idref bean="mlTranslationInterceptor"/>
|
||||||
<idref bean="mlContentInterceptor"/>
|
<idref bean="mlContentInterceptor"/>
|
||||||
<idref bean="tempFileMarkerInterceptor"/>
|
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
@@ -432,6 +432,7 @@
|
|||||||
org.alfresco.service.cmr.model.FileFolderService.getWriter=ACL_NODE.0.sys:base.WriteContent
|
org.alfresco.service.cmr.model.FileFolderService.getWriter=ACL_NODE.0.sys:base.WriteContent
|
||||||
org.alfresco.service.cmr.model.FileFolderService.exists=ACL_ALLOW
|
org.alfresco.service.cmr.model.FileFolderService.exists=ACL_ALLOW
|
||||||
org.alfresco.service.cmr.model.FileFolderService.getType=ACL_ALLOW
|
org.alfresco.service.cmr.model.FileFolderService.getType=ACL_ALLOW
|
||||||
|
org.alfresco.service.cmr.model.FileFolderService.removeHiddenFiles=ACL_ALLOW
|
||||||
org.alfresco.service.cmr.model.FileFolderService.*=ACL_DENY
|
org.alfresco.service.cmr.model.FileFolderService.*=ACL_DENY
|
||||||
</value>
|
</value>
|
||||||
</property>
|
</property>
|
||||||
|
@@ -36,7 +36,6 @@ import org.alfresco.jlan.server.filesys.FileName;
|
|||||||
import org.alfresco.jlan.server.filesys.FileType;
|
import org.alfresco.jlan.server.filesys.FileType;
|
||||||
import org.alfresco.jlan.util.WildCard;
|
import org.alfresco.jlan.util.WildCard;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.model.filefolder.FileFolderServiceImpl;
|
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
import org.alfresco.service.cmr.model.FileFolderUtil;
|
import org.alfresco.service.cmr.model.FileFolderUtil;
|
||||||
@@ -71,7 +70,7 @@ public class CifsHelper
|
|||||||
private FileFolderService fileFolderService;
|
private FileFolderService fileFolderService;
|
||||||
private MimetypeService mimetypeService;
|
private MimetypeService mimetypeService;
|
||||||
private PermissionService permissionService;
|
private PermissionService permissionService;
|
||||||
|
|
||||||
private Set<QName> excludedTypes = new HashSet<QName>();
|
private Set<QName> excludedTypes = new HashSet<QName>();
|
||||||
|
|
||||||
private boolean isReadOnlyFlagOnFolders = false;
|
private boolean isReadOnlyFlagOnFolders = false;
|
||||||
@@ -87,8 +86,8 @@ public class CifsHelper
|
|||||||
{
|
{
|
||||||
this.dictionaryService = dictionaryService;
|
this.dictionaryService = dictionaryService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNodeService(NodeService nodeService)
|
public void setNodeService(NodeService nodeService)
|
||||||
{
|
{
|
||||||
this.nodeService = nodeService;
|
this.nodeService = nodeService;
|
||||||
}
|
}
|
||||||
@@ -124,7 +123,7 @@ public class CifsHelper
|
|||||||
this.excludedTypes.add(QName.createQName(exType));
|
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
|
* 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
|
* 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)
|
if (name != null)
|
||||||
{
|
{
|
||||||
fileInfo.setFileName(name);
|
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
|
// Read/write access
|
||||||
@@ -704,4 +716,5 @@ public class CifsHelper
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -746,7 +746,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
|
|||||||
this.folderCacheLock.readLock().unlock();
|
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>();
|
final NavigableMap<Long, FileInfo> currentSearch = new TreeMap<Long, FileInfo>();
|
||||||
|
|
||||||
switch (viewMode)
|
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.
|
// Only list this folder if we have a wildcard name. Otherwise do a direct lookup by name.
|
||||||
if (name.contains("*") || name.contains("%"))
|
if (name.contains("*") || name.contains("%"))
|
||||||
{
|
{
|
||||||
list = fileFolderService.listFolders(root);
|
list = fileFolderService.removeHiddenFiles(fileFolderService.listFolders(root));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -256,9 +256,16 @@ public class FileFolderServiceImpl implements FileFolderService
|
|||||||
// Is it a folder
|
// Is it a folder
|
||||||
QName typeQName = nodeService.getType(nodeRef);
|
QName typeQName = nodeService.getType(nodeRef);
|
||||||
boolean isFolder = isFolder(typeQName);
|
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
|
// 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
|
// Done
|
||||||
return fileInfo;
|
return fileInfo;
|
||||||
}
|
}
|
||||||
@@ -569,7 +576,7 @@ public class FileFolderServiceImpl implements FileFolderService
|
|||||||
}
|
}
|
||||||
return childNodeRef;
|
return childNodeRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #search(NodeRef, String, boolean, boolean, boolean)
|
* @see #search(NodeRef, String, boolean, boolean, boolean)
|
||||||
*/
|
*/
|
||||||
@@ -1434,4 +1441,19 @@ public class FileFolderServiceImpl implements FileFolderService
|
|||||||
}
|
}
|
||||||
return new Pair<String, String>(base, ext);
|
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 junit.framework.TestCase;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.jlan.server.FileFilterMode;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.model.ForumModel;
|
import org.alfresco.model.ForumModel;
|
||||||
import org.alfresco.query.PagingRequest;
|
import org.alfresco.query.PagingRequest;
|
||||||
@@ -1277,6 +1278,35 @@ public class FileFolderServiceImplTest extends TestCase
|
|||||||
beforeSleep.compareTo((Date)nodeService.getProperty(destinationFolderNodeRef, ContentModel.PROP_MODIFIED)) < 0);
|
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()
|
public void testPatterns()
|
||||||
{
|
{
|
||||||
// sanity checks only (see also GetChildrenCannedQueryTest)
|
// sanity checks only (see also GetChildrenCannedQueryTest)
|
||||||
|
@@ -42,6 +42,7 @@ public class FileInfoImpl implements FileInfo
|
|||||||
private NodeRef linkNodeRef;
|
private NodeRef linkNodeRef;
|
||||||
private boolean isFolder;
|
private boolean isFolder;
|
||||||
private boolean isLink;
|
private boolean isLink;
|
||||||
|
private boolean isHindden;
|
||||||
private Map<QName, Serializable> properties;
|
private Map<QName, Serializable> properties;
|
||||||
private QName typeQName;
|
private QName typeQName;
|
||||||
|
|
||||||
@@ -52,6 +53,7 @@ public class FileInfoImpl implements FileInfo
|
|||||||
NodeRef nodeRef,
|
NodeRef nodeRef,
|
||||||
QName typeQName,
|
QName typeQName,
|
||||||
boolean isFolder,
|
boolean isFolder,
|
||||||
|
boolean isHidden,
|
||||||
Map<QName, Serializable> properties)
|
Map<QName, Serializable> properties)
|
||||||
{
|
{
|
||||||
this.nodeRef = nodeRef;
|
this.nodeRef = nodeRef;
|
||||||
@@ -59,6 +61,7 @@ public class FileInfoImpl implements FileInfo
|
|||||||
|
|
||||||
this.isFolder = isFolder;
|
this.isFolder = isFolder;
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
|
this.isHindden = isHidden;
|
||||||
|
|
||||||
// Check if this is a link node
|
// Check if this is a link node
|
||||||
if ( properties.containsKey( ContentModel.PROP_LINK_DESTINATION))
|
if ( properties.containsKey( ContentModel.PROP_LINK_DESTINATION))
|
||||||
@@ -135,6 +138,10 @@ public class FileInfoImpl implements FileInfo
|
|||||||
return isLink;
|
return isLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isHidden() {
|
||||||
|
return isHindden;
|
||||||
|
}
|
||||||
|
|
||||||
public NodeRef getLinkNodeRef()
|
public NodeRef getLinkNodeRef()
|
||||||
{
|
{
|
||||||
return linkNodeRef;
|
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"})
|
@Auditable(parameters = {"contextNodeRef"})
|
||||||
public List<FileInfo> list(NodeRef contextNodeRef);
|
public List<FileInfo> list(NodeRef contextNodeRef);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists page of immediate child files and/or folders of the given context node
|
* 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
|
* with optional filtering (exclusion of certain child file/folder subtypes) and sorting
|
||||||
@@ -396,4 +396,12 @@ public interface FileFolderService
|
|||||||
*/
|
*/
|
||||||
@Auditable(parameters = {"typeQName"})
|
@Auditable(parameters = {"typeQName"})
|
||||||
public FileFolderServiceType getType(QName 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();
|
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
|
* @return Return the reference to the node that this node is linked to
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user