From f880d471282f093b9be2c9b02b1c009cb9e009ea Mon Sep 17 00:00:00 2001 From: Mark Rogers Date: Mon, 21 Jan 2013 15:28:41 +0000 Subject: [PATCH] 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 --- config/alfresco/model/systemModel.xml | 5 + .../filesys/repo/ContentDiskDriver2.java | 27 ++++-- .../repo/model/filefolder/HiddenAspect.java | 92 ++++++++++++++++--- .../model/filefolder/HiddenAspectTest.java | 58 ++++++++++++ 4 files changed, 157 insertions(+), 25 deletions(-) diff --git a/config/alfresco/model/systemModel.xml b/config/alfresco/model/systemModel.xml index 88e9416111..1b81f3c11a 100644 --- a/config/alfresco/model/systemModel.xml +++ b/config/alfresco/model/systemModel.xml @@ -191,6 +191,11 @@ false 0 + + + d:boolean + false + diff --git a/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java b/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java index 510e98f032..0cc303df49 100644 --- a/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java +++ b/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java @@ -76,6 +76,7 @@ import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.encoding.ContentCharsetFinder; 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.RestoreNodeReport; import org.alfresco.repo.policy.BehaviourFilter; @@ -146,6 +147,7 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD private NodeMonitorFactory m_nodeMonitorFactory; private ContentComparator contentComparator; private NodeArchiveService nodeArchiveService; + private HiddenAspect hiddenAspect; // TODO Should not be here - should be specific to a context. private boolean isLockedFilesAsOffline; @@ -172,6 +174,7 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD PropertyCheck.mandatory(this, "ioControlHandler", ioControlHandler); PropertyCheck.mandatory(this, "contentComparator", getContentComparator()); PropertyCheck.mandatory(this, "nodeArchiveService", nodeArchiveService); + PropertyCheck.mandatory(this, "hiddenAspect", hiddenAspect); } /** @@ -387,6 +390,14 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD this.policyBehaviourFilter = policyFilter; } + /** + * @param hiddenAspect + */ + public void setHiddenAspect(HiddenAspect hiddenAspect) + { + this.hiddenAspect = hiddenAspect; + } + // Configuration key names private static final String KEY_STORE = "store"; @@ -1583,27 +1594,23 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD if(info.isHidden()) { // yes is hidden - if(!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_HIDDEN)) + if ( logger.isDebugEnabled()) { - if ( logger.isDebugEnabled()) - { - 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); + logger.debug("Set hidden aspect" + name); } + hiddenAspect.hideNodeExplicit(nodeRef); } else { - // not hidden is hidden + // not hidden if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_HIDDEN)) { 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 diff --git a/source/java/org/alfresco/repo/model/filefolder/HiddenAspect.java b/source/java/org/alfresco/repo/model/filefolder/HiddenAspect.java index 53887b395c..1ec22b0f0d 100644 --- a/source/java/org/alfresco/repo/model/filefolder/HiddenAspect.java +++ b/source/java/org/alfresco/repo/model/filefolder/HiddenAspect.java @@ -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 props = new HashMap(1); props.put(ContentModel.PROP_VISIBILITY_MASK, visibilityMask); + props.put(ContentModel.PROP_HIDDEN_FLAG, explicit); nodeService.addAspect(nodeRef, ContentModel.ASPECT_HIDDEN, props); if (logger.isDebugEnabled()) @@ -257,7 +290,7 @@ public class HiddenAspect NodeRef childNodeRef = file.getNodeRef(); if(filter.cascadeHiddenAspect() && !hasHiddenAspect(childNodeRef)) { - addHiddenAspect(childNodeRef, visibilityMask); + addHiddenAspect(childNodeRef, visibilityMask, false); } if(filter.cascadeIndexControlAspect() && !hasIndexControlAspect(childNodeRef)) @@ -344,6 +377,13 @@ public class HiddenAspect return ret; } + /** + * getClientVisibilityMap + * + * @param client + * @param visibility + * @return the client visibilityMask + */ public int getClientVisibilityMask(Client client, Visibility visibility) { return visibility.getMask() << getClientIndex(client)*2; @@ -389,10 +429,16 @@ public class HiddenAspect */ public void hideNode(NodeRef nodeRef) { - addHiddenAspect(nodeRef, 0); + addHiddenAspect(nodeRef, 0, false); 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) { 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 * according to the visibility mask. * - * @param client - * @param fileInfo - * @return + * @param nodeRef the node to hide + * @param clientVisibilityMask */ public void hideNode(NodeRef nodeRef, int clientVisibilityMask) { - addHiddenAspect(nodeRef, clientVisibilityMask); + addHiddenAspect(nodeRef, clientVisibilityMask, true); 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. + *

+ * Can optionally remove the hidden and index control aspects if the name of a node no longer matches the filter. * * @param fileInfo * @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 * according to the visibility mask. * - * @param client - * @param fileInfo - * @return + * @see getClientVisibilityMask() + * @param fileInfo, file to make hidden + * @param 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. + *

+ * Can optionally remove the hidden and index control aspects if the name of a node no longer matches the filter. * * @param nodeRef * @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 not present. - * @return + * @return HiddenFileInfo */ 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); if(filter != null) { @@ -496,7 +558,7 @@ public class HiddenAspect if(!hasHiddenAspect(nodeRef)) { // the file matches a pattern, apply the hidden and aspect control aspects - addHiddenAspect(nodeRef, visibilityMask); + addHiddenAspect(nodeRef, visibilityMask, false); } if(!hasIndexControlAspect(nodeRef)) diff --git a/source/java/org/alfresco/repo/model/filefolder/HiddenAspectTest.java b/source/java/org/alfresco/repo/model/filefolder/HiddenAspectTest.java index bf7a1e0205..bfeae3a550 100644 --- a/source/java/org/alfresco/repo/model/filefolder/HiddenAspectTest.java +++ b/source/java/org/alfresco/repo/model/filefolder/HiddenAspectTest.java @@ -546,6 +546,64 @@ public class HiddenAspectTest 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 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 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 children = fileFolderService.list(parent); + assertEquals(2, children.size()); + } + + } + finally + { + FileFilterMode.clearClient(); + } + + } + + private List getHiddenNodes(final StoreRef storeRef) {