diff --git a/config/alfresco/template-services-context.xml b/config/alfresco/template-services-context.xml index 292d860418..291b12e42a 100644 --- a/config/alfresco/template-services-context.xml +++ b/config/alfresco/template-services-context.xml @@ -44,6 +44,15 @@ + + + avm + + + + + + session diff --git a/source/java/org/alfresco/repo/jscript/AVM.java b/source/java/org/alfresco/repo/jscript/AVM.java index 6a7879bdd7..b74fbf7db5 100644 --- a/source/java/org/alfresco/repo/jscript/AVM.java +++ b/source/java/org/alfresco/repo/jscript/AVM.java @@ -46,9 +46,9 @@ public final class AVM extends BaseScopableScriptImplementation */ public void setServiceRegistry(ServiceRegistry serviceRegistry) { - this.services = serviceRegistry; + this.services = serviceRegistry; } - + /** * Return an AVM Node representing the public store root folder. * @@ -61,16 +61,16 @@ public final class AVM extends BaseScopableScriptImplementation AVMNode rootNode = null; if (store != null && store.length() != 0) { - String rootPath = store + ':' + getWebappsFolderPath(); - AVMNodeDescriptor nodeDesc = this.services.getAVMService().lookup(-1, rootPath); - if (nodeDesc != null) - { - rootNode = new AVMNode(AVMNodeConverter.ToNodeRef(-1, rootPath), this.services, getScope()); - } + String rootPath = store + ':' + getWebappsFolderPath(); + AVMNodeDescriptor nodeDesc = this.services.getAVMService().lookup(-1, rootPath); + if (nodeDesc != null) + { + rootNode = new AVMNode(AVMNodeConverter.ToNodeRef(-1, rootPath), this.services, getScope()); + } } return rootNode; } - + /** * Return an AVM Node for the fully qualified path. * @@ -91,13 +91,13 @@ public final class AVM extends BaseScopableScriptImplementation } return node; } - + public static String getWebappsFolderPath() { - return '/' + JNDIConstants.DIR_DEFAULT_WWW + '/' + - JNDIConstants.DIR_DEFAULT_APPBASE; + return '/' + JNDIConstants.DIR_DEFAULT_WWW + + '/' + JNDIConstants.DIR_DEFAULT_APPBASE; } - + public static String jsGet_webappsFolderPath() { return getWebappsFolderPath(); diff --git a/source/java/org/alfresco/repo/jscript/AVMNode.java b/source/java/org/alfresco/repo/jscript/AVMNode.java index 8cd17a13a0..88115200fa 100644 --- a/source/java/org/alfresco/repo/jscript/AVMNode.java +++ b/source/java/org/alfresco/repo/jscript/AVMNode.java @@ -24,9 +24,12 @@ */ package org.alfresco.repo.jscript; +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.repository.NodeRef; +import org.alfresco.service.namespace.QName; import org.alfresco.util.Pair; import org.alfresco.util.ParameterCheck; import org.mozilla.javascript.Scriptable; @@ -41,6 +44,9 @@ public class AVMNode extends Node { private String path; private int version; + private boolean deleted; + private AVMNodeDescriptor avmRef; + private QName type; /** * Constructor @@ -68,6 +74,13 @@ public class AVMNode extends Node Pair versionPath = AVMNodeConverter.ToAVMVersionPath(nodeRef); this.path = versionPath.getSecond(); this.version = versionPath.getFirst(); + AVMNodeDescriptor descriptor = this.services.getAVMService().lookup(this.version, this.path, true); + if (descriptor == null) + { + throw new IllegalArgumentException("Invalid node specified: " + nodeRef.toString()); + } + this.avmRef = descriptor; + this.deleted = descriptor.isDeleted(); } /** @@ -111,6 +124,60 @@ public class AVMNode extends Node return getVersion(); } + /** + * @return QName type of this node + */ + public QName getType() + { + if (this.type == null) + { + if (this.deleted == false) + { + this.type = this.services.getNodeService().getType(this.nodeRef); + } + else + { + this.type = avmRef.isDeletedDirectory() ? WCMModel.TYPE_AVM_FOLDER : WCMModel.TYPE_AVM_CONTENT; + } + } + + return type; + } + + public String jsGet_type() + { + return getType().toString(); + } + + public boolean isDirectory() + { + return this.avmRef.isDirectory() || this.avmRef.isDeletedDirectory(); + } + + public boolean jsGet_isDirectory() + { + return isDirectory(); + } + + public boolean isFile() + { + return this.avmRef.isFile() || this.avmRef.isDeletedFile(); + } + + public boolean jsGet_isFile() + { + return isFile(); + } + + /** + * @return Helper to return the 'name' property for the node + */ + @Override + public String getName() + { + return this.avmRef.getName(); + } + /** * Copy this Node into a new parent destination. * @@ -226,8 +293,15 @@ public class AVMNode extends Node { super.reset(); this.path = path; - this.nodeRef = AVMNodeConverter.ToNodeRef(version, path); + this.nodeRef = AVMNodeConverter.ToNodeRef(this.version, path); this.id = nodeRef.getId(); + AVMNodeDescriptor descriptor = this.services.getAVMService().lookup(this.version, path, true); + if (descriptor == null) + { + throw new IllegalArgumentException("Invalid node specified: " + nodeRef.toString()); + } + this.avmRef = descriptor; + this.deleted = descriptor.isDeleted(); } @Override diff --git a/source/java/org/alfresco/repo/template/AVM.java b/source/java/org/alfresco/repo/template/AVM.java new file mode 100644 index 0000000000..d6b9d98fca --- /dev/null +++ b/source/java/org/alfresco/repo/template/AVM.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ +package org.alfresco.repo.template; + +import org.alfresco.config.JNDIConstants; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.AVMStoreDescriptor; + +/** + * AVM root object access for a template model. + * + * @author Kevin Roast + */ +public class AVM extends BaseTemplateExtensionImplementation +{ + private ServiceRegistry services; + + /** + * Sets the service registry + * + * @param services the service registry + */ + public void setServiceRegistry(ServiceRegistry services) + { + this.services = services; + } + + /** + * Return an AVM store object for the specified store name + * + * @param store Store name to lookup + * + * @return the AVM store object for the specified store or null if not found + */ + public AVMTemplateStore lookupStore(String store) + { + AVMTemplateStore avmStore = null; + AVMStoreDescriptor descriptor = this.services.getAVMService().getStore(store); + if (descriptor != null) + { + avmStore = new AVMTemplateStore(this.services, getTemplateImageResolver(), descriptor); + } + return avmStore; + } + + /** + * Return the root node for a specified AVM store + * + * @param store Store name to find root node for + * + * @return the AVM store root node for the specified store or null if not found. + */ + public AVMTemplateNode lookupStoreRoot(String store) + { + AVMTemplateNode root = null; + if (store != null && store.length() != 0) + { + AVMTemplateStore avmStore = lookupStore(store); + if (avmStore != null) + { + root = avmStore.getLookupRoot(); + } + } + return root; + } + + /** + * Look a node by the absolute path. Path should include the store reference. + * + * @param path Absolute path to the node, including store reference. + * + * @return the node if found, null otherwise. + */ + public AVMTemplateNode lookupNode(String path) + { + AVMTemplateNode node = null; + if (path != null && path.length() != 0) + { + AVMNodeDescriptor nodeDesc = this.services.getAVMService().lookup(-1, path); + if (nodeDesc != null) + { + node = new AVMTemplateNode(path, -1, this.services, getTemplateImageResolver()); + } + } + return node; + } + + /** + * @return the path to the webapps folder in a standard web store. + */ + public static String getWebappsFolderPath() + { + return '/' + JNDIConstants.DIR_DEFAULT_WWW + + '/' + JNDIConstants.DIR_DEFAULT_APPBASE; + } +} diff --git a/source/java/org/alfresco/repo/template/AVMTemplateNode.java b/source/java/org/alfresco/repo/template/AVMTemplateNode.java new file mode 100644 index 0000000000..df84af7184 --- /dev/null +++ b/source/java/org/alfresco/repo/template/AVMTemplateNode.java @@ -0,0 +1,386 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ +package org.alfresco.repo.template; + +import java.io.Serializable; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.alfresco.model.WCMModel; +import org.alfresco.repo.avm.AVMNodeConverter; +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.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.repository.TemplateImageResolver; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.QNameMap; +import org.alfresco.util.Pair; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.xml.sax.InputSource; + +import freemarker.ext.dom.NodeModel; + +/** + * AVM node class for use by a Template model. + *

+ * The class exposes Node properties, children as dynamically populated maps and lists. + *

+ * Various helper methods are provided to access common and useful node variables such + * as the content url and type information. + *

+ * See {@link http://wiki.alfresco.com/wiki/Template_Guide} + * + * @author Kevin Roast + */ +public class AVMTemplateNode extends BasePermissionsNode +{ + private static Log logger = LogFactory.getLog(AVMTemplateNode.class); + + private final static String NAMESPACE_BEGIN = "" + QName.NAMESPACE_BEGIN; + + /** Cached values */ + private NodeRef nodeRef; + private String name; + private QName type; + private String path; + private int version; + private boolean deleted; + private QNameMap properties; + private boolean propsRetrieved = false; + private AVMTemplateNode parent = null; + private AVMNodeDescriptor avmRef; + + + // ------------------------------------------------------------------------------ + // Construction + + /** + * Constructor + * + * @param nodeRef The NodeRef for the AVM node this wrapper represents + * @param services The ServiceRegistry the Node can use to access services + * @param resolver Image resolver to use to retrieve icons + */ + public AVMTemplateNode(NodeRef nodeRef, ServiceRegistry services, TemplateImageResolver resolver) + { + if (nodeRef == null) + { + throw new IllegalArgumentException("NodeRef must be supplied."); + } + + if (services == null) + { + throw new IllegalArgumentException("The ServiceRegistry must be supplied."); + } + + this.nodeRef = nodeRef; + Pair pair = AVMNodeConverter.ToAVMVersionPath(nodeRef); + this.services = services; + this.imageResolver = resolver; + init(pair.getFirst(), pair.getSecond()); + } + + /** + * Constructor + * + * @param path AVM path to the node + * @param version Version number for avm path + * @param services The ServiceRegistry the Node can use to access services + * @param resolver Image resolver to use to retrieve icons + */ + public AVMTemplateNode(String path, int version, ServiceRegistry services, TemplateImageResolver resolver) + { + if (path == null) + { + throw new IllegalArgumentException("Path must be supplied."); + } + + if (services == null) + { + throw new IllegalArgumentException("The ServiceRegistry must be supplied."); + } + + this.nodeRef = AVMNodeConverter.ToNodeRef(version, path); + this.services = services; + this.imageResolver = resolver; + init(version, path); + } + + private void init(int version, String path) + { + this.version = version; + this.path = path; + this.properties = new QNameMap(this.services.getNamespaceService()); + AVMNodeDescriptor descriptor = this.services.getAVMService().lookup(version, path, true); + if (descriptor == null) + { + throw new IllegalArgumentException("Invalid node specified: " + nodeRef.toString()); + } + this.avmRef = descriptor; + this.deleted = descriptor.isDeleted(); + } + + + // ------------------------------------------------------------------------------ + // AVM Node API + + /** + * @return ID for the AVM path - the path. + */ + public String getId() + { + return this.path; + } + + /** + * @return the path for this AVM node. + */ + public String getPath() + { + return this.path; + } + + /** + * @return the version part of the AVM path. + */ + public int getVersion() + { + return this.version; + } + + /** + * @return file/folder name of the AVM path. + */ + public String getName() + { + if (this.name == null) + { + this.name = AVMNodeConverter.SplitBase(this.path)[1]; + } + return this.name; + } + + /** + * @return AVM path to the parent node + */ + public String getParentPath() + { + return AVMNodeConverter.SplitBase(this.path)[0]; + } + + /** + * @see org.alfresco.repo.template.TemplateNodeRef#getNodeRef() + */ + public NodeRef getNodeRef() + { + return this.nodeRef; + } + + /** + * @see org.alfresco.repo.template.TemplateNodeRef#getType() + */ + public QName getType() + { + if (this.type == null) + { + if (this.deleted == false) + { + this.type = this.services.getNodeService().getType(this.nodeRef); + } + else + { + this.type = this.avmRef.isDeletedDirectory() ? WCMModel.TYPE_AVM_FOLDER : WCMModel.TYPE_AVM_CONTENT; + } + } + + return type; + } + + /** + * @return true if the item is a deleted node, false otherwise + */ + public boolean getIsDeleted() + { + return this.avmRef.isDeleted(); + } + + + // ------------------------------------------------------------------------------ + // TemplateProperties API + + /** + * @return the immediate parent in the node path + */ + public TemplateProperties getParent() + { + if (this.parent == null) + { + this.parent = new AVMTemplateNode(this.getParentPath(), this.version, this.services, this.imageResolver); + } + return this.parent; + } + + /** + * @return true if this Node is a container (i.e. a folder) + */ + @Override + public boolean getIsContainer() + { + return this.avmRef.isDirectory() || this.avmRef.isDeletedDirectory(); + } + + /** + * @return true if this Node is a document (i.e. a file) + */ + @Override + public boolean getIsDocument() + { + return this.avmRef.isFile() || this.avmRef.isDeletedFile(); + } + + /** + * @see org.alfresco.repo.template.TemplateProperties#getChildren() + */ + public List getChildren() + { + if (this.children == null) + { + // use the NodeService so appropriate permission checks are performed + List childRefs = this.services.getNodeService().getChildAssocs(this.nodeRef); + this.children = new ArrayList(childRefs.size()); + for (ChildAssociationRef ref : childRefs) + { + // create our Node representation from the NodeRef + AVMTemplateNode child = new AVMTemplateNode(ref.getChildRef(), this.services, this.imageResolver); + this.children.add(child); + } + } + + return this.children; + } + + /** + * @see org.alfresco.repo.template.TemplateProperties#getProperties() + */ + public Map getProperties() + { + if (!this.propsRetrieved) + { + if (!this.deleted) + { + Map props = this.services.getAVMService().getNodeProperties(this.version, this.path); + for (QName qname: props.keySet()) + { + Serializable propValue = props.get(qname).getValue(DataTypeDefinition.ANY); + if (propValue instanceof NodeRef) + { + // NodeRef object properties are converted to new TemplateNode objects + // so they can be used as objects within a template + NodeRef nodeRef = (NodeRef)propValue; + if (StoreRef.PROTOCOL_AVM.equals(nodeRef.getStoreRef().getProtocol())) + { + propValue = new AVMTemplateNode(nodeRef, this.services, this.imageResolver); + } + else + { + propValue = new TemplateNode(nodeRef, this.services, this.imageResolver); + } + } + else if (propValue instanceof ContentData) + { + // ContentData object properties are converted to TemplateContentData objects + // so the content and other properties of those objects can be accessed + propValue = new TemplateContentData((ContentData)propValue, qname); + } + this.properties.put(qname.toString(), propValue); + } + } + + // AVM node properties not available in usual getProperties() call + this.properties.put("name", this.avmRef.getName()); + this.properties.put("created", new Date(this.avmRef.getCreateDate())); + this.properties.put("modified", new Date(this.avmRef.getModDate())); + this.properties.put("creator", this.avmRef.getCreator()); + this.properties.put("modifier", this.avmRef.getLastModifier()); + + this.propsRetrieved = true; + } + + return this.properties; + } + + + // ------------------------------------------------------------------------------ + // Audit API + + /** + * @return a list of AuditInfo objects describing the Audit Trail for this node instance + */ + public List getAuditTrail() + { + return this.services.getAuditService().getAuditTrail(this.nodeRef); + } + + + // ------------------------------------------------------------------------------ + // Node Helper API + + /** + * @return FreeMarker NodeModel for the XML content of this node, or null if no parsable XML found + */ + public NodeModel getXmlNodeModel() + { + try + { + return NodeModel.parse(new InputSource(new StringReader(getContent()))); + } + catch (Throwable err) + { + if (logger.isDebugEnabled()) + logger.debug(err.getMessage(), err); + + return null; + } + } + + /** + * @return Display path to this node - the path built of 'cm:name' attribute values. + */ + @Override + public String getDisplayPath() + { + return this.path; + } +} diff --git a/source/java/org/alfresco/repo/template/AVMTemplateStore.java b/source/java/org/alfresco/repo/template/AVMTemplateStore.java new file mode 100644 index 0000000000..783a6e0a75 --- /dev/null +++ b/source/java/org/alfresco/repo/template/AVMTemplateStore.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ +package org.alfresco.repo.template; + +import java.util.Date; + +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.AVMStoreDescriptor; +import org.alfresco.service.cmr.repository.TemplateImageResolver; + +/** + * Representation of an AVM Store for the template model. Accessed via the AVM helper object + * and is responsible for returning AVMTemplateNode objects via various mechanisms. + * + * @author Kevin Roast + */ +public class AVMTemplateStore +{ + private ServiceRegistry services; + private AVMStoreDescriptor descriptor; + private TemplateImageResolver resolver; + + /** + * Constructor + * + * @param services + * @param resolver + * @param store Store descriptor this object represents + */ + public AVMTemplateStore(ServiceRegistry services, TemplateImageResolver resolver, AVMStoreDescriptor store) + { + this.descriptor = store; + this.services = services; + this.resolver = resolver; + } + + /** + * @return Store name + */ + public String getName() + { + return this.descriptor.getName(); + } + + /** + * @return Store name + */ + public String getId() + { + return this.descriptor.getName(); + } + + /** + * @return User who created the store + */ + public String getCreator() + { + return this.descriptor.getCreator(); + } + + /** + * @return Creation date of the store + */ + public Date getCreatedDate() + { + return new Date(this.descriptor.getCreateDate()); + } + + /** + * @return the root node of all webapps in the store + */ + public AVMTemplateNode getLookupRoot() + { + AVMTemplateNode rootNode = null; + String rootPath = this.descriptor.getName() + ':' + AVM.getWebappsFolderPath(); + AVMNodeDescriptor nodeDesc = this.services.getAVMService().lookup(-1, rootPath); + if (nodeDesc != null) + { + rootNode = new AVMTemplateNode(rootPath, -1, this.services, this.resolver); + } + return rootNode; + } + + /** + * Lookup a node in the store, the path is assumed to be related to the webapps folder root. + * Therefore a valid path would be "/ROOT/WEB-INF/lib/web.xml". + * + * @param path Relative to the webapps folder root path for this store. + * + * @return node if found, null otherwise. + */ + public AVMTemplateNode lookupNode(String path) + { + AVMTemplateNode node = null; + if (path != null && path.length() != 0) + { + if (path.charAt(0) != '/') + { + path = '/' + path; + } + path = this.descriptor.getName() + ':' + AVM.getWebappsFolderPath() + path; + AVMNodeDescriptor nodeDesc = this.services.getAVMService().lookup(-1, path); + if (nodeDesc != null) + { + node = new AVMTemplateNode(path, -1, this.services, this.resolver); + } + } + return node; + } +} diff --git a/source/java/org/alfresco/repo/template/BaseContentNode.java b/source/java/org/alfresco/repo/template/BaseContentNode.java index b85b28444b..d06bf6a12d 100644 --- a/source/java/org/alfresco/repo/template/BaseContentNode.java +++ b/source/java/org/alfresco/repo/template/BaseContentNode.java @@ -28,16 +28,22 @@ import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.TemplateException; +import org.alfresco.service.cmr.repository.TemplateImageResolver; import org.alfresco.service.namespace.QName; import org.springframework.util.StringUtils; @@ -52,7 +58,15 @@ public abstract class BaseContentNode implements TemplateContent protected final static String CONTENT_PROP_URL = "/download/direct/{0}/{1}/{2}/{3}?property={4}"; protected final static String FOLDER_BROWSE_URL = "/navigate/browse/{0}/{1}/{2}"; + protected final static String NAMESPACE_BEGIN = "" + QName.NAMESPACE_BEGIN; + + /** The children of this node */ + protected List children = null; + protected ServiceRegistry services = null; + protected TemplateImageResolver imageResolver = null; + private Set aspects = null; + private String displayPath = null; private Boolean isDocument = null; private Boolean isContainer = null; @@ -103,6 +117,166 @@ public abstract class BaseContentNode implements TemplateContent } + // ------------------------------------------------------------------------------ + // Content display API + + /** + * @return QName path to this node. This can be used for Lucene PATH: style queries + */ + public String getQnamePath() + { + return this.services.getNodeService().getPath(getNodeRef()).toPrefixString(this.services.getNamespaceService()); + } + + /** + * @return the small icon image for this node + */ + public String getIcon16() + { + if (this.imageResolver != null) + { + if (getIsDocument()) + { + return this.imageResolver.resolveImagePathForName(getName(), true); + } + else + { + String icon = (String)getProperties().get("app:icon"); + if (icon != null) + { + return "/images/icons/" + icon + "-16.gif"; + } + else + { + return "/images/icons/space_small.gif"; + } + } + } + else + { + return "/images/filetypes/_default.gif"; + } + } + + /** + * @return the large icon image for this node + */ + public String getIcon32() + { + if (this.imageResolver != null) + { + if (getIsDocument()) + { + return this.imageResolver.resolveImagePathForName(getName(), false); + } + else + { + String icon = (String)getProperties().get("app:icon"); + if (icon != null) + { + return "/images/icons/" + icon + ".gif"; + } + else + { + return "/images/icons/space-icon-default.gif"; + } + } + } + else + { + return "/images/filetypes32/_default.gif"; + } + } + + /** + * @return Display path to this node - the path built of 'cm:name' attribute values. + */ + public String getDisplayPath() + { + if (displayPath == null) + { + try + { + displayPath = this.services.getNodeService().getPath(getNodeRef()).toDisplayPath(this.services.getNodeService()); + } + catch (AccessDeniedException err) + { + displayPath = ""; + } + } + + return displayPath; + } + + + // ------------------------------------------------------------------------------ + // TemplateProperties contract impl + + /** + * @return The children of this Node as objects that support the TemplateProperties contract. + */ + public List getChildren() + { + if (this.children == null) + { + List childRefs = this.services.getNodeService().getChildAssocs(getNodeRef()); + this.children = new ArrayList(childRefs.size()); + for (ChildAssociationRef ref : childRefs) + { + // create our Node representation from the NodeRef + TemplateNode child = new TemplateNode(ref.getChildRef(), this.services, this.imageResolver); + this.children.add(child); + } + } + + return this.children; + } + + /** + * @return The list of aspects applied to this node + */ + public Set getAspects() + { + if (this.aspects == null) + { + this.aspects = this.services.getNodeService().getAspects(getNodeRef()); + } + + return this.aspects; + } + + /** + * @param aspect The aspect name to test for + * + * @return true if the node has the aspect false otherwise + */ + public boolean hasAspect(String aspect) + { + if (this.aspects == null) + { + this.aspects = this.services.getNodeService().getAspects(getNodeRef()); + } + + if (aspect.startsWith(NAMESPACE_BEGIN)) + { + return this.aspects.contains((QName.createQName(aspect))); + } + else + { + boolean found = false; + for (QName qname : this.aspects) + { + if (qname.toPrefixString(this.services.getNamespaceService()).equals(aspect)) + { + found = true; + break; + } + } + return found; + } + } + + // ------------------------------------------------------------------------------ // Content API diff --git a/source/java/org/alfresco/repo/template/TemplateNode.java b/source/java/org/alfresco/repo/template/TemplateNode.java index fe86b7b956..989ec04fa4 100644 --- a/source/java/org/alfresco/repo/template/TemplateNode.java +++ b/source/java/org/alfresco/repo/template/TemplateNode.java @@ -30,10 +30,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Set; import org.alfresco.model.ContentModel; -import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.audit.AuditInfo; import org.alfresco.service.cmr.dictionary.DictionaryService; @@ -74,11 +72,6 @@ public class TemplateNode extends BasePermissionsNode private static Log logger = LogFactory.getLog(TemplateNode.class); - protected final static String NAMESPACE_BEGIN = "" + QName.NAMESPACE_BEGIN; - - /** The children of this node */ - private List children = null; - /** The target associations from this node */ private Map> targetAssocs = null; @@ -94,11 +87,8 @@ public class TemplateNode extends BasePermissionsNode private QName type; private String path; private String id; - private Set aspects = null; private QNameMap properties; private boolean propsRetrieved = false; - private String displayPath = null; - protected TemplateImageResolver imageResolver = null; private TemplateNode parent = null; private ChildAssociationRef primaryParentAssoc = null; private Boolean isCategory = null; @@ -199,26 +189,6 @@ public class TemplateNode extends BasePermissionsNode // ------------------------------------------------------------------------------ // TemplateProperties contract implementation - /** - * @return The children of this Node as objects that support the TemplateProperties contract. - */ - public List getChildren() - { - if (this.children == null) - { - List childRefs = this.services.getNodeService().getChildAssocs(this.nodeRef); - this.children = new ArrayList(childRefs.size()); - for (ChildAssociationRef ref : childRefs) - { - // create our Node representation from the NodeRef - TemplateNode child = new TemplateNode(ref.getChildRef(), this.services, this.imageResolver); - this.children.add(child); - } - } - - return this.children; - } - /** * @return All the properties known about this node. */ @@ -252,50 +222,6 @@ public class TemplateNode extends BasePermissionsNode return this.properties; } - /** - * @return The list of aspects applied to this node - */ - public Set getAspects() - { - if (this.aspects == null) - { - this.aspects = this.services.getNodeService().getAspects(this.nodeRef); - } - - return this.aspects; - } - - /** - * @param aspect The aspect name to test for - * - * @return true if the node has the aspect false otherwise - */ - public boolean hasAspect(String aspect) - { - if (this.aspects == null) - { - this.aspects = this.services.getNodeService().getAspects(this.nodeRef); - } - - if (aspect.startsWith(NAMESPACE_BEGIN)) - { - return aspects.contains((QName.createQName(aspect))); - } - else - { - boolean found = false; - for (QName qname : this.aspects) - { - if (qname.toPrefixString(this.services.getNamespaceService()).equals(aspect)) - { - found = true; - break; - } - } - return found; - } - } - // ------------------------------------------------------------------------------ // Repository Node API @@ -400,9 +326,9 @@ public class TemplateNode extends BasePermissionsNode } /** - * @return the parent node + * @return the primary parent node */ - public TemplateNode getParent() + public TemplateProperties getParent() { if (parent == null) { @@ -479,94 +405,6 @@ public class TemplateNode extends BasePermissionsNode } } - /** - * @return Display path to this node - the path built of 'cm:name' attribute values. - */ - public String getDisplayPath() - { - if (displayPath == null) - { - try - { - displayPath = this.services.getNodeService().getPath(this.nodeRef).toDisplayPath(this.services.getNodeService()); - } - catch (AccessDeniedException err) - { - displayPath = ""; - } - } - - return displayPath; - } - - /** - * @return QName path to this node. This can be used for Lucene PATH: style queries - */ - public String getQnamePath() - { - return this.services.getNodeService().getPath(this.nodeRef).toPrefixString(this.services.getNamespaceService()); - } - - /** - * @return the small icon image for this node - */ - public String getIcon16() - { - if (this.imageResolver != null) - { - if (getIsDocument()) - { - return this.imageResolver.resolveImagePathForName(getName(), true); - } - else - { - String icon = (String)getProperties().get("app:icon"); - if (icon != null) - { - return "/images/icons/" + icon + "-16.gif"; - } - else - { - return "/images/icons/space_small.gif"; - } - } - } - else - { - return "/images/filetypes/_default.gif"; - } - } - - /** - * @return the large icon image for this node - */ - public String getIcon32() - { - if (this.imageResolver != null) - { - if (getIsDocument()) - { - return this.imageResolver.resolveImagePathForName(getName(), false); - } - else - { - String icon = (String)getProperties().get("app:icon"); - if (icon != null) - { - return "/images/icons/" + icon + ".gif"; - } - else - { - return "/images/icons/space-icon-default.gif"; - } - } - } - else - { - return "/images/filetypes32/_default.gif"; - } - } - // ------------------------------------------------------------------------------ // Search API diff --git a/source/java/org/alfresco/repo/template/TemplateProperties.java b/source/java/org/alfresco/repo/template/TemplateProperties.java index deb29b4f6a..724068264f 100644 --- a/source/java/org/alfresco/repo/template/TemplateProperties.java +++ b/source/java/org/alfresco/repo/template/TemplateProperties.java @@ -59,4 +59,9 @@ public interface TemplateProperties extends TemplateNodeRef * @return The children of this Node as TemplateNode wrappers */ public List getChildren(); + + /** + * @return the primary parent of this node + */ + public TemplateProperties getParent(); } diff --git a/source/java/org/alfresco/repo/template/VersionHistoryNode.java b/source/java/org/alfresco/repo/template/VersionHistoryNode.java index 24e871baa9..76da7e0b41 100644 --- a/source/java/org/alfresco/repo/template/VersionHistoryNode.java +++ b/source/java/org/alfresco/repo/template/VersionHistoryNode.java @@ -255,6 +255,14 @@ public class VersionHistoryNode extends BaseContentNode return null; } + /** + * @see org.alfresco.repo.template.TemplateProperties#getParent() + */ + public TemplateProperties getParent() + { + return null; + } + // ------------------------------------------------------------------------------ // Content API