diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml
index e414c4fad6..9b67f4a0a9 100644
--- a/config/alfresco/web-scripts-application-context.xml
+++ b/config/alfresco/web-scripts-application-context.xml
@@ -37,6 +37,7 @@
+
@@ -83,6 +84,7 @@
+
${spaces.store}
/${spaces.company_home.childname}
@@ -115,6 +117,7 @@
+
diff --git a/source/java/org/alfresco/repo/web/scripts/RepoStore.java b/source/java/org/alfresco/repo/web/scripts/RepoStore.java
index 97b0543fdc..0fc8818e62 100644
--- a/source/java/org/alfresco/repo/web/scripts/RepoStore.java
+++ b/source/java/org/alfresco/repo/web/scripts/RepoStore.java
@@ -1,688 +1,750 @@
-/*
- * 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.web.scripts;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.alfresco.error.AlfrescoRuntimeException;
-import org.alfresco.model.ContentModel;
-import org.alfresco.repo.security.authentication.AuthenticationUtil;
-import org.alfresco.repo.transaction.RetryingTransactionHelper;
-import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
-import org.alfresco.service.cmr.model.FileFolderService;
-import org.alfresco.service.cmr.model.FileInfo;
-import org.alfresco.service.cmr.model.FileNotFoundException;
-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.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.repository.StoreRef;
-import org.alfresco.service.cmr.search.ResultSet;
-import org.alfresco.service.cmr.search.SearchService;
-import org.alfresco.service.cmr.security.PermissionService;
-import org.alfresco.service.namespace.NamespaceService;
-import org.alfresco.web.scripts.ScriptContent;
-import org.alfresco.web.scripts.ScriptLoader;
-import org.alfresco.web.scripts.Store;
-import org.alfresco.web.scripts.WebScript;
-import org.alfresco.web.scripts.WebScriptException;
-
-import freemarker.cache.TemplateLoader;
-
-
-/**
- * Repository based Web Script Store
- *
- * @author davidc
- */
-public class RepoStore implements Store
-{
- protected boolean mustExist = false;
- protected StoreRef repoStore;
- protected String repoPath;
- protected NodeRef baseNodeRef;
- protected String baseDir;
-
- // dependencies
- protected RetryingTransactionHelper retryingTransactionHelper;
- protected SearchService searchService;
- protected NodeService nodeService;
- protected ContentService contentService;
- protected FileFolderService fileService;
- protected NamespaceService namespaceService;
- protected PermissionService permissionService;
-
-
- /**
- * Sets helper that provides transaction callbacks
- */
- public void setTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
- {
- this.retryingTransactionHelper = retryingTransactionHelper;
- }
-
- /**
- * Sets the search service
- */
- public void setSearchService(SearchService searchService)
- {
- this.searchService = searchService;
- }
-
- /**
- * Sets the node service
- */
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
-
- /**
- * Sets the content service
- */
- public void setContentService(ContentService contentService)
- {
- this.contentService = contentService;
- }
-
- /**
- * Sets the file service
- */
- public void setFileFolderService(FileFolderService fileService)
- {
- this.fileService = fileService;
- }
-
- /**
- * Sets the namespace service
- */
- public void setNamespaceService(NamespaceService namespaceService)
- {
- this.namespaceService = namespaceService;
- }
-
- /**
- * Sets the permission service
- */
- public void setPermissionService(PermissionService permissionService)
- {
- this.permissionService = permissionService;
- }
-
- /**
- * Sets whether the repo store must exist
- *
- * @param mustExist
- */
- public void setMustExist(boolean mustExist)
- {
- this.mustExist = mustExist;
- }
-
- /**
- * Sets the repo store
- */
- public void setStore(String repoStore)
- {
- this.repoStore = new StoreRef(repoStore);
- }
-
- /**
- * Sets the repo path
- *
- * @param repoPath repoPath
- */
- public void setPath(String repoPath)
- {
- this.repoPath = repoPath;
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.web.scripts.Store#init()
- */
- public void init()
- {
- AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
- {
- public Object doWork() throws Exception
- {
- return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Object execute() throws Exception
- {
- String query = "PATH:\"" + repoPath + "\"";
- ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query);
- if (resultSet.length() == 1)
- {
- baseNodeRef = resultSet.getNodeRef(0);
- baseDir = getPath(baseNodeRef);
- }
- else if (mustExist)
- {
- throw new WebScriptException("Web Script Store " + repoStore.toString() + repoPath + " must exist; it was not found");
- }
- return null;
- }
- });
- }
- }, AuthenticationUtil.getSystemUserName());
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.web.scripts.WebScriptStore#exists()
- */
- public boolean exists()
- {
- return (baseNodeRef != null);
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.web.scripts.WebScriptStore#getBasePath()
- */
- public String getBasePath()
- {
- return repoStore.toString() + repoPath;
- }
-
- /**
- * Gets the display path for the specified node
- *
- * @param nodeRef
- * @return display path
- */
- protected String getPath(NodeRef nodeRef)
- {
- return nodeService.getPath(nodeRef).toDisplayPath(nodeService, permissionService) +
- "/" + nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
- }
-
- /**
- * Gets the node ref for the specified path within this repo store
- *
- * @param documentPath
- * @return node ref
- */
- protected NodeRef findNodeRef(String documentPath)
- {
- NodeRef node = null;
- try
- {
- String[] pathElements = documentPath.split("/");
- List pathElementsList = Arrays.asList(pathElements);
- FileInfo file = fileService.resolveNamePath(baseNodeRef, pathElementsList);
- node = file.getNodeRef();
- }
- catch (FileNotFoundException e)
- {
- // NOTE: return null
- }
- return node;
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.web.scripts.WebScriptStore#getScriptDocumentPaths(org.alfresco.web.scripts.WebScript)
- */
- public String[] getScriptDocumentPaths(final WebScript script)
- {
- return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
- {
- public String[] doWork() throws Exception
- {
- return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public String[] execute() throws Exception
- {
- int baseDirLength = baseDir.length() +1;
- List documentPaths = new ArrayList();
- String scriptPath = script.getDescription().getScriptPath();
- NodeRef scriptNodeRef = findNodeRef(scriptPath);
- if (scriptNodeRef != null)
- {
- org.alfresco.service.cmr.repository.Path repoScriptPath = nodeService.getPath(scriptNodeRef);
- String id = script.getDescription().getId().substring(script.getDescription().getScriptPath().length() +1);
- String query = "+PATH:\"" + repoScriptPath.toPrefixString(namespaceService) + "//*\" +QNAME:" + id + "*";
- ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query);
- List nodes = resultSet.getNodeRefs();
- for (NodeRef nodeRef : nodes)
- {
- String name = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
- if (name.startsWith(id))
- {
- String nodeDir = getPath(nodeRef);
- String documentPath = nodeDir.substring(baseDirLength);
- documentPaths.add(documentPath);
- }
- }
- }
-
- return documentPaths.toArray(new String[documentPaths.size()]);
- }
- });
- }
- }, AuthenticationUtil.getSystemUserName());
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.web.scripts.WebScriptStore#getDescriptionDocumentPaths()
- */
- public String[] getDescriptionDocumentPaths()
- {
- return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
- {
- public String[] doWork() throws Exception
- {
- return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public String[] execute() throws Exception
- {
- int baseDirLength = baseDir.length() +1;
- List documentPaths = new ArrayList();
-
- String query = "+PATH:\"" + repoPath + "//*\" +QNAME:*.desc.xml";
- ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query);
- List nodes = resultSet.getNodeRefs();
- for (NodeRef nodeRef : nodes)
- {
- String nodeDir = getPath(nodeRef);
- if (nodeDir.endsWith(".desc.xml"))
- {
- String documentPath = nodeDir.substring(baseDirLength);
- documentPaths.add(documentPath);
- }
- }
-
- return documentPaths.toArray(new String[documentPaths.size()]);
- }
- });
- }
- }, AuthenticationUtil.getSystemUserName());
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.web.scripts.WebScriptStore#hasDocument(java.lang.String)
- */
- public boolean hasDocument(final String documentPath)
- {
- return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
- {
- public Boolean doWork() throws Exception
- {
- return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Boolean execute() throws Exception
- {
- NodeRef nodeRef = findNodeRef(documentPath);
- return (nodeRef != null);
- }
- });
- }
- }, AuthenticationUtil.getSystemUserName());
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.web.scripts.WebScriptStore#getDescriptionDocument(java.lang.String)
- */
- public InputStream getDocument(final String documentPath)
- throws IOException
- {
- return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
- {
- public InputStream doWork() throws Exception
- {
- return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public InputStream execute() throws Exception
- {
- NodeRef nodeRef = findNodeRef(documentPath);
- if (nodeRef == null)
- {
- throw new IOException("Document " + documentPath + " does not exist.");
- }
- ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
- if (reader == null || !reader.exists())
- {
- throw new IOException("Failed to read content at " + documentPath + " (content reader does not exist)");
- }
- return reader.getContentInputStream();
- }
- });
- }
- }, AuthenticationUtil.getSystemUserName());
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.web.scripts.WebScriptStore#createDocument(java.lang.String, java.lang.String)
- */
- public void createDocument(String documentPath, String content) throws IOException
- {
- String[] pathElements = documentPath.split("/");
- String[] folderElements = new String[pathElements.length -1];
- System.arraycopy(pathElements, 0, folderElements, 0, pathElements.length -1);
- List folderElementsList = Arrays.asList(folderElements);
-
- // create folder
- FileInfo pathInfo = fileService.makeFolders(baseNodeRef, folderElementsList, ContentModel.TYPE_FOLDER);
-
- // create file
- String fileName = pathElements[pathElements.length -1];
- if (fileService.searchSimple(pathInfo.getNodeRef(), fileName) != null)
- {
- throw new IOException("Document " + documentPath + " already exists");
- }
- FileInfo fileInfo = fileService.create(pathInfo.getNodeRef(), fileName, ContentModel.TYPE_CONTENT);
- ContentWriter writer = fileService.getWriter(fileInfo.getNodeRef());
- writer.putContent(content);
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.web.scripts.WebScriptStore#getTemplateLoader()
- */
- public TemplateLoader getTemplateLoader()
- {
- return new RepoTemplateLoader();
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.web.scripts.WebScriptStore#getScriptLoader()
- */
- public ScriptLoader getScriptLoader()
- {
- return new RepoScriptLoader();
- }
-
- /**
- * Repository path based template loader
- *
- * @author davidc
- */
- private class RepoTemplateLoader implements TemplateLoader
- {
- /* (non-Javadoc)
- * @see freemarker.cache.TemplateLoader#findTemplateSource(java.lang.String)
- */
- public Object findTemplateSource(final String name)
- throws IOException
- {
- return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
- {
- public Object doWork() throws Exception
- {
- return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Object execute() throws Exception
- {
- RepoTemplateSource source = null;
- NodeRef nodeRef = findNodeRef(name);
- if (nodeRef != null)
- {
- source = new RepoTemplateSource(nodeRef);
- }
- return source;
- }
- });
- }
- }, AuthenticationUtil.getSystemUserName());
- }
-
- /* (non-Javadoc)
- * @see freemarker.cache.TemplateLoader#getLastModified(java.lang.Object)
- */
- public long getLastModified(Object templateSource)
- {
- return ((RepoTemplateSource)templateSource).lastModified();
- }
-
- /* (non-Javadoc)
- * @see freemarker.cache.TemplateLoader#getReader(java.lang.Object, java.lang.String)
- */
- public Reader getReader(Object templateSource, String encoding) throws IOException
- {
- return ((RepoTemplateSource)templateSource).getReader();
- }
-
- /* (non-Javadoc)
- * @see freemarker.cache.TemplateLoader#closeTemplateSource(java.lang.Object)
- */
- public void closeTemplateSource(Object arg0) throws IOException
- {
- }
- }
-
- /**
- * Repository (content) node template source
- *
- * @author davidc
- */
- private class RepoTemplateSource
- {
- protected final NodeRef nodeRef;
-
- /**
- * Construct
- *
- * @param ref
- */
- private RepoTemplateSource(NodeRef ref)
- {
- this.nodeRef = ref;
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#equals(java.lang.Object)
- */
- public boolean equals(Object o)
- {
- if (o instanceof RepoTemplateSource)
- {
- return nodeRef.equals(((RepoTemplateSource)o).nodeRef);
- }
- else
- {
- return false;
- }
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#hashCode()
- */
- public int hashCode()
- {
- return nodeRef.hashCode();
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#toString()
- */
- public String toString()
- {
- return nodeRef.toString();
- }
-
- /**
- * Gets the last modified time of the content
- *
- * @return last modified time
- */
- public long lastModified()
- {
- return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
- {
- public Long doWork() throws Exception
- {
- return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Long execute() throws Exception
- {
- ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
- return reader.getLastModified();
- }
- });
- }
- }, AuthenticationUtil.getSystemUserName());
- }
-
- /**
- * Gets the content reader
- *
- * @return content reader
- * @throws IOException
- */
- public Reader getReader() throws IOException
- {
- return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
- {
- public Reader doWork() throws Exception
- {
- return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Reader execute() throws Exception
- {
- ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
- return new InputStreamReader(reader.getContentInputStream(), reader.getEncoding());
- }
- });
- }
- }, AuthenticationUtil.getSystemUserName());
- }
- }
-
- /**
- * Repository path based script loader
- *
- * @author davidc
- */
- private class RepoScriptLoader implements ScriptLoader
- {
- /* (non-Javadoc)
- * @see org.alfresco.web.scripts.ScriptLoader#getScriptLocation(java.lang.String)
- */
- public ScriptContent getScript(final String path)
- {
- return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
- {
- public ScriptContent doWork() throws Exception
- {
- return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public ScriptContent execute() throws Exception
- {
- ScriptContent location = null;
- NodeRef nodeRef = findNodeRef(path);
- if (nodeRef != null)
- {
- location = new RepoScriptContent(path, nodeRef);
- }
- return location;
- }
- });
- }
- }, AuthenticationUtil.getSystemUserName());
- }
- }
-
- /**
- * Repo path script location
- *
- * @author davidc
- */
- private class RepoScriptContent implements ScriptContent
- {
- protected String path;
- protected NodeRef nodeRef;
-
- /**
- * Construct
- *
- * @param location
- */
- public RepoScriptContent(String path, NodeRef nodeRef)
- {
- this.path = path;
- this.nodeRef = nodeRef;
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.service.cmr.repository.ScriptLocation#getInputStream()
- */
- public InputStream getInputStream()
- {
- return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
- {
- public InputStream doWork() throws Exception
- {
- return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public InputStream execute() throws Exception
- {
- ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
- return reader.getContentInputStream();
- }
- });
- }
- }, AuthenticationUtil.getSystemUserName());
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.service.cmr.repository.ScriptLocation#getReader()
- */
- public Reader getReader()
- {
- ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
- try
- {
- return new InputStreamReader(getInputStream(), reader.getEncoding());
- }
- catch (UnsupportedEncodingException e)
- {
- throw new AlfrescoRuntimeException("Unsupported Encoding", e);
- }
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.web.scripts.ScriptContent#getPath()
- */
- public String getPath()
- {
- return repoStore + baseDir + "/" + path;
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.web.scripts.ScriptContent#getPathDescription()
- */
- public String getPathDescription()
- {
- return "/" + path + " (in repository store " + repoStore.toString() + baseDir + ")";
- }
- }
-
-}
+/*
+ * Copyright (C) 2005-2008 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.web.scripts;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.tenant.TenantDeployer;
+import org.alfresco.repo.tenant.TenantDeployerService;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
+import org.alfresco.service.cmr.model.FileFolderService;
+import org.alfresco.service.cmr.model.FileInfo;
+import org.alfresco.service.cmr.model.FileNotFoundException;
+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.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.service.cmr.search.ResultSet;
+import org.alfresco.service.cmr.search.SearchService;
+import org.alfresco.service.cmr.security.PermissionService;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.web.scripts.ScriptContent;
+import org.alfresco.web.scripts.ScriptLoader;
+import org.alfresco.web.scripts.Store;
+import org.alfresco.web.scripts.WebScript;
+import org.alfresco.web.scripts.WebScriptException;
+
+import freemarker.cache.TemplateLoader;
+
+
+/**
+ * Repository based Web Script Store
+ *
+ * @author davidc
+ */
+public class RepoStore implements Store, TenantDeployer
+{
+ protected boolean mustExist = false;
+ protected StoreRef repoStore;
+ protected String repoPath;
+ protected Map baseNodeRefs;
+
+ // dependencies
+ protected RetryingTransactionHelper retryingTransactionHelper;
+ protected SearchService searchService;
+ protected NodeService nodeService;
+ protected ContentService contentService;
+ protected FileFolderService fileService;
+ protected NamespaceService namespaceService;
+ protected PermissionService permissionService;
+
+ private TenantDeployerService tenantDeployerService;
+
+
+ /**
+ * Sets helper that provides transaction callbacks
+ */
+ public void setTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
+ {
+ this.retryingTransactionHelper = retryingTransactionHelper;
+ }
+
+ /**
+ * Sets the search service
+ */
+ public void setSearchService(SearchService searchService)
+ {
+ this.searchService = searchService;
+ }
+
+ /**
+ * Sets the node service
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * Sets the content service
+ */
+ public void setContentService(ContentService contentService)
+ {
+ this.contentService = contentService;
+ }
+
+ /**
+ * Sets the file service
+ */
+ public void setFileFolderService(FileFolderService fileService)
+ {
+ this.fileService = fileService;
+ }
+
+ /**
+ * Sets the namespace service
+ */
+ public void setNamespaceService(NamespaceService namespaceService)
+ {
+ this.namespaceService = namespaceService;
+ }
+
+ /**
+ * Sets the permission service
+ */
+ public void setPermissionService(PermissionService permissionService)
+ {
+ this.permissionService = permissionService;
+ }
+
+ /**
+ * Sets the tenant deployer service
+ */
+ public void setTenantDeployerService(TenantDeployerService tenantDeployerService)
+ {
+ this.tenantDeployerService = tenantDeployerService;
+ }
+
+ /**
+ * Sets whether the repo store must exist
+ *
+ * @param mustExist
+ */
+ public void setMustExist(boolean mustExist)
+ {
+ this.mustExist = mustExist;
+ }
+
+ /**
+ * Sets the repo store
+ */
+ public void setStore(String repoStore)
+ {
+ this.repoStore = new StoreRef(repoStore);
+ }
+
+ /**
+ * Sets the repo path
+ *
+ * @param repoPath repoPath
+ */
+ public void setPath(String repoPath)
+ {
+ this.repoPath = repoPath;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.Store#init()
+ * @see org.alfresco.repo.tenant.TenantDeployer#init()
+ */
+ public void init()
+ {
+ if (baseNodeRefs == null)
+ {
+ baseNodeRefs = new HashMap(1);
+ }
+
+ getBaseNodeRef();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.tenant.TenantDeployer#destroy()
+ */
+ public void destroy()
+ {
+ baseNodeRefs.remove(tenantDeployerService.getCurrentUserDomain());
+ }
+
+ private NodeRef getBaseNodeRef()
+ {
+ String tenantDomain = tenantDeployerService.getCurrentUserDomain();
+ NodeRef baseNodeRef = baseNodeRefs.get(tenantDomain);
+ if (baseNodeRef == null)
+ {
+ baseNodeRef = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
+ {
+ public NodeRef doWork() throws Exception
+ {
+ return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public NodeRef execute() throws Exception
+ {
+ String query = "PATH:\"" + repoPath + "\"";
+ ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query);
+ if (resultSet.length() == 1)
+ {
+ return resultSet.getNodeRef(0);
+ }
+ else if (mustExist)
+ {
+ throw new WebScriptException("Web Script Store " + repoStore.toString() + repoPath + " must exist; it was not found");
+ }
+ return null;
+ }
+ });
+ }
+ }, AuthenticationUtil.getSystemUserName());
+
+ // TODO clear on deleteTenant
+ baseNodeRefs.put(tenantDomain, baseNodeRef);
+ }
+ return baseNodeRef;
+ }
+
+ private String getBaseDir()
+ {
+ return getPath(getBaseNodeRef());
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.WebScriptStore#exists()
+ */
+ public boolean exists()
+ {
+ return (getBaseNodeRef() != null);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.WebScriptStore#getBasePath()
+ */
+ public String getBasePath()
+ {
+ return repoStore.toString() + repoPath;
+ }
+
+ /**
+ * Gets the display path for the specified node
+ *
+ * @param nodeRef
+ * @return display path
+ */
+ protected String getPath(NodeRef nodeRef)
+ {
+ return nodeService.getPath(nodeRef).toDisplayPath(nodeService, permissionService) +
+ "/" + nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
+ }
+
+ /**
+ * Gets the node ref for the specified path within this repo store
+ *
+ * @param documentPath
+ * @return node ref
+ */
+ protected NodeRef findNodeRef(String documentPath)
+ {
+ NodeRef node = null;
+ try
+ {
+ String[] pathElements = documentPath.split("/");
+ List pathElementsList = Arrays.asList(pathElements);
+ FileInfo file = fileService.resolveNamePath(getBaseNodeRef(), pathElementsList);
+ node = file.getNodeRef();
+ }
+ catch (FileNotFoundException e)
+ {
+ // NOTE: return null
+ }
+ return node;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.WebScriptStore#getScriptDocumentPaths(org.alfresco.web.scripts.WebScript)
+ */
+ public String[] getScriptDocumentPaths(final WebScript script)
+ {
+ return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
+ {
+ public String[] doWork() throws Exception
+ {
+ return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public String[] execute() throws Exception
+ {
+ int baseDirLength = getBaseDir().length() +1;
+ List documentPaths = new ArrayList();
+ String scriptPath = script.getDescription().getScriptPath();
+ NodeRef scriptNodeRef = findNodeRef(scriptPath);
+ if (scriptNodeRef != null)
+ {
+ org.alfresco.service.cmr.repository.Path repoScriptPath = nodeService.getPath(scriptNodeRef);
+ String id = script.getDescription().getId().substring(script.getDescription().getScriptPath().length() +1);
+ String query = "+PATH:\"" + repoScriptPath.toPrefixString(namespaceService) + "//*\" +QNAME:" + id + "*";
+ ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query);
+ List nodes = resultSet.getNodeRefs();
+ for (NodeRef nodeRef : nodes)
+ {
+ String name = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
+ if (name.startsWith(id))
+ {
+ String nodeDir = getPath(nodeRef);
+ String documentPath = nodeDir.substring(baseDirLength);
+ documentPaths.add(documentPath);
+ }
+ }
+ }
+
+ return documentPaths.toArray(new String[documentPaths.size()]);
+ }
+ });
+ }
+ }, AuthenticationUtil.getSystemUserName());
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.WebScriptStore#getDescriptionDocumentPaths()
+ */
+ public String[] getDescriptionDocumentPaths()
+ {
+ return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
+ {
+ public String[] doWork() throws Exception
+ {
+ return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public String[] execute() throws Exception
+ {
+ int baseDirLength = getBaseDir().length() +1;
+ List documentPaths = new ArrayList();
+
+ String query = "+PATH:\"" + repoPath + "//*\" +QNAME:*.desc.xml";
+ ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query);
+ List nodes = resultSet.getNodeRefs();
+ for (NodeRef nodeRef : nodes)
+ {
+ String nodeDir = getPath(nodeRef);
+ if (nodeDir.endsWith(".desc.xml"))
+ {
+ String documentPath = nodeDir.substring(baseDirLength);
+ documentPaths.add(documentPath);
+ }
+ }
+
+ return documentPaths.toArray(new String[documentPaths.size()]);
+ }
+ });
+ }
+ }, AuthenticationUtil.getSystemUserName());
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.WebScriptStore#hasDocument(java.lang.String)
+ */
+ public boolean hasDocument(final String documentPath)
+ {
+ return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
+ {
+ public Boolean doWork() throws Exception
+ {
+ return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public Boolean execute() throws Exception
+ {
+ NodeRef nodeRef = findNodeRef(documentPath);
+ return (nodeRef != null);
+ }
+ });
+ }
+ }, AuthenticationUtil.getSystemUserName());
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.WebScriptStore#getDescriptionDocument(java.lang.String)
+ */
+ public InputStream getDocument(final String documentPath)
+ throws IOException
+ {
+ return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
+ {
+ public InputStream doWork() throws Exception
+ {
+ return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public InputStream execute() throws Exception
+ {
+ NodeRef nodeRef = findNodeRef(documentPath);
+ if (nodeRef == null)
+ {
+ throw new IOException("Document " + documentPath + " does not exist.");
+ }
+ ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
+ if (reader == null || !reader.exists())
+ {
+ throw new IOException("Failed to read content at " + documentPath + " (content reader does not exist)");
+ }
+ return reader.getContentInputStream();
+ }
+ });
+ }
+ }, AuthenticationUtil.getSystemUserName());
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.WebScriptStore#createDocument(java.lang.String, java.lang.String)
+ */
+ public void createDocument(String documentPath, String content) throws IOException
+ {
+ String[] pathElements = documentPath.split("/");
+ String[] folderElements = new String[pathElements.length -1];
+ System.arraycopy(pathElements, 0, folderElements, 0, pathElements.length -1);
+ List folderElementsList = Arrays.asList(folderElements);
+
+ // create folder
+ FileInfo pathInfo = fileService.makeFolders(getBaseNodeRef(), folderElementsList, ContentModel.TYPE_FOLDER);
+
+ // create file
+ String fileName = pathElements[pathElements.length -1];
+ if (fileService.searchSimple(pathInfo.getNodeRef(), fileName) != null)
+ {
+ throw new IOException("Document " + documentPath + " already exists");
+ }
+ FileInfo fileInfo = fileService.create(pathInfo.getNodeRef(), fileName, ContentModel.TYPE_CONTENT);
+ ContentWriter writer = fileService.getWriter(fileInfo.getNodeRef());
+ writer.putContent(content);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.WebScriptStore#getTemplateLoader()
+ */
+ public TemplateLoader getTemplateLoader()
+ {
+ return new RepoTemplateLoader();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.WebScriptStore#getScriptLoader()
+ */
+ public ScriptLoader getScriptLoader()
+ {
+ return new RepoScriptLoader();
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.tenant.TenantDeployer#onEnableTenant()
+ */
+ public void onEnableTenant()
+ {
+ init();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.tenant.TenantDeployer#onDisableTenant()
+ */
+ public void onDisableTenant()
+ {
+ destroy();
+ }
+
+ /**
+ * Repository path based template loader
+ *
+ * @author davidc
+ */
+ private class RepoTemplateLoader implements TemplateLoader
+ {
+ /* (non-Javadoc)
+ * @see freemarker.cache.TemplateLoader#findTemplateSource(java.lang.String)
+ */
+ public Object findTemplateSource(final String name)
+ throws IOException
+ {
+ return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
+ {
+ public Object doWork() throws Exception
+ {
+ return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public Object execute() throws Exception
+ {
+ RepoTemplateSource source = null;
+ NodeRef nodeRef = findNodeRef(name);
+ if (nodeRef != null)
+ {
+ source = new RepoTemplateSource(nodeRef);
+ }
+ return source;
+ }
+ });
+ }
+ }, AuthenticationUtil.getSystemUserName());
+ }
+
+ /* (non-Javadoc)
+ * @see freemarker.cache.TemplateLoader#getLastModified(java.lang.Object)
+ */
+ public long getLastModified(Object templateSource)
+ {
+ return ((RepoTemplateSource)templateSource).lastModified();
+ }
+
+ /* (non-Javadoc)
+ * @see freemarker.cache.TemplateLoader#getReader(java.lang.Object, java.lang.String)
+ */
+ public Reader getReader(Object templateSource, String encoding) throws IOException
+ {
+ return ((RepoTemplateSource)templateSource).getReader();
+ }
+
+ /* (non-Javadoc)
+ * @see freemarker.cache.TemplateLoader#closeTemplateSource(java.lang.Object)
+ */
+ public void closeTemplateSource(Object arg0) throws IOException
+ {
+ }
+ }
+
+ /**
+ * Repository (content) node template source
+ *
+ * @author davidc
+ */
+ private class RepoTemplateSource
+ {
+ protected final NodeRef nodeRef;
+
+ /**
+ * Construct
+ *
+ * @param ref
+ */
+ private RepoTemplateSource(NodeRef ref)
+ {
+ this.nodeRef = ref;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object o)
+ {
+ if (o instanceof RepoTemplateSource)
+ {
+ return nodeRef.equals(((RepoTemplateSource)o).nodeRef);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode()
+ {
+ return nodeRef.hashCode();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ return nodeRef.toString();
+ }
+
+ /**
+ * Gets the last modified time of the content
+ *
+ * @return last modified time
+ */
+ public long lastModified()
+ {
+ return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
+ {
+ public Long doWork() throws Exception
+ {
+ return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public Long execute() throws Exception
+ {
+ ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
+ return reader.getLastModified();
+ }
+ });
+ }
+ }, AuthenticationUtil.getSystemUserName());
+ }
+
+ /**
+ * Gets the content reader
+ *
+ * @return content reader
+ * @throws IOException
+ */
+ public Reader getReader() throws IOException
+ {
+ return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
+ {
+ public Reader doWork() throws Exception
+ {
+ return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public Reader execute() throws Exception
+ {
+ ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
+ return new InputStreamReader(reader.getContentInputStream(), reader.getEncoding());
+ }
+ });
+ }
+ }, AuthenticationUtil.getSystemUserName());
+ }
+ }
+
+ /**
+ * Repository path based script loader
+ *
+ * @author davidc
+ */
+ private class RepoScriptLoader implements ScriptLoader
+ {
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.ScriptLoader#getScriptLocation(java.lang.String)
+ */
+ public ScriptContent getScript(final String path)
+ {
+ return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
+ {
+ public ScriptContent doWork() throws Exception
+ {
+ return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public ScriptContent execute() throws Exception
+ {
+ ScriptContent location = null;
+ NodeRef nodeRef = findNodeRef(path);
+ if (nodeRef != null)
+ {
+ location = new RepoScriptContent(path, nodeRef);
+ }
+ return location;
+ }
+ });
+ }
+ }, AuthenticationUtil.getSystemUserName());
+ }
+ }
+
+ /**
+ * Repo path script location
+ *
+ * @author davidc
+ */
+ private class RepoScriptContent implements ScriptContent
+ {
+ protected String path;
+ protected NodeRef nodeRef;
+
+ /**
+ * Construct
+ *
+ * @param location
+ */
+ public RepoScriptContent(String path, NodeRef nodeRef)
+ {
+ this.path = path;
+ this.nodeRef = nodeRef;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.cmr.repository.ScriptLocation#getInputStream()
+ */
+ public InputStream getInputStream()
+ {
+ return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
+ {
+ public InputStream doWork() throws Exception
+ {
+ return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public InputStream execute() throws Exception
+ {
+ ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
+ return reader.getContentInputStream();
+ }
+ });
+ }
+ }, AuthenticationUtil.getSystemUserName());
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.service.cmr.repository.ScriptLocation#getReader()
+ */
+ public Reader getReader()
+ {
+ ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
+ try
+ {
+ return new InputStreamReader(getInputStream(), reader.getEncoding());
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new AlfrescoRuntimeException("Unsupported Encoding", e);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.ScriptContent#getPath()
+ */
+ public String getPath()
+ {
+ return repoStore + getBaseDir() + "/" + path;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.ScriptContent#getPathDescription()
+ */
+ public String getPathDescription()
+ {
+ return "/" + path + " (in repository store " + repoStore.toString() + getBaseDir() + ")";
+ }
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/Repository.java b/source/java/org/alfresco/repo/web/scripts/Repository.java
index b85e7f377d..68fbf22068 100644
--- a/source/java/org/alfresco/repo/web/scripts/Repository.java
+++ b/source/java/org/alfresco/repo/web/scripts/Repository.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2008 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
@@ -25,12 +25,17 @@
package org.alfresco.repo.web.scripts;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
+import org.alfresco.repo.tenant.TenantDeployer;
+import org.alfresco.repo.tenant.TenantDeployerService;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.model.FileFolderService;
@@ -56,7 +61,7 @@ import org.springframework.context.ApplicationListener;
*
* @author davidc
*/
-public class Repository implements ApplicationContextAware, ApplicationListener
+public class Repository implements ApplicationContextAware, ApplicationListener, TenantDeployer
{
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
@@ -67,11 +72,12 @@ public class Repository implements ApplicationContextAware, ApplicationListener
private NodeService nodeService;
private FileFolderService fileFolderService;
private PersonService personService;
+ private TenantDeployerService tenantDeployerService;
// company home
private StoreRef companyHomeStore;
private String companyHomePath;
- private NodeRef companyHome;
+ private Map companyHomeRefs;
/**
@@ -151,6 +157,16 @@ public class Repository implements ApplicationContextAware, ApplicationListener
{
this.personService = personService;
}
+
+ /**
+ * Sets the tenant deployer service
+ *
+ * @param tenantDeployerService
+ */
+ public void setTenantDeployerService(TenantDeployerService tenantDeployerService)
+ {
+ this.tenantDeployerService = tenantDeployerService;
+ }
/* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
@@ -190,20 +206,14 @@ public class Repository implements ApplicationContextAware, ApplicationListener
*/
protected void initContext()
{
- retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
- {
- @SuppressWarnings("synthetic-access")
- public Object execute() throws Exception
- {
- List refs = searchService.selectNodes(nodeService.getRootNode(companyHomeStore), companyHomePath, null, namespaceService, false);
- if (refs.size() != 1)
- {
- throw new IllegalStateException("Invalid company home path: " + companyHomePath + " - found: " + refs.size());
- }
- companyHome = refs.get(0);
- return null;
- }
- });
+ tenantDeployerService.register(this);
+
+ if (companyHomeRefs == null)
+ {
+ companyHomeRefs = new HashMap(1);
+ }
+
+ getCompanyHome();
}
@@ -224,7 +234,32 @@ public class Repository implements ApplicationContextAware, ApplicationListener
*/
public NodeRef getCompanyHome()
{
- return companyHome;
+ String tenantDomain = tenantDeployerService.getCurrentUserDomain();
+ NodeRef companyHomeRef = companyHomeRefs.get(tenantDomain);
+ if (companyHomeRef == null)
+ {
+ companyHomeRef = 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), companyHomePath, null, namespaceService, false);
+ if (refs.size() != 1)
+ {
+ throw new IllegalStateException("Invalid company home path: " + companyHomePath + " - found: " + refs.size());
+ }
+ return refs.get(0);
+ }
+ });
+ }
+ }, AuthenticationUtil.getSystemUserName());
+
+ companyHomeRefs.put(tenantDomain, companyHomeRef);
+ }
+ return companyHomeRef;
}
/**
@@ -329,4 +364,35 @@ public class Repository implements ApplicationContextAware, ApplicationListener
return nodeRef;
}
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.tenant.TenantDeployer#onEnableTenant()
+ */
+ public void onEnableTenant()
+ {
+ init();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.tenant.TenantDeployer#onDisableTenant()
+ */
+ public void onDisableTenant()
+ {
+ destroy();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.tenant.TenantDeployer#init()
+ */
+ public void init()
+ {
+ initContext();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.tenant.TenantDeployer#destroy()
+ */
+ public void destroy()
+ {
+ companyHomeRefs.remove(tenantDeployerService.getCurrentUserDomain());
+ }
}
diff --git a/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java b/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java
index 894fa04d56..a6fe4b88ce 100644
--- a/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java
+++ b/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2008 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
@@ -31,6 +31,8 @@ import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.tenant.TenantDeployer;
+import org.alfresco.repo.tenant.TenantDeployerService;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
@@ -43,6 +45,7 @@ import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.web.scripts.AbstractRuntimeContainer;
import org.alfresco.web.scripts.Authenticator;
import org.alfresco.web.scripts.Description;
+import org.alfresco.web.scripts.Registry;
import org.alfresco.web.scripts.ServerModel;
import org.alfresco.web.scripts.WebScript;
import org.alfresco.web.scripts.WebScriptException;
@@ -59,7 +62,7 @@ import org.apache.commons.logging.LogFactory;
*
* @author davidc
*/
-public class RepositoryContainer extends AbstractRuntimeContainer
+public class RepositoryContainer extends AbstractRuntimeContainer implements TenantDeployer
{
// Logger
protected static final Log logger = LogFactory.getLog(RepositoryContainer.class);
@@ -71,6 +74,9 @@ public class RepositoryContainer extends AbstractRuntimeContainer
private AuthorityService authorityService;
private PermissionService permissionService;
private DescriptorService descriptorService;
+ private TenantDeployerService tenantDeployerService;
+
+ private Map tenantRegistries = new HashMap(0);
/**
* @param repository
@@ -120,6 +126,14 @@ public class RepositoryContainer extends AbstractRuntimeContainer
this.authorityService = authorityService;
}
+ /**
+ * @param tenantDeployerService
+ */
+ public void setTenantDeployerService(TenantDeployerService tenantDeployerService)
+ {
+ this.tenantDeployerService = tenantDeployerService;
+ }
+
/* (non-Javadoc)
* @see org.alfresco.web.scripts.Container#getDescription()
*/
@@ -192,7 +206,12 @@ public class RepositoryContainer extends AbstractRuntimeContainer
if (required == RequiredAuthentication.none)
{
- AuthenticationUtil.clearCurrentSecurityContext();
+ // MT-context will pre-authenticate (see MTWebScriptAuthenticationFilter)
+ if (! AuthenticationUtil.isMtEnabled())
+ {
+ // TODO revisit - cleared here, in-lieu of WebClient clear
+ AuthenticationUtil.clearCurrentSecurityContext();
+ }
transactionedExecute(script, scriptReq, scriptRes);
}
else if ((required == RequiredAuthentication.user || required == RequiredAuthentication.admin) && isGuest)
@@ -291,5 +310,71 @@ public class RepositoryContainer extends AbstractRuntimeContainer
}
}
}
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.AbstractRuntimeContainer#getRegistry()
+ */
+ @Override
+ public Registry getRegistry()
+ {
+ if (tenantDeployerService.isEnabled())
+ {
+ String tenantDomain = tenantDeployerService.getCurrentUserDomain();
+ Registry registry = tenantRegistries.get(tenantDomain);
+ if (registry == null)
+ {
+ init();
+ registry = tenantRegistries.get(tenantDomain);
+ }
+ return registry;
+ }
+ else
+ {
+ return super.getRegistry();
+ }
+ }
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.AbstractRuntimeContainer#reset()
+ */
+ @Override
+ public void reset()
+ {
+ tenantDeployerService.register(this);
+ super.reset();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.tenant.TenantDeployer#onEnableTenant()
+ */
+ public void onEnableTenant()
+ {
+ init();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.tenant.TenantDeployer#onDisableTenant()
+ */
+ public void onDisableTenant()
+ {
+ destroy();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.tenant.TenantDeployer#init()
+ */
+ public void init()
+ {
+ Registry registry = super.getRegistry().cloneEmpty();
+ tenantRegistries.put(tenantDeployerService.getCurrentUserDomain(), registry);
+ registry.reset();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.tenant.TenantDeployer#destroy()
+ */
+ public void destroy()
+ {
+ tenantRegistries.remove(tenantDeployerService.getCurrentUserDomain());
+ }
}
diff --git a/source/java/org/alfresco/web/app/servlet/MTWebScriptAuthenticationFilter.java b/source/java/org/alfresco/web/app/servlet/MTWebScriptAuthenticationFilter.java
new file mode 100644
index 0000000000..4cc85eaf9e
--- /dev/null
+++ b/source/java/org/alfresco/web/app/servlet/MTWebScriptAuthenticationFilter.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2005-2008 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.web.app.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.web.scripts.Authenticator;
+import org.alfresco.web.scripts.Description.RequiredAuthentication;
+import org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory;
+import org.alfresco.web.scripts.servlet.WebScriptServletRequest;
+import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
+import org.springframework.context.ApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+/**
+ * In case of MT-context, this servlet filter will force authentication prior to WebScript binding, even for WebScripts
+ * that do not require authentication.
+ *
+ * In future releases, consider updating the HTTP API such that an optional tenant context could be specified as part of
+ * the URL, hence not requiring pre-authentication in that case.
+ */
+public class MTWebScriptAuthenticationFilter implements Filter
+{
+ private FilterConfig config;
+
+ private ApplicationContext appContext;
+
+ /**
+ * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
+ */
+ public void init(FilterConfig config) throws ServletException
+ {
+ this.config = config;
+ this.appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext());
+ }
+
+ /**
+ * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
+ */
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
+ throws IOException, ServletException
+ {
+ if (AuthenticationUtil.isMtEnabled())
+ {
+ String currentUser = AuthenticationUtil.getCurrentUserName();
+ if (currentUser == null)
+ {
+ // retrieve authenticator factory
+ String authenticatorId = config.getInitParameter("authenticator");
+ if (authenticatorId != null && authenticatorId.length() > 0)
+ {
+ Object bean = appContext.getBean(authenticatorId);
+ if (bean == null || !(bean instanceof ServletAuthenticatorFactory))
+ {
+ throw new ServletException("Initialisation parameter 'authenticator' does not refer to a servlet authenticator factory (" + authenticatorId + ")");
+ }
+
+ ServletAuthenticatorFactory authenticatorFactory = (ServletAuthenticatorFactory)bean;
+
+ if ((req instanceof HttpServletRequest) && (res instanceof HttpServletResponse))
+ {
+ Authenticator authenticator = authenticatorFactory.create(new WebScriptServletRequest(null, (HttpServletRequest)req, null, null), new WebScriptServletResponse(null, (HttpServletResponse)res));
+ authenticator.authenticate(RequiredAuthentication.user, false);
+ }
+ }
+ }
+ }
+
+ // continue filter chaining
+ chain.doFilter(req, res);
+ }
+
+ /**
+ * @see javax.servlet.Filter#destroy()
+ */
+ public void destroy()
+ {
+ // nothing to do
+ }
+}
diff --git a/source/web/WEB-INF/web.xml b/source/web/WEB-INF/web.xml
index 82df994c38..9633002ac5 100644
--- a/source/web/WEB-INF/web.xml
+++ b/source/web/WEB-INF/web.xml
@@ -107,6 +107,24 @@
Admin Authentication Filter
org.alfresco.web.app.servlet.AdminAuthenticationFilter
+
+
+ MT WebScript Basic Authentication Filter
+ org.alfresco.web.app.servlet.MTWebScriptAuthenticationFilter
+
+ authenticator
+ webscripts.authenticator.basic
+
+
+
+
+ MT WebScript WC Authentication Filter
+ org.alfresco.web.app.servlet.MTWebScriptAuthenticationFilter
+
+ authenticator
+ webscripts.authenticator.webclient
+
+
Authentication Filter
@@ -165,6 +183,21 @@
Admin Authentication Filter
/faces/jsp/admin/system-info.jsp
+
+
+
+
+
+ MT WebScript Basic Authentication Filter
+ apiServlet
+
+
+
+ MT WebScript WC Authentication Filter
+ wcapiServlet
+
+
org.apache.myfaces.webapp.StartupServletContextListener