ALF-11698 Cifs needs to set hidden file attribute

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@45668 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Mark Rogers
2013-01-21 15:28:41 +00:00
parent 6f9c37ab6f
commit f880d47128
4 changed files with 157 additions and 25 deletions

View File

@@ -191,6 +191,11 @@
<mandatory>false</mandatory> <mandatory>false</mandatory>
<default>0</default> <default>0</default>
</property> </property>
<!-- Is this file hidden regardless of file name patterns -->
<property name="sys:hiddenFlag">
<type>d:boolean</type>
<mandatory>false</mandatory>
</property>
</properties> </properties>
</aspect> </aspect>

View File

@@ -76,6 +76,7 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.encoding.ContentCharsetFinder; import org.alfresco.repo.content.encoding.ContentCharsetFinder;
import org.alfresco.repo.content.filestore.FileContentReader; import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.repo.model.filefolder.HiddenAspect;
import org.alfresco.repo.node.archive.NodeArchiveService; import org.alfresco.repo.node.archive.NodeArchiveService;
import org.alfresco.repo.node.archive.RestoreNodeReport; import org.alfresco.repo.node.archive.RestoreNodeReport;
import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.policy.BehaviourFilter;
@@ -146,6 +147,7 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD
private NodeMonitorFactory m_nodeMonitorFactory; private NodeMonitorFactory m_nodeMonitorFactory;
private ContentComparator contentComparator; private ContentComparator contentComparator;
private NodeArchiveService nodeArchiveService; private NodeArchiveService nodeArchiveService;
private HiddenAspect hiddenAspect;
// TODO Should not be here - should be specific to a context. // TODO Should not be here - should be specific to a context.
private boolean isLockedFilesAsOffline; private boolean isLockedFilesAsOffline;
@@ -172,6 +174,7 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD
PropertyCheck.mandatory(this, "ioControlHandler", ioControlHandler); PropertyCheck.mandatory(this, "ioControlHandler", ioControlHandler);
PropertyCheck.mandatory(this, "contentComparator", getContentComparator()); PropertyCheck.mandatory(this, "contentComparator", getContentComparator());
PropertyCheck.mandatory(this, "nodeArchiveService", nodeArchiveService); PropertyCheck.mandatory(this, "nodeArchiveService", nodeArchiveService);
PropertyCheck.mandatory(this, "hiddenAspect", hiddenAspect);
} }
/** /**
@@ -387,6 +390,14 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD
this.policyBehaviourFilter = policyFilter; this.policyBehaviourFilter = policyFilter;
} }
/**
* @param hiddenAspect
*/
public void setHiddenAspect(HiddenAspect hiddenAspect)
{
this.hiddenAspect = hiddenAspect;
}
// Configuration key names // Configuration key names
private static final String KEY_STORE = "store"; private static final String KEY_STORE = "store";
@@ -1583,27 +1594,23 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD
if(info.isHidden()) if(info.isHidden())
{ {
// yes is hidden // yes is hidden
if(!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_HIDDEN)) if ( logger.isDebugEnabled())
{ {
if ( logger.isDebugEnabled()) logger.debug("Set hidden aspect" + name);
{
logger.debug("Set hidden aspect (not yet implemented)" + name);
}
// TODO Not yet implemented - and how to reset hidden bit?
// nodeService.addAspect(nodeRef, ContentModel.ASPECT_HIDDEN, null);
} }
hiddenAspect.hideNodeExplicit(nodeRef);
} }
else else
{ {
// not hidden is hidden // not hidden
if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_HIDDEN)) if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_HIDDEN))
{ {
if ( logger.isDebugEnabled()) if ( logger.isDebugEnabled())
{ {
logger.debug("Reset hidden aspect (not yet implemented)" + name); logger.debug("Reset hidden aspect" + name);
} }
hiddenAspect.unhideExplicit(nodeRef);
} }
// not hidden
} }
} // End of setting attributes } // End of setting attributes

View File

@@ -170,10 +170,43 @@ public class HiddenAspect
} }
} }
private void addHiddenAspect(NodeRef nodeRef, int visibilityMask) /**
* Mark this node as hidden regardless of any name/pattern/matching rules. Following this call the node
* will be hidden.
*
* If the node is already hidden will do nothing.
*
* @param nodeRef
*/
public void hideNodeExplicit(NodeRef nodeRef)
{
int mask = 0;
mask |= getClientVisibilityMask(Client.cifs, Visibility.HiddenAttribute);
mask |= getClientVisibilityMask(Client.webdav, Visibility.Visible);
mask |= getClientVisibilityMask(Client.nfs, Visibility.Visible);
mask |= getClientVisibilityMask(Client.ftp, Visibility.Visible);
addHiddenAspect(nodeRef, mask, true);
}
/**
* Remove the explicit hiding of a node. Following this call the node may or may not remain hidden based upon the other
* properties of the node.
*
* @param nodeRef
*/
public void unhideExplicit(NodeRef nodeRef)
{
nodeService.setProperty(nodeRef, ContentModel.PROP_HIDDEN_FLAG, false);
checkHidden(nodeRef, true);
}
private void addHiddenAspect(NodeRef nodeRef, int visibilityMask, boolean explicit)
{ {
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1); Map<QName, Serializable> props = new HashMap<QName, Serializable>(1);
props.put(ContentModel.PROP_VISIBILITY_MASK, visibilityMask); props.put(ContentModel.PROP_VISIBILITY_MASK, visibilityMask);
props.put(ContentModel.PROP_HIDDEN_FLAG, explicit);
nodeService.addAspect(nodeRef, ContentModel.ASPECT_HIDDEN, props); nodeService.addAspect(nodeRef, ContentModel.ASPECT_HIDDEN, props);
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
@@ -257,7 +290,7 @@ public class HiddenAspect
NodeRef childNodeRef = file.getNodeRef(); NodeRef childNodeRef = file.getNodeRef();
if(filter.cascadeHiddenAspect() && !hasHiddenAspect(childNodeRef)) if(filter.cascadeHiddenAspect() && !hasHiddenAspect(childNodeRef))
{ {
addHiddenAspect(childNodeRef, visibilityMask); addHiddenAspect(childNodeRef, visibilityMask, false);
} }
if(filter.cascadeIndexControlAspect() && !hasIndexControlAspect(childNodeRef)) if(filter.cascadeIndexControlAspect() && !hasIndexControlAspect(childNodeRef))
@@ -344,6 +377,13 @@ public class HiddenAspect
return ret; return ret;
} }
/**
* getClientVisibilityMap
*
* @param client
* @param visibility
* @return the client visibilityMask
*/
public int getClientVisibilityMask(Client client, Visibility visibility) public int getClientVisibilityMask(Client client, Visibility visibility)
{ {
return visibility.getMask() << getClientIndex(client)*2; return visibility.getMask() << getClientIndex(client)*2;
@@ -389,10 +429,16 @@ public class HiddenAspect
*/ */
public void hideNode(NodeRef nodeRef) public void hideNode(NodeRef nodeRef)
{ {
addHiddenAspect(nodeRef, 0); addHiddenAspect(nodeRef, 0, false);
addIndexControlAspect(nodeRef); addIndexControlAspect(nodeRef);
} }
/**
* Removes the hidden and index contol aspect. Reverses the effect of calling hideNode(NodeRef nodeRef)
*
* @param nodeRef the node to show
* @param cascade true to cascade to all descendents of this node
*/
public void showNode(NodeRef nodeRef, boolean cascade) public void showNode(NodeRef nodeRef, boolean cascade)
{ {
removeHiddenAspect(nodeRef); removeHiddenAspect(nodeRef);
@@ -411,13 +457,12 @@ public class HiddenAspect
* Hides the node by applying the hidden and not indexed aspects. The node will be hidden from clients * Hides the node by applying the hidden and not indexed aspects. The node will be hidden from clients
* according to the visibility mask. * according to the visibility mask.
* *
* @param client * @param nodeRef the node to hide
* @param fileInfo * @param clientVisibilityMask
* @return
*/ */
public void hideNode(NodeRef nodeRef, int clientVisibilityMask) public void hideNode(NodeRef nodeRef, int clientVisibilityMask)
{ {
addHiddenAspect(nodeRef, clientVisibilityMask); addHiddenAspect(nodeRef, clientVisibilityMask, true);
addIndexControlAspect(nodeRef); addIndexControlAspect(nodeRef);
} }
@@ -445,7 +490,10 @@ public class HiddenAspect
} }
/** /**
* Checks whether the file should be hidden and applies the hidden and not indexed aspects if so. * Checks whether the file should be hidden based upon whether its name maches a set of filters and applies the hidden
* and not indexed aspects if so.
* <p>
* Can optionally remove the hidden and index control aspects if the name of a node no longer matches the filter.
* *
* @param fileInfo * @param fileInfo
* @param both if true, will check if the node should not be hidden and remove hidden and index control * @param both if true, will check if the node should not be hidden and remove hidden and index control
@@ -467,9 +515,9 @@ public class HiddenAspect
* Hides the node by applying the hidden and not indexed aspects. The node will be hidden from clients * Hides the node by applying the hidden and not indexed aspects. The node will be hidden from clients
* according to the visibility mask. * according to the visibility mask.
* *
* @param client * @see getClientVisibilityMask()
* @param fileInfo * @param fileInfo, file to make hidden
* @return * @param visibilityMask
*/ */
public void hideNode(FileInfoImpl fileInfo, int visibilityMask) public void hideNode(FileInfoImpl fileInfo, int visibilityMask)
{ {
@@ -478,16 +526,30 @@ public class HiddenAspect
} }
/** /**
* Checks whether the file should be hidden and applies the hidden and not indexed aspects if so. * Checks whether the file should be hidden based upon whether its name maches a set of filters and applies the hidden
* and not indexed aspects if so.
* <p>
* Can optionally remove the hidden and index control aspects if the name of a node no longer matches the filter.
* *
* @param nodeRef * @param nodeRef
* @param both if true, will check both if the node should not be hidden and remove hidden and index control * @param both if true, will check both if the node should not be hidden and remove hidden and index control
* aspects if they are present, and if the node should be hidden and add hidden and index control * aspects if they are present, and if the node should be hidden and add hidden and index control
* aspects if they are not present. * aspects if they are not present.
* @return * @return HiddenFileInfo
*/ */
public HiddenFileInfo checkHidden(NodeRef nodeRef, boolean both) public HiddenFileInfo checkHidden(NodeRef nodeRef, boolean both)
{ {
if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_HIDDEN))
{
Boolean isHiddenFlag = (Boolean)nodeService.getProperty(nodeRef, ContentModel.PROP_HIDDEN_FLAG);
if(isHiddenFlag != null && isHiddenFlag)
{
logger.debug("node has hidden flag set");
// node has hidden flag - we are not going to change anything.
return null;
}
}
HiddenFileInfo filter = findMatch(nodeRef); HiddenFileInfo filter = findMatch(nodeRef);
if(filter != null) if(filter != null)
{ {
@@ -496,7 +558,7 @@ public class HiddenAspect
if(!hasHiddenAspect(nodeRef)) if(!hasHiddenAspect(nodeRef))
{ {
// the file matches a pattern, apply the hidden and aspect control aspects // the file matches a pattern, apply the hidden and aspect control aspects
addHiddenAspect(nodeRef, visibilityMask); addHiddenAspect(nodeRef, visibilityMask, false);
} }
if(!hasIndexControlAspect(nodeRef)) if(!hasIndexControlAspect(nodeRef))

View File

@@ -546,6 +546,64 @@ public class HiddenAspectTest
interceptor.setEnabled(true); interceptor.setEnabled(true);
} }
} }
@Test
public void testHideNodeExplicit() throws Exception
{
FileFilterMode.setClient(Client.cifs);
try
{
// check temporary file
NodeRef parent = fileFolderService.create(topNodeRef, "New Folder", ContentModel.TYPE_FOLDER).getNodeRef();
NodeRef childA = fileFolderService.create(parent, "fileA", ContentModel.TYPE_CONTENT).getNodeRef();
NodeRef childB = fileFolderService.create(parent, "Thumbs.db", ContentModel.TYPE_CONTENT).getNodeRef();
hiddenAspect.hideNodeExplicit(childA);
// Nodes A and B should be hidden, one by pattern, one explicit
assertTrue("node a should be hidden", nodeService.hasAspect(childA, ContentModel.ASPECT_HIDDEN));
// assertFalse("node b should be hidden", nodeService.hasAspect(childB, ContentModel.ASPECT_HIDDEN));
{
List<FileInfo> children = fileFolderService.list(parent);
assertEquals(2, children.size());
}
hiddenAspect.unhideExplicit(childA);
hiddenAspect.unhideExplicit(childB);
// Node B should still be hidden, A should not
assertFalse(nodeService.hasAspect(childA, ContentModel.ASPECT_HIDDEN));
// assertTrue(nodeService.hasAspect(childB, ContentModel.ASPECT_HIDDEN));
// call checkHidden to maks sure it does not make a mistake
hiddenAspect.checkHidden(childA, true);
// hiddenAspect.checkHidden(childB, true);
{
List<FileInfo> children = fileFolderService.list(parent);
assertEquals(2, children.size());
}
// Node B should still be hidden, A should not
assertFalse(nodeService.hasAspect(childA, ContentModel.ASPECT_HIDDEN));
// assertTrue(nodeService.hasAspect(childB, ContentModel.ASPECT_HIDDEN));
{
List<FileInfo> children = fileFolderService.list(parent);
assertEquals(2, children.size());
}
}
finally
{
FileFilterMode.clearClient();
}
}
private List<NodeRef> getHiddenNodes(final StoreRef storeRef) private List<NodeRef> getHiddenNodes(final StoreRef storeRef)
{ {