Merged 5.1.N (5.1.2) to 5.2.N (5.2.1)

125605 rmunteanu: Merged 5.1.1 (5.1.1) to 5.1.N (5.1.2)
      125498 slanglois: MNT-16155 Update source headers - remove svn:eol-style property on Java and JSP source files


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@125783 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Raluca Munteanu
2016-04-26 13:03:25 +00:00
parent 8674e2bfc8
commit dc6b2852d0
830 changed files with 142585 additions and 142585 deletions

View File

@@ -1,415 +1,415 @@
package org.alfresco.repo.model.filefolder;
import java.util.Iterator;
import java.util.regex.Pattern;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.model.filefolder.HiddenAspect.Visibility;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
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.FileFilterMode;
import org.alfresco.util.FileFilterMode.Client;
import org.alfresco.util.FileFilterMode.Mode;
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 FileFolderService methods, ensuring system, temporary and hidden files
* and paths are marked with the correct aspects.
*
* @author alex.mukha
*/
public class FilenameFilteringInterceptor implements MethodInterceptor
{
private static Log logger = LogFactory.getLog(FilenameFilteringInterceptor.class);
private static final String XLSX_MIMETYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
private static final String MACOS_TEMPORARY_FILE_NAME_PREFIX = "._";
private static final Pattern XSL_MACOS_TEMPORARY_FILENAME_FITLER = Pattern.compile("^(\\" + MACOS_TEMPORARY_FILE_NAME_PREFIX + ")?[0-9,a-f]{8}$", Pattern.CASE_INSENSITIVE
| Pattern.UNICODE_CASE);
private NodeService nodeService;
private PermissionService permissionService;
private ContentService contentService;
private PatternFilter temporaryFiles;
private PatternFilter systemPaths;
private HiddenAspect hiddenAspect;
private boolean enabled = true;
public FilenameFilteringInterceptor()
{
}
/**
* A list of regular expressions that represent patterns of temporary files.
*
*/
public void setTemporaryFiles(PatternFilter temporaryFiles)
{
this.temporaryFiles = temporaryFiles;
}
public void setHiddenAspect(HiddenAspect hiddenAspect)
{
this.hiddenAspect = hiddenAspect;
}
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
/**
* 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();
}
public Client getClient()
{
return FileFilterMode.getClient();
}
/**
* @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;
}
public void setContentService(ContentService contentService)
{
this.contentService = contentService;
}
public ContentService getContentService()
{
return contentService;
}
private void checkTemporaryAspect(boolean isTemporary, FileInfo fileInfo)
{
checkTemporaryAspect(isTemporary, fileInfo.getNodeRef());
}
private void checkTemporaryAspect(boolean isTemporary, NodeRef nodeRef)
{
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: " + nodeRef);
}
}
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: " + nodeRef);
}
}
}
}
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;
}
private int getSystemFileVisibilityMask()
{
int mask = 0;
mask |= hiddenAspect.getClientVisibilityMask(Client.cifs, Visibility.HiddenAttribute);
mask |= hiddenAspect.getClientVisibilityMask(Client.webdav, Visibility.Visible);
mask |= hiddenAspect.getClientVisibilityMask(Client.nfs, Visibility.Visible);
mask |= hiddenAspect.getClientVisibilityMask(Client.ftp, Visibility.Visible);
return mask;
}
public Object invoke(final MethodInvocation invocation) throws Throwable
{
if (!enabled)
{
return invocation.proceed();
}
// 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);
FileInfoImpl fileInfo = (FileInfoImpl)ret;
permissionService.setPermission(fileInfo.getNodeRef(), PermissionService.ALL_AUTHORITIES, PermissionService.FULL_CONTROL, true);
// it's always marked temporary and hidden
checkTemporaryAspect(true, fileInfo);
hiddenAspect.hideNode(fileInfo, getSystemFileVisibilityMask(), false, false, false);
}
else
{
// it's not a temporary file/folder, create as normal
ret = invocation.proceed();
FileInfoImpl fileInfo = (FileInfoImpl)ret;
if(isSystemPath(nodeRef, filename))
{
// it's on a system path, check whether temporary, hidden and noindex aspects need to be applied
checkTemporaryAspect(true, fileInfo);
hiddenAspect.hideNode(fileInfo, getSystemFileVisibilityMask(), false, false, false);
}
else
{
// check whether it's a temporary or hidden file
FileInfo sourceInfo = (FileInfo)ret;
boolean isTmp = isTemporaryObject(filename, sourceInfo.getNodeRef());
checkTemporaryAspect(isTmp, sourceInfo);
boolean isHidden = hiddenAspect.checkHidden(fileInfo, false, false);
if(isHidden && fileInfo instanceof FileInfoImpl)
{
((FileInfoImpl)fileInfo).setHidden(true);
}
}
}
}
else
{
ret = invocation.proceed();
FileInfoImpl fileInfo = (FileInfoImpl)ret;
boolean isTmp = isTemporaryObject(filename, fileInfo.getNodeRef());
checkTemporaryAspect(isTmp, fileInfo);
}
}
else if (methodName.startsWith("move"))
{
Object[] args = invocation.getArguments();
NodeRef sourceNodeRef = (NodeRef)args[0];
String newName = (String)args[args.length -1];
if(newName != null)
{
// Name is changing
// check against all the regular expressions
boolean isTmp = isTemporaryObject(newName, sourceNodeRef);
checkTemporaryAspect(isTmp, sourceNodeRef);
}
// now do the move
ret = invocation.proceed();
if(getMode() == Mode.ENHANCED)
{
hiddenAspect.checkHidden(sourceNodeRef, true, true);
}
}
else if (methodName.startsWith("copy"))
{
ret = invocation.proceed();
FileInfoImpl fileInfo = (FileInfoImpl) ret;
String filename = fileInfo.getName();
if (logger.isDebugEnabled())
{
logger.debug("Checking filename returned by " + methodName + ": " + filename);
}
// check against all the regular expressions
boolean isTmp = isTemporaryObject(filename, fileInfo.getNodeRef());
checkTemporaryAspect(isTmp, fileInfo);
if(getMode() == Mode.ENHANCED)
{
boolean isHidden = hiddenAspect.checkHidden(fileInfo, true, true);
if(isHidden && fileInfo instanceof FileInfoImpl)
{
((FileInfoImpl)fileInfo).setHidden(true);
}
}
/*
* TODO should these two calls be before the proceed? However its the same problem as create
* The node needs to be created before we can add aspects.
*/
}
else if (methodName.startsWith("rename"))
{
Object[] args = invocation.getArguments();
if(args != null && args.length == 2)
{
/**
* Expecting rename(NodeRef, newName)
*/
String newName = (String)args[1];
NodeRef sourceNodeRef = (NodeRef)args[0];
if (logger.isDebugEnabled())
{
logger.debug("Checking filename returned by " + methodName + ": " + newName);
}
// check against all the regular expressions
boolean isTmp = isTemporaryObject(newName, sourceNodeRef);
checkTemporaryAspect(isTmp, sourceNodeRef);
ret = invocation.proceed();
if(getMode() == Mode.ENHANCED)
{
boolean isHidden = hiddenAspect.checkHidden(sourceNodeRef, true, true);
if(isHidden && ret instanceof FileInfoImpl)
{
((FileInfoImpl)ret).setHidden(true);
}
}
return ret;
}
else
{
/**
* expected rename(NodeRef, String) - got something else...
*/
throw new AlfrescoRuntimeException("FilenameFilteringInterceptor: unknown rename method");
}
}
else
{
ret = invocation.proceed();
}
// done
return ret;
}
/**
* Determines whether specified <code>name</code> matches any pattern of temporary file names.
* <br>Also it checks special case of new XLS document creation in MacOS:
* <ul>
* <li>its name doesnt have extension (on MacOS, but it has .tmp extension on Windows);
* <li>length of its name equals to 8;
* <li>its name contains only hexadecimal digits (0-9, A-F);
* <li>it has Mimetype equal to application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.
* </ul>
*
* @param name - {@link String} value which contains name of node
* @param nodeRef - {@link NodeRef} instance of the node
* @return {@link boolean} value. <code>true</code> if <code>name</code> is name of temporary object.
*/
private boolean isTemporaryObject(String name, NodeRef nodeRef)
{
boolean isFiltered = temporaryFiles.isFiltered(name);
if (isFiltered)
{
return true;
}
// This pattern must be validated in conjunction with mimetype validation only!
boolean result = XSL_MACOS_TEMPORARY_FILENAME_FITLER.matcher(name).matches();
if (result && !name.startsWith(MACOS_TEMPORARY_FILE_NAME_PREFIX))
{
ContentReader contentReader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
if (null != contentReader)
{
result = XLSX_MIMETYPE.equals(contentReader.getMimetype());
}
else
{
// MNT-10561
// We are unable to determine the mimetype so assume it's NOT temporary
result = false;
}
}
return result;
}
}
package org.alfresco.repo.model.filefolder;
import java.util.Iterator;
import java.util.regex.Pattern;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.model.filefolder.HiddenAspect.Visibility;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
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.FileFilterMode;
import org.alfresco.util.FileFilterMode.Client;
import org.alfresco.util.FileFilterMode.Mode;
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 FileFolderService methods, ensuring system, temporary and hidden files
* and paths are marked with the correct aspects.
*
* @author alex.mukha
*/
public class FilenameFilteringInterceptor implements MethodInterceptor
{
private static Log logger = LogFactory.getLog(FilenameFilteringInterceptor.class);
private static final String XLSX_MIMETYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
private static final String MACOS_TEMPORARY_FILE_NAME_PREFIX = "._";
private static final Pattern XSL_MACOS_TEMPORARY_FILENAME_FITLER = Pattern.compile("^(\\" + MACOS_TEMPORARY_FILE_NAME_PREFIX + ")?[0-9,a-f]{8}$", Pattern.CASE_INSENSITIVE
| Pattern.UNICODE_CASE);
private NodeService nodeService;
private PermissionService permissionService;
private ContentService contentService;
private PatternFilter temporaryFiles;
private PatternFilter systemPaths;
private HiddenAspect hiddenAspect;
private boolean enabled = true;
public FilenameFilteringInterceptor()
{
}
/**
* A list of regular expressions that represent patterns of temporary files.
*
*/
public void setTemporaryFiles(PatternFilter temporaryFiles)
{
this.temporaryFiles = temporaryFiles;
}
public void setHiddenAspect(HiddenAspect hiddenAspect)
{
this.hiddenAspect = hiddenAspect;
}
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
/**
* 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();
}
public Client getClient()
{
return FileFilterMode.getClient();
}
/**
* @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;
}
public void setContentService(ContentService contentService)
{
this.contentService = contentService;
}
public ContentService getContentService()
{
return contentService;
}
private void checkTemporaryAspect(boolean isTemporary, FileInfo fileInfo)
{
checkTemporaryAspect(isTemporary, fileInfo.getNodeRef());
}
private void checkTemporaryAspect(boolean isTemporary, NodeRef nodeRef)
{
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: " + nodeRef);
}
}
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: " + nodeRef);
}
}
}
}
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;
}
private int getSystemFileVisibilityMask()
{
int mask = 0;
mask |= hiddenAspect.getClientVisibilityMask(Client.cifs, Visibility.HiddenAttribute);
mask |= hiddenAspect.getClientVisibilityMask(Client.webdav, Visibility.Visible);
mask |= hiddenAspect.getClientVisibilityMask(Client.nfs, Visibility.Visible);
mask |= hiddenAspect.getClientVisibilityMask(Client.ftp, Visibility.Visible);
return mask;
}
public Object invoke(final MethodInvocation invocation) throws Throwable
{
if (!enabled)
{
return invocation.proceed();
}
// 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);
FileInfoImpl fileInfo = (FileInfoImpl)ret;
permissionService.setPermission(fileInfo.getNodeRef(), PermissionService.ALL_AUTHORITIES, PermissionService.FULL_CONTROL, true);
// it's always marked temporary and hidden
checkTemporaryAspect(true, fileInfo);
hiddenAspect.hideNode(fileInfo, getSystemFileVisibilityMask(), false, false, false);
}
else
{
// it's not a temporary file/folder, create as normal
ret = invocation.proceed();
FileInfoImpl fileInfo = (FileInfoImpl)ret;
if(isSystemPath(nodeRef, filename))
{
// it's on a system path, check whether temporary, hidden and noindex aspects need to be applied
checkTemporaryAspect(true, fileInfo);
hiddenAspect.hideNode(fileInfo, getSystemFileVisibilityMask(), false, false, false);
}
else
{
// check whether it's a temporary or hidden file
FileInfo sourceInfo = (FileInfo)ret;
boolean isTmp = isTemporaryObject(filename, sourceInfo.getNodeRef());
checkTemporaryAspect(isTmp, sourceInfo);
boolean isHidden = hiddenAspect.checkHidden(fileInfo, false, false);
if(isHidden && fileInfo instanceof FileInfoImpl)
{
((FileInfoImpl)fileInfo).setHidden(true);
}
}
}
}
else
{
ret = invocation.proceed();
FileInfoImpl fileInfo = (FileInfoImpl)ret;
boolean isTmp = isTemporaryObject(filename, fileInfo.getNodeRef());
checkTemporaryAspect(isTmp, fileInfo);
}
}
else if (methodName.startsWith("move"))
{
Object[] args = invocation.getArguments();
NodeRef sourceNodeRef = (NodeRef)args[0];
String newName = (String)args[args.length -1];
if(newName != null)
{
// Name is changing
// check against all the regular expressions
boolean isTmp = isTemporaryObject(newName, sourceNodeRef);
checkTemporaryAspect(isTmp, sourceNodeRef);
}
// now do the move
ret = invocation.proceed();
if(getMode() == Mode.ENHANCED)
{
hiddenAspect.checkHidden(sourceNodeRef, true, true);
}
}
else if (methodName.startsWith("copy"))
{
ret = invocation.proceed();
FileInfoImpl fileInfo = (FileInfoImpl) ret;
String filename = fileInfo.getName();
if (logger.isDebugEnabled())
{
logger.debug("Checking filename returned by " + methodName + ": " + filename);
}
// check against all the regular expressions
boolean isTmp = isTemporaryObject(filename, fileInfo.getNodeRef());
checkTemporaryAspect(isTmp, fileInfo);
if(getMode() == Mode.ENHANCED)
{
boolean isHidden = hiddenAspect.checkHidden(fileInfo, true, true);
if(isHidden && fileInfo instanceof FileInfoImpl)
{
((FileInfoImpl)fileInfo).setHidden(true);
}
}
/*
* TODO should these two calls be before the proceed? However its the same problem as create
* The node needs to be created before we can add aspects.
*/
}
else if (methodName.startsWith("rename"))
{
Object[] args = invocation.getArguments();
if(args != null && args.length == 2)
{
/**
* Expecting rename(NodeRef, newName)
*/
String newName = (String)args[1];
NodeRef sourceNodeRef = (NodeRef)args[0];
if (logger.isDebugEnabled())
{
logger.debug("Checking filename returned by " + methodName + ": " + newName);
}
// check against all the regular expressions
boolean isTmp = isTemporaryObject(newName, sourceNodeRef);
checkTemporaryAspect(isTmp, sourceNodeRef);
ret = invocation.proceed();
if(getMode() == Mode.ENHANCED)
{
boolean isHidden = hiddenAspect.checkHidden(sourceNodeRef, true, true);
if(isHidden && ret instanceof FileInfoImpl)
{
((FileInfoImpl)ret).setHidden(true);
}
}
return ret;
}
else
{
/**
* expected rename(NodeRef, String) - got something else...
*/
throw new AlfrescoRuntimeException("FilenameFilteringInterceptor: unknown rename method");
}
}
else
{
ret = invocation.proceed();
}
// done
return ret;
}
/**
* Determines whether specified <code>name</code> matches any pattern of temporary file names.
* <br>Also it checks special case of new XLS document creation in MacOS:
* <ul>
* <li>its name doesnt have extension (on MacOS, but it has .tmp extension on Windows);
* <li>length of its name equals to 8;
* <li>its name contains only hexadecimal digits (0-9, A-F);
* <li>it has Mimetype equal to application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.
* </ul>
*
* @param name - {@link String} value which contains name of node
* @param nodeRef - {@link NodeRef} instance of the node
* @return {@link boolean} value. <code>true</code> if <code>name</code> is name of temporary object.
*/
private boolean isTemporaryObject(String name, NodeRef nodeRef)
{
boolean isFiltered = temporaryFiles.isFiltered(name);
if (isFiltered)
{
return true;
}
// This pattern must be validated in conjunction with mimetype validation only!
boolean result = XSL_MACOS_TEMPORARY_FILENAME_FITLER.matcher(name).matches();
if (result && !name.startsWith(MACOS_TEMPORARY_FILE_NAME_PREFIX))
{
ContentReader contentReader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
if (null != contentReader)
{
result = XLSX_MIMETYPE.equals(contentReader.getMimetype());
}
else
{
// MNT-10561
// We are unable to determine the mimetype so assume it's NOT temporary
result = false;
}
}
return result;
}
}

View File

@@ -1,183 +1,183 @@
package org.alfresco.repo.model.filefolder;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.query.CannedQueryParameters;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.domain.node.NodePropertyHelper;
import org.alfresco.repo.domain.qname.QNameDAO;
import org.alfresco.repo.domain.query.CannedQueryDAO;
import org.alfresco.repo.model.filefolder.HiddenAspect.Visibility;
import org.alfresco.repo.node.getchildren.FilterProp;
import org.alfresco.repo.node.getchildren.GetChildrenCannedQueryParams;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityBean;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.FileFilterMode;
import org.alfresco.util.FileFilterMode.Client;
/**
* GetChidren canned query for files and folders.
*
* To get paged list of files and folders of a parent folder filtered by child type.
* Also optionally filtered and/or sorted by one or more properties (up to three).
*
* This is the same as the nodes getchildren canned query, except it takes into account hidden files and folders (with respect to client visibility)
* and other aspect(s) to ignore - eg. optionally "cm:checkedOut" in case of Share DocLib.
*
* @since 4.1.1
* @author steveglover, janv
*
*/
public class GetChildrenCannedQuery extends org.alfresco.repo.node.getchildren.GetChildrenCannedQuery
{
private HiddenAspect hiddenAspect;
private DictionaryService dictionaryService;
private NodeService nodeService;
private Set<QName> ignoreAspectQNames;
public GetChildrenCannedQuery(
NodeDAO nodeDAO,
QNameDAO qnameDAO,
CannedQueryDAO cannedQueryDAO,
NodePropertyHelper nodePropertyHelper,
TenantService tenantService,
NodeService nodeService,
MethodSecurityBean<NodeRef> methodSecurity,
CannedQueryParameters params,
HiddenAspect hiddenAspect,
DictionaryService dictionaryService,
Set<QName> ignoreAspectQNames)
{
super(nodeDAO, qnameDAO, cannedQueryDAO, nodePropertyHelper, tenantService, nodeService, methodSecurity, params);
this.hiddenAspect = hiddenAspect;
this.dictionaryService = dictionaryService;
this.nodeService = nodeService;
this.ignoreAspectQNames = ignoreAspectQNames;
}
@Override
protected UnsortedChildQueryCallback getUnsortedChildQueryCallback(final List<NodeRef> rawResult, final int requestedCount, GetChildrenCannedQueryParams paramBean)
{
Set<QName> inclusiveAspects = paramBean.getInclusiveAspects();
Set<QName> exclusiveAspects = paramBean.getExclusiveAspects();
UnsortedChildQueryCallback callback = new FileFolderUnsortedChildQueryCallback(rawResult, requestedCount, inclusiveAspects, exclusiveAspects);
return callback;
}
@Override
protected FilterSortChildQueryCallback getFilterSortChildQuery(final List<FilterSortNode> children, final List<FilterProp> filterProps, GetChildrenCannedQueryParams paramBean)
{
FilterSortChildQueryCallback callback = new FileFolderFilterSortChildQueryCallback(children, filterProps);
return callback;
}
private class FileFolderFilterSortChildQueryCallback extends DefaultFilterSortChildQueryCallback
{
private Map<QName, Boolean> isTypeFolderMap = new HashMap<QName, Boolean>(10);
public FileFolderFilterSortChildQueryCallback(List<FilterSortNode> children, List<FilterProp> filterProps)
{
super(children, filterProps);
}
@Override
protected boolean include(FilterSortNode node)
{
boolean ret = super.include(node);
return ret && includeImpl(ret, node.getNodeRef());
}
@Override
public boolean handle(FilterSortNode node)
{
super.handle(node);
Map<QName, Serializable> propVals = node.getPropVals();
QName nodeTypeQName = (QName)propVals.get(GetChildrenCannedQuery.SORT_QNAME_NODE_TYPE);
if (nodeTypeQName != null)
{
// ALF-13968
Boolean isFolder = isTypeFolderMap.get(nodeTypeQName);
if (isFolder == null)
{
isFolder = dictionaryService.isSubClass(nodeTypeQName, ContentModel.TYPE_FOLDER);
isTypeFolderMap.put(nodeTypeQName, isFolder);
}
propVals.put(GetChildrenCannedQuery.SORT_QNAME_NODE_IS_FOLDER, isFolder);
}
return true;
}
}
private class FileFolderUnsortedChildQueryCallback extends DefaultUnsortedChildQueryCallback
{
public FileFolderUnsortedChildQueryCallback(List<NodeRef> rawResult,int requestedCount, Set<QName> inclusiveAspects, Set<QName> exclusiveAspects)
{
super(rawResult, requestedCount, inclusiveAspects, exclusiveAspects);
}
@Override
protected boolean include(NodeRef nodeRef)
{
boolean ret = super.include(nodeRef);
return ret && includeImpl(ret, nodeRef);
}
}
protected boolean includeImpl(boolean ret, NodeRef nodeRef)
{
// only visible files are returned, relative to the client type.
try
{
if (!nodeService.exists(nodeRef))
{
// Node has disappeared
return ret;
}
final Client client = FileFilterMode.getClient();
boolean notHidden = hiddenAspect.getVisibility(client, nodeRef) != Visibility.NotVisible;
boolean notIgnore = true;
if (ignoreAspectQNames != null)
{
if (ignoreAspectQNames.size() > 1)
{
Set<QName> nodeAspects = nodeService.getAspects(nodeRef);
notIgnore = (! nodeAspects.removeAll(ignoreAspectQNames));
}
else if (ignoreAspectQNames.size() == 1)
{
if (nodeService.hasAspect(nodeRef, ignoreAspectQNames.iterator().next()))
{
notIgnore = false;
}
}
}
return ret && notHidden && notIgnore;
}
catch (AccessDeniedException e)
{
// user may not have permission to determine the visibility of the node
return ret;
}
}
}
package org.alfresco.repo.model.filefolder;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.query.CannedQueryParameters;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.domain.node.NodePropertyHelper;
import org.alfresco.repo.domain.qname.QNameDAO;
import org.alfresco.repo.domain.query.CannedQueryDAO;
import org.alfresco.repo.model.filefolder.HiddenAspect.Visibility;
import org.alfresco.repo.node.getchildren.FilterProp;
import org.alfresco.repo.node.getchildren.GetChildrenCannedQueryParams;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityBean;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.FileFilterMode;
import org.alfresco.util.FileFilterMode.Client;
/**
* GetChidren canned query for files and folders.
*
* To get paged list of files and folders of a parent folder filtered by child type.
* Also optionally filtered and/or sorted by one or more properties (up to three).
*
* This is the same as the nodes getchildren canned query, except it takes into account hidden files and folders (with respect to client visibility)
* and other aspect(s) to ignore - eg. optionally "cm:checkedOut" in case of Share DocLib.
*
* @since 4.1.1
* @author steveglover, janv
*
*/
public class GetChildrenCannedQuery extends org.alfresco.repo.node.getchildren.GetChildrenCannedQuery
{
private HiddenAspect hiddenAspect;
private DictionaryService dictionaryService;
private NodeService nodeService;
private Set<QName> ignoreAspectQNames;
public GetChildrenCannedQuery(
NodeDAO nodeDAO,
QNameDAO qnameDAO,
CannedQueryDAO cannedQueryDAO,
NodePropertyHelper nodePropertyHelper,
TenantService tenantService,
NodeService nodeService,
MethodSecurityBean<NodeRef> methodSecurity,
CannedQueryParameters params,
HiddenAspect hiddenAspect,
DictionaryService dictionaryService,
Set<QName> ignoreAspectQNames)
{
super(nodeDAO, qnameDAO, cannedQueryDAO, nodePropertyHelper, tenantService, nodeService, methodSecurity, params);
this.hiddenAspect = hiddenAspect;
this.dictionaryService = dictionaryService;
this.nodeService = nodeService;
this.ignoreAspectQNames = ignoreAspectQNames;
}
@Override
protected UnsortedChildQueryCallback getUnsortedChildQueryCallback(final List<NodeRef> rawResult, final int requestedCount, GetChildrenCannedQueryParams paramBean)
{
Set<QName> inclusiveAspects = paramBean.getInclusiveAspects();
Set<QName> exclusiveAspects = paramBean.getExclusiveAspects();
UnsortedChildQueryCallback callback = new FileFolderUnsortedChildQueryCallback(rawResult, requestedCount, inclusiveAspects, exclusiveAspects);
return callback;
}
@Override
protected FilterSortChildQueryCallback getFilterSortChildQuery(final List<FilterSortNode> children, final List<FilterProp> filterProps, GetChildrenCannedQueryParams paramBean)
{
FilterSortChildQueryCallback callback = new FileFolderFilterSortChildQueryCallback(children, filterProps);
return callback;
}
private class FileFolderFilterSortChildQueryCallback extends DefaultFilterSortChildQueryCallback
{
private Map<QName, Boolean> isTypeFolderMap = new HashMap<QName, Boolean>(10);
public FileFolderFilterSortChildQueryCallback(List<FilterSortNode> children, List<FilterProp> filterProps)
{
super(children, filterProps);
}
@Override
protected boolean include(FilterSortNode node)
{
boolean ret = super.include(node);
return ret && includeImpl(ret, node.getNodeRef());
}
@Override
public boolean handle(FilterSortNode node)
{
super.handle(node);
Map<QName, Serializable> propVals = node.getPropVals();
QName nodeTypeQName = (QName)propVals.get(GetChildrenCannedQuery.SORT_QNAME_NODE_TYPE);
if (nodeTypeQName != null)
{
// ALF-13968
Boolean isFolder = isTypeFolderMap.get(nodeTypeQName);
if (isFolder == null)
{
isFolder = dictionaryService.isSubClass(nodeTypeQName, ContentModel.TYPE_FOLDER);
isTypeFolderMap.put(nodeTypeQName, isFolder);
}
propVals.put(GetChildrenCannedQuery.SORT_QNAME_NODE_IS_FOLDER, isFolder);
}
return true;
}
}
private class FileFolderUnsortedChildQueryCallback extends DefaultUnsortedChildQueryCallback
{
public FileFolderUnsortedChildQueryCallback(List<NodeRef> rawResult,int requestedCount, Set<QName> inclusiveAspects, Set<QName> exclusiveAspects)
{
super(rawResult, requestedCount, inclusiveAspects, exclusiveAspects);
}
@Override
protected boolean include(NodeRef nodeRef)
{
boolean ret = super.include(nodeRef);
return ret && includeImpl(ret, nodeRef);
}
}
protected boolean includeImpl(boolean ret, NodeRef nodeRef)
{
// only visible files are returned, relative to the client type.
try
{
if (!nodeService.exists(nodeRef))
{
// Node has disappeared
return ret;
}
final Client client = FileFilterMode.getClient();
boolean notHidden = hiddenAspect.getVisibility(client, nodeRef) != Visibility.NotVisible;
boolean notIgnore = true;
if (ignoreAspectQNames != null)
{
if (ignoreAspectQNames.size() > 1)
{
Set<QName> nodeAspects = nodeService.getAspects(nodeRef);
notIgnore = (! nodeAspects.removeAll(ignoreAspectQNames));
}
else if (ignoreAspectQNames.size() == 1)
{
if (nodeService.hasAspect(nodeRef, ignoreAspectQNames.iterator().next()))
{
notIgnore = false;
}
}
}
return ret && notHidden && notIgnore;
}
catch (AccessDeniedException e)
{
// user may not have permission to determine the visibility of the node
return ret;
}
}
}

View File

@@ -1,46 +1,46 @@
package org.alfresco.repo.model.filefolder;
import java.util.List;
import java.util.Set;
import org.alfresco.query.CannedQuery;
import org.alfresco.query.CannedQueryParameters;
import org.alfresco.query.PagingRequest;
import org.alfresco.repo.domain.node.NodePropertyHelper;
import org.alfresco.repo.node.getchildren.FilterProp;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
/**
* GetChidren canned query factory for files and folders.
*
* @since 4.1.1
* @author steveglover, janv
*
*/
public class GetChildrenCannedQueryFactory extends org.alfresco.repo.node.getchildren.GetChildrenCannedQueryFactory
{
private HiddenAspect hiddenAspect;
private Set<QName> ignoreAspectQNames;
public void setHiddenAspect(HiddenAspect hiddenAspect)
{
this.hiddenAspect = hiddenAspect;
}
public CannedQuery<NodeRef> getCannedQuery(NodeRef parentRef, String pattern, Set<QName> assocTypeQNames, Set<QName> childTypeQNames, Set<QName> ignoreAspectQNames, List<FilterProp> filterProps, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest)
{
this.ignoreAspectQNames = ignoreAspectQNames;
return super.getCannedQuery(parentRef, pattern, assocTypeQNames, childTypeQNames, filterProps, sortProps, pagingRequest);
}
@Override
public CannedQuery<NodeRef> getCannedQuery(CannedQueryParameters parameters)
{
NodePropertyHelper nodePropertyHelper = new NodePropertyHelper(dictionaryService, qnameDAO, localeDAO, contentDataDAO);
return (CannedQuery<NodeRef>) new GetChildrenCannedQuery(nodeDAO, qnameDAO, cannedQueryDAO, nodePropertyHelper, tenantService, nodeService, methodSecurity, parameters, hiddenAspect, dictionaryService, ignoreAspectQNames);
}
}
package org.alfresco.repo.model.filefolder;
import java.util.List;
import java.util.Set;
import org.alfresco.query.CannedQuery;
import org.alfresco.query.CannedQueryParameters;
import org.alfresco.query.PagingRequest;
import org.alfresco.repo.domain.node.NodePropertyHelper;
import org.alfresco.repo.node.getchildren.FilterProp;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
/**
* GetChidren canned query factory for files and folders.
*
* @since 4.1.1
* @author steveglover, janv
*
*/
public class GetChildrenCannedQueryFactory extends org.alfresco.repo.node.getchildren.GetChildrenCannedQueryFactory
{
private HiddenAspect hiddenAspect;
private Set<QName> ignoreAspectQNames;
public void setHiddenAspect(HiddenAspect hiddenAspect)
{
this.hiddenAspect = hiddenAspect;
}
public CannedQuery<NodeRef> getCannedQuery(NodeRef parentRef, String pattern, Set<QName> assocTypeQNames, Set<QName> childTypeQNames, Set<QName> ignoreAspectQNames, List<FilterProp> filterProps, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest)
{
this.ignoreAspectQNames = ignoreAspectQNames;
return super.getCannedQuery(parentRef, pattern, assocTypeQNames, childTypeQNames, filterProps, sortProps, pagingRequest);
}
@Override
public CannedQuery<NodeRef> getCannedQuery(CannedQueryParameters parameters)
{
NodePropertyHelper nodePropertyHelper = new NodePropertyHelper(dictionaryService, qnameDAO, localeDAO, contentDataDAO);
return (CannedQuery<NodeRef>) new GetChildrenCannedQuery(nodeDAO, qnameDAO, cannedQueryDAO, nodePropertyHelper, tenantService, nodeService, methodSecurity, parameters, hiddenAspect, dictionaryService, ignoreAspectQNames);
}
}

View File

@@ -1,100 +1,100 @@
package org.alfresco.repo.model.filefolder;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
/**
* Spring bean defining a hidden node filter.
*
* @since 4.0
*
*/
public class HiddenFileFilter implements InitializingBean
{
private String filter;
private String visibility;
private String hiddenAttribute;
private boolean cascadeHiddenAspect = true;
private boolean cascadeIndexControlAspect = true;
private boolean cmisDisableHideConfig;
public HiddenFileFilter()
{
}
public void setFilter(String filter)
{
this.filter = filter;
}
public void setVisibility(String visibility)
{
this.visibility = visibility;
}
public String getFilter()
{
return filter;
}
public String getVisibility()
{
return visibility;
}
public String getHiddenAttribute()
{
return hiddenAttribute;
}
public void setHiddenAttribute(String hiddenAttribute)
{
this.hiddenAttribute = hiddenAttribute;
}
public void setCascadeHiddenAspect(boolean cascadeHiddenAspect)
{
this.cascadeHiddenAspect = cascadeHiddenAspect;
}
public boolean cascadeHiddenAspect()
{
return cascadeHiddenAspect;
}
public void setCascadeIndexControlAspect(boolean cascadeIndexControlAspect)
{
this.cascadeIndexControlAspect = cascadeIndexControlAspect;
}
public boolean cascadeIndexControlAspect()
{
return cascadeIndexControlAspect;
}
public void setCmisDisableHideConfig(boolean cmisDisableHideConfig)
{
this.cmisDisableHideConfig = cmisDisableHideConfig;
}
public boolean isCmisDisableHideConfig()
{
return cmisDisableHideConfig;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "filter", filter);
if(visibility == null)
{
visibility = "";
}
if(hiddenAttribute == null)
{
hiddenAttribute = "";
}
}
}
package org.alfresco.repo.model.filefolder;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
/**
* Spring bean defining a hidden node filter.
*
* @since 4.0
*
*/
public class HiddenFileFilter implements InitializingBean
{
private String filter;
private String visibility;
private String hiddenAttribute;
private boolean cascadeHiddenAspect = true;
private boolean cascadeIndexControlAspect = true;
private boolean cmisDisableHideConfig;
public HiddenFileFilter()
{
}
public void setFilter(String filter)
{
this.filter = filter;
}
public void setVisibility(String visibility)
{
this.visibility = visibility;
}
public String getFilter()
{
return filter;
}
public String getVisibility()
{
return visibility;
}
public String getHiddenAttribute()
{
return hiddenAttribute;
}
public void setHiddenAttribute(String hiddenAttribute)
{
this.hiddenAttribute = hiddenAttribute;
}
public void setCascadeHiddenAspect(boolean cascadeHiddenAspect)
{
this.cascadeHiddenAspect = cascadeHiddenAspect;
}
public boolean cascadeHiddenAspect()
{
return cascadeHiddenAspect;
}
public void setCascadeIndexControlAspect(boolean cascadeIndexControlAspect)
{
this.cascadeIndexControlAspect = cascadeIndexControlAspect;
}
public boolean cascadeIndexControlAspect()
{
return cascadeIndexControlAspect;
}
public void setCmisDisableHideConfig(boolean cmisDisableHideConfig)
{
this.cmisDisableHideConfig = cmisDisableHideConfig;
}
public boolean isCmisDisableHideConfig()
{
return cmisDisableHideConfig;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "filter", filter);
if(visibility == null)
{
visibility = "";
}
if(hiddenAttribute == null)
{
hiddenAttribute = "";
}
}
}

View File

@@ -1,17 +1,17 @@
package org.alfresco.repo.model.filefolder;
/**
* Represents hidden file information, including the filter (regular expression) and the visibility mask.
*
* @since 4.0
*
*/
public interface HiddenFileInfo
{
public boolean cascadeHiddenAspect();
public boolean cascadeIndexControlAspect();
public boolean isClientControlled();
public int getVisibilityMask();
public String getFilter();
public boolean isHidden(String path);
}
package org.alfresco.repo.model.filefolder;
/**
* Represents hidden file information, including the filter (regular expression) and the visibility mask.
*
* @since 4.0
*
*/
public interface HiddenFileInfo
{
public boolean cascadeHiddenAspect();
public boolean cascadeIndexControlAspect();
public boolean isClientControlled();
public int getVisibilityMask();
public String getFilter();
public boolean isHidden(String path);
}