diff --git a/source/java/org/alfresco/repo/jscript/AVMNode.java b/source/java/org/alfresco/repo/jscript/AVMNode.java index d65a0c9d6e..d91761da92 100644 --- a/source/java/org/alfresco/repo/jscript/AVMNode.java +++ b/source/java/org/alfresco/repo/jscript/AVMNode.java @@ -24,10 +24,15 @@ */ package org.alfresco.repo.jscript; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + import org.alfresco.model.WCMModel; import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.locking.AVMLock; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; import org.alfresco.util.Pair; @@ -189,6 +194,60 @@ public class AVMNode extends ScriptNode { return this.avmRef.getName(); } + + /** + * @return true if the node is currently locked + */ + public boolean isLocked() + { + AVMLock lock = this.services.getAVMLockingService().getLock( + getWebProject(), path.substring(path.indexOf("/"))); + return (lock != null); + } + + public boolean jsGet_isLocked() + { + return isLocked(); + } + + /** + * @return true if this node is locked and the current user is the lock owner + */ + public boolean isLockOwner() + { + boolean lockOwner = false; + + AVMLock lock = this.services.getAVMLockingService().getLock( + getWebProject(), path.substring(path.indexOf("/"))); + if (lock != null) + { + List lockUsers = lock.getOwners(); + lockOwner = (lockUsers.contains(this.services.getAuthenticationService().getCurrentUserName())); + } + + return lockOwner; + } + + public boolean jsGet_isLockOwner() + { + return isLockOwner(); + } + + /** + * @return true if this user can perform operations on the node when locked. + * This is true if the item is either unlocked, or locked and the current user is the lock owner, + * or locked and the current user has Content Manager role in the associated web project. + */ + public boolean hasLockAccess() + { + return this.services.getAVMLockingService().hasAccess( + getWebProject(), path, this.services.getAuthenticationService().getCurrentUserName()); + } + + public boolean jsGet_hasLockAccess() + { + return hasLockAccess(); + } /** * Copy this Node into a new parent destination. @@ -298,6 +357,20 @@ public class AVMNode extends ScriptNode return success; } + /** + * @return The list of aspects applied to this node + */ + @Override + public Set getAspects() + { + if (this.aspects == null) + { + this.aspects = this.services.getAVMService().getAspects(this.version, this.path); + } + + return this.aspects; + } + /** * Reset the Node cached state */ @@ -315,6 +388,20 @@ public class AVMNode extends ScriptNode this.avmRef = descriptor; this.deleted = descriptor.isDeleted(); } + + /** + * @return the WebProject identifier for the current path + */ + private String getWebProject() + { + String webProject = this.path.substring(0, this.path.indexOf(':')); + int index = webProject.indexOf("--"); + if (index != -1) + { + webProject = webProject.substring(0, index); + } + return webProject; + } @Override public String toString() diff --git a/source/java/org/alfresco/repo/jscript/ScriptNode.java b/source/java/org/alfresco/repo/jscript/ScriptNode.java index 89e0deefa1..3971d32c53 100644 --- a/source/java/org/alfresco/repo/jscript/ScriptNode.java +++ b/source/java/org/alfresco/repo/jscript/ScriptNode.java @@ -116,7 +116,7 @@ public class ScriptNode implements Serializable, Scopeable protected String id; /** The aspects applied to this node */ - private Set aspects = null; + protected Set aspects = null; /** The target associations for this node */ private ScriptableQNameMap assocs = null; diff --git a/source/java/org/alfresco/repo/template/AVMTemplateNode.java b/source/java/org/alfresco/repo/template/AVMTemplateNode.java index c8e94176ce..4268fb6428 100644 --- a/source/java/org/alfresco/repo/template/AVMTemplateNode.java +++ b/source/java/org/alfresco/repo/template/AVMTemplateNode.java @@ -39,6 +39,7 @@ import org.alfresco.repo.domain.PropertyValue; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.audit.AuditInfo; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.locking.AVMLock; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentData; @@ -267,6 +268,45 @@ public class AVMTemplateNode extends BasePermissionsNode { return this.avmRef.isDeleted(); } + + /** + * @return true if the node is currently locked + */ + public boolean getIsLocked() + { + AVMLock lock = this.services.getAVMLockingService().getLock( + getWebProject(), path.substring(path.indexOf("/"))); + return (lock != null); + } + + /** + * @return true if this node is locked and the current user is the lock owner + */ + public boolean getIsLockOwner() + { + boolean lockOwner = false; + + AVMLock lock = this.services.getAVMLockingService().getLock( + getWebProject(), path.substring(path.indexOf("/"))); + if (lock != null) + { + List lockUsers = lock.getOwners(); + lockOwner = (lockUsers.contains(this.services.getAuthenticationService().getCurrentUserName())); + } + + return lockOwner; + } + + /** + * @return true if this user can perform operations on the node when locked. + * This is true if the item is either unlocked, or locked and the current user is the lock owner, + * or locked and the current user has Content Manager role in the associated web project. + */ + public boolean getHasLockAccess() + { + return this.services.getAVMLockingService().hasAccess( + getWebProject(), path, this.services.getAuthenticationService().getCurrentUserName()); + } // ------------------------------------------------------------------------------ @@ -381,8 +421,7 @@ public class AVMTemplateNode extends BasePermissionsNode { if (this.aspects == null) { - this.aspects = new HashSet(); - this.aspects.addAll(this.services.getAVMService().getAspects(this.version, this.path)); + this.aspects = this.services.getAVMService().getAspects(this.version, this.path); } return this.aspects; @@ -430,4 +469,22 @@ public class AVMTemplateNode extends BasePermissionsNode { return this.path; } + + + // ------------------------------------------------------------------------------ + // Private helpers + + /** + * @return the WebProject identifier for the current path + */ + private String getWebProject() + { + String webProject = this.path.substring(0, this.path.indexOf(':')); + int index = webProject.indexOf("--"); + if (index != -1) + { + webProject = webProject.substring(0, index); + } + return webProject; + } } diff --git a/source/java/org/alfresco/repo/template/FreeMarkerProcessor.java b/source/java/org/alfresco/repo/template/FreeMarkerProcessor.java index fd8fb36bcf..49b65c7472 100644 --- a/source/java/org/alfresco/repo/template/FreeMarkerProcessor.java +++ b/source/java/org/alfresco/repo/template/FreeMarkerProcessor.java @@ -74,6 +74,9 @@ public class FreeMarkerProcessor extends BaseProcessor implements TemplateProces /** Pseudo path to String based template */ private static final String PATH = "string://fixed"; + /** FreeMarker configuration object */ + private Configuration config; + /** Template encoding */ private String defaultEncoding; @@ -92,31 +95,34 @@ public class FreeMarkerProcessor extends BaseProcessor implements TemplateProces * * @return FreeMarker configuration */ - protected Configuration getConfig() + protected synchronized Configuration getConfig() { - Configuration config = new Configuration(); - - // setup template cache - config.setCacheStorage(new MruCacheStorage(2, 0)); - - // use our custom loader to find templates on the ClassPath - config.setTemplateLoader(new ClassPathRepoTemplateLoader( - this.services.getNodeService(), this.services.getContentService(), defaultEncoding)); - - // use our custom object wrapper that can deal with QNameMap objects directly - config.setObjectWrapper(new QNameAwareObjectWrapper()); - - // rethrow any exception so we can deal with them - config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); - - // localized template lookups off by default - as they create strange noderef lookups - // such as workspace://SpacesStore/01234_en_GB - causes problems for ns.exists() on DB2 - config.setLocalizedLookup(false); - - // set default template encoding - if (defaultEncoding != null) + if (config == null) { - config.setDefaultEncoding(defaultEncoding); + config = new Configuration(); + + // setup template cache + config.setCacheStorage(new MruCacheStorage(32, 32)); + + // use our custom loader to find templates on the ClassPath + config.setTemplateLoader(new ClassPathRepoTemplateLoader( + this.services.getNodeService(), this.services.getContentService(), defaultEncoding)); + + // use our custom object wrapper that can deal with QNameMap objects directly + config.setObjectWrapper(new QNameAwareObjectWrapper()); + + // rethrow any exception so we can deal with them + config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + + // localized template lookups off by default - as they create strange noderef lookups + // such as workspace://SpacesStore/01234_en_GB - causes problems for ns.exists() on DB2 + config.setLocalizedLookup(false); + + // set default template encoding + if (defaultEncoding != null) + { + config.setDefaultEncoding(defaultEncoding); + } } return config;