diff --git a/source/java/org/alfresco/web/bean/wcm/DeleteSandboxDialog.java b/source/java/org/alfresco/web/bean/wcm/DeleteSandboxDialog.java index 713d9520b8..735e5a24e0 100644 --- a/source/java/org/alfresco/web/bean/wcm/DeleteSandboxDialog.java +++ b/source/java/org/alfresco/web/bean/wcm/DeleteSandboxDialog.java @@ -31,6 +31,7 @@ import javax.faces.context.FacesContext; import org.alfresco.model.WCMAppModel; import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avm.locking.AVMLockingService; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.RegexQNamePattern; @@ -52,8 +53,12 @@ public class DeleteSandboxDialog extends BaseDialogBean protected AVMService avmService; protected AVMBrowseBean avmBrowseBean; + protected AVMLockingService avmLockingService; + // ------------------------------------------------------------------------------ + // Bean property getters and setters + /** * @param avmBrowseBean The avmBrowseBean to set. */ @@ -70,6 +75,14 @@ public class DeleteSandboxDialog extends BaseDialogBean this.avmService = avmService; } + /** + * @param avmLockingService The AVMLockingService to set + */ + public void setAvmLockingService(AVMLockingService avmLockingService) + { + this.avmLockingService = avmLockingService; + } + // ------------------------------------------------------------------------------ // Dialog implementation @@ -118,17 +131,21 @@ public class DeleteSandboxDialog extends BaseDialogBean // accessing a preview layer whose main layer has been torn // out from under it. AVMUtil.removeVServerWebapp(path, true); - + // TODO: Use the .sandbox-id. property to delete all sandboxes, // rather than assume a sandbox always had a single preview // layer attached. - + // purge the user main sandbox store from the system this.avmService.purgeStore(sandbox); - + // remove any locks this user may have + this.avmLockingService.removeStoreLocks(sandbox); + // purge the user preview sandbox store from the system sandbox = AVMUtil.buildUserPreviewStoreName(storeRoot, username); this.avmService.purgeStore(sandbox); + // remove any locks this user may have + this.avmLockingService.removeStoreLocks(sandbox); // remove the association to this web project user meta-data this.nodeService.removeChild(website.getNodeRef(), ref.getChildRef()); diff --git a/source/java/org/alfresco/web/bean/wcm/EditFilePropertiesDialog.java b/source/java/org/alfresco/web/bean/wcm/EditFilePropertiesDialog.java index 888bd9c6bc..187f43193a 100644 --- a/source/java/org/alfresco/web/bean/wcm/EditFilePropertiesDialog.java +++ b/source/java/org/alfresco/web/bean/wcm/EditFilePropertiesDialog.java @@ -26,9 +26,7 @@ package org.alfresco.web.bean.wcm; import java.io.Serializable; import java.text.MessageFormat; -import java.util.ArrayList; import java.util.Iterator; -import java.util.List; import java.util.Map; import javax.faces.context.FacesContext; @@ -36,9 +34,6 @@ import javax.faces.context.FacesContext; import org.alfresco.model.ContentModel; import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.service.cmr.avm.AVMService; -import org.alfresco.service.cmr.avm.locking.AVMLock; -import org.alfresco.service.cmr.avm.locking.AVMLockingException; -import org.alfresco.service.cmr.avm.locking.AVMLockingService; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.model.FileExistsException; @@ -60,7 +55,7 @@ public class EditFilePropertiesDialog extends EditContentPropertiesDialog { protected AVMBrowseBean avmBrowseBean; protected AVMService avmService; - protected AVMLockingService avmLockingService; + // ------------------------------------------------------------------------------ // Bean property getters and setters @@ -81,14 +76,6 @@ public class EditFilePropertiesDialog extends EditContentPropertiesDialog this.avmService = avmService; } - /** - * @param avmLockingService The AVMLockingService to set - */ - public void setAvmLockingService(AVMLockingService avmLockingService) - { - this.avmLockingService = avmLockingService; - } - // ------------------------------------------------------------------------------ // Dialog implementation @@ -106,106 +93,77 @@ public class EditFilePropertiesDialog extends EditContentPropertiesDialog throws Exception { NodeRef nodeRef = this.editableNode.getNodeRef(); - String webProjectId = this.avmBrowseBean.getWebProject().getStoreId(); - String avmPath = AVMNodeConverter.ToAVMVersionPath(nodeRef).getSecond(); - String[] storePath = avmPath.split(":"); - String username = Application.getCurrentUser(context).getUserName(); + Map editedProps = this.editableNode.getProperties(); - try + // handle the name property separately, it is a special case for AVM nodes + String name = (String)editedProps.get(ContentModel.PROP_NAME); + if (name != null) { - if (this.avmLockingService.hasAccess(webProjectId, avmPath, username) == false) - { - throw new AVMLockingException("avmlockservice.locked", new Object[]{avmPath}); - } - else + editedProps.remove(ContentModel.PROP_NAME); + } + + // we need to put all the properties from the editable bag back into + // the format expected by the repository + Map repoProps = this.nodeService.getProperties(nodeRef); + + // but first extract and deal with the special mimetype property for ContentData + String mimetype = (String)editedProps.get(TEMP_PROP_MIMETYPE); + if (mimetype != null) + { + // remove temporary prop from list so it isn't saved with the others + editedProps.remove(TEMP_PROP_MIMETYPE); + ContentData contentData = (ContentData)editedProps.get(ContentModel.PROP_CONTENT); + if (contentData != null) { - if (this.avmLockingService.getLock(webProjectId, avmPath) == null) - { - List owners = new ArrayList(1); - owners.add(username); - AVMLock lock = new AVMLock(webProjectId, storePath[0], storePath[1], AVMLockingService.Type.DISCRETIONARY, owners); - this.avmLockingService.lockPath(lock); - } - } - Map editedProps = this.editableNode.getProperties(); - - // handle the name property separately, it is a special case for AVM nodes - String name = (String)editedProps.get(ContentModel.PROP_NAME); - if (name != null) - { - editedProps.remove(ContentModel.PROP_NAME); - } - - // we need to put all the properties from the editable bag back into - // the format expected by the repository - Map repoProps = this.nodeService.getProperties(nodeRef); - - // but first extract and deal with the special mimetype property for ContentData - String mimetype = (String)editedProps.get(TEMP_PROP_MIMETYPE); - if (mimetype != null) - { - // remove temporary prop from list so it isn't saved with the others - editedProps.remove(TEMP_PROP_MIMETYPE); - ContentData contentData = (ContentData)editedProps.get(ContentModel.PROP_CONTENT); - if (contentData != null) - { - contentData = ContentData.setMimetype(contentData, mimetype); - editedProps.put(ContentModel.PROP_CONTENT.toString(), contentData); - } - } - - // add the "titled" aspect if required, properties will get set below - if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TITLED) == false) - { - this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_TITLED, null); - } - - // add the remaining properties - Iterator iterProps = editedProps.keySet().iterator(); - while (iterProps.hasNext()) - { - String propName = iterProps.next(); - QName qname = QName.createQName(propName); - - // make sure the property is represented correctly - Serializable propValue = (Serializable)editedProps.get(propName); - - // check for empty strings when using number types, set to null in this case - if ((propValue != null) && (propValue instanceof String) && - (propValue.toString().length() == 0)) - { - PropertyDefinition propDef = this.dictionaryService.getProperty(qname); - if (propDef != null) - { - if (propDef.getDataType().getName().equals(DataTypeDefinition.DOUBLE) || - propDef.getDataType().getName().equals(DataTypeDefinition.FLOAT) || - propDef.getDataType().getName().equals(DataTypeDefinition.INT) || - propDef.getDataType().getName().equals(DataTypeDefinition.LONG)) - { - propValue = null; - } - } - } - - repoProps.put(qname, propValue); - } - - // send the properties back to the repository - this.nodeService.setProperties(nodeRef, repoProps); - - // perform the rename last as for an AVM it changes the NodeRef - if (name != null) - { - this.fileFolderService.rename(nodeRef, name); - editedProps.put(ContentModel.PROP_NAME.toString(), name); + contentData = ContentData.setMimetype(contentData, mimetype); + editedProps.put(ContentModel.PROP_CONTENT.toString(), contentData); } } - finally + + // add the "titled" aspect if required, properties will get set below + if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TITLED) == false) { - if (this.avmLockingService.getLock(webProjectId, avmPath) != null) + nodeService.addAspect(nodeRef, ContentModel.ASPECT_TITLED, null); + } + + // add the remaining properties + Iterator iterProps = editedProps.keySet().iterator(); + while (iterProps.hasNext()) + { + String propName = iterProps.next(); + QName qname = QName.createQName(propName); + + // make sure the property is represented correctly + Serializable propValue = (Serializable)editedProps.get(propName); + + // check for empty strings when using number types, set to null in this case + if ((propValue != null) && (propValue instanceof String) && + (propValue.toString().length() == 0)) { - this.avmLockingService.removeLock(webProjectId, avmPath); + PropertyDefinition propDef = this.dictionaryService.getProperty(qname); + if (propDef != null) + { + if (propDef.getDataType().getName().equals(DataTypeDefinition.DOUBLE) || + propDef.getDataType().getName().equals(DataTypeDefinition.FLOAT) || + propDef.getDataType().getName().equals(DataTypeDefinition.INT) || + propDef.getDataType().getName().equals(DataTypeDefinition.LONG)) + { + propValue = null; + } + } } + + repoProps.put(qname, propValue); + } + + // send the properties back to the repository + this.nodeService.setProperties(nodeRef, repoProps); + + // perform the rename last as for an AVM it changes the NodeRef + if (name != null) + { + this.fileFolderService.rename(nodeRef, name); + editedProps.put(ContentModel.PROP_NAME.toString(), name); } return outcome; diff --git a/source/java/org/alfresco/web/bean/wcm/SubmitDialog.java b/source/java/org/alfresco/web/bean/wcm/SubmitDialog.java index eb4803eb8d..a8834b0523 100644 --- a/source/java/org/alfresco/web/bean/wcm/SubmitDialog.java +++ b/source/java/org/alfresco/web/bean/wcm/SubmitDialog.java @@ -50,6 +50,7 @@ import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.workflow.WorkflowModel; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avm.locking.AVMLockingService; import org.alfresco.service.cmr.avmsync.AVMDifference; import org.alfresco.service.cmr.avmsync.AVMSyncService; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; @@ -122,6 +123,7 @@ public class SubmitDialog extends BaseDialogBean protected AVMBrowseBean avmBrowseBean; protected WorkflowService workflowService; protected AVMSyncService avmSyncService; + protected AVMLockingService avmLockingService; protected NameMatcher nameMatcher; /** Current workflow for dialog context */ @@ -153,6 +155,14 @@ public class SubmitDialog extends BaseDialogBean this.avmSyncService = avmSyncService; } + /** + * @param avmLockingService The AVMLockingService to set + */ + public void setAvmLockingService(AVMLockingService avmLockingService) + { + this.avmLockingService = avmLockingService; + } + /** * @param avmBrowseBean The AVM BrowseBean to set */ @@ -373,13 +383,14 @@ public class SubmitDialog extends BaseDialogBean AVMDifference diff = new AVMDifference(-1, srcPath, -1, destPath, AVMDifference.NEWER); diffs.add(diff); + // recursively remove locks from this item + recursivelyRemoveLocks(this.avmBrowseBean.getWebProject().getStoreId(), -1, srcPath); + // If nothing has required notifying the virtualization server // so far, check to see if destPath forces a notification // (e.g.: it might be a path to a jar file within WEB-INF/lib). - if ( (this.virtUpdatePath == null) && - VirtServerUtils.requiresUpdateNotification( destPath ) - ) + VirtServerUtils.requiresUpdateNotification( destPath ) ) { this.virtUpdatePath = destPath; } @@ -396,6 +407,27 @@ public class SubmitDialog extends BaseDialogBean return outcome; } + + /** + * Recursively remove locks from a path. Walking child folders looking for files + * to remove locks from. + */ + private void recursivelyRemoveLocks(String webProject, int version, String path) + { + AVMNodeDescriptor desc = this.avmService.lookup(version, path, true); + if (desc.isFile() || desc.isDeletedFile()) + { + this.avmLockingService.removeLock(webProject, path.substring(path.indexOf(":") + 1)); + } + else + { + Map list = avmService.getDirectoryListing(version, path, true); + for (AVMNodeDescriptor child : list.values()) + { + recursivelyRemoveLocks(webProject, version, child.getPath()); + } + } + } /** * Handle notification to the virtualization server diff --git a/source/java/org/alfresco/web/ui/wcm/component/UIAVMLockIcon.java b/source/java/org/alfresco/web/ui/wcm/component/UIAVMLockIcon.java index 319044f7c7..caefc27025 100644 --- a/source/java/org/alfresco/web/ui/wcm/component/UIAVMLockIcon.java +++ b/source/java/org/alfresco/web/ui/wcm/component/UIAVMLockIcon.java @@ -48,6 +48,8 @@ import org.alfresco.web.ui.repo.component.UILockIcon; */ public class UIAVMLockIcon extends UILockIcon { + public static final String ALFRESCO_FACES_AVMLOCKICON = "org.alfresco.faces.AVMLockIcon"; + // ------------------------------------------------------------------------------ // Component implementation @@ -56,7 +58,7 @@ public class UIAVMLockIcon extends UILockIcon */ public String getFamily() { - return "org.alfresco.faces.AVMLockIcon"; + return ALFRESCO_FACES_AVMLOCKICON; } @@ -77,7 +79,7 @@ public class UIAVMLockIcon extends UILockIcon boolean locked = false; boolean lockedOwner = false; Object val = getValue(); - List lockUser = null; + List lockUsers = null; final String avmPath = (val instanceof NodeRef ? AVMNodeConverter.ToAVMVersionPath((NodeRef)val).getSecond() : (val instanceof String @@ -93,15 +95,14 @@ public class UIAVMLockIcon extends UILockIcon { locked = true; final User currentUser = Application.getCurrentUser(context); - lockUser = lock.getOwners(); - lockedOwner = (webProject.isManager(currentUser) || - lockUser.contains(currentUser.getUserName())); + lockUsers = lock.getOwners(); + lockedOwner = (lockUsers.contains(currentUser.getUserName())); } } } this.encodeBegin(context, locked, lockedOwner, - lockUser == null ? new String[0] : (String[])lockUser.toArray(new String[lockUser.size()])); + lockUsers == null ? new String[0] : (String[])lockUsers.toArray(new String[lockUsers.size()])); } } diff --git a/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java b/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java index 60e5d583de..0f5c68fc0b 100644 --- a/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java +++ b/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java @@ -719,7 +719,8 @@ public class UIUserSandboxes extends SelfRenderingComponent out.write(""); out.write(linkPrefix); out.write(name); - UIAVMLockIcon lockIcon = (UIAVMLockIcon)fc.getApplication().createComponent("org.alfresco.faces.AVMLockIcon"); + UIAVMLockIcon lockIcon = (UIAVMLockIcon)fc.getApplication().createComponent( + UIAVMLockIcon.ALFRESCO_FACES_AVMLOCKICON); lockIcon.setId("lock_" + FacesHelper.makeLegalId(name)); lockIcon.setValue(sourcePath); Utils.encodeRecursive(fc, lockIcon); diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index f9fac1a143..d581bd8dcf 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -3054,6 +3054,10 @@ avmService #{AVMService} + + avmLockingService + #{AVMLockingService} + avmBrowseBean #{AVMBrowseBean} @@ -3196,10 +3200,6 @@ avmService #{AVMService} - - avmLockingService - #{AVMLockingService} - fileFolderService #{FileFolderService} @@ -3397,6 +3397,10 @@ avmSyncService #{AVMSyncService} + + avmLockingService + #{AVMLockingService} + avmBrowseBean #{AVMBrowseBean}