diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml index 49a9f63801..fd930a1105 100644 --- a/config/alfresco/bootstrap-context.xml +++ b/config/alfresco/bootstrap-context.xml @@ -678,6 +678,7 @@ ${spaces.store} /${spaces.company_home.childname} + /${spaces.company_home.childname}/${spaces.shared.childname} diff --git a/config/alfresco/node-locator-context.xml b/config/alfresco/node-locator-context.xml index 419c950e48..31258d6042 100644 --- a/config/alfresco/node-locator-context.xml +++ b/config/alfresco/node-locator-context.xml @@ -16,7 +16,7 @@ - + @@ -26,6 +26,11 @@ + + + + + diff --git a/source/java/org/alfresco/repo/jscript/ScriptUtils.java b/source/java/org/alfresco/repo/jscript/ScriptUtils.java index 79269d09e6..586f1c5142 100644 --- a/source/java/org/alfresco/repo/jscript/ScriptUtils.java +++ b/source/java/org/alfresco/repo/jscript/ScriptUtils.java @@ -18,16 +18,26 @@ */ package org.alfresco.repo.jscript; +import java.io.Serializable; import java.util.Date; +import java.util.HashMap; import java.util.Locale; import java.util.Map; +import org.alfresco.repo.nodelocator.CompanyHomeNodeLocator; +import org.alfresco.repo.nodelocator.NodeLocatorService; +import org.alfresco.repo.nodelocator.SharedHomeNodeLocator; +import org.alfresco.repo.nodelocator.SitesHomeNodeLocator; +import org.alfresco.repo.nodelocator.UserHomeNodeLocator; +import org.alfresco.repo.nodelocator.XPathNodeLocator; import org.alfresco.repo.security.permissions.noop.PermissionServiceNOOPImpl; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.module.ModuleDetails; import org.alfresco.service.cmr.module.ModuleService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.util.ScriptPagingDetails; @@ -109,6 +119,71 @@ public class ScriptUtils extends BaseScopableProcessorExtension return (ScriptNode)new ValueConverter().convertValueForScript(this.services, getScope(), null, nodeRef); } + /** + * Use the Node Locator Service to find the given root node from a number of possible locator types. + * This method is responsible for determining the locator type and then calling the Service as the + * Service does not know how to guess which locator to use. + *

+ * This service supports 'virtual' nodes including the following: + *

+ * alfresco://company/home The Company Home root node + * alfresco://user/home The User Home node under Company Home + * alfresco://company/shared The Shared node under Company Home + * alfresco://sites/home The Sites home node under Company Home + * workspace://.../... Any standard NodeRef + * /app:company_home/cm:... XPath QName style node reference + * + * @param rootNode + * + * @return ScriptNode representing the node or null if not found + */ + public ScriptNode resolveNodeReference(final String reference) + { + if (reference == null) + { + throw new IllegalArgumentException("Node 'reference' argument is mandatory."); + } + + final NodeLocatorService locatorService = this.services.getNodeLocatorService(); + + NodeRef nodeRef = null; + + switch (reference) + { + case "alfresco://company/home": + nodeRef = locatorService.getNode(CompanyHomeNodeLocator.NAME, null, null); + break; + case "alfresco://user/home": + nodeRef = locatorService.getNode(UserHomeNodeLocator.NAME, null, null); + break; + case "alfresco://company/shared": + nodeRef = locatorService.getNode(SharedHomeNodeLocator.NAME, null, null); + break; + case "alfresco://sites/home": + nodeRef = locatorService.getNode(SitesHomeNodeLocator.NAME, null, null); + break; + default: + if (reference.indexOf("://") > 0) + { + NodeRef ref = new NodeRef(reference); + if (this.services.getNodeService().exists(ref) && + this.services.getPermissionService().hasPermission(ref, PermissionService.READ) == AccessStatus.ALLOWED) + { + nodeRef = ref; + } + } + else if (reference.startsWith("/")) + { + final Map params = new HashMap<>(1, 1.0f); + params.put(XPathNodeLocator.QUERY_KEY, reference); + nodeRef = locatorService.getNode(XPathNodeLocator.NAME, null, params); + } + break; + } + + return nodeRef != null ? (ScriptNode)new ValueConverter().convertValueForScript(this.services, getScope(), null, nodeRef) : null; + } + /** * Gets a boolean value from a string * diff --git a/source/java/org/alfresco/repo/model/Repository.java b/source/java/org/alfresco/repo/model/Repository.java index fa8ea2f564..016218fcb4 100644 --- a/source/java/org/alfresco/repo/model/Repository.java +++ b/source/java/org/alfresco/repo/model/Repository.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2013 Alfresco Software Limited. + * Copyright (C) 2005-2014 Alfresco Software Limited. * * This file is part of Alfresco * @@ -64,10 +64,12 @@ public class Repository implements ApplicationContextAware // company home private StoreRef companyHomeStore; // ie. workspace://SpaceStore private String companyHomePath; // ie. /app:company_home + private String sharedHomePath; // ie. /app:shared // note: cache is tenant-aware (if using EhCacheAdapter shared cache) private SimpleCache singletonCache; // eg. for companyHomeNodeRef private final String KEY_COMPANYHOME_NODEREF = "key.companyhome.noderef"; + private final String KEY_SHAREDHOME_NODEREF = "key.sharedhome.noderef"; /** @@ -90,6 +92,16 @@ public class Repository implements ApplicationContextAware this.companyHomePath = companyHomePath; } + /** + * Sets the Shared Home Path + * + * @param sharedHomePath + */ + public void setSharedHomePath(String sharedHomePath) + { + this.sharedHomePath = sharedHomePath; + } + public void setSingletonCache(SimpleCache singletonCache) { this.singletonCache = singletonCache; @@ -212,17 +224,51 @@ public class Repository implements ApplicationContextAware if (refs.size() != 1) { throw new IllegalStateException("Invalid company home path: " + companyHomePath + " - found: " + refs.size()); - } - return refs.get(0); } - }, true); - } - }, AuthenticationUtil.getSystemUserName()); + return refs.get(0); + } + }, true); + } + }, AuthenticationUtil.getSystemUserName()); singletonCache.put(KEY_COMPANYHOME_NODEREF, companyHomeRef); } return companyHomeRef; } + + /** + * Gets the Shared Home. Note this is tenant-aware if the correct Cache is supplied. + * + * @return shared home node ref + */ + public NodeRef getSharedHome() + { + NodeRef sharedHomeRef = singletonCache.get(KEY_SHAREDHOME_NODEREF); + if (sharedHomeRef == null) + { + sharedHomeRef = AuthenticationUtil.runAs(new RunAsWork() + { + public NodeRef doWork() throws Exception + { + return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback() + { + public NodeRef execute() throws Exception + { + List refs = searchService.selectNodes(nodeService.getRootNode(companyHomeStore), sharedHomePath, null, namespaceService, false); + if (refs.size() != 1) + { + throw new IllegalStateException("Invalid shared home path: " + sharedHomePath + " - found: " + refs.size()); + } + return refs.get(0); + } + }, true); + } + }, AuthenticationUtil.getSystemUserName()); + + singletonCache.put(KEY_SHAREDHOME_NODEREF, sharedHomeRef); + } + return sharedHomeRef; + } /** * Gets the currently authenticated person diff --git a/source/java/org/alfresco/repo/nodelocator/SharedHomeNodeLocator.java b/source/java/org/alfresco/repo/nodelocator/SharedHomeNodeLocator.java new file mode 100644 index 0000000000..fe01665971 --- /dev/null +++ b/source/java/org/alfresco/repo/nodelocator/SharedHomeNodeLocator.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.nodelocator; + + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.repo.model.Repository; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * Locates the Shared Home {@link NodeRef}. + * + * @author Kevin Roast + * @since 5.0.1 + */ +public class SharedHomeNodeLocator extends AbstractNodeLocator +{ + public static final String NAME = "sharedhome"; + + private Repository repoHelper; + + /** + * {@inheritDoc} + */ + public NodeRef getNode(NodeRef source, Map params) + { + return repoHelper.getSharedHome(); + } + + /** + * {@inheritDoc} + */ + @Override + public String getName() + { + return NAME; + } + + /** + * @param repoHelper the repoHelper to set + */ + public void setRepositoryHelper(Repository repoHelper) + { + this.repoHelper = repoHelper; + } +}