From f3969beff1edfe62a0dccdd1e989f910fadcedb5 Mon Sep 17 00:00:00 2001 From: Jan Vonka Date: Fri, 15 Feb 2008 15:29:27 +0000 Subject: [PATCH] MT - initial checkin for MT-enabled Web Scripts git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@8293 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../web-scripts-application-context.xml | 3 + .../alfresco/repo/web/scripts/RepoStore.java | 1438 +++++++++-------- .../alfresco/repo/web/scripts/Repository.java | 102 +- .../repo/web/scripts/RepositoryContainer.java | 91 +- .../MTWebScriptAuthenticationFilter.java | 112 ++ source/web/WEB-INF/web.xml | 33 + 6 files changed, 1070 insertions(+), 709 deletions(-) create mode 100644 source/java/org/alfresco/web/app/servlet/MTWebScriptAuthenticationFilter.java 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