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;
+ }
+}